diff --git a/.circleci/config.yml b/.circleci/config.yml
index 46fb65b2e..90c094059 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -37,7 +37,7 @@ jobs:
# 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
- - run: cmake -DBUILD_FRAMEWORK=ON -H. -Bbuild -GXcode -DHB_IOS=ON
+ - run: cmake -DBUILD_FRAMEWORK=ON -H. -Bbuild -GXcode -DHB_HAVE_CORETEXT=OFF -DHB_BUILD_SUBSET=OFF -DHB_BUILD_TESTS=OFF
- run: cd build && xcodebuild -sdk iphoneos12.0 -configuration Release build -arch arm64
distcheck:
@@ -120,7 +120,7 @@ jobs:
- run: apt update || true
- run: apt install -y clang lld binutils libtool autoconf automake make pkg-config gtk-doc-tools ragel libfreetype6-dev libfontconfig1-dev libglib2.0-dev libcairo2-dev libicu-dev libgraphite2-dev python python-pip
- run: pip install fonttools
- - run: CFLAGS="-Weverything -Wno-reserved-id-macro -Wno-conversion -Wno-padded -Wno-sign-conversion -Wno-cast-qual -Wno-documentation -Wno-documentation-unknown-command" CXXFLAGS="-Weverything -Wno-old-style-cast -Wno-documentation -Wno-documentation-unknown-command -Wno-c++98-compat -Wno-cast-qual -Wno-c++98-compat-pedantic -Wno-sign-conversion -Wno-padded -Wno-shorten-64-to-32 -Wno-extra-semi -Wno-reserved-id-macro -Wno-float-conversion -Wno-format-pedantic -Wno-shadow -Wno-conversion -Wno-zero-as-null-pointer-constant -Wno-missing-field-initializers -Wno-used-but-marked-unused -Wno-unused-macros -Wno-comma -Wno-float-equal -Wno-disabled-macro-expansion -Wno-weak-vtables -Wno-unused-parameter -Wno-covered-switch-default -Wno-unreachable-code" CC=clang CXX=clang++ ./autogen.sh --with-freetype --with-glib --with-cairo --with-icu --with-graphite2 --with-fontconfig
+ - run: CFLAGS="-Weverything -Wno-reserved-id-macro -Wno-conversion -Wno-padded -Wno-sign-conversion -Wno-cast-qual -Wno-documentation -Wno-documentation-unknown-command" CXXFLAGS="-Weverything -Wno-old-style-cast -Wno-documentation -Wno-documentation-unknown-command -Wno-c++98-compat -Wno-cast-qual -Wno-c++98-compat-pedantic -Wno-sign-conversion -Wno-padded -Wno-shorten-64-to-32 -Wno-reserved-id-macro -Wno-float-conversion -Wno-format-pedantic -Wno-shadow -Wno-conversion -Wno-zero-as-null-pointer-constant -Wno-missing-field-initializers -Wno-used-but-marked-unused -Wno-unused-macros -Wno-comma -Wno-float-equal -Wno-disabled-macro-expansion -Wno-weak-vtables -Wno-unused-parameter -Wno-covered-switch-default -Wno-unreachable-code" CC=clang CXX=clang++ ./autogen.sh --with-freetype --with-glib --with-cairo --with-icu --with-graphite2 --with-fontconfig
- run: make -j32 CPPFLAGS="-Werror"
- run: make check CPPFLAGS="-Werror" || .ci/fail.sh
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4eb23af4d..019e205bc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -52,6 +52,9 @@ if (HB_BUILD_UTILS)
set (HB_HAVE_FREETYPE ON)
endif ()
+option(HB_BUILD_SUBSET "Build harfbuzz-subset" ON)
+option(HB_BUILD_TESTS "Build harfbuzz tests" ON)
+
option(HB_HAVE_GOBJECT "Enable GObject Bindings" OFF)
if (HB_HAVE_GOBJECT)
set (HB_HAVE_GLIB ON)
@@ -82,16 +85,6 @@ if (HB_CHECK)
endif ()
endif ()
-set (HB_DISABLE_SUBSET OFF)
-set (HB_DISABLE_TESTS OFF)
-option(HB_IOS "Apply iOS specific build flags" OFF)
-if (HB_IOS)
- # We should fix their issue and enable them
- set (HB_DISABLE_SUBSET ON)
- set (HB_DISABLE_TESTS ON)
- set (HB_HAVE_CORETEXT OFF)
-endif ()
-
include_directories(AFTER
${PROJECT_SOURCE_DIR}/src
${PROJECT_BINARY_DIR}/src
@@ -556,7 +549,7 @@ add_library(harfbuzz ${project_sources} ${project_extra_sources} ${project_heade
target_link_libraries(harfbuzz ${THIRD_PARTY_LIBS})
## Define harfbuzz-subset library
-if (NOT HB_DISABLE_SUBSET)
+if (HB_BUILD_SUBSET)
add_library(harfbuzz-subset ${subset_project_sources} ${subset_project_headers})
add_dependencies(harfbuzz-subset harfbuzz)
target_link_libraries(harfbuzz-subset harfbuzz ${THIRD_PARTY_LIBS})
@@ -580,7 +573,7 @@ if (UNIX OR MINGW)
set (CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "m") # libm
set (CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
set_target_properties(harfbuzz PROPERTIES LINKER_LANGUAGE C)
- if (NOT HB_DISABLE_SUBSET)
+ if (HB_BUILD_SUBSET)
set_target_properties(harfbuzz-subset PROPERTIES LINKER_LANGUAGE C)
endif ()
@@ -861,7 +854,7 @@ if (UNIX AND CMAKE_GENERATOR STREQUAL "Ninja")
endif ()
-if (NOT HB_DISABLE_TESTS)
+if (HB_BUILD_TESTS)
## src/ executables
foreach (prog main test test-would-substitute test-size-params test-buffer-serialize hb-ot-tag test-unicode-ranges)
set (prog_name ${prog})
diff --git a/NEWS b/NEWS
index b8d364081..cb8a28ff0 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,84 @@
+Overview of changes leading to 2.1.0
+Tuesday, October 30, 2018
+====================================
+- AAT shaping improvements:
+ o Allow user controlling AAT features, for whole buffer only currently.
+ o Several 'morx' fixes.
+ o Implement tuple-kerns in 'kerx'; Fixes kerning with Apple default
+ San Francisco fonts.
+- Support for color fonts:
+ o COLR/CPAL API to fetch color layers.
+ o SVG table to fetch SVG documents.
+ o CBDT/sbix API to fetch PNG images.
+- New 'name' table API.
+- hb-ot-font now uses 'VORG' table to correctly position CFF glyphs
+ in vertical layout.
+- Various fuzzer-found bug fixes.
+
+Changed API:
+
+A type and a macro added in 2.0.0 were renamed:
+
+hb_name_id_t -> hb_ot_name_id_t
+HB_NAME_ID_INVALID -> HB_OT_NAME_ID_INVALID
+
+New API:
+
++hb_color_t
++HB_COLOR
++hb_color_get_alpha()
++hb_color_get_red()
++hb_color_get_green()
++hb_color_get_blue()
++hb_ot_color_has_palettes()
++hb_ot_color_palette_get_count()
++hb_ot_color_palette_get_name_id()
++hb_ot_color_palette_color_get_name_id()
++hb_ot_color_palette_flags_t
++hb_ot_color_palette_get_flags()
++hb_ot_color_palette_get_colors()
++hb_ot_color_has_layers()
++hb_ot_color_layer_t
++hb_ot_color_glyph_get_layers()
++hb_ot_color_has_svg()
++hb_ot_color_glyph_reference_svg()
++hb_ot_color_has_png()
++hb_ot_color_glyph_reference_png()
+
++hb_ot_name_id_t
++HB_OT_NAME_ID_INVALID
++HB_OT_NAME_ID_COPYRIGHT
++HB_OT_NAME_ID_FONT_FAMILY
++HB_OT_NAME_ID_FONT_SUBFAMILY
++HB_OT_NAME_ID_UNIQUE_ID
++HB_OT_NAME_ID_FULL_NAME
++HB_OT_NAME_ID_VERSION_STRING
++HB_OT_NAME_ID_POSTSCRIPT_NAME
++HB_OT_NAME_ID_TRADEMARK
++HB_OT_NAME_ID_MANUFACTURER
++HB_OT_NAME_ID_DESIGNER
++HB_OT_NAME_ID_DESCRIPTION
++HB_OT_NAME_ID_VENDOR_URL
++HB_OT_NAME_ID_DESIGNER_URL
++HB_OT_NAME_ID_LICENSE
++HB_OT_NAME_ID_LICENSE_URL
++HB_OT_NAME_ID_TYPOGRAPHIC_FAMILY
++HB_OT_NAME_ID_TYPOGRAPHIC_SUBFAMILY
++HB_OT_NAME_ID_MAC_FULL_NAME
++HB_OT_NAME_ID_SAMPLE_TEXT
++HB_OT_NAME_ID_CID_FINDFONT_NAME
++HB_OT_NAME_ID_WWS_FAMILY
++HB_OT_NAME_ID_WWS_SUBFAMILY
++HB_OT_NAME_ID_LIGHT_BACKGROUND
++HB_OT_NAME_ID_DARK_BACKGROUND
++HB_OT_NAME_ID_VARIATIONS_PS_PREFIX
++hb_ot_name_entry_t
++hb_ot_name_list_names()
++hb_ot_name_get_utf8()
++hb_ot_name_get_utf16()
++hb_ot_name_get_utf32()
+
+
Overview of changes leading to 2.0.2
Saturday, October 20, 2018
====================================
diff --git a/RELEASING.md b/RELEASING.md
index 4f5705e53..1fd836545 100644
--- a/RELEASING.md
+++ b/RELEASING.md
@@ -8,7 +8,8 @@ HarfBuzz release walk-through checklist:
Document them in NEWS. All API and API semantic changes should be clearly
marked as API additions, API changes, or API deletions. Document
deprecations. Ensure all new API / deprecations are in listed correctly in
- docs/harfbuzz-sections.txt
+ docs/harfbuzz-sections.txt. If release added new API, add entry for new
+ API index at the end of docs/harfbuzz-docs.xml.
If there's a backward-incompatible API change (including deletions for API
used anywhere), that's a release blocker. Do NOT release.
diff --git a/configure.ac b/configure.ac
index a2d0992a7..21d48f39a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,6 +1,6 @@
AC_PREREQ([2.64])
AC_INIT([HarfBuzz],
- [2.0.2],
+ [2.1.0],
[https://github.com/harfbuzz/harfbuzz/issues/new],
[harfbuzz],
[http://harfbuzz.org/])
diff --git a/docs/Makefile.am b/docs/Makefile.am
index e48b9ccd8..9b54b40e1 100644
--- a/docs/Makefile.am
+++ b/docs/Makefile.am
@@ -72,14 +72,15 @@ HTML_IMAGES= \
# Extra SGML files that are included by $(DOC_MAIN_SGML_FILE).
# e.g. content_files=running.sgml building.sgml changes-2.0.sgml
content_files= \
- usermanual-buffers-language-script-and-direction.xml \
- usermanual-clusters.xml \
- usermanual-fonts-and-faces.xml \
- usermanual-glyph-information.xml \
- usermanual-hello-harfbuzz.xml \
- usermanual-install-harfbuzz.xml \
- usermanual-opentype-features.xml \
usermanual-what-is-harfbuzz.xml \
+ usermanual-install-harfbuzz.xml \
+ usermanual-getting-started.xml \
+ usermanual-shaping-concepts.xml \
+ usermanual-buffers-language-script-and-direction.xml \
+ usermanual-fonts-and-faces.xml \
+ usermanual-clusters.xml \
+ usermanual-opentype-features.xml \
+ usermanual-glyph-information.xml \
version.xml
# SGML files where gtk-doc abbrevations (#GtkWidget) are expanded
diff --git a/docs/harfbuzz-docs.xml b/docs/harfbuzz-docs.xml
index 9452a92af..66a64d8f9 100644
--- a/docs/harfbuzz-docs.xml
+++ b/docs/harfbuzz-docs.xml
@@ -12,28 +12,21 @@
HarfBuzz is an OpenType
- text shaping engine.
+ text shaping engine. Using the HarfBuzz library allows
+ programs to convert a sequence of Unicode input into
+ properly formatted and positioned glyph output—for any writing
+ system and language.
+
- The current HarfBuzz codebase, formerly known as harfbuzz-ng, is
- versioned 1.x.x and is stable and under active maintenance. This is
- what is used in latest versions of Firefox, GNOME, ChromeOS, Chrome,
- LibreOffice, XeTeX, Android, and KDE, among other places. The canonical
- source tree is available
- here.
- Also available on
- github.
- See for release tarballs.
-
-
- The old HarfBuzz codebase, these days known as harfbuzz-old, was
- derived from FreeType,
- Pango, and
- Qt and is available
- here.
- It is not actively developed or maintained, and is extremely buggy. All
- users are encouraged to switch over to the new HarfBuzz as soon as
- possible. There are no release tarballs of old HarfBuzz whatsoever.
+ The canonical source-code tree is available at
+ github.com/harfbuzz/harfbuzz
+ and is also available at
+ cgit.freedesktop.org/harfbuzz.
+ See for
+ release tarballs.
@@ -42,7 +35,8 @@
User's manual
-
+
+
@@ -58,152 +52,119 @@
http://[SERVER]/libharfbuzz/.-->
+
+
+
+ The current HarfBuzz codebase is versioned 2.x.x and is stable
+ and under active maintenance. This is what is used in latest
+ versions of Firefox, GNOME, ChromeOS, Chrome, LibreOffice,
+ XeTeX, Android, and KDE, among other places.
+
+
+ Prior to 2012, the original HarfBuzz codebase (which, these
+ days, is referred to as harfbuzz-old) was
+ derived from code in FreeType, Pango, and
+ Qt.
+ It is not actively developed or
+ maintained, and is extremely buggy. All users of harfbuzz-old
+ are encouraged to switch over to the new HarfBuzz as soon as possible.
+
+
+ To make this distinction clearer in discussions, the current
+ HarfBuzz codebase is sometimes referred to as
+ harfbuzz-ng.
+
+
+ For reference purposes, the harfbuzz-old source tree is archived
+ here. There
+ are no release tarballs of harfbuzz-old whatsoever.
+
+
+
Reference manual
- HarfBuzz API
-
-
-
-
+ Core API
+
+
+
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
+
+
+ OpenType API
+
+
+
+
+
+
+
+
+
+
+ Integration API
+
+
+
+
+
+
+
+
+
+
+
+ API Index
+ Index of deprecated API
+
+ Index of new symbols in 2.1.0
+ Index of new symbols in 2.0.0
+ Index of new symbols in 1.9.0
+ Index of new symbols in 1.8.6
+ Index of new symbols in 1.8.5
+ Index of new symbols in 1.8.1
+ Index of new symbols in 1.8.0
+ Index of new symbols in 1.7.7
+ Index of new symbols in 1.7.5
+ Index of new symbols in 1.6.0
+ Index of new symbols in 1.5.0
+ Index of new symbols in 1.4.3
+ Index of new symbols in 1.4.2
+ Index of new symbols in 1.4.0
+ Index of new symbols in 1.3.3
+ Index of new symbols in 1.2.3
+ Index of new symbols in 1.1.3
+ Index of new symbols in 1.1.2
+ Index of new symbols in 1.0.5
+ Index of new symbols in 0.9.42
+ Index of new symbols in 0.9.41
+ Index of new symbols in 0.9.39
+ Index of new symbols in 0.9.38
+ Index of new symbols in 0.9.31
+ Index of new symbols in 0.9.30
+ Index of new symbols in 0.9.28
+ Index of new symbols in 0.9.22
+ Index of new symbols in 0.9.20
+ Index of new symbols in 0.9.11
+ Index of new symbols in 0.9.10
+ Index of new symbols in 0.9.8
+ Index of new symbols in 0.9.7
+ Index of new symbols in 0.9.5
+ Index of new symbols in 0.9.2
diff --git a/docs/harfbuzz-sections.txt b/docs/harfbuzz-sections.txt
index fccfcb0ed..6a498e940 100644
--- a/docs/harfbuzz-sections.txt
+++ b/docs/harfbuzz-sections.txt
@@ -1,8 +1,6 @@
-
-hb
HB_H_IN
-HB_EXTERN
+HB_OT_H_IN
@@ -146,6 +144,10 @@ uint16_t
uint32_t
uint64_t
uint8_t
+
+HB_EXTERN
+HB_DEPRECATED
+HB_DEPRECATED_FOR
@@ -358,6 +360,7 @@ HB_GOBJECT_TYPE_FONT_FUNCS
HB_GOBJECT_TYPE_GLYPH_FLAGS
HB_GOBJECT_TYPE_MAP
HB_GOBJECT_TYPE_MEMORY_MODE
+HB_GOBJECT_TYPE_OT_COLOR_PALETTE_FLAGS
HB_GOBJECT_TYPE_OT_LAYOUT_GLYPH_CLASS
HB_GOBJECT_TYPE_OT_MATH_CONSTANT
HB_GOBJECT_TYPE_OT_MATH_GLYPH_PART
@@ -390,6 +393,7 @@ hb_gobject_font_get_type
hb_gobject_glyph_flags_get_type
hb_gobject_map_get_type
hb_gobject_memory_mode_get_type
+hb_gobject_ot_color_palette_flags_get_type
hb_gobject_ot_layout_glyph_class_get_type
hb_gobject_ot_math_constant_get_type
hb_gobject_ot_math_glyph_part_get_type
@@ -412,11 +416,6 @@ hb_gobject_user_data_key_get_type
HB_GOBJECT_H_IN
-
-
hb-graphite2
HB_GRAPHITE2_TAG_SILF
@@ -452,9 +451,27 @@ hb_map_t
-hb-ot
-
-HB_OT_H_IN
+hb-ot-color
+hb_color_t
+HB_COLOR
+hb_color_get_alpha
+hb_color_get_blue
+hb_color_get_green
+hb_color_get_red
+hb_ot_color_glyph_get_layers
+hb_ot_color_glyph_reference_png
+hb_ot_color_glyph_reference_svg
+hb_ot_color_has_layers
+hb_ot_color_has_palettes
+hb_ot_color_has_png
+hb_ot_color_has_svg
+hb_ot_color_layer_t
+hb_ot_color_palette_color_get_name_id
+hb_ot_color_palette_flags_t
+hb_ot_color_palette_get_colors
+hb_ot_color_palette_get_count
+hb_ot_color_palette_get_flags
+hb_ot_color_palette_get_name_id
@@ -463,16 +480,31 @@ hb_ot_font_set_funcs
-hb-ot-shape
-hb_ot_shape_glyphs_closure
+hb-ot-name
+hb_ot_name_id_t
+HB_OT_NAME_ID_INVALID
+hb_ot_name_entry_t
+hb_ot_name_list_names
+hb_ot_name_get_utf16
+hb_ot_name_get_utf32
+hb_ot_name_get_utf8
hb-ot-layout
+HB_OT_MAX_TAGS_PER_LANGUAGE
+HB_OT_MAX_TAGS_PER_SCRIPT
+HB_OT_TAG_DEFAULT_LANGUAGE
+HB_OT_TAG_DEFAULT_SCRIPT
+hb_ot_tag_to_language
+hb_ot_tag_to_script
+hb_ot_tags_from_script_and_language
+hb_ot_tags_to_script_and_language
HB_OT_LAYOUT_DEFAULT_LANGUAGE_INDEX
HB_OT_LAYOUT_NO_FEATURE_INDEX
HB_OT_LAYOUT_NO_SCRIPT_INDEX
HB_OT_LAYOUT_NO_VARIATIONS_INDEX
+HB_OT_TAG_BASE
HB_OT_TAG_GDEF
HB_OT_TAG_GPOS
HB_OT_TAG_GSUB
@@ -517,23 +549,6 @@ Xhb_ot_layout_lookup_position
Xhb_ot_layout_lookup_substitute
-
-hb-ot-var
-HB_OT_TAG_VAR_AXIS_ITALIC
-HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE
-HB_OT_TAG_VAR_AXIS_SLANT
-HB_OT_TAG_VAR_AXIS_WEIGHT
-HB_OT_TAG_VAR_AXIS_WIDTH
-HB_OT_VAR_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_normalize_variations
-hb_ot_var_normalize_coords
-
-
hb-ot-math
HB_OT_TAG_MATH
@@ -555,15 +570,25 @@ hb_ot_math_get_glyph_assembly
-hb-ot-tag
-HB_OT_MAX_TAGS_PER_LANGUAGE
-HB_OT_MAX_TAGS_PER_SCRIPT
-HB_OT_TAG_DEFAULT_LANGUAGE
-HB_OT_TAG_DEFAULT_SCRIPT
-hb_ot_tag_to_language
-hb_ot_tag_to_script
-hb_ot_tags_from_script_and_language
-hb_ot_tags_to_script_and_language
+hb-ot-shape
+hb_ot_shape_glyphs_closure
+
+
+
+hb-ot-var
+HB_OT_TAG_VAR_AXIS_ITALIC
+HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE
+HB_OT_TAG_VAR_AXIS_SLANT
+HB_OT_TAG_VAR_AXIS_WEIGHT
+HB_OT_TAG_VAR_AXIS_WIDTH
+HB_OT_VAR_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_normalize_variations
+hb_ot_var_normalize_coords
diff --git a/docs/usermanual-buffers-language-script-and-direction.xml b/docs/usermanual-buffers-language-script-and-direction.xml
index 9eddb71a9..68ce9bd0b 100644
--- a/docs/usermanual-buffers-language-script-and-direction.xml
+++ b/docs/usermanual-buffers-language-script-and-direction.xml
@@ -1,3 +1,9 @@
+
+
+
+]>
Buffers, language, script and direction
@@ -74,4 +80,4 @@ void somefunc(hb_buffer_t *buffer) {
-
\ No newline at end of file
+
diff --git a/docs/usermanual-clusters.xml b/docs/usermanual-clusters.xml
index 608371b00..7b2c7adc7 100644
--- a/docs/usermanual-clusters.xml
+++ b/docs/usermanual-clusters.xml
@@ -1,3 +1,9 @@
+
+
+
+]>
Clusters
diff --git a/docs/usermanual-fonts-and-faces.xml b/docs/usermanual-fonts-and-faces.xml
index 7de0f051a..553600439 100644
--- a/docs/usermanual-fonts-and-faces.xml
+++ b/docs/usermanual-fonts-and-faces.xml
@@ -1,3 +1,9 @@
+
+
+
+]>
Fonts and faces
-
\ No newline at end of file
+
diff --git a/docs/usermanual-getting-started.xml b/docs/usermanual-getting-started.xml
new file mode 100644
index 000000000..9e16ecbf2
--- /dev/null
+++ b/docs/usermanual-getting-started.xml
@@ -0,0 +1,222 @@
+
+
+
+]>
+
+ Getting started with HarfBuzz
+
+ An overview of the HarfBuzz shaping API
+
+ The core of the HarfBuzz shaping API is the function
+ hb_shape(). This function takes a font, a
+ buffer containing a string of Unicode codepoints and
+ (optionally) a list of font features as its input. It replaces
+ the codepoints in the buffer with the corresponding glyphs from
+ the font, correctly ordered and positioned, and with any of the
+ optional font features applied.
+
+
+ In addition to holding the pre-shaping input (the Unicode
+ codepoints that comprise the input string) and the post-shaping
+ output (the glyphs and positions), a HarfBuzz buffer has several
+ properties that affect shaping. The most important are the
+ text-flow direction (e.g., left-to-right, right-to-left,
+ top-to-bottom, or bottom-to-top), the script tag, and the
+ language tag.
+
+
+
+ For input string buffers, flags are available to denote when the
+ buffer represents the beginning or end of a paragraph, to
+ indicate whether or not to visibly render Unicode Default
+ Ignorable codepoints, and to modify the cluster-merging
+ behavior for the buffer. For shaped output buffers, the
+ individual X and Y offsets and advances
+ (the logical dimensions) of each glyph are
+ accessible. HarfBuzz also flags glyphs as
+ UNSAFE_TO_BREAK if breaking the string at
+ that glyph (e.g., in a line-breaking or hyphenation process)
+ would require re-shaping the text.
+
+
+
+ HarfBuzz also provides methods to compare the contents of
+ buffers, join buffers, normalize buffer contents, and handle
+ invalid codepoints, as well as to determine the state of a
+ buffer (e.g., input codepoints or output glyphs). Buffer
+ lifecycles are managed and all buffers are reference-counted.
+
+
+
+ Although the default hb_shape() function is
+ sufficient for most use cases, a variant is also provide that
+ lets you specify which of HarfBuzz's shapers to use on a buffer.
+
+
+
+ HarfBuzz can read TrueType fonts, TrueType collections, OpenType
+ fonts, and OpenType collections. Functions are provided to query
+ font objects about metrics, Unicode coverage, available tables and
+ features, and variation selectors. Individual glyphs can also be
+ queried for metrics, variations, and glyph names. OpenType
+ variable fonts are supported, and HarfBuzz allows you to set
+ variation-axis coordinates on font objects.
+
+
+
+ HarfBuzz provides glue code to integrate with various other
+ libraries, including FreeType, GObject, and CoreText. Support
+ for integrating with Uniscribe and DirectWrite is experimental
+ at present.
+
+
+
+
+ Terminology
+
+
+ shaper
+
+
+ In HarfBuzz, a shaper is a
+ handler for a specific script shaping model. HarfBuzz
+ implements separate shapers for Indic, Arabic, Thai and
+ Lao, Khmer, Myanmar, Tibetan, Hangul, Hebrew, the
+ Universal Shaping Engine (USE), and a default shaper for
+ non-complex scripts.
+
+
+
+
+
+ cluster
+
+
+ In text shaping, a cluster is a
+ sequence of codepoints that must be handled as an
+ indivisible unit. Clusters can include codepoint
+ sequences that form a ligature or base-and-mark
+ sequences. Tracking and preserving clusters is important
+ when shaping operations might separate or reorder
+ codepoints.
+
+
+ HarfBuzz provides three cluster
+ levels that implement different
+ approaches to the problem of preserving clusters during
+ shaping operations.
+
+
+
+
+
+
+
+
+
+
+
+ A simple shaping example
+
+
+ Below is the simplest HarfBuzz shaping example possible.
+
+
+
+
+ Create a buffer and put your text in it.
+
+
+
+
+ #include <hb.h>
+ hb_buffer_t *buf;
+ buf = hb_buffer_create();
+ hb_buffer_add_utf8(buf, text, -1, 0, -1);
+
+
+
+
+ Guess the script, language and direction of the buffer.
+
+
+
+
+ hb_buffer_set_direction(buf, HB_DIRECTION_LTR);
+ hb_buffer_set_script(buf, HB_SCRIPT_LATIN);
+ hb_buffer_set_language(buf, hb_language_from_string("en", -1));
+
+
+
+
+ Create a face and a font, using FreeType for now.
+
+
+
+
+ #include <hb-ft.h>
+ FT_New_Face(ft_library, font_path, index, &face)
+ hb_font_t *font = hb_ft_font_create(face);
+
+
+
+
+ Shape!
+
+
+
+
+ hb_shape(font, buf, NULL, 0);
+
+
+
+
+ Get the glyph and position information.
+
+
+
+
+ hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos(buf, &glyph_count);
+ hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(buf, &glyph_count);
+
+
+
+
+ Iterate over each glyph.
+
+
+
+
+ for (i = 0; i < glyph_count; ++i) {
+ glyphid = glyph_info[i].codepoint;
+ x_offset = glyph_pos[i].x_offset / 64.0;
+ y_offset = glyph_pos[i].y_offset / 64.0;
+ x_advance = glyph_pos[i].x_advance / 64.0;
+ y_advance = glyph_pos[i].y_advance / 64.0;
+ draw_glyph(glyphid, cursor_x + x_offset, cursor_y + y_offset);
+ cursor_x += x_advance;
+ cursor_y += y_advance;
+ }
+
+
+
+
+ Tidy up.
+
+
+
+
+ hb_buffer_destroy(buf);
+ hb_font_destroy(hb_ft_font);
+
+
+
+ This example shows enough to get us started using HarfBuzz. In
+ the sections that follow, we will use the remainder of
+ HarfBuzz's API to refine and extend the example and improve its
+ text-shaping capabilities.
+
+
+
diff --git a/docs/usermanual-glyph-information.xml b/docs/usermanual-glyph-information.xml
index ca674c0c5..78f06c739 100644
--- a/docs/usermanual-glyph-information.xml
+++ b/docs/usermanual-glyph-information.xml
@@ -1,3 +1,9 @@
+
+
+
+]>
Glyph information
@@ -5,4 +11,4 @@
-
\ No newline at end of file
+
diff --git a/docs/usermanual-hello-harfbuzz.xml b/docs/usermanual-hello-harfbuzz.xml
deleted file mode 100644
index 716b2f2dd..000000000
--- a/docs/usermanual-hello-harfbuzz.xml
+++ /dev/null
@@ -1,183 +0,0 @@
-
- Hello, HarfBuzz
-
- Here's the simplest HarfBuzz that can possibly work. We will improve
- it later.
-
-
-
-
- Create a buffer and put your text in it.
-
-
-
-
- #include <hb.h>
- hb_buffer_t *buf;
- buf = hb_buffer_create();
- hb_buffer_add_utf8(buf, text, strlen(text), 0, strlen(text));
-
-
-
-
- Guess the script, language and direction of the buffer.
-
-
-
-
- hb_buffer_guess_segment_properties(buf);
-
-
-
-
- Create a face and a font, using FreeType for now.
-
-
-
-
- #include <hb-ft.h>
- FT_New_Face(ft_library, font_path, index, &face)
- hb_font_t *font = hb_ft_font_create(face);
-
-
-
-
- Shape!
-
-
-
-
- hb_shape(font, buf, NULL, 0);
-
-
-
-
- Get the glyph and position information.
-
-
-
-
- hb_glyph_info_t *glyph_info = hb_buffer_get_glyph_infos(buf, &glyph_count);
- hb_glyph_position_t *glyph_pos = hb_buffer_get_glyph_positions(buf, &glyph_count);
-
-
-
-
- Iterate over each glyph.
-
-
-
-
- for (i = 0; i < glyph_count; ++i) {
- glyphid = glyph_info[i].codepoint;
- x_offset = glyph_pos[i].x_offset / 64.0;
- y_offset = glyph_pos[i].y_offset / 64.0;
- x_advance = glyph_pos[i].x_advance / 64.0;
- y_advance = glyph_pos[i].y_advance / 64.0;
- draw_glyph(glyphid, cursor_x + x_offset, cursor_y + y_offset);
- cursor_x += x_advance;
- cursor_y += y_advance;
- }
-
-
-
-
- Tidy up.
-
-
-
-
- hb_buffer_destroy(buf);
- hb_font_destroy(hb_ft_font);
-
-
- What HarfBuzz doesn't do
-
- The code above will take a UTF8 string, shape it, and give you the
- information required to lay it out correctly on a single
- horizontal (or vertical) line using the font provided. That is the
- extent of HarfBuzz's responsibility.
-
-
- If you are implementing a text layout engine you may have other
- responsibilities, that HarfBuzz will not help you with:
-
-
-
-
- HarfBuzz won't help you with bidirectionality. If you want to
- lay out text with mixed Hebrew and English, you will need to
- ensure that the buffer provided to HarfBuzz has those
- characters in the correct layout order. This will be different
- from the logical order in which the Unicode text is stored. In
- other words, the user will hit the keys in the following
- sequence:
-
-
-A B C [space] ג ב א [space] D E F
-
-
- but will expect to see in the output:
-
-
-ABC אבג DEF
-
-
- This reordering is called bidi processing
- ("bidi" is short for bidirectional), and there's an
- algorithm as an annex to the Unicode Standard which tells you how
- to reorder a string from logical order into presentation order.
- Before sending your string to HarfBuzz, you may need to apply the
- bidi algorithm to it. Libraries such as ICU and fribidi can do
- this for you.
-
-
-
-
- HarfBuzz won't help you with text that contains different font
- properties. For instance, if you have the string "a
- huge breakfast", and you expect
- "huge" to be italic, you will need to send three
- strings to HarfBuzz: a, in your Roman font;
- huge using your italic font; and
- breakfast using your Roman font again.
- Similarly if you change font, font size, script, language or
- direction within your string, you will need to shape each run
- independently and then output them independently. HarfBuzz
- expects to shape a run of characters sharing the same
- properties.
-
-
-
-
- HarfBuzz won't help you with line breaking, hyphenation or
- justification. As mentioned above, it lays out the string
- along a single line of, notionally,
- infinite length. If you want to find out where the potential
- word, sentence and line break points are in your text, you
- could use the ICU library's break iterator functions.
-
-
- HarfBuzz can tell you how wide a shaped piece of text is, which is
- useful input to a justification algorithm, but it knows nothing
- about paragraphs, lines or line lengths. Nor will it adjust the
- space between words to fit them proportionally into a line. If you
- want to layout text in paragraphs, you will probably want to send
- each word of your text to HarfBuzz to determine its shaped width
- after glyph substitutions, then work out how many words will fit
- on a line, and then finally output each word of the line separated
- by a space of the correct size to fully justify the paragraph.
-
-
-
-
- As a layout engine implementor, HarfBuzz will help you with the
- interface between your text and your font, and that's something
- that you'll need - what you then do with the glyphs that your font
- returns is up to you. The example we saw above enough to get us
- started using HarfBuzz. Now we are going to use the remainder of
- HarfBuzz's API to refine that example and improve our text shaping
- capabilities.
-
-
-
\ No newline at end of file
diff --git a/docs/usermanual-install-harfbuzz.xml b/docs/usermanual-install-harfbuzz.xml
index 899cc5bd6..a6484fc5a 100644
--- a/docs/usermanual-install-harfbuzz.xml
+++ b/docs/usermanual-install-harfbuzz.xml
@@ -1,70 +1,431 @@
+
+
+
+]>
- Install HarfBuzz
+ Installing HarfBuzz
+
- Download
+ Downloading HarfBuzz
- For tarball releases of HarfBuzz, look
- here.
- At the same place you will
- also find Win32 binary bundles that include libharfbuzz DLL, hb-view.exe,
- hb-shape.exe, and all dependencies.
+ The HarfBuzz source code is hosted at github.com/harfbuzz/harfbuzz. The
+ same source tree is also available at the
+ Freedesktop.org
+ site.
- The canonical source tree is available
- here.
- Also available on github.
+ Tarball releases and Win32 binary bundles (which include the
+ libharfbuzz DLL, hb-view.exe, hb-shape.exe, and all
+ dependencies) of HarfBuzz can be downloaded from github.com/harfbuzz/harfbuzz/releases
+ or from
+ Freedesktop.org.
- The API that comes with will
- not change incompatibly. Other, peripheral, headers are more likely to go
- through minor modifications, but again, will do our best to never change
- API in an incompatible way. We will never break the ABI.
+ Release notes are posted with each new release to provide an
+ overview of the changes. The project tracks bug
+ reports and other issues on GitHub. Discussion and
+ questions are welcome on the HarfBuzz
+ mailing list.
- If you are not sure whether Pango or HarfBuzz is right for you, read
- this.
+ The API included in the file will not change in a
+ compatibility-breaking way in any release. However, other,
+ peripheral headers are more likely to go through minor
+ modifications. We will do our best to never change APIs in an
+ incompatible way. We will never break the ABI.
+
- Building
+ Building HarfBuzz
+
+
+ Building on Linux
- On Linux, install the development packages for FreeType, Cairo, and GLib.
- For example, on Ubuntu / Debian, you would do:
-
-sudo apt-get install gcc g++ libfreetype6-dev libglib2.0-dev libcairo2-dev
-
- whereas on Fedora, RHEL, CentOS, and other Red Hat based systems you would do:
-
-sudo yum install gcc gcc-c++ freetype-devel glib2-devel cairo-devel
-
- or using MacPorts:
-
-sudo port install freetype glib2 cairo
-
+ (1) To build HarfBuzz on Linux, you must first install the
+ development packages for FreeType, Cairo, and GLib. The exact
+ commands required for this step will vary depending on
+ the Linux distribution you use.
- If you are using a tarball, you can now proceed to running
- configure and make as with any
- other standard package. That should leave you with a shared library in
- src/, and a few utility programs including hb-view
- and hb-shape under util/.
+ For example, on an Ubuntu or Debian system, you would run:
+
+ sudo apt install gcc g++
+ libfreetype6-dev libglib2.0-dev libcairo2-dev
+
+ On Fedora, RHEL, CentOS, or other Red-Hat–based systems, you would run:
+
+ sudo yum install gcc gcc-c++ freetype-devel glib2-devel cairo-devel
+
+
+
+
+
+ (2) The next step depends on whether you
+ are building from the source in a downloaded release tarball or
+ from the source directly from the git repository.
- If you are bootstrapping from git, you need a few more tools before you
- can run autogen.sh for the first time. Namely,
- pkg-config and ragel.
- Again, on Ubuntu / Debian:
-
-sudo apt-get install autoconf automake libtool pkg-config ragel gtk-doc-tools
-
- and on Fedora, RHEL, CentOS:
-
-sudo yum install autoconf automake libtool pkgconfig ragel gtk-doc
-
- or using MacPorts:
-
-sudo port install autoconf automake libtool pkgconfig ragel gtk-doc
-
+ (2)(a) If you downloaded the HarfBuzz
+ source code in a tarball, you can now extract the source.
+
+ From a shell in the top-level directory of the extracted source
+ code, you can run ./configure followed by
+ make as with any other standard package.
+
+
+ This should leave you with a shared
+ library in the src/ directory, and a few
+ utility programs including hb-view and
+ hb-shape under the util/
+ directory.
+
+
+ (2)(b) If you are building from the source in the HarfBuzz git
+ repository, rather than installing from a downloaded tarball
+ release, then you must install two more auxiliary tools before you
+ can build for the first time: pkg-config and
+ ragel.
+
+
+ On Ubuntu or Debian, run:
+
+ sudo apt-get install autoconf automake libtool pkg-config ragel gtk-doc-tools
+
+ On Fedora, RHEL, CentOS, run:
+
+ sudo yum install autoconf automake libtool pkgconfig ragel gtk-doc
+
+
+
+
+ With pkg-config and ragel
+ installed, you can now run ./autogen.sh,
+ followed by ./configure and
+ make to build HarfBuzz.
+
+
+
+
+
+ Building on Windows
+
+
+ On Windows, consider using Microsoft's free vcpkg utility
+ to build HarfBuzz, its dependencies, and other open-source
+ libraries.
+
+
+ If you need to build HarfBuzz from source, first put the
+ ragel binary on your
+ PATH, then follow the appveyor CI cmake
+ build
+ instructions.
+
+
+
+
+
+ Building on macOS
+
+
+ There are two ways to build HarfBuzz on Mac systems: MacPorts
+ and Homebrew. The process is similar to the process used on a
+ Linux system.
+
+
+ (1) You must first install the
+ development packages for FreeType, Cairo, and GLib. If you are
+ using MacPorts, you should run:
+
+ sudo port install freetype glib2 cairo
+
+
+
+ If you are using Homebrew, you should run:
+
+ brew install freetype glib cairo
+
+
+
+ (2) The next step depends on whether you are building from the
+ source in a downloaded release tarball or from the source directly
+ from the git repository.
+
+
+ (2)(a) If you are installing HarfBuzz
+ from a downloaded tarball release, extract the tarball and
+ open a Terminal in the extracted source-code directory. Run:
+
+ ./configure
+
+ followed by:
+
+ make
+
+ to build HarfBuzz.
+
+
+ (2)(b) Alternatively, if you are building
+ HarfBuzz from the source in the HarfBuzz git repository, then
+ you must install several built-time dependencies before
+ proceeding.
+
+ If you are
+ using MacPorts, you should run:
+
+ sudo port install autoconf
+ automake libtool pkgconfig ragel gtk-doc
+
+ to install the build dependencies.
+
+ If you are using Homebrew, you should run:
+
+ brew install autoconf automake libtool pkgconfig ragel gtk-doc
+
+ Finally, you can run:
+
+ ./autogen.sh
+
+
+
+ (3) You can now build HarfBuzz (on either
+ a MacPorts or a Homebrew system) by running:
+
+ ./configure
+
+ followed by:
+
+ make
+
+
+
+ This should leave you with a shared
+ library in the src/ directory, and a few
+ utility programs including hb-view and
+ hb-shape under the util/
+ directory.
+
+
+
+
+
+ Configuration options
+
+
+ The instructions in the "Building HarfBuzz" section will build
+ the source code under its default configuration. If needed,
+ the following additional configuration options are available.
+
+
+
+
+ --with-libstdc++
+
+
+ Allow linking with libstdc++. (Default = no)
+
+
+ This option enables or disables linking HarfBuzz to the
+ system's libstdc++ library.
+
+
+
+
+
+ --with-glib
+
+
+ Use GLib. (Default = auto)
+
+
+ This option enables or disables usage of the GLib
+ library. The default setting is to check for the
+ presence of GLib and, if it is found, build with
+ GLib support. GLib is native to GNU/Linux systems but is
+ available on other operating system as well.
+
+
+
+
+
+ --with-gobject
+
+
+ Use GObject. (Default = no)
+
+
+ This option enables or disables usage of the GObject
+ library. The default setting is to check for the
+ presence of GObject and, if it is found, build with
+ GObject support. GObject is native to GNU/Linux systems but is
+ available on other operating system as well.
+
+
+
+
+
+ --with-cairo
+
+
+ Use Cairo. (Default = auto)
+
+
+ This option enables or disables usage of the Cairo
+ graphics-rendering library. The default setting is to
+ check for the presence of Cairo and, if it is found,
+ build with Cairo support.
+
+
+ Note: Cairo is used only by the HarfBuzz
+ command-line utilities, and not by the HarfBuzz library.
+
+
+
+
+
+ --with-fontconfig
+
+
+ Use Fontconfig. (Default = auto)
+
+
+ This option enables or disables usage of the Fontconfig
+ library, which provides font-matching functions and
+ provides access to font properties. The default setting
+ is to check for the presence of Fontconfig and, if it is
+ found, build with Fontconfig support.
+
+
+ Note: Fontconfig is used only by the HarfBuzz
+ command-line utilities, and not by the HarfBuzz library.
+
+
+
+
+
+ --with-icu
+
+
+ Use the ICU library. (Default = auto)
+
+
+ This option enables or disables usage of the
+ International Components for
+ Unicode (ICU) library, which provides access
+ to Unicode Character Database (UCD) properties as well
+ as normalization and conversion functions. The default
+ setting is to check for the presence of ICU and, if it
+ is found, build with ICU support.
+
+
+
+
+
+ --with-ucdn
+
+
+ Use HarfBuzz's built-in UCDN library. (Default = auto)
+
+
+ The HarfBuzz source tree includes a Unicode
+ Database and Normalization (UCDN) library
+ that provides access to basic character properties in
+ the Unicode Character Database (UCD) as well as low-level
+ normalization functions. HarfBuzz can be built without
+ this UCDN support if the usage of a different UCDN
+ library is desired.
+
+
+
+
+
+ --with-graphite2
+
+
+ Use the Graphite2 library. (Default = no)
+
+
+ This option enables or disables usage of the Graphite2
+ library, which provides support for the Graphite shaping
+ model.
+
+
+
+
+
+ --with-freetype
+
+
+ Use the FreeType library. (Default = auto)
+
+
+ This option enables or disables usage of the FreeType
+ font-rendering library. The default setting is to check for the
+ presence of FreeType and, if it is found, build with
+ FreeType support.
+
+
+
+
+
+ --with-uniscribe
+
+
+ Use the Uniscribe
+ library (experimental). (Default = no)
+
+
+ This option enables or disables usage of the Uniscribe
+ font-rendering library. Uniscribe is available on
+ Windows systems. Uniscribe support is used only for
+ testing purposes and does not need to be enabled for
+ HarfBuzz to run on Windows systems.
+
+
+
+
+
+ --with-directwrite
+
+
+ Use the DirectWrite library (experimental). (Default = no)
+
+
+ This option enables or disables usage of the DirectWrite
+ font-rendering library. DirectWrite is available on
+ Windows systems. DirectWrite support is used only for
+ testing purposes and does not need to be enabled for
+ HarfBuzz to run on Windows systems.
+
+
+
+
+
+ --with-coretext
+
+
+ Use the CoreText library. (Default = no)
+
+
+ This option enables or disables usage of the CoreText
+ library. CoreText is available on macOS and iOS systems.
+
+
+
+
+
+
diff --git a/docs/usermanual-opentype-features.xml b/docs/usermanual-opentype-features.xml
index 470bab8d1..51ff55a77 100644
--- a/docs/usermanual-opentype-features.xml
+++ b/docs/usermanual-opentype-features.xml
@@ -1,3 +1,9 @@
+
+
+
+]>
Shaping and shape plans
-
\ No newline at end of file
+
diff --git a/docs/usermanual-shaping-concepts.xml b/docs/usermanual-shaping-concepts.xml
new file mode 100644
index 000000000..bc9f1b830
--- /dev/null
+++ b/docs/usermanual-shaping-concepts.xml
@@ -0,0 +1,374 @@
+
+
+
+]>
+
+ Shaping concepts
+
+ Text shaping
+
+ Text shaping is the process of transforming a sequence of Unicode
+ codepoints that represent individual characters (letters,
+ diacritics, tone marks, numbers, symbols, etc.) into the
+ orthographically and linguistically correct two-dimensional layout
+ of glyph shapes taken from a specified font.
+
+
+ For some writing systems (or scripts) and
+ languages, the process is simple, requiring the shaper to do
+ little more than advance the horizontal position forward by the
+ correct amount for each successive glyph.
+
+
+ But, for complex scripts, any combination of
+ several shaping operations may be required, and the rules for how
+ and when they are applied vary from script to script. HarfBuzz and
+ other shaping engines implement these rules.
+
+
+ The exact rules and necessary operations for a particular script
+ constitute a shaping model. OpenType
+ specifies a set of shaping models that covers all of
+ Unicode. Other shaping models are available, however, including
+ Graphite and Apple Advanced Typography (AAT).
+
+
+
+
+ Complex scripts
+
+ In text-shaping terminology, scripts are generally classified as
+ either complex or non-complex.
+
+
+ Complex scripts are those for which transforming the input
+ sequence into the final layout requires some combination of
+ operations—such as context-dependent substitutions,
+ context-dependent mark positioning, glyph-to-glyph joining,
+ glyph reordering, or glyph stacking.
+
+
+ In some complex scripts, the shaping rules require that a text
+ run be divided into syllables before the operations can be
+ applied. Other complex scripts may apply shaping operations over
+ entire words or over the entire text run, with no subdivision
+ required.
+
+
+ Non-complex scripts, by definition, do not require these
+ operations. However, correctly shaping a text run in a
+ non-complex script may still involve Unicode normalization,
+ ligature substitutions, mark positioning, kerning, and applying
+ other font features. The key difference is that a text run in a
+ non-complex script can be processed sequentially and in the same
+ order as the input sequence of Unicode codepoints, without
+ requiring an analysis stage.
+
+
+
+
+ Shaping operations
+
+ Shaping a complex-script text run involves transforming the
+ input sequence of Unicode codepoints with some combination of
+ operations that is specified in the shaping model for the
+ script.
+
+
+ The specific conditions that trigger a given operation for a
+ text run varies from script to script, as do the order that the
+ operations are performed in and which codepoints are
+ affected. However, the same general set of shaping operations is
+ common to all of the complex-script shaping models.
+
+
+
+
+
+ A reordering operation moves a glyph
+ from its original ("logical") position in the sequence to
+ some other ("visual") position.
+
+
+ The shaping model for a given complex script might involve
+ more than one reordering step.
+
+
+
+
+
+ A joining operation replaces a glyph
+ with an alternate form that is designed to connect with one
+ or more of the adjacent glyphs in the sequence.
+
+
+
+
+
+ A contextual substitution operation
+ replaces either a single glyph or a subsequence of several
+ glyphs with an alternate glyph. This substitution is
+ performed when the original glyph or subsequence of glyphs
+ occurs in a specified position with respect to the
+ surrounding sequence. For example, one substitution might be
+ performed only when the target glyph is the first glyph in
+ the sequence, while another substitution is performed only
+ when a different target glyph occurs immediately after a
+ particular string pattern.
+
+
+ The shaping model for a given complex script might involve
+ multiple contextual-substitution operations, each applying
+ to different target glyphs and patterns, and which are
+ performed in separate steps.
+
+
+
+
+
+ A contextual positioning operation
+ moves the horizontal and/or vertical position of a
+ glyph. This positioning move is performed when the glyph
+ occurs in a specified position with respect to the
+ surrounding sequence.
+
+
+ Many contextual positioning operations are used to place
+ mark glyphs (such as diacritics, vowel
+ signs, and tone markers) with respect to
+ base glyphs. However, some complex
+ scripts may use contextual positioning operations to
+ correctly place base glyphs as well, such as
+ when the script uses stacking characters.
+
+
+
+
+
+
+
+ Unicode character categories
+
+ Shaping models are typically specified with respect to how
+ scripts are defined in the Unicode standard.
+
+
+ Every codepoint in the Unicode Character Database (UCD) is
+ assigned a Unicode General Category (UGC),
+ which provides the most fundamental information about the
+ codepoint: whether the codepoint represents a
+ Letter, a Mark, a
+ Number, Punctuation, a
+ Symbol, a Separator,
+ or something else (Other).
+
+
+ These UGC properties are "Major" categories. Each codepoint is
+ further assigned to a "minor" category within its Major
+ category, such as "Letter, uppercase" (Lu) or
+ "Letter, modifier" (Lm).
+
+
+ Shaping models are concerned primarily with Letter and Mark
+ codepoints. The minor categories of Mark codepoints are
+ particularly important for shaping. Marks can be nonspacing
+ (Mn), spacing combining
+ (Mc), or enclosing (Me).
+
+
+ In addition to the UGC property, codepoints in the Indic and
+ Southeast Asian scripts are also assigned
+ Unicode Indic Syllabic Category (UISC) and
+ Unicode Indic Positional Category (UIPC)
+ property that provides more detailed information needed for
+ shaping.
+
+
+ The UISC property sub-categorizes Letters and Marks according to
+ common script-shaping behaviors. For example, UISC distinguishes
+ between consonant letters, vowel letters, and vowel marks. The
+ UIPC property sub-categorizes Mark codepoints by the visual
+ position that they occupy (above, below, right, left, or in
+ multiple positions).
+
+
+ Some complex scripts require that the text run be split into
+ syllables, and what constitutes a valid syllable in these
+ scripts is specified in regular expressions of the Letter and
+ Mark codepoints that take the UISC and UIPC properties into account.
+
+
+
+
+
+ Text runs
+
+ Real-world text usually contains codepoints from a mixture of
+ different Unicode scripts (including punctuation, numbers, symbols,
+ white-space characters, and other codepoints that do not belong
+ to any script). Real-world text may also be marked up with
+ formatting that changes font properties (including the font,
+ font style, and font size).
+
+
+ For shaping purposes, all real-world text streams must be first
+ segmented into runs that have a uniform set of properties.
+
+
+ In particular, shaping models always assume that every codepoint
+ in a text run has the same direction,
+ script tag, and
+ language tag.
+
+
+
+
+ OpenType shaping models
+
+ OpenType provides shaping models for the following scripts:
+
+
+
+
+
+ The default shaping model handles all
+ non-complex scripts, and may also be used as a fallback for
+ handling unrecognized scripts.
+
+
+
+
+
+ The Indic shaping model handles the Indic
+ scripts Bengali, Devanagari, Gujarati, Gurmukhi, Kannada,
+ Malayalam, Oriya, Tamil, Telugu, and Sinhala.
+
+
+ The Indic shaping model was revised significantly in
+ 2005. To denote the change, a new set of script
+ tags was assigned for Bengali, Devanagari,
+ Gujarati, Gurmukhi, Kannada, Malayalam, Oriya, Tamil, and
+ Telugu. For the sake of clarity, the term "Indic2" is
+ sometimes used to refer to the current, revised shaping
+ model.
+
+
+
+
+
+ The Arabic shaping model supports
+ Arabic, Mongolian, N'Ko, Syriac, and several other connected
+ or cursive scripts.
+
+
+
+
+
+ The Thai/Lao shaping model supports
+ the Thai and Lao scripts.
+
+
+
+
+
+ The Khmer shaping model supports the
+ Khmer script.
+
+
+
+
+
+ The Myanmar shaping model supports the
+ Myanmar (or Burmese) script.
+
+
+
+
+
+ The Tibetan shaping model supports the
+ Tibetan script.
+
+
+
+
+
+ The Hangul shaping model supports the
+ Hangul script.
+
+
+
+
+
+ The Hebrew shaping model supports the
+ Hebrew script.
+
+
+
+
+
+ The Universal Shaping Engine (USE)
+ shaping model supports complex scripts not covered by one of
+ the above, script-specific shaping models, including
+ Javanese, Balinese, Buginese, Batak, Chakma, Lepcha, Modi,
+ Phags-pa, Tagalog, Siddham, Sundanese, Tai Le, Tai Tham, Tai
+ Viet, and many others.
+
+
+
+
+
+ Text runs that do not fall under one of the above shaping
+ models may still require processing by a shaping engine. Of
+ particular note is Emoji shaping, which
+ may involve variation-selector sequences and glyph
+ substitution. Emoji shaping is handled by the default
+ shaping model.
+
+
+
+
+
+
+
+
+ Graphite shaping
+
+ In contrast to OpenType shaping, Graphite shaping does not
+ specify a predefined set of shaping models or a set of supported
+ scripts.
+
+
+ Instead, each Graphite font contains a complete set of rules that
+ implement the required shaping model for the intended
+ script. These rules include finite-state machines to match
+ sequences of codepoints to the shaping operations to perform.
+
+
+ Graphite shaping can perform the same shaping operations used in
+ OpenType shaping, as well as other functions that have not been
+ defined for OpenType shaping.
+
+
+
+
+ AAT shaping
+
+ In contrast to OpenType shaping, AAT shaping does not specify a
+ predefined set of shaping models or a set of supported scripts.
+
+
+ Instead, each AAT font includes a complete set of rules that
+ implement the desired shaping model for the intended
+ script. These rules include finite-state machines to match glyph
+ sequences and the shaping operations to perform.
+
+
+ Notably, AAT shaping rules are expressed for glyphs in the font,
+ not for Unicode codepoints. AAT shaping can perform the same
+ shaping operations used in OpenType shaping, as well as other
+ functions that have not been defined for OpenType shaping.
+
+
+
diff --git a/docs/usermanual-what-is-harfbuzz.xml b/docs/usermanual-what-is-harfbuzz.xml
index 38f40cf11..8532d7cc2 100644
--- a/docs/usermanual-what-is-harfbuzz.xml
+++ b/docs/usermanual-what-is-harfbuzz.xml
@@ -1,115 +1,441 @@
+
+
+
+]>
What is HarfBuzz?
- HarfBuzz is a text shaping engine. It solves
- the problem of selecting and positioning glyphs from a font given a
- Unicode string.
+ HarfBuzz is a text-shaping engine. If you
+ give HarfBuzz a font and a string containing a sequence of Unicode
+ codepoints, HarfBuzz selects and positions the corresponding
+ glyphs from the font, applying all of the necessary layout rules
+ and font features. HarfBuzz then returns the string to you in the
+ form that is correctly arranged for the language and writing
+ system.
-
- Why do I need it?
+
+ HarfBuzz can properly shape all of the world's major writing
+ systems. It runs on all major operating systems and software
+ platforms and it supports the modern font formats in use
+ today.
+
+
+ What is text shaping?
- Text shaping is an integral part of preparing text for display. It
- is a fairly low level operation; HarfBuzz is used directly by
- graphic rendering libraries such as Pango, and the layout engines
- in Firefox, LibreOffice and Chromium. Unless you are
- writing one of these layout engines yourself,
- you will probably not need to use HarfBuzz - normally higher level
- libraries will turn text into glyphs for you.
+ Text shaping is the process of translating a string of character
+ codes (such as Unicode codepoints) into a properly arranged
+ sequence of glyphs that can be rendered onto a screen or into
+ final output form for inclusion in a document.
+
+
+ The shaping process is dependent on the input string, the active
+ font, the script (or writing system) that the string is in, and
+ the language that the string is in.
+
+
+ Modern software systems generally only deal with strings in the
+ Unicode encoding scheme (although legacy systems and documents may
+ involve other encodings).
+
+
+ There are several font formats that a program might
+ encounter, each of which has a set of standard text-shaping
+ rules.
+
+ The dominant format is OpenType. The
+ OpenType specification defines a series of shaping models for
+ various scripts from around the world. These shaping models depend on
+ the font including certain features in its GSUB
+ and GPOS tables.
+
+
+ Alternatively, OpenType fonts can include shaping features for
+ the Graphite shaping model.
+
+
+ TrueType fonts can also include OpenType shaping
+ features. Alternatively, TrueType fonts can also include Apple
+ Advanced Typography (AAT) tables to implement shaping
+ support. AAT fonts are generally only found on macOS and iOS systems.
+
+
+ Text strings will usually be tagged with a script and language
+ tag that provide the context needed to perform text shaping
+ correctly. The necessary Script
+ and language
+ tags are defined by OpenType.
+
+
+
+
+ Why do I need a shaping engine?
+
+ Text shaping is an integral part of preparing text for
+ display. Before a Unicode sequence can be rendered, the
+ codepoints in the sequence must be mapped to the corresponding
+ glyphs provided in the font, and those glyphs must be positioned
+ correctly relative to each other. For many of the scripts
+ supported in Unicode, these steps involve script-specific layout
+ rules, including complex joining, reordering, and positioning
+ behavior. Implementing these rules is the job of the shaping engine.
+
+
+ Text shaping is a fairly low-level operation. HarfBuzz is
+ used directly by text-handling libraries like Pango, as well as by the layout
+ engines in Firefox, LibreOffice, and Chromium. Unless you are
+ writing one of these layout engines
+ yourself, you will probably not need to use HarfBuzz: normally,
+ a layout engine, toolkit, or other library will turn text into
+ glyphs for you.
However, if you are writing a layout engine
- or graphics library yourself, you will need to perform text
- shaping, and this is where HarfBuzz can help you. Here are some
- reasons why you need it:
+ or graphics library yourself, then you will need to perform text
+ shaping, and this is where HarfBuzz can help you.
+
+
+ Here are some specific scenarios where a text-shaping engine
+ like HarfBuzz helps you:
- OpenType fonts contain a set of glyphs, indexed by glyph ID.
- The glyph ID within the font does not necessarily relate to a
- Unicode codepoint. For instance, some fonts have the letter
- "a" as glyph ID 1. To pull the right glyph out of
- the font in order to display it, you need to consult a table
- within the font (the "cmap" table) which maps
- Unicode codepoints to glyph IDs. Text shaping turns codepoints
- into glyph IDs.
+ OpenType fonts contain a set of glyphs (that is, shapes
+ to represent the letters, numbers, punctuation marks, and
+ all other symbols), which are indexed by a glyph ID.
+
+
+ A particular glyph ID within the font does not necessarily
+ correlate to a predictable Unicode codepoint. For instance,
+ some fonts have the letter "a" as glyph ID 1, but
+ many others do not. In order to retrieve the right glyph
+ from the font to display "a", you need to consult
+ the table inside the font (the cmap
+ table) that maps Unicode codepoints to glyph IDs. In other
+ words, text shaping turns codepoints into glyph
+ IDs.
Many OpenType fonts contain ligatures: combinations of
- characters which are rendered together. For instance, it's
- common for the fi combination to appear in
- print as the single ligature "fi". Whether you should
- render text as fi or "fi" does not
- depend on the input text, but on the capabilities of the font
- and the level of ligature application you wish to perform.
- Text shaping involves querying the font's ligature tables and
- determining what substitutions should be made.
+ characters that are rendered as a single unit. For instance,
+ it is common for the fi letter
+ combination to appear in print as the single ligature glyph
+ "fi".
+
+
+ Whether you should render an "f, i" sequence
+ as fi or as "fi" does not
+ depend on the input text. Instead, it depends on the whether
+ or not the font includes an "fi" glyph and on the
+ level of ligature application you wish to perform. The font
+ and the amount of ligature application used are under your
+ control. In other words, text shaping involves
+ querying the font's ligature tables and determining what
+ substitutions should be made.
- While ligatures like "fi" are typographic
- refinements, some languages require such
+ While ligatures like "fi" are optional typographic
+ refinements, some languages require certain
substitutions to be made in order to display text correctly.
- In Tamil, when the letter "TTA" (ட) letter is
- followed by "U" (உ), the combination should appear
- as the single glyph "டு". The sequence of Unicode
- characters "டஉ" needs to be rendered as a single
- glyph from the font - text shaping chooses the correct glyph
- from the sequence of characters provided.
+
+
+ For example, in Tamil, when the letter "TTA" (ட)
+ letter is followed by "U" (உ), the pair
+ must be replaced by the single glyph "டு". The
+ sequence of Unicode characters "டஉ" needs to be
+ substituted with a single "டு" glyph from the
+ font.
+
+
+ But "டு" does not have a Unicode codepoint. To
+ find this glyph, you need to consult the table inside
+ the font (the GSUB table) that contains
+ substitution information. In other words, text shaping
+ chooses the correct glyph for a sequence of characters
+ provided.
- Similarly, each Arabic character has four different variants:
- within a font, there will be glyphs for the initial, medial,
- final, and isolated forms of each letter. Unicode only encodes
- one codepoint per character, and so a Unicode string will not
- tell you which glyph to use. Text shaping chooses the correct
- form of the letter and returns the correct glyph from the font
- that you need to render.
+ Similarly, each Arabic character has four different variants
+ corresponding to the different positions it might appear in
+ within a sequence. Inside a font, there will be separate
+ glyphs for the initial, medial, final, and isolated forms of
+ each letter, each at a different glyph ID.
+
+
+ Unicode only assigns one codepoint per character, so a
+ Unicode string will not tell you which glyph variant to use
+ for each character. To decide, you need to analyze the whole
+ string and determine the appropriate glyph for each character
+ based on its position. In other words, text
+ shaping chooses the correct form of the letter by its
+ position and returns the correct glyph from the font.
- Other languages have marks and accents which need to be
- rendered in certain positions around a base character. For
- instance, the Moldovan language has the Cyrillic letter
- "zhe" (ж) with a breve accent, like so: ӂ. Some
- fonts will contain this character as an individual glyph,
- whereas other fonts will not contain a zhe-with-breve glyph
- but expect the rendering engine to form the character by
- overlaying the two glyphs ж and ˘. Where you should draw the
- combining breve depends on the height of the preceding glyph.
- Again, for Arabic, the correct positioning of vowel marks
- depends on the height of the character on which you are
- placing the mark. Text shaping tells you whether you have a
- precomposed glyph within your font or if you need to compose a
- glyph yourself out of combining marks, and if so, where to
- position those marks.
+ Other languages involve marks and accents that need to be
+ rendered in specific positions relative a base character. For
+ instance, the Moldovan language includes the Cyrillic letter
+ "zhe" (ж) with a breve accent, like so: "ӂ".
+
+
+ Some fonts will provide this character as a single
+ zhe-with-breve glyph, but other fonts will not and, instead,
+ will expect the rendering engine to form the character by
+ superimposing the separate "ж" and "˘"
+ glyphs.
+
+
+ But exactly where you should draw the breve depends on the
+ height and width of the preceding zhe glyph. To find the
+ right position, you need to consult the table inside
+ the font (the GPOS table) that contains
+ positioning information.
+ In other words, text shaping tells you whether you
+ have a precomposed glyph within your font or if you need to
+ compose a glyph yourself out of combining marks—and,
+ if so, where to position those marks.
- If this is something that you need to do, then you need a text
- shaping engine: you could use Uniscribe if you are using Windows;
- you could use CoreText on OS X; or you could use HarfBuzz. In the
- rest of this manual, we are going to assume that you are the
- implementor of a text layout engine.
+ If tasks like these are something that you need to do, then you
+ need a text shaping engine. You could use Uniscribe if you are
+ writing Windows software; you could use CoreText on macOS; or
+ you could use HarfBuzz.
+
+
+
+ In the rest of this manual, the text will assume that the reader
+ is that implementor of a text-layout engine.
+
+
+
+
+
+
+ What does HarfBuzz do?
+
+ HarfBuzz provides text shaping through a cross-platform
+ C API that accepts sequences of Unicode codepoints as input. Currently,
+ the following OpenType shaping models are supported:
+
+
+
+
+ Indic (covering Devanagari, Bengali, Gujarati,
+ Gurmukhi, Kannada, Malayalam, Oriya, Tamil, Telugu, and
+ Sinhala)
+
+
+
+
+ Arabic (covering Arabic, N'Ko, Syriac, and Mongolian)
+
+
+
+
+ Thai and Lao
+
+
+
+
+ Khmer
+
+
+
+
+ Myanmar
+
+
+
+
+
+ Tibetan
+
+
+
+
+
+ Hangul
+
+
+
+
+
+ Hebrew
+
+
+
+
+ The Universal Shaping Engine or USE
+ (covering complex scripts not covered by the above shaping
+ models)
+
+
+
+
+ A default shaping model for non-complex scripts
+ (covering Latin, Cyrillic, Greek, Armenian, Georgian, Tifinagh,
+ and many others)
+
+
+
+
+ Emoji (including emoji modifier sequences, flag sequences,
+ and ZWJ sequences)
+
+
+
+
+
+ In addition to OpenType shaping, HarfBuzz supports the latest
+ version of Graphite shaping (the "Graphite 2" model) and AAT
+ shaping.
+
+
+
+ HarfBuzz can read and understand TrueType fonts (.ttf), TrueType
+ collections (.ttc), and OpenType fonts (.otf, including those
+ fonts that contain TrueType-style outlines and those that
+ contain PostScript CFF or CFF2 outlines).
+
+
+
+ HarfBuzz is designed and tested to run on top of the FreeType
+ font renderer. It can run on Linux, Android, Windows, macOS, and
+ iOS systems.
+
+
+
+ In addition to its core shaping functionality, HarfBuzz provides
+ functions for accessing other font features, including optional
+ GSUB and GPOS OpenType features, as well as
+ all color-font formats (CBDT,
+ sbix, COLR/CPAL, and
+ SVG-OT) and OpenType variable fonts. HarfBuzz
+ also includes a font-subsetting feature. HarfBuzz can perform
+ some low-level math-shaping operations, although it does not
+ currently perform full shaping for mathematical typesetting.
+
+
+
+ A suite of command-line utilities is also provided in the
+ source-code tree, designed to help users test and debug
+ HarfBuzz's features on real-world fonts and input.
+
+
+ What HarfBuzz doesn't do
+
+ HarfBuzz will take a Unicode string, shape it, and give you the
+ information required to lay it out correctly on a single
+ horizontal (or vertical) line using the font provided. That is the
+ extent of HarfBuzz's responsibility.
+
+
+ It is important to note that if you are implementing a complete
+ text-layout engine you may have other responsibilities that
+ HarfBuzz will not help you with. For example:
+
+
+
+
+ HarfBuzz won't help you with bidirectionality. If you want to
+ lay out text that includes a mix of Hebrew and English, you
+ will need to ensure that each buffer provided to HarfBuzz
+ has all of its characters in the same order and that the
+ directionality of the buffer is set correctly. This may mean
+ segmenting the text before it is placed into HarfBuzz buffers. In
+ other words, the user will hit the keys in the following
+ sequence:
+
+
+ A B C [space] ג ב א [space] D E F
+
+
+ but will expect to see in the output:
+
+
+ ABC אבג DEF
+
+
+ This reordering is called bidi processing
+ ("bidi" is short for bidirectional), and there's an
+ algorithm as an annex to the Unicode Standard which tells you how
+ to process a string of mixed directionality.
+ Before sending your string to HarfBuzz, you may need to apply the
+ bidi algorithm to it. Libraries such as ICU and fribidi can do this for you.
+
+
+
+
+ HarfBuzz won't help you with text that contains different font
+ properties. For instance, if you have the string "a
+ huge breakfast", and you expect
+ "huge" to be italic, then you will need to send three
+ strings to HarfBuzz: a, in your Roman font;
+ huge using your italic font; and
+ breakfast using your Roman font again.
+
+
+ Similarly, if you change the font, font size, script,
+ language, or direction within your string, then you will
+ need to shape each run independently and output them
+ independently. HarfBuzz expects to shape a run of characters
+ that all share the same properties.
+
+
+
+
+ HarfBuzz won't help you with line breaking, hyphenation, or
+ justification. As mentioned above, HarfBuzz lays out the string
+ along a single line of, notionally,
+ infinite length. If you want to find out where the potential
+ word, sentence and line break points are in your text, you
+ could use the ICU library's break iterator functions.
+
+
+ HarfBuzz can tell you how wide a shaped piece of text is, which is
+ useful input to a justification algorithm, but it knows nothing
+ about paragraphs, lines or line lengths. Nor will it adjust the
+ space between words to fit them proportionally into a line.
+
+
+
+
+ As a layout-engine implementor, HarfBuzz will help you with the
+ interface between your text and your font, and that's something
+ that you'll need—what you then do with the glyphs that your font
+ returns is up to you.
+
+
+
Why is it called HarfBuzz?
- HarfBuzz began its life as text shaping code within the FreeType
- project, (and you will see references to the FreeType authors
- within the source code copyright declarations) but was then
- abstracted out to its own project. This project is maintained by
- Behdad Esfahbod, and named HarfBuzz. Originally, it was a shaping
- engine for OpenType fonts - "HarfBuzz" is the Persian
- for "open type".
+ HarfBuzz began its life as text-shaping code within the FreeType
+ project (and you will see references to the FreeType authors
+ within the source code copyright declarations), but was then
+ extracted out to its own project. This project is maintained by
+ Behdad Esfahbod, who named it HarfBuzz. Originally, it was a
+ shaping engine for OpenType fonts—"HarfBuzz" is
+ the Persian for "open type".
-
\ No newline at end of file
+
diff --git a/src/Makefile.am b/src/Makefile.am
index ac03890b3..fbd8f6023 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -170,7 +170,6 @@ pkgconfig_DATA += harfbuzz-subset.pc
EXTRA_DIST += harfbuzz-subset.pc.in
FUZZING_CPPFLAGS = \
- -DHB_NDEBUG \
-DHB_MAX_NESTING_LEVEL=3 \
-DHB_SANITIZE_MAX_EDITS=3 \
-DHB_SANITIZE_MAX_OPS_FACTOR=3 \
@@ -269,7 +268,7 @@ EXTRA_DIST += \
CLEANFILES += $(pkgconfig_DATA)
-DEF_FILES = harfbuzz.def harfbuzz-subset.def harfbuzz-icu.def harfbuzz-deprecated.def
+DEF_FILES = harfbuzz.def harfbuzz-subset.def harfbuzz-icu.def harfbuzz-deprecated-symbols.txt
if HAVE_GOBJECT
DEF_FILES += harfbuzz-gobject.def
endif
@@ -283,8 +282,8 @@ harfbuzz-icu.def: $(HB_ICU_headers)
$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
harfbuzz-gobject.def: $(HB_GOBJECT_headers)
$(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
-harfbuzz-deprecated.def: $(srcdir)/hb-deprecated.h
- $(AM_V_GEN) $(srcdir)/gen-def.py "$@" $^
+harfbuzz-deprecated-symbols.txt: $(srcdir)/hb-deprecated.h
+ $(AM_V_GEN) PLAIN_LIST=1 $(srcdir)/gen-def.py "$@" $^
GENERATORS = \
@@ -348,6 +347,7 @@ noinst_PROGRAMS = \
main \
test \
test-buffer-serialize \
+ test-name-table \
test-size-params \
test-would-substitute \
$(NULL)
@@ -361,17 +361,30 @@ test_SOURCES = test.cc
test_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
test_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
-test_would_substitute_SOURCES = test-would-substitute.cc
-test_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
-test_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
+test_buffer_serialize_SOURCES = test-buffer-serialize.cc
+test_buffer_serialize_CPPFLAGS = $(HBCFLAGS)
+test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS)
+
+test_name_table_SOURCES = test-name-table.cc
+test_name_table_CPPFLAGS = $(HBCFLAGS)
+test_name_table_LDADD = libharfbuzz.la $(HBLIBS)
test_size_params_SOURCES = test-size-params.cc
test_size_params_CPPFLAGS = $(HBCFLAGS)
test_size_params_LDADD = libharfbuzz.la $(HBLIBS)
-test_buffer_serialize_SOURCES = test-buffer-serialize.cc
-test_buffer_serialize_CPPFLAGS = $(HBCFLAGS)
-test_buffer_serialize_LDADD = libharfbuzz.la $(HBLIBS)
+test_would_substitute_SOURCES = test-would-substitute.cc
+test_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
+test_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
+
+if HAVE_FREETYPE
+if HAVE_CAIRO_FT
+noinst_PROGRAMS += test-ot-color
+test_ot_color_SOURCES = test-ot-color.cc
+test_ot_color_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) $(CAIRO_FT_CFLAGS)
+test_ot_color_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) $(CAIRO_LIBS) $(CAIRO_FT_LIBS)
+endif # HAVE_CAIRO_FT
+endif # HAVE_FREETYPE
dist_check_SCRIPTS = \
check-c-linkage-decls.sh \
@@ -408,15 +421,6 @@ dump_use_data_SOURCES = dump-use-data.cc hb-ot-shape-complex-use-table.cc
dump_use_data_CPPFLAGS = $(HBCFLAGS)
dump_use_data_LDADD = libharfbuzz.la $(HBLIBS)
-if HAVE_FREETYPE
-if HAVE_CAIRO_FT
-check_PROGRAMS += dump-emoji
-dump_emoji_SOURCES = dump-emoji.cc
-dump_emoji_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS) $(CAIRO_FT_CFLAGS)
-dump_emoji_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS) $(CAIRO_LIBS) $(CAIRO_FT_LIBS)
-endif # HAVE_CAIRO_FT
-endif # HAVE_FREETYPE
-
check_PROGRAMS += test-ot-tag test-unicode-ranges
TESTS += test-ot-tag test-unicode-ranges
diff --git a/src/Makefile.sources b/src/Makefile.sources
index 07713cc84..324ad0906 100644
--- a/src/Makefile.sources
+++ b/src/Makefile.sources
@@ -38,7 +38,10 @@ HB_BASE_sources = \
hb-ot-hmtx-table.hh \
hb-ot-kern-table.hh \
hb-ot-maxp-table.hh \
+ hb-ot-name-language.cc \
+ hb-ot-name-language.hh \
hb-ot-name-table.hh \
+ hb-ot-name.cc \
hb-ot-os2-table.hh \
hb-ot-os2-unicode-ranges.hh \
hb-ot-post-macroman.hh \
@@ -192,7 +195,6 @@ HB_OT_headers = \
hb-ot-math.h \
hb-ot-name.h \
hb-ot-shape.h \
- hb-ot-tag.h \
hb-ot-var.h \
$(NULL)
diff --git a/src/gen-def.py b/src/gen-def.py
index ba39eaae5..9111c698c 100755
--- a/src/gen-def.py
+++ b/src/gen-def.py
@@ -15,11 +15,10 @@ for h in header_paths:
if h.endswith (".h"):
with io.open (h, encoding='utf-8') as f: headers_content.append (f.read ())
-result = """EXPORTS
+symbols = "\n".join (sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re.M)))
+
+result = symbols if os.environ.get('PLAIN_LIST', '') else """EXPORTS
%s
-LIBRARY lib%s-0.dll""" % (
- "\n".join (sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re.M))),
- output_file.replace ('.def', '')
-)
+LIBRARY lib%s-0.dll""" % (symbols, output_file.replace ('.def', ''))
with open (output_file, "w") as f: f.write (result)
diff --git a/src/gen-vowel-constraints.py b/src/gen-vowel-constraints.py
index 02a338fa5..c4e75aa96 100755
--- a/src/gen-vowel-constraints.py
+++ b/src/gen-vowel-constraints.py
@@ -176,9 +176,9 @@ print ('}')
print ()
print ('void')
-print ('_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan,')
+print ('_hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,')
print ('\t\t\t\t hb_buffer_t *buffer,')
-print ('\t\t\t\t hb_font_t *font)')
+print ('\t\t\t\t hb_font_t *font HB_UNUSED)')
print ('{')
print (' /* UGLY UGLY UGLY business of adding dotted-circle in the middle of')
print (' * vowel-sequences that look like another vowel. Data for each script')
diff --git a/src/hb-aat-layout-common.hh b/src/hb-aat-layout-common.hh
index a99ccaf9f..51add2213 100644
--- a/src/hb-aat-layout-common.hh
+++ b/src/hb-aat-layout-common.hh
@@ -362,6 +362,7 @@ template <>
}
namespace AAT {
+enum { DELETED_GLYPH = 0xFFFF };
/*
* Extended State Table
@@ -376,7 +377,10 @@ struct Entry
/* Note, we don't recurse-sanitize data because we don't access it.
* That said, in our DEFINE_SIZE_STATIC we access T::static_size,
* which ensures that data has a simple sanitize(). To be determined
- * if I need to remove that as well. */
+ * if I need to remove that as well.
+ *
+ * XXX Because we are a template, our DEFINE_SIZE_STATIC assertion
+ * wouldn't be checked. */
return_trace (c->check_struct (this));
}
@@ -393,7 +397,7 @@ struct Entry
template <>
struct Entry
{
- inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
+ inline bool sanitize (hb_sanitize_context_t *c, unsigned int count /*XXX Unused?*/) const
{
TRACE_SANITIZE (this);
return_trace (c->check_struct (this));
@@ -406,9 +410,13 @@ struct Entry
DEFINE_SIZE_STATIC (4);
};
-template
+template
struct StateTable
{
+ typedef typename Types::HBUINT HBUINT;
+ typedef typename Types::HBUSHORT HBUSHORT;
+ typedef typename Types::ClassType ClassType;
+
enum State
{
STATE_START_OF_TEXT = 0,
@@ -422,10 +430,13 @@ struct StateTable
CLASS_END_OF_LINE = 3,
};
+ inline unsigned int new_state (unsigned int newState) const
+ { return Types::extended ? newState : (newState - stateArrayTable) / nClasses; }
+
inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
{
- const HBUINT16 *v = (this+classTable).get_value (glyph_id, num_glyphs);
- return v ? (unsigned) *v : (unsigned) CLASS_OUT_OF_BOUNDS;
+ if (unlikely (glyph_id == DELETED_GLYPH)) return CLASS_DELETED_GLYPH;
+ return (this+classTable).get_class (glyph_id, num_glyphs);
}
inline const Entry *get_entries () const
@@ -437,7 +448,7 @@ struct StateTable
{
if (unlikely (klass >= nClasses)) return nullptr;
- const HBUINT16 *states = (this+stateArrayTable).arrayZ;
+ const HBUSHORT *states = (this+stateArrayTable).arrayZ;
const Entry *entries = (this+entryTable).arrayZ;
unsigned int entry = states[state * nClasses + klass];
@@ -452,7 +463,7 @@ struct StateTable
if (unlikely (!(c->check_struct (this) &&
classTable.sanitize (c, this)))) return_trace (false);
- const HBUINT16 *states = (this+stateArrayTable).arrayZ;
+ const HBUSHORT *states = (this+stateArrayTable).arrayZ;
const Entry *entries = (this+entryTable).arrayZ;
unsigned int num_classes = nClasses;
@@ -474,8 +485,8 @@ struct StateTable
if ((c->max_ops -= num_states - state) < 0)
return_trace (false);
{ /* Sweep new states. */
- const HBUINT16 *stop = &states[num_states * num_classes];
- for (const HBUINT16 *p = &states[state * num_classes]; p < stop; p++)
+ const HBUSHORT *stop = &states[num_states * num_classes];
+ for (const HBUSHORT *p = &states[state * num_classes]; p < stop; p++)
num_entries = MAX (num_entries, *p + 1);
state = num_states;
}
@@ -487,7 +498,10 @@ struct StateTable
{ /* Sweep new entries. */
const Entry *stop = &entries[num_entries];
for (const Entry *p = &entries[entry]; p < stop; p++)
- num_states = MAX (num_states, p->newState + 1);
+ {
+ unsigned int newState = new_state (p->newState);
+ num_states = MAX (num_states, newState + 1);
+ }
entry = num_entries;
}
}
@@ -499,23 +513,101 @@ struct StateTable
}
protected:
- HBUINT32 nClasses; /* Number of classes, which is the number of indices
+ HBUINT nClasses; /* Number of classes, which is the number of indices
* in a single line in the state array. */
- LOffsetTo, false>
+ OffsetTo
classTable; /* Offset to the class table. */
- LOffsetTo, false>
+ OffsetTo, HBUINT, false>
stateArrayTable;/* Offset to the state array. */
- LOffsetTo >, false>
+ OffsetTo >, HBUINT, false>
entryTable; /* Offset to the entry array. */
public:
- DEFINE_SIZE_STATIC (16);
+ DEFINE_SIZE_STATIC (4 * sizeof (HBUINT));
};
-template
+struct ClassTable
+{
+ inline unsigned int get_class (hb_codepoint_t glyph_id) const
+ {
+ return firstGlyph <= glyph_id && glyph_id - firstGlyph < glyphCount ? classArrayZ[glyph_id - firstGlyph] : 1;
+ }
+ inline bool sanitize (hb_sanitize_context_t *c) const
+ {
+ TRACE_SANITIZE (this);
+ return_trace (c->check_struct (this) && classArrayZ.sanitize (c, glyphCount));
+ }
+ protected:
+ GlyphID firstGlyph; /* First glyph index included in the trimmed array. */
+ HBUINT16 glyphCount; /* Total number of glyphs (equivalent to the last
+ * glyph minus the value of firstGlyph plus 1). */
+ UnsizedArrayOf
+ classArrayZ; /* The class codes (indexed by glyph index minus
+ * firstGlyph). */
+ public:
+ DEFINE_SIZE_ARRAY (4, classArrayZ);
+};
+
+struct MortTypes
+{
+ 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) const
+ {
+ return ClassTable::get_class (glyph_id);
+ }
+ };
+ template
+ static inline unsigned int offsetToIndex (unsigned int offset,
+ const void *base,
+ const T *array)
+ {
+ return (offset - ((const char *) array - (const char *) base)) / sizeof (T);
+ }
+ template
+ static inline unsigned int wordOffsetToIndex (unsigned int offset,
+ const void *base,
+ const T *array)
+ {
+ return offsetToIndex (2 * offset, base, array);
+ }
+};
+struct MorxTypes
+{
+ static const bool extended = true;
+ typedef HBUINT32 HBUINT;
+ typedef HBUINT16 HBUSHORT;
+ struct ClassType : Lookup
+ {
+ inline unsigned int get_class (hb_codepoint_t glyph_id, unsigned int num_glyphs) const
+ {
+ const HBUINT16 *v = get_value (glyph_id, num_glyphs);
+ return v ? *v : 1;
+ }
+ };
+ template
+ static inline unsigned int offsetToIndex (unsigned int offset,
+ const void *base,
+ const T *array)
+ {
+ return offset;
+ }
+ template
+ static inline unsigned int wordOffsetToIndex (unsigned int offset,
+ const void *base,
+ const T *array)
+ {
+ return offset;
+ }
+};
+
+template
struct StateTableDriver
{
- inline StateTableDriver (const StateTable &machine_,
+ inline StateTableDriver (const StateTable &machine_,
hb_buffer_t *buffer_,
hb_face_t *face_) :
machine (machine_),
@@ -528,13 +620,13 @@ struct StateTableDriver
if (!c->in_place)
buffer->clear_output ();
- unsigned int state = StateTable::STATE_START_OF_TEXT;
+ unsigned int state = StateTable::STATE_START_OF_TEXT;
bool last_was_dont_advance = false;
- for (buffer->idx = 0;;)
+ for (buffer->idx = 0; buffer->successful;)
{
unsigned int klass = buffer->idx < buffer->len ?
machine.get_class (buffer->info[buffer->idx].codepoint, num_glyphs) :
- (unsigned) StateTable::CLASS_END_OF_TEXT;
+ (unsigned) StateTable::CLASS_END_OF_TEXT;
const Entry *entry = machine.get_entryZ (state, klass);
if (unlikely (!entry))
break;
@@ -548,7 +640,7 @@ struct StateTableDriver
/* If there's no action and we're just epsilon-transitioning to state 0,
* safe to break. */
if (c->is_actionable (this, entry) ||
- !(entry->newState == StateTable::STATE_START_OF_TEXT &&
+ !(entry->newState == StateTable::STATE_START_OF_TEXT &&
entry->flags == context_t::DontAdvance))
buffer->unsafe_to_break_from_outbuffer (buffer->backtrack_len () - 1, buffer->idx + 1);
}
@@ -562,19 +654,17 @@ struct StateTableDriver
}
if (unlikely (!c->transition (this, entry)))
- break;
-
- if (unlikely (!buffer->successful)) return;
+ break;
last_was_dont_advance = (entry->flags & context_t::DontAdvance) && buffer->max_ops-- > 0;
- state = entry->newState;
+ state = machine.new_state (entry->newState);
if (buffer->idx == buffer->len)
- break;
+ break;
if (!last_was_dont_advance)
- buffer->next_glyph ();
+ buffer->next_glyph ();
}
if (!c->in_place)
@@ -587,7 +677,7 @@ struct StateTableDriver
}
public:
- const StateTable &machine;
+ const StateTable &machine;
hb_buffer_t *buffer;
unsigned int num_glyphs;
};
diff --git a/src/hb-aat-layout-kerx-table.hh b/src/hb-aat-layout-kerx-table.hh
index 960c37e11..94e0a9b62 100644
--- a/src/hb-aat-layout-kerx-table.hh
+++ b/src/hb-aat-layout-kerx-table.hh
@@ -163,12 +163,12 @@ struct KerxSubTableFormat1
kernAction (&table->machine + table->kernAction),
depth (0) {}
- inline bool is_actionable (StateTableDriver *driver,
+ inline bool is_actionable (StateTableDriver *driver HB_UNUSED,
const Entry *entry)
{
return entry->data.kernActionIndex != 0xFFFF;
}
- inline bool transition (StateTableDriver *driver,
+ inline bool transition (StateTableDriver *driver,
const Entry *entry)
{
hb_buffer_t *buffer = driver->buffer;
@@ -239,7 +239,7 @@ struct KerxSubTableFormat1
driver_context_t dc (this, c);
- StateTableDriver driver (machine, c->buffer, c->font->face);
+ StateTableDriver driver (machine, c->buffer, c->font->face);
driver.drive (&dc);
return_trace (true);
@@ -255,7 +255,7 @@ struct KerxSubTableFormat1
protected:
KerxSubTableHeader header;
- StateTable machine;
+ StateTable machine;
LOffsetTo, false> kernAction;
public:
DEFINE_SIZE_STATIC (32);
@@ -365,12 +365,12 @@ struct KerxSubTableFormat4
mark_set (false),
mark (0) {}
- inline bool is_actionable (StateTableDriver *driver,
+ inline bool is_actionable (StateTableDriver *driver HB_UNUSED,
const Entry *entry)
{
return entry->data.ankrActionIndex != 0xFFFF;
}
- inline bool transition (StateTableDriver *driver,
+ inline bool transition (StateTableDriver *driver,
const Entry *entry)
{
hb_buffer_t *buffer = driver->buffer;
@@ -473,7 +473,7 @@ struct KerxSubTableFormat4
driver_context_t dc (this, c);
- StateTableDriver driver (machine, c->buffer, c->font->face);
+ StateTableDriver driver (machine, c->buffer, c->font->face);
driver.drive (&dc);
return_trace (true);
@@ -489,7 +489,8 @@ struct KerxSubTableFormat4
protected:
KerxSubTableHeader header;
- StateTable machine;
+ StateTable
+ machine;
HBUINT32 flags;
public:
DEFINE_SIZE_STATIC (32);
diff --git a/src/hb-aat-layout-morx-table.hh b/src/hb-aat-layout-morx-table.hh
index c663fcc84..d56af7bfe 100644
--- a/src/hb-aat-layout-morx-table.hh
+++ b/src/hb-aat-layout-morx-table.hh
@@ -35,17 +35,21 @@
/*
* morx -- Extended Glyph Metamorphosis
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6morx.html
+ * https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6mort.html
*/
#define HB_AAT_TAG_morx HB_TAG('m','o','r','x')
+#define HB_AAT_TAG_mort HB_TAG('m','o','r','t')
namespace AAT {
using namespace OT;
-
+template
struct RearrangementSubtable
{
+ typedef typename Types::HBUINT HBUINT;
+
typedef void EntryData;
struct driver_context_t
@@ -65,16 +69,16 @@ struct RearrangementSubtable
Verb = 0x000F, /* The type of rearrangement specified. */
};
- inline driver_context_t (const RearrangementSubtable *table) :
+ inline driver_context_t (const RearrangementSubtable *table HB_UNUSED) :
ret (false),
start (0), end (0) {}
- inline bool is_actionable (StateTableDriver *driver,
+ inline bool is_actionable (StateTableDriver *driver HB_UNUSED,
const Entry *entry)
{
return (entry->flags & Verb) && start < end;
}
- inline bool transition (StateTableDriver *driver,
+ inline bool transition (StateTableDriver *driver,
const Entry *entry)
{
hb_buffer_t *buffer = driver->buffer;
@@ -165,7 +169,7 @@ struct RearrangementSubtable
driver_context_t dc (this);
- StateTableDriver driver (machine, c->buffer, c->face);
+ StateTableDriver driver (machine, c->buffer, c->face);
driver.drive (&dc);
return_trace (dc.ret);
@@ -178,13 +182,16 @@ struct RearrangementSubtable
}
protected:
- StateTable machine;
+ StateTable machine;
public:
DEFINE_SIZE_STATIC (16);
};
+template
struct ContextualSubtable
{
+ typedef typename Types::HBUINT HBUINT;
+
struct EntryData
{
HBUINT16 markIndex; /* Index of the substitution table for the
@@ -206,13 +213,16 @@ struct ContextualSubtable
Reserved = 0x3FFF, /* These bits are reserved and should be set to 0. */
};
- inline driver_context_t (const ContextualSubtable *table) :
+ inline driver_context_t (const ContextualSubtable *table_,
+ hb_aat_apply_context_t *c_) :
ret (false),
+ c (c_),
mark_set (false),
mark (0),
+ table (table_),
subs (table+table->substitutionTables) {}
- inline bool is_actionable (StateTableDriver *driver,
+ inline bool is_actionable (StateTableDriver *driver,
const Entry *entry)
{
hb_buffer_t *buffer = driver->buffer;
@@ -222,7 +232,7 @@ struct ContextualSubtable
return entry->data.markIndex != 0xFFFF || entry->data.currentIndex != 0xFFFF;
}
- inline bool transition (StateTableDriver *driver,
+ inline bool transition (StateTableDriver *driver,
const Entry *entry)
{
hb_buffer_t *buffer = driver->buffer;
@@ -232,30 +242,55 @@ struct ContextualSubtable
if (buffer->idx == buffer->len && !mark_set)
return true;
- if (entry->data.markIndex != 0xFFFF)
+ const GlyphID *replacement;
+
+ replacement = nullptr;
+ if (Types::extended)
{
- const Lookup &lookup = subs[entry->data.markIndex];
- hb_glyph_info_t *info = buffer->info;
- const GlyphID *replacement = lookup.get_value (info[mark].codepoint, driver->num_glyphs);
- if (replacement)
+ if (entry->data.markIndex != 0xFFFF)
{
- buffer->unsafe_to_break (mark, MIN (buffer->idx + 1, buffer->len));
- info[mark].codepoint = *replacement;
- ret = true;
+ const Lookup &lookup = subs[entry->data.markIndex];
+ replacement = lookup.get_value (buffer->info[mark].codepoint, driver->num_glyphs);
}
}
- if (entry->data.currentIndex != 0xFFFF)
+ else
{
- unsigned int idx = MIN (buffer->idx, buffer->len - 1);
- const Lookup &lookup = subs[entry->data.currentIndex];
- hb_glyph_info_t *info = buffer->info;
- const GlyphID *replacement = lookup.get_value (info[idx].codepoint, driver->num_glyphs);
- if (replacement)
+ unsigned int offset = entry->data.markIndex + buffer->info[mark].codepoint;
+ const UnsizedArrayOf &subs_old = (const UnsizedArrayOf &) subs;
+ replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
+ if (!replacement->sanitize (&c->sanitizer) || !*replacement)
+ replacement = nullptr;
+ }
+ if (replacement)
+ {
+ buffer->unsafe_to_break (mark, MIN (buffer->idx + 1, buffer->len));
+ buffer->info[mark].codepoint = *replacement;
+ ret = true;
+ }
+
+ replacement = nullptr;
+ unsigned int idx = MIN (buffer->idx, buffer->len - 1);
+ if (Types::extended)
+ {
+ if (entry->data.currentIndex != 0xFFFF)
{
- info[idx].codepoint = *replacement;
- ret = true;
+ const Lookup &lookup = subs[entry->data.currentIndex];
+ replacement = lookup.get_value (buffer->info[idx].codepoint, driver->num_glyphs);
}
}
+ else
+ {
+ unsigned int offset = entry->data.currentIndex + buffer->info[idx].codepoint;
+ const UnsizedArrayOf &subs_old = (const UnsizedArrayOf &) subs;
+ replacement = &subs_old[Types::wordOffsetToIndex (offset, table, subs_old.arrayZ)];
+ if (!replacement->sanitize (&c->sanitizer) || !*replacement)
+ replacement = nullptr;
+ }
+ if (replacement)
+ {
+ buffer->info[idx].codepoint = *replacement;
+ ret = true;
+ }
if (entry->flags & SetMark)
{
@@ -269,18 +304,20 @@ struct ContextualSubtable
public:
bool ret;
private:
+ hb_aat_apply_context_t *c;
bool mark_set;
unsigned int mark;
- const UnsizedOffsetListOf, HBUINT32, false> &subs;
+ const ContextualSubtable *table;
+ const UnsizedOffsetListOf, HBUINT, false> &subs;
};
inline bool apply (hb_aat_apply_context_t *c) const
{
TRACE_APPLY (this);
- driver_context_t dc (this);
+ driver_context_t dc (this, c);
- StateTableDriver driver (machine, c->buffer, c->face);
+ StateTableDriver driver (machine, c->buffer, c->face);
driver.drive (&dc);
return_trace (dc.ret);
@@ -293,6 +330,8 @@ struct ContextualSubtable
unsigned int num_entries = 0;
if (unlikely (!machine.sanitize (c, &num_entries))) return_trace (false);
+ if (!Types::extended) return_trace (true);
+
unsigned int num_lookups = 0;
const Entry *entries = machine.get_entries ();
@@ -310,38 +349,90 @@ struct ContextualSubtable
}
protected:
- StateTable
+ StateTable
machine;
- LOffsetTo, HBUINT32, false>, false>
+ OffsetTo, HBUINT, false>, HBUINT, false>
substitutionTables;
public:
DEFINE_SIZE_STATIC (20);
};
-struct LigatureSubtable
+
+template
+struct LigatureEntry;
+
+template <>
+struct LigatureEntry
{
- struct EntryData
+ enum Flags
+ {
+ SetComponent = 0x8000, /* Push this glyph onto the component stack for
+ * eventual processing. */
+ DontAdvance = 0x4000, /* Leave the glyph pointer at this glyph for the
+ next iteration. */
+ PerformAction = 0x2000, /* Use the ligActionIndex to process a ligature
+ * group. */
+ Reserved = 0x1FFF, /* These bits are reserved and should be set to 0. */
+ };
+
+ typedef struct
{
HBUINT16 ligActionIndex; /* Index to the first ligActionTable entry
* for processing this group, if indicated
* by the flags. */
public:
DEFINE_SIZE_STATIC (2);
+ } EntryData;
+
+ template
+ static inline bool performAction (Flags flags)
+ { return flags & PerformAction; }
+
+ template
+ static inline unsigned int ligActionIndex (Entry &entry, Flags flags)
+ { return entry->data.ligActionIndex; }
+};
+template <>
+struct LigatureEntry
+{
+ enum Flags
+ {
+ SetComponent = 0x8000, /* Push this glyph onto the component stack for
+ * eventual processing. */
+ DontAdvance = 0x4000, /* Leave the glyph pointer at this glyph for the
+ next iteration. */
+ Offset = 0x3FFF, /* Byte offset from beginning of subtable to the
+ * ligature action list. This value must be a
+ * multiple of 4. */
};
+ typedef void EntryData;
+
+ template
+ static inline bool performAction (Flags flags)
+ { return flags & Offset; }
+
+ template
+ static inline unsigned int ligActionIndex (Entry &entry, Flags flags)
+ { return flags & 0x3FFF; }
+};
+
+
+template
+struct LigatureSubtable
+{
+ typedef typename Types::HBUINT HBUINT;
+
+ typedef LigatureEntry LigatureEntryT;
+ typedef typename LigatureEntryT::EntryData EntryData;
+
struct driver_context_t
{
- static const bool in_place = false;
- enum Flags
+ enum
{
- SetComponent = 0x8000, /* Push this glyph onto the component stack for
- * eventual processing. */
- DontAdvance = 0x4000, /* Leave the glyph pointer at this glyph for the
- next iteration. */
- PerformAction = 0x2000, /* Use the ligActionIndex to process a ligature
- * group. */
- Reserved = 0x1FFF, /* These bits are reserved and should be set to 0. */
+ DontAdvance = LigatureEntryT::DontAdvance,
};
+ static const bool in_place = false;
enum LigActionFlags
{
LigActionLast = 0x80000000, /* This is the last action in the list. This also
@@ -354,28 +445,29 @@ struct LigatureSubtable
* into the component table. */
};
- inline driver_context_t (const LigatureSubtable *table,
+ inline driver_context_t (const LigatureSubtable *table_,
hb_aat_apply_context_t *c_) :
ret (false),
c (c_),
+ table (table_),
ligAction (table+table->ligAction),
component (table+table->component),
ligature (table+table->ligature),
match_length (0) {}
- inline bool is_actionable (StateTableDriver *driver,
+ inline bool is_actionable (StateTableDriver *driver HB_UNUSED,
const Entry *entry)
{
- return entry->flags & PerformAction;
+ return LigatureEntryT::performAction (entry->flags);
}
- inline bool transition (StateTableDriver *driver,
+ inline bool transition (StateTableDriver *driver,
const Entry *entry)
{
hb_buffer_t *buffer = driver->buffer;
unsigned int flags = entry->flags;
DEBUG_MSG (APPLY, nullptr, "Ligature transition at %d", buffer->idx);
- if (flags & SetComponent)
+ if (flags & LigatureEntryT::SetComponent)
{
if (unlikely (match_length >= ARRAY_LENGTH (match_positions)))
return false;
@@ -388,18 +480,23 @@ struct LigatureSubtable
DEBUG_MSG (APPLY, nullptr, "Set component at %d", buffer->out_len);
}
- if (flags & PerformAction)
+ if (LigatureEntryT::performAction (flags))
{
DEBUG_MSG (APPLY, nullptr, "Perform action with %d", match_length);
unsigned int end = buffer->out_len;
- unsigned int action_idx = entry->data.ligActionIndex;
+ unsigned int action_idx = LigatureEntryT::ligActionIndex (entry, flags);
unsigned int action;
unsigned int ligature_idx = 0;
if (unlikely (!match_length))
return true;
+ if (buffer->idx >= buffer->len)
+ return false; // TODO Work on previous instead?
+
unsigned int cursor = match_length;
+ action_idx = Types::offsetToIndex (action_idx, table, ligAction.arrayZ);
+ const HBUINT32 *actionData = &ligAction[action_idx];
do
{
if (unlikely (!cursor))
@@ -413,18 +510,15 @@ struct LigatureSubtable
DEBUG_MSG (APPLY, nullptr, "Moving to stack position %d", cursor - 1);
buffer->move_to (match_positions[--cursor]);
- const HBUINT32 &actionData = ligAction[action_idx];
- if (unlikely (!actionData.sanitize (&c->sanitizer))) return false;
- action = actionData;
+ if (unlikely (!actionData->sanitize (&c->sanitizer))) return false;
+ action = *actionData;
uint32_t uoffset = action & LigActionOffset;
if (uoffset & 0x20000000)
uoffset |= 0xC0000000; /* Sign-extend. */
int32_t offset = (int32_t) uoffset;
- if (buffer->idx >= buffer->len)
- return false; // TODO Work on previous instead?
unsigned int component_idx = buffer->cur().codepoint + offset;
-
+ component_idx = Types::wordOffsetToIndex (component_idx, table, component.arrayZ);
const HBUINT16 &componentData = component[component_idx];
if (unlikely (!componentData.sanitize (&c->sanitizer))) return false;
ligature_idx += componentData;
@@ -434,7 +528,7 @@ struct LigatureSubtable
bool (action & LigActionLast));
if (action & (LigActionStore | LigActionLast))
{
-
+ ligature_idx = Types::offsetToIndex (ligature_idx, table, ligature.arrayZ);
const GlyphID &ligatureData = ligature[ligature_idx];
if (unlikely (!ligatureData.sanitize (&c->sanitizer))) return false;
hb_codepoint_t lig = ligatureData;
@@ -442,20 +536,20 @@ struct LigatureSubtable
DEBUG_MSG (APPLY, nullptr, "Produced ligature %d", lig);
buffer->replace_glyph (lig);
+ unsigned int lig_end = match_positions[match_length - 1] + 1;
/* Now go and delete all subsequent components. */
while (match_length - 1 > cursor)
{
DEBUG_MSG (APPLY, nullptr, "Skipping ligature component");
buffer->move_to (match_positions[--match_length]);
- buffer->skip_glyph ();
- end--;
+ buffer->replace_glyph (DELETED_GLYPH);
}
- buffer->move_to (end + 1);
+ buffer->move_to (lig_end);
buffer->merge_out_clusters (match_positions[cursor], buffer->out_len);
}
- action_idx++;
+ actionData++;
}
while (!(action & LigActionLast));
buffer->move_to (end);
@@ -468,6 +562,7 @@ struct LigatureSubtable
bool ret;
private:
hb_aat_apply_context_t *c;
+ const LigatureSubtable *table;
const UnsizedArrayOf &ligAction;
const UnsizedArrayOf &component;
const UnsizedArrayOf &ligature;
@@ -481,7 +576,7 @@ struct LigatureSubtable
driver_context_t dc (this, c);
- StateTableDriver driver (machine, c->buffer, c->face);
+ StateTableDriver driver (machine, c->buffer, c->face);
driver.drive (&dc);
return_trace (dc.ret);
@@ -496,18 +591,19 @@ struct LigatureSubtable
}
protected:
- StateTable
+ StateTable
machine;
- LOffsetTo, false>
+ OffsetTo, HBUINT, false>
ligAction; /* Offset to the ligature action table. */
- LOffsetTo, false>
+ OffsetTo, HBUINT, false>
component; /* Offset to the component table. */
- LOffsetTo, false>
+ OffsetTo, HBUINT, false>
ligature; /* Offset to the actual ligature lists. */
public:
DEFINE_SIZE_STATIC (28);
};
+template
struct NoncontextualSubtable
{
inline bool apply (hb_aat_apply_context_t *c) const
@@ -544,8 +640,11 @@ struct NoncontextualSubtable
DEFINE_SIZE_MIN (2);
};
+template
struct InsertionSubtable
{
+ typedef typename Types::HBUINT HBUINT;
+
struct EntryData
{
HBUINT16 currentInsertIndex; /* Zero-based index into the insertion glyph table.
@@ -621,13 +720,13 @@ struct InsertionSubtable
mark (0),
insertionAction (table+table->insertionAction) {}
- inline bool is_actionable (StateTableDriver *driver,
+ inline bool is_actionable (StateTableDriver *driver HB_UNUSED,
const Entry *entry)
{
return (entry->flags & (CurrentInsertCount | MarkedInsertCount)) &&
(entry->data.currentInsertIndex != 0xFFFF ||entry->data.markedInsertIndex != 0xFFFF);
}
- inline bool transition (StateTableDriver *driver,
+ inline bool transition (StateTableDriver *driver,
const Entry *entry)
{
hb_buffer_t *buffer = driver->buffer;
@@ -719,7 +818,7 @@ struct InsertionSubtable
driver_context_t dc (this, c);
- StateTableDriver driver (machine, c->buffer, c->face);
+ StateTableDriver driver (machine, c->buffer, c->face);
driver.drive (&dc);
return_trace (dc.ret);
@@ -734,9 +833,9 @@ struct InsertionSubtable
}
protected:
- StateTable
+ StateTable
machine;
- LOffsetTo, false>
+ OffsetTo, HBUINT, false>
insertionAction; /* Byte offset from stateHeader to the start of
* the insertion glyph table. */
public:
@@ -764,30 +863,32 @@ struct Feature
DEFINE_SIZE_STATIC (12);
};
-
+template
struct ChainSubtable
{
+ typedef typename Types::HBUINT HBUINT;
+
+ template
friend struct Chain;
inline unsigned int get_size (void) const { return length; }
- inline unsigned int get_type (void) const { return coverage & SubtableType; }
+ inline unsigned int get_type (void) const { return coverage & 0xFF; }
+ inline unsigned int get_coverage (void) const { return coverage >> (sizeof (HBUINT) * 8 - 8); }
enum Coverage
{
- Vertical = 0x80000000, /* If set, this subtable will only be applied
- * to vertical text. If clear, this subtable
- * will only be applied to horizontal text. */
- Backwards = 0x40000000, /* If set, this subtable will process glyphs
- * in descending order. If clear, it will
- * process the glyphs in ascending order. */
- AllDirections = 0x20000000, /* If set, this subtable will be applied to
- * both horizontal and vertical text (i.e.
- * the state of bit 0x80000000 is ignored). */
- Logical = 0x10000000, /* If set, this subtable will process glyphs
- * in logical order (or reverse logical order,
- * depending on the value of bit 0x80000000). */
- Reserved = 0x0FFFFF00, /* Reserved, set to zero. */
- SubtableType = 0x000000FF, /* Subtable type; see following table. */
+ Vertical = 0x80, /* If set, this subtable will only be applied
+ * to vertical text. If clear, this subtable
+ * will only be applied to horizontal text. */
+ Backwards = 0x40, /* If set, this subtable will process glyphs
+ * in descending order. If clear, it will
+ * process the glyphs in ascending order. */
+ AllDirections = 0x20, /* If set, this subtable will be applied to
+ * both horizontal and vertical text (i.e.
+ * the state of bit 0x80000000 is ignored). */
+ Logical = 0x10, /* If set, this subtable will process glyphs
+ * in logical order (or reverse logical order,
+ * depending on the value of bit 0x80000000). */
};
enum Type
{
@@ -825,40 +926,49 @@ struct ChainSubtable
}
protected:
- HBUINT32 length; /* Total subtable length, including this header. */
- HBUINT32 coverage; /* Coverage flags and subtable type. */
+ HBUINT length; /* Total subtable length, including this header. */
+ HBUINT coverage; /* Coverage flags and subtable type. */
HBUINT32 subFeatureFlags;/* The 32-bit mask identifying which subtable this is. */
union {
- RearrangementSubtable rearrangement;
- ContextualSubtable contextual;
- LigatureSubtable ligature;
- NoncontextualSubtable noncontextual;
- InsertionSubtable insertion;
+ RearrangementSubtable rearrangement;
+ ContextualSubtable contextual;
+ LigatureSubtable ligature;
+ NoncontextualSubtable noncontextual;
+ InsertionSubtable insertion;
} u;
public:
- DEFINE_SIZE_MIN (12);
+ DEFINE_SIZE_MIN (2 * sizeof (HBUINT) + 4);
};
+template
struct Chain
{
+ typedef typename Types::HBUINT HBUINT;
+
inline hb_mask_t compile_flags (const hb_aat_map_builder_t *map) const
{
hb_mask_t flags = defaultFlags;
{
- /* Compute applicable flags. TODO Should move this to planning
- * stage and take user-requested features into account. */
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;
+ retry:
const hb_aat_map_builder_t::feature_info_t *info = map->features.bsearch (type);
if (info && info->setting == setting)
{
flags &= feature.disableFlags;
flags |= feature.enableFlags;
}
+ else if (type == 3/*kLetterCaseType*/ && setting == 3/*kSmallCapsSelector*/)
+ {
+ /* Deprecated. https://github.com/harfbuzz/harfbuzz/issues/1342 */
+ type = 37/*kLowerCaseType*/;
+ setting = 1/*kLowerCaseSmallCapsSelector*/;
+ goto retry;
+ }
}
}
return flags;
@@ -867,7 +977,7 @@ struct Chain
inline void apply (hb_aat_apply_context_t *c,
hb_mask_t flags) const
{
- const ChainSubtable *subtable = &StructAtOffset (&featureZ, featureZ[0].static_size * featureCount);
+ const ChainSubtable *subtable = &StructAtOffset > (&featureZ, featureZ[0].static_size * featureCount);
unsigned int count = subtableCount;
for (unsigned int i = 0; i < count; i++)
{
@@ -876,9 +986,9 @@ struct Chain
if (!(subtable->subFeatureFlags & flags))
goto skip;
- if (!(subtable->coverage & ChainSubtable::AllDirections) &&
+ if (!(subtable->get_coverage() & ChainSubtable::AllDirections) &&
HB_DIRECTION_IS_VERTICAL (c->buffer->props.direction) !=
- bool (subtable->coverage & ChainSubtable::Vertical))
+ bool (subtable->get_coverage() & ChainSubtable::Vertical))
goto skip;
/* Buffer contents is always in logical direction. Determine if
@@ -908,9 +1018,9 @@ struct Chain
(the order opposite that of the characters, which
may be right-to-left or left-to-right).
*/
- reverse = subtable->coverage & ChainSubtable::Logical ?
- bool (subtable->coverage & ChainSubtable::Backwards) :
- bool (subtable->coverage & ChainSubtable::Backwards) !=
+ reverse = subtable->get_coverage () & ChainSubtable::Logical ?
+ bool (subtable->get_coverage () & ChainSubtable::Backwards) :
+ bool (subtable->get_coverage () & ChainSubtable::Backwards) !=
HB_DIRECTION_IS_BACKWARD (c->buffer->props.direction);
if (!c->buffer->message (c->font, "start chain subtable %d", c->lookup_index))
@@ -931,14 +1041,14 @@ struct Chain
if (unlikely (!c->buffer->successful)) return;
skip:
- subtable = &StructAfter (*subtable);
+ subtable = &StructAfter > (*subtable);
c->set_lookup_index (c->lookup_index + 1);
}
}
inline unsigned int get_size (void) const { return length; }
- inline bool sanitize (hb_sanitize_context_t *c, unsigned int version) const
+ inline bool sanitize (hb_sanitize_context_t *c, unsigned int version HB_UNUSED) const
{
TRACE_SANITIZE (this);
if (!length.sanitize (c) ||
@@ -949,13 +1059,13 @@ struct Chain
if (!c->check_array (featureZ.arrayZ, featureCount))
return_trace (false);
- const ChainSubtable *subtable = &StructAtOffset (&featureZ, featureZ[0].static_size * featureCount);
+ const ChainSubtable *subtable = &StructAtOffset > (&featureZ, featureZ[0].static_size * featureCount);
unsigned int count = subtableCount;
for (unsigned int i = 0; i < count; i++)
{
if (!subtable->sanitize (c))
return_trace (false);
- subtable = &StructAfter (*subtable);
+ subtable = &StructAfter > (*subtable);
}
return_trace (true);
@@ -964,23 +1074,24 @@ struct Chain
protected:
HBUINT32 defaultFlags; /* The default specification for subtables. */
HBUINT32 length; /* Total byte count, including this header. */
- HBUINT32 featureCount; /* Number of feature subtable entries. */
- HBUINT32 subtableCount; /* The number of subtables in the chain. */
+ HBUINT featureCount; /* Number of feature subtable entries. */
+ HBUINT subtableCount; /* The number of subtables in the chain. */
UnsizedArrayOf featureZ; /* Features. */
/*ChainSubtable firstSubtable;*//* Subtables. */
/*subtableGlyphCoverageArray*/ /* Only if version >= 3. We don't use. */
public:
- DEFINE_SIZE_MIN (16);
+ DEFINE_SIZE_MIN (8 + 2 * sizeof (HBUINT));
};
/*
- * The 'morx' Table
+ * The 'mort'/'morx' Table
*/
-struct morx
+template
+struct mortmorx
{
static const hb_tag_t tableTag = HB_AAT_TAG_morx;
@@ -989,43 +1100,59 @@ struct morx
inline void compile_flags (const hb_aat_map_builder_t *mapper,
hb_aat_map_t *map) const
{
- const Chain *chain = &firstChain;
+ const Chain *chain = &firstChain;
unsigned int count = chainCount;
for (unsigned int i = 0; i < count; i++)
{
map->chain_flags.push (chain->compile_flags (mapper));
- chain = &StructAfter (*chain);
+ chain = &StructAfter > (*chain);
}
}
+ inline static void remove_deleted_glyphs (hb_buffer_t *buffer)
+ {
+ if (unlikely (!buffer->successful)) return;
+
+ buffer->clear_output ();
+ for (buffer->idx = 0; buffer->idx < buffer->len && buffer->successful;)
+ {
+ if (unlikely (buffer->cur().codepoint == DELETED_GLYPH))
+ buffer->skip_glyph ();
+ else
+ buffer->next_glyph ();
+ }
+ if (likely (buffer->successful))
+ buffer->swap_buffers ();
+ }
+
inline void apply (hb_aat_apply_context_t *c) const
{
if (unlikely (!c->buffer->successful)) return;
c->set_lookup_index (0);
- const Chain *chain = &firstChain;
+ const Chain *chain = &firstChain;
unsigned int count = chainCount;
for (unsigned int i = 0; i < count; i++)
{
chain->apply (c, c->plan->aat_map.chain_flags[i]);
if (unlikely (!c->buffer->successful)) return;
- chain = &StructAfter (*chain);
+ chain = &StructAfter > (*chain);
}
+ remove_deleted_glyphs (c->buffer);
}
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- if (!version.sanitize (c) || version < 2 ||
- !chainCount.sanitize (c))
+ if (!version.sanitize (c) || !version || !chainCount.sanitize (c))
return_trace (false);
- const Chain *chain = &firstChain;
+ const Chain *chain = &firstChain;
unsigned int count = chainCount;
for (unsigned int i = 0; i < count; i++)
{
if (!chain->sanitize (c, version))
return_trace (false);
- chain = &StructAfter (*chain);
+ chain = &StructAfter > (*chain);
}
return_trace (true);
@@ -1033,16 +1160,26 @@ struct morx
protected:
HBUINT16 version; /* Version number of the glyph metamorphosis table.
- * 2 or 3. */
+ * 1, 2, or 3. */
HBUINT16 unused; /* Set to 0. */
HBUINT32 chainCount; /* Number of metamorphosis chains contained in this
* table. */
- Chain firstChain; /* Chains. */
+ Chain firstChain; /* Chains. */
public:
DEFINE_SIZE_MIN (8);
};
+struct morx : mortmorx
+{
+ static const hb_tag_t tableTag = HB_AAT_TAG_morx;
+};
+struct mort : mortmorx
+{
+ static const hb_tag_t tableTag = HB_AAT_TAG_mort;
+};
+
+
} /* namespace AAT */
diff --git a/src/hb-aat-layout.cc b/src/hb-aat-layout.cc
index 1e1c7b4f4..d917c29c6 100644
--- a/src/hb-aat-layout.cc
+++ b/src/hb-aat-layout.cc
@@ -34,13 +34,14 @@
#include "hb-aat-layout-kerx-table.hh"
#include "hb-aat-layout-morx-table.hh"
#include "hb-aat-layout-trak-table.hh"
-#include "hb-aat-ltag-table.hh" // Just so we compile it; unused otherwise.
+#include "hb-aat-ltag-table.hh"
/* 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*/},
@@ -130,9 +131,23 @@ hb_aat_layout_find_feature_mapping (hb_tag_t tag)
/*
- * morx/kerx/trak
+ * mort/morx/kerx/trak
*/
+static inline const AAT::mort&
+_get_mort (hb_face_t *face, hb_blob_t **blob = nullptr)
+{
+ if (unlikely (!hb_ot_shaper_face_data_ensure (face)))
+ {
+ if (blob)
+ *blob = hb_blob_get_empty ();
+ return Null(AAT::mort);
+ }
+ const AAT::mort& mort = *(hb_ot_face_data (face)->mort.get ());
+ if (blob)
+ *blob = hb_ot_face_data (face)->mort.get_blob ();
+ return mort;
+}
static inline const AAT::morx&
_get_morx (hb_face_t *face, hb_blob_t **blob = nullptr)
{
@@ -181,20 +196,39 @@ _get_trak (hb_face_t *face)
if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(AAT::trak);
return *(hb_ot_face_data (face)->trak.get ());
}
+static inline const AAT::ltag&
+_get_ltag (hb_face_t *face)
+{
+ if (unlikely (!hb_ot_shaper_face_data_ensure (face))) return Null(AAT::ltag);
+ return *(hb_ot_face_data (face)->ltag.get ());
+}
void
hb_aat_layout_compile_map (const hb_aat_map_builder_t *mapper,
hb_aat_map_t *map)
{
- _get_morx (mapper->face).compile_flags (mapper, map);
+ const AAT::morx& morx = _get_morx (mapper->face, nullptr);
+ if (morx.has_data ())
+ {
+ morx.compile_flags (mapper, map);
+ return;
+ }
+
+ const AAT::mort& mort = _get_mort (mapper->face, nullptr);
+ if (mort.has_data ())
+ {
+ mort.compile_flags (mapper, map);
+ return;
+ }
}
hb_bool_t
hb_aat_layout_has_substitution (hb_face_t *face)
{
- return _get_morx (face).has_data ();
+ return _get_morx (face).has_data () ||
+ _get_mort (face).has_data ();
}
void
@@ -203,10 +237,22 @@ hb_aat_layout_substitute (hb_ot_shape_plan_t *plan,
hb_buffer_t *buffer)
{
hb_blob_t *blob;
- const AAT::morx& morx = _get_morx (font->face, &blob);
- AAT::hb_aat_apply_context_t c (plan, font, buffer, blob);
- morx.apply (&c);
+ const AAT::morx& morx = _get_morx (font->face, &blob);
+ if (morx.has_data ())
+ {
+ AAT::hb_aat_apply_context_t c (plan, font, buffer, blob);
+ morx.apply (&c);
+ return;
+ }
+
+ const AAT::mort& mort = _get_mort (font->face, &blob);
+ if (mort.has_data ())
+ {
+ AAT::hb_aat_apply_context_t c (plan, font, buffer, blob);
+ mort.apply (&c);
+ return;
+ }
}
@@ -248,3 +294,10 @@ hb_aat_layout_track (hb_ot_shape_plan_t *plan,
AAT::hb_aat_apply_context_t c (plan, font, buffer);
trak.apply (&c);
}
+
+hb_language_t
+_hb_aat_language_get (hb_face_t *face,
+ unsigned int i)
+{
+ return _get_ltag (face).get_language (i);
+}
diff --git a/src/hb-aat-layout.hh b/src/hb-aat-layout.hh
index aea545689..8a558e6aa 100644
--- a/src/hb-aat-layout.hh
+++ b/src/hb-aat-layout.hh
@@ -80,4 +80,9 @@ hb_aat_layout_track (hb_ot_shape_plan_t *plan,
hb_font_t *font,
hb_buffer_t *buffer);
+HB_INTERNAL hb_language_t
+_hb_aat_language_get (hb_face_t *face,
+ unsigned int i);
+
+
#endif /* HB_AAT_LAYOUT_HH */
diff --git a/src/hb-aat-ltag-table.hh b/src/hb-aat-ltag-table.hh
index 08a1b51a9..8a42b3510 100644
--- a/src/hb-aat-ltag-table.hh
+++ b/src/hb-aat-ltag-table.hh
@@ -25,7 +25,7 @@
#ifndef HB_AAT_LTAG_TABLE_HH
#define HB_AAT_LTAG_TABLE_HH
-#include "hb-aat-layout-common.hh"
+#include "hb-open-type.hh"
/*
* ltag -- Language Tag
@@ -36,9 +36,13 @@
namespace AAT {
+using namespace OT;
+
struct FTStringRange
{
+ friend struct ltag;
+
inline bool sanitize (hb_sanitize_context_t *c, const void *base) const
{
TRACE_SANITIZE (this);
@@ -58,10 +62,19 @@ struct ltag
{
static const hb_tag_t tableTag = HB_AAT_TAG_ltag;
+ inline hb_language_t get_language (unsigned int i) const
+ {
+ const FTStringRange &range = tagRanges[i];
+ return hb_language_from_string ((const char *) (this+range.tag).arrayZ,
+ range.length);
+ }
+
inline bool sanitize (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
- return_trace (likely (c->check_struct (this) && tagRanges.sanitize (c, this)));
+ return_trace (likely (c->check_struct (this) &&
+ version >= 1 &&
+ tagRanges.sanitize (c, this)));
}
protected:
diff --git a/src/hb-aat-map.cc b/src/hb-aat-map.cc
index f2736bfd1..1ce1b12b0 100644
--- a/src/hb-aat-map.cc
+++ b/src/hb-aat-map.cc
@@ -34,6 +34,14 @@
void hb_aat_map_builder_t::add_feature (hb_tag_t tag,
unsigned int value)
{
+ if (tag == HB_TAG ('a','a','l','t'))
+ {
+ feature_info_t *info = features.push();
+ info->type = 17/*kCharacterAlternativesType*/;
+ info->setting = value;
+ return;
+ }
+
const hb_aat_feature_mapping_t *mapping = hb_aat_layout_find_feature_mapping (tag);
if (!mapping) return;
diff --git a/src/hb-aat-map.hh b/src/hb-aat-map.hh
index 846cdc1a9..6fd3fa1ea 100644
--- a/src/hb-aat-map.hh
+++ b/src/hb-aat-map.hh
@@ -30,8 +30,6 @@
#include "hb.hh"
-struct hb_ot_shape_plan_t;
-
struct hb_aat_map_t
{
friend struct hb_aat_map_builder_t;
@@ -58,15 +56,7 @@ struct hb_aat_map_builder_t
HB_INTERNAL hb_aat_map_builder_t (hb_face_t *face_,
const hb_segment_properties_t *props_ HB_UNUSED) :
- face (face_)
- {
- features.init ();
- }
-
- ~hb_aat_map_builder_t (void)
- {
- features.fini ();
- }
+ face (face_) {}
HB_INTERNAL void add_feature (hb_tag_t tag, unsigned int value=1);
diff --git a/src/hb-blob.cc b/src/hb-blob.cc
index 368491c05..51f22ce4d 100644
--- a/src/hb-blob.cc
+++ b/src/hb-blob.cc
@@ -40,6 +40,19 @@
#include
+/**
+ * SECTION: hb-blob
+ * @title: hb-blob
+ * @short_description: Binary data containers
+ * @include: hb.h
+ *
+ * Blobs wrap a chunk of binary data to handle lifecycle management of data
+ * while it is passed between client and HarfBuzz. Blobs are primarily used
+ * to create font faces, but also to access font face tables, as well as
+ * pass around other binary data.
+ **/
+
+
DEFINE_NULL_INSTANCE (hb_blob_t) =
{
HB_OBJECT_HEADER_STATIC,
diff --git a/src/hb-blob.hh b/src/hb-blob.hh
index bee8c9794..0181e94a4 100644
--- a/src/hb-blob.hh
+++ b/src/hb-blob.hh
@@ -60,7 +60,7 @@ struct hb_blob_t
template
inline const Type* as (void) const
{
- return unlikely (!data) ? &Null(Type) : reinterpret_cast (data);
+ return length < Type::min_size ? &Null(Type) : reinterpret_cast (data);
}
inline hb_bytes_t as_bytes (void) const
{
@@ -69,7 +69,6 @@ struct hb_blob_t
public:
hb_object_header_t header;
- ASSERT_POD ();
bool immutable;
diff --git a/src/hb-buffer.cc b/src/hb-buffer.cc
index ce9b0530c..5a8152ed4 100644
--- a/src/hb-buffer.cc
+++ b/src/hb-buffer.cc
@@ -33,14 +33,15 @@
/**
* SECTION: hb-buffer
- * @title: Buffers
+ * @title: hb-buffer
* @short_description: Input and output buffers
* @include: hb.h
*
* Buffers serve dual role in HarfBuzz; they hold the input characters that are
- * passed hb_shape(), and after shaping they hold the output glyphs.
+ * passed to hb_shape(), and after shaping they hold the output glyphs.
**/
+
/**
* hb_segment_properties_equal:
* @a: first #hb_segment_properties_t to compare.
@@ -1665,7 +1666,7 @@ hb_buffer_add_utf32 (hb_buffer_t *buffer,
unsigned int item_offset,
int item_length)
{
- hb_buffer_add_utf > (buffer, text, text_length, item_offset, item_length);
+ hb_buffer_add_utf (buffer, text, text_length, item_offset, item_length);
}
/**
@@ -1726,7 +1727,7 @@ hb_buffer_add_codepoints (hb_buffer_t *buffer,
unsigned int item_offset,
int item_length)
{
- hb_buffer_add_utf > (buffer, text, text_length, item_offset, item_length);
+ hb_buffer_add_utf (buffer, text, text_length, item_offset, item_length);
}
diff --git a/src/hb-buffer.hh b/src/hb-buffer.hh
index 0d888e1e0..37adeb083 100644
--- a/src/hb-buffer.hh
+++ b/src/hb-buffer.hh
@@ -86,7 +86,6 @@ HB_MARK_AS_FLAG_T (hb_buffer_scratch_flags_t);
struct hb_buffer_t
{
hb_object_header_t header;
- ASSERT_POD ();
/* Information about how the text in the buffer should be treated */
hb_unicode_funcs_t *unicode; /* Unicode functions */
diff --git a/src/hb-common.cc b/src/hb-common.cc
index 86d07cf16..d7c1921f3 100644
--- a/src/hb-common.cc
+++ b/src/hb-common.cc
@@ -36,6 +36,16 @@
#endif
+/**
+ * SECTION:hb-common
+ * @title: hb-common
+ * @short_description: Common data types
+ * @include: hb.h
+ *
+ * Common data types used across HarfBuzz are defined here.
+ **/
+
+
/* hb_options_t */
hb_atomic_int_t _hb_options;
@@ -615,6 +625,19 @@ hb_user_data_array_t::get (hb_user_data_key_t *key)
/* hb_version */
+
+/**
+ * SECTION:hb-version
+ * @title: hb-version
+ * @short_description: Information about the version of HarfBuzz in use
+ * @include: hb.h
+ *
+ * These functions and macros allow accessing version of the HarfBuzz
+ * library used at compile- as well as run-time, and to direct code
+ * conditionally based on those versions, again, at compile- or run-time.
+ **/
+
+
/**
* hb_version:
* @major: (out): Library major version component.
diff --git a/src/hb-common.h b/src/hb-common.h
index 0858c0e29..ae23698a5 100644
--- a/src/hb-common.h
+++ b/src/hb-common.h
@@ -33,6 +33,10 @@
#ifndef HB_COMMON_H
#define HB_COMMON_H
+#ifndef HB_EXTERN
+#define HB_EXTERN extern
+#endif
+
#ifndef HB_BEGIN_DECLS
# ifdef __cplusplus
# define HB_BEGIN_DECLS extern "C" {
@@ -449,15 +453,43 @@ hb_variation_to_string (hb_variation_t *variation,
*
* Data type for holding color values.
*
- * Since: REPLACEME
+ * Since: 2.1.0
*/
typedef uint32_t hb_color_t;
#define HB_COLOR(b,g,r,a) ((hb_color_t) HB_TAG ((b),(g),(r),(a)))
+/**
+ * hb_color_get_alpha:
+ *
+ *
+ *
+ * Since: 2.1.0
+ */
#define hb_color_get_alpha(color) ((color) & 0xFF)
+/**
+ * hb_color_get_red:
+ *
+ *
+ *
+ * Since: 2.1.0
+ */
#define hb_color_get_red(color) (((color) >> 8) & 0xFF)
+/**
+ * hb_color_get_green:
+ *
+ *
+ *
+ * Since: 2.1.0
+ */
#define hb_color_get_green(color) (((color) >> 16) & 0xFF)
+/**
+ * hb_color_get_blue:
+ *
+ *
+ *
+ * Since: 2.1.0
+ */
#define hb_color_get_blue(color) (((color) >> 24) & 0xFF)
diff --git a/src/hb-coretext.cc b/src/hb-coretext.cc
index 9f7745dbf..184db4944 100644
--- a/src/hb-coretext.cc
+++ b/src/hb-coretext.cc
@@ -35,6 +35,16 @@
#include "hb-aat-layout.hh"
#include
+
+/**
+ * SECTION:hb-coretext
+ * @title: hb-coretext
+ * @short_description: CoreText integration
+ * @include: hb-coretext.h
+ *
+ * Functions for using HarfBuzz with the CoreText fonts.
+ **/
+
/* https://developer.apple.com/documentation/coretext/1508745-ctfontcreatewithgraphicsfont */
#define HB_CORETEXT_DEFAULT_FONT_SIZE 12.f
@@ -464,8 +474,8 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
buffer->merge_clusters (i - 1, i + 1);
}
- hb_auto_t > feature_records;
- hb_auto_t > range_records;
+ hb_vector_t feature_records;
+ hb_vector_t range_records;
/*
* Set up features.
@@ -474,7 +484,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
if (num_features)
{
/* Sort features by start/end events. */
- hb_auto_t > feature_events;
+ hb_vector_t feature_events;
for (unsigned int i = 0; i < num_features; i++)
{
const hb_aat_feature_mapping_t * mapping = hb_aat_layout_find_feature_mapping (features[i].tag);
@@ -513,7 +523,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
}
/* Scan events and save features for each range. */
- hb_auto_t > active_features;
+ hb_vector_t active_features;
unsigned int last_index = 0;
for (unsigned int i = 0; i < feature_events.len; i++)
{
@@ -586,7 +596,7 @@ _hb_coretext_shape (hb_shape_plan_t *shape_plan,
} else {
active_feature_t *feature = active_features.find (&event->feature);
if (feature)
- active_features.remove (feature - active_features.arrayZ());
+ active_features.remove (feature - active_features);
}
}
}
diff --git a/src/hb-debug.hh b/src/hb-debug.hh
index 58c190d27..d218e4328 100644
--- a/src/hb-debug.hh
+++ b/src/hb-debug.hh
@@ -173,7 +173,7 @@ _hb_debug_msg_va (const char *what,
fprintf (stderr, "\n");
}
-template <> inline void
+template <> inline void HB_PRINTF_FUNC(7, 0)
_hb_debug_msg_va<0> (const char *what HB_UNUSED,
const void *obj HB_UNUSED,
const char *func HB_UNUSED,
@@ -192,7 +192,7 @@ _hb_debug_msg (const char *what,
int level_dir,
const char *message,
...) HB_PRINTF_FUNC(7, 8);
-template static inline void
+template static inline void HB_PRINTF_FUNC(7, 8)
_hb_debug_msg (const char *what,
const void *obj,
const char *func,
@@ -216,7 +216,7 @@ _hb_debug_msg<0> (const char *what HB_UNUSED,
int level_dir HB_UNUSED,
const char *message HB_UNUSED,
...) HB_PRINTF_FUNC(7, 8);
-template <> inline void
+template <> inline void HB_PRINTF_FUNC(7, 8)
_hb_debug_msg<0> (const char *what HB_UNUSED,
const void *obj HB_UNUSED,
const char *func HB_UNUSED,
diff --git a/src/hb-deprecated.h b/src/hb-deprecated.h
index 369d07361..e39b79f74 100644
--- a/src/hb-deprecated.h
+++ b/src/hb-deprecated.h
@@ -36,6 +36,18 @@
#include "hb-font.h"
#include "hb-set.h"
+
+/**
+ * SECTION:hb-deprecated
+ * @title: hb-deprecated
+ * @short_description: Deprecated API
+ * @include: hb.h
+ *
+ * These API have been deprecated in favor of newer API, or because they
+ * were deemed unnecessary.
+ **/
+
+
HB_BEGIN_DECLS
#ifndef HB_DISABLE_DEPRECATED
diff --git a/src/hb-dsalgs.hh b/src/hb-dsalgs.hh
index 7e846161d..59df860df 100644
--- a/src/hb-dsalgs.hh
+++ b/src/hb-dsalgs.hh
@@ -312,6 +312,27 @@ hb_in_ranges (T u, T lo1, T hi1, T lo2, T hi2, T lo3, T hi3)
* Sort and search.
*/
+static inline void *
+hb_bsearch (const void *key, const void *base,
+ size_t nmemb, size_t size,
+ int (*compar)(const void *_key, const void *_item))
+{
+ int min = 0, max = (int) nmemb - 1;
+ while (min <= max)
+ {
+ int mid = (min + max) / 2;
+ const void *p = (const void *) (((const char *) base) + (mid * size));
+ int c = compar (key, p);
+ if (c < 0)
+ max = mid - 1;
+ else if (c > 0)
+ min = mid + 1;
+ else
+ return (void *) p;
+ }
+ return nullptr;
+}
+
static inline void *
hb_bsearch_r (const void *key, const void *base,
size_t nmemb, size_t size,
@@ -321,7 +342,7 @@ hb_bsearch_r (const void *key, const void *base,
int min = 0, max = (int) nmemb - 1;
while (min <= max)
{
- int mid = (min + max) / 2;
+ int mid = ((unsigned int) min + (unsigned int) max) / 2;
const void *p = (const void *) (((const char *) base) + (mid * size));
int c = compar (key, p, arg);
if (c < 0)
@@ -490,56 +511,6 @@ hb_codepoint_parse (const char *s, unsigned int len, int base, hb_codepoint_t *o
}
-template
-struct hb_auto_t : Type
-{
- hb_auto_t (void) { Type::init (); }
- /* Explicitly allow the following only for pointer and references,
- * to avoid any accidental copies.
- *
- * Apparently if we template for all types, then gcc seems to
- * capture a reference argument in the type, but clang doesn't,
- * causing unwanted copies and bugs that come with it. Ideally
- * we should use C++11-style rvalue reference &&t1. */
- template explicit hb_auto_t (T1 *t1) { Type::init (t1); }
- template explicit hb_auto_t (T1 &t1) { Type::init (t1); }
- ~hb_auto_t (void) { Type::fini (); }
- private: /* Hide */
- void init (void) {}
- void fini (void) {}
-};
-
-template
-struct hb_array_t
-{
- inline hb_array_t (void) : arrayZ (nullptr), len (0) {}
- inline hb_array_t (T *array_, unsigned int len_) : arrayZ (array_), len (len_) {}
-
- inline T& operator [] (unsigned int i) const
- {
- if (unlikely (i >= len)) return Null(T);
- return arrayZ[i];
- }
-
- inline hb_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const
- {
- unsigned int count = len;
- if (unlikely (start_offset > count))
- count = 0;
- else
- count -= start_offset;
- count = MIN (count, seg_count);
- return hb_array_t (arrayZ + start_offset, count);
- }
-
- inline void free (void) { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; }
-
- T *arrayZ;
- unsigned int len;
-};
-template static inline
-hb_array_t hb_array (T *array, unsigned int len) { return hb_array_t (array, len); }
-
struct hb_bytes_t
{
inline hb_bytes_t (void) : arrayZ (nullptr), len (0) {}
@@ -568,6 +539,42 @@ struct hb_bytes_t
unsigned int len;
};
+template
+struct hb_array_t
+{
+ inline hb_array_t (void) : arrayZ (nullptr), len (0) {}
+ inline hb_array_t (T *array_, unsigned int len_) : arrayZ (array_), len (len_) {}
+
+ inline T& operator [] (unsigned int i) const
+ {
+ if (unlikely (i >= len)) return Null(T);
+ return arrayZ[i];
+ }
+
+ inline hb_array_t sub_array (unsigned int start_offset, unsigned int seg_count) const
+ {
+ unsigned int count = len;
+ if (unlikely (start_offset > count))
+ count = 0;
+ else
+ count -= start_offset;
+ count = MIN (count, seg_count);
+ return hb_array_t (arrayZ + start_offset, count);
+ }
+
+ inline hb_bytes_t as_bytes (void) const
+ {
+ return hb_bytes_t (arrayZ, len * sizeof (T));
+ }
+
+ inline void free (void) { ::free ((void *) arrayZ); arrayZ = nullptr; len = 0; }
+
+ T *arrayZ;
+ unsigned int len;
+};
+template static inline
+hb_array_t hb_array (T *array, unsigned int len) { return hb_array_t (array, len); }
+
struct HbOpOr
{
@@ -603,8 +610,10 @@ struct HbOpXor
template
struct hb_vector_size_t
{
- elt_t& operator [] (unsigned int i) { return u.v[i]; }
- const elt_t& operator [] (unsigned int i) const { return u.v[i]; }
+ inline elt_t& operator [] (unsigned int i) { return u.v[i]; }
+ inline const elt_t& operator [] (unsigned int i) const { return u.v[i]; }
+
+ inline void clear (unsigned char v = 0) { memset (this, v, sizeof (*this)); }
template
inline hb_vector_size_t process (const hb_vector_size_t &o) const
diff --git a/src/hb-face.cc b/src/hb-face.cc
index bba1ee3fa..7ca4b1ba2 100644
--- a/src/hb-face.cc
+++ b/src/hb-face.cc
@@ -35,6 +35,19 @@
#include "hb-ot-cmap-table.hh"
+/**
+ * SECTION:hb-face
+ * @title: hb-face
+ * @short_description: Font face objects
+ * @include: hb.h
+ *
+ * Font face is objects represent a single face in a font family.
+ * More exactly, a font face represents a single face in a binary font file.
+ * Font faces are typically built from a binary blob and a face index.
+ * Font faces are used to create fonts.
+ **/
+
+
/**
* hb_face_count:
* @blob: a blob.
@@ -666,7 +679,7 @@ _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
}
static hb_blob_t *
-_hb_face_builder_reference_table (hb_face_t *face, hb_tag_t tag, void *user_data)
+_hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
{
hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
diff --git a/src/hb-face.hh b/src/hb-face.hh
index f90453dbd..89673ff84 100644
--- a/src/hb-face.hh
+++ b/src/hb-face.hh
@@ -42,7 +42,6 @@
struct hb_face_t
{
hb_object_header_t header;
- ASSERT_POD ();
hb_bool_t immutable;
diff --git a/src/hb-font.cc b/src/hb-font.cc
index b6b668dd8..86b03f4b6 100644
--- a/src/hb-font.cc
+++ b/src/hb-font.cc
@@ -34,6 +34,19 @@
#include "hb-ot.h"
+/**
+ * SECTION:hb-font
+ * @title: hb-font
+ * @short_description: Font objects
+ * @include: hb.h
+ *
+ * Font objects represent a font face at a certain size and other
+ * parameters (pixels per EM, points per EM, variation settings.)
+ * Fonts are created from font faces, and are used as input to
+ * hb_shape() among other things.
+ **/
+
+
/*
* hb_font_funcs_t
*/
@@ -41,23 +54,23 @@
static hb_bool_t
hb_font_get_font_h_extents_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
- hb_font_extents_t *metrics,
+ hb_font_extents_t *extents,
void *user_data HB_UNUSED)
{
- memset (metrics, 0, sizeof (*metrics));
+ memset (extents, 0, sizeof (*extents));
return false;
}
static hb_bool_t
hb_font_get_font_h_extents_default (hb_font_t *font,
void *font_data HB_UNUSED,
- hb_font_extents_t *metrics,
+ hb_font_extents_t *extents,
void *user_data HB_UNUSED)
{
- hb_bool_t ret = font->parent->get_font_h_extents (metrics);
+ hb_bool_t ret = font->parent->get_font_h_extents (extents);
if (ret) {
- metrics->ascender = font->parent_scale_y_distance (metrics->ascender);
- metrics->descender = font->parent_scale_y_distance (metrics->descender);
- metrics->line_gap = font->parent_scale_y_distance (metrics->line_gap);
+ extents->ascender = font->parent_scale_y_distance (extents->ascender);
+ extents->descender = font->parent_scale_y_distance (extents->descender);
+ extents->line_gap = font->parent_scale_y_distance (extents->line_gap);
}
return ret;
}
@@ -65,23 +78,23 @@ hb_font_get_font_h_extents_default (hb_font_t *font,
static hb_bool_t
hb_font_get_font_v_extents_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
- hb_font_extents_t *metrics,
+ hb_font_extents_t *extents,
void *user_data HB_UNUSED)
{
- memset (metrics, 0, sizeof (*metrics));
+ memset (extents, 0, sizeof (*extents));
return false;
}
static hb_bool_t
hb_font_get_font_v_extents_default (hb_font_t *font,
void *font_data HB_UNUSED,
- hb_font_extents_t *metrics,
+ hb_font_extents_t *extents,
void *user_data HB_UNUSED)
{
- hb_bool_t ret = font->parent->get_font_v_extents (metrics);
+ hb_bool_t ret = font->parent->get_font_v_extents (extents);
if (ret) {
- metrics->ascender = font->parent_scale_x_distance (metrics->ascender);
- metrics->descender = font->parent_scale_x_distance (metrics->descender);
- metrics->line_gap = font->parent_scale_x_distance (metrics->line_gap);
+ extents->ascender = font->parent_scale_x_distance (extents->ascender);
+ extents->descender = font->parent_scale_x_distance (extents->descender);
+ extents->line_gap = font->parent_scale_x_distance (extents->line_gap);
}
return ret;
}
@@ -89,7 +102,7 @@ hb_font_get_font_v_extents_default (hb_font_t *font,
static hb_bool_t
hb_font_get_nominal_glyph_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
- hb_codepoint_t unicode,
+ hb_codepoint_t unicode HB_UNUSED,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
@@ -142,8 +155,8 @@ hb_font_get_nominal_glyphs_default (hb_font_t *font,
static hb_bool_t
hb_font_get_variation_glyph_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
- hb_codepoint_t unicode,
- hb_codepoint_t variation_selector,
+ hb_codepoint_t unicode HB_UNUSED,
+ hb_codepoint_t variation_selector HB_UNUSED,
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
@@ -276,7 +289,7 @@ hb_font_get_glyph_v_advances_default (hb_font_t* font,
static hb_bool_t
hb_font_get_glyph_h_origin_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
+ hb_codepoint_t glyph HB_UNUSED,
hb_position_t *x,
hb_position_t *y,
void *user_data HB_UNUSED)
@@ -301,7 +314,7 @@ hb_font_get_glyph_h_origin_default (hb_font_t *font,
static hb_bool_t
hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
+ hb_codepoint_t glyph HB_UNUSED,
hb_position_t *x,
hb_position_t *y,
void *user_data HB_UNUSED)
@@ -326,8 +339,8 @@ hb_font_get_glyph_v_origin_default (hb_font_t *font,
static hb_position_t
hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
- hb_codepoint_t left_glyph,
- hb_codepoint_t right_glyph,
+ hb_codepoint_t left_glyph HB_UNUSED,
+ hb_codepoint_t right_glyph HB_UNUSED,
void *user_data HB_UNUSED)
{
return 0;
@@ -345,8 +358,8 @@ hb_font_get_glyph_h_kerning_default (hb_font_t *font,
static hb_position_t
hb_font_get_glyph_v_kerning_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
- hb_codepoint_t top_glyph,
- hb_codepoint_t bottom_glyph,
+ hb_codepoint_t top_glyph HB_UNUSED,
+ hb_codepoint_t bottom_glyph HB_UNUSED,
void *user_data HB_UNUSED)
{
return 0;
@@ -364,7 +377,7 @@ hb_font_get_glyph_v_kerning_default (hb_font_t *font,
static hb_bool_t
hb_font_get_glyph_extents_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
+ hb_codepoint_t glyph HB_UNUSED,
hb_glyph_extents_t *extents,
void *user_data HB_UNUSED)
{
@@ -389,8 +402,8 @@ hb_font_get_glyph_extents_default (hb_font_t *font,
static hb_bool_t
hb_font_get_glyph_contour_point_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
- unsigned int point_index,
+ hb_codepoint_t glyph HB_UNUSED,
+ unsigned int point_index HB_UNUSED,
hb_position_t *x,
hb_position_t *y,
void *user_data HB_UNUSED)
@@ -416,7 +429,7 @@ hb_font_get_glyph_contour_point_default (hb_font_t *font,
static hb_bool_t
hb_font_get_glyph_name_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
- hb_codepoint_t glyph,
+ hb_codepoint_t glyph HB_UNUSED,
char *name, unsigned int size,
void *user_data HB_UNUSED)
{
@@ -436,7 +449,8 @@ hb_font_get_glyph_name_default (hb_font_t *font,
static hb_bool_t
hb_font_get_glyph_from_name_nil (hb_font_t *font HB_UNUSED,
void *font_data HB_UNUSED,
- const char *name, int len, /* -1 means nul-terminated */
+ const char *name HB_UNUSED,
+ int len HB_UNUSED, /* -1 means nul-terminated */
hb_codepoint_t *glyph,
void *user_data HB_UNUSED)
{
diff --git a/src/hb-font.h b/src/hb-font.h
index 74c61aba4..e2086d818 100644
--- a/src/hb-font.h
+++ b/src/hb-font.h
@@ -110,7 +110,7 @@ typedef struct hb_glyph_extents_t
/* func types */
typedef hb_bool_t (*hb_font_get_font_extents_func_t) (hb_font_t *font, void *font_data,
- hb_font_extents_t *metrics,
+ hb_font_extents_t *extents,
void *user_data);
typedef hb_font_get_font_extents_func_t hb_font_get_font_h_extents_func_t;
typedef hb_font_get_font_extents_func_t hb_font_get_font_v_extents_func_t;
diff --git a/src/hb-font.hh b/src/hb-font.hh
index 2df5e42ee..3dce233db 100644
--- a/src/hb-font.hh
+++ b/src/hb-font.hh
@@ -62,7 +62,6 @@
struct hb_font_funcs_t
{
hb_object_header_t header;
- ASSERT_POD ();
hb_bool_t immutable;
@@ -102,7 +101,6 @@ DECLARE_NULL_INSTANCE (hb_font_funcs_t);
struct hb_font_t
{
hb_object_header_t header;
- ASSERT_POD ();
hb_bool_t immutable;
diff --git a/src/hb-ft.cc b/src/hb-ft.cc
index fbf362688..5e0511052 100644
--- a/src/hb-ft.cc
+++ b/src/hb-ft.cc
@@ -40,6 +40,17 @@
#include FT_TRUETYPE_TABLES_H
+/**
+ * SECTION:hb-ft
+ * @title: hb-ft
+ * @short_description: FreeType integration
+ * @include: hb-ft.h
+ *
+ * Functions for using HarfBuzz with the FreeType library to provide face and
+ * font data.
+ **/
+
+
/* TODO:
*
* In general, this file does a fine job of what it's supposed to do.
diff --git a/src/hb-glib.cc b/src/hb-glib.cc
index a34acbba1..23a0d89c8 100644
--- a/src/hb-glib.cc
+++ b/src/hb-glib.cc
@@ -33,6 +33,16 @@
#include "hb-machinery.hh"
+/**
+ * SECTION:hb-glib
+ * @title: hb-glib
+ * @short_description: GLib integration
+ * @include: hb-glib.h
+ *
+ * Functions for using HarfBuzz with the GLib library to provide Unicode data.
+ **/
+
+
#if !GLIB_CHECK_VERSION(2,29,14)
static const hb_script_t
glib_script_to_script[] =
diff --git a/src/hb-gobject-structs.cc b/src/hb-gobject-structs.cc
index 1b8758583..23ca43656 100644
--- a/src/hb-gobject-structs.cc
+++ b/src/hb-gobject-structs.cc
@@ -26,6 +26,18 @@
#include "hb.hh"
+
+/**
+ * SECTION:hb-gobject
+ * @title: hb-gobject
+ * @short_description: GObject integration
+ * @include: hb-gobject.h
+ *
+ * Functions for using HarfBuzz with the GObject library to provide
+ * type data.
+ **/
+
+
/* g++ didn't like older gtype.h gcc-only code path. */
#include
#if !GLIB_CHECK_VERSION(2,29,16)
diff --git a/src/hb-graphite2.cc b/src/hb-graphite2.cc
index 6b2b6f19d..971241f92 100644
--- a/src/hb-graphite2.cc
+++ b/src/hb-graphite2.cc
@@ -33,7 +33,17 @@
#include
-#include "hb-ot-tag.h"
+#include "hb-ot-layout.h"
+
+
+/**
+ * SECTION:hb-graphite2
+ * @title: hb-graphite2
+ * @short_description: Graphite2 integration
+ * @include: hb-graphite2.h
+ *
+ * Functions for using HarfBuzz with the Graphite2 fonts.
+ **/
HB_SHAPER_DATA_ENSURE_DEFINE(graphite2, face)
@@ -197,11 +207,14 @@ _hb_graphite2_shaper_font_data_destroy (hb_graphite2_font_data_t *data HB_UNUSED
{
}
-/*
+/**
+ * hb_graphite2_font_get_gr_font:
+ *
* Since: 0.9.10
+ * Deprecated: 1.4.2
*/
gr_font *
-hb_graphite2_font_get_gr_font (hb_font_t *font)
+hb_graphite2_font_get_gr_font (hb_font_t *font HB_UNUSED)
{
return nullptr;
}
@@ -243,7 +256,7 @@ struct hb_graphite2_cluster_t {
};
hb_bool_t
-_hb_graphite2_shape (hb_shape_plan_t *shape_plan,
+_hb_graphite2_shape (hb_shape_plan_t *shape_plan HB_UNUSED,
hb_font_t *font,
hb_buffer_t *buffer,
const hb_feature_t *features,
diff --git a/src/hb-icu.cc b/src/hb-icu.cc
index e012314b5..12864677c 100644
--- a/src/hb-icu.cc
+++ b/src/hb-icu.cc
@@ -40,6 +40,16 @@
#include
+/**
+ * SECTION:hb-icu
+ * @title: hb-icu
+ * @short_description: ICU integration
+ * @include: hb-icu.h
+ *
+ * Functions for using HarfBuzz with the ICU library to provide Unicode data.
+ **/
+
+
hb_script_t
hb_icu_script_to_script (UScriptCode script)
{
diff --git a/src/hb-machinery.hh b/src/hb-machinery.hh
index 19245e89b..465bbb14f 100644
--- a/src/hb-machinery.hh
+++ b/src/hb-machinery.hh
@@ -82,10 +82,8 @@ 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), ""); \
- ASSERT_INSTANCE_POD (*this); /* Make sure it's POD. */ \
- }
+ { static_assert ((_assertion), ""); } \
+ static_assert (true, "") /* So we require semicolon here. */
# define _DEFINE_INSTANCE_ASSERTION0(_line, _assertion) _DEFINE_INSTANCE_ASSERTION1 (_line, _assertion)
# define DEFINE_INSTANCE_ASSERTION(_assertion) _DEFINE_INSTANCE_ASSERTION0 (__LINE__, _assertion)
@@ -99,9 +97,9 @@ static inline Type& StructAfter(TObject &X)
#define DEFINE_SIZE_STATIC(size) \
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size)); \
+ inline unsigned int get_size (void) const { return (size); } \
enum { static_size = (size) }; \
- enum { min_size = (size) }; \
- inline unsigned int get_size (void) const { return (size); }
+ enum { min_size = (size) }
#define DEFINE_SIZE_UNION(size, _member) \
DEFINE_INSTANCE_ASSERTION (0*sizeof(this->u._member.static_size) + sizeof(this->u._member) == (size)); \
@@ -114,11 +112,11 @@ static inline Type& StructAfter(TObject &X)
#define DEFINE_SIZE_ARRAY(size, array) \
DEFINE_INSTANCE_ASSERTION (sizeof (*this) == (size) + VAR * sizeof (array[0])); \
DEFINE_COMPILES_ASSERTION ((void) array[0].static_size) \
- enum { min_size = (size) }; \
+ enum { min_size = (size) }
#define DEFINE_SIZE_ARRAY_SIZED(size, array) \
- DEFINE_SIZE_ARRAY(size, array); \
- inline unsigned int get_size (void) const { return (size - array.min_size + array.get_size ()); }
+ 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])); \
@@ -136,7 +134,7 @@ struct hb_dispatch_context_t
enum { max_debug_depth = MaxDebugDepth };
typedef Return return_t;
template
- inline bool may_dispatch (const T *obj, const F *format) { return true; }
+ inline bool may_dispatch (const T *obj HB_UNUSED, const F *format HB_UNUSED) { return true; }
static return_t no_dispatch_return_value (void) { return Context::default_return_value (); }
};
@@ -235,7 +233,7 @@ struct hb_sanitize_context_t :
inline const char *get_name (void) { return "SANITIZE"; }
template
- inline bool may_dispatch (const T *obj, const F *format)
+ inline bool may_dispatch (const T *obj HB_UNUSED, const F *format)
{ return format->sanitize (this); }
template
inline return_t dispatch (const T &obj) { return obj.sanitize (this); }
@@ -612,7 +610,7 @@ struct Supplier
}
inline Supplier (const hb_vector_t *v)
{
- head = v->arrayZ();
+ head = *v;
len = v->len;
stride = sizeof (Type);
}
diff --git a/src/hb-map.cc b/src/hb-map.cc
index 225f37bc6..067a2b371 100644
--- a/src/hb-map.cc
+++ b/src/hb-map.cc
@@ -27,7 +27,16 @@
#include "hb-map.hh"
-/* Public API */
+/**
+ * SECTION:hb-map
+ * @title: hb-map
+ * @short_description: Object representing integer to integer mapping
+ * @include: hb.h
+ *
+ * Map objects are integer-to-integer hash-maps. Currently they are
+ * not used in the HarfBuzz public API, but are provided for client's
+ * use if desired.
+ **/
/**
diff --git a/src/hb-map.hh b/src/hb-map.hh
index b55e3a954..c54c9d7b6 100644
--- a/src/hb-map.hh
+++ b/src/hb-map.hh
@@ -44,6 +44,10 @@ inline uint32_t Hash (const T &v)
struct hb_map_t
{
+ HB_NO_COPY_ASSIGN (hb_map_t);
+ inline hb_map_t (void) { init (); }
+ inline ~hb_map_t (void) { fini (); }
+
struct item_t
{
hb_codepoint_t key;
@@ -77,9 +81,11 @@ struct hb_map_t
inline void fini_shallow (void)
{
free (items);
+ items = nullptr;
}
inline void fini (void)
{
+ population = occupancy = 0;
hb_object_fini (this);
fini_shallow ();
}
diff --git a/src/hb-null.hh b/src/hb-null.hh
index 6906555e3..204689bd7 100644
--- a/src/hb-null.hh
+++ b/src/hb-null.hh
@@ -87,7 +87,7 @@ template
static inline Type& Crap (void) {
static_assert (sizeof (Type) <= HB_NULL_POOL_SIZE, "Increase HB_NULL_POOL_SIZE.");
Type *obj = reinterpret_cast (_hb_CrapPool);
- *obj = Null(Type);
+ memcpy (obj, &Null(Type), sizeof (*obj));
return *obj;
}
#define Crap(Type) Crap::value>::value>()
diff --git a/src/hb-object.hh b/src/hb-object.hh
index ca85af691..106f59206 100644
--- a/src/hb-object.hh
+++ b/src/hb-object.hh
@@ -195,12 +195,8 @@ struct hb_object_header_t
{
hb_reference_count_t ref_count;
hb_atomic_ptr_t user_data;
-
-#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, HB_ATOMIC_PTR_INIT (nullptr)}
-
- private:
- ASSERT_POD ();
};
+#define HB_OBJECT_HEADER_STATIC {HB_REFERENCE_COUNT_INIT, HB_ATOMIC_PTR_INIT (nullptr)}
/*
@@ -276,6 +272,7 @@ static inline void hb_object_fini (Type *obj)
{
user_data->fini ();
free (user_data);
+ user_data = nullptr;
}
}
template
diff --git a/src/hb-open-type.hh b/src/hb-open-type.hh
index 2b1b432ba..00bd134dd 100644
--- a/src/hb-open-type.hh
+++ b/src/hb-open-type.hh
@@ -335,9 +335,14 @@ static inline Type& operator + (Base &base, OffsetTo
template
struct UnsizedArrayOf
{
+ HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (UnsizedArrayOf, Type);
+
inline const Type& operator [] (unsigned int i) const { return arrayZ[i]; }
inline Type& operator [] (unsigned int i) { return arrayZ[i]; }
+ template inline operator T * (void) { return arrayZ; }
+ template inline operator const T * (void) const { return arrayZ; }
+
inline bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
{
TRACE_SANITIZE (this);
@@ -424,6 +429,8 @@ struct UnsizedOffsetListOf : UnsizedOffsetArrayOf
template
struct ArrayOf
{
+ 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;
@@ -446,6 +453,10 @@ struct ArrayOf
if (unlikely (i >= len)) return Crap(Type);
return arrayZ[i];
}
+
+ template inline operator T * (void) { return arrayZ; }
+ template inline operator const T * (void) const { return arrayZ; }
+
inline unsigned int get_size (void) const
{ return len.static_size + len * Type::static_size; }
@@ -523,7 +534,6 @@ struct ArrayOf
::qsort (arrayZ, len, sizeof (Type), Type::cmp);
}
- private:
inline bool sanitize_shallow (hb_sanitize_context_t *c) const
{
TRACE_SANITIZE (this);
@@ -540,8 +550,12 @@ template struct LArrayOf : ArrayOf {};
typedef ArrayOf PString;
/* Array of Offset's */
-template
-struct OffsetArrayOf : ArrayOf > {};
+template
+struct OffsetArrayOf : ArrayOf > {};
+template
+struct LOffsetArrayOf : ArrayOf > {};
+template
+struct LOffsetLArrayOf : ArrayOf, HBUINT32> {};
/* Array of offsets relative to the beginning of the array itself. */
template
@@ -586,6 +600,8 @@ struct OffsetListOf : OffsetArrayOf
template
struct HeadlessArrayOf
{
+ HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (HeadlessArrayOf, Type, LenType);
+
inline const Type& operator [] (unsigned int i) const
{
if (unlikely (i >= lenP1 || !i)) return Null(Type);
@@ -650,6 +666,8 @@ struct HeadlessArrayOf
template
struct ArrayOfM1
{
+ HB_NO_CREATE_COPY_ASSIGN_TEMPLATE2 (ArrayOfM1, Type, LenType);
+
inline const Type& operator [] (unsigned int i) const
{
if (unlikely (i > lenM1)) return Null(Type);
@@ -702,7 +720,7 @@ struct SortedArrayOf : ArrayOf
int min = 0, max = (int) this->len - 1;
while (min <= max)
{
- int mid = (min + max) / 2;
+ int mid = ((unsigned int) min + (unsigned int) max) / 2;
int c = arr[mid].cmp (x);
if (c < 0)
max = mid - 1;
@@ -754,6 +772,7 @@ struct BinSearchHeader
template
struct BinSearchArrayOf : SortedArrayOf > {};
+
struct VarSizedBinSearchHeader
{
@@ -779,6 +798,8 @@ struct VarSizedBinSearchHeader
template
struct VarSizedBinSearchArrayOf
{
+ HB_NO_CREATE_COPY_ASSIGN_TEMPLATE (VarSizedBinSearchArrayOf, Type);
+
inline const Type& operator [] (unsigned int i) const
{
if (unlikely (i >= header.nUnits)) return Null(Type);
@@ -825,7 +846,7 @@ struct VarSizedBinSearchArrayOf
int min = 0, max = (int) header.nUnits - 1;
while (min <= max)
{
- int mid = (min + max) / 2;
+ int mid = ((unsigned int) min + (unsigned int) max) / 2;
const Type *p = (const Type *) (((const char *) &bytesZ) + (mid * size));
int c = p->cmp (key);
if (c < 0)
diff --git a/src/hb-ot-cmap-table.hh b/src/hb-ot-cmap-table.hh
index e5793c387..a1c5a9747 100644
--- a/src/hb-ot-cmap-table.hh
+++ b/src/hb-ot-cmap-table.hh
@@ -228,6 +228,10 @@ struct CmapSubtableFormat4
struct accelerator_t
{
+ inline accelerator_t (void) {}
+ inline accelerator_t (const CmapSubtableFormat4 *subtable) { init (subtable); }
+ inline ~accelerator_t (void) { fini (); }
+
inline void init (const CmapSubtableFormat4 *subtable)
{
segCount = subtable->segCountX2 / 2;
@@ -249,7 +253,7 @@ struct CmapSubtableFormat4
unsigned int i;
while (min <= max)
{
- int mid = (min + max) / 2;
+ int mid = ((unsigned int) min + (unsigned int) max) / 2;
if (codepoint < startCount[mid])
max = mid - 1;
else if (codepoint > endCount[mid])
@@ -327,12 +331,12 @@ struct CmapSubtableFormat4
inline bool get_glyph (hb_codepoint_t codepoint, hb_codepoint_t *glyph) const
{
- hb_auto_t accel (this);
+ accelerator_t accel (this);
return accel.get_glyph_func (&accel, codepoint, glyph);
}
inline void collect_unicodes (hb_set_t *out) const
{
- hb_auto_t accel (this);
+ accelerator_t accel (this);
accel.collect_unicodes (out);
}
@@ -495,7 +499,7 @@ struct CmapSubtableLongSegmented
{
TRACE_SERIALIZE (this);
if (unlikely (!c->extend_min (*this))) return_trace (false);
- Supplier supplier (group_data.arrayZ(), group_data.len);
+ Supplier supplier (group_data, group_data.len);
if (unlikely (!groups.serialize (c, supplier, group_data.len))) return_trace (false);
return true;
}
@@ -851,18 +855,6 @@ struct cmap
struct subset_plan
{
- subset_plan(void)
- {
- format4_segments.init();
- format12_groups.init();
- }
-
- ~subset_plan(void)
- {
- format4_segments.fini();
- format12_groups.fini();
- }
-
inline size_t final_size() const
{
return 4 // header
@@ -871,9 +863,7 @@ struct cmap
+ CmapSubtableFormat12::get_sub_table_size (this->format12_groups);
}
- // Format 4
hb_vector_t format4_segments;
- // Format 12
hb_vector_t format12_groups;
};
diff --git a/src/hb-ot-color-cbdt-table.hh b/src/hb-ot-color-cbdt-table.hh
index 1e1fe0956..614cc80ce 100644
--- a/src/hb-ot-color-cbdt-table.hh
+++ b/src/hb-ot-color-cbdt-table.hh
@@ -166,7 +166,7 @@ struct IndexSubtable
}
}
- inline bool get_extents (hb_glyph_extents_t *extents) const
+ inline bool get_extents (hb_glyph_extents_t *extents HB_UNUSED) const
{
switch (u.header.indexFormat) {
case 2: case 5: /* TODO */
@@ -343,26 +343,30 @@ struct CBLC
}
protected:
- const IndexSubtableRecord *find_table (hb_codepoint_t glyph,
- unsigned int *x_ppem, unsigned int *y_ppem,
- const void **base) const
+ const BitmapSizeTable &choose_strike (hb_font_t *font) const
{
- /* TODO: Make it possible to select strike. */
+ unsigned count = sizeTables.len;
+ if (unlikely (!count))
+ return Null(BitmapSizeTable);
- unsigned int count = sizeTables.len;
- for (uint32_t i = 0; i < count; ++i)
+ unsigned int requested_ppem = MAX (font->x_ppem, font->y_ppem);
+ if (!requested_ppem)
+ requested_ppem = 1<<30; /* Choose largest strike. */
+ unsigned int best_i = 0;
+ unsigned int best_ppem = MAX (sizeTables[0].ppemX, sizeTables[0].ppemY);
+
+ for (unsigned int i = 1; i < count; i++)
{
- unsigned int startGlyphIndex = sizeTables.arrayZ[i].startGlyphIndex;
- unsigned int endGlyphIndex = sizeTables.arrayZ[i].endGlyphIndex;
- if (startGlyphIndex <= glyph && glyph <= endGlyphIndex)
+ unsigned int ppem = MAX (sizeTables[i].ppemX, sizeTables[i].ppemY);
+ if ((requested_ppem <= ppem && ppem < best_ppem) ||
+ (requested_ppem > best_ppem && ppem > best_ppem))
{
- *x_ppem = sizeTables[i].ppemX;
- *y_ppem = sizeTables[i].ppemY;
- return sizeTables[i].find_table (glyph, this, base);
+ best_i = i;
+ best_ppem = ppem;
}
}
- return nullptr;
+ return sizeTables[best_i];
}
protected:
@@ -376,13 +380,6 @@ struct CBDT
{
static const hb_tag_t tableTag = HB_OT_TAG_CBDT;
- inline bool sanitize (hb_sanitize_context_t *c) const
- {
- TRACE_SANITIZE (this);
- return_trace (c->check_struct (this) &&
- likely (version.major == 2 || version.major == 3));
- }
-
struct accelerator_t
{
inline void init (hb_face_t *face)
@@ -409,16 +406,16 @@ struct CBDT
hb_blob_destroy (this->cbdt_blob);
}
- inline bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
+ inline bool get_extents (hb_font_t *font, hb_codepoint_t glyph,
+ hb_glyph_extents_t *extents) const
{
- unsigned int x_ppem = upem, y_ppem = upem; /* TODO Use font ppem if available. */
-
if (!cblc)
- return false; // Not a color bitmap font.
+ return false;
const void *base;
- const IndexSubtableRecord *subtable_record = this->cblc->find_table (glyph, &x_ppem, &y_ppem, &base);
- if (!subtable_record || !x_ppem || !y_ppem)
+ const BitmapSizeTable &strike = this->cblc->choose_strike (font);
+ const IndexSubtableRecord *subtable_record = strike.find_table (glyph, cblc, &base);
+ if (!subtable_record || !strike.ppemX || !strike.ppemY)
return false;
if (subtable_record->get_extents (extents, base))
@@ -437,80 +434,94 @@ struct CBDT
case 17: {
if (unlikely (image_length < GlyphBitmapDataFormat17::min_size))
return false;
-
const GlyphBitmapDataFormat17& glyphFormat17 =
StructAtOffset