Compare commits
1 Commits
main
...
coverage-c
Author | SHA1 | Date |
---|---|---|
Behdad Esfahbod | 1ec0f58297 |
|
@ -2,7 +2,7 @@
|
|||
set -e
|
||||
|
||||
meson --cross-file=.ci/win32-cross-file.txt \
|
||||
--wrap-mode=default \
|
||||
--wrap-mode=forcefallback \
|
||||
-Dtests=disabled \
|
||||
-Dcairo=enabled \
|
||||
-Dcairo:fontconfig=disabled \
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
set -e
|
||||
|
||||
meson --cross-file=.ci/win64-cross-file.txt \
|
||||
--wrap-mode=default \
|
||||
--wrap-mode=forcefallback \
|
||||
-Dtests=disabled \
|
||||
-Dcairo=enabled \
|
||||
-Dcairo:fontconfig=disabled \
|
||||
|
|
|
@ -18,9 +18,9 @@ jobs:
|
|||
xcode: "12.5.1"
|
||||
steps:
|
||||
- checkout
|
||||
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config ragel freetype glib cairo python3 icu4c graphite2 gobject-introspection ninja
|
||||
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install pkg-config ragel freetype glib cairo python3 icu4c graphite2 gobject-introspection gtk-doc ninja
|
||||
- run: pip3 install meson --upgrade
|
||||
- run: PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/libffi/lib/pkgconfig" meson setup build -Dcoretext=enabled -Dgraphite=enabled -Dauto_features=enabled -Dchafa=disabled -Ddocs=disabled
|
||||
- run: PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:/usr/local/opt/libffi/lib/pkgconfig" meson setup build -Dcoretext=enabled -Dgraphite=enabled -Dauto_features=enabled -Dchafa=disabled
|
||||
- run: meson compile -Cbuild
|
||||
- run: meson test -Cbuild --print-errorlogs
|
||||
- store_artifacts:
|
||||
|
@ -123,7 +123,7 @@ jobs:
|
|||
executor: win32-executor
|
||||
steps:
|
||||
- checkout
|
||||
- run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build python3 python3-pip git g++-mingw-w64-i686 zip
|
||||
- run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build gtk-doc-tools python3 python3-pip git g++-mingw-w64-i686 zip
|
||||
- run: pip3 install meson==0.60.0
|
||||
- run: .ci/build-win32.sh
|
||||
- store_artifacts:
|
||||
|
@ -146,7 +146,7 @@ jobs:
|
|||
executor: win64-executor
|
||||
steps:
|
||||
- checkout
|
||||
- run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build python3 python3-pip git g++-mingw-w64-x86-64 zip
|
||||
- run: sudo apt update && DEBIAN_FRONTEND=noninteractive sudo apt install -y ninja-build gtk-doc-tools python3 python3-pip git g++-mingw-w64-x86-64 zip
|
||||
- run: pip3 install meson==0.60.0
|
||||
- run: bash .ci/build-win64.sh
|
||||
- store_artifacts:
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
comment: false
|
||||
comment: off
|
||||
|
||||
coverage:
|
||||
status:
|
||||
project:
|
||||
default:
|
||||
informational: true
|
||||
patch:
|
||||
default:
|
||||
informational: true
|
||||
threshold: 1%
|
||||
patch: off
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
name: CIFuzz
|
||||
on: [pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
Fuzzing:
|
||||
runs-on: ubuntu-latest
|
||||
|
|
|
@ -49,7 +49,6 @@ jobs:
|
|||
-Dgraphite=enabled \
|
||||
-Doptimization=2 \
|
||||
-Db_coverage=true \
|
||||
-Ddoc_tests=true \
|
||||
-Dragel_subproject=true
|
||||
- name: Build
|
||||
run: meson compile -Cbuild
|
||||
|
|
4
COPYING
4
COPYING
|
@ -12,13 +12,13 @@ Copyright © 2009 Keith Stribley
|
|||
Copyright © 2011 Martin Hosken and SIL International
|
||||
Copyright © 2007 Chris Wilson
|
||||
Copyright © 2005,2006,2020,2021,2022,2023 Behdad Esfahbod
|
||||
Copyright © 2005 David Turner
|
||||
Copyright © 2004,2007,2008,2009,2010,2013,2021,2022,2023 Red Hat, Inc.
|
||||
Copyright © 1998-2005 David Turner and Werner Lemberg
|
||||
Copyright © 1998-2004 David Turner and Werner Lemberg
|
||||
Copyright © 2016 Igalia S.L.
|
||||
Copyright © 2022 Matthias Clasen
|
||||
Copyright © 2018,2021 Khaled Hosny
|
||||
Copyright © 2018,2019,2020 Adobe, Inc
|
||||
Copyright © 2013-2015 Alexei Podtelezhnikov
|
||||
|
||||
For full copyright notices consult the individual files in the package.
|
||||
|
||||
|
|
146
NEWS
146
NEWS
|
@ -1,149 +1,3 @@
|
|||
Overview of changes leading to 7.1.0
|
||||
Friday, March 3, 2023
|
||||
====================================
|
||||
- New experimental hb_shape_justify() API that uses font variations to expand
|
||||
or shrink the text to a given advance. (Behdad Esfahbod)
|
||||
- Various build and bug fixes. (Behdad Esfahbod, Garret Rieger, Qunxin Liu)
|
||||
|
||||
- New API:
|
||||
+hb_font_set_variation()
|
||||
|
||||
Overview of changes leading to 7.0.1
|
||||
Monday, February 20, 2023
|
||||
====================================
|
||||
- Various build and bug fixes.
|
||||
|
||||
|
||||
Overview of changes leading to 7.0.0
|
||||
Saturday, February 11, 2023
|
||||
====================================
|
||||
- New hb-paint API that is designed mainly to paint “COLRv1” glyphs, but can be
|
||||
also used as a unified API to paint any of the glyph representations
|
||||
supported by HarfBuzz (B/W outlines, color layers, or color bitmaps).
|
||||
(Behdad Esfahbod, Matthias Clasen)
|
||||
- New hb-cairo API for integrating with cairo graphics library. This is provided
|
||||
as a separate harfbuzz-cairo library. (Behdad Esfahbod, Matthias Clasen)
|
||||
- Support for instancing “CFF2” table. (Behdad Esfahbod)
|
||||
- Support font emboldening. (Behdad Esfahbod)
|
||||
- Support feature ranges with AAT shaping. (Behdad Esfahbod)
|
||||
- Experimental support to cubic curves in “glyf” table, see
|
||||
https://github.com/harfbuzz/boring-expansion-spec/blob/main/glyf1-cubicOutlines.md
|
||||
for spec. (Behdad Esfahbod)
|
||||
- Various subsetter improvements. (Garret Rieger, Qunxin Liu, Behdad Esfahbod)
|
||||
- Various documentation improvements.
|
||||
(Behdad Esfahbod, Matthias Clasen, Khaled Hosny)
|
||||
- Significantly reduced memory use during shaping. (Behdad Esfahbod)
|
||||
- Greatly reduced memory use during subsetting “CFF” table. (Behdad Esfahbod)
|
||||
- New command line utility, hb-info, for querying various font information.
|
||||
(Behdad Esfahbod, Matthias Clasen)
|
||||
- New hb-shape/hb-view options: --glyphs, --color-palette, --font-bold,
|
||||
--font-grade, and --named-instance. (Behdad Esfahbod)
|
||||
- Miscellaneous fixes and improvements.
|
||||
(Amir Masoud Abdol, Andres Salomon, Behdad Esfahbod, Chun-wei Fan,
|
||||
Garret Rieger, Jens Kutilek, Khaled Hosny, Konstantin Käfer, Matthias Clasen,
|
||||
Nirbheek Chauhan, Pedro J. Estébanez, Qunxin Liu, Sergei Trofimovich)
|
||||
|
||||
- New API:
|
||||
+HB_FONT_NO_VAR_NAMED_INSTANCE
|
||||
+HB_PAINT_IMAGE_FORMAT_BGRA
|
||||
+HB_PAINT_IMAGE_FORMAT_PNG
|
||||
+HB_PAINT_IMAGE_FORMAT_SVG
|
||||
+hb_cairo_font_face_create_for_face
|
||||
+hb_cairo_font_face_create_for_font
|
||||
+hb_cairo_font_face_get_face
|
||||
+hb_cairo_font_face_get_font
|
||||
+hb_cairo_font_face_get_scale_factor
|
||||
+hb_cairo_font_face_set_font_init_func
|
||||
+hb_cairo_font_face_set_scale_factor
|
||||
+hb_cairo_font_init_func_t
|
||||
+hb_cairo_glyphs_from_buffer
|
||||
+hb_cairo_scaled_font_get_font
|
||||
+hb_color_line_get_color_stops
|
||||
+hb_color_line_get_color_stops_func_t
|
||||
+hb_color_line_get_extend
|
||||
+hb_color_line_get_extend_func_t
|
||||
+hb_color_line_t
|
||||
+hb_color_stop_t
|
||||
+hb_draw_funcs_get_empty
|
||||
+hb_draw_funcs_get_user_data
|
||||
+hb_draw_funcs_set_user_data
|
||||
+hb_face_collect_nominal_glyph_mapping
|
||||
+hb_font_draw_glyph
|
||||
+hb_font_draw_glyph_func_t
|
||||
+hb_font_funcs_set_draw_glyph_func
|
||||
+hb_font_funcs_set_paint_glyph_func
|
||||
+hb_font_get_synthetic_bold
|
||||
+hb_font_get_var_named_instance
|
||||
+hb_font_paint_glyph
|
||||
+hb_font_paint_glyph_func_t
|
||||
+hb_font_set_synthetic_bold
|
||||
+hb_map_keys
|
||||
+hb_map_next
|
||||
+hb_map_update
|
||||
+hb_map_values
|
||||
+hb_ot_color_glyph_has_paint
|
||||
+hb_ot_color_has_paint
|
||||
+hb_ot_layout_script_select_language2
|
||||
+hb_ot_name_id_predefined_t
|
||||
+hb_paint_color
|
||||
+hb_paint_color_func_t
|
||||
+hb_paint_composite_mode_t
|
||||
+hb_paint_custom_palette_color
|
||||
+hb_paint_custom_palette_color_func_t
|
||||
+hb_paint_extend_t
|
||||
+hb_paint_funcs_create
|
||||
+hb_paint_funcs_destroy
|
||||
+hb_paint_funcs_get_empty
|
||||
+hb_paint_funcs_get_user_data
|
||||
+hb_paint_funcs_is_immutable
|
||||
+hb_paint_funcs_make_immutable
|
||||
+hb_paint_funcs_reference
|
||||
+hb_paint_funcs_set_color_func
|
||||
+hb_paint_funcs_set_custom_palette_color_func
|
||||
+hb_paint_funcs_set_image_func
|
||||
+hb_paint_funcs_set_linear_gradient_func
|
||||
+hb_paint_funcs_set_pop_clip_func
|
||||
+hb_paint_funcs_set_pop_group_func
|
||||
+hb_paint_funcs_set_pop_transform_func
|
||||
+hb_paint_funcs_set_push_clip_glyph_func
|
||||
+hb_paint_funcs_set_push_clip_rectangle_func
|
||||
+hb_paint_funcs_set_push_group_func
|
||||
+hb_paint_funcs_set_push_transform_func
|
||||
+hb_paint_funcs_set_radial_gradient_func
|
||||
+hb_paint_funcs_set_sweep_gradient_func
|
||||
+hb_paint_funcs_set_user_data
|
||||
+hb_paint_funcs_t
|
||||
+hb_paint_image
|
||||
+hb_paint_image_func_t
|
||||
+hb_paint_linear_gradient
|
||||
+hb_paint_linear_gradient_func_t
|
||||
+hb_paint_pop_clip
|
||||
+hb_paint_pop_clip_func_t
|
||||
+hb_paint_pop_group
|
||||
+hb_paint_pop_group_func_t
|
||||
+hb_paint_pop_transform
|
||||
+hb_paint_pop_transform_func_t
|
||||
+hb_paint_push_clip_glyph
|
||||
+hb_paint_push_clip_glyph_func_t
|
||||
+hb_paint_push_clip_rectangle
|
||||
+hb_paint_push_clip_rectangle_func_t
|
||||
+hb_paint_push_group
|
||||
+hb_paint_push_group_func_t
|
||||
+hb_paint_push_transform
|
||||
+hb_paint_push_transform_func_t
|
||||
+hb_paint_radial_gradient
|
||||
+hb_paint_radial_gradient_func_t
|
||||
+hb_paint_sweep_gradient
|
||||
+hb_paint_sweep_gradient_func_t
|
||||
+hb_set_is_inverted
|
||||
+hb_subset_input_keep_everything
|
||||
|
||||
- Deprecated API:
|
||||
+hb_font_funcs_set_glyph_shape_func
|
||||
+hb_font_get_glyph_shape_func_t
|
||||
+hb_font_get_glyph_shape
|
||||
|
||||
|
||||
Overview of changes leading to 6.0.0
|
||||
Friday, December 16, 2022
|
||||
====================================
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
- [ ] Based on severity of changes, decide whether it's a minor or micro release number bump.
|
||||
|
||||
- [ ] Search for 'XSince: REPLACEME' on the repository and replace it with the chosen version for the release, e.g. 'Since: 1.4.7'.
|
||||
- [ ] Search for REPLACEME on the repository and replace it with the chosen version for the release.
|
||||
|
||||
- [ ] Make sure you have correct date and new version at the top of NEWS file.
|
||||
|
||||
|
|
20
SECURITY.md
20
SECURITY.md
|
@ -1,20 +0,0 @@
|
|||
# Security Policy
|
||||
|
||||
If you have discovered a security vulnerability in this project, please report it
|
||||
privately. **Do not disclose it as a public issue.** This gives me time to work with you
|
||||
to fix the issue before public exposure, reducing the chance that the exploit will be
|
||||
used before a patch is released.
|
||||
|
||||
You may submit the report in the following ways:
|
||||
|
||||
- send an email to behdad@behdad.org and harfbuzz-admin@googlegroups.com; and/or
|
||||
- send me a [private vulnerability report](https://github.com/harfbuzz/harfbuzz/security/advisories/new)
|
||||
|
||||
Please provide the following information in your report:
|
||||
|
||||
- A description of the vulnerability and its impact
|
||||
- How to reproduce the issue
|
||||
|
||||
This project is mostly maintained by two developers, working on a reasonable effort
|
||||
basis. As such, we ask that you give us 90 days to work on a fix before public
|
||||
disclosure.
|
|
@ -1,6 +1,6 @@
|
|||
AC_PREREQ([2.64])
|
||||
AC_INIT([HarfBuzz],
|
||||
[7.1.0],
|
||||
[6.0.0],
|
||||
[https://github.com/harfbuzz/harfbuzz/issues/new],
|
||||
[harfbuzz],
|
||||
[http://harfbuzz.org/])
|
||||
|
|
|
@ -120,8 +120,6 @@
|
|||
<index id="api-index-full"><title>API Index</title><xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="deprecated-api-index"><title>Index of deprecated API</title><xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include></index>
|
||||
|
||||
<index id="api-index-7-1-0"><title>Index of new symbols in 7.1.0</title><xi:include href="xml/api-index-7.1.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-7-0-0"><title>Index of new symbols in 7.0.0</title><xi:include href="xml/api-index-7.0.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-6-0-0"><title>Index of new symbols in 6.0.0</title><xi:include href="xml/api-index-6.0.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-5-3-0"><title>Index of new symbols in 5.3.0</title><xi:include href="xml/api-index-5.3.0.xml"><xi:fallback /></xi:include></index>
|
||||
<index id="api-index-5-0-0"><title>Index of new symbols in 5.0.0</title><xi:include href="xml/api-index-5.0.0.xml"><xi:fallback /></xi:include></index>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
<SECTION>
|
||||
<SUBSECTION Private>
|
||||
HB_H_IN
|
||||
HB_OT_H_IN
|
||||
|
@ -417,12 +416,9 @@ hb_font_set_ptem
|
|||
hb_font_get_ptem
|
||||
hb_font_set_scale
|
||||
hb_font_get_scale
|
||||
hb_font_get_synthetic_bold
|
||||
hb_font_set_synthetic_bold
|
||||
hb_font_set_synthetic_slant
|
||||
hb_font_get_synthetic_slant
|
||||
hb_font_set_variations
|
||||
hb_font_set_variation
|
||||
HB_FONT_NO_VAR_NAMED_INSTANCE
|
||||
hb_font_set_var_named_instance
|
||||
hb_font_get_var_named_instance
|
||||
|
@ -781,7 +777,6 @@ hb_set_t
|
|||
<FILE>hb-shape</FILE>
|
||||
hb_shape
|
||||
hb_shape_full
|
||||
hb_shape_justify
|
||||
hb_shape_list_shapers
|
||||
</SECTION>
|
||||
|
||||
|
|
|
@ -59,6 +59,4 @@ gnome.gtkdoc('harfbuzz',
|
|||
html_assets: html_images,
|
||||
ignore_headers: ignore_headers,
|
||||
dependencies: [libharfbuzz_dep],
|
||||
install: true,
|
||||
check: get_option('doc_tests'),
|
||||
)
|
||||
install: true)
|
||||
|
|
|
@ -182,7 +182,8 @@
|
|||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><emphasis>Level 0</emphasis> is the default.
|
||||
<para><emphasis>Level 0</emphasis> is the default and
|
||||
reproduces the behavior of the old HarfBuzz library.
|
||||
</para>
|
||||
<para>
|
||||
The distinguishing feature of level 0 behavior is that, at
|
||||
|
@ -193,7 +194,7 @@
|
|||
as well as the <emphasis>Zero Width Joiner</emphasis> and
|
||||
<emphasis>Zero Width Non-Joiner</emphasis> code points, are
|
||||
assigned the cluster value of the closest preceding code
|
||||
point from <emphasis>different</emphasis> category.
|
||||
point from <emphasis>different</emphasis> category.
|
||||
</para>
|
||||
<para>
|
||||
In essence, whenever a base character is followed by a mark
|
||||
|
@ -205,11 +206,6 @@
|
|||
url="https://www.unicode.org/reports/tr29/#Regex_Definitions">Unicode
|
||||
Technical Report 29</ulink>.
|
||||
</para>
|
||||
<para>
|
||||
This cluster level is suitable for code that likes to use
|
||||
HarfBuzz cluster values as an approximation of the Unicode
|
||||
Grapheme Cluster Boundaries as well.
|
||||
</para>
|
||||
<para>
|
||||
Client programs can specify level 0 behavior for a buffer by
|
||||
setting its <literal>cluster_level</literal> to
|
||||
|
@ -224,13 +220,13 @@
|
|||
implement backward compatibility with the old HarfBuzz.
|
||||
</para>
|
||||
<para>
|
||||
<emphasis>Level 1</emphasis> differs from level 0 by not merging the
|
||||
Level 1 differs from level 0 by not merging the
|
||||
clusters of marks and other modifier code points with the
|
||||
preceding "base" code point's cluster. By preserving the
|
||||
separate cluster values of these marks and modifier code
|
||||
points, script shapers can perform additional operations
|
||||
that might lead to improved results (for example, coloring
|
||||
mark glyphs differently than their base).
|
||||
that might lead to improved results (for example, reordering
|
||||
a sequence of marks).
|
||||
</para>
|
||||
<para>
|
||||
Client programs can specify level 1 behavior for a buffer by
|
||||
|
@ -246,7 +242,7 @@
|
|||
</para>
|
||||
<para>
|
||||
This difference can be seen most clearly when HarfBuzz processes
|
||||
ligature substitutions and glyph decompositions. In level 0
|
||||
ligature substitutions and glyph decompositions. In level 0
|
||||
and level 1, ligatures and glyph decomposition both involve
|
||||
merging clusters; in level 2, neither of these operations
|
||||
triggers a merge.
|
||||
|
@ -263,7 +259,7 @@
|
|||
assign initial cluster values in a buffer by reusing the indices
|
||||
of the code points in the input text. This gives a sequence of
|
||||
cluster values that is monotonically increasing (for example,
|
||||
0,1,2,3,4).
|
||||
0,1,2,3,4).
|
||||
</para>
|
||||
<para>
|
||||
It is not <emphasis>required</emphasis> that the cluster values
|
||||
|
@ -318,7 +314,7 @@
|
|||
</listitem>
|
||||
</itemizedlist>
|
||||
</section>
|
||||
|
||||
|
||||
<section id="a-clustering-example-for-levels-0-and-1">
|
||||
<title>A clustering example for levels 0 and 1</title>
|
||||
<para>
|
||||
|
|
|
@ -473,7 +473,7 @@
|
|||
</para>
|
||||
</section>
|
||||
|
||||
<section id="glyphs-and-rendering">
|
||||
<section>
|
||||
<title>Glyphs and rendering</title>
|
||||
|
||||
<para>
|
||||
|
|
|
@ -174,9 +174,7 @@
|
|||
<para>
|
||||
HarfBuzz provides integration points with FreeType at the
|
||||
face-object and font-object level and for the font-functions
|
||||
virtual-method structure of a font object. These functions
|
||||
make it easy for clients that use FreeType for rasterization
|
||||
or font-loading, to use HarfBuzz for shaping. To use the
|
||||
virtual-method structure of a font object. To use the
|
||||
FreeType-integration API, include the
|
||||
<filename>hb-ft.h</filename> header.
|
||||
</para>
|
||||
|
|
10
meson.build
10
meson.build
|
@ -1,6 +1,6 @@
|
|||
project('harfbuzz', 'c', 'cpp',
|
||||
meson_version: '>= 0.55.0',
|
||||
version: '7.1.0',
|
||||
version: '6.0.0',
|
||||
default_options: [
|
||||
'cpp_eh=none', # Just to support msvc, we are passing -fno-exceptions also anyway
|
||||
'cpp_rtti=false', # Just to support msvc, we are passing -fno-rtti also anyway
|
||||
|
@ -373,10 +373,7 @@ foreach check : check_funcs
|
|||
endforeach
|
||||
|
||||
subdir('src')
|
||||
|
||||
if not get_option('utilities').disabled()
|
||||
subdir('util')
|
||||
endif
|
||||
subdir('util')
|
||||
|
||||
if not get_option('tests').disabled()
|
||||
subdir('test')
|
||||
|
@ -392,9 +389,6 @@ endif
|
|||
|
||||
configure_file(output: 'config.h', configuration: conf)
|
||||
|
||||
alias_target('lib', libharfbuzz)
|
||||
alias_target('libs', libharfbuzz, libharfbuzz_subset)
|
||||
|
||||
build_summary = {
|
||||
'Directories':
|
||||
{'prefix': get_option('prefix'),
|
||||
|
|
|
@ -29,10 +29,6 @@ option('introspection', type: 'feature', value: 'auto', yield: true,
|
|||
description: 'Generate gobject-introspection bindings (.gir/.typelib files)')
|
||||
option('docs', type: 'feature', value: 'auto', yield: true,
|
||||
description: 'Generate documentation with gtk-doc')
|
||||
option('doc_tests', type: 'boolean', value: false,
|
||||
description: 'Run gtkdoc-check tests')
|
||||
option('utilities', type: 'feature', value: 'enabled', yield: true,
|
||||
description: 'Build harfbuzz utils')
|
||||
|
||||
option('benchmark', type: 'feature', value: 'disabled',
|
||||
description: 'Enable benchmark tests')
|
||||
|
|
|
@ -382,7 +382,6 @@ noinst_PROGRAMS = \
|
|||
test-ot-name \
|
||||
test-ot-glyphname \
|
||||
test-gpos-size-params \
|
||||
test-gsub-get-alternates \
|
||||
test-gsub-would-substitute \
|
||||
test-use-table \
|
||||
$(NULL)
|
||||
|
@ -420,10 +419,6 @@ test_gpos_size_params_SOURCES = test-gpos-size-params.cc
|
|||
test_gpos_size_params_CPPFLAGS = $(HBCFLAGS)
|
||||
test_gpos_size_params_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
|
||||
test_gsub_get_alternates_SOURCES = test-gsub-get-alternates.cc
|
||||
test_gsub_get_alternates_CPPFLAGS = $(HBCFLAGS)
|
||||
test_gsub_get_alternates_LDADD = libharfbuzz.la $(HBLIBS)
|
||||
|
||||
test_gsub_would_substitute_SOURCES = test-gsub-would-substitute.cc
|
||||
test_gsub_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
|
||||
test_gsub_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
|
||||
|
|
|
@ -85,8 +85,6 @@ HB_BASE_sources = \
|
|||
hb-ot-layout-common.hh \
|
||||
hb-ot-layout-gdef-table.hh \
|
||||
hb-ot-layout-gpos-table.hh \
|
||||
hb-outline.hh \
|
||||
hb-outline.cc \
|
||||
hb-paint.cc \
|
||||
hb-paint.hh \
|
||||
hb-paint-extents.cc \
|
||||
|
@ -225,7 +223,6 @@ HB_BASE_sources = \
|
|||
hb-ot-tag.cc \
|
||||
hb-ot-var-avar-table.hh \
|
||||
hb-ot-var-common.hh \
|
||||
hb-ot-var-cvar-table.hh \
|
||||
hb-ot-var-fvar-table.hh \
|
||||
hb-ot-var-gvar-table.hh \
|
||||
hb-ot-var-hvar-table.hh \
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
*/
|
||||
#define HB_OT_TAG_COLR HB_TAG('C','O','L','R')
|
||||
|
||||
|
||||
namespace OT {
|
||||
struct hb_paint_context_t;
|
||||
}
|
||||
|
@ -241,15 +242,10 @@ struct Variable
|
|||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ value.closurev1 (c); }
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
if (!value.subset (c, instancer, varIdxBase)) return_trace (false);
|
||||
if (c->plan->all_axes_pinned)
|
||||
return_trace (true);
|
||||
|
||||
//TODO: update varIdxBase for partial-instancing
|
||||
if (!value.subset (c)) return_trace (false);
|
||||
return_trace (c->serializer->embed (varIdxBase));
|
||||
}
|
||||
|
||||
|
@ -300,11 +296,10 @@ struct NoVariable
|
|||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ value.closurev1 (c); }
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
return_trace (value.subset (c, instancer, varIdxBase));
|
||||
return_trace (value.subset (c));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -342,20 +337,11 @@ struct ColorStop
|
|||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ c->add_palette_index (paletteIndex); }
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer,
|
||||
uint32_t varIdxBase) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (*this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
|
||||
{
|
||||
out->stopOffset.set_float (stopOffset.to_float(instancer (varIdxBase, 0)));
|
||||
out->alpha.set_float (alpha.to_float (instancer (varIdxBase, 1)));
|
||||
}
|
||||
|
||||
return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes.get (paletteIndex),
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
}
|
||||
|
@ -404,8 +390,7 @@ struct ColorLine
|
|||
stop.closurev1 (c);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (this);
|
||||
|
@ -417,7 +402,7 @@ struct ColorLine
|
|||
|
||||
for (const auto& stop : stops.iter ())
|
||||
{
|
||||
if (!stop.subset (c, instancer)) return_trace (false);
|
||||
if (!stop.subset (c)) return_trace (false);
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
@ -538,25 +523,6 @@ struct Affine2x3
|
|||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer,
|
||||
uint32_t varIdxBase) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (*this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
|
||||
{
|
||||
out->xx.set_float (xx.to_float(instancer (varIdxBase, 0)));
|
||||
out->yx.set_float (yx.to_float(instancer (varIdxBase, 1)));
|
||||
out->xy.set_float (xy.to_float(instancer (varIdxBase, 2)));
|
||||
out->yy.set_float (yy.to_float(instancer (varIdxBase, 3)));
|
||||
out->dx.set_float (dx.to_float(instancer (varIdxBase, 4)));
|
||||
out->dy.set_float (dy.to_float(instancer (varIdxBase, 5)));
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
||||
{
|
||||
c->funcs->push_transform (c->data,
|
||||
|
@ -582,8 +548,7 @@ struct PaintColrLayers
|
|||
{
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer HB_UNUSED) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
|
@ -614,20 +579,11 @@ struct PaintSolid
|
|||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ c->add_palette_index (paletteIndex); }
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer,
|
||||
uint32_t varIdxBase) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (*this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
|
||||
out->alpha.set_float (alpha.to_float (instancer (varIdxBase, 0)));
|
||||
|
||||
if (format == 3 && c->plan->all_axes_pinned)
|
||||
out->format = 2;
|
||||
|
||||
return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes.get (paletteIndex),
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
}
|
||||
|
@ -662,28 +618,13 @@ struct PaintLinearGradient
|
|||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ (this+colorLine).closurev1 (c); }
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer,
|
||||
uint32_t varIdxBase) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
|
||||
{
|
||||
out->x0 = x0 + (int) roundf (instancer (varIdxBase, 0));
|
||||
out->y0 = y0 + (int) roundf (instancer (varIdxBase, 1));
|
||||
out->x1 = x1 + (int) roundf (instancer (varIdxBase, 2));
|
||||
out->y1 = y1 + (int) roundf (instancer (varIdxBase, 3));
|
||||
out->x2 = x2 + (int) roundf (instancer (varIdxBase, 4));
|
||||
out->y2 = y2 + (int) roundf (instancer (varIdxBase, 5));
|
||||
}
|
||||
|
||||
if (format == 5 && c->plan->all_axes_pinned)
|
||||
out->format = 4;
|
||||
|
||||
return_trace (out->colorLine.serialize_subset (c, colorLine, this, instancer));
|
||||
return_trace (out->colorLine.serialize_subset (c, colorLine, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -728,28 +669,13 @@ struct PaintRadialGradient
|
|||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ (this+colorLine).closurev1 (c); }
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer,
|
||||
uint32_t varIdxBase) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
|
||||
{
|
||||
out->x0 = x0 + (int) roundf (instancer (varIdxBase, 0));
|
||||
out->y0 = y0 + (int) roundf (instancer (varIdxBase, 1));
|
||||
out->radius0 = radius0 + (unsigned) roundf (instancer (varIdxBase, 2));
|
||||
out->x1 = x1 + (int) roundf (instancer (varIdxBase, 3));
|
||||
out->y1 = y1 + (int) roundf (instancer (varIdxBase, 4));
|
||||
out->radius1 = radius1 + (unsigned) roundf (instancer (varIdxBase, 5));
|
||||
}
|
||||
|
||||
if (format == 7 && c->plan->all_axes_pinned)
|
||||
out->format = 6;
|
||||
|
||||
return_trace (out->colorLine.serialize_subset (c, colorLine, this, instancer));
|
||||
return_trace (out->colorLine.serialize_subset (c, colorLine, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -794,26 +720,13 @@ struct PaintSweepGradient
|
|||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||
{ (this+colorLine).closurev1 (c); }
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer,
|
||||
uint32_t varIdxBase) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
|
||||
{
|
||||
out->centerX = centerX + (int) roundf (instancer (varIdxBase, 0));
|
||||
out->centerY = centerY + (int) roundf (instancer (varIdxBase, 1));
|
||||
out->startAngle.set_float (startAngle.to_float (instancer (varIdxBase, 2)));
|
||||
out->endAngle.set_float (endAngle.to_float (instancer (varIdxBase, 3)));
|
||||
}
|
||||
|
||||
if (format == 9 && c->plan->all_axes_pinned)
|
||||
out->format = 8;
|
||||
|
||||
return_trace (out->colorLine.serialize_subset (c, colorLine, this, instancer));
|
||||
return_trace (out->colorLine.serialize_subset (c, colorLine, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -833,8 +746,8 @@ struct PaintSweepGradient
|
|||
c->funcs->sweep_gradient (c->data, &cl,
|
||||
centerX + c->instancer (varIdxBase, 0),
|
||||
centerY + c->instancer (varIdxBase, 1),
|
||||
(startAngle.to_float (c->instancer (varIdxBase, 2)) + 1) * HB_PI,
|
||||
(endAngle.to_float (c->instancer (varIdxBase, 3)) + 1) * HB_PI);
|
||||
(startAngle.to_float (c->instancer (varIdxBase, 2)) + 1) * (float) M_PI,
|
||||
(endAngle.to_float (c->instancer (varIdxBase, 3)) + 1) * (float) M_PI);
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 8(noVar) or 9 (Var) */
|
||||
|
@ -853,8 +766,7 @@ struct PaintGlyph
|
|||
{
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
|
@ -864,7 +776,7 @@ struct PaintGlyph
|
|||
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (out->paint.serialize_subset (c, paint, this, instancer));
|
||||
return_trace (out->paint.serialize_subset (c, paint, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -895,8 +807,7 @@ struct PaintColrGlyph
|
|||
{
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer HB_UNUSED) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
|
@ -925,16 +836,13 @@ struct PaintTransform
|
|||
{
|
||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
if (!out->transform.serialize_subset (c, transform, this, instancer)) return_trace (false);
|
||||
if (format == 13 && c->plan->all_axes_pinned)
|
||||
out->format = 12;
|
||||
return_trace (out->src.serialize_subset (c, src, this, instancer));
|
||||
if (!out->transform.serialize_copy (c->serializer, transform, this)) return_trace (false);
|
||||
return_trace (out->src.serialize_subset (c, src, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -963,24 +871,13 @@ struct PaintTranslate
|
|||
{
|
||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer,
|
||||
uint32_t varIdxBase) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
|
||||
{
|
||||
out->dx = dx + (int) roundf (instancer (varIdxBase, 0));
|
||||
out->dy = dy + (int) roundf (instancer (varIdxBase, 1));
|
||||
}
|
||||
|
||||
if (format == 15 && c->plan->all_axes_pinned)
|
||||
out->format = 14;
|
||||
|
||||
return_trace (out->src.serialize_subset (c, src, this, instancer));
|
||||
return_trace (out->src.serialize_subset (c, src, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -1011,24 +908,13 @@ struct PaintScale
|
|||
{
|
||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer,
|
||||
uint32_t varIdxBase) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
|
||||
{
|
||||
out->scaleX.set_float (scaleX.to_float (instancer (varIdxBase, 0)));
|
||||
out->scaleY.set_float (scaleY.to_float (instancer (varIdxBase, 1)));
|
||||
}
|
||||
|
||||
if (format == 17 && c->plan->all_axes_pinned)
|
||||
out->format = 16;
|
||||
|
||||
return_trace (out->src.serialize_subset (c, src, this, instancer));
|
||||
return_trace (out->src.serialize_subset (c, src, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -1059,26 +945,13 @@ struct PaintScaleAroundCenter
|
|||
{
|
||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer,
|
||||
uint32_t varIdxBase) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
|
||||
{
|
||||
out->scaleX.set_float (scaleX.to_float (instancer (varIdxBase, 0)));
|
||||
out->scaleY.set_float (scaleY.to_float (instancer (varIdxBase, 1)));
|
||||
out->centerX = centerX + (int) roundf (instancer (varIdxBase, 2));
|
||||
out->centerY = centerY + (int) roundf (instancer (varIdxBase, 3));
|
||||
}
|
||||
|
||||
if (format == 19 && c->plan->all_axes_pinned)
|
||||
out->format = 18;
|
||||
|
||||
return_trace (out->src.serialize_subset (c, src, this, instancer));
|
||||
return_trace (out->src.serialize_subset (c, src, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -1117,21 +990,13 @@ struct PaintScaleUniform
|
|||
{
|
||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer,
|
||||
uint32_t varIdxBase) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
|
||||
out->scale.set_float (scale.to_float (instancer (varIdxBase, 0)));
|
||||
|
||||
if (format == 21 && c->plan->all_axes_pinned)
|
||||
out->format = 20;
|
||||
|
||||
return_trace (out->src.serialize_subset (c, src, this, instancer));
|
||||
return_trace (out->src.serialize_subset (c, src, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -1160,25 +1025,13 @@ struct PaintScaleUniformAroundCenter
|
|||
{
|
||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer,
|
||||
uint32_t varIdxBase) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
|
||||
{
|
||||
out->scale.set_float (scale.to_float (instancer (varIdxBase, 0)));
|
||||
out->centerX = centerX + (int) roundf (instancer (varIdxBase, 1));
|
||||
out->centerY = centerY + (int) roundf (instancer (varIdxBase, 2));
|
||||
}
|
||||
|
||||
if (format == 23 && c->plan->all_axes_pinned)
|
||||
out->format = 22;
|
||||
|
||||
return_trace (out->src.serialize_subset (c, src, this, instancer));
|
||||
return_trace (out->src.serialize_subset (c, src, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -1215,21 +1068,13 @@ struct PaintRotate
|
|||
{
|
||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer,
|
||||
uint32_t varIdxBase) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
|
||||
out->angle.set_float (angle.to_float (instancer (varIdxBase, 0)));
|
||||
|
||||
if (format == 25 && c->plan->all_axes_pinned)
|
||||
out->format = 24;
|
||||
|
||||
return_trace (out->src.serialize_subset (c, src, this, instancer));
|
||||
return_trace (out->src.serialize_subset (c, src, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -1258,25 +1103,13 @@ struct PaintRotateAroundCenter
|
|||
{
|
||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer,
|
||||
uint32_t varIdxBase) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
|
||||
{
|
||||
out->angle.set_float (angle.to_float (instancer (varIdxBase, 0)));
|
||||
out->centerX = centerX + (int) roundf (instancer (varIdxBase, 1));
|
||||
out->centerY = centerY + (int) roundf (instancer (varIdxBase, 2));
|
||||
}
|
||||
|
||||
if (format ==27 && c->plan->all_axes_pinned)
|
||||
out->format = 26;
|
||||
|
||||
return_trace (out->src.serialize_subset (c, src, this, instancer));
|
||||
return_trace (out->src.serialize_subset (c, src, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -1313,24 +1146,13 @@ struct PaintSkew
|
|||
{
|
||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer,
|
||||
uint32_t varIdxBase) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
|
||||
{
|
||||
out->xSkewAngle.set_float (xSkewAngle.to_float (instancer (varIdxBase, 0)));
|
||||
out->ySkewAngle.set_float (ySkewAngle.to_float (instancer (varIdxBase, 1)));
|
||||
}
|
||||
|
||||
if (format == 29 && c->plan->all_axes_pinned)
|
||||
out->format = 28;
|
||||
|
||||
return_trace (out->src.serialize_subset (c, src, this, instancer));
|
||||
return_trace (out->src.serialize_subset (c, src, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -1361,26 +1183,13 @@ struct PaintSkewAroundCenter
|
|||
{
|
||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer,
|
||||
uint32_t varIdxBase) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
|
||||
{
|
||||
out->xSkewAngle.set_float (xSkewAngle.to_float (instancer (varIdxBase, 0)));
|
||||
out->ySkewAngle.set_float (ySkewAngle.to_float (instancer (varIdxBase, 1)));
|
||||
out->centerX = centerX + (int) roundf (instancer (varIdxBase, 2));
|
||||
out->centerY = centerY + (int) roundf (instancer (varIdxBase, 3));
|
||||
}
|
||||
|
||||
if (format == 31 && c->plan->all_axes_pinned)
|
||||
out->format = 30;
|
||||
|
||||
return_trace (out->src.serialize_subset (c, src, this, instancer));
|
||||
return_trace (out->src.serialize_subset (c, src, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -1419,15 +1228,14 @@ struct PaintComposite
|
|||
{
|
||||
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (!out->src.serialize_subset (c, src, this, instancer)) return_trace (false);
|
||||
return_trace (out->backdrop.serialize_subset (c, backdrop, this, instancer));
|
||||
if (!out->src.serialize_subset (c, src, this)) return_trace (false);
|
||||
return_trace (out->backdrop.serialize_subset (c, backdrop, this));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
@ -1475,28 +1283,6 @@ struct ClipBoxFormat1
|
|||
clip_box.yMax = yMax;
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer,
|
||||
uint32_t varIdxBase) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (*this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (instancer && !c->plan->pinned_at_default && varIdxBase != VarIdx::NO_VARIATION)
|
||||
{
|
||||
out->xMin = xMin + (int) roundf (instancer (varIdxBase, 0));
|
||||
out->yMin = yMin + (int) roundf (instancer (varIdxBase, 1));
|
||||
out->xMax = xMax + (int) roundf (instancer (varIdxBase, 2));
|
||||
out->yMax = yMax + (int) roundf (instancer (varIdxBase, 3));
|
||||
}
|
||||
|
||||
if (format == 2 && c->plan->all_axes_pinned)
|
||||
out->format = 1;
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
public:
|
||||
HBUINT8 format; /* format = 1(noVar) or 2(Var)*/
|
||||
FWORD xMin;
|
||||
|
@ -1524,14 +1310,13 @@ struct ClipBoxFormat2 : Variable<ClipBoxFormat1>
|
|||
|
||||
struct ClipBox
|
||||
{
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer) const
|
||||
ClipBox* copy (hb_serialize_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
TRACE_SERIALIZE (this);
|
||||
switch (u.format) {
|
||||
case 1: return_trace (u.format1.subset (c, instancer, VarIdx::NO_VARIATION));
|
||||
case 2: return_trace (u.format2.subset (c, instancer));
|
||||
default:return_trace (c->default_return_value ());
|
||||
case 1: return_trace (reinterpret_cast<ClipBox *> (c->embed (u.format1)));
|
||||
case 2: return_trace (reinterpret_cast<ClipBox *> (c->embed (u.format2)));
|
||||
default:return_trace (nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1582,15 +1367,13 @@ struct ClipRecord
|
|||
int cmp (hb_codepoint_t g) const
|
||||
{ return g < startGlyphID ? -1 : g <= endGlyphID ? 0 : +1; }
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const void *base,
|
||||
const VarStoreInstancer &instancer) const
|
||||
ClipRecord* copy (hb_serialize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (*this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
return_trace (out->clipBox.serialize_subset (c, clipBox, base, instancer));
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = c->embed (this);
|
||||
if (unlikely (!out)) return_trace (nullptr);
|
||||
if (!out->clipBox.serialize_copy (c, clipBox, base)) return_trace (nullptr);
|
||||
return_trace (out);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
|
@ -1617,8 +1400,7 @@ DECLARE_NULL_NAMESPACE_BYTES (OT, ClipRecord);
|
|||
|
||||
struct ClipList
|
||||
{
|
||||
unsigned serialize_clip_records (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer,
|
||||
unsigned serialize_clip_records (hb_serialize_context_t *c,
|
||||
const hb_set_t& gids,
|
||||
const hb_map_t& gid_offset_map) const
|
||||
{
|
||||
|
@ -1650,7 +1432,7 @@ struct ClipList
|
|||
record.endGlyphID = prev_gid;
|
||||
record.clipBox = prev_offset;
|
||||
|
||||
if (!record.subset (c, this, instancer)) return_trace (0);
|
||||
if (!c->copy (record, this)) return_trace (0);
|
||||
count++;
|
||||
|
||||
start_gid = _;
|
||||
|
@ -1664,14 +1446,13 @@ struct ClipList
|
|||
record.startGlyphID = start_gid;
|
||||
record.endGlyphID = prev_gid;
|
||||
record.clipBox = prev_offset;
|
||||
if (!record.subset (c, this, instancer)) return_trace (0);
|
||||
if (!c->copy (record, this)) return_trace (0);
|
||||
count++;
|
||||
}
|
||||
return_trace (count);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
|
@ -1696,7 +1477,7 @@ struct ClipList
|
|||
}
|
||||
}
|
||||
|
||||
unsigned count = serialize_clip_records (c, instancer, new_gids, new_gid_offset_map);
|
||||
unsigned count = serialize_clip_records (c->serializer, new_gids, new_gid_offset_map);
|
||||
if (!count) return_trace (false);
|
||||
return_trace (c->serializer->check_assign (out->clips.len, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
}
|
||||
|
@ -1830,8 +1611,7 @@ struct BaseGlyphPaintRecord
|
|||
{ return g < glyphId ? -1 : g > glyphId ? 1 : 0; }
|
||||
|
||||
bool serialize (hb_serialize_context_t *s, const hb_map_t* glyph_map,
|
||||
const void* src_base, hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer) const
|
||||
const void* src_base, hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
auto *out = s->embed (this);
|
||||
|
@ -1840,7 +1620,7 @@ struct BaseGlyphPaintRecord
|
|||
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (out->paint.serialize_subset (c, paint, src_base, instancer));
|
||||
return_trace (out->paint.serialize_subset (c, paint, src_base));
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
|
@ -1859,8 +1639,7 @@ struct BaseGlyphPaintRecord
|
|||
|
||||
struct BaseGlyphList : SortedArray32Of<BaseGlyphPaintRecord>
|
||||
{
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (this);
|
||||
|
@ -1872,7 +1651,7 @@ struct BaseGlyphList : SortedArray32Of<BaseGlyphPaintRecord>
|
|||
unsigned gid = _.glyphId;
|
||||
if (!glyphset->has (gid)) continue;
|
||||
|
||||
if (_.serialize (c->serializer, c->plan->glyph_map, this, c, instancer)) out->len++;
|
||||
if (_.serialize (c->serializer, c->plan->glyph_map, this, c)) out->len++;
|
||||
else return_trace (false);
|
||||
}
|
||||
|
||||
|
@ -1891,8 +1670,7 @@ struct LayerList : Array32OfOffset32To<Paint>
|
|||
const Paint& get_paint (unsigned i) const
|
||||
{ return this+(*this)[i]; }
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
const VarStoreInstancer &instancer) const
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (this);
|
||||
|
@ -1903,7 +1681,7 @@ struct LayerList : Array32OfOffset32To<Paint>
|
|||
|
||||
{
|
||||
auto *o = out->serialize_append (c->serializer);
|
||||
if (unlikely (!o) || !o->serialize_subset (c, _.second, this, instancer))
|
||||
if (unlikely (!o) || !o->serialize_subset (c, _.second, this))
|
||||
return_trace (false);
|
||||
}
|
||||
return_trace (true);
|
||||
|
@ -2105,6 +1883,7 @@ struct COLR
|
|||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
const hb_map_t &reverse_glyph_map = *c->plan->reverse_glyph_map;
|
||||
const hb_set_t& glyphset = c->plan->_glyphset_colred;
|
||||
|
||||
|
@ -2175,12 +1954,7 @@ struct COLR
|
|||
|
||||
auto snap = c->serializer->snapshot ();
|
||||
if (!c->serializer->allocate_size<void> (5 * HBUINT32::static_size)) return_trace (false);
|
||||
|
||||
VarStoreInstancer instancer (varStore ? &(this+varStore) : nullptr,
|
||||
varIdxMap ? &(this+varIdxMap) : nullptr,
|
||||
c->plan->normalized_coords.as_array ());
|
||||
|
||||
if (!colr_prime->baseGlyphList.serialize_subset (c, baseGlyphList, this, instancer))
|
||||
if (!colr_prime->baseGlyphList.serialize_subset (c, baseGlyphList, this))
|
||||
{
|
||||
if (c->serializer->in_error ()) return_trace (false);
|
||||
//no more COLRv1 glyphs: downgrade to version 0
|
||||
|
@ -2190,11 +1964,8 @@ struct COLR
|
|||
|
||||
if (!colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it)) return_trace (false);
|
||||
|
||||
colr_prime->layerList.serialize_subset (c, layerList, this, instancer);
|
||||
colr_prime->clipList.serialize_subset (c, clipList, this, instancer);
|
||||
if (!varStore || c->plan->all_axes_pinned)
|
||||
return_trace (true);
|
||||
|
||||
colr_prime->layerList.serialize_subset (c, layerList, this);
|
||||
colr_prime->clipList.serialize_subset (c, clipList, this);
|
||||
colr_prime->varIdxMap.serialize_copy (c->serializer, varIdxMap, this);
|
||||
colr_prime->varStore.serialize_copy (c->serializer, varStore, this);
|
||||
return_trace (true);
|
||||
|
@ -2213,15 +1984,14 @@ struct COLR
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
#ifndef HB_NO_PAINT
|
||||
bool
|
||||
get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
|
||||
{
|
||||
if (version != 1)
|
||||
return false;
|
||||
|
||||
VarStoreInstancer instancer (&(this+varStore),
|
||||
&(this+varIdxMap),
|
||||
VarStoreInstancer instancer (this+varStore,
|
||||
this+varIdxMap,
|
||||
hb_array (font->coords, font->num_coords));
|
||||
|
||||
if (get_clip (glyph, extents, instancer))
|
||||
|
@ -2252,7 +2022,6 @@ struct COLR
|
|||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
has_paint_for_glyph (hb_codepoint_t glyph) const
|
||||
|
@ -2276,12 +2045,11 @@ struct COLR
|
|||
instancer);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_PAINT
|
||||
bool
|
||||
paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, unsigned int palette_index, hb_color_t foreground, bool clip = true) const
|
||||
{
|
||||
VarStoreInstancer instancer (&(this+varStore),
|
||||
&(this+varIdxMap),
|
||||
VarStoreInstancer instancer (this+varStore,
|
||||
this+varIdxMap,
|
||||
hb_array (font->coords, font->num_coords));
|
||||
hb_paint_context_t c (this, funcs, data, font, palette_index, foreground, instancer);
|
||||
|
||||
|
@ -2292,8 +2060,8 @@ struct COLR
|
|||
{
|
||||
// COLRv1 glyph
|
||||
|
||||
VarStoreInstancer instancer (&(this+varStore),
|
||||
&(this+varIdxMap),
|
||||
VarStoreInstancer instancer (this+varStore,
|
||||
this+varIdxMap,
|
||||
hb_array (font->coords, font->num_coords));
|
||||
|
||||
bool is_bounded = true;
|
||||
|
@ -2363,7 +2131,6 @@ struct COLR
|
|||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
HBUINT16 version; /* Table version number (starts at 0). */
|
||||
|
|
|
@ -73,30 +73,6 @@ struct CPALV1Tail
|
|||
}
|
||||
|
||||
public:
|
||||
void collect_name_ids (const void *base,
|
||||
unsigned palette_count,
|
||||
unsigned color_count,
|
||||
const hb_map_t *color_index_map,
|
||||
hb_set_t *nameids_to_retain /* OUT */) const
|
||||
{
|
||||
if (paletteLabelsZ)
|
||||
{
|
||||
+ (base+paletteLabelsZ).as_array (palette_count)
|
||||
| hb_sink (nameids_to_retain)
|
||||
;
|
||||
}
|
||||
|
||||
if (colorLabelsZ)
|
||||
{
|
||||
const hb_array_t<const NameID> colorLabels = (base+colorLabelsZ).as_array (color_count);
|
||||
for (unsigned i = 0; i < color_count; i++)
|
||||
{
|
||||
if (!color_index_map->has (i)) continue;
|
||||
nameids_to_retain->add (colorLabels[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
unsigned palette_count,
|
||||
unsigned color_count,
|
||||
|
@ -119,10 +95,13 @@ struct CPALV1Tail
|
|||
if (colorLabelsZ)
|
||||
{
|
||||
c->push ();
|
||||
for (unsigned i = 0; i < color_count; i++)
|
||||
for (const auto _ : colorLabels)
|
||||
{
|
||||
if (!color_index_map->has (i)) continue;
|
||||
if (!c->copy<NameID> (colorLabels[i]))
|
||||
const hb_codepoint_t *v;
|
||||
if (!color_index_map->has (_, &v)) continue;
|
||||
NameID new_color_idx;
|
||||
new_color_idx = *v;
|
||||
if (!c->copy<NameID> (new_color_idx))
|
||||
{
|
||||
c->pop_discard ();
|
||||
return_trace (false);
|
||||
|
@ -210,13 +189,6 @@ struct CPAL
|
|||
return numColors;
|
||||
}
|
||||
|
||||
void collect_name_ids (const hb_map_t *color_index_map,
|
||||
hb_set_t *nameids_to_retain /* OUT */) const
|
||||
{
|
||||
if (version == 1)
|
||||
v1 ().collect_name_ids (this, numPalettes, numColors, color_index_map, nameids_to_retain);
|
||||
}
|
||||
|
||||
private:
|
||||
const CPALV1Tail& v1 () const
|
||||
{
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#ifndef OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
|
||||
#define OT_LAYOUT_COMMON_COVERAGEFORMAT1_HH
|
||||
|
||||
#include "../../../hb-cache.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace Common {
|
||||
|
@ -57,8 +59,18 @@ struct CoverageFormat1_3
|
|||
|
||||
unsigned int get_coverage (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
static hb_cache_t<16, 8, 9, true> cache;
|
||||
|
||||
unsigned v;
|
||||
if (cache.get ((glyph_id + (uintptr_t) this) & 0xFFFF, &v))
|
||||
{
|
||||
if (glyphArray[v] == glyph_id)
|
||||
return v;
|
||||
}
|
||||
|
||||
unsigned int i;
|
||||
glyphArray.bfind (glyph_id, &i, HB_NOT_FOUND_STORE, NOT_COVERED);
|
||||
cache.set ((glyph_id + (uintptr_t) this) & 0xFFFF, i);
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@
|
|||
|
||||
#include "RangeRecord.hh"
|
||||
|
||||
#include "../../../hb-cache.hh"
|
||||
|
||||
namespace OT {
|
||||
namespace Layout {
|
||||
namespace Common {
|
||||
|
@ -59,7 +61,18 @@ struct CoverageFormat2_4
|
|||
|
||||
unsigned int get_coverage (hb_codepoint_t glyph_id) const
|
||||
{
|
||||
static hb_cache_t<16, 8, 9, true> cache;
|
||||
|
||||
unsigned v;
|
||||
if (cache.get ((glyph_id + (uintptr_t) this) & 0xFFFF, &v))
|
||||
{
|
||||
const RangeRecord<Types> &range = rangeRecord[v];
|
||||
if (range.first <= glyph_id && glyph_id <= range.last)
|
||||
return (unsigned int) range.value + (glyph_id - range.first);
|
||||
}
|
||||
|
||||
const RangeRecord<Types> &range = rangeRecord.bsearch (glyph_id);
|
||||
cache.set ((glyph_id + (uintptr_t) this) & 0xFFFF, &range - &rangeRecord[0]);
|
||||
return likely (range.first <= range.last)
|
||||
? (unsigned int) range.value + (glyph_id - range.first)
|
||||
: NOT_COVERED;
|
||||
|
|
|
@ -90,25 +90,6 @@ struct MarkBasePosFormat1_2
|
|||
|
||||
const Coverage &get_coverage () const { return this+markCoverage; }
|
||||
|
||||
static inline bool accept (hb_buffer_t *buffer, unsigned idx)
|
||||
{
|
||||
/* We only want to attach to the first of a MultipleSubst sequence.
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/740
|
||||
* Reject others...
|
||||
* ...but stop if we find a mark in the MultipleSubst sequence:
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/1020 */
|
||||
return !_hb_glyph_info_multiplied (&buffer->info[idx]) ||
|
||||
0 == _hb_glyph_info_get_lig_comp (&buffer->info[idx]) ||
|
||||
(idx == 0 ||
|
||||
_hb_glyph_info_is_mark (&buffer->info[idx - 1]) ||
|
||||
!_hb_glyph_info_multiplied (&buffer->info[idx - 1]) ||
|
||||
_hb_glyph_info_get_lig_id (&buffer->info[idx]) !=
|
||||
_hb_glyph_info_get_lig_id (&buffer->info[idx - 1]) ||
|
||||
_hb_glyph_info_get_lig_comp (&buffer->info[idx]) !=
|
||||
_hb_glyph_info_get_lig_comp (&buffer->info[idx - 1]) + 1
|
||||
);
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
@ -116,54 +97,48 @@ struct MarkBasePosFormat1_2
|
|||
unsigned int mark_index = (this+markCoverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (mark_index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
/* Now we search backwards for a non-mark glyph.
|
||||
* We don't use skippy_iter.prev() to avoid O(n^2) behavior. */
|
||||
|
||||
/* Now we search backwards for a non-mark glyph */
|
||||
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
|
||||
skippy_iter.reset (buffer->idx, 1);
|
||||
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
|
||||
|
||||
if (c->last_base_until > buffer->idx)
|
||||
{
|
||||
c->last_base_until = 0;
|
||||
c->last_base = -1;
|
||||
}
|
||||
unsigned j;
|
||||
for (j = buffer->idx; j > c->last_base_until; j--)
|
||||
{
|
||||
auto match = skippy_iter.match (buffer->info[j - 1]);
|
||||
if (match == skippy_iter.MATCH)
|
||||
do {
|
||||
unsigned unsafe_from;
|
||||
if (!skippy_iter.prev (&unsafe_from))
|
||||
{
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/4124
|
||||
if (!accept (buffer, j - 1) &&
|
||||
NOT_COVERED == (this+baseCoverage).get_coverage (buffer->info[j - 1].codepoint))
|
||||
match = skippy_iter.SKIP;
|
||||
buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
if (match == skippy_iter.MATCH)
|
||||
{
|
||||
c->last_base = (signed) j - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
c->last_base_until = buffer->idx;
|
||||
if (c->last_base == -1)
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (0, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
unsigned idx = (unsigned) c->last_base;
|
||||
/* We only want to attach to the first of a MultipleSubst sequence.
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/740
|
||||
* Reject others...
|
||||
* ...but stop if we find a mark in the MultipleSubst sequence:
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/1020 */
|
||||
if (!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx]) ||
|
||||
0 == _hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) ||
|
||||
(skippy_iter.idx == 0 ||
|
||||
_hb_glyph_info_is_mark (&buffer->info[skippy_iter.idx - 1]) ||
|
||||
!_hb_glyph_info_multiplied (&buffer->info[skippy_iter.idx - 1]) ||
|
||||
_hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx]) !=
|
||||
_hb_glyph_info_get_lig_id (&buffer->info[skippy_iter.idx - 1]) ||
|
||||
_hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx]) !=
|
||||
_hb_glyph_info_get_lig_comp (&buffer->info[skippy_iter.idx - 1]) + 1
|
||||
))
|
||||
break;
|
||||
skippy_iter.reject ();
|
||||
} while (true);
|
||||
|
||||
/* Checking that matched glyph is actually a base glyph by GDEF is too strong; disabled */
|
||||
//if (!_hb_glyph_info_is_base_glyph (&buffer->info[idx])) { return_trace (false); }
|
||||
//if (!_hb_glyph_info_is_base_glyph (&buffer->info[skippy_iter.idx])) { return_trace (false); }
|
||||
|
||||
unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[idx].codepoint);
|
||||
unsigned int base_index = (this+baseCoverage).get_coverage (buffer->info[skippy_iter.idx].codepoint);
|
||||
if (base_index == NOT_COVERED)
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1);
|
||||
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, idx));
|
||||
return_trace ((this+markArray).apply (c, mark_index, base_index, this+baseArray, classCount, skippy_iter.idx));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
|
|
|
@ -100,41 +100,24 @@ struct MarkLigPosFormat1_2
|
|||
if (likely (mark_index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
/* Now we search backwards for a non-mark glyph */
|
||||
|
||||
hb_ot_apply_context_t::skipping_iterator_t &skippy_iter = c->iter_input;
|
||||
skippy_iter.reset (buffer->idx, 1);
|
||||
skippy_iter.set_lookup_props (LookupFlag::IgnoreMarks);
|
||||
|
||||
if (c->last_base_until > buffer->idx)
|
||||
unsigned unsafe_from;
|
||||
if (!skippy_iter.prev (&unsafe_from))
|
||||
{
|
||||
c->last_base_until = 0;
|
||||
c->last_base = -1;
|
||||
}
|
||||
unsigned j;
|
||||
for (j = buffer->idx; j > c->last_base_until; j--)
|
||||
{
|
||||
auto match = skippy_iter.match (buffer->info[j - 1]);
|
||||
if (match == skippy_iter.MATCH)
|
||||
{
|
||||
c->last_base = (signed) j - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
c->last_base_until = buffer->idx;
|
||||
if (c->last_base == -1)
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (0, buffer->idx + 1);
|
||||
buffer->unsafe_to_concat_from_outbuffer (unsafe_from, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
unsigned idx = (unsigned) c->last_base;
|
||||
|
||||
/* Checking that matched glyph is actually a ligature by GDEF is too strong; disabled */
|
||||
//if (!_hb_glyph_info_is_ligature (&buffer->info[idx])) { return_trace (false); }
|
||||
//if (!_hb_glyph_info_is_ligature (&buffer->info[skippy_iter.idx])) { return_trace (false); }
|
||||
|
||||
unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[idx].codepoint);
|
||||
unsigned int j = skippy_iter.idx;
|
||||
unsigned int lig_index = (this+ligatureCoverage).get_coverage (buffer->info[j].codepoint);
|
||||
if (lig_index == NOT_COVERED)
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1);
|
||||
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
|
@ -145,7 +128,7 @@ struct MarkLigPosFormat1_2
|
|||
unsigned int comp_count = lig_attach.rows;
|
||||
if (unlikely (!comp_count))
|
||||
{
|
||||
buffer->unsafe_to_concat_from_outbuffer (idx, buffer->idx + 1);
|
||||
buffer->unsafe_to_concat_from_outbuffer (skippy_iter.idx, buffer->idx + 1);
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
|
@ -154,7 +137,7 @@ struct MarkLigPosFormat1_2
|
|||
* can directly use the component index. If not, we attach the mark
|
||||
* glyph to the last component of the ligature. */
|
||||
unsigned int comp_index;
|
||||
unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[idx]);
|
||||
unsigned int lig_id = _hb_glyph_info_get_lig_id (&buffer->info[j]);
|
||||
unsigned int mark_id = _hb_glyph_info_get_lig_id (&buffer->cur());
|
||||
unsigned int mark_comp = _hb_glyph_info_get_lig_comp (&buffer->cur());
|
||||
if (lig_id && lig_id == mark_id && mark_comp > 0)
|
||||
|
@ -162,7 +145,7 @@ struct MarkLigPosFormat1_2
|
|||
else
|
||||
comp_index = comp_count - 1;
|
||||
|
||||
return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, idx));
|
||||
return_trace ((this+markArray).apply (c, mark_index, comp_index, lig_attach, classCount, j));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
|
|
|
@ -55,7 +55,7 @@ struct PairPosFormat1_3
|
|||
|
||||
if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len) / 4)
|
||||
{
|
||||
for (hb_codepoint_t g : glyphs->iter())
|
||||
for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
|
||||
{
|
||||
unsigned i = cov.get_coverage (g);
|
||||
if ((this+pairSet[i]).intersects (glyphs, valueFormat))
|
||||
|
|
|
@ -28,15 +28,7 @@ struct SinglePosFormat1
|
|||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
coverage.sanitize (c, this) &&
|
||||
/* The coverage table may use a range to represent a set
|
||||
* of glyphs, which means a small number of bytes can
|
||||
* generate a large glyph set. Manually modify the
|
||||
* sanitizer max ops to take this into account.
|
||||
*
|
||||
* Note: This check *must* be right after coverage sanitize. */
|
||||
c->check_ops ((this + coverage).get_population () >> 1) &&
|
||||
valueFormat.sanitize_value (c, this, values));
|
||||
|
||||
}
|
||||
|
||||
bool intersects (const hb_set_t *glyphs) const
|
||||
|
|
|
@ -29,9 +29,6 @@ struct Ligature
|
|||
bool intersects (const hb_set_t *glyphs) const
|
||||
{ return hb_all (component, glyphs); }
|
||||
|
||||
bool intersects_lig_glyph (const hb_set_t *glyphs) const
|
||||
{ return glyphs->has(ligGlyph); }
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
if (!intersects (c->glyphs)) return;
|
||||
|
|
|
@ -34,18 +34,6 @@ struct LigatureSet
|
|||
;
|
||||
}
|
||||
|
||||
bool intersects_lig_glyph (const hb_set_t *glyphs) const
|
||||
{
|
||||
return
|
||||
+ hb_iter (ligature)
|
||||
| hb_map (hb_add (this))
|
||||
| hb_map ([glyphs] (const Ligature<Types> &_) {
|
||||
return _.intersects_lig_glyph (glyphs) && _.intersects (glyphs);
|
||||
})
|
||||
| hb_any
|
||||
;
|
||||
}
|
||||
|
||||
void closure (hb_closure_context_t *c) const
|
||||
{
|
||||
+ hb_iter (ligature)
|
||||
|
|
|
@ -130,7 +130,7 @@ struct LigatureSubstFormat1_2
|
|||
+ hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this)))
|
||||
| hb_filter (glyphset, hb_first)
|
||||
| hb_filter ([&] (const LigatureSet<Types>& _) {
|
||||
return _.intersects_lig_glyph (&glyphset);
|
||||
return _.intersects (&glyphset);
|
||||
}, hb_second)
|
||||
| hb_map (hb_first)
|
||||
| hb_sink (new_coverage);
|
||||
|
|
|
@ -25,15 +25,7 @@ struct SingleSubstFormat1_3
|
|||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
coverage.sanitize (c, this) &&
|
||||
/* The coverage table may use a range to represent a set
|
||||
* of glyphs, which means a small number of bytes can
|
||||
* generate a large glyph set. Manually modify the
|
||||
* sanitizer max ops to take this into account.
|
||||
*
|
||||
* Note: This check *must* be right after coverage sanitize. */
|
||||
c->check_ops ((this + coverage).get_population () >> 1));
|
||||
return_trace (coverage.sanitize (c, this) && deltaGlyphID.sanitize (c));
|
||||
}
|
||||
|
||||
hb_codepoint_t get_mask () const
|
||||
|
@ -95,34 +87,6 @@ struct SingleSubstFormat1_3
|
|||
bool would_apply (hb_would_apply_context_t *c) const
|
||||
{ return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
|
||||
|
||||
unsigned
|
||||
get_glyph_alternates (hb_codepoint_t glyph_id,
|
||||
unsigned start_offset,
|
||||
unsigned *alternate_count /* IN/OUT. May be NULL. */,
|
||||
hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
|
||||
{
|
||||
unsigned int index = (this+coverage).get_coverage (glyph_id);
|
||||
if (likely (index == NOT_COVERED))
|
||||
{
|
||||
if (alternate_count)
|
||||
*alternate_count = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (alternate_count && *alternate_count)
|
||||
{
|
||||
hb_codepoint_t d = deltaGlyphID;
|
||||
hb_codepoint_t mask = get_mask ();
|
||||
|
||||
glyph_id = (glyph_id + d) & mask;
|
||||
|
||||
*alternate_glyphs = glyph_id;
|
||||
*alternate_count = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
|
|
@ -75,31 +75,6 @@ struct SingleSubstFormat2_4
|
|||
bool would_apply (hb_would_apply_context_t *c) const
|
||||
{ return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
|
||||
|
||||
unsigned
|
||||
get_glyph_alternates (hb_codepoint_t glyph_id,
|
||||
unsigned start_offset,
|
||||
unsigned *alternate_count /* IN/OUT. May be NULL. */,
|
||||
hb_codepoint_t *alternate_glyphs /* OUT. May be NULL. */) const
|
||||
{
|
||||
unsigned int index = (this+coverage).get_coverage (glyph_id);
|
||||
if (likely (index == NOT_COVERED))
|
||||
{
|
||||
if (alternate_count)
|
||||
*alternate_count = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (alternate_count && *alternate_count)
|
||||
{
|
||||
glyph_id = substitute[index];
|
||||
|
||||
*alternate_glyphs = glyph_id;
|
||||
*alternate_count = 1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c) const
|
||||
{
|
||||
TRACE_APPLY (this);
|
||||
|
|
|
@ -87,34 +87,27 @@ struct CompositeGlyphRecord
|
|||
}
|
||||
}
|
||||
|
||||
void transform_points (contour_point_vector_t &points,
|
||||
const float (&matrix)[4],
|
||||
const contour_point_t &trans) const
|
||||
{
|
||||
if (scaled_offsets ())
|
||||
{
|
||||
points.translate (trans);
|
||||
points.transform (matrix);
|
||||
}
|
||||
else
|
||||
{
|
||||
points.transform (matrix);
|
||||
points.translate (trans);
|
||||
}
|
||||
}
|
||||
|
||||
bool get_points (contour_point_vector_t &points) const
|
||||
void transform_points (contour_point_vector_t &points) const
|
||||
{
|
||||
float matrix[4];
|
||||
contour_point_t trans;
|
||||
get_transformation (matrix, trans);
|
||||
if (unlikely (!points.resize (points.length + 1))) return false;
|
||||
points[points.length - 1] = trans;
|
||||
return true;
|
||||
if (get_transformation (matrix, trans))
|
||||
{
|
||||
if (scaled_offsets ())
|
||||
{
|
||||
points.translate (trans);
|
||||
points.transform (matrix);
|
||||
}
|
||||
else
|
||||
{
|
||||
points.transform (matrix);
|
||||
points.translate (trans);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned compile_with_point (const contour_point_t &point,
|
||||
char *out) const
|
||||
unsigned compile_with_deltas (const contour_point_t &p_delta,
|
||||
char *out) const
|
||||
{
|
||||
const HBINT8 *p = &StructAfter<const HBINT8> (flags);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
@ -128,17 +121,18 @@ struct CompositeGlyphRecord
|
|||
unsigned len_before_val = (const char *)p - (const char *)this;
|
||||
if (flags & ARG_1_AND_2_ARE_WORDS)
|
||||
{
|
||||
// no overflow, copy value
|
||||
// no overflow, copy and update value with deltas
|
||||
hb_memcpy (out, this, len);
|
||||
|
||||
const HBINT16 *px = reinterpret_cast<const HBINT16 *> (p);
|
||||
HBINT16 *o = reinterpret_cast<HBINT16 *> (out + len_before_val);
|
||||
o[0] = roundf (point.x);
|
||||
o[1] = roundf (point.y);
|
||||
o[0] = px[0] + roundf (p_delta.x);
|
||||
o[1] = px[1] + roundf (p_delta.y);
|
||||
}
|
||||
else
|
||||
{
|
||||
int new_x = roundf (point.x);
|
||||
int new_y = roundf (point.y);
|
||||
int new_x = p[0] + roundf (p_delta.x);
|
||||
int new_y = p[1] + roundf (p_delta.y);
|
||||
if (new_x <= 127 && new_x >= -128 &&
|
||||
new_y <= 127 && new_y >= -128)
|
||||
{
|
||||
|
@ -149,7 +143,7 @@ struct CompositeGlyphRecord
|
|||
}
|
||||
else
|
||||
{
|
||||
// new point value has an int8 overflow
|
||||
// int8 overflows after deltas applied
|
||||
hb_memcpy (out, this, len_before_val);
|
||||
|
||||
//update flags
|
||||
|
@ -177,7 +171,6 @@ struct CompositeGlyphRecord
|
|||
bool scaled_offsets () const
|
||||
{ return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; }
|
||||
|
||||
public:
|
||||
bool get_transformation (float (&matrix)[4], contour_point_t &trans) const
|
||||
{
|
||||
matrix[0] = matrix[3] = 1.f;
|
||||
|
@ -232,6 +225,7 @@ struct CompositeGlyphRecord
|
|||
return tx || ty;
|
||||
}
|
||||
|
||||
public:
|
||||
hb_codepoint_t get_gid () const
|
||||
{
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
|
@ -252,27 +246,6 @@ struct CompositeGlyphRecord
|
|||
StructAfter<HBGlyphID16> (flags) = gid;
|
||||
}
|
||||
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
void lower_gid_24_to_16 ()
|
||||
{
|
||||
hb_codepoint_t gid = get_gid ();
|
||||
if (!(flags & GID_IS_24BIT) || gid > 0xFFFFu)
|
||||
return;
|
||||
|
||||
/* Lower the flag and move the rest of the struct down. */
|
||||
|
||||
unsigned size = get_size ();
|
||||
char *end = (char *) this + size;
|
||||
char *p = &StructAfter<char> (flags);
|
||||
p += HBGlyphID24::static_size;
|
||||
|
||||
flags = flags & ~GID_IS_24BIT;
|
||||
set_gid (gid);
|
||||
|
||||
memmove (p - HBGlyphID24::static_size + HBGlyphID16::static_size, p, end - p);
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
HBUINT16 flags;
|
||||
HBUINT24 pad;
|
||||
|
@ -331,7 +304,7 @@ struct CompositeGlyph
|
|||
}
|
||||
|
||||
bool compile_bytes_with_deltas (const hb_bytes_t &source_bytes,
|
||||
const contour_point_vector_t &points_with_deltas,
|
||||
const contour_point_vector_t &deltas,
|
||||
hb_bytes_t &dest_bytes /* OUT */)
|
||||
{
|
||||
if (source_bytes.length <= GlyphHeader::static_size ||
|
||||
|
@ -346,7 +319,7 @@ struct CompositeGlyph
|
|||
/* try to allocate more memories than source glyph bytes
|
||||
* in case that there might be an overflow for int8 value
|
||||
* and we would need to use int16 instead */
|
||||
char *o = (char *) hb_calloc (source_len * 2, sizeof (char));
|
||||
char *o = (char *) hb_calloc (source_len + source_len/2, sizeof (char));
|
||||
if (unlikely (!o)) return false;
|
||||
|
||||
const CompositeGlyphRecord *c = reinterpret_cast<const CompositeGlyphRecord *> (source_bytes.arrayZ + GlyphHeader::static_size);
|
||||
|
@ -356,11 +329,8 @@ struct CompositeGlyph
|
|||
unsigned i = 0, source_comp_len = 0;
|
||||
for (const auto &component : it)
|
||||
{
|
||||
/* last 4 points in points_with_deltas are phantom points and should not be included */
|
||||
if (i >= points_with_deltas.length - 4) {
|
||||
free (o);
|
||||
return false;
|
||||
}
|
||||
/* last 4 points in deltas are phantom points and should not be included */
|
||||
if (i >= deltas.length - 4) return false;
|
||||
|
||||
unsigned comp_len = component.get_size ();
|
||||
if (component.is_anchored ())
|
||||
|
@ -370,7 +340,7 @@ struct CompositeGlyph
|
|||
}
|
||||
else
|
||||
{
|
||||
unsigned new_len = component.compile_with_point (points_with_deltas[i], p);
|
||||
unsigned new_len = component.compile_with_deltas (deltas[i], p);
|
||||
p += new_len;
|
||||
}
|
||||
i++;
|
||||
|
|
|
@ -29,14 +29,7 @@ enum phantom_point_index_t
|
|||
|
||||
struct Glyph
|
||||
{
|
||||
enum glyph_type_t {
|
||||
EMPTY,
|
||||
SIMPLE,
|
||||
COMPOSITE,
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
VAR_COMPOSITE,
|
||||
#endif
|
||||
};
|
||||
enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE, VAR_COMPOSITE };
|
||||
|
||||
public:
|
||||
composite_iter_t get_composite_iterator () const
|
||||
|
@ -46,23 +39,15 @@ struct Glyph
|
|||
}
|
||||
var_composite_iter_t get_var_composite_iterator () const
|
||||
{
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
if (type != VAR_COMPOSITE) return var_composite_iter_t ();
|
||||
return VarCompositeGlyph (*header, bytes).iter ();
|
||||
#else
|
||||
return var_composite_iter_t ();
|
||||
#endif
|
||||
}
|
||||
|
||||
const hb_bytes_t trim_padding () const
|
||||
{
|
||||
switch (type) {
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
case VAR_COMPOSITE: return VarCompositeGlyph (*header, bytes).trim_padding ();
|
||||
#endif
|
||||
case COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding ();
|
||||
case SIMPLE: return SimpleGlyph (*header, bytes).trim_padding ();
|
||||
case EMPTY: return bytes;
|
||||
default: return bytes;
|
||||
}
|
||||
}
|
||||
|
@ -70,36 +55,27 @@ struct Glyph
|
|||
void drop_hints ()
|
||||
{
|
||||
switch (type) {
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
case VAR_COMPOSITE: return; // No hinting
|
||||
#endif
|
||||
case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
|
||||
case SIMPLE: SimpleGlyph (*header, bytes).drop_hints (); return;
|
||||
case EMPTY: return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
void set_overlaps_flag ()
|
||||
{
|
||||
switch (type) {
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
case VAR_COMPOSITE: return; // No overlaps flag
|
||||
#endif
|
||||
case COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return;
|
||||
case SIMPLE: SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
|
||||
case EMPTY: return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
|
||||
{
|
||||
switch (type) {
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
case VAR_COMPOSITE: return; // No hinting
|
||||
#endif
|
||||
case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return;
|
||||
case SIMPLE: SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return;
|
||||
case EMPTY: return;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,7 +119,7 @@ struct Glyph
|
|||
hb_bytes_t &dest_bytes /* OUT */) const
|
||||
{
|
||||
GlyphHeader *glyph_header = nullptr;
|
||||
if (!plan->pinned_at_default && type != EMPTY && all_points.length >= 4)
|
||||
if (!plan->pinned_at_default && type != EMPTY && all_points.length > 4)
|
||||
{
|
||||
glyph_header = (GlyphHeader *) hb_calloc (1, GlyphHeader::static_size);
|
||||
if (unlikely (!glyph_header)) return false;
|
||||
|
@ -205,7 +181,7 @@ struct Glyph
|
|||
hb_bytes_t &dest_start, /* IN/OUT */
|
||||
hb_bytes_t &dest_end /* OUT */)
|
||||
{
|
||||
contour_point_vector_t all_points, points_with_deltas;
|
||||
contour_point_vector_t all_points, deltas;
|
||||
unsigned composite_contours = 0;
|
||||
head_maxp_info_t *head_maxp_info_p = &plan->head_maxp_info;
|
||||
unsigned *composite_contours_p = &composite_contours;
|
||||
|
@ -219,7 +195,7 @@ struct Glyph
|
|||
composite_contours_p = nullptr;
|
||||
}
|
||||
|
||||
if (!get_points (font, glyf, all_points, &points_with_deltas, head_maxp_info_p, composite_contours_p, false, false))
|
||||
if (!get_points (font, glyf, all_points, &deltas, head_maxp_info_p, composite_contours_p, false, false))
|
||||
return false;
|
||||
|
||||
// .notdef, set type to empty so we only update metrics and don't compile bytes for
|
||||
|
@ -233,20 +209,11 @@ struct Glyph
|
|||
}
|
||||
|
||||
//dont compile bytes when pinned at default, just recalculate bounds
|
||||
if (!plan->pinned_at_default)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
case VAR_COMPOSITE:
|
||||
// TODO
|
||||
dest_end = hb_bytes_t ();
|
||||
break;
|
||||
#endif
|
||||
|
||||
if (!plan->pinned_at_default) {
|
||||
switch (type) {
|
||||
case COMPOSITE:
|
||||
if (!CompositeGlyph (*header, bytes).compile_bytes_with_deltas (dest_start,
|
||||
points_with_deltas,
|
||||
deltas,
|
||||
dest_end))
|
||||
return false;
|
||||
break;
|
||||
|
@ -256,7 +223,7 @@ struct Glyph
|
|||
dest_end))
|
||||
return false;
|
||||
break;
|
||||
case EMPTY:
|
||||
default:
|
||||
/* set empty bytes for empty glyph
|
||||
* do not use source glyph's pointers */
|
||||
dest_start = hb_bytes_t ();
|
||||
|
@ -280,7 +247,7 @@ struct Glyph
|
|||
template <typename accelerator_t>
|
||||
bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
|
||||
contour_point_vector_t &all_points /* OUT */,
|
||||
contour_point_vector_t *points_with_deltas = nullptr, /* OUT */
|
||||
contour_point_vector_t *deltas = nullptr, /* OUT */
|
||||
head_maxp_info_t * head_maxp_info = nullptr, /* OUT */
|
||||
unsigned *composite_contours = nullptr, /* OUT */
|
||||
bool shift_points_hori = true,
|
||||
|
@ -320,8 +287,9 @@ struct Glyph
|
|||
break;
|
||||
case COMPOSITE:
|
||||
{
|
||||
for (auto &item : get_composite_iterator ())
|
||||
if (unlikely (!item.get_points (points))) return false;
|
||||
/* pseudo component points for each component in composite glyph */
|
||||
unsigned num_points = hb_len (CompositeGlyph (*header, bytes).iter ());
|
||||
if (unlikely (!points.resize (num_points))) return false;
|
||||
break;
|
||||
}
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
|
@ -331,7 +299,7 @@ struct Glyph
|
|||
if (unlikely (!item.get_points (points))) return false;
|
||||
}
|
||||
#endif
|
||||
case EMPTY:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -359,11 +327,17 @@ struct Glyph
|
|||
#endif
|
||||
;
|
||||
phantoms[PHANTOM_LEFT].x = h_delta;
|
||||
phantoms[PHANTOM_RIGHT].x = (int) h_adv + h_delta;
|
||||
phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
|
||||
phantoms[PHANTOM_TOP].y = v_orig;
|
||||
phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
|
||||
}
|
||||
|
||||
if (deltas != nullptr && depth == 0 && type == COMPOSITE)
|
||||
{
|
||||
if (unlikely (!deltas->resize (points.length))) return false;
|
||||
deltas->copy_vector (points);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
glyf_accelerator.gvar->apply_deltas_to_points (gid,
|
||||
coords,
|
||||
|
@ -372,10 +346,13 @@ struct Glyph
|
|||
|
||||
// mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
|
||||
// with child glyphs' points
|
||||
if (points_with_deltas != nullptr && depth == 0 && type == COMPOSITE)
|
||||
if (deltas != nullptr && depth == 0 && type == COMPOSITE)
|
||||
{
|
||||
if (unlikely (!points_with_deltas->resize (points.length))) return false;
|
||||
points_with_deltas->copy_vector (points);
|
||||
for (unsigned i = 0 ; i < points.length; i++)
|
||||
{
|
||||
deltas->arrayZ[i].x = points.arrayZ[i].x - deltas->arrayZ[i].x;
|
||||
deltas->arrayZ[i].y = points.arrayZ[i].y - deltas->arrayZ[i].y;
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
|
@ -396,7 +373,7 @@ struct Glyph
|
|||
.get_points (font,
|
||||
glyf_accelerator,
|
||||
comp_points,
|
||||
points_with_deltas,
|
||||
deltas,
|
||||
head_maxp_info,
|
||||
composite_contours,
|
||||
shift_points_hori,
|
||||
|
@ -412,12 +389,11 @@ struct Glyph
|
|||
for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
|
||||
phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
|
||||
|
||||
float matrix[4];
|
||||
contour_point_t default_trans;
|
||||
item.get_transformation (matrix, default_trans);
|
||||
/* Apply component transformation & translation */
|
||||
item.transform_points (comp_points);
|
||||
|
||||
/* Apply component transformation & translation (with deltas applied) */
|
||||
item.transform_points (comp_points, matrix, points[comp_index]);
|
||||
/* Apply translation from gvar */
|
||||
comp_points.translate (points[comp_index]);
|
||||
|
||||
if (item.is_anchored ())
|
||||
{
|
||||
|
@ -463,7 +439,7 @@ struct Glyph
|
|||
|
||||
auto component_coords = coords;
|
||||
if (item.is_reset_unspecified_axes ())
|
||||
component_coords = hb_array<int> ();
|
||||
component_coords = hb_array (font->coords, font->num_coords);
|
||||
|
||||
coord_setter_t coord_setter (component_coords);
|
||||
item.set_variations (coord_setter, record_points);
|
||||
|
@ -472,7 +448,7 @@ struct Glyph
|
|||
.get_points (font,
|
||||
glyf_accelerator,
|
||||
comp_points,
|
||||
points_with_deltas,
|
||||
deltas,
|
||||
head_maxp_info,
|
||||
nullptr,
|
||||
shift_points_hori,
|
||||
|
@ -501,7 +477,7 @@ struct Glyph
|
|||
all_points.extend (phantoms);
|
||||
} break;
|
||||
#endif
|
||||
case EMPTY:
|
||||
default:
|
||||
all_points.extend (phantoms);
|
||||
break;
|
||||
}
|
||||
|
@ -527,8 +503,6 @@ struct Glyph
|
|||
}
|
||||
|
||||
hb_bytes_t get_bytes () const { return bytes; }
|
||||
glyph_type_t get_type () const { return type; }
|
||||
const GlyphHeader *get_header () const { return header; }
|
||||
|
||||
Glyph () : bytes (),
|
||||
header (bytes.as<GlyphHeader> ()),
|
||||
|
@ -544,9 +518,7 @@ struct Glyph
|
|||
int num_contours = header->numberOfContours;
|
||||
if (unlikely (num_contours == 0)) type = EMPTY;
|
||||
else if (num_contours > 0) type = SIMPLE;
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
else if (num_contours == -2) type = VAR_COMPOSITE;
|
||||
#endif
|
||||
else type = COMPOSITE; /* negative numbers */
|
||||
}
|
||||
|
||||
|
@ -554,7 +526,7 @@ struct Glyph
|
|||
hb_bytes_t bytes;
|
||||
const GlyphHeader *header;
|
||||
hb_codepoint_t gid;
|
||||
glyph_type_t type;
|
||||
unsigned type;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ struct SimpleGlyph
|
|||
FLAG_X_SAME = 0x10,
|
||||
FLAG_Y_SAME = 0x20,
|
||||
FLAG_OVERLAP_SIMPLE = 0x40,
|
||||
FLAG_CUBIC = 0x80
|
||||
FLAG_RESERVED2 = 0x80
|
||||
};
|
||||
|
||||
const GlyphHeader &header;
|
||||
|
@ -34,11 +34,6 @@ struct SimpleGlyph
|
|||
unsigned int length (unsigned int instruction_len) const
|
||||
{ return instruction_len_offset () + 2 + instruction_len; }
|
||||
|
||||
bool has_instructions_length () const
|
||||
{
|
||||
return instruction_len_offset () + 2 <= bytes.length;
|
||||
}
|
||||
|
||||
unsigned int instructions_length () const
|
||||
{
|
||||
unsigned int instruction_length_offset = instruction_len_offset ();
|
||||
|
@ -99,7 +94,6 @@ struct SimpleGlyph
|
|||
/* zero instruction length */
|
||||
void drop_hints ()
|
||||
{
|
||||
if (!has_instructions_length ()) return;
|
||||
GlyphHeader &glyph_header = const_cast<GlyphHeader &> (header);
|
||||
(HBUINT16 &) StructAtOffset<HBUINT16> (&glyph_header, instruction_len_offset ()) = 0;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ struct SubsetGlyph
|
|||
Glyph source_glyph;
|
||||
hb_bytes_t dest_start; /* region of source_glyph to copy first */
|
||||
hb_bytes_t dest_end; /* region of source_glyph to copy second */
|
||||
bool allocated;
|
||||
|
||||
bool serialize (hb_serialize_context_t *c,
|
||||
bool use_short_loca,
|
||||
|
@ -27,12 +26,7 @@ struct SubsetGlyph
|
|||
TRACE_SERIALIZE (this);
|
||||
|
||||
hb_bytes_t dest_glyph = dest_start.copy (c);
|
||||
hb_bytes_t end_copy = dest_end.copy (c);
|
||||
if (!end_copy.arrayZ || !dest_glyph.arrayZ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + end_copy.length);
|
||||
dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length);
|
||||
unsigned int pad_length = use_short_loca ? padding () : 0;
|
||||
DEBUG_MSG (SUBSET, nullptr, "serialize %u byte glyph, width %u pad %u", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
|
||||
|
||||
|
@ -46,68 +40,13 @@ struct SubsetGlyph
|
|||
|
||||
if (unlikely (!dest_glyph.length)) return_trace (true);
|
||||
|
||||
/* update components gids. */
|
||||
/* update components gids */
|
||||
for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
|
||||
{
|
||||
hb_codepoint_t new_gid;
|
||||
if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
|
||||
const_cast<CompositeGlyphRecord &> (_).set_gid (new_gid);
|
||||
}
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
for (auto &_ : Glyph (dest_glyph).get_var_composite_iterator ())
|
||||
{
|
||||
hb_codepoint_t new_gid;
|
||||
if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
|
||||
const_cast<VarCompositeGlyphRecord &> (_).set_gid (new_gid);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
auto it = Glyph (dest_glyph).get_composite_iterator ();
|
||||
if (it)
|
||||
{
|
||||
/* lower GID24 to GID16 in components if possible.
|
||||
*
|
||||
* TODO: VarComposite. Not as critical, since VarComposite supports
|
||||
* gid24 from the first version. */
|
||||
char *p = it ? (char *) &*it : nullptr;
|
||||
char *q = p;
|
||||
const char *end = dest_glyph.arrayZ + dest_glyph.length;
|
||||
while (it)
|
||||
{
|
||||
auto &rec = const_cast<CompositeGlyphRecord &> (*it);
|
||||
++it;
|
||||
|
||||
q += rec.get_size ();
|
||||
|
||||
rec.lower_gid_24_to_16 ();
|
||||
|
||||
unsigned size = rec.get_size ();
|
||||
|
||||
memmove (p, &rec, size);
|
||||
|
||||
p += size;
|
||||
}
|
||||
memmove (p, q, end - q);
|
||||
p += end - q;
|
||||
|
||||
/* We want to shorten the glyph, but we can't do that without
|
||||
* updating the length in the loca table, which is already
|
||||
* written out :-(. So we just fill the rest of the glyph with
|
||||
* harmless instructions, since that's what they will be
|
||||
* interpreted as.
|
||||
*
|
||||
* Should move the lowering to _populate_subset_glyphs() to
|
||||
* fix this issue. */
|
||||
|
||||
hb_memset (p, 0x7A /* TrueType instruction ROFF; harmless */, end - p);
|
||||
p += end - p;
|
||||
dest_glyph = hb_bytes_t (dest_glyph.arrayZ, p - (char *) dest_glyph.arrayZ);
|
||||
|
||||
// TODO: Padding; & trim serialized bytes.
|
||||
// TODO: Update length in loca. Ugh.
|
||||
}
|
||||
#endif
|
||||
|
||||
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
Glyph (dest_glyph).drop_hints ();
|
||||
|
@ -121,18 +60,12 @@ struct SubsetGlyph
|
|||
bool compile_bytes_with_deltas (const hb_subset_plan_t *plan,
|
||||
hb_font_t *font,
|
||||
const glyf_accelerator_t &glyf)
|
||||
{
|
||||
allocated = source_glyph.compile_bytes_with_deltas (plan, font, glyf, dest_start, dest_end);
|
||||
return allocated;
|
||||
}
|
||||
{ return source_glyph.compile_bytes_with_deltas (plan, font, glyf, dest_start, dest_end); }
|
||||
|
||||
void free_compiled_bytes ()
|
||||
{
|
||||
if (likely (allocated)) {
|
||||
allocated = false;
|
||||
dest_start.fini ();
|
||||
dest_end.fini ();
|
||||
}
|
||||
dest_start.fini ();
|
||||
dest_end.fini ();
|
||||
}
|
||||
|
||||
void drop_hints_bytes ()
|
||||
|
|
|
@ -27,7 +27,7 @@ struct VarCompositeGlyphRecord
|
|||
HAVE_SKEW_Y = 0x0200,
|
||||
HAVE_TCENTER_X = 0x0400,
|
||||
HAVE_TCENTER_Y = 0x0800,
|
||||
GID_IS_24BIT = 0x1000,
|
||||
GID_IS_24 = 0x1000,
|
||||
AXES_HAVE_VARIATION = 0x2000,
|
||||
RESET_UNSPECIFIED_AXES = 0x4000,
|
||||
};
|
||||
|
@ -43,7 +43,7 @@ struct VarCompositeGlyphRecord
|
|||
|
||||
// gid
|
||||
size += 2;
|
||||
if (flags & GID_IS_24BIT) size += 1;
|
||||
if (flags & GID_IS_24) size += 1;
|
||||
|
||||
if (flags & HAVE_TRANSLATE_X) size += 2;
|
||||
if (flags & HAVE_TRANSLATE_Y) size += 2;
|
||||
|
@ -65,20 +65,12 @@ struct VarCompositeGlyphRecord
|
|||
|
||||
hb_codepoint_t get_gid () const
|
||||
{
|
||||
if (flags & GID_IS_24BIT)
|
||||
if (flags & GID_IS_24)
|
||||
return StructAfter<const HBGlyphID24> (numAxes);
|
||||
else
|
||||
return StructAfter<const HBGlyphID16> (numAxes);
|
||||
}
|
||||
|
||||
void set_gid (hb_codepoint_t gid)
|
||||
{
|
||||
if (flags & GID_IS_24BIT)
|
||||
StructAfter<HBGlyphID24> (numAxes) = gid;
|
||||
else
|
||||
StructAfter<HBGlyphID16> (numAxes) = gid;
|
||||
}
|
||||
|
||||
unsigned get_numAxes () const
|
||||
{
|
||||
return numAxes;
|
||||
|
@ -153,7 +145,7 @@ struct VarCompositeGlyphRecord
|
|||
float rotation)
|
||||
{
|
||||
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240
|
||||
rotation = rotation * HB_PI;
|
||||
rotation = rotation * float (M_PI);
|
||||
float c = cosf (rotation);
|
||||
float s = sinf (rotation);
|
||||
float other[6] = {c, s, -s, c, 0.f, 0.f};
|
||||
|
@ -164,8 +156,8 @@ struct VarCompositeGlyphRecord
|
|||
float skewX, float skewY)
|
||||
{
|
||||
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255
|
||||
skewX = skewX * HB_PI;
|
||||
skewY = skewY * HB_PI;
|
||||
skewX = skewX * float (M_PI);
|
||||
skewY = skewY * float (M_PI);
|
||||
float other[6] = {1.f, tanf (skewY), tanf (skewX), 1.f, 0.f, 0.f};
|
||||
transform (matrix, trans, other);
|
||||
}
|
||||
|
@ -188,7 +180,7 @@ struct VarCompositeGlyphRecord
|
|||
unsigned axes_size = numAxes * axis_width;
|
||||
|
||||
const F2DOT14 *q = (const F2DOT14 *) (axes_size +
|
||||
(flags & GID_IS_24BIT ? 3 : 2) +
|
||||
(flags & GID_IS_24 ? 3 : 2) +
|
||||
&StructAfter<const HBUINT8> (numAxes));
|
||||
|
||||
hb_array_t<contour_point_t> rec_points = points.as_array ().sub_array (points.length - get_num_points ());
|
||||
|
@ -316,8 +308,8 @@ struct VarCompositeGlyphRecord
|
|||
bool have_variations = flags & AXES_HAVE_VARIATION;
|
||||
unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
|
||||
|
||||
const HBUINT8 *p = (const HBUINT8 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24BIT ? 3 : 2));
|
||||
const HBUINT16 *q = (const HBUINT16 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24BIT ? 3 : 2));
|
||||
const HBUINT8 *p = (const HBUINT8 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24 ? 3 : 2));
|
||||
const HBUINT16 *q = (const HBUINT16 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24 ? 3 : 2));
|
||||
|
||||
const F2DOT14 *a = (const F2DOT14 *) ((HBUINT8 *) (axis_width == 1 ? (p + numAxes) : (HBUINT8 *) (q + numAxes)));
|
||||
|
||||
|
@ -352,13 +344,6 @@ struct VarCompositeGlyph
|
|||
var_composite_iter_t iter () const
|
||||
{ return var_composite_iter_t (bytes, &StructAfter<VarCompositeGlyphRecord, GlyphHeader> (header)); }
|
||||
|
||||
const hb_bytes_t trim_padding () const
|
||||
{
|
||||
unsigned length = GlyphHeader::static_size;
|
||||
for (auto &comp : iter ())
|
||||
length += comp.get_size ();
|
||||
return bytes.sub_array (0, length);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -31,12 +31,6 @@ struct glyf
|
|||
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_glyf;
|
||||
|
||||
static bool has_valid_glyf_format(const hb_face_t* face)
|
||||
{
|
||||
const OT::head &head = *face->table.head;
|
||||
return head.indexToLocFormat <= 1 && head.glyphDataFormat <= 1;
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -78,13 +72,6 @@ struct glyf
|
|||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
if (!has_valid_glyf_format (c->plan->source)) {
|
||||
// glyf format is unknown don't attempt to subset it.
|
||||
DEBUG_MSG (SUBSET, nullptr,
|
||||
"unkown glyf format, dropping from subset.");
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
glyf *glyf_prime = c->serializer->start_embed <glyf> ();
|
||||
if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
|
||||
|
||||
|
@ -98,17 +85,11 @@ struct glyf
|
|||
hb_vector_t<unsigned> padded_offsets;
|
||||
unsigned num_glyphs = c->plan->num_output_glyphs ();
|
||||
if (unlikely (!padded_offsets.resize (num_glyphs)))
|
||||
{
|
||||
hb_font_destroy (font);
|
||||
return false;
|
||||
}
|
||||
|
||||
hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
|
||||
if (!_populate_subset_glyphs (c->plan, font, glyphs))
|
||||
{
|
||||
hb_font_destroy (font);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (font)
|
||||
hb_font_destroy (font);
|
||||
|
@ -129,11 +110,12 @@ struct glyf
|
|||
padded_offsets[i] = glyphs[i].length ();
|
||||
}
|
||||
|
||||
bool result = glyf_prime->serialize (c->serializer, glyphs.writer (), use_short_loca, c->plan);
|
||||
if (c->plan->normalized_coords && !c->plan->pinned_at_default)
|
||||
_free_compiled_subset_glyphs (glyphs);
|
||||
|
||||
if (!result) return false;
|
||||
if (!glyf_prime->serialize (c->serializer, glyphs.writer (), use_short_loca, c->plan))
|
||||
{
|
||||
if (c->plan->normalized_coords && !c->plan->pinned_at_default)
|
||||
_free_compiled_subset_glyphs (glyphs, glyphs.length - 1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (unlikely (c->serializer->in_error ())) return_trace (false);
|
||||
|
||||
|
@ -150,9 +132,9 @@ struct glyf
|
|||
hb_font_t *
|
||||
_create_font_for_instancing (const hb_subset_plan_t *plan) const;
|
||||
|
||||
void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> &glyphs) const
|
||||
void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> &glyphs, unsigned index) const
|
||||
{
|
||||
for (unsigned i = 0; i < glyphs.length; i++)
|
||||
for (unsigned i = 0; i <= index && i < glyphs.length; i++)
|
||||
glyphs[i].free_compiled_bytes ();
|
||||
}
|
||||
|
||||
|
@ -181,7 +163,7 @@ struct glyf_accelerator_t
|
|||
vmtx = nullptr;
|
||||
#endif
|
||||
const OT::head &head = *face->table.head;
|
||||
if (!glyf::has_valid_glyf_format (face))
|
||||
if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
|
||||
/* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
|
||||
return;
|
||||
short_offset = 0 == head.indexToLocFormat;
|
||||
|
@ -241,8 +223,6 @@ struct glyf_accelerator_t
|
|||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
struct points_aggregator_t
|
||||
{
|
||||
|
@ -306,6 +286,7 @@ struct glyf_accelerator_t
|
|||
contour_point_t *get_phantoms_sink () { return phantoms; }
|
||||
};
|
||||
|
||||
public:
|
||||
unsigned
|
||||
get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
|
||||
{
|
||||
|
@ -347,15 +328,6 @@ struct glyf_accelerator_t
|
|||
}
|
||||
#endif
|
||||
|
||||
bool get_leading_bearing_without_var_unscaled (hb_codepoint_t gid, bool is_vertical, int *lsb) const
|
||||
{
|
||||
if (unlikely (gid >= num_glyphs)) return false;
|
||||
if (is_vertical) return false; // TODO Humm, what to do here?
|
||||
|
||||
*lsb = glyph_for_gid (gid).get_header ()->xMin;
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
|
||||
{
|
||||
|
@ -434,6 +406,7 @@ glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
|
|||
unsigned num_glyphs = plan->num_output_glyphs ();
|
||||
if (!glyphs.resize (num_glyphs)) return false;
|
||||
|
||||
unsigned idx = 0;
|
||||
for (auto p : plan->glyph_map->iter ())
|
||||
{
|
||||
unsigned new_gid = p.second;
|
||||
|
@ -461,10 +434,11 @@ glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
|
|||
if (unlikely (!subset_glyph.compile_bytes_with_deltas (plan, font, glyf)))
|
||||
{
|
||||
// when pinned at default, only bounds are updated, thus no need to free
|
||||
if (!plan->pinned_at_default)
|
||||
_free_compiled_subset_glyphs (glyphs);
|
||||
if (!plan->pinned_at_default && idx > 0)
|
||||
_free_compiled_subset_glyphs (glyphs, idx - 1);
|
||||
return false;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -478,10 +452,7 @@ glyf::_create_font_for_instancing (const hb_subset_plan_t *plan) const
|
|||
|
||||
hb_vector_t<hb_variation_t> vars;
|
||||
if (unlikely (!vars.alloc (plan->user_axes_location.get_population (), true)))
|
||||
{
|
||||
hb_font_destroy (font);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (auto _ : plan->user_axes_location)
|
||||
{
|
||||
|
|
|
@ -26,29 +26,22 @@ struct path_builder_t
|
|||
|
||||
optional_point_t lerp (optional_point_t p, float t)
|
||||
{ return optional_point_t (x + t * (p.x - x), y + t * (p.y - y)); }
|
||||
} first_oncurve, first_offcurve, first_offcurve2, last_offcurve, last_offcurve2;
|
||||
} first_oncurve, first_offcurve, last_offcurve;
|
||||
|
||||
path_builder_t (hb_font_t *font_, hb_draw_session_t &draw_session_)
|
||||
{
|
||||
font = font_;
|
||||
draw_session = &draw_session_;
|
||||
first_oncurve = first_offcurve = first_offcurve2 = last_offcurve = last_offcurve2 = optional_point_t ();
|
||||
first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
|
||||
}
|
||||
|
||||
/* based on https://github.com/RazrFalcon/ttf-parser/blob/4f32821/src/glyf.rs#L287
|
||||
See also:
|
||||
* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM01/Chap1.html
|
||||
* https://stackoverflow.com/a/20772557
|
||||
*
|
||||
* Cubic support added. */
|
||||
* https://stackoverflow.com/a/20772557 */
|
||||
void consume_point (const contour_point_t &point)
|
||||
{
|
||||
bool is_on_curve = point.flag & glyf_impl::SimpleGlyph::FLAG_ON_CURVE;
|
||||
#ifdef HB_NO_CUBIC_GLYF
|
||||
bool is_cubic = false;
|
||||
#else
|
||||
bool is_cubic = !is_on_curve && (point.flag & glyf_impl::SimpleGlyph::FLAG_CUBIC);
|
||||
#endif
|
||||
optional_point_t p (font->em_fscalef_x (point.x), font->em_fscalef_y (point.y));
|
||||
if (!first_oncurve)
|
||||
{
|
||||
|
@ -59,12 +52,7 @@ struct path_builder_t
|
|||
}
|
||||
else
|
||||
{
|
||||
if (is_cubic && !first_offcurve2)
|
||||
{
|
||||
first_offcurve2 = first_offcurve;
|
||||
first_offcurve = p;
|
||||
}
|
||||
else if (first_offcurve)
|
||||
if (first_offcurve)
|
||||
{
|
||||
optional_point_t mid = first_offcurve.lerp (p, .5f);
|
||||
first_oncurve = mid;
|
||||
|
@ -81,41 +69,16 @@ struct path_builder_t
|
|||
{
|
||||
if (is_on_curve)
|
||||
{
|
||||
if (last_offcurve2)
|
||||
{
|
||||
draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
|
||||
last_offcurve.x, last_offcurve.y,
|
||||
p.x, p.y);
|
||||
last_offcurve2 = optional_point_t ();
|
||||
}
|
||||
else
|
||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||
p.x, p.y);
|
||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||
p.x, p.y);
|
||||
last_offcurve = optional_point_t ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_cubic && !last_offcurve2)
|
||||
{
|
||||
last_offcurve2 = last_offcurve;
|
||||
last_offcurve = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
optional_point_t mid = last_offcurve.lerp (p, .5f);
|
||||
|
||||
if (is_cubic)
|
||||
{
|
||||
draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
|
||||
last_offcurve.x, last_offcurve.y,
|
||||
mid.x, mid.y);
|
||||
last_offcurve2 = optional_point_t ();
|
||||
}
|
||||
else
|
||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||
mid.x, mid.y);
|
||||
last_offcurve = p;
|
||||
}
|
||||
optional_point_t mid = last_offcurve.lerp (p, .5f);
|
||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||
mid.x, mid.y);
|
||||
last_offcurve = p;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -131,40 +94,19 @@ struct path_builder_t
|
|||
{
|
||||
if (first_offcurve && last_offcurve)
|
||||
{
|
||||
optional_point_t mid = last_offcurve.lerp (first_offcurve2 ?
|
||||
first_offcurve2 :
|
||||
first_offcurve, .5f);
|
||||
if (last_offcurve2)
|
||||
draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
|
||||
last_offcurve.x, last_offcurve.y,
|
||||
mid.x, mid.y);
|
||||
else
|
||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||
mid.x, mid.y);
|
||||
optional_point_t mid = last_offcurve.lerp (first_offcurve, .5f);
|
||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||
mid.x, mid.y);
|
||||
last_offcurve = optional_point_t ();
|
||||
/* now check the rest */
|
||||
}
|
||||
/* now check the rest */
|
||||
|
||||
if (first_offcurve && first_oncurve)
|
||||
{
|
||||
if (first_offcurve2)
|
||||
draw_session->cubic_to (first_offcurve2.x, first_offcurve2.y,
|
||||
first_offcurve.x, first_offcurve.y,
|
||||
first_oncurve.x, first_oncurve.y);
|
||||
else
|
||||
draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
|
||||
first_oncurve.x, first_oncurve.y);
|
||||
}
|
||||
draw_session->quadratic_to (first_offcurve.x, first_offcurve.y,
|
||||
first_oncurve.x, first_oncurve.y);
|
||||
else if (last_offcurve && first_oncurve)
|
||||
{
|
||||
if (last_offcurve2)
|
||||
draw_session->cubic_to (last_offcurve2.x, last_offcurve2.y,
|
||||
last_offcurve.x, last_offcurve.y,
|
||||
first_oncurve.x, first_oncurve.y);
|
||||
else
|
||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||
first_oncurve.x, first_oncurve.y);
|
||||
}
|
||||
draw_session->quadratic_to (last_offcurve.x, last_offcurve.y,
|
||||
first_oncurve.x, first_oncurve.y);
|
||||
else if (first_oncurve)
|
||||
draw_session->line_to (first_oncurve.x, first_oncurve.y);
|
||||
else if (first_offcurve)
|
||||
|
@ -175,7 +117,7 @@ struct path_builder_t
|
|||
}
|
||||
|
||||
/* Getting ready for the next contour */
|
||||
first_oncurve = first_offcurve = last_offcurve = last_offcurve2 = optional_point_t ();
|
||||
first_oncurve = first_offcurve = last_offcurve = optional_point_t ();
|
||||
draw_session->close_path ();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,7 @@ symbols = sorted (re.findall (r"^hb_\w+(?= \()", "\n".join (headers_content), re
|
|||
if '--experimental-api' not in sys.argv:
|
||||
# Move these to harfbuzz-sections.txt when got stable
|
||||
experimental_symbols = \
|
||||
"""hb_shape_justify
|
||||
hb_subset_repack_or_fail
|
||||
"""hb_subset_repack_or_fail
|
||||
hb_subset_input_override_name_table
|
||||
""".splitlines ()
|
||||
symbols = [x for x in symbols if x not in experimental_symbols]
|
||||
|
|
|
@ -12,17 +12,13 @@ list(GET _harfbuzz_version_info 2
|
|||
_harfbuzz_age)
|
||||
unset(_harfbuzz_version_info)
|
||||
|
||||
if ("@default_library@" MATCHES "static")
|
||||
set(_harfbuzz_lib_suffix ".a")
|
||||
if (APPLE)
|
||||
set(_harfbuzz_lib_suffix ".0${CMAKE_SHARED_LIBRARY_SUFFIX}")
|
||||
elseif (UNIX)
|
||||
set(_harfbuzz_lib_suffix "${CMAKE_SHARED_LIBRARY_SUFFIX}.0.${_harfbuzz_current}.${_harfbuzz_revision}")
|
||||
else ()
|
||||
if (APPLE)
|
||||
set(_harfbuzz_lib_suffix ".0${CMAKE_SHARED_LIBRARY_SUFFIX}")
|
||||
elseif (UNIX)
|
||||
set(_harfbuzz_lib_suffix "${CMAKE_SHARED_LIBRARY_SUFFIX}.0.${_harfbuzz_current}.${_harfbuzz_revision}")
|
||||
else ()
|
||||
# Unsupported.
|
||||
set(harfbuzz_FOUND 0)
|
||||
endif ()
|
||||
# Unsupported.
|
||||
set(harfbuzz_FOUND 0)
|
||||
endif ()
|
||||
|
||||
# Add the libraries.
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
#include "hb-ot-shaper-vowel-constraints.cc"
|
||||
#include "hb-ot-tag.cc"
|
||||
#include "hb-ot-var.cc"
|
||||
#include "hb-outline.cc"
|
||||
#include "hb-paint-extents.cc"
|
||||
#include "hb-paint.cc"
|
||||
#include "hb-set.cc"
|
||||
|
|
|
@ -46,7 +46,6 @@
|
|||
#include "hb-ot-shaper-vowel-constraints.cc"
|
||||
#include "hb-ot-tag.cc"
|
||||
#include "hb-ot-var.cc"
|
||||
#include "hb-outline.cc"
|
||||
#include "hb-paint-extents.cc"
|
||||
#include "hb-paint.cc"
|
||||
#include "hb-set.cc"
|
||||
|
|
|
@ -464,8 +464,7 @@ enum { DELETED_GLYPH = 0xFFFF };
|
|||
template <typename T>
|
||||
struct Entry
|
||||
{
|
||||
// This does seem like it's ever called.
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
/* Note, we don't recurse-sanitize data because we don't access it.
|
||||
|
@ -493,8 +492,7 @@ struct Entry
|
|||
template <>
|
||||
struct Entry<void>
|
||||
{
|
||||
// This does seem like it's ever called.
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
bool sanitize (hb_sanitize_context_t *c, unsigned int count /*XXX Unused?*/) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this));
|
||||
|
|
|
@ -110,10 +110,9 @@ struct BEInt<Type, 2>
|
|||
constexpr operator Type () const
|
||||
{
|
||||
#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
|
||||
((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
|
||||
defined(__BYTE_ORDER) && \
|
||||
(__BYTE_ORDER == __BIG_ENDIAN || \
|
||||
(__BYTE_ORDER == __LITTLE_ENDIAN && \
|
||||
hb_has_builtin(__builtin_bswap16)))
|
||||
(__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
|
||||
/* Spoon-feed the compiler a big-endian integer with alignment 1.
|
||||
* https://github.com/harfbuzz/harfbuzz/pull/1398 */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
|
@ -156,10 +155,9 @@ struct BEInt<Type, 4>
|
|||
struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
|
||||
constexpr operator Type () const {
|
||||
#if defined(__OPTIMIZE__) && !defined(HB_NO_PACKED) && \
|
||||
((defined(__GNUC__) && __GNUC__ >= 5) || defined(__clang__)) && \
|
||||
defined(__BYTE_ORDER) && \
|
||||
(__BYTE_ORDER == __BIG_ENDIAN || \
|
||||
(__BYTE_ORDER == __LITTLE_ENDIAN && \
|
||||
hb_has_builtin(__builtin_bswap32)))
|
||||
(__BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __BIG_ENDIAN)
|
||||
/* Spoon-feed the compiler a big-endian integer with alignment 1.
|
||||
* https://github.com/harfbuzz/harfbuzz/pull/1398 */
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
|
@ -600,17 +598,13 @@ template <typename T>
|
|||
static inline unsigned int
|
||||
hb_popcount (T v)
|
||||
{
|
||||
#if hb_has_builtin(__builtin_popcount)
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
|
||||
if (sizeof (T) <= sizeof (unsigned int))
|
||||
return __builtin_popcount (v);
|
||||
#endif
|
||||
|
||||
#if hb_has_builtin(__builtin_popcountl)
|
||||
if (sizeof (T) <= sizeof (unsigned long))
|
||||
return __builtin_popcountl (v);
|
||||
#endif
|
||||
|
||||
#if hb_has_builtin(__builtin_popcountll)
|
||||
if (sizeof (T) <= sizeof (unsigned long long))
|
||||
return __builtin_popcountll (v);
|
||||
#endif
|
||||
|
@ -647,17 +641,13 @@ hb_bit_storage (T v)
|
|||
{
|
||||
if (unlikely (!v)) return 0;
|
||||
|
||||
#if hb_has_builtin(__builtin_clz)
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
|
||||
if (sizeof (T) <= sizeof (unsigned int))
|
||||
return sizeof (unsigned int) * 8 - __builtin_clz (v);
|
||||
#endif
|
||||
|
||||
#if hb_has_builtin(__builtin_clzl)
|
||||
if (sizeof (T) <= sizeof (unsigned long))
|
||||
return sizeof (unsigned long) * 8 - __builtin_clzl (v);
|
||||
#endif
|
||||
|
||||
#if hb_has_builtin(__builtin_clzll)
|
||||
if (sizeof (T) <= sizeof (unsigned long long))
|
||||
return sizeof (unsigned long long) * 8 - __builtin_clzll (v);
|
||||
#endif
|
||||
|
@ -725,17 +715,13 @@ hb_ctz (T v)
|
|||
{
|
||||
if (unlikely (!v)) return 8 * sizeof (T);
|
||||
|
||||
#if hb_has_builtin(__builtin_ctz)
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__)
|
||||
if (sizeof (T) <= sizeof (unsigned int))
|
||||
return __builtin_ctz (v);
|
||||
#endif
|
||||
|
||||
#if hb_has_builtin(__builtin_ctzl)
|
||||
if (sizeof (T) <= sizeof (unsigned long))
|
||||
return __builtin_ctzl (v);
|
||||
#endif
|
||||
|
||||
#if hb_has_builtin(__builtin_ctzll)
|
||||
if (sizeof (T) <= sizeof (unsigned long long))
|
||||
return __builtin_ctzll (v);
|
||||
#endif
|
||||
|
@ -889,7 +875,7 @@ hb_in_ranges (T u, T lo1, T hi1, Ts... ds)
|
|||
static inline bool
|
||||
hb_unsigned_mul_overflows (unsigned int count, unsigned int size, unsigned *result = nullptr)
|
||||
{
|
||||
#if hb_has_builtin(__builtin_mul_overflow)
|
||||
#if (defined(__GNUC__) && (__GNUC__ >= 4)) || (defined(__clang__) && (__clang_major__ >= 8))
|
||||
unsigned stack_result;
|
||||
if (!result)
|
||||
result = &stack_result;
|
||||
|
@ -1344,62 +1330,4 @@ struct
|
|||
HB_FUNCOBJ (hb_dec);
|
||||
|
||||
|
||||
/* Adapted from kurbo implementation with extra parameters added,
|
||||
* and finding for a particular range instead of 0.
|
||||
*
|
||||
* For documentation and implementation see:
|
||||
*
|
||||
* [ITP method]: https://en.wikipedia.org/wiki/ITP_Method
|
||||
* [An Enhancement of the Bisection Method Average Performance Preserving Minmax Optimality]: https://dl.acm.org/doi/10.1145/3423597
|
||||
* https://docs.rs/kurbo/0.8.1/kurbo/common/fn.solve_itp.html
|
||||
* https://github.com/linebender/kurbo/blob/fd839c25ea0c98576c7ce5789305822675a89938/src/common.rs#L162-L248
|
||||
*/
|
||||
template <typename func_t>
|
||||
double solve_itp (func_t f,
|
||||
double a, double b,
|
||||
double epsilon,
|
||||
double min_y, double max_y,
|
||||
double &ya, double &yb, double &y)
|
||||
{
|
||||
unsigned n1_2 = (unsigned) (hb_max (ceil (log2 ((b - a) / epsilon)) - 1.0, 0.0));
|
||||
const unsigned n0 = 1; // Hardwired
|
||||
const double k1 = 0.2 / (b - a); // Hardwired.
|
||||
unsigned nmax = n0 + n1_2;
|
||||
double scaled_epsilon = epsilon * double (1llu << nmax);
|
||||
double _2_epsilon = 2.0 * epsilon;
|
||||
while (b - a > _2_epsilon)
|
||||
{
|
||||
double x1_2 = 0.5 * (a + b);
|
||||
double r = scaled_epsilon - 0.5 * (b - a);
|
||||
double xf = (yb * a - ya * b) / (yb - ya);
|
||||
double sigma = x1_2 - xf;
|
||||
double b_a = b - a;
|
||||
// This has k2 = 2 hardwired for efficiency.
|
||||
double b_a_k2 = b_a * b_a;
|
||||
double delta = k1 * b_a_k2;
|
||||
int sigma_sign = sigma >= 0 ? +1 : -1;
|
||||
double xt = delta <= fabs (x1_2 - xf) ? xf + delta * sigma_sign : x1_2;
|
||||
double xitp = fabs (xt - x1_2) <= r ? xt : x1_2 - r * sigma_sign;
|
||||
double yitp = f (xitp);
|
||||
if (yitp > max_y)
|
||||
{
|
||||
b = xitp;
|
||||
yb = yitp;
|
||||
}
|
||||
else if (yitp < min_y)
|
||||
{
|
||||
a = xitp;
|
||||
ya = yitp;
|
||||
}
|
||||
else
|
||||
{
|
||||
y = yitp;
|
||||
return xitp;
|
||||
}
|
||||
scaled_epsilon *= 0.5;
|
||||
}
|
||||
return 0.5 * (a + b);
|
||||
}
|
||||
|
||||
|
||||
#endif /* HB_ALGS_HH */
|
||||
|
|
|
@ -304,9 +304,6 @@ struct hb_array_t : hb_iter_with_fallback_t<hb_array_t<Type>, Type&>
|
|||
unsigned int backwards_length = 0;
|
||||
};
|
||||
template <typename T> inline hb_array_t<T>
|
||||
hb_array ()
|
||||
{ return hb_array_t<T> (); }
|
||||
template <typename T> inline hb_array_t<T>
|
||||
hb_array (T *array, unsigned int length)
|
||||
{ return hb_array_t<T> (array, length); }
|
||||
template <typename T, unsigned int length_> inline hb_array_t<T>
|
||||
|
|
|
@ -38,10 +38,6 @@
|
|||
|
||||
/*
|
||||
* Atomic integers and pointers.
|
||||
*
|
||||
* hb_atomic_int_t and hb_atomic_ptr_t are typedefs to the actual
|
||||
* atomic type. They are guaranteed to be at least 32 bits wide.
|
||||
* hb_atomic_int_t is signed.
|
||||
*/
|
||||
|
||||
|
||||
|
@ -115,15 +111,10 @@ _hb_atomic_ptr_impl_cmplexch (const void **P, const void *O_, const void *N)
|
|||
#endif
|
||||
|
||||
|
||||
/* This should never be disabled, even under HB_NO_MT.
|
||||
* except that MSVC gives me an internal compiler error, so disabled there.
|
||||
*
|
||||
* https://github.com/harfbuzz/harfbuzz/pull/4119
|
||||
*/
|
||||
#ifndef _hb_compiler_memory_r_barrier
|
||||
#if defined(__ATOMIC_ACQUIRE) // gcc-like
|
||||
#define _hb_compiler_memory_r_barrier() asm volatile("": : :"memory")
|
||||
#elif !defined(_MSC_VER)
|
||||
/* This we always use std::atomic for; and should never be disabled...
|
||||
* except that MSVC gives me an internal compiler error on it. */
|
||||
#if !defined(_MSC_VER)
|
||||
#include <atomic>
|
||||
#define _hb_compiler_memory_r_barrier() std::atomic_signal_fence (std::memory_order_acquire)
|
||||
#else
|
||||
|
|
|
@ -194,7 +194,7 @@ struct hb_bit_set_t
|
|||
unsigned int end = major_start (m + 1);
|
||||
do
|
||||
{
|
||||
if (g != INVALID && (v || page)) /* The v check is to optimize out the page check if v is true. */
|
||||
if (v || page) /* The v check is to optimize out the page check if v is true. */
|
||||
page->set (g, v);
|
||||
|
||||
array = &StructAtOffsetUnaligned<T> (array, stride);
|
||||
|
@ -238,7 +238,7 @@ struct hb_bit_set_t
|
|||
if (g < last_g) return false;
|
||||
last_g = g;
|
||||
|
||||
if (g != INVALID && (v || page)) /* The v check is to optimize out the page check if v is true. */
|
||||
if (v || page) /* The v check is to optimize out the page check if v is true. */
|
||||
page->add (g);
|
||||
|
||||
array = &StructAtOffsetUnaligned<T> (array, stride);
|
||||
|
|
|
@ -676,7 +676,7 @@ fail_without_close:
|
|||
wchar_t * wchar_file_name = (wchar_t *) hb_malloc (sizeof (wchar_t) * size);
|
||||
if (unlikely (!wchar_file_name)) goto fail_without_close;
|
||||
mbstowcs (wchar_file_name, file_name, size);
|
||||
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
|
||||
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
{
|
||||
CREATEFILE2_EXTENDED_PARAMETERS ceparams = { 0 };
|
||||
ceparams.dwSize = sizeof(CREATEFILE2_EXTENDED_PARAMETERS);
|
||||
|
@ -697,7 +697,7 @@ fail_without_close:
|
|||
|
||||
if (unlikely (fd == INVALID_HANDLE_VALUE)) goto fail_without_close;
|
||||
|
||||
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
|
||||
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
{
|
||||
LARGE_INTEGER length;
|
||||
GetFileSizeEx (fd, &length);
|
||||
|
@ -710,7 +710,7 @@ fail_without_close:
|
|||
#endif
|
||||
if (unlikely (!file->mapping)) goto fail;
|
||||
|
||||
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
|
||||
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
file->contents = (char *) MapViewOfFileFromApp (file->mapping, FILE_MAP_READ, 0, 0);
|
||||
#else
|
||||
file->contents = (char *) MapViewOfFile (file->mapping, FILE_MAP_READ, 0, 0, 0);
|
||||
|
|
|
@ -63,7 +63,7 @@ HB_BEGIN_DECLS
|
|||
* HarfBuzz and doing that just once (no reuse!),
|
||||
*
|
||||
* - If the font is mmap()ed, it's okay to use
|
||||
* @HB_MEMORY_MODE_READONLY_MAY_MAKE_WRITABLE, however, using that mode
|
||||
* @HB_MEMORY_READONLY_MAY_MAKE_WRITABLE, however, using that mode
|
||||
* correctly is very tricky. Use @HB_MEMORY_MODE_READONLY instead.
|
||||
**/
|
||||
typedef enum {
|
||||
|
|
|
@ -40,11 +40,6 @@
|
|||
* Buffers serve a dual role in HarfBuzz; before shaping, they hold
|
||||
* the input characters that are passed to hb_shape(), and after
|
||||
* shaping they hold the output glyphs.
|
||||
*
|
||||
* The input buffer is a sequence of Unicode codepoints, with
|
||||
* associated attributes such as direction and script. The output
|
||||
* buffer is a sequence of glyphs, with associated attributes such
|
||||
* as position and cluster.
|
||||
**/
|
||||
|
||||
|
||||
|
@ -527,17 +522,15 @@ hb_buffer_t::merge_clusters_impl (unsigned int start,
|
|||
cluster = hb_min (cluster, info[i].cluster);
|
||||
|
||||
/* Extend end */
|
||||
if (cluster != info[end - 1].cluster)
|
||||
while (end < len && info[end - 1].cluster == info[end].cluster)
|
||||
end++;
|
||||
while (end < len && info[end - 1].cluster == info[end].cluster)
|
||||
end++;
|
||||
|
||||
/* Extend start */
|
||||
if (cluster != info[start].cluster)
|
||||
while (idx < start && info[start - 1].cluster == info[start].cluster)
|
||||
start--;
|
||||
while (idx < start && info[start - 1].cluster == info[start].cluster)
|
||||
start--;
|
||||
|
||||
/* If we hit the start of buffer, continue in out-buffer. */
|
||||
if (idx == start && info[start].cluster != cluster)
|
||||
if (idx == start)
|
||||
for (unsigned int i = out_len; i && out_info[i - 1].cluster == info[start].cluster; i--)
|
||||
set_cluster (out_info[i - 1], cluster);
|
||||
|
||||
|
|
|
@ -581,59 +581,21 @@ struct hb_buffer_t
|
|||
unsigned int cluster,
|
||||
hb_mask_t mask)
|
||||
{
|
||||
if (unlikely (start == end))
|
||||
return;
|
||||
|
||||
unsigned cluster_first = infos[start].cluster;
|
||||
unsigned cluster_last = infos[end - 1].cluster;
|
||||
|
||||
if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS ||
|
||||
(cluster != cluster_first && cluster != cluster_last))
|
||||
{
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
if (cluster != infos[i].cluster)
|
||||
{
|
||||
scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
|
||||
infos[i].mask |= mask;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Monotone clusters */
|
||||
|
||||
if (cluster == cluster_first)
|
||||
{
|
||||
for (unsigned int i = end; start < i && infos[i - 1].cluster != cluster_first; i--)
|
||||
{
|
||||
scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
|
||||
infos[i - 1].mask |= mask;
|
||||
}
|
||||
}
|
||||
else /* cluster == cluster_last */
|
||||
{
|
||||
for (unsigned int i = start; i < end && infos[i].cluster != cluster_last; i++)
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
if (cluster != infos[i].cluster)
|
||||
{
|
||||
scratch_flags |= HB_BUFFER_SCRATCH_FLAG_HAS_GLYPH_FLAGS;
|
||||
infos[i].mask |= mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
unsigned
|
||||
static unsigned
|
||||
_infos_find_min_cluster (const hb_glyph_info_t *infos,
|
||||
unsigned start, unsigned end,
|
||||
unsigned cluster = UINT_MAX)
|
||||
{
|
||||
if (unlikely (start == end))
|
||||
return cluster;
|
||||
|
||||
if (cluster_level == HB_BUFFER_CLUSTER_LEVEL_CHARACTERS)
|
||||
{
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
cluster = hb_min (cluster, infos[i].cluster);
|
||||
return cluster;
|
||||
}
|
||||
|
||||
return hb_min (cluster, hb_min (infos[start].cluster, infos[end - 1].cluster));
|
||||
for (unsigned int i = start; i < end; i++)
|
||||
cluster = hb_min (cluster, infos[i].cluster);
|
||||
return cluster;
|
||||
}
|
||||
|
||||
void clear_glyph_flags (hb_mask_t mask = 0)
|
||||
|
|
|
@ -30,19 +30,7 @@
|
|||
#include "hb.hh"
|
||||
|
||||
|
||||
/* Implements a lockfree cache for int->int functions.
|
||||
*
|
||||
* The cache is a fixed-size array of 16-bit or 32-bit integers.
|
||||
* The key is split into two parts: the cache index and the rest.
|
||||
*
|
||||
* The cache index is used to index into the array. The rest is used
|
||||
* to store the key and the value.
|
||||
*
|
||||
* The value is stored in the least significant bits of the integer.
|
||||
* The key is stored in the most significant bits of the integer.
|
||||
* The key is shifted by cache_bits to the left to make room for the
|
||||
* value.
|
||||
*/
|
||||
/* Implements a lockfree cache for int->int functions. */
|
||||
|
||||
template <unsigned int key_bits=16,
|
||||
unsigned int value_bits=8 + 32 - key_bits,
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2022 Red Hat, Inc
|
||||
* Copyright © 2021, 2022 Black Foundry
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
|
@ -33,14 +32,10 @@
|
|||
|
||||
#include <cairo.h>
|
||||
|
||||
/* Some routines in this file were ported from BlackRenderer by Black Foundry.
|
||||
* Used by permission to relicense to HarfBuzz license.
|
||||
*
|
||||
* https://github.com/BlackFoundryCom/black-renderer
|
||||
*/
|
||||
|
||||
#define PREALLOCATED_COLOR_STOPS 16
|
||||
|
||||
#define _2_M_PIf (2.f * float (M_PI))
|
||||
|
||||
typedef struct {
|
||||
float r, g, b, a;
|
||||
} hb_cairo_color_t;
|
||||
|
@ -320,9 +315,9 @@ _hb_cairo_paint_linear_gradient (hb_cairo_context_t *c,
|
|||
{
|
||||
cairo_t *cr = c->cr;
|
||||
|
||||
unsigned int len = PREALLOCATED_COLOR_STOPS;
|
||||
hb_color_stop_t stops_[PREALLOCATED_COLOR_STOPS];
|
||||
hb_color_stop_t *stops = stops_;
|
||||
unsigned int len = PREALLOCATED_COLOR_STOPS;
|
||||
float xx0, yy0, xx1, yy1;
|
||||
float xxx0, yyy0, xxx1, yyy1;
|
||||
float min, max;
|
||||
|
@ -368,9 +363,9 @@ _hb_cairo_paint_radial_gradient (hb_cairo_context_t *c,
|
|||
{
|
||||
cairo_t *cr = c->cr;
|
||||
|
||||
unsigned int len = PREALLOCATED_COLOR_STOPS;
|
||||
hb_color_stop_t stops_[PREALLOCATED_COLOR_STOPS];
|
||||
hb_color_stop_t *stops = stops_;
|
||||
unsigned int len;
|
||||
float min, max;
|
||||
float xx0, yy0, xx1, yy1;
|
||||
float rr0, rr1;
|
||||
|
@ -523,7 +518,7 @@ _hb_cairo_add_patch (cairo_pattern_t *pattern, hb_cairo_point_t *center, hb_cair
|
|||
cairo_mesh_pattern_end_patch (pattern);
|
||||
}
|
||||
|
||||
#define MAX_ANGLE (HB_PI / 8.f)
|
||||
#define MAX_ANGLE ((float) M_PI / 8.f)
|
||||
|
||||
static void
|
||||
_hb_cairo_add_sweep_gradient_patches1 (float cx, float cy, float radius,
|
||||
|
@ -606,7 +601,7 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops,
|
|||
start_angle, &c,
|
||||
pattern);
|
||||
}
|
||||
if (end_angle < HB_2_PI)
|
||||
if (end_angle < _2_M_PIf)
|
||||
{
|
||||
c.r = hb_color_get_red (stops[n_stops - 1].color) / 255.;
|
||||
c.g = hb_color_get_green (stops[n_stops - 1].color) / 255.;
|
||||
|
@ -614,7 +609,7 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops,
|
|||
c.a = hb_color_get_alpha (stops[n_stops - 1].color) / 255.;
|
||||
_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
|
||||
end_angle, &c,
|
||||
HB_2_PI, &c,
|
||||
_2_M_PIf, &c,
|
||||
pattern);
|
||||
}
|
||||
}
|
||||
|
@ -678,7 +673,7 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops,
|
|||
color0 = colors[n_stops-1];
|
||||
_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
|
||||
0., &color0,
|
||||
HB_2_PI, &color0,
|
||||
_2_M_PIf, &color0,
|
||||
pattern);
|
||||
goto done;
|
||||
}
|
||||
|
@ -690,7 +685,7 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops,
|
|||
|
||||
for (pos++; pos < n_stops; pos++)
|
||||
{
|
||||
if (angles[pos] <= HB_2_PI)
|
||||
if (angles[pos] <= _2_M_PIf)
|
||||
{
|
||||
_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
|
||||
angles[pos - 1], &colors[pos-1],
|
||||
|
@ -699,11 +694,11 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops,
|
|||
}
|
||||
else
|
||||
{
|
||||
float k = (HB_2_PI - angles[pos - 1]) / (angles[pos] - angles[pos - 1]);
|
||||
float k = (_2_M_PIf - angles[pos - 1]) / (angles[pos] - angles[pos - 1]);
|
||||
_hb_cairo_interpolate_colors (&colors[pos - 1], &colors[pos], k, &color1);
|
||||
_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
|
||||
angles[pos - 1], &colors[pos - 1],
|
||||
HB_2_PI, &color1,
|
||||
_2_M_PIf, &color1,
|
||||
pattern);
|
||||
break;
|
||||
}
|
||||
|
@ -715,7 +710,7 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops,
|
|||
color0 = colors[n_stops - 1];
|
||||
_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
|
||||
angles[n_stops - 1], &color0,
|
||||
HB_2_PI, &color0,
|
||||
_2_M_PIf, &color0,
|
||||
pattern);
|
||||
goto done;
|
||||
}
|
||||
|
@ -799,14 +794,14 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops,
|
|||
a1, c1,
|
||||
pattern);
|
||||
}
|
||||
else if (a1 >= HB_2_PI)
|
||||
else if (a1 >= _2_M_PIf)
|
||||
{
|
||||
hb_cairo_color_t color;
|
||||
float f = (HB_2_PI - a0)/(a1 - a0);
|
||||
float f = (_2_M_PIf - a0)/(a1 - a0);
|
||||
_hb_cairo_interpolate_colors (c0, c1, f, &color);
|
||||
_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
|
||||
a0, c0,
|
||||
HB_2_PI, &color,
|
||||
_2_M_PIf, &color,
|
||||
pattern);
|
||||
goto done;
|
||||
}
|
||||
|
@ -838,7 +833,7 @@ _hb_cairo_paint_sweep_gradient (hb_cairo_context_t *c,
|
|||
{
|
||||
cairo_t *cr = c->cr;
|
||||
|
||||
unsigned int len = PREALLOCATED_COLOR_STOPS;
|
||||
unsigned int len;
|
||||
hb_color_stop_t stops_[PREALLOCATED_COLOR_STOPS];
|
||||
hb_color_stop_t *stops = stops_;
|
||||
cairo_extend_t extend;
|
||||
|
|
|
@ -651,7 +651,7 @@ user_font_face_create (hb_face_t *face)
|
|||
*
|
||||
* Returns: (transfer full): a newly created #cairo_font_face_t
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
cairo_font_face_t *
|
||||
hb_cairo_font_face_create_for_font (hb_font_t *font)
|
||||
|
@ -677,7 +677,7 @@ hb_cairo_font_face_create_for_font (hb_font_t *font)
|
|||
*
|
||||
* Returns: (nullable) (transfer none): the #hb_font_t that @font_face was created from
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
hb_font_t *
|
||||
hb_cairo_font_face_get_font (cairo_font_face_t *font_face)
|
||||
|
@ -695,7 +695,7 @@ hb_cairo_font_face_get_font (cairo_font_face_t *font_face)
|
|||
*
|
||||
* Returns: (transfer full): a newly created #cairo_font_face_t
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
cairo_font_face_t *
|
||||
hb_cairo_font_face_create_for_face (hb_face_t *face)
|
||||
|
@ -713,7 +713,7 @@ hb_cairo_font_face_create_for_face (hb_face_t *face)
|
|||
*
|
||||
* Returns: (nullable) (transfer none): the #hb_face_t associated with @font_face
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
hb_face_t *
|
||||
hb_cairo_font_face_get_face (cairo_font_face_t *font_face)
|
||||
|
@ -733,7 +733,7 @@ hb_cairo_font_face_get_face (cairo_font_face_t *font_face)
|
|||
* face created using hb_cairo_font_face_create_for_face()
|
||||
* creates an #hb_font_t for a #cairo_scaled_font_t.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_cairo_font_face_set_font_init_func (cairo_font_face_t *font_face,
|
||||
|
@ -766,7 +766,7 @@ hb_cairo_font_face_set_font_init_func (cairo_font_face_t *font_face,
|
|||
*
|
||||
* Returns: (nullable) (transfer none): the #hb_font_t associated with @scaled_font
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
hb_font_t *
|
||||
hb_cairo_scaled_font_get_font (cairo_scaled_font_t *scaled_font)
|
||||
|
@ -814,7 +814,7 @@ hb_cairo_scaled_font_get_font (cairo_scaled_font_t *scaled_font)
|
|||
* (because you set the scale of the #hb_font_t yourself), use
|
||||
* the conversion rate involved.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_cairo_font_face_set_scale_factor (cairo_font_face_t *font_face,
|
||||
|
@ -835,7 +835,7 @@ hb_cairo_font_face_set_scale_factor (cairo_font_face_t *font_face,
|
|||
*
|
||||
* Returns: the scale factor of @font_face
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
unsigned int
|
||||
hb_cairo_font_face_get_scale_factor (cairo_font_face_t *font_face)
|
||||
|
@ -898,7 +898,7 @@ hb_cairo_font_face_get_scale_factor (cairo_font_face_t *font_face)
|
|||
* it and the x,y values of the extra entry at the end add up the advance
|
||||
* x,y of all the glyphs in the @buffer.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_cairo_glyphs_from_buffer (hb_buffer_t *buffer,
|
||||
|
|
|
@ -57,7 +57,7 @@ hb_cairo_font_face_get_face (cairo_font_face_t *font_face);
|
|||
*
|
||||
* Return value: the #hb_font_t value to use; in most cases same as @font
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
typedef hb_font_t * (*hb_cairo_font_init_func_t) (hb_font_t *font,
|
||||
cairo_scaled_font_t *scaled_font,
|
||||
|
|
|
@ -35,8 +35,10 @@ using namespace OT;
|
|||
/* an opstr and the parsed out dict value(s) */
|
||||
struct dict_val_t : op_str_t
|
||||
{
|
||||
void init () {}
|
||||
void init () { single_val.set_int (0); }
|
||||
void fini () {}
|
||||
|
||||
number_t single_val;
|
||||
};
|
||||
|
||||
typedef dict_val_t num_dict_val_t;
|
||||
|
|
|
@ -29,6 +29,32 @@
|
|||
#include "hb.hh"
|
||||
#include "hb-machinery.hh"
|
||||
|
||||
#if !defined(HB_NO_SETLOCALE) && (!defined(HAVE_NEWLOCALE) || !defined(HAVE_USELOCALE))
|
||||
#define HB_NO_SETLOCALE 1
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_SETLOCALE
|
||||
|
||||
#include <locale.h>
|
||||
#ifdef HAVE_XLOCALE_H
|
||||
#include <xlocale.h> // Needed on BSD/OS X for uselocale
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
#define hb_locale_t _locale_t
|
||||
#else
|
||||
#define hb_locale_t locale_t
|
||||
#endif
|
||||
#define hb_setlocale setlocale
|
||||
#define hb_uselocale uselocale
|
||||
|
||||
#else
|
||||
|
||||
#define hb_locale_t void *
|
||||
#define hb_setlocale(Category, Locale) "C"
|
||||
#define hb_uselocale(Locale) ((hb_locale_t) 0)
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* SECTION:hb-common
|
||||
|
@ -632,7 +658,6 @@ hb_script_get_horizontal_direction (hb_script_t script)
|
|||
case HB_SCRIPT_OLD_HUNGARIAN:
|
||||
case HB_SCRIPT_OLD_ITALIC:
|
||||
case HB_SCRIPT_RUNIC:
|
||||
case HB_SCRIPT_TIFINAGH:
|
||||
|
||||
return HB_DIRECTION_INVALID;
|
||||
}
|
||||
|
|
|
@ -37,7 +37,6 @@
|
|||
|
||||
#ifndef HB_EXPERIMENTAL_API
|
||||
#define HB_NO_BEYOND_64K
|
||||
#define HB_NO_CUBIC_GLYF
|
||||
#define HB_NO_VAR_COMPOSITES
|
||||
#endif
|
||||
|
||||
|
@ -136,10 +135,6 @@
|
|||
#define HB_NO_SUBSET_CFF
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_DRAW
|
||||
#define HB_NO_OUTLINE
|
||||
#endif
|
||||
|
||||
#ifdef HB_NO_GETENV
|
||||
#define HB_NO_UNISCRIBE_BUG_COMPATIBLE
|
||||
#endif
|
||||
|
|
|
@ -373,10 +373,6 @@ struct hb_no_trace_t {
|
|||
#define HB_DEBUG_FT (HB_DEBUG+0)
|
||||
#endif
|
||||
|
||||
#ifndef HB_DEBUG_JUSTIFY
|
||||
#define HB_DEBUG_JUSTIFY (HB_DEBUG+0)
|
||||
#endif
|
||||
|
||||
#ifndef HB_DEBUG_OBJECT
|
||||
#define HB_DEBUG_OBJECT (HB_DEBUG+0)
|
||||
#endif
|
||||
|
|
|
@ -207,7 +207,7 @@ DEFINE_NULL_INSTANCE (hb_draw_funcs_t) =
|
|||
*
|
||||
* Return value: (transfer full): The empty draw-functions structure
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
hb_draw_funcs_t *
|
||||
hb_draw_funcs_get_empty ()
|
||||
|
@ -276,7 +276,7 @@ hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs)
|
|||
*
|
||||
* Return value: `true` if success, `false` otherwise
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_draw_funcs_set_user_data (hb_draw_funcs_t *dfuncs,
|
||||
|
@ -298,7 +298,7 @@ hb_draw_funcs_set_user_data (hb_draw_funcs_t *dfuncs,
|
|||
*
|
||||
* Return value: (transfer none): A pointer to the user data
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
void *
|
||||
hb_draw_funcs_get_user_data (const hb_draw_funcs_t *dfuncs,
|
||||
|
|
|
@ -47,12 +47,6 @@
|
|||
* More precisely, 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.
|
||||
*
|
||||
* A font face can be created from a binary blob using hb_face_create().
|
||||
* The face index is used to select a face from a binary blob that contains
|
||||
* multiple faces. For example, a binary blob that contains both a regular
|
||||
* and a bold face can be used to create two font faces, one for each face
|
||||
* index.
|
||||
**/
|
||||
|
||||
|
||||
|
@ -203,7 +197,7 @@ _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void
|
|||
* a face index into that blob.
|
||||
*
|
||||
* The face index is used for blobs of file formats such as TTC and
|
||||
* DFont that can contain more than one face. Face indices within
|
||||
* and DFont that can contain more than one face. Face indices within
|
||||
* such collections are zero-based.
|
||||
*
|
||||
* <note>Note: If the blob font format is not a collection, @index
|
||||
|
@ -615,7 +609,7 @@ hb_face_collect_unicodes (hb_face_t *face,
|
|||
* Collects the mapping from Unicode characters to nominal glyphs of the @face,
|
||||
* and optionally all of the Unicode characters covered by @face.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_face_collect_nominal_glyph_mapping (hb_face_t *face,
|
||||
|
|
|
@ -76,7 +76,7 @@ struct hb_face_t
|
|||
if (unlikely (!reference_table_func))
|
||||
return hb_blob_get_empty ();
|
||||
|
||||
blob = reference_table_func (/*Oh, well.*/const_cast<hb_face_t *> (this), tag, user_data);
|
||||
blob = reference_table_func (/*XXX*/const_cast<hb_face_t *> (this), tag, user_data);
|
||||
if (unlikely (!blob))
|
||||
return hb_blob_get_empty ();
|
||||
|
||||
|
|
172
src/hb-font.cc
172
src/hb-font.cc
|
@ -59,11 +59,6 @@
|
|||
*
|
||||
* HarfBuzz provides a built-in set of lightweight default
|
||||
* functions for each method in #hb_font_funcs_t.
|
||||
*
|
||||
* The default font functions are implemented in terms of the
|
||||
* #hb_font_funcs_t methods of the parent font object. This allows
|
||||
* client programs to override only the methods they need to, and
|
||||
* otherwise inherit the parent font's implementation, if any.
|
||||
**/
|
||||
|
||||
|
||||
|
@ -1392,7 +1387,7 @@ hb_font_get_glyph_from_name (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_get_glyph_shape:
|
||||
* @font: #hb_font_t to work upon
|
||||
* @glyph: The glyph ID
|
||||
* @glyph: : The glyph ID
|
||||
* @dfuncs: #hb_draw_funcs_t to draw to
|
||||
* @draw_data: User data to pass to draw callbacks
|
||||
*
|
||||
|
@ -1401,7 +1396,6 @@ hb_font_get_glyph_from_name (hb_font_t *font,
|
|||
* objects, with @draw_data passed to them.
|
||||
*
|
||||
* Since: 4.0.0
|
||||
* Deprecated: 7.0.0: Use hb_font_draw_glyph() instead
|
||||
*/
|
||||
void
|
||||
hb_font_get_glyph_shape (hb_font_t *font,
|
||||
|
@ -1414,7 +1408,7 @@ hb_font_get_glyph_shape (hb_font_t *font,
|
|||
/**
|
||||
* hb_font_draw_glyph:
|
||||
* @font: #hb_font_t to work upon
|
||||
* @glyph: The glyph ID
|
||||
* @glyph: : The glyph ID
|
||||
* @dfuncs: #hb_draw_funcs_t to draw to
|
||||
* @draw_data: User data to pass to draw callbacks
|
||||
*
|
||||
|
@ -1423,7 +1417,7 @@ hb_font_get_glyph_shape (hb_font_t *font,
|
|||
* The outline is returned by way of calls to the callbacks of the @dfuncs
|
||||
* objects, with @draw_data passed to them.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
void
|
||||
hb_font_draw_glyph (hb_font_t *font,
|
||||
|
@ -1452,7 +1446,7 @@ hb_font_draw_glyph (hb_font_t *font,
|
|||
* then @palette_index selects the palette to use. If the font only
|
||||
* has one palette, this will be 0.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_font_paint_glyph (hb_font_t *font,
|
||||
|
@ -1778,13 +1772,8 @@ DEFINE_NULL_INSTANCE (hb_font_t) =
|
|||
|
||||
1000, /* x_scale */
|
||||
1000, /* y_scale */
|
||||
0.f, /* x_embolden */
|
||||
0.f, /* y_embolden */
|
||||
true, /* embolden_in_place */
|
||||
0, /* x_strength */
|
||||
0, /* y_strength */
|
||||
0.f, /* slant */
|
||||
0.f, /* slant_xy; */
|
||||
0., /* slant */
|
||||
0., /* slant_xy; */
|
||||
1.f, /* x_multf */
|
||||
1.f, /* y_multf */
|
||||
1<<16, /* x_mult */
|
||||
|
@ -1822,7 +1811,6 @@ _hb_font_create (hb_face_t *face)
|
|||
font->klass = hb_font_funcs_get_empty ();
|
||||
font->data.init0 (font);
|
||||
font->x_scale = font->y_scale = face->get_upem ();
|
||||
font->embolden_in_place = true;
|
||||
font->x_multf = font->y_multf = 1.f;
|
||||
font->x_mult = font->y_mult = 1 << 16;
|
||||
font->instance_index = HB_FONT_NO_VAR_NAMED_INSTANCE;
|
||||
|
@ -1907,9 +1895,6 @@ hb_font_create_sub_font (hb_font_t *parent)
|
|||
|
||||
font->x_scale = parent->x_scale;
|
||||
font->y_scale = parent->y_scale;
|
||||
font->x_embolden = parent->x_embolden;
|
||||
font->y_embolden = parent->y_embolden;
|
||||
font->embolden_in_place = parent->embolden_in_place;
|
||||
font->slant = parent->slant;
|
||||
font->x_ppem = parent->x_ppem;
|
||||
font->y_ppem = parent->y_ppem;
|
||||
|
@ -2457,76 +2442,6 @@ hb_font_get_ptem (hb_font_t *font)
|
|||
return font->ptem;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_set_synthetic_bold:
|
||||
* @font: #hb_font_t to work upon
|
||||
* @x_embolden: the amount to embolden horizontally
|
||||
* @y_embolden: the amount to embolden vertically
|
||||
* @in_place: whether to embolden glyphs in-place
|
||||
*
|
||||
* Sets the "synthetic boldness" of a font.
|
||||
*
|
||||
* Positive values for @x_embolden / @y_embolden make a font
|
||||
* bolder, negative values thinner. Typical values are in the
|
||||
* 0.01 to 0.05 range. The default value is zero.
|
||||
*
|
||||
* Synthetic boldness is applied by offsetting the contour
|
||||
* points of the glyph shape.
|
||||
*
|
||||
* Synthetic boldness is applied when rendering a glyph via
|
||||
* hb_font_draw_glyph().
|
||||
*
|
||||
* If @in_place is `false`, then glyph advance-widths are also
|
||||
* adjusted, otherwise they are not. The in-place mode is
|
||||
* useful for simulating [font grading](https://fonts.google.com/knowledge/glossary/grade).
|
||||
*
|
||||
*
|
||||
* Since: 7.0.0
|
||||
**/
|
||||
void
|
||||
hb_font_set_synthetic_bold (hb_font_t *font,
|
||||
float x_embolden,
|
||||
float y_embolden,
|
||||
hb_bool_t in_place)
|
||||
{
|
||||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
if (font->x_embolden == x_embolden &&
|
||||
font->y_embolden == y_embolden &&
|
||||
font->embolden_in_place == (bool) in_place)
|
||||
return;
|
||||
|
||||
font->serial++;
|
||||
|
||||
font->x_embolden = x_embolden;
|
||||
font->y_embolden = y_embolden;
|
||||
font->embolden_in_place = in_place;
|
||||
font->mults_changed ();
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_get_synthetic_bold:
|
||||
* @font: #hb_font_t to work upon
|
||||
* @x_embolden: (out): return location for horizontal value
|
||||
* @y_embolden: (out): return location for vertical value
|
||||
* @in_place: (out): return location for in-place value
|
||||
*
|
||||
* Fetches the "synthetic boldness" parameters of a font.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
**/
|
||||
void
|
||||
hb_font_get_synthetic_bold (hb_font_t *font,
|
||||
float *x_embolden,
|
||||
float *y_embolden,
|
||||
hb_bool_t *in_place)
|
||||
{
|
||||
if (x_embolden) *x_embolden = font->x_embolden;
|
||||
if (y_embolden) *y_embolden = font->y_embolden;
|
||||
if (in_place) *in_place = font->embolden_in_place;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_set_synthetic_slant:
|
||||
* @font: #hb_font_t to work upon
|
||||
|
@ -2654,79 +2569,6 @@ hb_font_set_variations (hb_font_t *font,
|
|||
_hb_font_adopt_var_coords (font, normalized, design_coords, coords_length);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_set_variation:
|
||||
* @font: #hb_font_t to work upon
|
||||
* @tag: The #hb_tag_t tag of the variation-axis name
|
||||
* @value: The value of the variation axis
|
||||
*
|
||||
* Change the value of one variation axis on the font.
|
||||
*
|
||||
* Note: This function is expensive to be called repeatedly.
|
||||
* If you want to set multiple variation axes at the same time,
|
||||
* use hb_font_set_variations() instead.
|
||||
*
|
||||
* Since: 7.1.0
|
||||
*/
|
||||
void
|
||||
hb_font_set_variation (hb_font_t *font,
|
||||
hb_tag_t tag,
|
||||
float value)
|
||||
{
|
||||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
font->serial_coords = ++font->serial;
|
||||
|
||||
// TODO Share some of this code with set_variations()
|
||||
|
||||
const OT::fvar &fvar = *font->face->table.fvar;
|
||||
auto axes = fvar.get_axes ();
|
||||
const unsigned coords_length = axes.length;
|
||||
|
||||
int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr;
|
||||
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
|
||||
|
||||
if (unlikely (coords_length && !(normalized && design_coords)))
|
||||
{
|
||||
hb_free (normalized);
|
||||
hb_free (design_coords);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Initialize design coords. */
|
||||
if (font->design_coords)
|
||||
{
|
||||
assert (coords_length == font->num_coords);
|
||||
for (unsigned int i = 0; i < coords_length; i++)
|
||||
design_coords[i] = font->design_coords[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < coords_length; i++)
|
||||
design_coords[i] = axes[i].get_default ();
|
||||
if (font->instance_index != HB_FONT_NO_VAR_NAMED_INSTANCE)
|
||||
{
|
||||
unsigned count = coords_length;
|
||||
/* This may fail if index is out-of-range;
|
||||
* That's why we initialize design_coords from fvar above
|
||||
* unconditionally. */
|
||||
hb_ot_var_named_instance_get_design_coords (font->face, font->instance_index,
|
||||
&count, design_coords);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned axis_index = 0; axis_index < coords_length; axis_index++)
|
||||
if (axes[axis_index].axisTag == tag)
|
||||
design_coords[axis_index] = value;
|
||||
|
||||
font->face->table.avar->map_coords (normalized, coords_length);
|
||||
|
||||
hb_ot_var_normalize_coords (font->face, coords_length, design_coords, normalized);
|
||||
_hb_font_adopt_var_coords (font, normalized, design_coords, coords_length);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_set_var_coords_design:
|
||||
* @font: #hb_font_t to work upon
|
||||
|
@ -2802,7 +2644,7 @@ hb_font_set_var_named_instance (hb_font_t *font,
|
|||
*
|
||||
* Return value: Named-instance index or %HB_FONT_NO_VAR_NAMED_INSTANCE.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
unsigned int
|
||||
hb_font_get_var_named_instance (hb_font_t *font)
|
||||
|
|
|
@ -497,7 +497,8 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
|
|||
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
|
||||
*
|
||||
* Since: 4.0.0
|
||||
* Deprecated: 7.0.0: Use #hb_font_draw_glyph_func_t instead
|
||||
*
|
||||
* Deprecated: REPLACEME: Use #hb_font_draw_glyph_func_t instead
|
||||
**/
|
||||
typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
|
@ -515,7 +516,7 @@ typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data
|
|||
*
|
||||
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*
|
||||
**/
|
||||
typedef void (*hb_font_draw_glyph_func_t) (hb_font_t *font, void *font_data,
|
||||
|
@ -536,7 +537,7 @@ typedef void (*hb_font_draw_glyph_func_t) (hb_font_t *font, void *font_data,
|
|||
*
|
||||
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
typedef void (*hb_font_paint_glyph_func_t) (hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
|
@ -814,7 +815,8 @@ hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs,
|
|||
* which is the same as #hb_font_draw_glyph_func_t.
|
||||
*
|
||||
* Since: 4.0.0
|
||||
* Deprecated: 7.0.0: Use hb_font_funcs_set_draw_glyph_func() instead
|
||||
*
|
||||
* Deprecated: REPLACEME: Use hb_font_funcs_set_draw_glyph_func() instead
|
||||
**/
|
||||
HB_EXTERN void
|
||||
hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
|
||||
|
@ -831,7 +833,7 @@ hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
|
|||
* Sets the implementation function for #hb_font_draw_glyph_func_t,
|
||||
* which is the same as #hb_font_get_glyph_shape_func_t.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
HB_EXTERN void
|
||||
hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs,
|
||||
|
@ -847,7 +849,7 @@ hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs,
|
|||
*
|
||||
* Sets the implementation function for #hb_font_paint_glyph_func_t.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
HB_EXTERN void
|
||||
hb_font_funcs_set_paint_glyph_func (hb_font_funcs_t *ffuncs,
|
||||
|
@ -1129,16 +1131,6 @@ hb_font_set_ptem (hb_font_t *font, float ptem);
|
|||
HB_EXTERN float
|
||||
hb_font_get_ptem (hb_font_t *font);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_set_synthetic_bold (hb_font_t *font,
|
||||
float x_embolden, float y_embolden,
|
||||
hb_bool_t in_place);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_get_synthetic_bold (hb_font_t *font,
|
||||
float *x_embolden, float *y_embolden,
|
||||
hb_bool_t *in_place);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_set_synthetic_slant (hb_font_t *font, float slant);
|
||||
|
||||
|
@ -1150,11 +1142,6 @@ hb_font_set_variations (hb_font_t *font,
|
|||
const hb_variation_t *variations,
|
||||
unsigned int variations_length);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_set_variation (hb_font_t *font,
|
||||
hb_tag_t tag,
|
||||
float value);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_font_set_var_coords_design (hb_font_t *font,
|
||||
const float *coords,
|
||||
|
@ -1180,7 +1167,7 @@ hb_font_get_var_coords_normalized (hb_font_t *font,
|
|||
* named-instance index set. This is the default of
|
||||
* a font.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
#define HB_FONT_NO_VAR_NAMED_INSTANCE 0xFFFFFFFF
|
||||
|
||||
|
|
|
@ -113,16 +113,8 @@ struct hb_font_t
|
|||
|
||||
int32_t x_scale;
|
||||
int32_t y_scale;
|
||||
|
||||
float x_embolden;
|
||||
float y_embolden;
|
||||
bool embolden_in_place;
|
||||
int32_t x_strength; /* x_embolden, in scaled units. */
|
||||
int32_t y_strength; /* y_embolden, in scaled units. */
|
||||
|
||||
float slant;
|
||||
float slant_xy;
|
||||
|
||||
float x_multf;
|
||||
float y_multf;
|
||||
int64_t x_mult;
|
||||
|
@ -208,21 +200,6 @@ struct hb_font_t
|
|||
extents->width = ceilf (x2) - extents->x_bearing;
|
||||
extents->height = ceilf (y2) - extents->y_bearing;
|
||||
|
||||
if (x_strength || y_strength)
|
||||
{
|
||||
/* Y */
|
||||
int y_shift = y_strength;
|
||||
if (y_scale < 0) y_shift = -y_shift;
|
||||
extents->y_bearing += y_shift;
|
||||
extents->height -= y_shift;
|
||||
|
||||
/* X */
|
||||
int x_shift = x_strength;
|
||||
if (x_scale < 0) x_shift = -x_shift;
|
||||
if (embolden_in_place)
|
||||
extents->x_bearing -= x_shift / 2;
|
||||
extents->width += x_shift;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -689,17 +666,12 @@ struct hb_font_t
|
|||
void mults_changed ()
|
||||
{
|
||||
float upem = face->get_upem ();
|
||||
|
||||
x_multf = x_scale / upem;
|
||||
y_multf = y_scale / upem;
|
||||
bool x_neg = x_scale < 0;
|
||||
x_mult = (x_neg ? -((int64_t) -x_scale << 16) : ((int64_t) x_scale << 16)) / upem;
|
||||
bool y_neg = y_scale < 0;
|
||||
y_mult = (y_neg ? -((int64_t) -y_scale << 16) : ((int64_t) y_scale << 16)) / upem;
|
||||
|
||||
x_strength = fabsf (roundf (x_scale * x_embolden));
|
||||
y_strength = fabsf (roundf (y_scale * y_embolden));
|
||||
|
||||
slant_xy = y_scale ? slant * x_scale / y_scale : 0.f;
|
||||
|
||||
data.fini ();
|
||||
|
|
|
@ -301,8 +301,8 @@ _hb_ft_paint (hb_ft_paint_context_t *c,
|
|||
c->funcs->sweep_gradient (c->data, &cl,
|
||||
paint.u.sweep_gradient.center.x / 65536.f,
|
||||
paint.u.sweep_gradient.center.y / 65536.f,
|
||||
(paint.u.sweep_gradient.start_angle / 65536.f + 1) * HB_PI,
|
||||
(paint.u.sweep_gradient.end_angle / 65536.f + 1) * HB_PI);
|
||||
(paint.u.sweep_gradient.start_angle / 65536.f + 1) * (float) M_PI,
|
||||
(paint.u.sweep_gradient.end_angle / 65536.f + 1) * (float) M_PI);
|
||||
}
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_GLYPH:
|
||||
|
|
72
src/hb-ft.cc
72
src/hb-ft.cc
|
@ -45,7 +45,6 @@
|
|||
#include FT_MULTIPLE_MASTERS_H
|
||||
#include FT_OUTLINE_H
|
||||
#include FT_TRUETYPE_TABLES_H
|
||||
#include FT_SYNTHESIS_H
|
||||
#if (FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) >= 21300
|
||||
#include FT_COLOR_H
|
||||
#endif
|
||||
|
@ -448,7 +447,6 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
|||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ft_font_t *ft_font = (const hb_ft_font_t *) font_data;
|
||||
hb_position_t *orig_first_advance = first_advance;
|
||||
hb_lock_t lock (ft_font->lock);
|
||||
FT_Face ft_face = ft_font->ft_face;
|
||||
int load_flags = ft_font->load_flags;
|
||||
|
@ -481,26 +479,13 @@ hb_ft_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
|||
/* Work around bug that FreeType seems to return negative advance
|
||||
* for variable-set fonts if x_scale is negative! */
|
||||
v = abs (v);
|
||||
v = (int) (v * x_mult + (1<<9)) >> 10;
|
||||
ft_font->advance_cache.set (glyph, v);
|
||||
}
|
||||
|
||||
*first_advance = v;
|
||||
*first_advance = (int) (v * x_mult + (1<<9)) >> 10;
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
|
||||
if (font->x_strength && !font->embolden_in_place)
|
||||
{
|
||||
/* Emboldening. */
|
||||
hb_position_t x_strength = font->x_scale >= 0 ? font->x_strength : -font->x_strength;
|
||||
first_advance = orig_first_advance;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance += *first_advance ? x_strength : 0;
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
|
@ -536,8 +521,7 @@ hb_ft_get_glyph_v_advance (hb_font_t *font,
|
|||
/* Note: FreeType's vertical metrics grows downward while other FreeType coordinates
|
||||
* have a Y growing upward. Hence the extra negation. */
|
||||
|
||||
hb_position_t y_strength = font->y_scale >= 0 ? font->y_strength : -font->y_strength;
|
||||
return ((-v + (1<<9)) >> 10) + (font->embolden_in_place ? 0 : y_strength);
|
||||
return (-v + (1<<9)) >> 10;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -657,22 +641,6 @@ hb_ft_get_glyph_extents (hb_font_t *font,
|
|||
extents->width = ceilf (x2) - extents->x_bearing;
|
||||
extents->height = ceilf (y2) - extents->y_bearing;
|
||||
|
||||
if (font->x_strength || font->y_strength)
|
||||
{
|
||||
/* Y */
|
||||
int y_shift = font->y_strength;
|
||||
if (font->y_scale < 0) y_shift = -y_shift;
|
||||
extents->y_bearing += y_shift;
|
||||
extents->height -= y_shift;
|
||||
|
||||
/* X */
|
||||
int x_shift = font->x_strength;
|
||||
if (font->x_scale < 0) x_shift = -x_shift;
|
||||
if (font->embolden_in_place)
|
||||
extents->x_bearing -= x_shift / 2;
|
||||
extents->width += x_shift;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -794,7 +762,7 @@ hb_ft_get_font_h_extents (hb_font_t *font HB_UNUSED,
|
|||
metrics->line_gap = ft_face->size->metrics.height - (metrics->ascender - metrics->descender);
|
||||
}
|
||||
|
||||
metrics->ascender = (hb_position_t) (y_mult * (metrics->ascender + font->y_strength));
|
||||
metrics->ascender = (hb_position_t) (y_mult * metrics->ascender);
|
||||
metrics->descender = (hb_position_t) (y_mult * metrics->descender);
|
||||
metrics->line_gap = (hb_position_t) (y_mult * metrics->line_gap);
|
||||
|
||||
|
@ -846,7 +814,7 @@ _hb_ft_cubic_to (const FT_Vector *control1,
|
|||
}
|
||||
|
||||
static void
|
||||
hb_ft_draw_glyph (hb_font_t *font,
|
||||
hb_ft_draw_glyph (hb_font_t *font HB_UNUSED,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_draw_funcs_t *draw_funcs, void *draw_data,
|
||||
|
@ -874,38 +842,6 @@ hb_ft_draw_glyph (hb_font_t *font,
|
|||
|
||||
hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy);
|
||||
|
||||
/* Embolden */
|
||||
if (font->x_strength || font->y_strength)
|
||||
{
|
||||
FT_Outline_EmboldenXY (&ft_face->glyph->outline, font->x_strength, font->y_strength);
|
||||
|
||||
int x_shift = 0;
|
||||
int y_shift = 0;
|
||||
if (font->embolden_in_place)
|
||||
{
|
||||
/* Undo the FreeType shift. */
|
||||
x_shift = -font->x_strength / 2;
|
||||
y_shift = 0;
|
||||
if (font->y_scale < 0) y_shift = -font->y_strength;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FreeType applied things in the wrong direction for negative scale; fix up. */
|
||||
if (font->x_scale < 0) x_shift = -font->x_strength;
|
||||
if (font->y_scale < 0) y_shift = -font->y_strength;
|
||||
}
|
||||
if (x_shift || y_shift)
|
||||
{
|
||||
auto &outline = ft_face->glyph->outline;
|
||||
for (auto &point : hb_iter (outline.points, outline.contours[outline.n_contours - 1] + 1))
|
||||
{
|
||||
point.x += x_shift;
|
||||
point.y += y_shift;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
FT_Outline_Decompose (&ft_face->glyph->outline,
|
||||
&outline_funcs,
|
||||
&draw_session);
|
||||
|
|
|
@ -349,7 +349,7 @@ hb_map_hash (const hb_map_t *map)
|
|||
*
|
||||
* Add the contents of @other to @map.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
HB_EXTERN void
|
||||
hb_map_update (hb_map_t *map,
|
||||
|
@ -375,7 +375,7 @@ hb_map_update (hb_map_t *map,
|
|||
*
|
||||
* Return value: `true` if there was a next value, `false` otherwise
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_map_next (const hb_map_t *map,
|
||||
|
@ -393,13 +393,13 @@ hb_map_next (const hb_map_t *map,
|
|||
*
|
||||
* Add the keys of @map to @keys.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
void
|
||||
hb_map_keys (const hb_map_t *map,
|
||||
hb_set_t *keys)
|
||||
{
|
||||
hb_copy (map->keys() , *keys);
|
||||
map->keys (*keys);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -409,11 +409,11 @@ hb_map_keys (const hb_map_t *map,
|
|||
*
|
||||
* Add the values of @map to @values.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
void
|
||||
hb_map_values (const hb_map_t *map,
|
||||
hb_set_t *values)
|
||||
{
|
||||
hb_copy (map->values() , *values);
|
||||
map->values (*values);
|
||||
}
|
||||
|
|
|
@ -317,6 +317,16 @@ struct hb_hashmap_t
|
|||
hb_copy (other, *this);
|
||||
}
|
||||
|
||||
void keys (hb_set_t &keys_) const
|
||||
{
|
||||
hb_copy (keys() , keys_);
|
||||
}
|
||||
|
||||
void values (hb_set_t &values_) const
|
||||
{
|
||||
hb_copy (values() , values_);
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterator
|
||||
*/
|
||||
|
@ -343,8 +353,7 @@ struct hb_hashmap_t
|
|||
)
|
||||
auto keys () const HB_AUTO_RETURN
|
||||
(
|
||||
+ iter_items ()
|
||||
| hb_map (&item_t::key)
|
||||
+ keys_ref ()
|
||||
| hb_map (hb_ridentity)
|
||||
)
|
||||
auto values_ref () const HB_AUTO_RETURN
|
||||
|
@ -354,8 +363,7 @@ struct hb_hashmap_t
|
|||
)
|
||||
auto values () const HB_AUTO_RETURN
|
||||
(
|
||||
+ iter_items ()
|
||||
| hb_map (&item_t::value)
|
||||
+ values_ref ()
|
||||
| hb_map (hb_ridentity)
|
||||
)
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ typedef pthread_mutex_t hb_mutex_impl_t;
|
|||
#elif !defined(HB_NO_MT) && !defined(HB_MUTEX_IMPL_STD_MUTEX) && defined(_WIN32)
|
||||
|
||||
typedef CRITICAL_SECTION hb_mutex_impl_t;
|
||||
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
|
||||
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
#define hb_mutex_impl_init(M) InitializeCriticalSectionEx (M, 0, 0)
|
||||
#else
|
||||
#define hb_mutex_impl_init(M) InitializeCriticalSection (M)
|
||||
|
|
|
@ -902,6 +902,8 @@ struct cff1_private_dict_opset_t : dict_opset_t
|
|||
case OpCode_FamilyOtherBlues:
|
||||
case OpCode_StemSnapH:
|
||||
case OpCode_StemSnapV:
|
||||
env.clear_args ();
|
||||
break;
|
||||
case OpCode_StdHW:
|
||||
case OpCode_StdVW:
|
||||
case OpCode_BlueScale:
|
||||
|
@ -913,6 +915,7 @@ struct cff1_private_dict_opset_t : dict_opset_t
|
|||
case OpCode_initialRandomSeed:
|
||||
case OpCode_defaultWidthX:
|
||||
case OpCode_nominalWidthX:
|
||||
val.single_val = env.argStack.pop_num ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
case OpCode_Subrs:
|
||||
|
|
|
@ -283,6 +283,9 @@ struct cff2_private_dict_opset_t : dict_opset_t
|
|||
case OpCode_BlueFuzz:
|
||||
case OpCode_ExpansionFactor:
|
||||
case OpCode_LanguageGroup:
|
||||
val.single_val = env.argStack.pop_num ();
|
||||
env.clear_args ();
|
||||
break;
|
||||
case OpCode_BlueValues:
|
||||
case OpCode_OtherBlues:
|
||||
case OpCode_FamilyBlues:
|
||||
|
|
|
@ -216,7 +216,7 @@ hb_ot_color_has_layers (hb_face_t *face)
|
|||
*
|
||||
* Return value: `true` if data found, `false` otherwise
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
hb_bool_t
|
||||
hb_ot_color_has_paint (hb_face_t *face)
|
||||
|
@ -234,7 +234,7 @@ hb_ot_color_has_paint (hb_face_t *face)
|
|||
*
|
||||
* Return value: `true` if data found, `false` otherwise
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
hb_bool_t
|
||||
hb_ot_color_glyph_has_paint (hb_face_t *face,
|
||||
|
|
|
@ -93,7 +93,6 @@ HB_OT_ACCELERATOR (OT, cff2)
|
|||
#ifndef HB_NO_VAR
|
||||
HB_OT_CORE_TABLE (OT, fvar)
|
||||
HB_OT_CORE_TABLE (OT, avar)
|
||||
HB_OT_CORE_TABLE (OT, cvar)
|
||||
HB_OT_ACCELERATOR (OT, gvar)
|
||||
HB_OT_CORE_TABLE (OT, MVAR)
|
||||
#endif
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include "hb-font.hh"
|
||||
#include "hb-machinery.hh"
|
||||
#include "hb-ot-face.hh"
|
||||
#include "hb-outline.hh"
|
||||
|
||||
#include "hb-ot-cmap-table.hh"
|
||||
#include "hb-ot-glyf-table.hh"
|
||||
|
@ -122,7 +121,8 @@ _hb_ot_font_destroy (void *font_data)
|
|||
hb_ot_font_t *ot_font = (hb_ot_font_t *) font_data;
|
||||
|
||||
auto *cache = ot_font->advance_cache.get_relaxed ();
|
||||
hb_free (cache);
|
||||
if (cache)
|
||||
hb_free (cache);
|
||||
|
||||
hb_free (ot_font);
|
||||
}
|
||||
|
@ -181,13 +181,10 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
|||
unsigned advance_stride,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
|
||||
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
||||
const hb_ot_face_t *ot_face = ot_font->ot_face;
|
||||
const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
|
||||
|
||||
hb_position_t *orig_first_advance = first_advance;
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
const OT::HVAR &HVAR = *hmtx.var_table;
|
||||
const OT::VariationStore &varStore = &HVAR + HVAR.varStore;
|
||||
|
@ -261,18 +258,6 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
|||
#ifndef HB_NO_VAR
|
||||
OT::VariationStore::destroy_cache (varStore_cache);
|
||||
#endif
|
||||
|
||||
if (font->x_strength && !font->embolden_in_place)
|
||||
{
|
||||
/* Emboldening. */
|
||||
hb_position_t x_strength = font->x_scale >= 0 ? font->x_strength : -font->x_strength;
|
||||
first_advance = orig_first_advance;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance += *first_advance ? x_strength : 0;
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
|
@ -289,8 +274,6 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
|
|||
const hb_ot_face_t *ot_face = ot_font->ot_face;
|
||||
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
|
||||
|
||||
hb_position_t *orig_first_advance = first_advance;
|
||||
|
||||
if (vmtx.has_data ())
|
||||
{
|
||||
#ifndef HB_NO_VAR
|
||||
|
@ -325,18 +308,6 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
|
|||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
|
||||
if (font->y_strength && !font->embolden_in_place)
|
||||
{
|
||||
/* Emboldening. */
|
||||
hb_position_t y_strength = font->y_scale >= 0 ? font->y_strength : -font->y_strength;
|
||||
first_advance = orig_first_advance;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance += *first_advance ? y_strength : 0;
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -413,7 +384,7 @@ hb_ot_get_glyph_extents (hb_font_t *font,
|
|||
if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
|
||||
if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
|
||||
#endif
|
||||
#if !defined(HB_NO_COLOR) && !defined(HB_NO_PAINT)
|
||||
#if !defined(HB_NO_COLOR)
|
||||
if (ot_face->COLR->get_extents (font, glyph, extents)) return true;
|
||||
#endif
|
||||
if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
|
||||
|
@ -466,16 +437,9 @@ hb_ot_get_font_h_extents (hb_font_t *font,
|
|||
hb_font_extents_t *metrics,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
bool ret = _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) &&
|
||||
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) &&
|
||||
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap);
|
||||
|
||||
/* Embolden */
|
||||
int y_shift = font->y_strength;
|
||||
if (font->y_scale < 0) y_shift = -y_shift;
|
||||
metrics->ascender += y_shift;
|
||||
|
||||
return ret;
|
||||
return _hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, &metrics->ascender) &&
|
||||
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, &metrics->descender) &&
|
||||
_hb_ot_metrics_get_position_common (font, HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, &metrics->line_gap);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
|
@ -499,31 +463,12 @@ hb_ot_draw_glyph (hb_font_t *font,
|
|||
hb_draw_funcs_t *draw_funcs, void *draw_data,
|
||||
void *user_data)
|
||||
{
|
||||
bool embolden = font->x_strength || font->y_strength;
|
||||
hb_outline_t outline;
|
||||
|
||||
{ // Need draw_session to be destructed before emboldening.
|
||||
hb_draw_session_t draw_session (embolden ? hb_outline_recording_pen_get_funcs () : draw_funcs,
|
||||
embolden ? &outline : draw_data, font->slant_xy);
|
||||
if (!font->face->table.glyf->get_path (font, glyph, draw_session))
|
||||
hb_draw_session_t draw_session (draw_funcs, draw_data, font->slant_xy);
|
||||
if (font->face->table.glyf->get_path (font, glyph, draw_session)) return;
|
||||
#ifndef HB_NO_CFF
|
||||
if (!font->face->table.cff1->get_path (font, glyph, draw_session))
|
||||
if (!font->face->table.cff2->get_path (font, glyph, draw_session))
|
||||
if (font->face->table.cff1->get_path (font, glyph, draw_session)) return;
|
||||
if (font->face->table.cff2->get_path (font, glyph, draw_session)) return;
|
||||
#endif
|
||||
{}
|
||||
}
|
||||
|
||||
if (embolden)
|
||||
{
|
||||
float x_shift = font->embolden_in_place ? 0 : (float) font->x_strength / 2;
|
||||
float y_shift = (float) font->y_strength / 2;
|
||||
if (font->x_scale < 0) x_shift = -x_shift;
|
||||
if (font->y_scale < 0) y_shift = -y_shift;
|
||||
outline.embolden (font->x_strength, font->y_strength,
|
||||
x_shift, y_shift);
|
||||
|
||||
outline.replay (draw_funcs, draw_data);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -633,4 +578,20 @@ hb_ot_font_set_funcs (hb_font_t *font)
|
|||
_hb_ot_font_destroy);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
bool
|
||||
_glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical,
|
||||
int *lsb)
|
||||
{
|
||||
return font->face->table.glyf->get_leading_bearing_with_var_unscaled (font, glyph, is_vertical, lsb);
|
||||
}
|
||||
|
||||
unsigned
|
||||
_glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
|
||||
{
|
||||
return font->face->table.glyf->get_advance_with_var_unscaled (font, glyph, is_vertical);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -76,7 +76,7 @@ struct DeviceRecord
|
|||
HBUINT8 maxWidth; /* Maximum width. */
|
||||
UnsizedArrayOf<HBUINT8> widthsZ; /* Array of widths (numGlyphs is from the 'maxp' table). */
|
||||
public:
|
||||
DEFINE_SIZE_UNBOUNDED (2);
|
||||
DEFINE_SIZE_ARRAY (2, widthsZ);
|
||||
};
|
||||
|
||||
|
||||
|
@ -87,6 +87,14 @@ struct hdmx
|
|||
unsigned int get_size () const
|
||||
{ return min_size + numRecords * sizeDeviceRecord; }
|
||||
|
||||
const DeviceRecord& operator [] (unsigned int i) const
|
||||
{
|
||||
/* XXX Null(DeviceRecord) is NOT safe as it's num-glyphs lengthed.
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/1300 */
|
||||
if (unlikely (i >= numRecords)) return Null (DeviceRecord);
|
||||
return StructAtOffset<DeviceRecord> (&this->firstDeviceRecord, i * sizeDeviceRecord);
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
bool serialize (hb_serialize_context_t *c, unsigned version, Iterator it)
|
||||
|
|
|
@ -63,25 +63,7 @@ struct head
|
|||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
head *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (c->plan->normalized_coords)
|
||||
{
|
||||
if (unlikely (!c->serializer->check_assign (out->xMin, c->plan->head_maxp_info.xMin,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW)))
|
||||
return_trace (false);
|
||||
if (unlikely (!c->serializer->check_assign (out->xMax, c->plan->head_maxp_info.xMax,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW)))
|
||||
return_trace (false);
|
||||
if (unlikely (!c->serializer->check_assign (out->yMin, c->plan->head_maxp_info.yMin,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW)))
|
||||
return_trace (false);
|
||||
if (unlikely (!c->serializer->check_assign (out->yMax, c->plan->head_maxp_info.yMax,
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW)))
|
||||
return_trace (false);
|
||||
}
|
||||
return_trace (true);
|
||||
return_trace (serialize (c->serializer));
|
||||
}
|
||||
|
||||
enum mac_style_flag_t {
|
||||
|
|
|
@ -50,9 +50,6 @@ _glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t gly
|
|||
HB_INTERNAL unsigned
|
||||
_glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
|
||||
|
||||
HB_INTERNAL bool
|
||||
_glyf_get_leading_bearing_without_var_unscaled (hb_face_t *face, hb_codepoint_t gid, bool is_vertical, int *lsb);
|
||||
|
||||
|
||||
namespace OT {
|
||||
|
||||
|
@ -95,7 +92,7 @@ struct hmtxvmtx
|
|||
|
||||
unsigned int length;
|
||||
H *table = (H *) hb_blob_get_data (dest_blob, &length);
|
||||
c->serializer->check_assign (table->numberOfLongMetrics, num_hmetrics, HB_SERIALIZE_ERROR_INT_OVERFLOW);
|
||||
table->numberOfLongMetrics = num_hmetrics;
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
if (c->plan->normalized_coords)
|
||||
|
@ -168,19 +165,12 @@ struct hmtxvmtx
|
|||
lm.sb = _.second;
|
||||
if (unlikely (!c->embed<LongMetric> (&lm))) return;
|
||||
}
|
||||
else if (idx < 0x10000u)
|
||||
else
|
||||
{
|
||||
FWORD *sb = c->allocate_size<FWORD> (FWORD::static_size);
|
||||
if (unlikely (!sb)) return;
|
||||
*sb = _.second;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: This does not do tail optimization.
|
||||
UFWORD *adv = c->allocate_size<UFWORD> (UFWORD::static_size);
|
||||
if (unlikely (!adv)) return;
|
||||
*adv = _.first;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
@ -199,7 +189,7 @@ struct hmtxvmtx
|
|||
/* Determine num_long_metrics to encode. */
|
||||
auto& plan = c->plan;
|
||||
|
||||
num_long_metrics = hb_min (plan->num_output_glyphs (), 0xFFFFu);
|
||||
num_long_metrics = plan->num_output_glyphs ();
|
||||
unsigned int last_advance = get_new_gid_advance_unscaled (plan, mtx_map, num_long_metrics - 1, _mtx);
|
||||
while (num_long_metrics > 1 &&
|
||||
last_advance == get_new_gid_advance_unscaled (plan, mtx_map, num_long_metrics - 2, _mtx))
|
||||
|
@ -218,8 +208,7 @@ struct hmtxvmtx
|
|||
if (!c->plan->old_gid_for_new_gid (_, &old_gid))
|
||||
return hb_pair (0u, 0);
|
||||
int lsb = 0;
|
||||
if (!_mtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb))
|
||||
(void) _glyf_get_leading_bearing_without_var_unscaled (c->plan->source, old_gid, !T::is_horizontal, &lsb);
|
||||
(void) _mtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb);
|
||||
return hb_pair (_mtx.get_advance_without_var_unscaled (old_gid), +lsb);
|
||||
}
|
||||
return mtx_map->get (_);
|
||||
|
|
|
@ -529,9 +529,6 @@ struct FeatureParamsSize
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
void collect_name_ids (hb_set_t *nameids_to_retain /* OUT */) const
|
||||
{ nameids_to_retain->add (subfamilyNameID); }
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
@ -588,9 +585,6 @@ struct FeatureParamsStylisticSet
|
|||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
void collect_name_ids (hb_set_t *nameids_to_retain /* OUT */) const
|
||||
{ nameids_to_retain->add (uiNameID); }
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
@ -638,20 +632,6 @@ struct FeatureParamsCharacterVariants
|
|||
unsigned get_size () const
|
||||
{ return min_size + characters.len * HBUINT24::static_size; }
|
||||
|
||||
void collect_name_ids (hb_set_t *nameids_to_retain /* OUT */) const
|
||||
{
|
||||
if (featUILableNameID) nameids_to_retain->add (featUILableNameID);
|
||||
if (featUITooltipTextNameID) nameids_to_retain->add (featUITooltipTextNameID);
|
||||
if (sampleTextNameID) nameids_to_retain->add (sampleTextNameID);
|
||||
|
||||
if (!firstParamUILabelNameID || !numNamedParameters || numNamedParameters >= 0x7FFF)
|
||||
return;
|
||||
|
||||
unsigned last_name_id = (unsigned) firstParamUILabelNameID + (unsigned) numNamedParameters - 1;
|
||||
if (last_name_id >= 256 && last_name_id <= 32767)
|
||||
nameids_to_retain->add_range (firstParamUILabelNameID, last_name_id);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
@ -714,19 +694,6 @@ struct FeatureParams
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
void collect_name_ids (hb_tag_t tag, hb_set_t *nameids_to_retain /* OUT */) const
|
||||
{
|
||||
#ifdef HB_NO_LAYOUT_FEATURE_PARAMS
|
||||
return;
|
||||
#endif
|
||||
if (tag == HB_TAG ('s','i','z','e'))
|
||||
return (u.size.collect_name_ids (nameids_to_retain));
|
||||
if ((tag & 0xFFFF0000u) == HB_TAG ('s','s','\0','\0')) /* ssXX */
|
||||
return (u.stylisticSet.collect_name_ids (nameids_to_retain));
|
||||
if ((tag & 0xFFFF0000u) == HB_TAG ('c','v','\0','\0')) /* cvXX */
|
||||
return (u.characterVariants.collect_name_ids (nameids_to_retain));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c, const Tag* tag) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
@ -795,12 +762,6 @@ struct Feature
|
|||
bool intersects_lookup_indexes (const hb_map_t *lookup_indexes) const
|
||||
{ return lookupIndex.intersects (lookup_indexes); }
|
||||
|
||||
void collect_name_ids (hb_tag_t tag, hb_set_t *nameids_to_retain /* OUT */) const
|
||||
{
|
||||
if (featureParams)
|
||||
get_feature_params ().collect_name_ids (tag, nameids_to_retain);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
hb_subset_layout_context_t *l,
|
||||
const Tag *tag = nullptr) const
|
||||
|
|
|
@ -64,8 +64,11 @@ inline bool PosLookup::dispatch_recurse_func<hb_ot_apply_context_t> (hb_ot_apply
|
|||
c->set_lookup_props (l.get_props ());
|
||||
|
||||
bool ret = false;
|
||||
auto *accel = gpos->get_accel (lookup_index);
|
||||
ret = accel && accel->apply (c, l.get_subtable_count (), false);
|
||||
if (lookup_index < gpos->lookup_count)
|
||||
{
|
||||
auto &accel = gpos->accels[lookup_index];
|
||||
ret = accel.apply (c, false);
|
||||
}
|
||||
|
||||
c->set_lookup_index (saved_lookup_index);
|
||||
c->set_lookup_props (saved_lookup_props);
|
||||
|
|
|
@ -77,8 +77,11 @@ inline bool SubstLookup::dispatch_recurse_func<hb_ot_apply_context_t> (hb_ot_app
|
|||
c->set_lookup_props (l.get_props ());
|
||||
|
||||
bool ret = false;
|
||||
auto *accel = gsub->get_accel (lookup_index);
|
||||
ret = accel && accel->apply (c, l.get_subtable_count (), false);
|
||||
if (lookup_index < gsub->lookup_count)
|
||||
{
|
||||
auto &accel = gsub->accels[lookup_index];
|
||||
ret = accel.apply (c, false);
|
||||
}
|
||||
|
||||
c->set_lookup_index (saved_lookup_index);
|
||||
c->set_lookup_props (saved_lookup_props);
|
||||
|
|
|
@ -532,30 +532,6 @@ struct hb_ot_apply_context_t :
|
|||
may_skip (const hb_glyph_info_t &info) const
|
||||
{ return matcher.may_skip (c, info); }
|
||||
|
||||
enum match_t {
|
||||
MATCH,
|
||||
NOT_MATCH,
|
||||
SKIP
|
||||
};
|
||||
|
||||
match_t match (hb_glyph_info_t &info)
|
||||
{
|
||||
matcher_t::may_skip_t skip = matcher.may_skip (c, info);
|
||||
if (unlikely (skip == matcher_t::SKIP_YES))
|
||||
return SKIP;
|
||||
|
||||
matcher_t::may_match_t match = matcher.may_match (info, get_glyph_data ());
|
||||
if (match == matcher_t::MATCH_YES ||
|
||||
(match == matcher_t::MATCH_MAYBE &&
|
||||
skip == matcher_t::SKIP_NO))
|
||||
return MATCH;
|
||||
|
||||
if (skip == matcher_t::SKIP_NO)
|
||||
return NOT_MATCH;
|
||||
|
||||
return SKIP;
|
||||
}
|
||||
|
||||
bool next (unsigned *unsafe_to = nullptr)
|
||||
{
|
||||
assert (num_items > 0);
|
||||
|
@ -567,22 +543,27 @@ struct hb_ot_apply_context_t :
|
|||
while ((signed) idx < stop)
|
||||
{
|
||||
idx++;
|
||||
switch (match (c->buffer->info[idx]))
|
||||
hb_glyph_info_t &info = c->buffer->info[idx];
|
||||
|
||||
matcher_t::may_skip_t skip = matcher.may_skip (c, info);
|
||||
if (unlikely (skip == matcher_t::SKIP_YES))
|
||||
continue;
|
||||
|
||||
matcher_t::may_match_t match = matcher.may_match (info, get_glyph_data ());
|
||||
if (match == matcher_t::MATCH_YES ||
|
||||
(match == matcher_t::MATCH_MAYBE &&
|
||||
skip == matcher_t::SKIP_NO))
|
||||
{
|
||||
case MATCH:
|
||||
{
|
||||
num_items--;
|
||||
advance_glyph_data ();
|
||||
return true;
|
||||
}
|
||||
case NOT_MATCH:
|
||||
{
|
||||
if (unsafe_to)
|
||||
*unsafe_to = idx + 1;
|
||||
return false;
|
||||
}
|
||||
case SKIP:
|
||||
continue;
|
||||
num_items--;
|
||||
advance_glyph_data ();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (skip == matcher_t::SKIP_NO)
|
||||
{
|
||||
if (unsafe_to)
|
||||
*unsafe_to = idx + 1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (unsafe_to)
|
||||
|
@ -600,22 +581,27 @@ struct hb_ot_apply_context_t :
|
|||
while (idx > stop)
|
||||
{
|
||||
idx--;
|
||||
switch (match (c->buffer->out_info[idx]))
|
||||
hb_glyph_info_t &info = c->buffer->out_info[idx];
|
||||
|
||||
matcher_t::may_skip_t skip = matcher.may_skip (c, info);
|
||||
if (unlikely (skip == matcher_t::SKIP_YES))
|
||||
continue;
|
||||
|
||||
matcher_t::may_match_t match = matcher.may_match (info, get_glyph_data ());
|
||||
if (match == matcher_t::MATCH_YES ||
|
||||
(match == matcher_t::MATCH_MAYBE &&
|
||||
skip == matcher_t::SKIP_NO))
|
||||
{
|
||||
case MATCH:
|
||||
{
|
||||
num_items--;
|
||||
advance_glyph_data ();
|
||||
return true;
|
||||
}
|
||||
case NOT_MATCH:
|
||||
{
|
||||
if (unsafe_from)
|
||||
*unsafe_from = hb_max (1u, idx) - 1u;
|
||||
return false;
|
||||
}
|
||||
case SKIP:
|
||||
continue;
|
||||
num_items--;
|
||||
advance_glyph_data ();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (skip == matcher_t::SKIP_NO)
|
||||
{
|
||||
if (unsafe_from)
|
||||
*unsafe_from = hb_max (1u, idx) - 1u;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (unsafe_from)
|
||||
|
@ -712,9 +698,6 @@ struct hb_ot_apply_context_t :
|
|||
uint32_t random_state = 1;
|
||||
unsigned new_syllables = (unsigned) -1;
|
||||
|
||||
signed last_base = -1; // GPOS uses
|
||||
unsigned last_base_until = 0; // GPOS uses
|
||||
|
||||
hb_ot_apply_context_t (unsigned int table_index_,
|
||||
hb_font_t *font_,
|
||||
hb_buffer_t *buffer_) :
|
||||
|
@ -753,7 +736,7 @@ struct hb_ot_apply_context_t :
|
|||
iter_context.init (this, true);
|
||||
}
|
||||
|
||||
void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; last_base = -1; last_base_until = 0; init_iters (); }
|
||||
void set_lookup_mask (hb_mask_t mask) { lookup_mask = mask; init_iters (); }
|
||||
void set_auto_zwj (bool auto_zwj_) { auto_zwj = auto_zwj_; init_iters (); }
|
||||
void set_auto_zwnj (bool auto_zwnj_) { auto_zwnj = auto_zwnj_; init_iters (); }
|
||||
void set_per_syllable (bool per_syllable_) { per_syllable = per_syllable_; init_iters (); }
|
||||
|
@ -961,6 +944,8 @@ struct hb_accelerate_subtables_context_t :
|
|||
hb_set_digest_t digest;
|
||||
};
|
||||
|
||||
typedef hb_vector_t<hb_applicable_t> array_t;
|
||||
|
||||
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
template <typename T>
|
||||
auto cache_cost (const T &obj, hb_priority<1>) HB_AUTO_RETURN ( obj.cache_cost () )
|
||||
|
@ -972,7 +957,7 @@ struct hb_accelerate_subtables_context_t :
|
|||
template <typename T>
|
||||
return_t dispatch (const T &obj)
|
||||
{
|
||||
hb_applicable_t *entry = &array[i++];
|
||||
hb_applicable_t *entry = array.push ();
|
||||
|
||||
entry->init (obj,
|
||||
apply_to<T>
|
||||
|
@ -992,9 +977,9 @@ struct hb_accelerate_subtables_context_t :
|
|||
* and we allocate the cache opportunity to the costliest subtable.
|
||||
*/
|
||||
unsigned cost = cache_cost (obj, hb_prioritize);
|
||||
if (cost > cache_user_cost)
|
||||
if (cost > cache_user_cost && !array.in_error ())
|
||||
{
|
||||
cache_user_idx = i - 1;
|
||||
cache_user_idx = array.length - 1;
|
||||
cache_user_cost = cost;
|
||||
}
|
||||
#endif
|
||||
|
@ -1003,11 +988,10 @@ struct hb_accelerate_subtables_context_t :
|
|||
}
|
||||
static return_t default_return_value () { return hb_empty_t (); }
|
||||
|
||||
hb_accelerate_subtables_context_t (hb_applicable_t *array_) :
|
||||
hb_accelerate_subtables_context_t (array_t &array_) :
|
||||
array (array_) {}
|
||||
|
||||
hb_applicable_t *array;
|
||||
unsigned i = 0;
|
||||
array_t &array;
|
||||
|
||||
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
unsigned cache_user_idx = (unsigned) -1;
|
||||
|
@ -4030,50 +4014,36 @@ struct Extension
|
|||
struct hb_ot_layout_lookup_accelerator_t
|
||||
{
|
||||
template <typename TLookup>
|
||||
static hb_ot_layout_lookup_accelerator_t *create (const TLookup &lookup)
|
||||
void init (const TLookup &lookup)
|
||||
{
|
||||
unsigned count = lookup.get_subtable_count ();
|
||||
|
||||
unsigned size = sizeof (hb_ot_layout_lookup_accelerator_t) -
|
||||
HB_VAR_ARRAY * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t) +
|
||||
count * sizeof (hb_accelerate_subtables_context_t::hb_applicable_t);
|
||||
|
||||
/* The following is a calloc because when we are collecting subtables,
|
||||
* some of them might be invalid and hence not collect; as a result,
|
||||
* we might not fill in all the count entries of the subtables array.
|
||||
* Zeroing it allows the set digest to gatekeep it without having to
|
||||
* initialize it further. */
|
||||
auto *thiz = (hb_ot_layout_lookup_accelerator_t *) hb_calloc (1, size);
|
||||
if (unlikely (!thiz))
|
||||
return nullptr;
|
||||
|
||||
hb_accelerate_subtables_context_t c_accelerate_subtables (thiz->subtables);
|
||||
subtables.init ();
|
||||
subtables.alloc (lookup.get_subtable_count (), true);
|
||||
hb_accelerate_subtables_context_t c_accelerate_subtables (subtables);
|
||||
lookup.dispatch (&c_accelerate_subtables);
|
||||
|
||||
thiz->digest.init ();
|
||||
for (auto& subtable : hb_iter (thiz->subtables, count))
|
||||
thiz->digest.add (subtable.digest);
|
||||
digest.init ();
|
||||
for (auto& subtable : subtables)
|
||||
digest.add (subtable.digest);
|
||||
|
||||
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
thiz->cache_user_idx = c_accelerate_subtables.cache_user_idx;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
if (i != thiz->cache_user_idx)
|
||||
thiz->subtables[i].apply_cached_func = thiz->subtables[i].apply_func;
|
||||
cache_user_idx = c_accelerate_subtables.cache_user_idx;
|
||||
for (unsigned i = 0; i < subtables.length; i++)
|
||||
if (i != cache_user_idx)
|
||||
subtables[i].apply_cached_func = subtables[i].apply_func;
|
||||
#endif
|
||||
|
||||
return thiz;
|
||||
}
|
||||
void fini () { subtables.fini (); }
|
||||
|
||||
bool may_have (hb_codepoint_t g) const
|
||||
{ return digest.may_have (g); }
|
||||
|
||||
bool apply (hb_ot_apply_context_t *c, unsigned subtables_count, bool use_cache) const
|
||||
bool apply (hb_ot_apply_context_t *c, bool use_cache) const
|
||||
{
|
||||
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
if (use_cache)
|
||||
{
|
||||
return
|
||||
+ hb_iter (hb_iter (subtables, subtables_count))
|
||||
+ hb_iter (subtables)
|
||||
| hb_map ([&c] (const hb_accelerate_subtables_context_t::hb_applicable_t &_) { return _.apply_cached (c); })
|
||||
| hb_any
|
||||
;
|
||||
|
@ -4082,7 +4052,7 @@ struct hb_ot_layout_lookup_accelerator_t
|
|||
#endif
|
||||
{
|
||||
return
|
||||
+ hb_iter (hb_iter (subtables, subtables_count))
|
||||
+ hb_iter (subtables)
|
||||
| hb_map ([&c] (const hb_accelerate_subtables_context_t::hb_applicable_t &_) { return _.apply (c); })
|
||||
| hb_any
|
||||
;
|
||||
|
@ -4109,10 +4079,10 @@ struct hb_ot_layout_lookup_accelerator_t
|
|||
|
||||
hb_set_digest_t digest;
|
||||
private:
|
||||
hb_accelerate_subtables_context_t::array_t subtables;
|
||||
#ifndef HB_NO_OT_LAYOUT_LOOKUP_CACHE
|
||||
unsigned cache_user_idx = (unsigned) -1;
|
||||
#endif
|
||||
hb_accelerate_subtables_context_t::hb_applicable_t subtables[HB_VAR_ARRAY];
|
||||
};
|
||||
|
||||
template <typename Types>
|
||||
|
@ -4461,18 +4431,6 @@ struct GSUBGPOS
|
|||
}
|
||||
}
|
||||
|
||||
void collect_name_ids (const hb_map_t *feature_index_map,
|
||||
hb_set_t *nameids_to_retain /* OUT */) const
|
||||
{
|
||||
unsigned count = get_feature_count ();
|
||||
for (unsigned i = 0 ; i < count; i++)
|
||||
{
|
||||
if (!feature_index_map->has (i)) continue;
|
||||
hb_tag_t tag = get_feature_tag (i);
|
||||
get_feature (i).collect_name_ids (tag, nameids_to_retain);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct accelerator_t
|
||||
{
|
||||
|
@ -4487,47 +4445,28 @@ struct GSUBGPOS
|
|||
|
||||
this->lookup_count = table->get_lookup_count ();
|
||||
|
||||
this->accels = (hb_atomic_ptr_t<hb_ot_layout_lookup_accelerator_t> *) hb_calloc (this->lookup_count, sizeof (*accels));
|
||||
this->accels = (hb_ot_layout_lookup_accelerator_t *) hb_calloc (this->lookup_count, sizeof (hb_ot_layout_lookup_accelerator_t));
|
||||
if (unlikely (!this->accels))
|
||||
{
|
||||
this->lookup_count = 0;
|
||||
this->table.destroy ();
|
||||
this->table = hb_blob_get_empty ();
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < this->lookup_count; i++)
|
||||
this->accels[i].init (table->get_lookup (i));
|
||||
}
|
||||
~accelerator_t ()
|
||||
{
|
||||
for (unsigned int i = 0; i < this->lookup_count; i++)
|
||||
hb_free (this->accels[i]);
|
||||
this->accels[i].fini ();
|
||||
hb_free (this->accels);
|
||||
this->table.destroy ();
|
||||
}
|
||||
|
||||
hb_ot_layout_lookup_accelerator_t *get_accel (unsigned lookup_index) const
|
||||
{
|
||||
if (unlikely (lookup_index >= lookup_count)) return nullptr;
|
||||
|
||||
retry:
|
||||
auto *accel = accels[lookup_index].get_acquire ();
|
||||
if (unlikely (!accel))
|
||||
{
|
||||
accel = hb_ot_layout_lookup_accelerator_t::create (table->get_lookup (lookup_index));
|
||||
if (unlikely (!accel))
|
||||
return nullptr;
|
||||
|
||||
if (unlikely (!accels[lookup_index].cmpexch (nullptr, accel)))
|
||||
{
|
||||
hb_free (accel);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
return accel;
|
||||
}
|
||||
|
||||
hb_blob_ptr_t<T> table;
|
||||
unsigned int lookup_count;
|
||||
hb_atomic_ptr_t<hb_ot_layout_lookup_accelerator_t> *accels;
|
||||
hb_ot_layout_lookup_accelerator_t *accels;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
|
|
@ -64,8 +64,6 @@ using OT::Layout::GPOS;
|
|||
* @include: hb-ot.h
|
||||
*
|
||||
* Functions for querying OpenType Layout features in the font face.
|
||||
* See the <ulink url="http://www.microsoft.com/typography/otspec/">OpenType
|
||||
* specification</ulink> for details.
|
||||
**/
|
||||
|
||||
|
||||
|
@ -748,7 +746,7 @@ hb_ot_layout_script_find_language (hb_face_t *face,
|
|||
*
|
||||
* Return value: `true` if one of the given language tags is found, `false` otherwise
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_ot_layout_script_select_language2 (hb_face_t *face,
|
||||
|
@ -1489,13 +1487,11 @@ hb_ot_layout_lookup_would_substitute (hb_face_t *face,
|
|||
unsigned int glyphs_length,
|
||||
hb_bool_t zero_context)
|
||||
{
|
||||
auto &gsub = face->table.GSUB;
|
||||
if (unlikely (lookup_index >= gsub->lookup_count)) return false;
|
||||
if (unlikely (lookup_index >= face->table.GSUB->lookup_count)) return false;
|
||||
OT::hb_would_apply_context_t c (face, glyphs, glyphs_length, (bool) zero_context);
|
||||
|
||||
const OT::SubstLookup& l = gsub->table->get_lookup (lookup_index);
|
||||
auto *accel = gsub->get_accel (lookup_index);
|
||||
return accel && l.would_apply (&c, accel);
|
||||
const OT::SubstLookup& l = face->table.GSUB->table->get_lookup (lookup_index);
|
||||
return l.would_apply (&c, &face->table.GSUB->accels[lookup_index]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1834,9 +1830,11 @@ struct GSUBProxy
|
|||
typedef OT::SubstLookup Lookup;
|
||||
|
||||
GSUBProxy (hb_face_t *face) :
|
||||
accel (*face->table.GSUB) {}
|
||||
table (*face->table.GSUB->table),
|
||||
accels (face->table.GSUB->accels) {}
|
||||
|
||||
const GSUB::accelerator_t &accel;
|
||||
const GSUB &table;
|
||||
const OT::hb_ot_layout_lookup_accelerator_t *accels;
|
||||
};
|
||||
|
||||
struct GPOSProxy
|
||||
|
@ -1846,16 +1844,17 @@ struct GPOSProxy
|
|||
typedef OT::PosLookup Lookup;
|
||||
|
||||
GPOSProxy (hb_face_t *face) :
|
||||
accel (*face->table.GPOS) {}
|
||||
table (*face->table.GPOS->table),
|
||||
accels (face->table.GPOS->accels) {}
|
||||
|
||||
const GPOS::accelerator_t &accel;
|
||||
const GPOS &table;
|
||||
const OT::hb_ot_layout_lookup_accelerator_t *accels;
|
||||
};
|
||||
|
||||
|
||||
static inline bool
|
||||
apply_forward (OT::hb_ot_apply_context_t *c,
|
||||
const OT::hb_ot_layout_lookup_accelerator_t &accel,
|
||||
unsigned subtable_count)
|
||||
const OT::hb_ot_layout_lookup_accelerator_t &accel)
|
||||
{
|
||||
bool use_cache = accel.cache_enter (c);
|
||||
|
||||
|
@ -1868,7 +1867,7 @@ apply_forward (OT::hb_ot_apply_context_t *c,
|
|||
(buffer->cur().mask & c->lookup_mask) &&
|
||||
c->check_glyph_property (&buffer->cur(), c->lookup_props))
|
||||
{
|
||||
applied = accel.apply (c, subtable_count, use_cache);
|
||||
applied = accel.apply (c, use_cache);
|
||||
}
|
||||
|
||||
if (applied)
|
||||
|
@ -1885,8 +1884,7 @@ apply_forward (OT::hb_ot_apply_context_t *c,
|
|||
|
||||
static inline bool
|
||||
apply_backward (OT::hb_ot_apply_context_t *c,
|
||||
const OT::hb_ot_layout_lookup_accelerator_t &accel,
|
||||
unsigned subtable_count)
|
||||
const OT::hb_ot_layout_lookup_accelerator_t &accel)
|
||||
{
|
||||
bool ret = false;
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
|
@ -1895,7 +1893,7 @@ apply_backward (OT::hb_ot_apply_context_t *c,
|
|||
if (accel.digest.may_have (buffer->cur().codepoint) &&
|
||||
(buffer->cur().mask & c->lookup_mask) &&
|
||||
c->check_glyph_property (&buffer->cur(), c->lookup_props))
|
||||
ret |= accel.apply (c, subtable_count, false);
|
||||
ret |= accel.apply (c, false);
|
||||
|
||||
/* The reverse lookup doesn't "advance" cursor (for good reason). */
|
||||
buffer->idx--;
|
||||
|
@ -1911,13 +1909,11 @@ apply_string (OT::hb_ot_apply_context_t *c,
|
|||
const typename Proxy::Lookup &lookup,
|
||||
const OT::hb_ot_layout_lookup_accelerator_t &accel)
|
||||
{
|
||||
bool ret = false;
|
||||
hb_buffer_t *buffer = c->buffer;
|
||||
unsigned subtable_count = lookup.get_subtable_count ();
|
||||
|
||||
if (unlikely (!buffer->len || !c->lookup_mask))
|
||||
return false;
|
||||
|
||||
bool ret = false;
|
||||
return ret;
|
||||
|
||||
c->set_lookup_props (lookup.get_props ());
|
||||
|
||||
|
@ -1928,7 +1924,7 @@ apply_string (OT::hb_ot_apply_context_t *c,
|
|||
buffer->clear_output ();
|
||||
|
||||
buffer->idx = 0;
|
||||
ret = apply_forward (c, accel, subtable_count);
|
||||
ret = apply_forward (c, accel);
|
||||
|
||||
if (!Proxy::always_inplace)
|
||||
buffer->sync ();
|
||||
|
@ -1938,7 +1934,7 @@ apply_string (OT::hb_ot_apply_context_t *c,
|
|||
/* in-place backward substitution/positioning */
|
||||
assert (!buffer->have_output);
|
||||
buffer->idx = buffer->len - 1;
|
||||
ret = apply_backward (c, accel, subtable_count);
|
||||
ret = apply_backward (c, accel);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -1963,10 +1959,6 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
|
|||
auto &lookup = lookups[table_index][i];
|
||||
|
||||
unsigned int lookup_index = lookup.index;
|
||||
|
||||
auto *accel = proxy.accel.get_accel (lookup_index);
|
||||
if (unlikely (!accel)) continue;
|
||||
|
||||
if (buffer->messaging () &&
|
||||
!buffer->message (font, "start lookup %u feature '%c%c%c%c'", lookup_index, HB_UNTAG (lookup.feature_tag))) continue;
|
||||
|
||||
|
@ -1974,7 +1966,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
|
|||
* (plus some past glyphs).
|
||||
*
|
||||
* Only try applying the lookup if there is any overlap. */
|
||||
if (accel->digest.may_have (c.digest))
|
||||
if (proxy.accels[lookup_index].digest.may_have (c.digest))
|
||||
{
|
||||
c.set_lookup_index (lookup_index);
|
||||
c.set_lookup_mask (lookup.mask);
|
||||
|
@ -1984,8 +1976,8 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
|
|||
c.set_per_syllable (lookup.per_syllable);
|
||||
|
||||
apply_string<Proxy> (&c,
|
||||
proxy.accel.table->get_lookup (lookup_index),
|
||||
*accel);
|
||||
proxy.table.get_lookup (lookup_index),
|
||||
proxy.accels[lookup_index]);
|
||||
}
|
||||
else if (buffer->messaging ())
|
||||
(void) buffer->message (font, "skipped lookup %u feature '%c%c%c%c' because no glyph matches", lookup_index, HB_UNTAG (lookup.feature_tag));
|
||||
|
|
|
@ -100,7 +100,7 @@ struct maxp
|
|||
maxp *maxp_prime = c->serializer->embed (this);
|
||||
if (unlikely (!maxp_prime)) return_trace (false);
|
||||
|
||||
maxp_prime->numGlyphs = hb_min (c->plan->num_output_glyphs (), 0xFFFFu);
|
||||
maxp_prime->numGlyphs = c->plan->num_output_glyphs ();
|
||||
if (maxp_prime->version.major == 1)
|
||||
{
|
||||
const maxpV1Tail *src_v1 = &StructAfter<maxpV1Tail> (*this);
|
||||
|
|
|
@ -181,4 +181,6 @@ hb_ot_name_get_utf32 (hb_face_t *face,
|
|||
return hb_ot_name_get_utf<hb_utf32_t> (face, name_id, language, text_size, text);
|
||||
}
|
||||
|
||||
#include "hb-ot-name-language-static.hh"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -35,6 +35,14 @@ HB_BEGIN_DECLS
|
|||
|
||||
/**
|
||||
* hb_ot_name_id_predefined_t:
|
||||
*
|
||||
* An enum type representing the pre-defined name IDs.
|
||||
*
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
|
||||
/**
|
||||
* hb_ot_name_id_t:
|
||||
* @HB_OT_NAME_ID_COPYRIGHT: Copyright notice
|
||||
* @HB_OT_NAME_ID_FONT_FAMILY: Font Family name
|
||||
* @HB_OT_NAME_ID_FONT_SUBFAMILY: Font Subfamily name
|
||||
|
@ -64,12 +72,14 @@ HB_BEGIN_DECLS
|
|||
* @HB_OT_NAME_ID_VARIATIONS_PS_PREFIX: Variations PostScript Name Prefix
|
||||
* @HB_OT_NAME_ID_INVALID: Value to represent a nonexistent name ID.
|
||||
*
|
||||
* An enum type representing the pre-defined name IDs.
|
||||
* An integral type representing an OpenType 'name' table name identifier.
|
||||
* There are predefined name IDs, as well as name IDs return from other
|
||||
* API. These can be used to fetch name strings from a font face.
|
||||
*
|
||||
* For more information on these fields, see the
|
||||
* [OpenType spec](https://docs.microsoft.com/en-us/typography/opentype/spec/name#name-ids).
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: 2.0.0
|
||||
**/
|
||||
typedef enum
|
||||
{
|
||||
|
@ -103,15 +113,6 @@ typedef enum
|
|||
HB_OT_NAME_ID_INVALID = 0xFFFF
|
||||
} hb_ot_name_id_predefined_t;
|
||||
|
||||
/**
|
||||
* hb_ot_name_id_t:
|
||||
*
|
||||
* An integral type representing an OpenType 'name' table name identifier.
|
||||
* There are predefined name IDs, as well as name IDs return from other
|
||||
* API. These can be used to fetch name strings from a font face.
|
||||
*
|
||||
* Since: 2.0.0
|
||||
**/
|
||||
typedef unsigned int hb_ot_name_id_t;
|
||||
|
||||
|
||||
|
|
|
@ -99,10 +99,6 @@ struct post
|
|||
post *post_prime = c->serializer->start_embed<post> ();
|
||||
if (unlikely (!post_prime)) return_trace (false);
|
||||
|
||||
bool glyph_names = c->plan->flags & HB_SUBSET_FLAGS_GLYPH_NAMES;
|
||||
if (!serialize (c->serializer, glyph_names))
|
||||
return_trace (false);
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
if (c->plan->normalized_coords)
|
||||
{
|
||||
|
@ -114,6 +110,10 @@ struct post
|
|||
}
|
||||
#endif
|
||||
|
||||
bool glyph_names = c->plan->flags & HB_SUBSET_FLAGS_GLYPH_NAMES;
|
||||
if (!serialize (c->serializer, glyph_names))
|
||||
return_trace (false);
|
||||
|
||||
if (c->plan->user_axes_location.has (HB_TAG ('s','l','n','t')) &&
|
||||
!c->plan->pinned_at_default)
|
||||
{
|
||||
|
|
|
@ -228,7 +228,7 @@ struct arabic_fallback_plan_t
|
|||
|
||||
hb_mask_t mask_array[ARABIC_FALLBACK_MAX_LOOKUPS];
|
||||
OT::SubstLookup *lookup_array[ARABIC_FALLBACK_MAX_LOOKUPS];
|
||||
OT::hb_ot_layout_lookup_accelerator_t *accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
|
||||
OT::hb_ot_layout_lookup_accelerator_t accel_array[ARABIC_FALLBACK_MAX_LOOKUPS];
|
||||
};
|
||||
|
||||
#if defined(_WIN32) && !defined(HB_NO_WIN1256)
|
||||
|
@ -278,7 +278,7 @@ arabic_fallback_plan_init_win1256 (arabic_fallback_plan_t *fallback_plan HB_UNUS
|
|||
fallback_plan->lookup_array[j] = const_cast<OT::SubstLookup*> (&(&manifest+manifest[i].lookupOffset));
|
||||
if (fallback_plan->lookup_array[j])
|
||||
{
|
||||
fallback_plan->accel_array[j] = OT::hb_ot_layout_lookup_accelerator_t::create (*fallback_plan->lookup_array[j]);
|
||||
fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ arabic_fallback_plan_init_unicode (arabic_fallback_plan_t *fallback_plan,
|
|||
fallback_plan->lookup_array[j] = arabic_fallback_synthesize_lookup (plan, font, i);
|
||||
if (fallback_plan->lookup_array[j])
|
||||
{
|
||||
fallback_plan->accel_array[j] = OT::hb_ot_layout_lookup_accelerator_t::create (*fallback_plan->lookup_array[j]);
|
||||
fallback_plan->accel_array[j].init (*fallback_plan->lookup_array[j]);
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
@ -355,7 +355,7 @@ arabic_fallback_plan_destroy (arabic_fallback_plan_t *fallback_plan)
|
|||
for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
|
||||
if (fallback_plan->lookup_array[i])
|
||||
{
|
||||
hb_free (fallback_plan->accel_array[i]);
|
||||
fallback_plan->accel_array[i].fini ();
|
||||
if (fallback_plan->free_lookups)
|
||||
hb_free (fallback_plan->lookup_array[i]);
|
||||
}
|
||||
|
@ -372,10 +372,9 @@ arabic_fallback_plan_shape (arabic_fallback_plan_t *fallback_plan,
|
|||
for (unsigned int i = 0; i < fallback_plan->num_lookups; i++)
|
||||
if (fallback_plan->lookup_array[i]) {
|
||||
c.set_lookup_mask (fallback_plan->mask_array[i]);
|
||||
if (fallback_plan->accel_array[i])
|
||||
hb_ot_layout_substitute_lookup (&c,
|
||||
*fallback_plan->lookup_array[i],
|
||||
*fallback_plan->accel_array[i]);
|
||||
hb_ot_layout_substitute_lookup (&c,
|
||||
*fallback_plan->lookup_array[i],
|
||||
fallback_plan->accel_array[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -482,7 +482,9 @@ initial_reordering_consonant_syllable (const hb_ot_shape_plan_t *plan,
|
|||
is_one_of (info[start+2], FLAG (I_Cat(ZWJ))))
|
||||
{
|
||||
buffer->merge_clusters (start+1, start+3);
|
||||
hb_swap (info[start+1], info[start+2]);
|
||||
hb_glyph_info_t tmp = info[start+1];
|
||||
info[start+1] = info[start+2];
|
||||
info[start+2] = tmp;
|
||||
}
|
||||
|
||||
/* 1. Find base consonant:
|
||||
|
@ -1067,15 +1069,12 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
|
|||
base = i;
|
||||
while (base < end && is_halant (info[base]))
|
||||
base++;
|
||||
if (base < end)
|
||||
info[base].indic_position() = POS_BASE_C;
|
||||
info[base].indic_position() = POS_BASE_C;
|
||||
|
||||
try_pref = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (base == end)
|
||||
break;
|
||||
}
|
||||
/* For Malayalam, skip over unformed below- (but NOT post-) forms. */
|
||||
if (buffer->props.script == HB_SCRIPT_MALAYALAM)
|
||||
|
|
|
@ -536,8 +536,6 @@ struct STAT
|
|||
| hb_map (&AxisValue::get_value_name_id)
|
||||
| hb_sink (nameids_to_retain)
|
||||
;
|
||||
|
||||
nameids_to_retain->add (elidedFallbackNameID);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
|
|
|
@ -222,353 +222,21 @@ struct DeltaSetIndexMap
|
|||
|
||||
struct VarStoreInstancer
|
||||
{
|
||||
VarStoreInstancer (const VariationStore *varStore,
|
||||
const DeltaSetIndexMap *varIdxMap,
|
||||
VarStoreInstancer (const VariationStore &varStore,
|
||||
const DeltaSetIndexMap &varIdxMap,
|
||||
hb_array_t<int> coords) :
|
||||
varStore (varStore), varIdxMap (varIdxMap), coords (coords) {}
|
||||
|
||||
operator bool () const { return varStore && bool (coords); }
|
||||
operator bool () const { return bool (coords); }
|
||||
|
||||
/* according to the spec, if colr table has varStore but does not have
|
||||
* varIdxMap, then an implicit identity mapping is used */
|
||||
float operator() (uint32_t varIdx, unsigned short offset = 0) const
|
||||
{ return varStore->get_delta (varIdxMap ? varIdxMap->map (VarIdx::add (varIdx, offset)) : varIdx + offset, coords); }
|
||||
{ return varStore.get_delta (varIdxMap.map (VarIdx::add (varIdx, offset)), coords); }
|
||||
|
||||
const VariationStore *varStore;
|
||||
const DeltaSetIndexMap *varIdxMap;
|
||||
const VariationStore &varStore;
|
||||
const DeltaSetIndexMap &varIdxMap;
|
||||
hb_array_t<int> coords;
|
||||
};
|
||||
|
||||
/* https://docs.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuplevariationheader */
|
||||
struct TupleVariationHeader
|
||||
{
|
||||
unsigned get_size (unsigned axis_count) const
|
||||
{ return min_size + get_all_tuples (axis_count).get_size (); }
|
||||
|
||||
unsigned get_data_size () const { return varDataSize; }
|
||||
|
||||
const TupleVariationHeader &get_next (unsigned axis_count) const
|
||||
{ return StructAtOffset<TupleVariationHeader> (this, get_size (axis_count)); }
|
||||
|
||||
float calculate_scalar (hb_array_t<int> coords, unsigned int coord_count,
|
||||
const hb_array_t<const F2DOT14> shared_tuples) const
|
||||
{
|
||||
hb_array_t<const F2DOT14> peak_tuple;
|
||||
|
||||
if (has_peak ())
|
||||
peak_tuple = get_peak_tuple (coord_count);
|
||||
else
|
||||
{
|
||||
unsigned int index = get_index ();
|
||||
if (unlikely (index * coord_count >= shared_tuples.length))
|
||||
return 0.f;
|
||||
peak_tuple = shared_tuples.sub_array (coord_count * index, coord_count);
|
||||
}
|
||||
|
||||
hb_array_t<const F2DOT14> start_tuple;
|
||||
hb_array_t<const F2DOT14> end_tuple;
|
||||
if (has_intermediate ())
|
||||
{
|
||||
start_tuple = get_start_tuple (coord_count);
|
||||
end_tuple = get_end_tuple (coord_count);
|
||||
}
|
||||
|
||||
float scalar = 1.f;
|
||||
for (unsigned int i = 0; i < coord_count; i++)
|
||||
{
|
||||
int v = coords[i];
|
||||
int peak = peak_tuple[i].to_int ();
|
||||
if (!peak || v == peak) continue;
|
||||
|
||||
if (has_intermediate ())
|
||||
{
|
||||
int start = start_tuple[i].to_int ();
|
||||
int end = end_tuple[i].to_int ();
|
||||
if (unlikely (start > peak || peak > end ||
|
||||
(start < 0 && end > 0 && peak))) continue;
|
||||
if (v < start || v > end) return 0.f;
|
||||
if (v < peak)
|
||||
{ if (peak != start) scalar *= (float) (v - start) / (peak - start); }
|
||||
else
|
||||
{ if (peak != end) scalar *= (float) (end - v) / (end - peak); }
|
||||
}
|
||||
else if (!v || v < hb_min (0, peak) || v > hb_max (0, peak)) return 0.f;
|
||||
else
|
||||
scalar *= (float) v / peak;
|
||||
}
|
||||
return scalar;
|
||||
}
|
||||
|
||||
bool has_peak () const { return tupleIndex & TuppleIndex::EmbeddedPeakTuple; }
|
||||
bool has_intermediate () const { return tupleIndex & TuppleIndex::IntermediateRegion; }
|
||||
bool has_private_points () const { return tupleIndex & TuppleIndex::PrivatePointNumbers; }
|
||||
unsigned get_index () const { return tupleIndex & TuppleIndex::TupleIndexMask; }
|
||||
|
||||
protected:
|
||||
struct TuppleIndex : HBUINT16
|
||||
{
|
||||
enum Flags {
|
||||
EmbeddedPeakTuple = 0x8000u,
|
||||
IntermediateRegion = 0x4000u,
|
||||
PrivatePointNumbers = 0x2000u,
|
||||
TupleIndexMask = 0x0FFFu
|
||||
};
|
||||
|
||||
DEFINE_SIZE_STATIC (2);
|
||||
};
|
||||
|
||||
hb_array_t<const F2DOT14> get_all_tuples (unsigned axis_count) const
|
||||
{ return StructAfter<UnsizedArrayOf<F2DOT14>> (tupleIndex).as_array ((has_peak () + has_intermediate () * 2) * axis_count); }
|
||||
hb_array_t<const F2DOT14> get_peak_tuple (unsigned axis_count) const
|
||||
{ return get_all_tuples (axis_count).sub_array (0, axis_count); }
|
||||
hb_array_t<const F2DOT14> get_start_tuple (unsigned axis_count) const
|
||||
{ return get_all_tuples (axis_count).sub_array (has_peak () * axis_count, axis_count); }
|
||||
hb_array_t<const F2DOT14> get_end_tuple (unsigned axis_count) const
|
||||
{ return get_all_tuples (axis_count).sub_array (has_peak () * axis_count + axis_count, axis_count); }
|
||||
|
||||
HBUINT16 varDataSize; /* The size in bytes of the serialized
|
||||
* data for this tuple variation table. */
|
||||
TuppleIndex tupleIndex; /* A packed field. The high 4 bits are flags (see below).
|
||||
The low 12 bits are an index into a shared tuple
|
||||
records array. */
|
||||
/* UnsizedArrayOf<F2DOT14> peakTuple - optional */
|
||||
/* Peak tuple record for this tuple variation table — optional,
|
||||
* determined by flags in the tupleIndex value.
|
||||
*
|
||||
* Note that this must always be included in the 'cvar' table. */
|
||||
/* UnsizedArrayOf<F2DOT14> intermediateStartTuple - optional */
|
||||
/* Intermediate start tuple record for this tuple variation table — optional,
|
||||
determined by flags in the tupleIndex value. */
|
||||
/* UnsizedArrayOf<F2DOT14> intermediateEndTuple - optional */
|
||||
/* Intermediate end tuple record for this tuple variation table — optional,
|
||||
* determined by flags in the tupleIndex value. */
|
||||
public:
|
||||
DEFINE_SIZE_MIN (4);
|
||||
};
|
||||
|
||||
struct TupleVariationData
|
||||
{
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
// here check on min_size only, TupleVariationHeader and var data will be
|
||||
// checked while accessing through iterator.
|
||||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
unsigned get_size (unsigned axis_count) const
|
||||
{
|
||||
unsigned total_size = min_size;
|
||||
unsigned count = tupleVarCount;
|
||||
const TupleVariationHeader *tuple_var_header = &(get_tuple_var_header());
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
total_size += tuple_var_header->get_size (axis_count) + tuple_var_header->get_data_size ();
|
||||
tuple_var_header = &tuple_var_header->get_next (axis_count);
|
||||
}
|
||||
|
||||
return total_size;
|
||||
}
|
||||
|
||||
const TupleVariationHeader &get_tuple_var_header (void) const
|
||||
{ return StructAfter<TupleVariationHeader> (data); }
|
||||
|
||||
struct tuple_iterator_t
|
||||
{
|
||||
void init (hb_bytes_t var_data_bytes_, unsigned int axis_count_, const void *table_base_)
|
||||
{
|
||||
var_data_bytes = var_data_bytes_;
|
||||
var_data = var_data_bytes_.as<TupleVariationData> ();
|
||||
index = 0;
|
||||
axis_count = axis_count_;
|
||||
current_tuple = &var_data->get_tuple_var_header ();
|
||||
data_offset = 0;
|
||||
table_base = table_base_;
|
||||
}
|
||||
|
||||
bool get_shared_indices (hb_vector_t<unsigned int> &shared_indices /* OUT */)
|
||||
{
|
||||
if (var_data->has_shared_point_numbers ())
|
||||
{
|
||||
const HBUINT8 *base = &(table_base+var_data->data);
|
||||
const HBUINT8 *p = base;
|
||||
if (!unpack_points (p, shared_indices, (const HBUINT8 *) (var_data_bytes.arrayZ + var_data_bytes.length))) return false;
|
||||
data_offset = p - base;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_valid () const
|
||||
{
|
||||
return (index < var_data->tupleVarCount.get_count ()) &&
|
||||
var_data_bytes.check_range (current_tuple, TupleVariationHeader::min_size) &&
|
||||
var_data_bytes.check_range (current_tuple, hb_max (current_tuple->get_data_size (),
|
||||
current_tuple->get_size (axis_count)));
|
||||
}
|
||||
|
||||
bool move_to_next ()
|
||||
{
|
||||
data_offset += current_tuple->get_data_size ();
|
||||
current_tuple = ¤t_tuple->get_next (axis_count);
|
||||
index++;
|
||||
return is_valid ();
|
||||
}
|
||||
|
||||
const HBUINT8 *get_serialized_data () const
|
||||
{ return &(table_base+var_data->data) + data_offset; }
|
||||
|
||||
private:
|
||||
const TupleVariationData *var_data;
|
||||
unsigned int index;
|
||||
unsigned int axis_count;
|
||||
unsigned int data_offset;
|
||||
const void *table_base;
|
||||
|
||||
public:
|
||||
hb_bytes_t var_data_bytes;
|
||||
const TupleVariationHeader *current_tuple;
|
||||
};
|
||||
|
||||
static bool get_tuple_iterator (hb_bytes_t var_data_bytes, unsigned axis_count,
|
||||
const void *table_base,
|
||||
hb_vector_t<unsigned int> &shared_indices /* OUT */,
|
||||
tuple_iterator_t *iterator /* OUT */)
|
||||
{
|
||||
iterator->init (var_data_bytes, axis_count, table_base);
|
||||
if (!iterator->get_shared_indices (shared_indices))
|
||||
return false;
|
||||
return iterator->is_valid ();
|
||||
}
|
||||
|
||||
bool has_shared_point_numbers () const { return tupleVarCount.has_shared_point_numbers (); }
|
||||
|
||||
static bool unpack_points (const HBUINT8 *&p /* IN/OUT */,
|
||||
hb_vector_t<unsigned int> &points /* OUT */,
|
||||
const HBUINT8 *end)
|
||||
{
|
||||
enum packed_point_flag_t
|
||||
{
|
||||
POINTS_ARE_WORDS = 0x80,
|
||||
POINT_RUN_COUNT_MASK = 0x7F
|
||||
};
|
||||
|
||||
if (unlikely (p + 1 > end)) return false;
|
||||
|
||||
unsigned count = *p++;
|
||||
if (count & POINTS_ARE_WORDS)
|
||||
{
|
||||
if (unlikely (p + 1 > end)) return false;
|
||||
count = ((count & POINT_RUN_COUNT_MASK) << 8) | *p++;
|
||||
}
|
||||
if (unlikely (!points.resize (count, false))) return false;
|
||||
|
||||
unsigned n = 0;
|
||||
unsigned i = 0;
|
||||
while (i < count)
|
||||
{
|
||||
if (unlikely (p + 1 > end)) return false;
|
||||
unsigned control = *p++;
|
||||
unsigned run_count = (control & POINT_RUN_COUNT_MASK) + 1;
|
||||
if (unlikely (i + run_count > count)) return false;
|
||||
unsigned j;
|
||||
if (control & POINTS_ARE_WORDS)
|
||||
{
|
||||
if (unlikely (p + run_count * HBUINT16::static_size > end)) return false;
|
||||
for (j = 0; j < run_count; j++, i++)
|
||||
{
|
||||
n += *(const HBUINT16 *)p;
|
||||
points.arrayZ[i] = n;
|
||||
p += HBUINT16::static_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unlikely (p + run_count > end)) return false;
|
||||
for (j = 0; j < run_count; j++, i++)
|
||||
{
|
||||
n += *p++;
|
||||
points.arrayZ[i] = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool unpack_deltas (const HBUINT8 *&p /* IN/OUT */,
|
||||
hb_vector_t<int> &deltas /* IN/OUT */,
|
||||
const HBUINT8 *end)
|
||||
{
|
||||
enum packed_delta_flag_t
|
||||
{
|
||||
DELTAS_ARE_ZERO = 0x80,
|
||||
DELTAS_ARE_WORDS = 0x40,
|
||||
DELTA_RUN_COUNT_MASK = 0x3F
|
||||
};
|
||||
|
||||
unsigned i = 0;
|
||||
unsigned count = deltas.length;
|
||||
while (i < count)
|
||||
{
|
||||
if (unlikely (p + 1 > end)) return false;
|
||||
unsigned control = *p++;
|
||||
unsigned run_count = (control & DELTA_RUN_COUNT_MASK) + 1;
|
||||
if (unlikely (i + run_count > count)) return false;
|
||||
unsigned j;
|
||||
if (control & DELTAS_ARE_ZERO)
|
||||
{
|
||||
for (j = 0; j < run_count; j++, i++)
|
||||
deltas.arrayZ[i] = 0;
|
||||
}
|
||||
else if (control & DELTAS_ARE_WORDS)
|
||||
{
|
||||
if (unlikely (p + run_count * HBUINT16::static_size > end)) return false;
|
||||
for (j = 0; j < run_count; j++, i++)
|
||||
{
|
||||
deltas.arrayZ[i] = * (const HBINT16 *) p;
|
||||
p += HBUINT16::static_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unlikely (p + run_count > end)) return false;
|
||||
for (j = 0; j < run_count; j++, i++)
|
||||
{
|
||||
deltas.arrayZ[i] = * (const HBINT8 *) p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool has_data () const { return tupleVarCount; }
|
||||
|
||||
protected:
|
||||
struct TupleVarCount : HBUINT16
|
||||
{
|
||||
bool has_shared_point_numbers () const { return ((*this) & SharedPointNumbers); }
|
||||
unsigned int get_count () const { return (*this) & CountMask; }
|
||||
|
||||
protected:
|
||||
enum Flags
|
||||
{
|
||||
SharedPointNumbers= 0x8000u,
|
||||
CountMask = 0x0FFFu
|
||||
};
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (2);
|
||||
};
|
||||
|
||||
TupleVarCount tupleVarCount; /* A packed field. The high 4 bits are flags, and the
|
||||
* low 12 bits are the number of tuple variation tables
|
||||
* for this glyph. The number of tuple variation tables
|
||||
* can be any number between 1 and 4095. */
|
||||
Offset16To<HBUINT8>
|
||||
data; /* Offset from the start of the base table
|
||||
* to the serialized data. */
|
||||
/* TupleVariationHeader tupleVariationHeaders[] *//* Array of tuple variation headers. */
|
||||
public:
|
||||
DEFINE_SIZE_MIN (4);
|
||||
};
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
|
|
|
@ -1,158 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2023 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_VAR_CVAR_TABLE_HH
|
||||
#define HB_OT_VAR_CVAR_TABLE_HH
|
||||
|
||||
#include "hb-ot-var-common.hh"
|
||||
|
||||
|
||||
namespace OT {
|
||||
/*
|
||||
* cvar -- control value table (CVT) Variations
|
||||
* https://docs.microsoft.com/en-us/typography/opentype/spec/cvar
|
||||
*/
|
||||
#define HB_OT_TAG_cvar HB_TAG('c','v','a','r')
|
||||
|
||||
struct cvar
|
||||
{
|
||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_cvar;
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (c->check_struct (this) &&
|
||||
version.sanitize (c) && likely (version.major == 1) &&
|
||||
tupleVariationData.sanitize (c));
|
||||
}
|
||||
|
||||
const TupleVariationData* get_tuple_var_data (void) const
|
||||
{ return &tupleVariationData; }
|
||||
|
||||
static bool calculate_cvt_deltas (unsigned axis_count,
|
||||
hb_array_t<int> coords,
|
||||
unsigned num_cvt_item,
|
||||
const TupleVariationData *tuple_var_data,
|
||||
const void *base,
|
||||
hb_vector_t<float>& cvt_deltas /* OUT */)
|
||||
{
|
||||
if (!coords) return true;
|
||||
hb_vector_t<unsigned> shared_indices;
|
||||
TupleVariationData::tuple_iterator_t iterator;
|
||||
unsigned var_data_length = tuple_var_data->get_size (axis_count);
|
||||
hb_bytes_t var_data_bytes = hb_bytes_t (reinterpret_cast<const char*> (tuple_var_data), var_data_length);
|
||||
if (!TupleVariationData::get_tuple_iterator (var_data_bytes, axis_count, base,
|
||||
shared_indices, &iterator))
|
||||
return true; /* isn't applied at all */
|
||||
|
||||
hb_array_t<const F2DOT14> shared_tuples = hb_array<F2DOT14> ();
|
||||
hb_vector_t<unsigned> private_indices;
|
||||
hb_vector_t<int> unpacked_deltas;
|
||||
|
||||
do
|
||||
{
|
||||
float scalar = iterator.current_tuple->calculate_scalar (coords, axis_count, shared_tuples);
|
||||
if (scalar == 0.f) continue;
|
||||
const HBUINT8 *p = iterator.get_serialized_data ();
|
||||
unsigned int length = iterator.current_tuple->get_data_size ();
|
||||
if (unlikely (!iterator.var_data_bytes.check_range (p, length)))
|
||||
return false;
|
||||
|
||||
const HBUINT8 *end = p + length;
|
||||
|
||||
bool has_private_points = iterator.current_tuple->has_private_points ();
|
||||
if (has_private_points &&
|
||||
!TupleVariationData::unpack_points (p, private_indices, end))
|
||||
return false;
|
||||
const hb_vector_t<unsigned int> &indices = has_private_points ? private_indices : shared_indices;
|
||||
|
||||
bool apply_to_all = (indices.length == 0);
|
||||
unsigned num_deltas = apply_to_all ? num_cvt_item : indices.length;
|
||||
if (unlikely (!unpacked_deltas.resize (num_deltas, false))) return false;
|
||||
if (unlikely (!TupleVariationData::unpack_deltas (p, unpacked_deltas, end))) return false;
|
||||
|
||||
for (unsigned int i = 0; i < num_deltas; i++)
|
||||
{
|
||||
unsigned int idx = apply_to_all ? i : indices[i];
|
||||
if (unlikely (idx >= num_cvt_item)) continue;
|
||||
if (scalar != 1.0f) cvt_deltas[idx] += unpacked_deltas[i] * scalar ;
|
||||
else cvt_deltas[idx] += unpacked_deltas[i];
|
||||
}
|
||||
} while (iterator.move_to_next ());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool add_cvt_and_apply_deltas (hb_subset_plan_t *plan,
|
||||
const TupleVariationData *tuple_var_data,
|
||||
const void *base)
|
||||
{
|
||||
const hb_tag_t cvt = HB_TAG('c','v','t',' ');
|
||||
hb_blob_t *cvt_blob = hb_face_reference_table (plan->source, cvt);
|
||||
hb_blob_t *cvt_prime_blob = hb_blob_copy_writable_or_fail (cvt_blob);
|
||||
hb_blob_destroy (cvt_blob);
|
||||
|
||||
if (unlikely (!cvt_prime_blob))
|
||||
return false;
|
||||
|
||||
unsigned cvt_blob_length = hb_blob_get_length (cvt_prime_blob);
|
||||
unsigned num_cvt_item = cvt_blob_length / FWORD::static_size;
|
||||
|
||||
hb_vector_t<float> cvt_deltas;
|
||||
if (unlikely (!cvt_deltas.resize (num_cvt_item)))
|
||||
{
|
||||
hb_blob_destroy (cvt_prime_blob);
|
||||
return false;
|
||||
}
|
||||
hb_memset (cvt_deltas.arrayZ, 0, cvt_deltas.get_size ());
|
||||
|
||||
if (!calculate_cvt_deltas (plan->normalized_coords.length, plan->normalized_coords.as_array (),
|
||||
num_cvt_item, tuple_var_data, base, cvt_deltas))
|
||||
{
|
||||
hb_blob_destroy (cvt_prime_blob);
|
||||
return false;
|
||||
}
|
||||
|
||||
FWORD *cvt_prime = (FWORD *) hb_blob_get_data_writable (cvt_prime_blob, nullptr);
|
||||
for (unsigned i = 0; i < num_cvt_item; i++)
|
||||
cvt_prime[i] += (int) roundf (cvt_deltas[i]);
|
||||
|
||||
bool success = plan->add_table (cvt, cvt_prime_blob);
|
||||
hb_blob_destroy (cvt_prime_blob);
|
||||
return success;
|
||||
}
|
||||
|
||||
protected:
|
||||
FixedVersion<>version; /* Version of the CVT variation table
|
||||
* initially set to 0x00010000u */
|
||||
TupleVariationData tupleVariationData; /* TupleVariationDate for cvar table */
|
||||
public:
|
||||
DEFINE_SIZE_MIN (8);
|
||||
};
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
|
||||
#endif /* HB_OT_VAR_CVAR_TABLE_HH */
|
|
@ -29,7 +29,6 @@
|
|||
#define HB_OT_VAR_GVAR_TABLE_HH
|
||||
|
||||
#include "hb-open-type.hh"
|
||||
#include "hb-ot-var-common.hh"
|
||||
|
||||
/*
|
||||
* gvar -- Glyph Variation Table
|
||||
|
@ -91,8 +90,311 @@ struct contour_point_vector_t : hb_vector_t<contour_point_t>
|
|||
}
|
||||
};
|
||||
|
||||
struct GlyphVariationData : TupleVariationData
|
||||
{};
|
||||
/* https://docs.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuplevariationheader */
|
||||
struct TupleVariationHeader
|
||||
{
|
||||
unsigned get_size (unsigned axis_count) const
|
||||
{ return min_size + get_all_tuples (axis_count).get_size (); }
|
||||
|
||||
unsigned get_data_size () const { return varDataSize; }
|
||||
|
||||
const TupleVariationHeader &get_next (unsigned axis_count) const
|
||||
{ return StructAtOffset<TupleVariationHeader> (this, get_size (axis_count)); }
|
||||
|
||||
float calculate_scalar (hb_array_t<int> coords, unsigned int coord_count,
|
||||
const hb_array_t<const F2DOT14> shared_tuples) const
|
||||
{
|
||||
hb_array_t<const F2DOT14> peak_tuple;
|
||||
|
||||
if (has_peak ())
|
||||
peak_tuple = get_peak_tuple (coord_count);
|
||||
else
|
||||
{
|
||||
unsigned int index = get_index ();
|
||||
if (unlikely (index * coord_count >= shared_tuples.length))
|
||||
return 0.f;
|
||||
peak_tuple = shared_tuples.sub_array (coord_count * index, coord_count);
|
||||
}
|
||||
|
||||
hb_array_t<const F2DOT14> start_tuple;
|
||||
hb_array_t<const F2DOT14> end_tuple;
|
||||
if (has_intermediate ())
|
||||
{
|
||||
start_tuple = get_start_tuple (coord_count);
|
||||
end_tuple = get_end_tuple (coord_count);
|
||||
}
|
||||
|
||||
float scalar = 1.f;
|
||||
for (unsigned int i = 0; i < coord_count; i++)
|
||||
{
|
||||
int v = coords[i];
|
||||
int peak = peak_tuple[i].to_int ();
|
||||
if (!peak || v == peak) continue;
|
||||
|
||||
if (has_intermediate ())
|
||||
{
|
||||
int start = start_tuple[i].to_int ();
|
||||
int end = end_tuple[i].to_int ();
|
||||
if (unlikely (start > peak || peak > end ||
|
||||
(start < 0 && end > 0 && peak))) continue;
|
||||
if (v < start || v > end) return 0.f;
|
||||
if (v < peak)
|
||||
{ if (peak != start) scalar *= (float) (v - start) / (peak - start); }
|
||||
else
|
||||
{ if (peak != end) scalar *= (float) (end - v) / (end - peak); }
|
||||
}
|
||||
else if (!v || v < hb_min (0, peak) || v > hb_max (0, peak)) return 0.f;
|
||||
else
|
||||
scalar *= (float) v / peak;
|
||||
}
|
||||
return scalar;
|
||||
}
|
||||
|
||||
bool has_peak () const { return tupleIndex & TuppleIndex::EmbeddedPeakTuple; }
|
||||
bool has_intermediate () const { return tupleIndex & TuppleIndex::IntermediateRegion; }
|
||||
bool has_private_points () const { return tupleIndex & TuppleIndex::PrivatePointNumbers; }
|
||||
unsigned get_index () const { return tupleIndex & TuppleIndex::TupleIndexMask; }
|
||||
|
||||
protected:
|
||||
struct TuppleIndex : HBUINT16
|
||||
{
|
||||
enum Flags {
|
||||
EmbeddedPeakTuple = 0x8000u,
|
||||
IntermediateRegion = 0x4000u,
|
||||
PrivatePointNumbers = 0x2000u,
|
||||
TupleIndexMask = 0x0FFFu
|
||||
};
|
||||
|
||||
DEFINE_SIZE_STATIC (2);
|
||||
};
|
||||
|
||||
hb_array_t<const F2DOT14> get_all_tuples (unsigned axis_count) const
|
||||
{ return StructAfter<UnsizedArrayOf<F2DOT14>> (tupleIndex).as_array ((has_peak () + has_intermediate () * 2) * axis_count); }
|
||||
hb_array_t<const F2DOT14> get_peak_tuple (unsigned axis_count) const
|
||||
{ return get_all_tuples (axis_count).sub_array (0, axis_count); }
|
||||
hb_array_t<const F2DOT14> get_start_tuple (unsigned axis_count) const
|
||||
{ return get_all_tuples (axis_count).sub_array (has_peak () * axis_count, axis_count); }
|
||||
hb_array_t<const F2DOT14> get_end_tuple (unsigned axis_count) const
|
||||
{ return get_all_tuples (axis_count).sub_array (has_peak () * axis_count + axis_count, axis_count); }
|
||||
|
||||
HBUINT16 varDataSize; /* The size in bytes of the serialized
|
||||
* data for this tuple variation table. */
|
||||
TuppleIndex tupleIndex; /* A packed field. The high 4 bits are flags (see below).
|
||||
The low 12 bits are an index into a shared tuple
|
||||
records array. */
|
||||
/* UnsizedArrayOf<F2DOT14> peakTuple - optional */
|
||||
/* Peak tuple record for this tuple variation table — optional,
|
||||
* determined by flags in the tupleIndex value.
|
||||
*
|
||||
* Note that this must always be included in the 'cvar' table. */
|
||||
/* UnsizedArrayOf<F2DOT14> intermediateStartTuple - optional */
|
||||
/* Intermediate start tuple record for this tuple variation table — optional,
|
||||
determined by flags in the tupleIndex value. */
|
||||
/* UnsizedArrayOf<F2DOT14> intermediateEndTuple - optional */
|
||||
/* Intermediate end tuple record for this tuple variation table — optional,
|
||||
* determined by flags in the tupleIndex value. */
|
||||
public:
|
||||
DEFINE_SIZE_MIN (4);
|
||||
};
|
||||
|
||||
struct GlyphVariationData
|
||||
{
|
||||
const TupleVariationHeader &get_tuple_var_header (void) const
|
||||
{ return StructAfter<TupleVariationHeader> (data); }
|
||||
|
||||
struct tuple_iterator_t
|
||||
{
|
||||
void init (hb_bytes_t var_data_bytes_, unsigned int axis_count_)
|
||||
{
|
||||
var_data_bytes = var_data_bytes_;
|
||||
var_data = var_data_bytes_.as<GlyphVariationData> ();
|
||||
index = 0;
|
||||
axis_count = axis_count_;
|
||||
current_tuple = &var_data->get_tuple_var_header ();
|
||||
data_offset = 0;
|
||||
}
|
||||
|
||||
bool get_shared_indices (hb_vector_t<unsigned int> &shared_indices /* OUT */)
|
||||
{
|
||||
if (var_data->has_shared_point_numbers ())
|
||||
{
|
||||
const HBUINT8 *base = &(var_data+var_data->data);
|
||||
const HBUINT8 *p = base;
|
||||
if (!unpack_points (p, shared_indices, (const HBUINT8 *) (var_data_bytes.arrayZ + var_data_bytes.length))) return false;
|
||||
data_offset = p - base;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool is_valid () const
|
||||
{
|
||||
return (index < var_data->tupleVarCount.get_count ()) &&
|
||||
var_data_bytes.check_range (current_tuple, TupleVariationHeader::min_size) &&
|
||||
var_data_bytes.check_range (current_tuple, hb_max (current_tuple->get_data_size (),
|
||||
current_tuple->get_size (axis_count)));
|
||||
}
|
||||
|
||||
bool move_to_next ()
|
||||
{
|
||||
data_offset += current_tuple->get_data_size ();
|
||||
current_tuple = ¤t_tuple->get_next (axis_count);
|
||||
index++;
|
||||
return is_valid ();
|
||||
}
|
||||
|
||||
const HBUINT8 *get_serialized_data () const
|
||||
{ return &(var_data+var_data->data) + data_offset; }
|
||||
|
||||
private:
|
||||
const GlyphVariationData *var_data;
|
||||
unsigned int index;
|
||||
unsigned int axis_count;
|
||||
unsigned int data_offset;
|
||||
|
||||
public:
|
||||
hb_bytes_t var_data_bytes;
|
||||
const TupleVariationHeader *current_tuple;
|
||||
};
|
||||
|
||||
static bool get_tuple_iterator (hb_bytes_t var_data_bytes, unsigned axis_count,
|
||||
hb_vector_t<unsigned int> &shared_indices /* OUT */,
|
||||
tuple_iterator_t *iterator /* OUT */)
|
||||
{
|
||||
iterator->init (var_data_bytes, axis_count);
|
||||
if (!iterator->get_shared_indices (shared_indices))
|
||||
return false;
|
||||
return iterator->is_valid ();
|
||||
}
|
||||
|
||||
bool has_shared_point_numbers () const { return tupleVarCount.has_shared_point_numbers (); }
|
||||
|
||||
static bool unpack_points (const HBUINT8 *&p /* IN/OUT */,
|
||||
hb_vector_t<unsigned int> &points /* OUT */,
|
||||
const HBUINT8 *end)
|
||||
{
|
||||
enum packed_point_flag_t
|
||||
{
|
||||
POINTS_ARE_WORDS = 0x80,
|
||||
POINT_RUN_COUNT_MASK = 0x7F
|
||||
};
|
||||
|
||||
if (unlikely (p + 1 > end)) return false;
|
||||
|
||||
unsigned count = *p++;
|
||||
if (count & POINTS_ARE_WORDS)
|
||||
{
|
||||
if (unlikely (p + 1 > end)) return false;
|
||||
count = ((count & POINT_RUN_COUNT_MASK) << 8) | *p++;
|
||||
}
|
||||
if (unlikely (!points.resize (count, false))) return false;
|
||||
|
||||
unsigned n = 0;
|
||||
unsigned i = 0;
|
||||
while (i < count)
|
||||
{
|
||||
if (unlikely (p + 1 > end)) return false;
|
||||
unsigned control = *p++;
|
||||
unsigned run_count = (control & POINT_RUN_COUNT_MASK) + 1;
|
||||
if (unlikely (i + run_count > count)) return false;
|
||||
unsigned j;
|
||||
if (control & POINTS_ARE_WORDS)
|
||||
{
|
||||
if (unlikely (p + run_count * HBUINT16::static_size > end)) return false;
|
||||
for (j = 0; j < run_count; j++, i++)
|
||||
{
|
||||
n += *(const HBUINT16 *)p;
|
||||
points.arrayZ[i] = n;
|
||||
p += HBUINT16::static_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unlikely (p + run_count > end)) return false;
|
||||
for (j = 0; j < run_count; j++, i++)
|
||||
{
|
||||
n += *p++;
|
||||
points.arrayZ[i] = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool unpack_deltas (const HBUINT8 *&p /* IN/OUT */,
|
||||
hb_vector_t<int> &deltas /* IN/OUT */,
|
||||
const HBUINT8 *end)
|
||||
{
|
||||
enum packed_delta_flag_t
|
||||
{
|
||||
DELTAS_ARE_ZERO = 0x80,
|
||||
DELTAS_ARE_WORDS = 0x40,
|
||||
DELTA_RUN_COUNT_MASK = 0x3F
|
||||
};
|
||||
|
||||
unsigned i = 0;
|
||||
unsigned count = deltas.length;
|
||||
while (i < count)
|
||||
{
|
||||
if (unlikely (p + 1 > end)) return false;
|
||||
unsigned control = *p++;
|
||||
unsigned run_count = (control & DELTA_RUN_COUNT_MASK) + 1;
|
||||
if (unlikely (i + run_count > count)) return false;
|
||||
unsigned j;
|
||||
if (control & DELTAS_ARE_ZERO)
|
||||
{
|
||||
for (j = 0; j < run_count; j++, i++)
|
||||
deltas.arrayZ[i] = 0;
|
||||
}
|
||||
else if (control & DELTAS_ARE_WORDS)
|
||||
{
|
||||
if (unlikely (p + run_count * HBUINT16::static_size > end)) return false;
|
||||
for (j = 0; j < run_count; j++, i++)
|
||||
{
|
||||
deltas.arrayZ[i] = * (const HBINT16 *) p;
|
||||
p += HBUINT16::static_size;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unlikely (p + run_count > end)) return false;
|
||||
for (j = 0; j < run_count; j++, i++)
|
||||
{
|
||||
deltas.arrayZ[i] = * (const HBINT8 *) p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool has_data () const { return tupleVarCount; }
|
||||
|
||||
protected:
|
||||
struct TupleVarCount : HBUINT16
|
||||
{
|
||||
bool has_shared_point_numbers () const { return ((*this) & SharedPointNumbers); }
|
||||
unsigned int get_count () const { return (*this) & CountMask; }
|
||||
|
||||
protected:
|
||||
enum Flags
|
||||
{
|
||||
SharedPointNumbers= 0x8000u,
|
||||
CountMask = 0x0FFFu
|
||||
};
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (2);
|
||||
};
|
||||
|
||||
TupleVarCount tupleVarCount; /* A packed field. The high 4 bits are flags, and the
|
||||
* low 12 bits are the number of tuple variation tables
|
||||
* for this glyph. The number of tuple variation tables
|
||||
* can be any number between 1 and 4095. */
|
||||
Offset16To<HBUINT8>
|
||||
data; /* Offset from the start of the GlyphVariationData table
|
||||
* to the serialized data. */
|
||||
/* TupleVariationHeader tupleVariationHeaders[] *//* Array of tuple variation headers. */
|
||||
public:
|
||||
DEFINE_SIZE_MIN (4);
|
||||
};
|
||||
|
||||
struct gvar
|
||||
{
|
||||
|
@ -104,8 +406,8 @@ struct gvar
|
|||
return_trace (c->check_struct (this) && (version.major == 1) &&
|
||||
sharedTuples.sanitize (c, this, axisCount * sharedTupleCount) &&
|
||||
(is_long_offset () ?
|
||||
c->check_array (get_long_offset_array (), c->get_num_glyphs () + 1) :
|
||||
c->check_array (get_short_offset_array (), c->get_num_glyphs () + 1)));
|
||||
c->check_array (get_long_offset_array (), glyphCount+1) :
|
||||
c->check_array (get_short_offset_array (), glyphCount+1)));
|
||||
}
|
||||
|
||||
/* GlyphVariationData not sanitized here; must be checked while accessing each glyph variation data */
|
||||
|
@ -116,8 +418,6 @@ struct gvar
|
|||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
unsigned glyph_count = version.to_int () ? c->plan->source->get_num_glyphs () : 0;
|
||||
|
||||
gvar *out = c->serializer->allocate_min<gvar> ();
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
|
@ -127,7 +427,7 @@ struct gvar
|
|||
out->sharedTupleCount = sharedTupleCount;
|
||||
|
||||
unsigned int num_glyphs = c->plan->num_output_glyphs ();
|
||||
out->glyphCountX = hb_min (0xFFFFu, num_glyphs);
|
||||
out->glyphCount = num_glyphs;
|
||||
|
||||
unsigned int subset_data_size = 0;
|
||||
for (hb_codepoint_t gid = (c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE) ? 0 : 1;
|
||||
|
@ -136,7 +436,7 @@ struct gvar
|
|||
{
|
||||
hb_codepoint_t old_gid;
|
||||
if (!c->plan->old_gid_for_new_gid (gid, &old_gid)) continue;
|
||||
subset_data_size += get_glyph_var_data_bytes (c->source_blob, glyph_count, old_gid).length;
|
||||
subset_data_size += get_glyph_var_data_bytes (c->source_blob, old_gid).length;
|
||||
}
|
||||
|
||||
bool long_offset = subset_data_size & ~0xFFFFu;
|
||||
|
@ -168,9 +468,7 @@ struct gvar
|
|||
{
|
||||
hb_codepoint_t old_gid;
|
||||
hb_bytes_t var_data_bytes = c->plan->old_gid_for_new_gid (gid, &old_gid)
|
||||
? get_glyph_var_data_bytes (c->source_blob,
|
||||
glyph_count,
|
||||
old_gid)
|
||||
? get_glyph_var_data_bytes (c->source_blob, old_gid)
|
||||
: hb_bytes_t ();
|
||||
|
||||
if (long_offset)
|
||||
|
@ -192,12 +490,10 @@ struct gvar
|
|||
}
|
||||
|
||||
protected:
|
||||
const hb_bytes_t get_glyph_var_data_bytes (hb_blob_t *blob,
|
||||
unsigned glyph_count,
|
||||
hb_codepoint_t glyph) const
|
||||
const hb_bytes_t get_glyph_var_data_bytes (hb_blob_t *blob, hb_codepoint_t glyph) const
|
||||
{
|
||||
unsigned start_offset = get_offset (glyph_count, glyph);
|
||||
unsigned end_offset = get_offset (glyph_count, glyph+1);
|
||||
unsigned start_offset = get_offset (glyph);
|
||||
unsigned end_offset = get_offset (glyph+1);
|
||||
if (unlikely (end_offset < start_offset)) return hb_bytes_t ();
|
||||
unsigned length = end_offset - start_offset;
|
||||
hb_bytes_t var_data = blob->as_bytes ().sub_array (((unsigned) dataZ) + start_offset, length);
|
||||
|
@ -206,9 +502,9 @@ struct gvar
|
|||
|
||||
bool is_long_offset () const { return flags & 1; }
|
||||
|
||||
unsigned get_offset (unsigned glyph_count, unsigned i) const
|
||||
unsigned get_offset (unsigned i) const
|
||||
{
|
||||
if (unlikely (i > glyph_count)) return 0;
|
||||
if (unlikely (i > glyphCount)) return 0;
|
||||
_hb_compiler_memory_r_barrier ();
|
||||
return is_long_offset () ? get_long_offset_array ()[i] : get_short_offset_array ()[i] * 2;
|
||||
}
|
||||
|
@ -220,11 +516,7 @@ struct gvar
|
|||
struct accelerator_t
|
||||
{
|
||||
accelerator_t (hb_face_t *face)
|
||||
{
|
||||
table = hb_sanitize_context_t ().reference_table<gvar> (face);
|
||||
/* If sanitize failed, set glyphCount to 0. */
|
||||
glyphCount = table->version.to_int () ? face->get_num_glyphs () : 0;
|
||||
}
|
||||
{ table = hb_sanitize_context_t ().reference_table<gvar> (face); }
|
||||
~accelerator_t () { table.destroy (); }
|
||||
|
||||
private:
|
||||
|
@ -262,14 +554,13 @@ struct gvar
|
|||
{
|
||||
if (!coords) return true;
|
||||
|
||||
if (unlikely (glyph >= glyphCount)) return true;
|
||||
if (unlikely (glyph >= table->glyphCount)) return true;
|
||||
|
||||
hb_bytes_t var_data_bytes = table->get_glyph_var_data_bytes (table.get_blob (), glyphCount, glyph);
|
||||
hb_bytes_t var_data_bytes = table->get_glyph_var_data_bytes (table.get_blob (), glyph);
|
||||
if (!var_data_bytes.as<GlyphVariationData> ()->has_data ()) return true;
|
||||
hb_vector_t<unsigned int> shared_indices;
|
||||
GlyphVariationData::tuple_iterator_t iterator;
|
||||
if (!GlyphVariationData::get_tuple_iterator (var_data_bytes, table->axisCount,
|
||||
var_data_bytes.arrayZ,
|
||||
shared_indices, &iterator))
|
||||
return true; /* so isn't applied at all */
|
||||
|
||||
|
@ -413,7 +704,6 @@ struct gvar
|
|||
|
||||
private:
|
||||
hb_blob_ptr_t<gvar> table;
|
||||
unsigned glyphCount;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
@ -429,7 +719,7 @@ struct gvar
|
|||
NNOffset32To<UnsizedArrayOf<F2DOT14>>
|
||||
sharedTuples; /* Offset from the start of this table to the shared tuple records.
|
||||
* Array of tuple records shared across all glyph variation data tables. */
|
||||
HBUINT16 glyphCountX; /* The number of glyphs in this font. This must match the number of
|
||||
HBUINT16 glyphCount; /* The number of glyphs in this font. This must match the number of
|
||||
* glyphs stored elsewhere in the font. */
|
||||
HBUINT16 flags; /* Bit-field that gives the format of the offset array that follows.
|
||||
* If bit 0 is clear, the offsets are uint16; if bit 0 is set, the
|
||||
|
|
|
@ -265,9 +265,6 @@ struct HVARVVAR
|
|||
rsbMap.sanitize (c, this));
|
||||
}
|
||||
|
||||
const VariationStore& get_var_store () const
|
||||
{ return this+varStore; }
|
||||
|
||||
void listup_index_maps (hb_vector_t<const DeltaSetIndexMap *> &index_maps) const
|
||||
{
|
||||
index_maps.push (&(this+advMap));
|
||||
|
|
|
@ -1,321 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2023 Behdad Esfahbod
|
||||
* Copyright © 1999 David Turner
|
||||
* Copyright © 2005 Werner Lemberg
|
||||
* Copyright © 2013-2015 Alexei Podtelezhnikov
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#ifndef HB_NO_OUTLINE
|
||||
|
||||
#include "hb-outline.hh"
|
||||
|
||||
#include "hb-machinery.hh"
|
||||
|
||||
|
||||
void hb_outline_t::replay (hb_draw_funcs_t *pen, void *pen_data) const
|
||||
{
|
||||
hb_draw_state_t st = HB_DRAW_STATE_DEFAULT;
|
||||
|
||||
unsigned first = 0;
|
||||
for (unsigned contour : contours)
|
||||
{
|
||||
auto it = points.as_array ().sub_array (first, contour - first);
|
||||
while (it)
|
||||
{
|
||||
hb_outline_point_t p1 = *it++;
|
||||
switch (p1.type)
|
||||
{
|
||||
case hb_outline_point_t::type_t::MOVE_TO:
|
||||
{
|
||||
pen->move_to (pen_data, st,
|
||||
p1.x, p1.y);
|
||||
}
|
||||
break;
|
||||
case hb_outline_point_t::type_t::LINE_TO:
|
||||
{
|
||||
pen->line_to (pen_data, st,
|
||||
p1.x, p1.y);
|
||||
}
|
||||
break;
|
||||
case hb_outline_point_t::type_t::QUADRATIC_TO:
|
||||
{
|
||||
hb_outline_point_t p2 = *it++;
|
||||
pen->quadratic_to (pen_data, st,
|
||||
p1.x, p1.y,
|
||||
p2.x, p2.y);
|
||||
}
|
||||
break;
|
||||
case hb_outline_point_t::type_t::CUBIC_TO:
|
||||
{
|
||||
hb_outline_point_t p2 = *it++;
|
||||
hb_outline_point_t p3 = *it++;
|
||||
pen->cubic_to (pen_data, st,
|
||||
p1.x, p1.y,
|
||||
p2.x, p2.y,
|
||||
p3.x, p3.y);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
pen->close_path (pen_data, st);
|
||||
first = contour;
|
||||
}
|
||||
}
|
||||
|
||||
float hb_outline_t::control_area () const
|
||||
{
|
||||
float a = 0;
|
||||
unsigned first = 0;
|
||||
for (unsigned contour : contours)
|
||||
{
|
||||
for (unsigned i = first; i < contour; i++)
|
||||
{
|
||||
unsigned j = i + 1 < contour ? i + 1 : first;
|
||||
|
||||
auto &pi = points[i];
|
||||
auto &pj = points[j];
|
||||
a += pi.x * pj.y - pi.y * pj.x;
|
||||
}
|
||||
|
||||
first = contour;
|
||||
}
|
||||
return a * .5f;
|
||||
}
|
||||
|
||||
void hb_outline_t::embolden (float x_strength, float y_strength,
|
||||
float x_shift, float y_shift)
|
||||
{
|
||||
/* This function is a straight port of FreeType's FT_Outline_EmboldenXY.
|
||||
* Permission has been obtained from the FreeType authors of the code
|
||||
* to relicense it under the HarfBuzz license. */
|
||||
|
||||
if (!x_strength && !y_strength) return;
|
||||
if (!points) return;
|
||||
|
||||
x_strength /= 2.f;
|
||||
y_strength /= 2.f;
|
||||
|
||||
bool orientation_negative = control_area () < 0;
|
||||
|
||||
signed first = 0;
|
||||
for (unsigned c = 0; c < contours.length; c++)
|
||||
{
|
||||
hb_outline_vector_t in, out, anchor, shift;
|
||||
float l_in, l_out, l_anchor = 0, l, q, d;
|
||||
|
||||
l_in = 0;
|
||||
signed last = (int) contours[c] - 1;
|
||||
|
||||
/* pacify compiler */
|
||||
in.x = in.y = anchor.x = anchor.y = 0;
|
||||
|
||||
/* Counter j cycles though the points; counter i advances only */
|
||||
/* when points are moved; anchor k marks the first moved point. */
|
||||
for ( signed i = last, j = first, k = -1;
|
||||
j != i && i != k;
|
||||
j = j < last ? j + 1 : first )
|
||||
{
|
||||
if ( j != k )
|
||||
{
|
||||
out.x = points[j].x - points[i].x;
|
||||
out.y = points[j].y - points[i].y;
|
||||
l_out = out.normalize_len ();
|
||||
|
||||
if ( l_out == 0 )
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
out = anchor;
|
||||
l_out = l_anchor;
|
||||
}
|
||||
|
||||
if ( l_in != 0 )
|
||||
{
|
||||
if ( k < 0 )
|
||||
{
|
||||
k = i;
|
||||
anchor = in;
|
||||
l_anchor = l_in;
|
||||
}
|
||||
|
||||
d = in.x * out.x + in.y * out.y;
|
||||
|
||||
/* shift only if turn is less than ~160 degrees */
|
||||
if ( d > -15.f/16.f )
|
||||
{
|
||||
d = d + 1.f;
|
||||
|
||||
/* shift components along lateral bisector in proper orientation */
|
||||
shift.x = in.y + out.y;
|
||||
shift.y = in.x + out.x;
|
||||
|
||||
if ( orientation_negative )
|
||||
shift.x = -shift.x;
|
||||
else
|
||||
shift.y = -shift.y;
|
||||
|
||||
/* restrict shift magnitude to better handle collapsing segments */
|
||||
q = out.x * in.y - out.y * in.x;
|
||||
if ( orientation_negative )
|
||||
q = -q;
|
||||
|
||||
l = hb_min (l_in, l_out);
|
||||
|
||||
/* non-strict inequalities avoid divide-by-zero when q == l == 0 */
|
||||
if (x_strength * q <= l * d)
|
||||
shift.x = shift.x * x_strength / d;
|
||||
else
|
||||
shift.x = shift.x * l / q;
|
||||
|
||||
|
||||
if (y_strength * q <= l * d)
|
||||
shift.y = shift.y * y_strength / d;
|
||||
else
|
||||
shift.y = shift.y * l / q;
|
||||
}
|
||||
else
|
||||
shift.x = shift.y = 0;
|
||||
|
||||
for ( ;
|
||||
i != j;
|
||||
i = i < last ? i + 1 : first )
|
||||
{
|
||||
points[i].x += x_shift + shift.x;
|
||||
points[i].y += y_shift + shift.y;
|
||||
}
|
||||
}
|
||||
else
|
||||
i = j;
|
||||
|
||||
in = out;
|
||||
l_in = l_out;
|
||||
}
|
||||
|
||||
first = last + 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
hb_outline_recording_pen_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
||||
void *data,
|
||||
hb_draw_state_t *st,
|
||||
float to_x, float to_y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_outline_t *c = (hb_outline_t *) data;
|
||||
|
||||
c->points.push (hb_outline_point_t {to_x, to_y, hb_outline_point_t::type_t::MOVE_TO});
|
||||
}
|
||||
|
||||
static void
|
||||
hb_outline_recording_pen_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
||||
void *data,
|
||||
hb_draw_state_t *st,
|
||||
float to_x, float to_y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_outline_t *c = (hb_outline_t *) data;
|
||||
|
||||
c->points.push (hb_outline_point_t {to_x, to_y, hb_outline_point_t::type_t::LINE_TO});
|
||||
}
|
||||
|
||||
static void
|
||||
hb_outline_recording_pen_quadratic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
||||
void *data,
|
||||
hb_draw_state_t *st,
|
||||
float control_x, float control_y,
|
||||
float to_x, float to_y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_outline_t *c = (hb_outline_t *) data;
|
||||
|
||||
c->points.push (hb_outline_point_t {control_x, control_y, hb_outline_point_t::type_t::QUADRATIC_TO});
|
||||
c->points.push (hb_outline_point_t {to_x, to_y, hb_outline_point_t::type_t::QUADRATIC_TO});
|
||||
}
|
||||
|
||||
static void
|
||||
hb_outline_recording_pen_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
||||
void *data,
|
||||
hb_draw_state_t *st,
|
||||
float control1_x, float control1_y,
|
||||
float control2_x, float control2_y,
|
||||
float to_x, float to_y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_outline_t *c = (hb_outline_t *) data;
|
||||
|
||||
c->points.push (hb_outline_point_t {control1_x, control1_y, hb_outline_point_t::type_t::CUBIC_TO});
|
||||
c->points.push (hb_outline_point_t {control2_x, control2_y, hb_outline_point_t::type_t::CUBIC_TO});
|
||||
c->points.push (hb_outline_point_t {to_x, to_y, hb_outline_point_t::type_t::CUBIC_TO});
|
||||
}
|
||||
|
||||
static void
|
||||
hb_outline_recording_pen_close_path (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
||||
void *data,
|
||||
hb_draw_state_t *st,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_outline_t *c = (hb_outline_t *) data;
|
||||
|
||||
c->contours.push (c->points.length);
|
||||
}
|
||||
|
||||
static inline void free_static_outline_recording_pen_funcs ();
|
||||
|
||||
static struct hb_outline_recording_pen_funcs_lazy_loader_t : hb_draw_funcs_lazy_loader_t<hb_outline_recording_pen_funcs_lazy_loader_t>
|
||||
{
|
||||
static hb_draw_funcs_t *create ()
|
||||
{
|
||||
hb_draw_funcs_t *funcs = hb_draw_funcs_create ();
|
||||
|
||||
hb_draw_funcs_set_move_to_func (funcs, hb_outline_recording_pen_move_to, nullptr, nullptr);
|
||||
hb_draw_funcs_set_line_to_func (funcs, hb_outline_recording_pen_line_to, nullptr, nullptr);
|
||||
hb_draw_funcs_set_quadratic_to_func (funcs, hb_outline_recording_pen_quadratic_to, nullptr, nullptr);
|
||||
hb_draw_funcs_set_cubic_to_func (funcs, hb_outline_recording_pen_cubic_to, nullptr, nullptr);
|
||||
hb_draw_funcs_set_close_path_func (funcs, hb_outline_recording_pen_close_path, nullptr, nullptr);
|
||||
|
||||
hb_draw_funcs_make_immutable (funcs);
|
||||
|
||||
hb_atexit (free_static_outline_recording_pen_funcs);
|
||||
|
||||
return funcs;
|
||||
}
|
||||
} static_outline_recording_pen_funcs;
|
||||
|
||||
static inline
|
||||
void free_static_outline_recording_pen_funcs ()
|
||||
{
|
||||
static_outline_recording_pen_funcs.free_instance ();
|
||||
}
|
||||
|
||||
hb_draw_funcs_t *
|
||||
hb_outline_recording_pen_get_funcs ()
|
||||
{
|
||||
return static_outline_recording_pen_funcs.get_unconst ();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -1,83 +0,0 @@
|
|||
/*
|
||||
* Copyright © 2023 Behdad Esfahbod
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*/
|
||||
|
||||
#ifndef HB_OUTLINE_HH
|
||||
#define HB_OUTLINE_HH
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#include "hb-draw.hh"
|
||||
|
||||
|
||||
struct hb_outline_point_t
|
||||
{
|
||||
enum class type_t
|
||||
{
|
||||
MOVE_TO,
|
||||
LINE_TO,
|
||||
QUADRATIC_TO,
|
||||
CUBIC_TO,
|
||||
};
|
||||
|
||||
hb_outline_point_t (float x, float y, type_t type) :
|
||||
x (x), y (y), type (type) {}
|
||||
|
||||
float x, y;
|
||||
type_t type;
|
||||
};
|
||||
|
||||
struct hb_outline_vector_t
|
||||
{
|
||||
float normalize_len ()
|
||||
{
|
||||
float len = hypotf (x, y);
|
||||
if (len)
|
||||
{
|
||||
x /= len;
|
||||
y /= len;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
float x, y;
|
||||
};
|
||||
|
||||
struct hb_outline_t
|
||||
{
|
||||
void reset () { points.shrink (0, false); contours.resize (0); }
|
||||
|
||||
HB_INTERNAL void replay (hb_draw_funcs_t *pen, void *pen_data) const;
|
||||
HB_INTERNAL float control_area () const;
|
||||
HB_INTERNAL void embolden (float x_strength, float y_strength,
|
||||
float x_shift, float y_shift);
|
||||
|
||||
hb_vector_t<hb_outline_point_t> points;
|
||||
hb_vector_t<unsigned> contours;
|
||||
};
|
||||
|
||||
HB_INTERNAL hb_draw_funcs_t *
|
||||
hb_outline_recording_pen_get_funcs ();
|
||||
|
||||
|
||||
#endif /* HB_OUTLINE_HH */
|
|
@ -216,7 +216,7 @@ HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS
|
|||
*
|
||||
* Returns value: (transfer full): the paint-functions structure
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
hb_paint_funcs_t *
|
||||
hb_paint_funcs_create ()
|
||||
|
@ -248,7 +248,7 @@ DEFINE_NULL_INSTANCE (hb_paint_funcs_t) =
|
|||
*
|
||||
* Return value: (transfer full): The empty paint-functions structure
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
hb_paint_funcs_t *
|
||||
hb_paint_funcs_get_empty ()
|
||||
|
@ -267,7 +267,7 @@ hb_paint_funcs_get_empty ()
|
|||
*
|
||||
* Return value: The paint-functions structure
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
hb_paint_funcs_t *
|
||||
hb_paint_funcs_reference (hb_paint_funcs_t *funcs)
|
||||
|
@ -284,7 +284,7 @@ hb_paint_funcs_reference (hb_paint_funcs_t *funcs)
|
|||
* When the reference count reaches zero, the structure
|
||||
* is destroyed, freeing all memory.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_paint_funcs_destroy (hb_paint_funcs_t *funcs)
|
||||
|
@ -316,7 +316,7 @@ hb_paint_funcs_destroy (hb_paint_funcs_t *funcs)
|
|||
*
|
||||
* Return value: `true` if success, `false` otherwise
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_paint_funcs_set_user_data (hb_paint_funcs_t *funcs,
|
||||
|
@ -338,7 +338,7 @@ hb_paint_funcs_set_user_data (hb_paint_funcs_t *funcs,
|
|||
*
|
||||
* Return value: (transfer none): A pointer to the user data
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
**/
|
||||
void *
|
||||
hb_paint_funcs_get_user_data (const hb_paint_funcs_t *funcs,
|
||||
|
@ -356,7 +356,7 @@ hb_paint_funcs_get_user_data (const hb_paint_funcs_t *funcs,
|
|||
* After this call, all attempts to set one of the callbacks
|
||||
* on @funcs will fail.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_paint_funcs_make_immutable (hb_paint_funcs_t *funcs)
|
||||
|
@ -375,7 +375,7 @@ hb_paint_funcs_make_immutable (hb_paint_funcs_t *funcs)
|
|||
*
|
||||
* Return value: `true` if @funcs is immutable, `false` otherwise
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
hb_bool_t
|
||||
hb_paint_funcs_is_immutable (hb_paint_funcs_t *funcs)
|
||||
|
@ -400,7 +400,7 @@ hb_paint_funcs_is_immutable (hb_paint_funcs_t *funcs)
|
|||
*
|
||||
* Return value: the total number of color stops in @color_line
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
unsigned int
|
||||
hb_color_line_get_color_stops (hb_color_line_t *color_line,
|
||||
|
@ -423,7 +423,7 @@ hb_color_line_get_color_stops (hb_color_line_t *color_line,
|
|||
*
|
||||
* Return value: the extend mode of @color_line
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
hb_paint_extend_t
|
||||
hb_color_line_get_extend (hb_color_line_t *color_line)
|
||||
|
@ -447,7 +447,7 @@ hb_color_line_get_extend (hb_color_line_t *color_line)
|
|||
*
|
||||
* Perform a "push-transform" paint operation.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_paint_push_transform (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
|
@ -465,7 +465,7 @@ hb_paint_push_transform (hb_paint_funcs_t *funcs, void *paint_data,
|
|||
*
|
||||
* Perform a "pop-transform" paint operation.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_paint_pop_transform (hb_paint_funcs_t *funcs, void *paint_data)
|
||||
|
@ -482,7 +482,7 @@ hb_paint_pop_transform (hb_paint_funcs_t *funcs, void *paint_data)
|
|||
*
|
||||
* Perform a "push-clip-glyph" paint operation.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_paint_push_clip_glyph (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
|
@ -503,7 +503,7 @@ hb_paint_push_clip_glyph (hb_paint_funcs_t *funcs, void *paint_data,
|
|||
*
|
||||
* Perform a "push-clip-rect" paint operation.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_paint_push_clip_rectangle (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
|
@ -519,7 +519,7 @@ hb_paint_push_clip_rectangle (hb_paint_funcs_t *funcs, void *paint_data,
|
|||
*
|
||||
* Perform a "pop-clip" paint operation.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_paint_pop_clip (hb_paint_funcs_t *funcs, void *paint_data)
|
||||
|
@ -536,7 +536,7 @@ hb_paint_pop_clip (hb_paint_funcs_t *funcs, void *paint_data)
|
|||
*
|
||||
* Perform a "color" paint operation.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_paint_color (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
|
@ -559,7 +559,7 @@ hb_paint_color (hb_paint_funcs_t *funcs, void *paint_data,
|
|||
*
|
||||
* Perform a "image" paint operation.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_paint_image (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
|
@ -587,7 +587,7 @@ hb_paint_image (hb_paint_funcs_t *funcs, void *paint_data,
|
|||
*
|
||||
* Perform a "linear-gradient" paint operation.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_paint_linear_gradient (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
|
@ -613,7 +613,7 @@ hb_paint_linear_gradient (hb_paint_funcs_t *funcs, void *paint_data,
|
|||
*
|
||||
* Perform a "radial-gradient" paint operation.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_paint_radial_gradient (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
|
@ -636,7 +636,7 @@ hb_paint_radial_gradient (hb_paint_funcs_t *funcs, void *paint_data,
|
|||
*
|
||||
* Perform a "sweep-gradient" paint operation.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_paint_sweep_gradient (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
|
@ -654,7 +654,7 @@ hb_paint_sweep_gradient (hb_paint_funcs_t *funcs, void *paint_data,
|
|||
*
|
||||
* Perform a "push-group" paint operation.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_paint_push_group (hb_paint_funcs_t *funcs, void *paint_data)
|
||||
|
@ -670,7 +670,7 @@ hb_paint_push_group (hb_paint_funcs_t *funcs, void *paint_data)
|
|||
*
|
||||
* Perform a "pop-group" paint operation.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
void
|
||||
hb_paint_pop_group (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
|
@ -690,7 +690,7 @@ hb_paint_pop_group (hb_paint_funcs_t *funcs, void *paint_data,
|
|||
*
|
||||
* Return value: `true` if found, `false` otherwise
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* Since: REPLACEME
|
||||
*/
|
||||
hb_bool_t
|
||||
hb_paint_custom_palette_color (hb_paint_funcs_t *funcs, void *paint_data,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue