Compare commits
95 Commits
Author | SHA1 | Date |
---|---|---|
Behdad Esfahbod | d1c00c0470 | |
Behdad Esfahbod | 4129061e37 | |
Behdad Esfahbod | e76a3649db | |
Behdad Esfahbod | 8e43e3a8ce | |
Behdad Esfahbod | 48f8ed7e02 | |
Behdad Esfahbod | b31684dca4 | |
Behdad Esfahbod | bffdca89f7 | |
Behdad Esfahbod | a960571f24 | |
Behdad Esfahbod | 2b042cc5c6 | |
Qunxin Liu | 591c9460dc | |
Behdad Esfahbod | 3520f528aa | |
Behdad Esfahbod | 33972b3bf6 | |
Behdad Esfahbod | 290cef39be | |
Behdad Esfahbod | 4353192d05 | |
Behdad Esfahbod | 305012609b | |
Behdad Esfahbod | f74abc307d | |
Behdad Esfahbod | d1f49ba6d2 | |
Behdad Esfahbod | 1e9a0511f3 | |
Behdad Esfahbod | 106a237e40 | |
Behdad Esfahbod | f2d21425a3 | |
Behdad Esfahbod | 15d0a1dcfd | |
Behdad Esfahbod | 85d0c3b5f1 | |
Behdad Esfahbod | 5d74b42b9e | |
Behdad Esfahbod | c997e490c7 | |
Behdad Esfahbod | 781da13e99 | |
Behdad Esfahbod | 0e4bcf908c | |
Behdad Esfahbod | 639f45ef9e | |
Behdad Esfahbod | b3da715b9c | |
Behdad Esfahbod | 32f145ff9c | |
Behdad Esfahbod | 000a3c5dca | |
Behdad Esfahbod | 1111c7578e | |
Behdad Esfahbod | 219e739c9f | |
Behdad Esfahbod | a2e8ecf996 | |
Behdad Esfahbod | 317e3693da | |
Behdad Esfahbod | 64ecf8720c | |
Behdad Esfahbod | 7f629c0df2 | |
Garret Rieger | 19e1b698c5 | |
Garret Rieger | 647b024784 | |
Garret Rieger | 3db6baa20e | |
Garret Rieger | 8658c257c4 | |
Josef Friedrich | ac4c3b3e85 | |
DeadSix27 | ef6adadba9 | |
Garret Rieger | 90356eb226 | |
Garret Rieger | 14b9d8d534 | |
Behdad Esfahbod | 9c258936e7 | |
Pedro Kaj Kjellerup Nacht | feb1f6d39e | |
Pedro Kaj Kjellerup Nacht | 26c719e8cd | |
Qunxin Liu | 96ed20725c | |
Behdad Esfahbod | 04a47932a3 | |
Garret Rieger | 2cd81fdfb6 | |
Behdad Esfahbod | 453ded0539 | |
Qunxin Liu | c1acfe9966 | |
Garret Rieger | be87200106 | |
Garret Rieger | 79ae6b657f | |
Qunxin Liu | ab87d7d225 | |
Qunxin Liu | fe671a5ac8 | |
Garret Rieger | f0f7f22525 | |
Garret Rieger | 79233a1492 | |
Garret Rieger | 8d8bcde8cf | |
Garret Rieger | a84cae424d | |
Behdad Esfahbod | 09a2662361 | |
Behdad Esfahbod | 75e6498d9a | |
Qunxin Liu | 204e155acb | |
Jason Simmons | 32c889f1d6 | |
Qunxin Liu | 0d65738633 | |
Qunxin Liu | 125450d2f2 | |
Garret Rieger | 663ecc01d8 | |
Garret Rieger | 3d05b96181 | |
Garret Rieger | 7a87b17742 | |
Qunxin Liu | de6533d885 | |
Qunxin Liu | 7b77cd198c | |
Behdad Esfahbod | 6d2705a719 | |
Simon Cozens | 2d8634624c | |
Jean-Michaël Celerier | 905eeee4a4 | |
Garret Rieger | 28b05e1cb6 | |
Garret Rieger | 9286e12525 | |
Behdad Esfahbod | cfa9541daa | |
Behdad Esfahbod | 552290f604 | |
Behdad Esfahbod | 7327006d68 | |
Behdad Esfahbod | 69183217df | |
Behdad Esfahbod | ea17c7a81a | |
Behdad Esfahbod | f325aba561 | |
Khaled Hosny | b4b089c427 | |
Behdad Esfahbod | d165afec1d | |
Khaled Hosny | 690145fa00 | |
Behdad Esfahbod | e9d6f23b5d | |
Behdad Esfahbod | 5cf54aedde | |
Behdad Esfahbod | 5c334b9686 | |
Behdad Esfahbod | ab249fd24b | |
Khaled Hosny | 039ea9adda | |
Behdad Esfahbod | be47182d48 | |
Behdad Esfahbod | ab4c321180 | |
Khaled Hosny | e57defc07c | |
Behdad Esfahbod | a2efa5b489 | |
Khaled Hosny | bfab56d3b5 |
|
@ -1,5 +1,9 @@
|
||||||
name: CIFuzz
|
name: CIFuzz
|
||||||
on: [pull_request]
|
on: [pull_request]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
Fuzzing:
|
Fuzzing:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
|
@ -49,6 +49,7 @@ jobs:
|
||||||
-Dgraphite=enabled \
|
-Dgraphite=enabled \
|
||||||
-Doptimization=2 \
|
-Doptimization=2 \
|
||||||
-Db_coverage=true \
|
-Db_coverage=true \
|
||||||
|
-Ddoc_tests=true \
|
||||||
-Dragel_subproject=true
|
-Dragel_subproject=true
|
||||||
- name: Build
|
- name: Build
|
||||||
run: meson compile -Cbuild
|
run: meson compile -Cbuild
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
# 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.
|
|
@ -60,5 +60,5 @@ gnome.gtkdoc('harfbuzz',
|
||||||
ignore_headers: ignore_headers,
|
ignore_headers: ignore_headers,
|
||||||
dependencies: [libharfbuzz_dep],
|
dependencies: [libharfbuzz_dep],
|
||||||
install: true,
|
install: true,
|
||||||
check: true,
|
check: get_option('doc_tests'),
|
||||||
)
|
)
|
||||||
|
|
|
@ -174,7 +174,9 @@
|
||||||
<para>
|
<para>
|
||||||
HarfBuzz provides integration points with FreeType at the
|
HarfBuzz provides integration points with FreeType at the
|
||||||
face-object and font-object level and for the font-functions
|
face-object and font-object level and for the font-functions
|
||||||
virtual-method structure of a font object. To use the
|
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
|
||||||
FreeType-integration API, include the
|
FreeType-integration API, include the
|
||||||
<filename>hb-ft.h</filename> header.
|
<filename>hb-ft.h</filename> header.
|
||||||
</para>
|
</para>
|
||||||
|
|
|
@ -373,7 +373,10 @@ foreach check : check_funcs
|
||||||
endforeach
|
endforeach
|
||||||
|
|
||||||
subdir('src')
|
subdir('src')
|
||||||
subdir('util')
|
|
||||||
|
if not get_option('utilities').disabled()
|
||||||
|
subdir('util')
|
||||||
|
endif
|
||||||
|
|
||||||
if not get_option('tests').disabled()
|
if not get_option('tests').disabled()
|
||||||
subdir('test')
|
subdir('test')
|
||||||
|
|
|
@ -29,6 +29,10 @@ option('introspection', type: 'feature', value: 'auto', yield: true,
|
||||||
description: 'Generate gobject-introspection bindings (.gir/.typelib files)')
|
description: 'Generate gobject-introspection bindings (.gir/.typelib files)')
|
||||||
option('docs', type: 'feature', value: 'auto', yield: true,
|
option('docs', type: 'feature', value: 'auto', yield: true,
|
||||||
description: 'Generate documentation with gtk-doc')
|
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',
|
option('benchmark', type: 'feature', value: 'disabled',
|
||||||
description: 'Enable benchmark tests')
|
description: 'Enable benchmark tests')
|
||||||
|
|
|
@ -382,6 +382,7 @@ noinst_PROGRAMS = \
|
||||||
test-ot-name \
|
test-ot-name \
|
||||||
test-ot-glyphname \
|
test-ot-glyphname \
|
||||||
test-gpos-size-params \
|
test-gpos-size-params \
|
||||||
|
test-gsub-get-alternates \
|
||||||
test-gsub-would-substitute \
|
test-gsub-would-substitute \
|
||||||
test-use-table \
|
test-use-table \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
@ -419,6 +420,10 @@ test_gpos_size_params_SOURCES = test-gpos-size-params.cc
|
||||||
test_gpos_size_params_CPPFLAGS = $(HBCFLAGS)
|
test_gpos_size_params_CPPFLAGS = $(HBCFLAGS)
|
||||||
test_gpos_size_params_LDADD = libharfbuzz.la $(HBLIBS)
|
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_SOURCES = test-gsub-would-substitute.cc
|
||||||
test_gsub_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
|
test_gsub_would_substitute_CPPFLAGS = $(HBCFLAGS) $(FREETYPE_CFLAGS)
|
||||||
test_gsub_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
|
test_gsub_would_substitute_LDADD = libharfbuzz.la $(HBLIBS) $(FREETYPE_LIBS)
|
||||||
|
|
|
@ -40,7 +40,6 @@
|
||||||
*/
|
*/
|
||||||
#define HB_OT_TAG_COLR HB_TAG('C','O','L','R')
|
#define HB_OT_TAG_COLR HB_TAG('C','O','L','R')
|
||||||
|
|
||||||
|
|
||||||
namespace OT {
|
namespace OT {
|
||||||
struct hb_paint_context_t;
|
struct hb_paint_context_t;
|
||||||
}
|
}
|
||||||
|
@ -242,10 +241,15 @@ struct Variable
|
||||||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||||
{ value.closurev1 (c); }
|
{ value.closurev1 (c); }
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
if (!value.subset (c)) return_trace (false);
|
if (!value.subset (c, instancer, varIdxBase)) return_trace (false);
|
||||||
|
if (c->plan->all_axes_pinned)
|
||||||
|
return_trace (true);
|
||||||
|
|
||||||
|
//TODO: update varIdxBase for partial-instancing
|
||||||
return_trace (c->serializer->embed (varIdxBase));
|
return_trace (c->serializer->embed (varIdxBase));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,10 +300,11 @@ struct NoVariable
|
||||||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||||
{ value.closurev1 (c); }
|
{ value.closurev1 (c); }
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
return_trace (value.subset (c));
|
return_trace (value.subset (c, instancer, varIdxBase));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
@ -337,11 +342,20 @@ struct ColorStop
|
||||||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||||
{ c->add_palette_index (paletteIndex); }
|
{ c->add_palette_index (paletteIndex); }
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer,
|
||||||
|
uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (*this);
|
auto *out = c->serializer->embed (*this);
|
||||||
if (unlikely (!out)) return_trace (false);
|
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),
|
return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes.get (paletteIndex),
|
||||||
HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||||
}
|
}
|
||||||
|
@ -390,7 +404,8 @@ struct ColorLine
|
||||||
stop.closurev1 (c);
|
stop.closurev1 (c);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->start_embed (this);
|
auto *out = c->serializer->start_embed (this);
|
||||||
|
@ -402,7 +417,7 @@ struct ColorLine
|
||||||
|
|
||||||
for (const auto& stop : stops.iter ())
|
for (const auto& stop : stops.iter ())
|
||||||
{
|
{
|
||||||
if (!stop.subset (c)) return_trace (false);
|
if (!stop.subset (c, instancer)) return_trace (false);
|
||||||
}
|
}
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
}
|
}
|
||||||
|
@ -523,6 +538,25 @@ struct Affine2x3
|
||||||
return_trace (c->check_struct (this));
|
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
|
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
c->funcs->push_transform (c->data,
|
c->funcs->push_transform (c->data,
|
||||||
|
@ -548,7 +582,8 @@ struct PaintColrLayers
|
||||||
{
|
{
|
||||||
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer HB_UNUSED) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
|
@ -579,11 +614,20 @@ struct PaintSolid
|
||||||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||||
{ c->add_palette_index (paletteIndex); }
|
{ c->add_palette_index (paletteIndex); }
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer,
|
||||||
|
uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (*this);
|
auto *out = c->serializer->embed (*this);
|
||||||
if (unlikely (!out)) return_trace (false);
|
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),
|
return_trace (c->serializer->check_assign (out->paletteIndex, c->plan->colr_palettes.get (paletteIndex),
|
||||||
HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||||
}
|
}
|
||||||
|
@ -618,13 +662,28 @@ struct PaintLinearGradient
|
||||||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||||
{ (this+colorLine).closurev1 (c); }
|
{ (this+colorLine).closurev1 (c); }
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer,
|
||||||
|
uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
if (unlikely (!out)) return_trace (false);
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
return_trace (out->colorLine.serialize_subset (c, colorLine, this));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
@ -669,13 +728,28 @@ struct PaintRadialGradient
|
||||||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||||
{ (this+colorLine).closurev1 (c); }
|
{ (this+colorLine).closurev1 (c); }
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer,
|
||||||
|
uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
if (unlikely (!out)) return_trace (false);
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
return_trace (out->colorLine.serialize_subset (c, colorLine, this));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
@ -720,13 +794,26 @@ struct PaintSweepGradient
|
||||||
void closurev1 (hb_colrv1_closure_context_t* c) const
|
void closurev1 (hb_colrv1_closure_context_t* c) const
|
||||||
{ (this+colorLine).closurev1 (c); }
|
{ (this+colorLine).closurev1 (c); }
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer,
|
||||||
|
uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
if (unlikely (!out)) return_trace (false);
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
return_trace (out->colorLine.serialize_subset (c, colorLine, this));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
@ -746,8 +833,8 @@ struct PaintSweepGradient
|
||||||
c->funcs->sweep_gradient (c->data, &cl,
|
c->funcs->sweep_gradient (c->data, &cl,
|
||||||
centerX + c->instancer (varIdxBase, 0),
|
centerX + c->instancer (varIdxBase, 0),
|
||||||
centerY + c->instancer (varIdxBase, 1),
|
centerY + c->instancer (varIdxBase, 1),
|
||||||
(startAngle.to_float (c->instancer (varIdxBase, 2)) + 1) * (float) M_PI,
|
(startAngle.to_float (c->instancer (varIdxBase, 2)) + 1) * HB_PI,
|
||||||
(endAngle.to_float (c->instancer (varIdxBase, 3)) + 1) * (float) M_PI);
|
(endAngle.to_float (c->instancer (varIdxBase, 3)) + 1) * HB_PI);
|
||||||
}
|
}
|
||||||
|
|
||||||
HBUINT8 format; /* format = 8(noVar) or 9 (Var) */
|
HBUINT8 format; /* format = 8(noVar) or 9 (Var) */
|
||||||
|
@ -766,7 +853,8 @@ struct PaintGlyph
|
||||||
{
|
{
|
||||||
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
|
@ -776,7 +864,7 @@ struct PaintGlyph
|
||||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
|
|
||||||
return_trace (out->paint.serialize_subset (c, paint, this));
|
return_trace (out->paint.serialize_subset (c, paint, this, instancer));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
@ -807,7 +895,8 @@ struct PaintColrGlyph
|
||||||
{
|
{
|
||||||
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer HB_UNUSED) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
|
@ -836,13 +925,16 @@ struct PaintTransform
|
||||||
{
|
{
|
||||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
if (unlikely (!out)) return_trace (false);
|
if (unlikely (!out)) return_trace (false);
|
||||||
if (!out->transform.serialize_copy (c->serializer, transform, this)) return_trace (false);
|
if (!out->transform.serialize_subset (c, transform, this, instancer)) return_trace (false);
|
||||||
return_trace (out->src.serialize_subset (c, src, this));
|
if (format == 13 && c->plan->all_axes_pinned)
|
||||||
|
out->format = 12;
|
||||||
|
return_trace (out->src.serialize_subset (c, src, this, instancer));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
@ -871,13 +963,24 @@ struct PaintTranslate
|
||||||
{
|
{
|
||||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer,
|
||||||
|
uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
if (unlikely (!out)) return_trace (false);
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
return_trace (out->src.serialize_subset (c, src, this));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
@ -908,13 +1011,24 @@ struct PaintScale
|
||||||
{
|
{
|
||||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer,
|
||||||
|
uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
if (unlikely (!out)) return_trace (false);
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
return_trace (out->src.serialize_subset (c, src, this));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
@ -945,13 +1059,26 @@ struct PaintScaleAroundCenter
|
||||||
{
|
{
|
||||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer,
|
||||||
|
uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
if (unlikely (!out)) return_trace (false);
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
return_trace (out->src.serialize_subset (c, src, this));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
@ -990,13 +1117,21 @@ struct PaintScaleUniform
|
||||||
{
|
{
|
||||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer,
|
||||||
|
uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
if (unlikely (!out)) return_trace (false);
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
return_trace (out->src.serialize_subset (c, src, this));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
@ -1025,13 +1160,25 @@ struct PaintScaleUniformAroundCenter
|
||||||
{
|
{
|
||||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer,
|
||||||
|
uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
if (unlikely (!out)) return_trace (false);
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
return_trace (out->src.serialize_subset (c, src, this));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
@ -1068,13 +1215,21 @@ struct PaintRotate
|
||||||
{
|
{
|
||||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer,
|
||||||
|
uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
if (unlikely (!out)) return_trace (false);
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
return_trace (out->src.serialize_subset (c, src, this));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
@ -1103,13 +1258,25 @@ struct PaintRotateAroundCenter
|
||||||
{
|
{
|
||||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer,
|
||||||
|
uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
if (unlikely (!out)) return_trace (false);
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
return_trace (out->src.serialize_subset (c, src, this));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
@ -1146,13 +1313,24 @@ struct PaintSkew
|
||||||
{
|
{
|
||||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer,
|
||||||
|
uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
if (unlikely (!out)) return_trace (false);
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
return_trace (out->src.serialize_subset (c, src, this));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
@ -1183,13 +1361,26 @@ struct PaintSkewAroundCenter
|
||||||
{
|
{
|
||||||
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
HB_INTERNAL void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer,
|
||||||
|
uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
if (unlikely (!out)) return_trace (false);
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
return_trace (out->src.serialize_subset (c, src, this));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
@ -1228,14 +1419,15 @@ struct PaintComposite
|
||||||
{
|
{
|
||||||
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
void closurev1 (hb_colrv1_closure_context_t* c) const;
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
if (unlikely (!out)) return_trace (false);
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
if (!out->src.serialize_subset (c, src, this)) return_trace (false);
|
if (!out->src.serialize_subset (c, src, this, instancer)) return_trace (false);
|
||||||
return_trace (out->backdrop.serialize_subset (c, backdrop, this));
|
return_trace (out->backdrop.serialize_subset (c, backdrop, this, instancer));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
|
@ -1283,6 +1475,28 @@ struct ClipBoxFormat1
|
||||||
clip_box.yMax = yMax;
|
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:
|
public:
|
||||||
HBUINT8 format; /* format = 1(noVar) or 2(Var)*/
|
HBUINT8 format; /* format = 1(noVar) or 2(Var)*/
|
||||||
FWORD xMin;
|
FWORD xMin;
|
||||||
|
@ -1310,13 +1524,14 @@ struct ClipBoxFormat2 : Variable<ClipBoxFormat1>
|
||||||
|
|
||||||
struct ClipBox
|
struct ClipBox
|
||||||
{
|
{
|
||||||
ClipBox* copy (hb_serialize_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer) const
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SUBSET (this);
|
||||||
switch (u.format) {
|
switch (u.format) {
|
||||||
case 1: return_trace (reinterpret_cast<ClipBox *> (c->embed (u.format1)));
|
case 1: return_trace (u.format1.subset (c, instancer, VarIdx::NO_VARIATION));
|
||||||
case 2: return_trace (reinterpret_cast<ClipBox *> (c->embed (u.format2)));
|
case 2: return_trace (u.format2.subset (c, instancer));
|
||||||
default:return_trace (nullptr);
|
default:return_trace (c->default_return_value ());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1367,13 +1582,15 @@ struct ClipRecord
|
||||||
int cmp (hb_codepoint_t g) const
|
int cmp (hb_codepoint_t g) const
|
||||||
{ return g < startGlyphID ? -1 : g <= endGlyphID ? 0 : +1; }
|
{ return g < startGlyphID ? -1 : g <= endGlyphID ? 0 : +1; }
|
||||||
|
|
||||||
ClipRecord* copy (hb_serialize_context_t *c, const void *base) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const void *base,
|
||||||
|
const VarStoreInstancer &instancer) const
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->embed (this);
|
auto *out = c->serializer->embed (*this);
|
||||||
if (unlikely (!out)) return_trace (nullptr);
|
if (unlikely (!out)) return_trace (false);
|
||||||
if (!out->clipBox.serialize_copy (c, clipBox, base)) return_trace (nullptr);
|
|
||||||
return_trace (out);
|
return_trace (out->clipBox.serialize_subset (c, clipBox, base, instancer));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||||
|
@ -1400,7 +1617,8 @@ DECLARE_NULL_NAMESPACE_BYTES (OT, ClipRecord);
|
||||||
|
|
||||||
struct ClipList
|
struct ClipList
|
||||||
{
|
{
|
||||||
unsigned serialize_clip_records (hb_serialize_context_t *c,
|
unsigned serialize_clip_records (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer,
|
||||||
const hb_set_t& gids,
|
const hb_set_t& gids,
|
||||||
const hb_map_t& gid_offset_map) const
|
const hb_map_t& gid_offset_map) const
|
||||||
{
|
{
|
||||||
|
@ -1432,7 +1650,7 @@ struct ClipList
|
||||||
record.endGlyphID = prev_gid;
|
record.endGlyphID = prev_gid;
|
||||||
record.clipBox = prev_offset;
|
record.clipBox = prev_offset;
|
||||||
|
|
||||||
if (!c->copy (record, this)) return_trace (0);
|
if (!record.subset (c, this, instancer)) return_trace (0);
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
start_gid = _;
|
start_gid = _;
|
||||||
|
@ -1446,13 +1664,14 @@ struct ClipList
|
||||||
record.startGlyphID = start_gid;
|
record.startGlyphID = start_gid;
|
||||||
record.endGlyphID = prev_gid;
|
record.endGlyphID = prev_gid;
|
||||||
record.clipBox = prev_offset;
|
record.clipBox = prev_offset;
|
||||||
if (!c->copy (record, this)) return_trace (0);
|
if (!record.subset (c, this, instancer)) return_trace (0);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
return_trace (count);
|
return_trace (count);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->start_embed (*this);
|
auto *out = c->serializer->start_embed (*this);
|
||||||
|
@ -1477,7 +1696,7 @@ struct ClipList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned count = serialize_clip_records (c->serializer, new_gids, new_gid_offset_map);
|
unsigned count = serialize_clip_records (c, instancer, new_gids, new_gid_offset_map);
|
||||||
if (!count) return_trace (false);
|
if (!count) return_trace (false);
|
||||||
return_trace (c->serializer->check_assign (out->clips.len, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
return_trace (c->serializer->check_assign (out->clips.len, count, HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||||
}
|
}
|
||||||
|
@ -1611,7 +1830,8 @@ struct BaseGlyphPaintRecord
|
||||||
{ return g < glyphId ? -1 : g > glyphId ? 1 : 0; }
|
{ return g < glyphId ? -1 : g > glyphId ? 1 : 0; }
|
||||||
|
|
||||||
bool serialize (hb_serialize_context_t *s, const hb_map_t* glyph_map,
|
bool serialize (hb_serialize_context_t *s, const hb_map_t* glyph_map,
|
||||||
const void* src_base, hb_subset_context_t *c) const
|
const void* src_base, hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer) const
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
auto *out = s->embed (this);
|
auto *out = s->embed (this);
|
||||||
|
@ -1620,7 +1840,7 @@ struct BaseGlyphPaintRecord
|
||||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
|
|
||||||
return_trace (out->paint.serialize_subset (c, paint, src_base));
|
return_trace (out->paint.serialize_subset (c, paint, src_base, instancer));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||||
|
@ -1639,7 +1859,8 @@ struct BaseGlyphPaintRecord
|
||||||
|
|
||||||
struct BaseGlyphList : SortedArray32Of<BaseGlyphPaintRecord>
|
struct BaseGlyphList : SortedArray32Of<BaseGlyphPaintRecord>
|
||||||
{
|
{
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->start_embed (this);
|
auto *out = c->serializer->start_embed (this);
|
||||||
|
@ -1651,7 +1872,7 @@ struct BaseGlyphList : SortedArray32Of<BaseGlyphPaintRecord>
|
||||||
unsigned gid = _.glyphId;
|
unsigned gid = _.glyphId;
|
||||||
if (!glyphset->has (gid)) continue;
|
if (!glyphset->has (gid)) continue;
|
||||||
|
|
||||||
if (_.serialize (c->serializer, c->plan->glyph_map, this, c)) out->len++;
|
if (_.serialize (c->serializer, c->plan->glyph_map, this, c, instancer)) out->len++;
|
||||||
else return_trace (false);
|
else return_trace (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1670,7 +1891,8 @@ struct LayerList : Array32OfOffset32To<Paint>
|
||||||
const Paint& get_paint (unsigned i) const
|
const Paint& get_paint (unsigned i) const
|
||||||
{ return this+(*this)[i]; }
|
{ return this+(*this)[i]; }
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c,
|
||||||
|
const VarStoreInstancer &instancer) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->start_embed (this);
|
auto *out = c->serializer->start_embed (this);
|
||||||
|
@ -1681,7 +1903,7 @@ struct LayerList : Array32OfOffset32To<Paint>
|
||||||
|
|
||||||
{
|
{
|
||||||
auto *o = out->serialize_append (c->serializer);
|
auto *o = out->serialize_append (c->serializer);
|
||||||
if (unlikely (!o) || !o->serialize_subset (c, _.second, this))
|
if (unlikely (!o) || !o->serialize_subset (c, _.second, this, instancer))
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
}
|
}
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
|
@ -1883,7 +2105,6 @@ struct COLR
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
|
|
||||||
const hb_map_t &reverse_glyph_map = *c->plan->reverse_glyph_map;
|
const hb_map_t &reverse_glyph_map = *c->plan->reverse_glyph_map;
|
||||||
const hb_set_t& glyphset = c->plan->_glyphset_colred;
|
const hb_set_t& glyphset = c->plan->_glyphset_colred;
|
||||||
|
|
||||||
|
@ -1954,7 +2175,12 @@ struct COLR
|
||||||
|
|
||||||
auto snap = c->serializer->snapshot ();
|
auto snap = c->serializer->snapshot ();
|
||||||
if (!c->serializer->allocate_size<void> (5 * HBUINT32::static_size)) return_trace (false);
|
if (!c->serializer->allocate_size<void> (5 * HBUINT32::static_size)) return_trace (false);
|
||||||
if (!colr_prime->baseGlyphList.serialize_subset (c, baseGlyphList, this))
|
|
||||||
|
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 (c->serializer->in_error ()) return_trace (false);
|
if (c->serializer->in_error ()) return_trace (false);
|
||||||
//no more COLRv1 glyphs: downgrade to version 0
|
//no more COLRv1 glyphs: downgrade to version 0
|
||||||
|
@ -1964,8 +2190,11 @@ struct COLR
|
||||||
|
|
||||||
if (!colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it)) return_trace (false);
|
if (!colr_prime->serialize_V0 (c->serializer, version, base_it, layer_it)) return_trace (false);
|
||||||
|
|
||||||
colr_prime->layerList.serialize_subset (c, layerList, this);
|
colr_prime->layerList.serialize_subset (c, layerList, this, instancer);
|
||||||
colr_prime->clipList.serialize_subset (c, clipList, this);
|
colr_prime->clipList.serialize_subset (c, clipList, this, instancer);
|
||||||
|
if (!varStore || c->plan->all_axes_pinned)
|
||||||
|
return_trace (true);
|
||||||
|
|
||||||
colr_prime->varIdxMap.serialize_copy (c->serializer, varIdxMap, this);
|
colr_prime->varIdxMap.serialize_copy (c->serializer, varIdxMap, this);
|
||||||
colr_prime->varStore.serialize_copy (c->serializer, varStore, this);
|
colr_prime->varStore.serialize_copy (c->serializer, varStore, this);
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
|
@ -1984,14 +2213,15 @@ struct COLR
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HB_NO_PAINT
|
||||||
bool
|
bool
|
||||||
get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
|
get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
|
||||||
{
|
{
|
||||||
if (version != 1)
|
if (version != 1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
VarStoreInstancer instancer (this+varStore,
|
VarStoreInstancer instancer (&(this+varStore),
|
||||||
this+varIdxMap,
|
&(this+varIdxMap),
|
||||||
hb_array (font->coords, font->num_coords));
|
hb_array (font->coords, font->num_coords));
|
||||||
|
|
||||||
if (get_clip (glyph, extents, instancer))
|
if (get_clip (glyph, extents, instancer))
|
||||||
|
@ -2022,6 +2252,7 @@ struct COLR
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
bool
|
bool
|
||||||
has_paint_for_glyph (hb_codepoint_t glyph) const
|
has_paint_for_glyph (hb_codepoint_t glyph) const
|
||||||
|
@ -2045,11 +2276,12 @@ struct COLR
|
||||||
instancer);
|
instancer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HB_NO_PAINT
|
||||||
bool
|
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
|
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,
|
VarStoreInstancer instancer (&(this+varStore),
|
||||||
this+varIdxMap,
|
&(this+varIdxMap),
|
||||||
hb_array (font->coords, font->num_coords));
|
hb_array (font->coords, font->num_coords));
|
||||||
hb_paint_context_t c (this, funcs, data, font, palette_index, foreground, instancer);
|
hb_paint_context_t c (this, funcs, data, font, palette_index, foreground, instancer);
|
||||||
|
|
||||||
|
@ -2060,8 +2292,8 @@ struct COLR
|
||||||
{
|
{
|
||||||
// COLRv1 glyph
|
// COLRv1 glyph
|
||||||
|
|
||||||
VarStoreInstancer instancer (this+varStore,
|
VarStoreInstancer instancer (&(this+varStore),
|
||||||
this+varIdxMap,
|
&(this+varIdxMap),
|
||||||
hb_array (font->coords, font->num_coords));
|
hb_array (font->coords, font->num_coords));
|
||||||
|
|
||||||
bool is_bounded = true;
|
bool is_bounded = true;
|
||||||
|
@ -2131,6 +2363,7 @@ struct COLR
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
HBUINT16 version; /* Table version number (starts at 0). */
|
HBUINT16 version; /* Table version number (starts at 0). */
|
||||||
|
|
|
@ -73,6 +73,30 @@ struct CPALV1Tail
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
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,
|
bool serialize (hb_serialize_context_t *c,
|
||||||
unsigned palette_count,
|
unsigned palette_count,
|
||||||
unsigned color_count,
|
unsigned color_count,
|
||||||
|
@ -95,13 +119,10 @@ struct CPALV1Tail
|
||||||
if (colorLabelsZ)
|
if (colorLabelsZ)
|
||||||
{
|
{
|
||||||
c->push ();
|
c->push ();
|
||||||
for (const auto _ : colorLabels)
|
for (unsigned i = 0; i < color_count; i++)
|
||||||
{
|
{
|
||||||
const hb_codepoint_t *v;
|
if (!color_index_map->has (i)) continue;
|
||||||
if (!color_index_map->has (_, &v)) continue;
|
if (!c->copy<NameID> (colorLabels[i]))
|
||||||
NameID new_color_idx;
|
|
||||||
new_color_idx = *v;
|
|
||||||
if (!c->copy<NameID> (new_color_idx))
|
|
||||||
{
|
{
|
||||||
c->pop_discard ();
|
c->pop_discard ();
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
|
@ -189,6 +210,13 @@ struct CPAL
|
||||||
return numColors;
|
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:
|
private:
|
||||||
const CPALV1Tail& v1 () const
|
const CPALV1Tail& v1 () const
|
||||||
{
|
{
|
||||||
|
|
|
@ -55,7 +55,7 @@ struct PairPosFormat1_3
|
||||||
|
|
||||||
if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len) / 4)
|
if (pairSet.len > glyphs->get_population () * hb_bit_storage ((unsigned) pairSet.len) / 4)
|
||||||
{
|
{
|
||||||
for (hb_codepoint_t g = HB_SET_VALUE_INVALID; glyphs->next (&g);)
|
for (hb_codepoint_t g : glyphs->iter())
|
||||||
{
|
{
|
||||||
unsigned i = cov.get_coverage (g);
|
unsigned i = cov.get_coverage (g);
|
||||||
if ((this+pairSet[i]).intersects (glyphs, valueFormat))
|
if ((this+pairSet[i]).intersects (glyphs, valueFormat))
|
||||||
|
|
|
@ -29,6 +29,9 @@ struct Ligature
|
||||||
bool intersects (const hb_set_t *glyphs) const
|
bool intersects (const hb_set_t *glyphs) const
|
||||||
{ return hb_all (component, glyphs); }
|
{ 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
|
void closure (hb_closure_context_t *c) const
|
||||||
{
|
{
|
||||||
if (!intersects (c->glyphs)) return;
|
if (!intersects (c->glyphs)) return;
|
||||||
|
|
|
@ -34,6 +34,18 @@ 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
|
void closure (hb_closure_context_t *c) const
|
||||||
{
|
{
|
||||||
+ hb_iter (ligature)
|
+ hb_iter (ligature)
|
||||||
|
|
|
@ -130,7 +130,7 @@ struct LigatureSubstFormat1_2
|
||||||
+ hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this)))
|
+ hb_zip (this+coverage, hb_iter (ligatureSet) | hb_map (hb_add (this)))
|
||||||
| hb_filter (glyphset, hb_first)
|
| hb_filter (glyphset, hb_first)
|
||||||
| hb_filter ([&] (const LigatureSet<Types>& _) {
|
| hb_filter ([&] (const LigatureSet<Types>& _) {
|
||||||
return _.intersects (&glyphset);
|
return _.intersects_lig_glyph (&glyphset);
|
||||||
}, hb_second)
|
}, hb_second)
|
||||||
| hb_map (hb_first)
|
| hb_map (hb_first)
|
||||||
| hb_sink (new_coverage);
|
| hb_sink (new_coverage);
|
||||||
|
|
|
@ -95,6 +95,34 @@ struct SingleSubstFormat1_3
|
||||||
bool would_apply (hb_would_apply_context_t *c) const
|
bool would_apply (hb_would_apply_context_t *c) const
|
||||||
{ return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
|
{ 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
|
bool apply (hb_ot_apply_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_APPLY (this);
|
TRACE_APPLY (this);
|
||||||
|
|
|
@ -75,6 +75,31 @@ struct SingleSubstFormat2_4
|
||||||
bool would_apply (hb_would_apply_context_t *c) const
|
bool would_apply (hb_would_apply_context_t *c) const
|
||||||
{ return c->len == 1 && (this+coverage).get_coverage (c->glyphs[0]) != NOT_COVERED; }
|
{ 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
|
bool apply (hb_ot_apply_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_APPLY (this);
|
TRACE_APPLY (this);
|
||||||
|
|
|
@ -87,27 +87,34 @@ struct CompositeGlyphRecord
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void transform_points (contour_point_vector_t &points) const
|
void transform_points (contour_point_vector_t &points,
|
||||||
|
const float (&matrix)[4],
|
||||||
|
const contour_point_t &trans) const
|
||||||
{
|
{
|
||||||
float matrix[4];
|
if (scaled_offsets ())
|
||||||
contour_point_t trans;
|
|
||||||
if (get_transformation (matrix, trans))
|
|
||||||
{
|
{
|
||||||
if (scaled_offsets ())
|
points.translate (trans);
|
||||||
{
|
points.transform (matrix);
|
||||||
points.translate (trans);
|
}
|
||||||
points.transform (matrix);
|
else
|
||||||
}
|
{
|
||||||
else
|
points.transform (matrix);
|
||||||
{
|
points.translate (trans);
|
||||||
points.transform (matrix);
|
|
||||||
points.translate (trans);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned compile_with_deltas (const contour_point_t &p_delta,
|
bool get_points (contour_point_vector_t &points) const
|
||||||
char *out) 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned compile_with_point (const contour_point_t &point,
|
||||||
|
char *out) const
|
||||||
{
|
{
|
||||||
const HBINT8 *p = &StructAfter<const HBINT8> (flags);
|
const HBINT8 *p = &StructAfter<const HBINT8> (flags);
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BEYOND_64K
|
||||||
|
@ -121,18 +128,17 @@ struct CompositeGlyphRecord
|
||||||
unsigned len_before_val = (const char *)p - (const char *)this;
|
unsigned len_before_val = (const char *)p - (const char *)this;
|
||||||
if (flags & ARG_1_AND_2_ARE_WORDS)
|
if (flags & ARG_1_AND_2_ARE_WORDS)
|
||||||
{
|
{
|
||||||
// no overflow, copy and update value with deltas
|
// no overflow, copy value
|
||||||
hb_memcpy (out, this, len);
|
hb_memcpy (out, this, len);
|
||||||
|
|
||||||
const HBINT16 *px = reinterpret_cast<const HBINT16 *> (p);
|
|
||||||
HBINT16 *o = reinterpret_cast<HBINT16 *> (out + len_before_val);
|
HBINT16 *o = reinterpret_cast<HBINT16 *> (out + len_before_val);
|
||||||
o[0] = px[0] + roundf (p_delta.x);
|
o[0] = roundf (point.x);
|
||||||
o[1] = px[1] + roundf (p_delta.y);
|
o[1] = roundf (point.y);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int new_x = p[0] + roundf (p_delta.x);
|
int new_x = roundf (point.x);
|
||||||
int new_y = p[1] + roundf (p_delta.y);
|
int new_y = roundf (point.y);
|
||||||
if (new_x <= 127 && new_x >= -128 &&
|
if (new_x <= 127 && new_x >= -128 &&
|
||||||
new_y <= 127 && new_y >= -128)
|
new_y <= 127 && new_y >= -128)
|
||||||
{
|
{
|
||||||
|
@ -143,7 +149,7 @@ struct CompositeGlyphRecord
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// int8 overflows after deltas applied
|
// new point value has an int8 overflow
|
||||||
hb_memcpy (out, this, len_before_val);
|
hb_memcpy (out, this, len_before_val);
|
||||||
|
|
||||||
//update flags
|
//update flags
|
||||||
|
@ -171,6 +177,7 @@ struct CompositeGlyphRecord
|
||||||
bool scaled_offsets () const
|
bool scaled_offsets () const
|
||||||
{ return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; }
|
{ return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; }
|
||||||
|
|
||||||
|
public:
|
||||||
bool get_transformation (float (&matrix)[4], contour_point_t &trans) const
|
bool get_transformation (float (&matrix)[4], contour_point_t &trans) const
|
||||||
{
|
{
|
||||||
matrix[0] = matrix[3] = 1.f;
|
matrix[0] = matrix[3] = 1.f;
|
||||||
|
@ -225,7 +232,6 @@ struct CompositeGlyphRecord
|
||||||
return tx || ty;
|
return tx || ty;
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
|
||||||
hb_codepoint_t get_gid () const
|
hb_codepoint_t get_gid () const
|
||||||
{
|
{
|
||||||
#ifndef HB_NO_BEYOND_64K
|
#ifndef HB_NO_BEYOND_64K
|
||||||
|
@ -246,6 +252,27 @@ struct CompositeGlyphRecord
|
||||||
StructAfter<HBGlyphID16> (flags) = gid;
|
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:
|
protected:
|
||||||
HBUINT16 flags;
|
HBUINT16 flags;
|
||||||
HBUINT24 pad;
|
HBUINT24 pad;
|
||||||
|
@ -304,7 +331,7 @@ struct CompositeGlyph
|
||||||
}
|
}
|
||||||
|
|
||||||
bool compile_bytes_with_deltas (const hb_bytes_t &source_bytes,
|
bool compile_bytes_with_deltas (const hb_bytes_t &source_bytes,
|
||||||
const contour_point_vector_t &deltas,
|
const contour_point_vector_t &points_with_deltas,
|
||||||
hb_bytes_t &dest_bytes /* OUT */)
|
hb_bytes_t &dest_bytes /* OUT */)
|
||||||
{
|
{
|
||||||
if (source_bytes.length <= GlyphHeader::static_size ||
|
if (source_bytes.length <= GlyphHeader::static_size ||
|
||||||
|
@ -319,7 +346,7 @@ struct CompositeGlyph
|
||||||
/* try to allocate more memories than source glyph bytes
|
/* try to allocate more memories than source glyph bytes
|
||||||
* in case that there might be an overflow for int8 value
|
* in case that there might be an overflow for int8 value
|
||||||
* and we would need to use int16 instead */
|
* and we would need to use int16 instead */
|
||||||
char *o = (char *) hb_calloc (source_len + source_len/2, sizeof (char));
|
char *o = (char *) hb_calloc (source_len * 2, sizeof (char));
|
||||||
if (unlikely (!o)) return false;
|
if (unlikely (!o)) return false;
|
||||||
|
|
||||||
const CompositeGlyphRecord *c = reinterpret_cast<const CompositeGlyphRecord *> (source_bytes.arrayZ + GlyphHeader::static_size);
|
const CompositeGlyphRecord *c = reinterpret_cast<const CompositeGlyphRecord *> (source_bytes.arrayZ + GlyphHeader::static_size);
|
||||||
|
@ -329,8 +356,11 @@ struct CompositeGlyph
|
||||||
unsigned i = 0, source_comp_len = 0;
|
unsigned i = 0, source_comp_len = 0;
|
||||||
for (const auto &component : it)
|
for (const auto &component : it)
|
||||||
{
|
{
|
||||||
/* last 4 points in deltas are phantom points and should not be included */
|
/* last 4 points in points_with_deltas are phantom points and should not be included */
|
||||||
if (i >= deltas.length - 4) return false;
|
if (i >= points_with_deltas.length - 4) {
|
||||||
|
free (o);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned comp_len = component.get_size ();
|
unsigned comp_len = component.get_size ();
|
||||||
if (component.is_anchored ())
|
if (component.is_anchored ())
|
||||||
|
@ -340,7 +370,7 @@ struct CompositeGlyph
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned new_len = component.compile_with_deltas (deltas[i], p);
|
unsigned new_len = component.compile_with_point (points_with_deltas[i], p);
|
||||||
p += new_len;
|
p += new_len;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
|
|
@ -29,7 +29,14 @@ enum phantom_point_index_t
|
||||||
|
|
||||||
struct Glyph
|
struct Glyph
|
||||||
{
|
{
|
||||||
enum glyph_type_t { EMPTY, SIMPLE, COMPOSITE, VAR_COMPOSITE };
|
enum glyph_type_t {
|
||||||
|
EMPTY,
|
||||||
|
SIMPLE,
|
||||||
|
COMPOSITE,
|
||||||
|
#ifndef HB_NO_VAR_COMPOSITES
|
||||||
|
VAR_COMPOSITE,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
composite_iter_t get_composite_iterator () const
|
composite_iter_t get_composite_iterator () const
|
||||||
|
@ -39,15 +46,23 @@ struct Glyph
|
||||||
}
|
}
|
||||||
var_composite_iter_t get_var_composite_iterator () const
|
var_composite_iter_t get_var_composite_iterator () const
|
||||||
{
|
{
|
||||||
|
#ifndef HB_NO_VAR_COMPOSITES
|
||||||
if (type != VAR_COMPOSITE) return var_composite_iter_t ();
|
if (type != VAR_COMPOSITE) return var_composite_iter_t ();
|
||||||
return VarCompositeGlyph (*header, bytes).iter ();
|
return VarCompositeGlyph (*header, bytes).iter ();
|
||||||
|
#else
|
||||||
|
return var_composite_iter_t ();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
const hb_bytes_t trim_padding () const
|
const hb_bytes_t trim_padding () const
|
||||||
{
|
{
|
||||||
switch (type) {
|
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 COMPOSITE: return CompositeGlyph (*header, bytes).trim_padding ();
|
||||||
case SIMPLE: return SimpleGlyph (*header, bytes).trim_padding ();
|
case SIMPLE: return SimpleGlyph (*header, bytes).trim_padding ();
|
||||||
|
case EMPTY: return bytes;
|
||||||
default: return bytes;
|
default: return bytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,27 +70,36 @@ struct Glyph
|
||||||
void drop_hints ()
|
void drop_hints ()
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
#ifndef HB_NO_VAR_COMPOSITES
|
||||||
|
case VAR_COMPOSITE: return; // No hinting
|
||||||
|
#endif
|
||||||
case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
|
case COMPOSITE: CompositeGlyph (*header, bytes).drop_hints (); return;
|
||||||
case SIMPLE: SimpleGlyph (*header, bytes).drop_hints (); return;
|
case SIMPLE: SimpleGlyph (*header, bytes).drop_hints (); return;
|
||||||
default: return;
|
case EMPTY: return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_overlaps_flag ()
|
void set_overlaps_flag ()
|
||||||
{
|
{
|
||||||
switch (type) {
|
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 COMPOSITE: CompositeGlyph (*header, bytes).set_overlaps_flag (); return;
|
||||||
case SIMPLE: SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
|
case SIMPLE: SimpleGlyph (*header, bytes).set_overlaps_flag (); return;
|
||||||
default: return;
|
case EMPTY: return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
|
void drop_hints_bytes (hb_bytes_t &dest_start, hb_bytes_t &dest_end) const
|
||||||
{
|
{
|
||||||
switch (type) {
|
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 COMPOSITE: CompositeGlyph (*header, bytes).drop_hints_bytes (dest_start); return;
|
||||||
case SIMPLE: SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return;
|
case SIMPLE: SimpleGlyph (*header, bytes).drop_hints_bytes (dest_start, dest_end); return;
|
||||||
default: return;
|
case EMPTY: return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +205,7 @@ struct Glyph
|
||||||
hb_bytes_t &dest_start, /* IN/OUT */
|
hb_bytes_t &dest_start, /* IN/OUT */
|
||||||
hb_bytes_t &dest_end /* OUT */)
|
hb_bytes_t &dest_end /* OUT */)
|
||||||
{
|
{
|
||||||
contour_point_vector_t all_points, deltas;
|
contour_point_vector_t all_points, points_with_deltas;
|
||||||
unsigned composite_contours = 0;
|
unsigned composite_contours = 0;
|
||||||
head_maxp_info_t *head_maxp_info_p = &plan->head_maxp_info;
|
head_maxp_info_t *head_maxp_info_p = &plan->head_maxp_info;
|
||||||
unsigned *composite_contours_p = &composite_contours;
|
unsigned *composite_contours_p = &composite_contours;
|
||||||
|
@ -195,7 +219,7 @@ struct Glyph
|
||||||
composite_contours_p = nullptr;
|
composite_contours_p = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!get_points (font, glyf, all_points, &deltas, head_maxp_info_p, composite_contours_p, false, false))
|
if (!get_points (font, glyf, all_points, &points_with_deltas, head_maxp_info_p, composite_contours_p, false, false))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// .notdef, set type to empty so we only update metrics and don't compile bytes for
|
// .notdef, set type to empty so we only update metrics and don't compile bytes for
|
||||||
|
@ -209,11 +233,20 @@ struct Glyph
|
||||||
}
|
}
|
||||||
|
|
||||||
//dont compile bytes when pinned at default, just recalculate bounds
|
//dont compile bytes when pinned at default, just recalculate bounds
|
||||||
if (!plan->pinned_at_default) {
|
if (!plan->pinned_at_default)
|
||||||
switch (type) {
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
#ifndef HB_NO_VAR_COMPOSITES
|
||||||
|
case VAR_COMPOSITE:
|
||||||
|
// TODO
|
||||||
|
dest_end = hb_bytes_t ();
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case COMPOSITE:
|
case COMPOSITE:
|
||||||
if (!CompositeGlyph (*header, bytes).compile_bytes_with_deltas (dest_start,
|
if (!CompositeGlyph (*header, bytes).compile_bytes_with_deltas (dest_start,
|
||||||
deltas,
|
points_with_deltas,
|
||||||
dest_end))
|
dest_end))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
@ -223,7 +256,7 @@ struct Glyph
|
||||||
dest_end))
|
dest_end))
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
default:
|
case EMPTY:
|
||||||
/* set empty bytes for empty glyph
|
/* set empty bytes for empty glyph
|
||||||
* do not use source glyph's pointers */
|
* do not use source glyph's pointers */
|
||||||
dest_start = hb_bytes_t ();
|
dest_start = hb_bytes_t ();
|
||||||
|
@ -247,7 +280,7 @@ struct Glyph
|
||||||
template <typename accelerator_t>
|
template <typename accelerator_t>
|
||||||
bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
|
bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
|
||||||
contour_point_vector_t &all_points /* OUT */,
|
contour_point_vector_t &all_points /* OUT */,
|
||||||
contour_point_vector_t *deltas = nullptr, /* OUT */
|
contour_point_vector_t *points_with_deltas = nullptr, /* OUT */
|
||||||
head_maxp_info_t * head_maxp_info = nullptr, /* OUT */
|
head_maxp_info_t * head_maxp_info = nullptr, /* OUT */
|
||||||
unsigned *composite_contours = nullptr, /* OUT */
|
unsigned *composite_contours = nullptr, /* OUT */
|
||||||
bool shift_points_hori = true,
|
bool shift_points_hori = true,
|
||||||
|
@ -287,9 +320,8 @@ struct Glyph
|
||||||
break;
|
break;
|
||||||
case COMPOSITE:
|
case COMPOSITE:
|
||||||
{
|
{
|
||||||
/* pseudo component points for each component in composite glyph */
|
for (auto &item : get_composite_iterator ())
|
||||||
unsigned num_points = hb_len (CompositeGlyph (*header, bytes).iter ());
|
if (unlikely (!item.get_points (points))) return false;
|
||||||
if (unlikely (!points.resize (num_points))) return false;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifndef HB_NO_VAR_COMPOSITES
|
#ifndef HB_NO_VAR_COMPOSITES
|
||||||
|
@ -299,7 +331,7 @@ struct Glyph
|
||||||
if (unlikely (!item.get_points (points))) return false;
|
if (unlikely (!item.get_points (points))) return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
default:
|
case EMPTY:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,17 +359,11 @@ struct Glyph
|
||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
phantoms[PHANTOM_LEFT].x = h_delta;
|
phantoms[PHANTOM_LEFT].x = h_delta;
|
||||||
phantoms[PHANTOM_RIGHT].x = h_adv + h_delta;
|
phantoms[PHANTOM_RIGHT].x = (int) h_adv + h_delta;
|
||||||
phantoms[PHANTOM_TOP].y = v_orig;
|
phantoms[PHANTOM_TOP].y = v_orig;
|
||||||
phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
|
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
|
#ifndef HB_NO_VAR
|
||||||
glyf_accelerator.gvar->apply_deltas_to_points (gid,
|
glyf_accelerator.gvar->apply_deltas_to_points (gid,
|
||||||
coords,
|
coords,
|
||||||
|
@ -346,13 +372,10 @@ struct Glyph
|
||||||
|
|
||||||
// mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
|
// mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
|
||||||
// with child glyphs' points
|
// with child glyphs' points
|
||||||
if (deltas != nullptr && depth == 0 && type == COMPOSITE)
|
if (points_with_deltas != nullptr && depth == 0 && type == COMPOSITE)
|
||||||
{
|
{
|
||||||
for (unsigned i = 0 ; i < points.length; i++)
|
if (unlikely (!points_with_deltas->resize (points.length))) return false;
|
||||||
{
|
points_with_deltas->copy_vector (points);
|
||||||
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) {
|
switch (type) {
|
||||||
|
@ -373,7 +396,7 @@ struct Glyph
|
||||||
.get_points (font,
|
.get_points (font,
|
||||||
glyf_accelerator,
|
glyf_accelerator,
|
||||||
comp_points,
|
comp_points,
|
||||||
deltas,
|
points_with_deltas,
|
||||||
head_maxp_info,
|
head_maxp_info,
|
||||||
composite_contours,
|
composite_contours,
|
||||||
shift_points_hori,
|
shift_points_hori,
|
||||||
|
@ -389,11 +412,12 @@ struct Glyph
|
||||||
for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
|
for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
|
||||||
phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
|
phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
|
||||||
|
|
||||||
/* Apply component transformation & translation */
|
float matrix[4];
|
||||||
item.transform_points (comp_points);
|
contour_point_t default_trans;
|
||||||
|
item.get_transformation (matrix, default_trans);
|
||||||
|
|
||||||
/* Apply translation from gvar */
|
/* Apply component transformation & translation (with deltas applied) */
|
||||||
comp_points.translate (points[comp_index]);
|
item.transform_points (comp_points, matrix, points[comp_index]);
|
||||||
|
|
||||||
if (item.is_anchored ())
|
if (item.is_anchored ())
|
||||||
{
|
{
|
||||||
|
@ -448,7 +472,7 @@ struct Glyph
|
||||||
.get_points (font,
|
.get_points (font,
|
||||||
glyf_accelerator,
|
glyf_accelerator,
|
||||||
comp_points,
|
comp_points,
|
||||||
deltas,
|
points_with_deltas,
|
||||||
head_maxp_info,
|
head_maxp_info,
|
||||||
nullptr,
|
nullptr,
|
||||||
shift_points_hori,
|
shift_points_hori,
|
||||||
|
@ -477,7 +501,7 @@ struct Glyph
|
||||||
all_points.extend (phantoms);
|
all_points.extend (phantoms);
|
||||||
} break;
|
} break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
case EMPTY:
|
||||||
all_points.extend (phantoms);
|
all_points.extend (phantoms);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -503,6 +527,8 @@ struct Glyph
|
||||||
}
|
}
|
||||||
|
|
||||||
hb_bytes_t get_bytes () const { return bytes; }
|
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 (),
|
Glyph () : bytes (),
|
||||||
header (bytes.as<GlyphHeader> ()),
|
header (bytes.as<GlyphHeader> ()),
|
||||||
|
@ -518,7 +544,9 @@ struct Glyph
|
||||||
int num_contours = header->numberOfContours;
|
int num_contours = header->numberOfContours;
|
||||||
if (unlikely (num_contours == 0)) type = EMPTY;
|
if (unlikely (num_contours == 0)) type = EMPTY;
|
||||||
else if (num_contours > 0) type = SIMPLE;
|
else if (num_contours > 0) type = SIMPLE;
|
||||||
|
#ifndef HB_NO_VAR_COMPOSITES
|
||||||
else if (num_contours == -2) type = VAR_COMPOSITE;
|
else if (num_contours == -2) type = VAR_COMPOSITE;
|
||||||
|
#endif
|
||||||
else type = COMPOSITE; /* negative numbers */
|
else type = COMPOSITE; /* negative numbers */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -526,7 +554,7 @@ struct Glyph
|
||||||
hb_bytes_t bytes;
|
hb_bytes_t bytes;
|
||||||
const GlyphHeader *header;
|
const GlyphHeader *header;
|
||||||
hb_codepoint_t gid;
|
hb_codepoint_t gid;
|
||||||
unsigned type;
|
glyph_type_t type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,11 @@ struct SimpleGlyph
|
||||||
unsigned int length (unsigned int instruction_len) const
|
unsigned int length (unsigned int instruction_len) const
|
||||||
{ return instruction_len_offset () + 2 + instruction_len; }
|
{ 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 instructions_length () const
|
||||||
{
|
{
|
||||||
unsigned int instruction_length_offset = instruction_len_offset ();
|
unsigned int instruction_length_offset = instruction_len_offset ();
|
||||||
|
@ -94,6 +99,7 @@ struct SimpleGlyph
|
||||||
/* zero instruction length */
|
/* zero instruction length */
|
||||||
void drop_hints ()
|
void drop_hints ()
|
||||||
{
|
{
|
||||||
|
if (!has_instructions_length ()) return;
|
||||||
GlyphHeader &glyph_header = const_cast<GlyphHeader &> (header);
|
GlyphHeader &glyph_header = const_cast<GlyphHeader &> (header);
|
||||||
(HBUINT16 &) StructAtOffset<HBUINT16> (&glyph_header, instruction_len_offset ()) = 0;
|
(HBUINT16 &) StructAtOffset<HBUINT16> (&glyph_header, instruction_len_offset ()) = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@ struct SubsetGlyph
|
||||||
Glyph source_glyph;
|
Glyph source_glyph;
|
||||||
hb_bytes_t dest_start; /* region of source_glyph to copy first */
|
hb_bytes_t dest_start; /* region of source_glyph to copy first */
|
||||||
hb_bytes_t dest_end; /* region of source_glyph to copy second */
|
hb_bytes_t dest_end; /* region of source_glyph to copy second */
|
||||||
|
bool allocated;
|
||||||
|
|
||||||
bool serialize (hb_serialize_context_t *c,
|
bool serialize (hb_serialize_context_t *c,
|
||||||
bool use_short_loca,
|
bool use_short_loca,
|
||||||
|
@ -26,7 +27,12 @@ struct SubsetGlyph
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
|
|
||||||
hb_bytes_t dest_glyph = dest_start.copy (c);
|
hb_bytes_t dest_glyph = dest_start.copy (c);
|
||||||
dest_glyph = hb_bytes_t (&dest_glyph, dest_glyph.length + dest_end.copy (c).length);
|
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);
|
||||||
unsigned int pad_length = use_short_loca ? padding () : 0;
|
unsigned int pad_length = use_short_loca ? padding () : 0;
|
||||||
DEBUG_MSG (SUBSET, nullptr, "serialize %u byte glyph, width %u pad %u", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
|
DEBUG_MSG (SUBSET, nullptr, "serialize %u byte glyph, width %u pad %u", dest_glyph.length, dest_glyph.length + pad_length, pad_length);
|
||||||
|
|
||||||
|
@ -40,13 +46,68 @@ struct SubsetGlyph
|
||||||
|
|
||||||
if (unlikely (!dest_glyph.length)) return_trace (true);
|
if (unlikely (!dest_glyph.length)) return_trace (true);
|
||||||
|
|
||||||
/* update components gids */
|
/* update components gids. */
|
||||||
for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
|
for (auto &_ : Glyph (dest_glyph).get_composite_iterator ())
|
||||||
{
|
{
|
||||||
hb_codepoint_t new_gid;
|
hb_codepoint_t new_gid;
|
||||||
if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
|
if (plan->new_gid_for_old_gid (_.get_gid(), &new_gid))
|
||||||
const_cast<CompositeGlyphRecord &> (_).set_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)
|
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||||
Glyph (dest_glyph).drop_hints ();
|
Glyph (dest_glyph).drop_hints ();
|
||||||
|
@ -60,12 +121,18 @@ struct SubsetGlyph
|
||||||
bool compile_bytes_with_deltas (const hb_subset_plan_t *plan,
|
bool compile_bytes_with_deltas (const hb_subset_plan_t *plan,
|
||||||
hb_font_t *font,
|
hb_font_t *font,
|
||||||
const glyf_accelerator_t &glyf)
|
const glyf_accelerator_t &glyf)
|
||||||
{ return source_glyph.compile_bytes_with_deltas (plan, font, glyf, dest_start, dest_end); }
|
{
|
||||||
|
allocated = source_glyph.compile_bytes_with_deltas (plan, font, glyf, dest_start, dest_end);
|
||||||
|
return allocated;
|
||||||
|
}
|
||||||
|
|
||||||
void free_compiled_bytes ()
|
void free_compiled_bytes ()
|
||||||
{
|
{
|
||||||
dest_start.fini ();
|
if (likely (allocated)) {
|
||||||
dest_end.fini ();
|
allocated = false;
|
||||||
|
dest_start.fini ();
|
||||||
|
dest_end.fini ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void drop_hints_bytes ()
|
void drop_hints_bytes ()
|
||||||
|
|
|
@ -27,7 +27,7 @@ struct VarCompositeGlyphRecord
|
||||||
HAVE_SKEW_Y = 0x0200,
|
HAVE_SKEW_Y = 0x0200,
|
||||||
HAVE_TCENTER_X = 0x0400,
|
HAVE_TCENTER_X = 0x0400,
|
||||||
HAVE_TCENTER_Y = 0x0800,
|
HAVE_TCENTER_Y = 0x0800,
|
||||||
GID_IS_24 = 0x1000,
|
GID_IS_24BIT = 0x1000,
|
||||||
AXES_HAVE_VARIATION = 0x2000,
|
AXES_HAVE_VARIATION = 0x2000,
|
||||||
RESET_UNSPECIFIED_AXES = 0x4000,
|
RESET_UNSPECIFIED_AXES = 0x4000,
|
||||||
};
|
};
|
||||||
|
@ -43,7 +43,7 @@ struct VarCompositeGlyphRecord
|
||||||
|
|
||||||
// gid
|
// gid
|
||||||
size += 2;
|
size += 2;
|
||||||
if (flags & GID_IS_24) size += 1;
|
if (flags & GID_IS_24BIT) size += 1;
|
||||||
|
|
||||||
if (flags & HAVE_TRANSLATE_X) size += 2;
|
if (flags & HAVE_TRANSLATE_X) size += 2;
|
||||||
if (flags & HAVE_TRANSLATE_Y) size += 2;
|
if (flags & HAVE_TRANSLATE_Y) size += 2;
|
||||||
|
@ -65,12 +65,20 @@ struct VarCompositeGlyphRecord
|
||||||
|
|
||||||
hb_codepoint_t get_gid () const
|
hb_codepoint_t get_gid () const
|
||||||
{
|
{
|
||||||
if (flags & GID_IS_24)
|
if (flags & GID_IS_24BIT)
|
||||||
return StructAfter<const HBGlyphID24> (numAxes);
|
return StructAfter<const HBGlyphID24> (numAxes);
|
||||||
else
|
else
|
||||||
return StructAfter<const HBGlyphID16> (numAxes);
|
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
|
unsigned get_numAxes () const
|
||||||
{
|
{
|
||||||
return numAxes;
|
return numAxes;
|
||||||
|
@ -145,7 +153,7 @@ struct VarCompositeGlyphRecord
|
||||||
float rotation)
|
float rotation)
|
||||||
{
|
{
|
||||||
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240
|
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240
|
||||||
rotation = rotation * float (M_PI);
|
rotation = rotation * HB_PI;
|
||||||
float c = cosf (rotation);
|
float c = cosf (rotation);
|
||||||
float s = sinf (rotation);
|
float s = sinf (rotation);
|
||||||
float other[6] = {c, s, -s, c, 0.f, 0.f};
|
float other[6] = {c, s, -s, c, 0.f, 0.f};
|
||||||
|
@ -156,8 +164,8 @@ struct VarCompositeGlyphRecord
|
||||||
float skewX, float skewY)
|
float skewX, float skewY)
|
||||||
{
|
{
|
||||||
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255
|
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255
|
||||||
skewX = skewX * float (M_PI);
|
skewX = skewX * HB_PI;
|
||||||
skewY = skewY * float (M_PI);
|
skewY = skewY * HB_PI;
|
||||||
float other[6] = {1.f, tanf (skewY), tanf (skewX), 1.f, 0.f, 0.f};
|
float other[6] = {1.f, tanf (skewY), tanf (skewX), 1.f, 0.f, 0.f};
|
||||||
transform (matrix, trans, other);
|
transform (matrix, trans, other);
|
||||||
}
|
}
|
||||||
|
@ -180,7 +188,7 @@ struct VarCompositeGlyphRecord
|
||||||
unsigned axes_size = numAxes * axis_width;
|
unsigned axes_size = numAxes * axis_width;
|
||||||
|
|
||||||
const F2DOT14 *q = (const F2DOT14 *) (axes_size +
|
const F2DOT14 *q = (const F2DOT14 *) (axes_size +
|
||||||
(flags & GID_IS_24 ? 3 : 2) +
|
(flags & GID_IS_24BIT ? 3 : 2) +
|
||||||
&StructAfter<const HBUINT8> (numAxes));
|
&StructAfter<const HBUINT8> (numAxes));
|
||||||
|
|
||||||
hb_array_t<contour_point_t> rec_points = points.as_array ().sub_array (points.length - get_num_points ());
|
hb_array_t<contour_point_t> rec_points = points.as_array ().sub_array (points.length - get_num_points ());
|
||||||
|
@ -308,8 +316,8 @@ struct VarCompositeGlyphRecord
|
||||||
bool have_variations = flags & AXES_HAVE_VARIATION;
|
bool have_variations = flags & AXES_HAVE_VARIATION;
|
||||||
unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
|
unsigned axis_width = (flags & AXIS_INDICES_ARE_SHORT) ? 2 : 1;
|
||||||
|
|
||||||
const HBUINT8 *p = (const HBUINT8 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24 ? 3 : 2));
|
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_24 ? 3 : 2));
|
const HBUINT16 *q = (const HBUINT16 *) (((HBUINT8 *) &numAxes) + numAxes.static_size + (flags & GID_IS_24BIT ? 3 : 2));
|
||||||
|
|
||||||
const F2DOT14 *a = (const F2DOT14 *) ((HBUINT8 *) (axis_width == 1 ? (p + numAxes) : (HBUINT8 *) (q + numAxes)));
|
const F2DOT14 *a = (const F2DOT14 *) ((HBUINT8 *) (axis_width == 1 ? (p + numAxes) : (HBUINT8 *) (q + numAxes)));
|
||||||
|
|
||||||
|
@ -344,6 +352,13 @@ struct VarCompositeGlyph
|
||||||
var_composite_iter_t iter () const
|
var_composite_iter_t iter () const
|
||||||
{ return var_composite_iter_t (bytes, &StructAfter<VarCompositeGlyphRecord, GlyphHeader> (header)); }
|
{ 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,6 +31,12 @@ struct glyf
|
||||||
|
|
||||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_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
|
bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
|
@ -72,6 +78,13 @@ struct glyf
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
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> ();
|
glyf *glyf_prime = c->serializer->start_embed <glyf> ();
|
||||||
if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
|
if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
|
||||||
|
|
||||||
|
@ -85,11 +98,17 @@ struct glyf
|
||||||
hb_vector_t<unsigned> padded_offsets;
|
hb_vector_t<unsigned> padded_offsets;
|
||||||
unsigned num_glyphs = c->plan->num_output_glyphs ();
|
unsigned num_glyphs = c->plan->num_output_glyphs ();
|
||||||
if (unlikely (!padded_offsets.resize (num_glyphs)))
|
if (unlikely (!padded_offsets.resize (num_glyphs)))
|
||||||
|
{
|
||||||
|
hb_font_destroy (font);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
|
hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
|
||||||
if (!_populate_subset_glyphs (c->plan, font, glyphs))
|
if (!_populate_subset_glyphs (c->plan, font, glyphs))
|
||||||
|
{
|
||||||
|
hb_font_destroy (font);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (font)
|
if (font)
|
||||||
hb_font_destroy (font);
|
hb_font_destroy (font);
|
||||||
|
@ -112,7 +131,7 @@ struct glyf
|
||||||
|
|
||||||
bool result = glyf_prime->serialize (c->serializer, glyphs.writer (), use_short_loca, c->plan);
|
bool result = glyf_prime->serialize (c->serializer, glyphs.writer (), use_short_loca, c->plan);
|
||||||
if (c->plan->normalized_coords && !c->plan->pinned_at_default)
|
if (c->plan->normalized_coords && !c->plan->pinned_at_default)
|
||||||
_free_compiled_subset_glyphs (glyphs, glyphs.length - 1);
|
_free_compiled_subset_glyphs (glyphs);
|
||||||
|
|
||||||
if (!result) return false;
|
if (!result) return false;
|
||||||
|
|
||||||
|
@ -131,9 +150,9 @@ struct glyf
|
||||||
hb_font_t *
|
hb_font_t *
|
||||||
_create_font_for_instancing (const hb_subset_plan_t *plan) const;
|
_create_font_for_instancing (const hb_subset_plan_t *plan) const;
|
||||||
|
|
||||||
void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> &glyphs, unsigned index) const
|
void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> &glyphs) const
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i <= index && i < glyphs.length; i++)
|
for (unsigned i = 0; i < glyphs.length; i++)
|
||||||
glyphs[i].free_compiled_bytes ();
|
glyphs[i].free_compiled_bytes ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +181,7 @@ struct glyf_accelerator_t
|
||||||
vmtx = nullptr;
|
vmtx = nullptr;
|
||||||
#endif
|
#endif
|
||||||
const OT::head &head = *face->table.head;
|
const OT::head &head = *face->table.head;
|
||||||
if (head.indexToLocFormat > 1 || head.glyphDataFormat > 0)
|
if (!glyf::has_valid_glyf_format (face))
|
||||||
/* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
|
/* Unknown format. Leave num_glyphs=0, that takes care of disabling us. */
|
||||||
return;
|
return;
|
||||||
short_offset = 0 == head.indexToLocFormat;
|
short_offset = 0 == head.indexToLocFormat;
|
||||||
|
@ -222,6 +241,8 @@ struct glyf_accelerator_t
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
#ifndef HB_NO_VAR
|
#ifndef HB_NO_VAR
|
||||||
struct points_aggregator_t
|
struct points_aggregator_t
|
||||||
{
|
{
|
||||||
|
@ -285,7 +306,6 @@ struct glyf_accelerator_t
|
||||||
contour_point_t *get_phantoms_sink () { return phantoms; }
|
contour_point_t *get_phantoms_sink () { return phantoms; }
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
|
||||||
unsigned
|
unsigned
|
||||||
get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
|
get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
|
||||||
{
|
{
|
||||||
|
@ -327,6 +347,15 @@ struct glyf_accelerator_t
|
||||||
}
|
}
|
||||||
#endif
|
#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:
|
public:
|
||||||
bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
|
bool get_extents (hb_font_t *font, hb_codepoint_t gid, hb_glyph_extents_t *extents) const
|
||||||
{
|
{
|
||||||
|
@ -405,7 +434,6 @@ glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
|
||||||
unsigned num_glyphs = plan->num_output_glyphs ();
|
unsigned num_glyphs = plan->num_output_glyphs ();
|
||||||
if (!glyphs.resize (num_glyphs)) return false;
|
if (!glyphs.resize (num_glyphs)) return false;
|
||||||
|
|
||||||
unsigned idx = 0;
|
|
||||||
for (auto p : plan->glyph_map->iter ())
|
for (auto p : plan->glyph_map->iter ())
|
||||||
{
|
{
|
||||||
unsigned new_gid = p.second;
|
unsigned new_gid = p.second;
|
||||||
|
@ -433,11 +461,10 @@ glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
|
||||||
if (unlikely (!subset_glyph.compile_bytes_with_deltas (plan, font, glyf)))
|
if (unlikely (!subset_glyph.compile_bytes_with_deltas (plan, font, glyf)))
|
||||||
{
|
{
|
||||||
// when pinned at default, only bounds are updated, thus no need to free
|
// when pinned at default, only bounds are updated, thus no need to free
|
||||||
if (!plan->pinned_at_default && idx > 0)
|
if (!plan->pinned_at_default)
|
||||||
_free_compiled_subset_glyphs (glyphs, idx - 1);
|
_free_compiled_subset_glyphs (glyphs);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
idx++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -451,7 +478,10 @@ glyf::_create_font_for_instancing (const hb_subset_plan_t *plan) const
|
||||||
|
|
||||||
hb_vector_t<hb_variation_t> vars;
|
hb_vector_t<hb_variation_t> vars;
|
||||||
if (unlikely (!vars.alloc (plan->user_axes_location.get_population (), true)))
|
if (unlikely (!vars.alloc (plan->user_axes_location.get_population (), true)))
|
||||||
|
{
|
||||||
|
hb_font_destroy (font);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto _ : plan->user_axes_location)
|
for (auto _ : plan->user_axes_location)
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,13 +12,17 @@ list(GET _harfbuzz_version_info 2
|
||||||
_harfbuzz_age)
|
_harfbuzz_age)
|
||||||
unset(_harfbuzz_version_info)
|
unset(_harfbuzz_version_info)
|
||||||
|
|
||||||
if (APPLE)
|
if ("@default_library@" MATCHES "static")
|
||||||
set(_harfbuzz_lib_suffix ".0${CMAKE_SHARED_LIBRARY_SUFFIX}")
|
set(_harfbuzz_lib_suffix ".a")
|
||||||
elseif (UNIX)
|
|
||||||
set(_harfbuzz_lib_suffix "${CMAKE_SHARED_LIBRARY_SUFFIX}.0.${_harfbuzz_current}.${_harfbuzz_revision}")
|
|
||||||
else ()
|
else ()
|
||||||
# Unsupported.
|
if (APPLE)
|
||||||
set(harfbuzz_FOUND 0)
|
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 ()
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
# Add the libraries.
|
# Add the libraries.
|
||||||
|
|
|
@ -464,7 +464,8 @@ enum { DELETED_GLYPH = 0xFFFF };
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct Entry
|
struct Entry
|
||||||
{
|
{
|
||||||
bool sanitize (hb_sanitize_context_t *c, unsigned int count) const
|
// This does seem like it's ever called.
|
||||||
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
/* Note, we don't recurse-sanitize data because we don't access it.
|
/* Note, we don't recurse-sanitize data because we don't access it.
|
||||||
|
@ -492,7 +493,8 @@ struct Entry
|
||||||
template <>
|
template <>
|
||||||
struct Entry<void>
|
struct Entry<void>
|
||||||
{
|
{
|
||||||
bool sanitize (hb_sanitize_context_t *c, unsigned int count /*XXX Unused?*/) const
|
// This does seem like it's ever called.
|
||||||
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SANITIZE (this);
|
TRACE_SANITIZE (this);
|
||||||
return_trace (c->check_struct (this));
|
return_trace (c->check_struct (this));
|
||||||
|
|
|
@ -38,6 +38,10 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Atomic integers and pointers.
|
* 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -194,7 +194,7 @@ struct hb_bit_set_t
|
||||||
unsigned int end = major_start (m + 1);
|
unsigned int end = major_start (m + 1);
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (v || page) /* The v check is to optimize out the page check if v is true. */
|
if (g != INVALID && (v || page)) /* The v check is to optimize out the page check if v is true. */
|
||||||
page->set (g, v);
|
page->set (g, v);
|
||||||
|
|
||||||
array = &StructAtOffsetUnaligned<T> (array, stride);
|
array = &StructAtOffsetUnaligned<T> (array, stride);
|
||||||
|
@ -238,7 +238,7 @@ struct hb_bit_set_t
|
||||||
if (g < last_g) return false;
|
if (g < last_g) return false;
|
||||||
last_g = g;
|
last_g = g;
|
||||||
|
|
||||||
if (v || page) /* The v check is to optimize out the page check if v is true. */
|
if (g != INVALID && (v || page)) /* The v check is to optimize out the page check if v is true. */
|
||||||
page->add (g);
|
page->add (g);
|
||||||
|
|
||||||
array = &StructAtOffsetUnaligned<T> (array, stride);
|
array = &StructAtOffsetUnaligned<T> (array, stride);
|
||||||
|
|
|
@ -40,6 +40,11 @@
|
||||||
* Buffers serve a dual role in HarfBuzz; before shaping, they hold
|
* Buffers serve a dual role in HarfBuzz; before shaping, they hold
|
||||||
* the input characters that are passed to hb_shape(), and after
|
* the input characters that are passed to hb_shape(), and after
|
||||||
* shaping they hold the output glyphs.
|
* 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.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,19 @@
|
||||||
#include "hb.hh"
|
#include "hb.hh"
|
||||||
|
|
||||||
|
|
||||||
/* Implements a lockfree cache for int->int functions. */
|
/* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
template <unsigned int key_bits=16,
|
template <unsigned int key_bits=16,
|
||||||
unsigned int value_bits=8 + 32 - key_bits,
|
unsigned int value_bits=8 + 32 - key_bits,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright © 2022 Red Hat, Inc
|
* Copyright © 2022 Red Hat, Inc
|
||||||
|
* Copyright © 2021, 2022 Black Foundry
|
||||||
*
|
*
|
||||||
* This is part of HarfBuzz, a text shaping library.
|
* This is part of HarfBuzz, a text shaping library.
|
||||||
*
|
*
|
||||||
|
@ -32,9 +33,13 @@
|
||||||
|
|
||||||
#include <cairo.h>
|
#include <cairo.h>
|
||||||
|
|
||||||
#define PREALLOCATED_COLOR_STOPS 16
|
/* 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 _2_M_PIf (2.f * float (M_PI))
|
#define PREALLOCATED_COLOR_STOPS 16
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float r, g, b, a;
|
float r, g, b, a;
|
||||||
|
@ -518,7 +523,7 @@ _hb_cairo_add_patch (cairo_pattern_t *pattern, hb_cairo_point_t *center, hb_cair
|
||||||
cairo_mesh_pattern_end_patch (pattern);
|
cairo_mesh_pattern_end_patch (pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MAX_ANGLE ((float) M_PI / 8.f)
|
#define MAX_ANGLE (HB_PI / 8.f)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_hb_cairo_add_sweep_gradient_patches1 (float cx, float cy, float radius,
|
_hb_cairo_add_sweep_gradient_patches1 (float cx, float cy, float radius,
|
||||||
|
@ -601,7 +606,7 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops,
|
||||||
start_angle, &c,
|
start_angle, &c,
|
||||||
pattern);
|
pattern);
|
||||||
}
|
}
|
||||||
if (end_angle < _2_M_PIf)
|
if (end_angle < HB_2_PI)
|
||||||
{
|
{
|
||||||
c.r = hb_color_get_red (stops[n_stops - 1].color) / 255.;
|
c.r = hb_color_get_red (stops[n_stops - 1].color) / 255.;
|
||||||
c.g = hb_color_get_green (stops[n_stops - 1].color) / 255.;
|
c.g = hb_color_get_green (stops[n_stops - 1].color) / 255.;
|
||||||
|
@ -609,7 +614,7 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops,
|
||||||
c.a = hb_color_get_alpha (stops[n_stops - 1].color) / 255.;
|
c.a = hb_color_get_alpha (stops[n_stops - 1].color) / 255.;
|
||||||
_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
|
_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
|
||||||
end_angle, &c,
|
end_angle, &c,
|
||||||
_2_M_PIf, &c,
|
HB_2_PI, &c,
|
||||||
pattern);
|
pattern);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -673,7 +678,7 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops,
|
||||||
color0 = colors[n_stops-1];
|
color0 = colors[n_stops-1];
|
||||||
_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
|
_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
|
||||||
0., &color0,
|
0., &color0,
|
||||||
_2_M_PIf, &color0,
|
HB_2_PI, &color0,
|
||||||
pattern);
|
pattern);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -685,7 +690,7 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops,
|
||||||
|
|
||||||
for (pos++; pos < n_stops; pos++)
|
for (pos++; pos < n_stops; pos++)
|
||||||
{
|
{
|
||||||
if (angles[pos] <= _2_M_PIf)
|
if (angles[pos] <= HB_2_PI)
|
||||||
{
|
{
|
||||||
_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
|
_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
|
||||||
angles[pos - 1], &colors[pos-1],
|
angles[pos - 1], &colors[pos-1],
|
||||||
|
@ -694,11 +699,11 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
float k = (_2_M_PIf - angles[pos - 1]) / (angles[pos] - angles[pos - 1]);
|
float k = (HB_2_PI - angles[pos - 1]) / (angles[pos] - angles[pos - 1]);
|
||||||
_hb_cairo_interpolate_colors (&colors[pos - 1], &colors[pos], k, &color1);
|
_hb_cairo_interpolate_colors (&colors[pos - 1], &colors[pos], k, &color1);
|
||||||
_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
|
_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
|
||||||
angles[pos - 1], &colors[pos - 1],
|
angles[pos - 1], &colors[pos - 1],
|
||||||
_2_M_PIf, &color1,
|
HB_2_PI, &color1,
|
||||||
pattern);
|
pattern);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -710,7 +715,7 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops,
|
||||||
color0 = colors[n_stops - 1];
|
color0 = colors[n_stops - 1];
|
||||||
_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
|
_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
|
||||||
angles[n_stops - 1], &color0,
|
angles[n_stops - 1], &color0,
|
||||||
_2_M_PIf, &color0,
|
HB_2_PI, &color0,
|
||||||
pattern);
|
pattern);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
@ -794,14 +799,14 @@ _hb_cairo_add_sweep_gradient_patches (hb_color_stop_t *stops,
|
||||||
a1, c1,
|
a1, c1,
|
||||||
pattern);
|
pattern);
|
||||||
}
|
}
|
||||||
else if (a1 >= _2_M_PIf)
|
else if (a1 >= HB_2_PI)
|
||||||
{
|
{
|
||||||
hb_cairo_color_t color;
|
hb_cairo_color_t color;
|
||||||
float f = (_2_M_PIf - a0)/(a1 - a0);
|
float f = (HB_2_PI - a0)/(a1 - a0);
|
||||||
_hb_cairo_interpolate_colors (c0, c1, f, &color);
|
_hb_cairo_interpolate_colors (c0, c1, f, &color);
|
||||||
_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
|
_hb_cairo_add_sweep_gradient_patches1 (cx, cy, radius,
|
||||||
a0, c0,
|
a0, c0,
|
||||||
_2_M_PIf, &color,
|
HB_2_PI, &color,
|
||||||
pattern);
|
pattern);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
|
@ -632,6 +632,7 @@ hb_script_get_horizontal_direction (hb_script_t script)
|
||||||
case HB_SCRIPT_OLD_HUNGARIAN:
|
case HB_SCRIPT_OLD_HUNGARIAN:
|
||||||
case HB_SCRIPT_OLD_ITALIC:
|
case HB_SCRIPT_OLD_ITALIC:
|
||||||
case HB_SCRIPT_RUNIC:
|
case HB_SCRIPT_RUNIC:
|
||||||
|
case HB_SCRIPT_TIFINAGH:
|
||||||
|
|
||||||
return HB_DIRECTION_INVALID;
|
return HB_DIRECTION_INVALID;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,12 @@
|
||||||
* More precisely, a font face represents a single face in a binary font file.
|
* 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 typically built from a binary blob and a face index.
|
||||||
* Font faces are used to create fonts.
|
* 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.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
@ -197,7 +203,7 @@ _hb_face_for_data_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void
|
||||||
* a face index into that blob.
|
* a face index into that blob.
|
||||||
*
|
*
|
||||||
* The face index is used for blobs of file formats such as TTC and
|
* The face index is used for blobs of file formats such as TTC and
|
||||||
* and DFont that can contain more than one face. Face indices within
|
* DFont that can contain more than one face. Face indices within
|
||||||
* such collections are zero-based.
|
* such collections are zero-based.
|
||||||
*
|
*
|
||||||
* <note>Note: If the blob font format is not a collection, @index
|
* <note>Note: If the blob font format is not a collection, @index
|
||||||
|
|
|
@ -76,7 +76,7 @@ struct hb_face_t
|
||||||
if (unlikely (!reference_table_func))
|
if (unlikely (!reference_table_func))
|
||||||
return hb_blob_get_empty ();
|
return hb_blob_get_empty ();
|
||||||
|
|
||||||
blob = reference_table_func (/*XXX*/const_cast<hb_face_t *> (this), tag, user_data);
|
blob = reference_table_func (/*Oh, well.*/const_cast<hb_face_t *> (this), tag, user_data);
|
||||||
if (unlikely (!blob))
|
if (unlikely (!blob))
|
||||||
return hb_blob_get_empty ();
|
return hb_blob_get_empty ();
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,11 @@
|
||||||
*
|
*
|
||||||
* HarfBuzz provides a built-in set of lightweight default
|
* HarfBuzz provides a built-in set of lightweight default
|
||||||
* functions for each method in #hb_font_funcs_t.
|
* 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.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
@ -1387,7 +1392,7 @@ hb_font_get_glyph_from_name (hb_font_t *font,
|
||||||
/**
|
/**
|
||||||
* hb_font_get_glyph_shape:
|
* hb_font_get_glyph_shape:
|
||||||
* @font: #hb_font_t to work upon
|
* @font: #hb_font_t to work upon
|
||||||
* @glyph: : The glyph ID
|
* @glyph: The glyph ID
|
||||||
* @dfuncs: #hb_draw_funcs_t to draw to
|
* @dfuncs: #hb_draw_funcs_t to draw to
|
||||||
* @draw_data: User data to pass to draw callbacks
|
* @draw_data: User data to pass to draw callbacks
|
||||||
*
|
*
|
||||||
|
@ -1409,7 +1414,7 @@ hb_font_get_glyph_shape (hb_font_t *font,
|
||||||
/**
|
/**
|
||||||
* hb_font_draw_glyph:
|
* hb_font_draw_glyph:
|
||||||
* @font: #hb_font_t to work upon
|
* @font: #hb_font_t to work upon
|
||||||
* @glyph: : The glyph ID
|
* @glyph: The glyph ID
|
||||||
* @dfuncs: #hb_draw_funcs_t to draw to
|
* @dfuncs: #hb_draw_funcs_t to draw to
|
||||||
* @draw_data: User data to pass to draw callbacks
|
* @draw_data: User data to pass to draw callbacks
|
||||||
*
|
*
|
||||||
|
|
|
@ -301,8 +301,8 @@ _hb_ft_paint (hb_ft_paint_context_t *c,
|
||||||
c->funcs->sweep_gradient (c->data, &cl,
|
c->funcs->sweep_gradient (c->data, &cl,
|
||||||
paint.u.sweep_gradient.center.x / 65536.f,
|
paint.u.sweep_gradient.center.x / 65536.f,
|
||||||
paint.u.sweep_gradient.center.y / 65536.f,
|
paint.u.sweep_gradient.center.y / 65536.f,
|
||||||
(paint.u.sweep_gradient.start_angle / 65536.f + 1) * (float) M_PI,
|
(paint.u.sweep_gradient.start_angle / 65536.f + 1) * HB_PI,
|
||||||
(paint.u.sweep_gradient.end_angle / 65536.f + 1) * (float) M_PI);
|
(paint.u.sweep_gradient.end_angle / 65536.f + 1) * HB_PI);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case FT_COLR_PAINTFORMAT_GLYPH:
|
case FT_COLR_PAINTFORMAT_GLYPH:
|
||||||
|
|
|
@ -343,7 +343,8 @@ struct hb_hashmap_t
|
||||||
)
|
)
|
||||||
auto keys () const HB_AUTO_RETURN
|
auto keys () const HB_AUTO_RETURN
|
||||||
(
|
(
|
||||||
+ keys_ref ()
|
+ iter_items ()
|
||||||
|
| hb_map (&item_t::key)
|
||||||
| hb_map (hb_ridentity)
|
| hb_map (hb_ridentity)
|
||||||
)
|
)
|
||||||
auto values_ref () const HB_AUTO_RETURN
|
auto values_ref () const HB_AUTO_RETURN
|
||||||
|
@ -353,7 +354,8 @@ struct hb_hashmap_t
|
||||||
)
|
)
|
||||||
auto values () const HB_AUTO_RETURN
|
auto values () const HB_AUTO_RETURN
|
||||||
(
|
(
|
||||||
+ values_ref ()
|
+ iter_items ()
|
||||||
|
| hb_map (&item_t::value)
|
||||||
| hb_map (hb_ridentity)
|
| hb_map (hb_ridentity)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -413,7 +413,7 @@ hb_ot_get_glyph_extents (hb_font_t *font,
|
||||||
if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
|
if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
|
||||||
if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
|
if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
|
||||||
#endif
|
#endif
|
||||||
#if !defined(HB_NO_COLOR)
|
#if !defined(HB_NO_COLOR) && !defined(HB_NO_PAINT)
|
||||||
if (ot_face->COLR->get_extents (font, glyph, extents)) return true;
|
if (ot_face->COLR->get_extents (font, glyph, extents)) return true;
|
||||||
#endif
|
#endif
|
||||||
if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
|
if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
|
||||||
|
@ -633,20 +633,4 @@ hb_ot_font_set_funcs (hb_font_t *font)
|
||||||
_hb_ot_font_destroy);
|
_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
|
#endif
|
||||||
|
|
|
@ -76,7 +76,7 @@ struct DeviceRecord
|
||||||
HBUINT8 maxWidth; /* Maximum width. */
|
HBUINT8 maxWidth; /* Maximum width. */
|
||||||
UnsizedArrayOf<HBUINT8> widthsZ; /* Array of widths (numGlyphs is from the 'maxp' table). */
|
UnsizedArrayOf<HBUINT8> widthsZ; /* Array of widths (numGlyphs is from the 'maxp' table). */
|
||||||
public:
|
public:
|
||||||
DEFINE_SIZE_ARRAY (2, widthsZ);
|
DEFINE_SIZE_UNBOUNDED (2);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,14 +87,6 @@ struct hdmx
|
||||||
unsigned int get_size () const
|
unsigned int get_size () const
|
||||||
{ return min_size + numRecords * sizeDeviceRecord; }
|
{ 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,
|
template<typename Iterator,
|
||||||
hb_requires (hb_is_iterator (Iterator))>
|
hb_requires (hb_is_iterator (Iterator))>
|
||||||
bool serialize (hb_serialize_context_t *c, unsigned version, Iterator it)
|
bool serialize (hb_serialize_context_t *c, unsigned version, Iterator it)
|
||||||
|
|
|
@ -63,7 +63,25 @@ struct head
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
return_trace (serialize (c->serializer));
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum mac_style_flag_t {
|
enum mac_style_flag_t {
|
||||||
|
|
|
@ -50,6 +50,9 @@ _glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t gly
|
||||||
HB_INTERNAL unsigned
|
HB_INTERNAL unsigned
|
||||||
_glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
|
_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 {
|
namespace OT {
|
||||||
|
|
||||||
|
@ -92,7 +95,7 @@ struct hmtxvmtx
|
||||||
|
|
||||||
unsigned int length;
|
unsigned int length;
|
||||||
H *table = (H *) hb_blob_get_data (dest_blob, &length);
|
H *table = (H *) hb_blob_get_data (dest_blob, &length);
|
||||||
table->numberOfLongMetrics = num_hmetrics;
|
c->serializer->check_assign (table->numberOfLongMetrics, num_hmetrics, HB_SERIALIZE_ERROR_INT_OVERFLOW);
|
||||||
|
|
||||||
#ifndef HB_NO_VAR
|
#ifndef HB_NO_VAR
|
||||||
if (c->plan->normalized_coords)
|
if (c->plan->normalized_coords)
|
||||||
|
@ -165,12 +168,19 @@ struct hmtxvmtx
|
||||||
lm.sb = _.second;
|
lm.sb = _.second;
|
||||||
if (unlikely (!c->embed<LongMetric> (&lm))) return;
|
if (unlikely (!c->embed<LongMetric> (&lm))) return;
|
||||||
}
|
}
|
||||||
else
|
else if (idx < 0x10000u)
|
||||||
{
|
{
|
||||||
FWORD *sb = c->allocate_size<FWORD> (FWORD::static_size);
|
FWORD *sb = c->allocate_size<FWORD> (FWORD::static_size);
|
||||||
if (unlikely (!sb)) return;
|
if (unlikely (!sb)) return;
|
||||||
*sb = _.second;
|
*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++;
|
idx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,7 +199,7 @@ struct hmtxvmtx
|
||||||
/* Determine num_long_metrics to encode. */
|
/* Determine num_long_metrics to encode. */
|
||||||
auto& plan = c->plan;
|
auto& plan = c->plan;
|
||||||
|
|
||||||
num_long_metrics = plan->num_output_glyphs ();
|
num_long_metrics = hb_min (plan->num_output_glyphs (), 0xFFFFu);
|
||||||
unsigned int last_advance = get_new_gid_advance_unscaled (plan, mtx_map, num_long_metrics - 1, _mtx);
|
unsigned int last_advance = get_new_gid_advance_unscaled (plan, mtx_map, num_long_metrics - 1, _mtx);
|
||||||
while (num_long_metrics > 1 &&
|
while (num_long_metrics > 1 &&
|
||||||
last_advance == get_new_gid_advance_unscaled (plan, mtx_map, num_long_metrics - 2, _mtx))
|
last_advance == get_new_gid_advance_unscaled (plan, mtx_map, num_long_metrics - 2, _mtx))
|
||||||
|
@ -208,7 +218,8 @@ struct hmtxvmtx
|
||||||
if (!c->plan->old_gid_for_new_gid (_, &old_gid))
|
if (!c->plan->old_gid_for_new_gid (_, &old_gid))
|
||||||
return hb_pair (0u, 0);
|
return hb_pair (0u, 0);
|
||||||
int lsb = 0;
|
int lsb = 0;
|
||||||
(void) _mtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb);
|
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);
|
||||||
return hb_pair (_mtx.get_advance_without_var_unscaled (old_gid), +lsb);
|
return hb_pair (_mtx.get_advance_without_var_unscaled (old_gid), +lsb);
|
||||||
}
|
}
|
||||||
return mtx_map->get (_);
|
return mtx_map->get (_);
|
||||||
|
|
|
@ -529,6 +529,9 @@ struct FeatureParamsSize
|
||||||
return_trace (true);
|
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
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
|
@ -585,6 +588,9 @@ struct FeatureParamsStylisticSet
|
||||||
return_trace (c->check_struct (this));
|
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
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
|
@ -632,6 +638,20 @@ struct FeatureParamsCharacterVariants
|
||||||
unsigned get_size () const
|
unsigned get_size () const
|
||||||
{ return min_size + characters.len * HBUINT24::static_size; }
|
{ 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
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
|
@ -694,6 +714,19 @@ struct FeatureParams
|
||||||
return_trace (true);
|
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
|
bool subset (hb_subset_context_t *c, const Tag* tag) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
|
@ -762,6 +795,12 @@ struct Feature
|
||||||
bool intersects_lookup_indexes (const hb_map_t *lookup_indexes) const
|
bool intersects_lookup_indexes (const hb_map_t *lookup_indexes) const
|
||||||
{ return lookupIndex.intersects (lookup_indexes); }
|
{ 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,
|
bool subset (hb_subset_context_t *c,
|
||||||
hb_subset_layout_context_t *l,
|
hb_subset_layout_context_t *l,
|
||||||
const Tag *tag = nullptr) const
|
const Tag *tag = nullptr) const
|
||||||
|
|
|
@ -4461,6 +4461,18 @@ 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>
|
template <typename T>
|
||||||
struct accelerator_t
|
struct accelerator_t
|
||||||
{
|
{
|
||||||
|
|
|
@ -64,6 +64,8 @@ using OT::Layout::GPOS;
|
||||||
* @include: hb-ot.h
|
* @include: hb-ot.h
|
||||||
*
|
*
|
||||||
* Functions for querying OpenType Layout features in the font face.
|
* 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.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ struct maxp
|
||||||
maxp *maxp_prime = c->serializer->embed (this);
|
maxp *maxp_prime = c->serializer->embed (this);
|
||||||
if (unlikely (!maxp_prime)) return_trace (false);
|
if (unlikely (!maxp_prime)) return_trace (false);
|
||||||
|
|
||||||
maxp_prime->numGlyphs = c->plan->num_output_glyphs ();
|
maxp_prime->numGlyphs = hb_min (c->plan->num_output_glyphs (), 0xFFFFu);
|
||||||
if (maxp_prime->version.major == 1)
|
if (maxp_prime->version.major == 1)
|
||||||
{
|
{
|
||||||
const maxpV1Tail *src_v1 = &StructAfter<maxpV1Tail> (*this);
|
const maxpV1Tail *src_v1 = &StructAfter<maxpV1Tail> (*this);
|
||||||
|
|
|
@ -181,6 +181,4 @@ 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);
|
return hb_ot_name_get_utf<hb_utf32_t> (face, name_id, language, text_size, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "hb-ot-name-language-static.hh"
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1067,12 +1067,15 @@ final_reordering_syllable_indic (const hb_ot_shape_plan_t *plan,
|
||||||
base = i;
|
base = i;
|
||||||
while (base < end && is_halant (info[base]))
|
while (base < end && is_halant (info[base]))
|
||||||
base++;
|
base++;
|
||||||
info[base].indic_position() = POS_BASE_C;
|
if (base < end)
|
||||||
|
info[base].indic_position() = POS_BASE_C;
|
||||||
|
|
||||||
try_pref = false;
|
try_pref = false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (base == end)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
/* For Malayalam, skip over unformed below- (but NOT post-) forms. */
|
/* For Malayalam, skip over unformed below- (but NOT post-) forms. */
|
||||||
if (buffer->props.script == HB_SCRIPT_MALAYALAM)
|
if (buffer->props.script == HB_SCRIPT_MALAYALAM)
|
||||||
|
|
|
@ -536,6 +536,8 @@ struct STAT
|
||||||
| hb_map (&AxisValue::get_value_name_id)
|
| hb_map (&AxisValue::get_value_name_id)
|
||||||
| hb_sink (nameids_to_retain)
|
| hb_sink (nameids_to_retain)
|
||||||
;
|
;
|
||||||
|
|
||||||
|
nameids_to_retain->add (elidedFallbackNameID);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
|
|
|
@ -222,18 +222,20 @@ struct DeltaSetIndexMap
|
||||||
|
|
||||||
struct VarStoreInstancer
|
struct VarStoreInstancer
|
||||||
{
|
{
|
||||||
VarStoreInstancer (const VariationStore &varStore,
|
VarStoreInstancer (const VariationStore *varStore,
|
||||||
const DeltaSetIndexMap &varIdxMap,
|
const DeltaSetIndexMap *varIdxMap,
|
||||||
hb_array_t<int> coords) :
|
hb_array_t<int> coords) :
|
||||||
varStore (varStore), varIdxMap (varIdxMap), coords (coords) {}
|
varStore (varStore), varIdxMap (varIdxMap), coords (coords) {}
|
||||||
|
|
||||||
operator bool () const { return bool (coords); }
|
operator bool () const { return varStore && 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
|
float operator() (uint32_t varIdx, unsigned short offset = 0) const
|
||||||
{ return varStore.get_delta (varIdxMap.map (VarIdx::add (varIdx, offset)), coords); }
|
{ return varStore->get_delta (varIdxMap ? varIdxMap->map (VarIdx::add (varIdx, offset)) : varIdx + offset, coords); }
|
||||||
|
|
||||||
const VariationStore &varStore;
|
const VariationStore *varStore;
|
||||||
const DeltaSetIndexMap &varIdxMap;
|
const DeltaSetIndexMap *varIdxMap;
|
||||||
hb_array_t<int> coords;
|
hb_array_t<int> coords;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -358,9 +360,12 @@ struct TupleVariationData
|
||||||
{
|
{
|
||||||
unsigned total_size = min_size;
|
unsigned total_size = min_size;
|
||||||
unsigned count = tupleVarCount;
|
unsigned count = tupleVarCount;
|
||||||
const TupleVariationHeader& tuple_var_header = get_tuple_var_header();
|
const TupleVariationHeader *tuple_var_header = &(get_tuple_var_header());
|
||||||
for (unsigned i = 0; i < count; i++)
|
for (unsigned i = 0; i < count; i++)
|
||||||
total_size += tuple_var_header.get_size (axis_count) + tuple_var_header.get_data_size ();
|
{
|
||||||
|
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;
|
return total_size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,8 +104,8 @@ struct gvar
|
||||||
return_trace (c->check_struct (this) && (version.major == 1) &&
|
return_trace (c->check_struct (this) && (version.major == 1) &&
|
||||||
sharedTuples.sanitize (c, this, axisCount * sharedTupleCount) &&
|
sharedTuples.sanitize (c, this, axisCount * sharedTupleCount) &&
|
||||||
(is_long_offset () ?
|
(is_long_offset () ?
|
||||||
c->check_array (get_long_offset_array (), glyphCount+1) :
|
c->check_array (get_long_offset_array (), c->get_num_glyphs () + 1) :
|
||||||
c->check_array (get_short_offset_array (), glyphCount+1)));
|
c->check_array (get_short_offset_array (), c->get_num_glyphs () + 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* GlyphVariationData not sanitized here; must be checked while accessing each glyph variation data */
|
/* GlyphVariationData not sanitized here; must be checked while accessing each glyph variation data */
|
||||||
|
@ -116,6 +116,8 @@ struct gvar
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
|
|
||||||
|
unsigned glyph_count = version.to_int () ? c->plan->source->get_num_glyphs () : 0;
|
||||||
|
|
||||||
gvar *out = c->serializer->allocate_min<gvar> ();
|
gvar *out = c->serializer->allocate_min<gvar> ();
|
||||||
if (unlikely (!out)) return_trace (false);
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
|
@ -125,7 +127,7 @@ struct gvar
|
||||||
out->sharedTupleCount = sharedTupleCount;
|
out->sharedTupleCount = sharedTupleCount;
|
||||||
|
|
||||||
unsigned int num_glyphs = c->plan->num_output_glyphs ();
|
unsigned int num_glyphs = c->plan->num_output_glyphs ();
|
||||||
out->glyphCount = num_glyphs;
|
out->glyphCountX = hb_min (0xFFFFu, num_glyphs);
|
||||||
|
|
||||||
unsigned int subset_data_size = 0;
|
unsigned int subset_data_size = 0;
|
||||||
for (hb_codepoint_t gid = (c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE) ? 0 : 1;
|
for (hb_codepoint_t gid = (c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE) ? 0 : 1;
|
||||||
|
@ -134,7 +136,7 @@ struct gvar
|
||||||
{
|
{
|
||||||
hb_codepoint_t old_gid;
|
hb_codepoint_t old_gid;
|
||||||
if (!c->plan->old_gid_for_new_gid (gid, &old_gid)) continue;
|
if (!c->plan->old_gid_for_new_gid (gid, &old_gid)) continue;
|
||||||
subset_data_size += get_glyph_var_data_bytes (c->source_blob, old_gid).length;
|
subset_data_size += get_glyph_var_data_bytes (c->source_blob, glyph_count, old_gid).length;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool long_offset = subset_data_size & ~0xFFFFu;
|
bool long_offset = subset_data_size & ~0xFFFFu;
|
||||||
|
@ -166,7 +168,9 @@ struct gvar
|
||||||
{
|
{
|
||||||
hb_codepoint_t old_gid;
|
hb_codepoint_t old_gid;
|
||||||
hb_bytes_t var_data_bytes = c->plan->old_gid_for_new_gid (gid, &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, old_gid)
|
? get_glyph_var_data_bytes (c->source_blob,
|
||||||
|
glyph_count,
|
||||||
|
old_gid)
|
||||||
: hb_bytes_t ();
|
: hb_bytes_t ();
|
||||||
|
|
||||||
if (long_offset)
|
if (long_offset)
|
||||||
|
@ -188,10 +192,12 @@ struct gvar
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const hb_bytes_t get_glyph_var_data_bytes (hb_blob_t *blob, hb_codepoint_t glyph) const
|
const hb_bytes_t get_glyph_var_data_bytes (hb_blob_t *blob,
|
||||||
|
unsigned glyph_count,
|
||||||
|
hb_codepoint_t glyph) const
|
||||||
{
|
{
|
||||||
unsigned start_offset = get_offset (glyph);
|
unsigned start_offset = get_offset (glyph_count, glyph);
|
||||||
unsigned end_offset = get_offset (glyph+1);
|
unsigned end_offset = get_offset (glyph_count, glyph+1);
|
||||||
if (unlikely (end_offset < start_offset)) return hb_bytes_t ();
|
if (unlikely (end_offset < start_offset)) return hb_bytes_t ();
|
||||||
unsigned length = end_offset - start_offset;
|
unsigned length = end_offset - start_offset;
|
||||||
hb_bytes_t var_data = blob->as_bytes ().sub_array (((unsigned) dataZ) + start_offset, length);
|
hb_bytes_t var_data = blob->as_bytes ().sub_array (((unsigned) dataZ) + start_offset, length);
|
||||||
|
@ -200,9 +206,9 @@ struct gvar
|
||||||
|
|
||||||
bool is_long_offset () const { return flags & 1; }
|
bool is_long_offset () const { return flags & 1; }
|
||||||
|
|
||||||
unsigned get_offset (unsigned i) const
|
unsigned get_offset (unsigned glyph_count, unsigned i) const
|
||||||
{
|
{
|
||||||
if (unlikely (i > glyphCount)) return 0;
|
if (unlikely (i > glyph_count)) return 0;
|
||||||
_hb_compiler_memory_r_barrier ();
|
_hb_compiler_memory_r_barrier ();
|
||||||
return is_long_offset () ? get_long_offset_array ()[i] : get_short_offset_array ()[i] * 2;
|
return is_long_offset () ? get_long_offset_array ()[i] : get_short_offset_array ()[i] * 2;
|
||||||
}
|
}
|
||||||
|
@ -214,7 +220,11 @@ struct gvar
|
||||||
struct accelerator_t
|
struct accelerator_t
|
||||||
{
|
{
|
||||||
accelerator_t (hb_face_t *face)
|
accelerator_t (hb_face_t *face)
|
||||||
{ table = hb_sanitize_context_t ().reference_table<gvar> (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;
|
||||||
|
}
|
||||||
~accelerator_t () { table.destroy (); }
|
~accelerator_t () { table.destroy (); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -252,9 +262,9 @@ struct gvar
|
||||||
{
|
{
|
||||||
if (!coords) return true;
|
if (!coords) return true;
|
||||||
|
|
||||||
if (unlikely (glyph >= table->glyphCount)) return true;
|
if (unlikely (glyph >= glyphCount)) return true;
|
||||||
|
|
||||||
hb_bytes_t var_data_bytes = table->get_glyph_var_data_bytes (table.get_blob (), glyph);
|
hb_bytes_t var_data_bytes = table->get_glyph_var_data_bytes (table.get_blob (), glyphCount, glyph);
|
||||||
if (!var_data_bytes.as<GlyphVariationData> ()->has_data ()) return true;
|
if (!var_data_bytes.as<GlyphVariationData> ()->has_data ()) return true;
|
||||||
hb_vector_t<unsigned int> shared_indices;
|
hb_vector_t<unsigned int> shared_indices;
|
||||||
GlyphVariationData::tuple_iterator_t iterator;
|
GlyphVariationData::tuple_iterator_t iterator;
|
||||||
|
@ -403,6 +413,7 @@ struct gvar
|
||||||
|
|
||||||
private:
|
private:
|
||||||
hb_blob_ptr_t<gvar> table;
|
hb_blob_ptr_t<gvar> table;
|
||||||
|
unsigned glyphCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -418,7 +429,7 @@ struct gvar
|
||||||
NNOffset32To<UnsizedArrayOf<F2DOT14>>
|
NNOffset32To<UnsizedArrayOf<F2DOT14>>
|
||||||
sharedTuples; /* Offset from the start of this table to the shared tuple records.
|
sharedTuples; /* Offset from the start of this table to the shared tuple records.
|
||||||
* Array of tuple records shared across all glyph variation data tables. */
|
* Array of tuple records shared across all glyph variation data tables. */
|
||||||
HBUINT16 glyphCount; /* The number of glyphs in this font. This must match the number of
|
HBUINT16 glyphCountX; /* The number of glyphs in this font. This must match the number of
|
||||||
* glyphs stored elsewhere in the font. */
|
* glyphs stored elsewhere in the font. */
|
||||||
HBUINT16 flags; /* Bit-field that gives the format of the offset array that follows.
|
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
|
* If bit 0 is clear, the offsets are uint16; if bit 0 is set, the
|
||||||
|
|
|
@ -265,6 +265,9 @@ struct HVARVVAR
|
||||||
rsbMap.sanitize (c, this));
|
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
|
void listup_index_maps (hb_vector_t<const DeltaSetIndexMap *> &index_maps) const
|
||||||
{
|
{
|
||||||
index_maps.push (&(this+advMap));
|
index_maps.push (&(this+advMap));
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
* Copyright © 2005 Werner Lemberg
|
* Copyright © 2005 Werner Lemberg
|
||||||
* Copyright © 2013-2015 Alexei Podtelezhnikov
|
* Copyright © 2013-2015 Alexei Podtelezhnikov
|
||||||
*
|
*
|
||||||
*
|
|
||||||
* This is part of HarfBuzz, a text shaping library.
|
* This is part of HarfBuzz, a text shaping library.
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, without written agreement and without
|
* Permission is hereby granted, without written agreement and without
|
||||||
|
|
|
@ -616,7 +616,7 @@ typedef enum {
|
||||||
HB_PAINT_COMPOSITE_MODE_HSL_HUE,
|
HB_PAINT_COMPOSITE_MODE_HSL_HUE,
|
||||||
HB_PAINT_COMPOSITE_MODE_HSL_SATURATION,
|
HB_PAINT_COMPOSITE_MODE_HSL_SATURATION,
|
||||||
HB_PAINT_COMPOSITE_MODE_HSL_COLOR,
|
HB_PAINT_COMPOSITE_MODE_HSL_COLOR,
|
||||||
HB_PAINT_COMPOSITE_MODE_HSL_LUMINOSITY,
|
HB_PAINT_COMPOSITE_MODE_HSL_LUMINOSITY
|
||||||
} hb_paint_composite_mode_t;
|
} hb_paint_composite_mode_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -203,8 +203,8 @@ struct hb_paint_funcs_t
|
||||||
if (!a)
|
if (!a)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
float cc = cosf (a * (float) M_PI);
|
float cc = cosf (a * HB_PI);
|
||||||
float ss = sinf (a * (float) M_PI);
|
float ss = sinf (a * HB_PI);
|
||||||
push_transform (paint_data, cc, ss, -ss, cc, 0.f, 0.f);
|
push_transform (paint_data, cc, ss, -ss, cc, 0.f, 0.f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -216,8 +216,8 @@ struct hb_paint_funcs_t
|
||||||
if (!sx && !sy)
|
if (!sx && !sy)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
float x = tanf (-sx * (float) M_PI);
|
float x = tanf (-sx * HB_PI);
|
||||||
float y = tanf (+sy * (float) M_PI);
|
float y = tanf (+sy * HB_PI);
|
||||||
push_transform (paint_data, 1.f, y, x, 1.f, 0.f, 0.f);
|
push_transform (paint_data, 1.f, y, x, 1.f, 0.f, 0.f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,16 @@
|
||||||
|
|
||||||
#include "hb.hh"
|
#include "hb.hh"
|
||||||
|
|
||||||
/* Memory pool for persistent allocation of small objects. */
|
/* Memory pool for persistent allocation of small objects.
|
||||||
|
*
|
||||||
|
* Some AI musings on this, not necessarily true:
|
||||||
|
*
|
||||||
|
* This is a very simple implementation, but it's good enough for our
|
||||||
|
* purposes. It's not thread-safe. It's not very fast. It's not
|
||||||
|
* very memory efficient. It's not very cache efficient. It's not
|
||||||
|
* very anything efficient. But it's simple and it works. And it's
|
||||||
|
* good enough for our purposes. If you need something more
|
||||||
|
* sophisticated, use a real allocator. Or use a real language. */
|
||||||
|
|
||||||
template <typename T, unsigned ChunkLen = 32>
|
template <typename T, unsigned ChunkLen = 32>
|
||||||
struct hb_pool_t
|
struct hb_pool_t
|
||||||
|
|
|
@ -35,6 +35,12 @@
|
||||||
*
|
*
|
||||||
* Priority queue implemented as a binary heap. Supports extract minimum
|
* Priority queue implemented as a binary heap. Supports extract minimum
|
||||||
* and insert operations.
|
* and insert operations.
|
||||||
|
*
|
||||||
|
* The priority queue is implemented as a binary heap, which is a complete
|
||||||
|
* binary tree. The root of the tree is the minimum element. The heap
|
||||||
|
* property is that the priority of a node is less than or equal to the
|
||||||
|
* priority of its children. The heap is stored in an array, with the
|
||||||
|
* children of node i stored at indices 2i + 1 and 2i + 2.
|
||||||
*/
|
*/
|
||||||
struct hb_priority_queue_t
|
struct hb_priority_queue_t
|
||||||
{
|
{
|
||||||
|
|
|
@ -271,9 +271,13 @@ hb_shape_justify (hb_font_t *font,
|
||||||
|
|
||||||
/* If default advance already matches target, nothing to do. Shape and return. */
|
/* If default advance already matches target, nothing to do. Shape and return. */
|
||||||
if (min_target_advance <= *advance && *advance <= max_target_advance)
|
if (min_target_advance <= *advance && *advance <= max_target_advance)
|
||||||
|
{
|
||||||
|
*var_tag = HB_TAG_NONE;
|
||||||
|
*var_value = 0.0f;
|
||||||
return hb_shape_full (font, buffer,
|
return hb_shape_full (font, buffer,
|
||||||
features, num_features,
|
features, num_features,
|
||||||
shaper_list);
|
shaper_list);
|
||||||
|
}
|
||||||
|
|
||||||
hb_face_t *face = font->face;
|
hb_face_t *face = font->face;
|
||||||
|
|
||||||
|
@ -297,6 +301,8 @@ hb_shape_justify (hb_font_t *font,
|
||||||
/* If no suitable variation axis found, can't justify. Just shape and return. */
|
/* If no suitable variation axis found, can't justify. Just shape and return. */
|
||||||
if (!tag)
|
if (!tag)
|
||||||
{
|
{
|
||||||
|
*var_tag = HB_TAG_NONE;
|
||||||
|
*var_value = 0.0f;
|
||||||
if (hb_shape_full (font, buffer,
|
if (hb_shape_full (font, buffer,
|
||||||
features, num_features,
|
features, num_features,
|
||||||
shaper_list))
|
shaper_list))
|
||||||
|
@ -331,7 +337,11 @@ hb_shape_justify (hb_font_t *font,
|
||||||
* Do this again, in case advance was just calculated.
|
* Do this again, in case advance was just calculated.
|
||||||
*/
|
*/
|
||||||
if (min_target_advance <= *advance && *advance <= max_target_advance)
|
if (min_target_advance <= *advance && *advance <= max_target_advance)
|
||||||
|
{
|
||||||
|
*var_tag = HB_TAG_NONE;
|
||||||
|
*var_value = 0.0f;
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Prepare for running the solver. */
|
/* Prepare for running the solver. */
|
||||||
double a, b, ya, yb;
|
double a, b, ya, yb;
|
||||||
|
@ -355,6 +365,7 @@ hb_shape_justify (hb_font_t *font,
|
||||||
* there's nothing to solve for. Just return it. */
|
* there's nothing to solve for. Just return it. */
|
||||||
if (yb <= (double) max_target_advance)
|
if (yb <= (double) max_target_advance)
|
||||||
{
|
{
|
||||||
|
*var_value = (float) b;
|
||||||
*advance = (float) yb;
|
*advance = (float) yb;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -379,6 +390,7 @@ hb_shape_justify (hb_font_t *font,
|
||||||
* there's nothing to solve for. Just return it. */
|
* there's nothing to solve for. Just return it. */
|
||||||
if (ya >= (double) min_target_advance)
|
if (ya >= (double) min_target_advance)
|
||||||
{
|
{
|
||||||
|
*var_value = (float) a;
|
||||||
*advance = (float) ya;
|
*advance = (float) ya;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,9 +36,11 @@
|
||||||
#include "OT/Color/COLR/COLR.hh"
|
#include "OT/Color/COLR/COLR.hh"
|
||||||
#include "hb-ot-glyf-table.hh"
|
#include "hb-ot-glyf-table.hh"
|
||||||
#include "hb-ot-head-table.hh"
|
#include "hb-ot-head-table.hh"
|
||||||
|
#include "hb-ot-hmtx-table.hh"
|
||||||
#include "hb-ot-maxp-table.hh"
|
#include "hb-ot-maxp-table.hh"
|
||||||
|
|
||||||
#ifndef HB_NO_VISIBILITY
|
#ifndef HB_NO_VISIBILITY
|
||||||
|
#include "hb-ot-name-language-static.hh"
|
||||||
|
|
||||||
uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {};
|
uint64_t const _hb_NullPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {};
|
||||||
/*thread_local*/ uint64_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {};
|
/*thread_local*/ uint64_t _hb_CrapPool[(HB_NULL_POOL_SIZE + sizeof (uint64_t) - 1) / sizeof (uint64_t)] = {};
|
||||||
|
@ -108,4 +110,26 @@ hb_face_t::load_upem () const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
bool
|
||||||
|
_glyf_get_leading_bearing_without_var_unscaled (hb_face_t *face, hb_codepoint_t gid, bool is_vertical, int *lsb)
|
||||||
|
{
|
||||||
|
return face->table.glyf->get_leading_bearing_without_var_unscaled (gid, is_vertical, lsb);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -46,13 +46,13 @@
|
||||||
static inline float
|
static inline float
|
||||||
_hb_angle_to_ratio (float a)
|
_hb_angle_to_ratio (float a)
|
||||||
{
|
{
|
||||||
return tanf (a * float (-M_PI / 180.));
|
return tanf (a * -HB_PI / 180.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline float
|
static inline float
|
||||||
_hb_ratio_to_angle (float r)
|
_hb_ratio_to_angle (float r)
|
||||||
{
|
{
|
||||||
return atanf (r) * float (-180. / M_PI);
|
return atanf (r) * -180.f / HB_PI;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -125,7 +125,7 @@ _solve (Triple tent, Triple axisLimit, bool negative = false)
|
||||||
return result_t{}; // No overlap
|
return result_t{}; // No overlap
|
||||||
|
|
||||||
/* case 2: Only the peak and outermost bound fall outside the new limit;
|
/* case 2: Only the peak and outermost bound fall outside the new limit;
|
||||||
* we keep the deltaset, update peak and outermost bound and and scale deltas
|
* we keep the deltaset, update peak and outermost bound and scale deltas
|
||||||
* by the scalar value for the restricted axis at the new limit, and solve
|
* by the scalar value for the restricted axis at the new limit, and solve
|
||||||
* recursively.
|
* recursively.
|
||||||
*
|
*
|
||||||
|
|
|
@ -36,8 +36,10 @@
|
||||||
#include "hb-ot-layout-gpos-table.hh"
|
#include "hb-ot-layout-gpos-table.hh"
|
||||||
#include "hb-ot-layout-gsub-table.hh"
|
#include "hb-ot-layout-gsub-table.hh"
|
||||||
#include "hb-ot-cff1-table.hh"
|
#include "hb-ot-cff1-table.hh"
|
||||||
|
#include "hb-ot-cff2-table.hh"
|
||||||
#include "OT/Color/COLR/COLR.hh"
|
#include "OT/Color/COLR/COLR.hh"
|
||||||
#include "OT/Color/COLR/colrv1-closure.hh"
|
#include "OT/Color/COLR/colrv1-closure.hh"
|
||||||
|
#include "OT/Color/CPAL/CPAL.hh"
|
||||||
#include "hb-ot-var-fvar-table.hh"
|
#include "hb-ot-var-fvar-table.hh"
|
||||||
#include "hb-ot-var-avar-table.hh"
|
#include "hb-ot-var-avar-table.hh"
|
||||||
#include "hb-ot-stat-table.hh"
|
#include "hb-ot-stat-table.hh"
|
||||||
|
@ -293,7 +295,7 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan,
|
||||||
feature_record_cond_idx_map,
|
feature_record_cond_idx_map,
|
||||||
feature_substitutes_map);
|
feature_substitutes_map);
|
||||||
|
|
||||||
if (table_tag == HB_OT_TAG_GSUB)
|
if (table_tag == HB_OT_TAG_GSUB && !(plan->flags & HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE))
|
||||||
hb_ot_layout_lookups_substitute_closure (plan->source,
|
hb_ot_layout_lookups_substitute_closure (plan->source,
|
||||||
&lookup_indices,
|
&lookup_indices,
|
||||||
gids_to_retain);
|
gids_to_retain);
|
||||||
|
@ -345,7 +347,10 @@ _get_hb_font_with_variations (const hb_subset_plan_t *plan)
|
||||||
hb_font_t *font = hb_font_create (plan->source);
|
hb_font_t *font = hb_font_create (plan->source);
|
||||||
|
|
||||||
hb_vector_t<hb_variation_t> vars;
|
hb_vector_t<hb_variation_t> vars;
|
||||||
vars.alloc (plan->user_axes_location.get_population ());
|
if (!vars.alloc (plan->user_axes_location.get_population ())) {
|
||||||
|
hb_font_destroy (font);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto _ : plan->user_axes_location)
|
for (auto _ : plan->user_axes_location)
|
||||||
{
|
{
|
||||||
|
@ -381,7 +386,13 @@ _collect_layout_variation_indices (hb_subset_plan_t* plan)
|
||||||
bool collect_delta = plan->pinned_at_default ? false : true;
|
bool collect_delta = plan->pinned_at_default ? false : true;
|
||||||
if (collect_delta)
|
if (collect_delta)
|
||||||
{
|
{
|
||||||
font = _get_hb_font_with_variations (plan);
|
if (unlikely (!plan->check_success (font = _get_hb_font_with_variations (plan)))) {
|
||||||
|
hb_font_destroy (font);
|
||||||
|
gdef.destroy ();
|
||||||
|
gpos.destroy ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (gdef->has_var_store ())
|
if (gdef->has_var_store ())
|
||||||
{
|
{
|
||||||
var_store = &(gdef->get_var_store ());
|
var_store = &(gdef->get_var_store ());
|
||||||
|
@ -555,9 +566,12 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
|
||||||
if (plan->codepoint_to_glyph->has (cp))
|
if (plan->codepoint_to_glyph->has (cp))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
|
hb_codepoint_t *gid;
|
||||||
plan->codepoint_to_glyph->set (cp, gid);
|
if (!unicode_glyphid_map->has(cp, &gid))
|
||||||
plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
|
continue;
|
||||||
|
|
||||||
|
plan->codepoint_to_glyph->set (cp, *gid);
|
||||||
|
plan->unicode_to_new_gid_list.push (hb_pair (cp, *gid));
|
||||||
}
|
}
|
||||||
plan->unicode_to_new_gid_list.qsort ();
|
plan->unicode_to_new_gid_list.qsort ();
|
||||||
}
|
}
|
||||||
|
@ -609,7 +623,7 @@ _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf,
|
||||||
|
|
||||||
gids_to_retain->add (gid);
|
gids_to_retain->add (gid);
|
||||||
|
|
||||||
for (auto item : glyf.glyph_for_gid (gid).get_composite_iterator ())
|
for (auto &item : glyf.glyph_for_gid (gid).get_composite_iterator ())
|
||||||
operation_count =
|
operation_count =
|
||||||
_glyf_add_gid_and_children (glyf,
|
_glyf_add_gid_and_children (glyf,
|
||||||
item.get_gid (),
|
item.get_gid (),
|
||||||
|
@ -617,9 +631,53 @@ _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf,
|
||||||
operation_count,
|
operation_count,
|
||||||
depth);
|
depth);
|
||||||
|
|
||||||
|
#ifndef HB_NO_VAR_COMPOSITES
|
||||||
|
for (auto &item : glyf.glyph_for_gid (gid).get_var_composite_iterator ())
|
||||||
|
{
|
||||||
|
operation_count =
|
||||||
|
_glyf_add_gid_and_children (glyf,
|
||||||
|
item.get_gid (),
|
||||||
|
gids_to_retain,
|
||||||
|
operation_count,
|
||||||
|
depth);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return operation_count;
|
return operation_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_nameid_closure (hb_subset_plan_t* plan,
|
||||||
|
hb_set_t* drop_tables)
|
||||||
|
{
|
||||||
|
#ifndef HB_NO_STYLE
|
||||||
|
plan->source->table.STAT->collect_name_ids (&plan->user_axes_location, &plan->name_ids);
|
||||||
|
#endif
|
||||||
|
#ifndef HB_NO_VAR
|
||||||
|
if (!plan->all_axes_pinned)
|
||||||
|
plan->source->table.fvar->collect_name_ids (&plan->user_axes_location, &plan->name_ids);
|
||||||
|
#endif
|
||||||
|
#ifndef HB_NO_COLOR
|
||||||
|
if (!drop_tables->has (HB_OT_TAG_CPAL))
|
||||||
|
plan->source->table.CPAL->collect_name_ids (&plan->colr_palettes, &plan->name_ids);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_NO_SUBSET_LAYOUT
|
||||||
|
if (!drop_tables->has (HB_OT_TAG_GPOS))
|
||||||
|
{
|
||||||
|
hb_blob_ptr_t<GPOS> gpos = plan->source_table<GPOS> ();
|
||||||
|
gpos->collect_name_ids (&plan->gpos_features, &plan->name_ids);
|
||||||
|
gpos.destroy ();
|
||||||
|
}
|
||||||
|
if (!drop_tables->has (HB_OT_TAG_GSUB))
|
||||||
|
{
|
||||||
|
hb_blob_ptr_t<GSUB> gsub = plan->source_table<GSUB> ();
|
||||||
|
gsub->collect_name_ids (&plan->gsub_features, &plan->name_ids);
|
||||||
|
gsub.destroy ();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_populate_gids_to_retain (hb_subset_plan_t* plan,
|
_populate_gids_to_retain (hb_subset_plan_t* plan,
|
||||||
hb_set_t* drop_tables)
|
hb_set_t* drop_tables)
|
||||||
|
@ -673,6 +731,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
|
||||||
|
|
||||||
plan->_glyphset_colred = cur_glyphset;
|
plan->_glyphset_colred = cur_glyphset;
|
||||||
|
|
||||||
|
_nameid_closure (plan, drop_tables);
|
||||||
/* Populate a full set of glyphs to retain by adding all referenced
|
/* Populate a full set of glyphs to retain by adding all referenced
|
||||||
* composite glyphs. */
|
* composite glyphs. */
|
||||||
if (glyf.has_data ())
|
if (glyf.has_data ())
|
||||||
|
@ -756,21 +815,6 @@ _create_old_gid_to_new_gid_map (const hb_face_t *face,
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
_nameid_closure (hb_face_t *face,
|
|
||||||
hb_set_t *nameids,
|
|
||||||
bool all_axes_pinned,
|
|
||||||
hb_hashmap_t<hb_tag_t, float> *user_axes_location)
|
|
||||||
{
|
|
||||||
#ifndef HB_NO_STYLE
|
|
||||||
face->table.STAT->collect_name_ids (user_axes_location, nameids);
|
|
||||||
#endif
|
|
||||||
#ifndef HB_NO_VAR
|
|
||||||
if (!all_axes_pinned)
|
|
||||||
face->table.fvar->collect_name_ids (user_axes_location, nameids);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef HB_NO_VAR
|
#ifndef HB_NO_VAR
|
||||||
static void
|
static void
|
||||||
_normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
|
_normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
|
||||||
|
@ -783,12 +827,15 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
|
||||||
|
|
||||||
bool has_avar = face->table.avar->has_data ();
|
bool has_avar = face->table.avar->has_data ();
|
||||||
const OT::SegmentMaps *seg_maps = nullptr;
|
const OT::SegmentMaps *seg_maps = nullptr;
|
||||||
|
unsigned avar_axis_count = 0;
|
||||||
if (has_avar)
|
if (has_avar)
|
||||||
|
{
|
||||||
seg_maps = face->table.avar->get_segment_maps ();
|
seg_maps = face->table.avar->get_segment_maps ();
|
||||||
|
avar_axis_count = face->table.avar->get_axis_count();
|
||||||
|
}
|
||||||
|
|
||||||
bool axis_not_pinned = false;
|
bool axis_not_pinned = false;
|
||||||
unsigned old_axis_idx = 0, new_axis_idx = 0;
|
unsigned old_axis_idx = 0, new_axis_idx = 0;
|
||||||
unsigned int i = 0;
|
|
||||||
for (const auto& axis : axes)
|
for (const auto& axis : axes)
|
||||||
{
|
{
|
||||||
hb_tag_t axis_tag = axis.get_axis_tag ();
|
hb_tag_t axis_tag = axis.get_axis_tag ();
|
||||||
|
@ -803,7 +850,7 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int normalized_v = axis.normalize_axis_value (plan->user_axes_location.get (axis_tag));
|
int normalized_v = axis.normalize_axis_value (plan->user_axes_location.get (axis_tag));
|
||||||
if (has_avar && old_axis_idx < face->table.avar->get_axis_count ())
|
if (has_avar && old_axis_idx < avar_axis_count)
|
||||||
{
|
{
|
||||||
normalized_v = seg_maps->map (normalized_v);
|
normalized_v = seg_maps->map (normalized_v);
|
||||||
}
|
}
|
||||||
|
@ -811,17 +858,99 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
|
||||||
if (normalized_v != 0)
|
if (normalized_v != 0)
|
||||||
plan->pinned_at_default = false;
|
plan->pinned_at_default = false;
|
||||||
|
|
||||||
plan->normalized_coords[i] = normalized_v;
|
plan->normalized_coords[old_axis_idx] = normalized_v;
|
||||||
}
|
}
|
||||||
if (has_avar)
|
|
||||||
seg_maps = &StructAfter<OT::SegmentMaps> (*seg_maps);
|
|
||||||
|
|
||||||
old_axis_idx++;
|
old_axis_idx++;
|
||||||
|
|
||||||
i++;
|
if (has_avar && old_axis_idx < avar_axis_count)
|
||||||
|
seg_maps = &StructAfter<OT::SegmentMaps> (*seg_maps);
|
||||||
}
|
}
|
||||||
plan->all_axes_pinned = !axis_not_pinned;
|
plan->all_axes_pinned = !axis_not_pinned;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan)
|
||||||
|
{
|
||||||
|
if (!plan->normalized_coords) return;
|
||||||
|
OT::cff2::accelerator_t cff2 (plan->source);
|
||||||
|
if (!cff2.is_valid ()) return;
|
||||||
|
|
||||||
|
hb_font_t *font = nullptr;
|
||||||
|
if (unlikely (!plan->check_success (font = _get_hb_font_with_variations (plan))))
|
||||||
|
{
|
||||||
|
hb_font_destroy (font);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_glyph_extents_t extents = {0x7FFF, -0x7FFF};
|
||||||
|
OT::hmtx_accelerator_t _hmtx (plan->source);
|
||||||
|
float *hvar_store_cache = nullptr;
|
||||||
|
if (_hmtx.has_data () && _hmtx.var_table.get_length ())
|
||||||
|
hvar_store_cache = _hmtx.var_table->get_var_store ().create_cache ();
|
||||||
|
|
||||||
|
OT::vmtx_accelerator_t _vmtx (plan->source);
|
||||||
|
float *vvar_store_cache = nullptr;
|
||||||
|
if (_vmtx.has_data () && _vmtx.var_table.get_length ())
|
||||||
|
vvar_store_cache = _vmtx.var_table->get_var_store ().create_cache ();
|
||||||
|
|
||||||
|
for (auto p : *plan->glyph_map)
|
||||||
|
{
|
||||||
|
hb_codepoint_t old_gid = p.first;
|
||||||
|
hb_codepoint_t new_gid = p.second;
|
||||||
|
if (!cff2.get_extents (font, old_gid, &extents)) continue;
|
||||||
|
bool has_bounds_info = true;
|
||||||
|
if (extents.x_bearing == 0 && extents.width == 0 &&
|
||||||
|
extents.height == 0 && extents.y_bearing == 0)
|
||||||
|
has_bounds_info = false;
|
||||||
|
|
||||||
|
if (has_bounds_info)
|
||||||
|
{
|
||||||
|
plan->head_maxp_info.xMin = hb_min (plan->head_maxp_info.xMin, extents.x_bearing);
|
||||||
|
plan->head_maxp_info.xMax = hb_max (plan->head_maxp_info.xMax, extents.x_bearing + extents.width);
|
||||||
|
plan->head_maxp_info.yMax = hb_max (plan->head_maxp_info.yMax, extents.y_bearing);
|
||||||
|
plan->head_maxp_info.yMin = hb_min (plan->head_maxp_info.yMin, extents.y_bearing + extents.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_hmtx.has_data ())
|
||||||
|
{
|
||||||
|
int hori_aw = _hmtx.get_advance_without_var_unscaled (old_gid);
|
||||||
|
if (_hmtx.var_table.get_length ())
|
||||||
|
hori_aw += (int) roundf (_hmtx.var_table->get_advance_delta_unscaled (old_gid, font->coords, font->num_coords,
|
||||||
|
hvar_store_cache));
|
||||||
|
int lsb = extents.x_bearing;
|
||||||
|
if (!has_bounds_info)
|
||||||
|
{
|
||||||
|
if (!_hmtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb));
|
||||||
|
plan->bounds_width_map.set (new_gid, extents.width);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_vmtx.has_data ())
|
||||||
|
{
|
||||||
|
int vert_aw = _vmtx.get_advance_without_var_unscaled (old_gid);
|
||||||
|
if (_vmtx.var_table.get_length ())
|
||||||
|
vert_aw += (int) roundf (_vmtx.var_table->get_advance_delta_unscaled (old_gid, font->coords, font->num_coords,
|
||||||
|
vvar_store_cache));
|
||||||
|
|
||||||
|
int tsb = extents.y_bearing;
|
||||||
|
if (!has_bounds_info)
|
||||||
|
{
|
||||||
|
if (!_vmtx.get_leading_bearing_without_var_unscaled (old_gid, &tsb))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
plan->vmtx_map.set (new_gid, hb_pair ((unsigned) vert_aw, tsb));
|
||||||
|
plan->bounds_height_map.set (new_gid, extents.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hb_font_destroy (font);
|
||||||
|
if (hvar_store_cache)
|
||||||
|
_hmtx.var_table->get_var_store ().destroy_cache (hvar_store_cache);
|
||||||
|
if (vvar_store_cache)
|
||||||
|
_vmtx.var_table->get_var_store ().destroy_cache (vvar_store_cache);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
|
hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
|
||||||
|
@ -884,6 +1013,8 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
|
||||||
_populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, this);
|
_populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, this);
|
||||||
|
|
||||||
_populate_gids_to_retain (this, input->sets.drop_tables);
|
_populate_gids_to_retain (this, input->sets.drop_tables);
|
||||||
|
if (unlikely (in_error ()))
|
||||||
|
return;
|
||||||
|
|
||||||
_create_old_gid_to_new_gid_map (face,
|
_create_old_gid_to_new_gid_map (face,
|
||||||
input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS,
|
input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS,
|
||||||
|
@ -905,10 +1036,13 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
|
||||||
glyph_map->get(unicode_to_new_gid_list.arrayZ[i].second);
|
glyph_map->get(unicode_to_new_gid_list.arrayZ[i].second);
|
||||||
}
|
}
|
||||||
|
|
||||||
_nameid_closure (face, &name_ids, all_axes_pinned, &user_axes_location);
|
|
||||||
if (unlikely (in_error ()))
|
if (unlikely (in_error ()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#ifndef HB_NO_VAR
|
||||||
|
_update_instance_metrics_map_from_cff2 (this);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (attach_accelerator_data)
|
if (attach_accelerator_data)
|
||||||
{
|
{
|
||||||
hb_multimap_t gid_to_unicodes;
|
hb_multimap_t gid_to_unicodes;
|
||||||
|
|
|
@ -211,7 +211,7 @@ struct hb_subset_plan_t
|
||||||
template<typename T>
|
template<typename T>
|
||||||
hb_blob_ptr_t<T> source_table()
|
hb_blob_ptr_t<T> source_table()
|
||||||
{
|
{
|
||||||
hb_lock_t (accelerator ? &accelerator->sanitized_table_cache_lock : nullptr);
|
hb_lock_t lock (accelerator ? &accelerator->sanitized_table_cache_lock : nullptr);
|
||||||
|
|
||||||
auto *cache = accelerator ? &accelerator->sanitized_table_cache : &sanitized_table_cache;
|
auto *cache = accelerator ? &accelerator->sanitized_table_cache : &sanitized_table_cache;
|
||||||
if (cache
|
if (cache
|
||||||
|
|
|
@ -637,8 +637,3 @@ hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
|
||||||
end:
|
end:
|
||||||
return success ? hb_face_reference (plan->dest) : nullptr;
|
return success ? hb_face_reference (plan->dest) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef HB_NO_VISIBILITY
|
|
||||||
/* If NO_VISIBILITY, libharfbuzz has this. */
|
|
||||||
#include "hb-ot-name-language-static.hh"
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -71,6 +71,8 @@ typedef struct hb_subset_plan_t hb_subset_plan_t;
|
||||||
* in the final subset.
|
* in the final subset.
|
||||||
* @HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES: If set then the unicode ranges in
|
* @HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES: If set then the unicode ranges in
|
||||||
* OS/2 will not be recalculated.
|
* OS/2 will not be recalculated.
|
||||||
|
* @HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE: If set don't perform glyph closure on layout
|
||||||
|
* substitution rules (GSUB).
|
||||||
*
|
*
|
||||||
* List of boolean properties that can be configured on the subset input.
|
* List of boolean properties that can be configured on the subset input.
|
||||||
*
|
*
|
||||||
|
@ -87,6 +89,7 @@ typedef enum { /*< flags >*/
|
||||||
HB_SUBSET_FLAGS_NOTDEF_OUTLINE = 0x00000040u,
|
HB_SUBSET_FLAGS_NOTDEF_OUTLINE = 0x00000040u,
|
||||||
HB_SUBSET_FLAGS_GLYPH_NAMES = 0x00000080u,
|
HB_SUBSET_FLAGS_GLYPH_NAMES = 0x00000080u,
|
||||||
HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES = 0x00000100u,
|
HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES = 0x00000100u,
|
||||||
|
HB_SUBSET_FLAGS_NO_LAYOUT_CLOSURE = 0x00000200u,
|
||||||
} hb_subset_flags_t;
|
} hb_subset_flags_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -509,6 +509,12 @@ static_assert ((sizeof (hb_mask_t) == 4), "");
|
||||||
static_assert ((sizeof (hb_var_int_t) == 4), "");
|
static_assert ((sizeof (hb_var_int_t) == 4), "");
|
||||||
|
|
||||||
|
|
||||||
|
/* Pie time. */
|
||||||
|
// https://github.com/harfbuzz/harfbuzz/issues/4166
|
||||||
|
#define HB_PI 3.14159265358979f
|
||||||
|
#define HB_2_PI (2.f * HB_PI)
|
||||||
|
|
||||||
|
|
||||||
/* Headers we include for everyone. Keep topologically sorted by dependency.
|
/* Headers we include for everyone. Keep topologically sorted by dependency.
|
||||||
* They express dependency amongst themselves, but no other file should include
|
* They express dependency amongst themselves, but no other file should include
|
||||||
* them directly.*/
|
* them directly.*/
|
||||||
|
|
|
@ -0,0 +1,288 @@
|
||||||
|
import gi
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "3.0")
|
||||||
|
from gi.repository import Gtk, HarfBuzz as hb
|
||||||
|
|
||||||
|
|
||||||
|
POOL = {}
|
||||||
|
|
||||||
|
|
||||||
|
def move_to_f(funcs, draw_data, st, to_x, to_y, user_data):
|
||||||
|
context = POOL[draw_data]
|
||||||
|
context.move_to(to_x, to_y)
|
||||||
|
|
||||||
|
|
||||||
|
def line_to_f(funcs, draw_data, st, to_x, to_y, user_data):
|
||||||
|
context = POOL[draw_data]
|
||||||
|
context.line_to(to_x, to_y)
|
||||||
|
|
||||||
|
|
||||||
|
def cubic_to_f(
|
||||||
|
funcs,
|
||||||
|
draw_data,
|
||||||
|
st,
|
||||||
|
control1_x,
|
||||||
|
control1_y,
|
||||||
|
control2_x,
|
||||||
|
control2_y,
|
||||||
|
to_x,
|
||||||
|
to_y,
|
||||||
|
user_data,
|
||||||
|
):
|
||||||
|
context = POOL[draw_data]
|
||||||
|
context.curve_to(control1_x, control1_y, control2_x, control2_y, to_x, to_y)
|
||||||
|
|
||||||
|
|
||||||
|
def close_path_f(funcs, draw_data, st, user_data):
|
||||||
|
context = POOL[draw_data]
|
||||||
|
context.close_path()
|
||||||
|
|
||||||
|
|
||||||
|
DFUNCS = hb.draw_funcs_create()
|
||||||
|
hb.draw_funcs_set_move_to_func(DFUNCS, move_to_f, None)
|
||||||
|
hb.draw_funcs_set_line_to_func(DFUNCS, line_to_f, None)
|
||||||
|
hb.draw_funcs_set_cubic_to_func(DFUNCS, cubic_to_f, None)
|
||||||
|
hb.draw_funcs_set_close_path_func(DFUNCS, close_path_f, None)
|
||||||
|
|
||||||
|
|
||||||
|
def push_transform_f(funcs, paint_data, xx, yx, xy, yy, dx, dy, user_data):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
def pop_transform_f(funcs, paint_data, user_data):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
def color_f(funcs, paint_data, is_foreground, color, user_data):
|
||||||
|
context = POOL[paint_data]
|
||||||
|
r = hb.color_get_red(color) / 255
|
||||||
|
g = hb.color_get_green(color) / 255
|
||||||
|
b = hb.color_get_blue(color) / 255
|
||||||
|
a = hb.color_get_alpha(color) / 255
|
||||||
|
context.set_source_rgba(r, g, b, a)
|
||||||
|
context.paint()
|
||||||
|
|
||||||
|
|
||||||
|
def push_clip_rectangle_f(funcs, paint_data, xmin, ymin, xmax, ymax, user_data):
|
||||||
|
context = POOL[paint_data]
|
||||||
|
context.save()
|
||||||
|
context.rectangle(xmin, ymin, xmax, ymax)
|
||||||
|
context.clip()
|
||||||
|
|
||||||
|
|
||||||
|
def push_clip_glyph_f(funcs, paint_data, glyph, font, user_data):
|
||||||
|
context = POOL[paint_data]
|
||||||
|
context.save()
|
||||||
|
context.new_path()
|
||||||
|
hb.font_draw_glyph(font, glyph, DFUNCS, paint_data)
|
||||||
|
context.close_path()
|
||||||
|
context.clip()
|
||||||
|
|
||||||
|
|
||||||
|
def pop_clip_f(funcs, paint_data, user_data):
|
||||||
|
context = POOL[paint_data]
|
||||||
|
context.restore()
|
||||||
|
|
||||||
|
|
||||||
|
def push_group_f(funcs, paint_data, user_data):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
def pop_group_f(funcs, paint_data, mode, user_data):
|
||||||
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
|
PFUNCS = hb.paint_funcs_create()
|
||||||
|
hb.paint_funcs_set_push_transform_func(PFUNCS, push_transform_f, None)
|
||||||
|
hb.paint_funcs_set_pop_transform_func(PFUNCS, pop_transform_f, None)
|
||||||
|
hb.paint_funcs_set_color_func(PFUNCS, color_f, None)
|
||||||
|
hb.paint_funcs_set_push_clip_glyph_func(PFUNCS, push_clip_glyph_f, None)
|
||||||
|
hb.paint_funcs_set_push_clip_rectangle_func(PFUNCS, push_clip_rectangle_f, None)
|
||||||
|
hb.paint_funcs_set_pop_clip_func(PFUNCS, pop_clip_f, None)
|
||||||
|
hb.paint_funcs_set_push_group_func(PFUNCS, push_group_f, None)
|
||||||
|
hb.paint_funcs_set_pop_group_func(PFUNCS, pop_group_f, None)
|
||||||
|
|
||||||
|
|
||||||
|
def makebuffer(words):
|
||||||
|
buf = hb.buffer_create()
|
||||||
|
|
||||||
|
text = " ".join(words)
|
||||||
|
hb.buffer_add_codepoints(buf, [ord(c) for c in text], 0, len(text))
|
||||||
|
|
||||||
|
hb.buffer_guess_segment_properties(buf)
|
||||||
|
|
||||||
|
return buf
|
||||||
|
|
||||||
|
|
||||||
|
def justify(face, words, advance, target_advance):
|
||||||
|
font = hb.font_create(face)
|
||||||
|
buf = makebuffer(words)
|
||||||
|
|
||||||
|
wiggle = 5
|
||||||
|
shrink = target_advance - wiggle < advance
|
||||||
|
expand = target_advance + wiggle > advance
|
||||||
|
|
||||||
|
ret, advance, tag, value = hb.shape_justify(
|
||||||
|
font,
|
||||||
|
buf,
|
||||||
|
None,
|
||||||
|
None,
|
||||||
|
target_advance,
|
||||||
|
target_advance,
|
||||||
|
advance,
|
||||||
|
)
|
||||||
|
|
||||||
|
if not ret:
|
||||||
|
return False, buf, None
|
||||||
|
|
||||||
|
if tag:
|
||||||
|
variation = hb.variation_t()
|
||||||
|
variation.tag = tag
|
||||||
|
variation.value = value
|
||||||
|
else:
|
||||||
|
variation = None
|
||||||
|
|
||||||
|
if shrink and advance > target_advance + wiggle:
|
||||||
|
return False, buf, variation
|
||||||
|
if expand and advance < target_advance - wiggle:
|
||||||
|
return False, buf, variation
|
||||||
|
|
||||||
|
return True, buf, variation
|
||||||
|
|
||||||
|
|
||||||
|
def shape(face, words):
|
||||||
|
font = hb.font_create(face)
|
||||||
|
buf = makebuffer(words)
|
||||||
|
hb.shape(font, buf)
|
||||||
|
positions = hb.buffer_get_glyph_positions(buf)
|
||||||
|
advance = sum(p.x_advance for p in positions)
|
||||||
|
return buf, advance
|
||||||
|
|
||||||
|
|
||||||
|
def typeset(face, text, target_advance):
|
||||||
|
lines = []
|
||||||
|
words = []
|
||||||
|
for word in text.split():
|
||||||
|
words.append(word)
|
||||||
|
buf, advance = shape(face, words)
|
||||||
|
if advance > target_advance:
|
||||||
|
# Shrink
|
||||||
|
ret, buf, variation = justify(face, words, advance, target_advance)
|
||||||
|
if ret:
|
||||||
|
lines.append((buf, variation))
|
||||||
|
words = []
|
||||||
|
# If if fails, pop the last word and shrink, and hope for the best.
|
||||||
|
# A too short line is better than too long.
|
||||||
|
elif len(words) > 1:
|
||||||
|
words.pop()
|
||||||
|
_, buf, variation = justify(face, words, advance, target_advance)
|
||||||
|
lines.append((buf, variation))
|
||||||
|
words = [word]
|
||||||
|
# But if it is one word, meh.
|
||||||
|
else:
|
||||||
|
lines.append((buf, variation))
|
||||||
|
words = []
|
||||||
|
|
||||||
|
# Justify last line
|
||||||
|
if words:
|
||||||
|
_, buf, variation = justify(face, words, advance, target_advance)
|
||||||
|
lines.append((buf, variation))
|
||||||
|
|
||||||
|
return lines
|
||||||
|
|
||||||
|
|
||||||
|
def render(face, text, context, width, height, fontsize):
|
||||||
|
font = hb.font_create(face)
|
||||||
|
|
||||||
|
margin = fontsize * 2
|
||||||
|
scale = fontsize / hb.face_get_upem(face)
|
||||||
|
target_advance = (width - (margin * 2)) / scale
|
||||||
|
|
||||||
|
lines = typeset(face, text, target_advance)
|
||||||
|
|
||||||
|
_, extents = hb.font_get_h_extents(font)
|
||||||
|
lineheight = extents.ascender - extents.descender + extents.line_gap
|
||||||
|
lineheight *= scale
|
||||||
|
|
||||||
|
context.save()
|
||||||
|
context.translate(0, margin)
|
||||||
|
context.set_font_size(12)
|
||||||
|
context.set_source_rgb(1, 0, 0)
|
||||||
|
for buf, variation in lines:
|
||||||
|
rtl = hb.buffer_get_direction(buf) == hb.direction_t.RTL
|
||||||
|
if rtl:
|
||||||
|
hb.buffer_reverse(buf)
|
||||||
|
infos = hb.buffer_get_glyph_infos(buf)
|
||||||
|
positions = hb.buffer_get_glyph_positions(buf)
|
||||||
|
advance = sum(p.x_advance for p in positions)
|
||||||
|
|
||||||
|
context.translate(0, lineheight)
|
||||||
|
context.save()
|
||||||
|
|
||||||
|
context.save()
|
||||||
|
context.move_to(0, -20)
|
||||||
|
if variation:
|
||||||
|
tag = hb.tag_to_string(variation.tag).decode("ascii")
|
||||||
|
context.show_text(f" {tag}={variation.value:g}")
|
||||||
|
context.move_to(0, 0)
|
||||||
|
context.show_text(f" {advance:g}/{target_advance:g}")
|
||||||
|
context.restore()
|
||||||
|
|
||||||
|
if variation:
|
||||||
|
hb.font_set_variations(font, [variation])
|
||||||
|
|
||||||
|
context.translate(margin, 0)
|
||||||
|
context.scale(scale, -scale)
|
||||||
|
|
||||||
|
if rtl:
|
||||||
|
context.translate(target_advance, 0)
|
||||||
|
|
||||||
|
for info, pos in zip(infos, positions):
|
||||||
|
if rtl:
|
||||||
|
context.translate(-pos.x_advance, pos.y_advance)
|
||||||
|
context.save()
|
||||||
|
context.translate(pos.x_offset, pos.y_offset)
|
||||||
|
hb.font_paint_glyph(font, info.codepoint, PFUNCS, id(context), 0, 0x0000FF)
|
||||||
|
context.restore()
|
||||||
|
if not rtl:
|
||||||
|
context.translate(+pos.x_advance, pos.y_advance)
|
||||||
|
|
||||||
|
context.restore()
|
||||||
|
context.restore()
|
||||||
|
|
||||||
|
|
||||||
|
def main(fontpath, textpath):
|
||||||
|
fontsize = 70
|
||||||
|
|
||||||
|
blob = hb.blob_create_from_file(fontpath)
|
||||||
|
face = hb.face_create(blob, 0)
|
||||||
|
|
||||||
|
with open(textpath) as f:
|
||||||
|
text = f.read()
|
||||||
|
|
||||||
|
def on_draw(da, context):
|
||||||
|
alloc = da.get_allocation()
|
||||||
|
POOL[id(context)] = context
|
||||||
|
render(face, text, context, alloc.width, alloc.height, fontsize)
|
||||||
|
del POOL[id(context)]
|
||||||
|
|
||||||
|
drawingarea = Gtk.DrawingArea()
|
||||||
|
drawingarea.connect("draw", on_draw)
|
||||||
|
|
||||||
|
win = Gtk.Window()
|
||||||
|
win.connect("destroy", Gtk.main_quit)
|
||||||
|
win.set_default_size(1000, 700)
|
||||||
|
win.add(drawingarea)
|
||||||
|
|
||||||
|
win.show_all()
|
||||||
|
Gtk.main()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import argparse
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="HarfBuzz justification demo.")
|
||||||
|
parser.add_argument("fontfile", help="font file")
|
||||||
|
parser.add_argument("textfile", help="text")
|
||||||
|
args = parser.parse_args()
|
||||||
|
main(args.fontfile, args.textfile)
|
|
@ -668,6 +668,7 @@ if get_option('tests').enabled()
|
||||||
'test-ot-name': 'test-ot-name.cc',
|
'test-ot-name': 'test-ot-name.cc',
|
||||||
'test-ot-glyphname': 'test-ot-glyphname.cc',
|
'test-ot-glyphname': 'test-ot-glyphname.cc',
|
||||||
'test-ot-gpos-size-params': 'test-gpos-size-params.cc',
|
'test-ot-gpos-size-params': 'test-gpos-size-params.cc',
|
||||||
|
'test-ot-gsub-get-alternates': 'test-gsub-get-alternates.cc',
|
||||||
'test-ot-gsub-would-substitute': 'test-gsub-would-substitute.cc',
|
'test-ot-gsub-would-substitute': 'test-gsub-would-substitute.cc',
|
||||||
'test-use-table': 'test-use-table.cc',
|
'test-use-table': 'test-use-table.cc',
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2010,2011 Google, Inc.
|
||||||
|
*
|
||||||
|
* This is part of HarfBuzz, a text shaping library.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, without written agreement and without
|
||||||
|
* license or royalty fees, to use, copy, modify, and distribute this
|
||||||
|
* software and its documentation for any purpose, provided that the
|
||||||
|
* above copyright notice and the following two paragraphs appear in
|
||||||
|
* all copies of this software.
|
||||||
|
*
|
||||||
|
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||||
|
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||||
|
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
* DAMAGE.
|
||||||
|
*
|
||||||
|
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||||
|
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||||
|
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||||
|
*
|
||||||
|
* Google Author(s): Behdad Esfahbod
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <hb.h>
|
||||||
|
#include <hb-ot.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc != 3) {
|
||||||
|
fprintf (stderr, "usage: %s font-file text\n", argv[0]);
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the face */
|
||||||
|
hb_blob_t *blob = hb_blob_create_from_file_or_fail (argv[1]);
|
||||||
|
hb_face_t *face = hb_face_create (blob, 0 /* first face */);
|
||||||
|
hb_blob_destroy (blob);
|
||||||
|
blob = nullptr;
|
||||||
|
|
||||||
|
hb_font_t *font = hb_font_create (face);
|
||||||
|
hb_buffer_t *buffer = hb_buffer_create ();
|
||||||
|
|
||||||
|
hb_buffer_add_utf8 (buffer, argv[2], -1, 0, -1);
|
||||||
|
hb_buffer_guess_segment_properties (buffer);
|
||||||
|
hb_shape (font, buffer, NULL, 0);
|
||||||
|
|
||||||
|
hb_tag_t features[] = {HB_TAG('a','a','l','t'), HB_TAG_NONE};
|
||||||
|
hb_set_t *lookup_indexes = hb_set_create ();
|
||||||
|
hb_ot_layout_collect_lookups (face,
|
||||||
|
HB_OT_TAG_GSUB,
|
||||||
|
NULL, NULL,
|
||||||
|
features,
|
||||||
|
lookup_indexes);
|
||||||
|
printf ("lookups %u\n", hb_set_get_population (lookup_indexes));
|
||||||
|
|
||||||
|
unsigned count;
|
||||||
|
hb_glyph_info_t *info = hb_buffer_get_glyph_infos (buffer, &count);
|
||||||
|
for (unsigned i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
unsigned alt_count = 0;
|
||||||
|
for (unsigned lookup_index = HB_SET_VALUE_INVALID;
|
||||||
|
hb_set_next (lookup_indexes, &lookup_index);)
|
||||||
|
if ((alt_count = hb_ot_layout_lookup_get_glyph_alternates (face,
|
||||||
|
lookup_index,
|
||||||
|
info[i].codepoint,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL)))
|
||||||
|
break;
|
||||||
|
printf ("glyph %u alt count %u\n", info[i].codepoint, alt_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_set_destroy (lookup_indexes);
|
||||||
|
hb_buffer_destroy (buffer);
|
||||||
|
hb_font_destroy (font);
|
||||||
|
hb_face_destroy (face);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -137,5 +137,29 @@ main (int argc, char **argv)
|
||||||
assert (s.has (HB_SET_VALUE_INVALID));
|
assert (s.has (HB_SET_VALUE_INVALID));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Adding HB_SET_VALUE_INVALID */
|
||||||
|
{
|
||||||
|
hb_set_t s;
|
||||||
|
|
||||||
|
s.add(HB_SET_VALUE_INVALID);
|
||||||
|
assert(!s.has(HB_SET_VALUE_INVALID));
|
||||||
|
|
||||||
|
s.clear();
|
||||||
|
assert(!s.add_range(HB_SET_VALUE_INVALID - 2, HB_SET_VALUE_INVALID));
|
||||||
|
assert(!s.has(HB_SET_VALUE_INVALID));
|
||||||
|
|
||||||
|
hb_codepoint_t array[] = {(unsigned) HB_SET_VALUE_INVALID, 0, 2};
|
||||||
|
s.clear();
|
||||||
|
s.add_array(array, 3);
|
||||||
|
assert(!s.has(HB_SET_VALUE_INVALID));
|
||||||
|
assert(s.has(2));
|
||||||
|
|
||||||
|
hb_codepoint_t sorted_array[] = {0, 2, (unsigned) HB_SET_VALUE_INVALID};
|
||||||
|
s.clear();
|
||||||
|
s.add_sorted_array(sorted_array, 3);
|
||||||
|
assert(!s.has(HB_SET_VALUE_INVALID));
|
||||||
|
assert(s.has(2));
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -64,12 +64,24 @@ extern "C" int LLVMFuzzerTestOneInput (const uint8_t *data, size_t size)
|
||||||
};
|
};
|
||||||
|
|
||||||
hb_subset_input_t *input = hb_subset_input_create_or_fail ();
|
hb_subset_input_t *input = hb_subset_input_create_or_fail ();
|
||||||
|
if (!input)
|
||||||
|
{
|
||||||
|
hb_face_destroy (face);
|
||||||
|
hb_blob_destroy (blob);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
trySubset (face, text, sizeof (text) / sizeof (hb_codepoint_t), flags, input);
|
trySubset (face, text, sizeof (text) / sizeof (hb_codepoint_t), flags, input);
|
||||||
|
|
||||||
unsigned num_axes;
|
unsigned num_axes;
|
||||||
hb_codepoint_t text_from_data[16];
|
hb_codepoint_t text_from_data[16];
|
||||||
if (size > sizeof (text_from_data) + sizeof (flags) + sizeof(num_axes)) {
|
if (size > sizeof (text_from_data) + sizeof (flags) + sizeof(num_axes)) {
|
||||||
hb_subset_input_t *input = hb_subset_input_create_or_fail ();
|
hb_subset_input_t *input = hb_subset_input_create_or_fail ();
|
||||||
|
if (!input)
|
||||||
|
{
|
||||||
|
hb_face_destroy (face);
|
||||||
|
hb_blob_destroy (blob);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
size -= sizeof (text_from_data);
|
size -= sizeof (text_from_data);
|
||||||
memcpy (text_from_data,
|
memcpy (text_from_data,
|
||||||
data + size,
|
data + size,
|
||||||
|
|
|
@ -10,6 +10,7 @@ EXTRA_DIST += \
|
||||||
$(DISABLED_TESTS) \
|
$(DISABLED_TESTS) \
|
||||||
expected/32bit_var_store \
|
expected/32bit_var_store \
|
||||||
expected/basics \
|
expected/basics \
|
||||||
|
expected/preprocess \
|
||||||
expected/full-font \
|
expected/full-font \
|
||||||
expected/glyf_bug_3131 \
|
expected/glyf_bug_3131 \
|
||||||
expected/cff-full-font \
|
expected/cff-full-font \
|
||||||
|
@ -43,6 +44,7 @@ EXTRA_DIST += \
|
||||||
expected/layout.duplicate_features \
|
expected/layout.duplicate_features \
|
||||||
expected/layout.unsorted_featurelist \
|
expected/layout.unsorted_featurelist \
|
||||||
expected/layout.drop_feature \
|
expected/layout.drop_feature \
|
||||||
|
expected/no_layout_closure \
|
||||||
expected/cmap \
|
expected/cmap \
|
||||||
expected/cmap14 \
|
expected/cmap14 \
|
||||||
expected/sbix \
|
expected/sbix \
|
||||||
|
@ -67,6 +69,9 @@ EXTRA_DIST += \
|
||||||
expected/instance_comp_glyph_empty_child \
|
expected/instance_comp_glyph_empty_child \
|
||||||
expected/post_apply_mvar_delta \
|
expected/post_apply_mvar_delta \
|
||||||
expected/apply_cvar_delta \
|
expected/apply_cvar_delta \
|
||||||
|
expected/collect_name_ids \
|
||||||
|
expected/instantiate_colrv1 \
|
||||||
|
expected/instantiate_cff2_update_metrics \
|
||||||
fonts \
|
fonts \
|
||||||
profiles \
|
profiles \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
TESTS = \
|
TESTS = \
|
||||||
tests/32bit_var_store.tests \
|
tests/32bit_var_store.tests \
|
||||||
tests/basics.tests \
|
tests/basics.tests \
|
||||||
|
tests/preprocess.tests \
|
||||||
tests/cbdt.tests \
|
tests/cbdt.tests \
|
||||||
tests/cff-full-font.tests \
|
tests/cff-full-font.tests \
|
||||||
tests/cff-japanese.tests \
|
tests/cff-japanese.tests \
|
||||||
|
@ -42,6 +43,7 @@ TESTS = \
|
||||||
tests/layout.duplicate_features.tests \
|
tests/layout.duplicate_features.tests \
|
||||||
tests/layout.unsorted_featurelist.tests \
|
tests/layout.unsorted_featurelist.tests \
|
||||||
tests/layout.drop_feature.tests \
|
tests/layout.drop_feature.tests \
|
||||||
|
tests/no_layout_closure.tests \
|
||||||
tests/sbix.tests \
|
tests/sbix.tests \
|
||||||
tests/variable.tests \
|
tests/variable.tests \
|
||||||
tests/glyph_names.tests \
|
tests/glyph_names.tests \
|
||||||
|
@ -58,6 +60,9 @@ TESTS = \
|
||||||
tests/instance_comp_glyph_empty_child.tests \
|
tests/instance_comp_glyph_empty_child.tests \
|
||||||
tests/post_apply_mvar_delta.tests \
|
tests/post_apply_mvar_delta.tests \
|
||||||
tests/apply_cvar_delta.tests \
|
tests/apply_cvar_delta.tests \
|
||||||
|
tests/collect_name_ids.tests \
|
||||||
|
tests/instantiate_colrv1.tests \
|
||||||
|
tests/instantiate_cff2_update_metrics.tests \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
# TODO: re-enable once colrv1 subsetting is stabilized.
|
# TODO: re-enable once colrv1 subsetting is stabilized.
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,2 @@
|
||||||
|
--no-layout-closure
|
||||||
|
--gids=74,77,446
|
|
@ -0,0 +1,3 @@
|
||||||
|
--no-layout-closure
|
||||||
|
--gids=74,87,88,443,448
|
||||||
|
--layout-features+=dlig
|
|
@ -1,5 +1,6 @@
|
||||||
FONTS:
|
FONTS:
|
||||||
Comfortaa-Regular-new.ttf
|
Comfortaa-Regular-new.ttf
|
||||||
|
Muli-ABC.ttf
|
||||||
|
|
||||||
PROFILES:
|
PROFILES:
|
||||||
default.txt
|
default.txt
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
FONTS:
|
||||||
|
SourceSerif4Variable-Roman_subset.otf
|
||||||
|
|
||||||
|
PROFILES:
|
||||||
|
keep-all-layout-features.txt
|
||||||
|
|
||||||
|
SUBSETS:
|
||||||
|
*
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
no_fonttools
|
|
@ -0,0 +1,15 @@
|
||||||
|
FONTS:
|
||||||
|
Cantarell-VF-ABC.otf
|
||||||
|
|
||||||
|
PROFILES:
|
||||||
|
default.txt
|
||||||
|
retain-gids.txt
|
||||||
|
|
||||||
|
SUBSETS:
|
||||||
|
*
|
||||||
|
|
||||||
|
INSTANCES:
|
||||||
|
wght=800
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
no_fonttools
|
|
@ -0,0 +1,14 @@
|
||||||
|
FONTS:
|
||||||
|
Foldit.ttf
|
||||||
|
|
||||||
|
PROFILES:
|
||||||
|
default.txt
|
||||||
|
|
||||||
|
SUBSETS:
|
||||||
|
*
|
||||||
|
|
||||||
|
INSTANCES:
|
||||||
|
wght=900
|
||||||
|
|
||||||
|
OPTIONS:
|
||||||
|
no_fonttools
|
|
@ -0,0 +1,9 @@
|
||||||
|
FONTS:
|
||||||
|
Roboto-Regular.ttf
|
||||||
|
|
||||||
|
PROFILES:
|
||||||
|
no-layout-closure-gids.txt
|
||||||
|
no-layout-closure-gids2.txt
|
||||||
|
|
||||||
|
SUBSETS:
|
||||||
|
no-unicodes
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue