Upgrade Harfbuzz to version 8.2.0
Task-number: QTBUG-117136 Pick-to: 6.6.0 6.5 6.5.3 6.2 5.15 Change-Id: I910c8bff2fe521aa02929b9000fa7f38192d1a51 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> (cherry picked from commit 08134e458d7fdd0b9565976046821b3903166dd6) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
e2752e4274
commit
5a6d960018
12
src/3rdparty/harfbuzz-ng/NEWS
vendored
12
src/3rdparty/harfbuzz-ng/NEWS
vendored
@ -1,3 +1,15 @@
|
|||||||
|
Overview of changes leading to 8.2.0
|
||||||
|
Friday, September 8, 2023
|
||||||
|
====================================
|
||||||
|
- Various build and fuzzing fixes
|
||||||
|
- Improvements to COLRv1 painting.
|
||||||
|
|
||||||
|
- New API:
|
||||||
|
+hb_paint_color_glyph_func_t
|
||||||
|
+hb_paint_funcs_set_color_glyph_func
|
||||||
|
+hb_paint_color_glyph
|
||||||
|
|
||||||
|
|
||||||
Overview of changes leading to 8.1.1
|
Overview of changes leading to 8.1.1
|
||||||
Wednesday, August 2, 2023
|
Wednesday, August 2, 2023
|
||||||
====================================
|
====================================
|
||||||
|
4
src/3rdparty/harfbuzz-ng/README.md
vendored
4
src/3rdparty/harfbuzz-ng/README.md
vendored
@ -29,8 +29,8 @@ For user manual as well as API documentation, check: https://harfbuzz.github.io
|
|||||||
## Download
|
## Download
|
||||||
|
|
||||||
For tarball releases of HarfBuzz, look [here][3]. At the same place you
|
For tarball releases of HarfBuzz, look [here][3]. At the same place you
|
||||||
will also find Win32/Win64 binary bundles that include libharfbuzz DLL,
|
will also find Win32/Win64 binary bundles that include `libharfbuzz` DLL,
|
||||||
hb-view.exe, hb-shape.exe, and all dependencies.
|
`hb-view.exe`, `hb-shape.exe`, and all dependencies.
|
||||||
|
|
||||||
The canonical source tree is available on [github][4].
|
The canonical source tree is available on [github][4].
|
||||||
|
|
||||||
|
4
src/3rdparty/harfbuzz-ng/qt_attribution.json
vendored
4
src/3rdparty/harfbuzz-ng/qt_attribution.json
vendored
@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
"Description": "HarfBuzz is an OpenType text shaping engine.",
|
"Description": "HarfBuzz is an OpenType text shaping engine.",
|
||||||
"Homepage": "http://harfbuzz.org",
|
"Homepage": "http://harfbuzz.org",
|
||||||
"Version": "8.1.1",
|
"Version": "8.2.0",
|
||||||
"DownloadLocation": "https://github.com/harfbuzz/harfbuzz/releases/tag/8.1.1",
|
"DownloadLocation": "https://github.com/harfbuzz/harfbuzz/releases/tag/8.2.0",
|
||||||
|
|
||||||
"License": "MIT License",
|
"License": "MIT License",
|
||||||
"LicenseId": "MIT",
|
"LicenseId": "MIT",
|
||||||
|
@ -53,6 +53,7 @@ struct Paint;
|
|||||||
struct hb_paint_context_t :
|
struct hb_paint_context_t :
|
||||||
hb_dispatch_context_t<hb_paint_context_t>
|
hb_dispatch_context_t<hb_paint_context_t>
|
||||||
{
|
{
|
||||||
|
const char *get_name () { return "PAINT"; }
|
||||||
template <typename T>
|
template <typename T>
|
||||||
return_t dispatch (const T &obj) { obj.paint_glyph (this); return hb_empty_t (); }
|
return_t dispatch (const T &obj) { obj.paint_glyph (this); return hb_empty_t (); }
|
||||||
static return_t default_return_value () { return hb_empty_t (); }
|
static return_t default_return_value () { return hb_empty_t (); }
|
||||||
@ -68,6 +69,8 @@ public:
|
|||||||
unsigned int palette_index;
|
unsigned int palette_index;
|
||||||
hb_color_t foreground;
|
hb_color_t foreground;
|
||||||
VarStoreInstancer &instancer;
|
VarStoreInstancer &instancer;
|
||||||
|
hb_map_t current_glyphs;
|
||||||
|
hb_map_t current_layers;
|
||||||
int depth_left = HB_MAX_NESTING_LEVEL;
|
int depth_left = HB_MAX_NESTING_LEVEL;
|
||||||
int edge_count = HB_COLRV1_MAX_EDGE_COUNT;
|
int edge_count = HB_COLRV1_MAX_EDGE_COUNT;
|
||||||
|
|
||||||
@ -261,6 +264,7 @@ struct Variable
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c) const
|
void paint_glyph (hb_paint_context_t *c) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
value.paint_glyph (c, varIdxBase);
|
value.paint_glyph (c, varIdxBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +285,7 @@ struct Variable
|
|||||||
public:
|
public:
|
||||||
VarIdx varIdxBase;
|
VarIdx varIdxBase;
|
||||||
public:
|
public:
|
||||||
DEFINE_SIZE_STATIC (4 + T::static_size);
|
DEFINE_SIZE_MIN (VarIdx::static_size + T::min_size);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -315,6 +319,7 @@ struct NoVariable
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c) const
|
void paint_glyph (hb_paint_context_t *c) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
value.paint_glyph (c, varIdxBase);
|
value.paint_glyph (c, varIdxBase);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -332,7 +337,7 @@ struct NoVariable
|
|||||||
|
|
||||||
T value;
|
T value;
|
||||||
public:
|
public:
|
||||||
DEFINE_SIZE_STATIC (T::static_size);
|
DEFINE_SIZE_MIN (T::min_size);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Color structures
|
// Color structures
|
||||||
@ -558,6 +563,7 @@ struct Affine2x3
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
c->funcs->push_transform (c->data,
|
c->funcs->push_transform (c->data,
|
||||||
xx.to_float (c->instancer (varIdxBase, 0)),
|
xx.to_float (c->instancer (varIdxBase, 0)),
|
||||||
yx.to_float (c->instancer (varIdxBase, 1)),
|
yx.to_float (c->instancer (varIdxBase, 1)),
|
||||||
@ -639,6 +645,7 @@ struct PaintSolid
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
hb_bool_t is_foreground;
|
hb_bool_t is_foreground;
|
||||||
hb_color_t color;
|
hb_color_t color;
|
||||||
|
|
||||||
@ -693,6 +700,7 @@ struct PaintLinearGradient
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
hb_color_line_t cl = {
|
hb_color_line_t cl = {
|
||||||
(void *) &(this+colorLine),
|
(void *) &(this+colorLine),
|
||||||
(this+colorLine).static_get_color_stops, c,
|
(this+colorLine).static_get_color_stops, c,
|
||||||
@ -759,6 +767,7 @@ struct PaintRadialGradient
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
hb_color_line_t cl = {
|
hb_color_line_t cl = {
|
||||||
(void *) &(this+colorLine),
|
(void *) &(this+colorLine),
|
||||||
(this+colorLine).static_get_color_stops, c,
|
(this+colorLine).static_get_color_stops, c,
|
||||||
@ -823,6 +832,7 @@ struct PaintSweepGradient
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
hb_color_line_t cl = {
|
hb_color_line_t cl = {
|
||||||
(void *) &(this+colorLine),
|
(void *) &(this+colorLine),
|
||||||
(this+colorLine).static_get_color_stops, c,
|
(this+colorLine).static_get_color_stops, c,
|
||||||
@ -874,6 +884,7 @@ struct PaintGlyph
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c) const
|
void paint_glyph (hb_paint_context_t *c) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
c->funcs->push_inverse_root_transform (c->data, c->font);
|
c->funcs->push_inverse_root_transform (c->data, c->font);
|
||||||
c->funcs->push_clip_glyph (c->data, gid, c->font);
|
c->funcs->push_clip_glyph (c->data, gid, c->font);
|
||||||
c->funcs->push_root_transform (c->data, c->font);
|
c->funcs->push_root_transform (c->data, c->font);
|
||||||
@ -946,6 +957,7 @@ struct PaintTransform
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c) const
|
void paint_glyph (hb_paint_context_t *c) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
(this+transform).paint_glyph (c);
|
(this+transform).paint_glyph (c);
|
||||||
c->recurse (this+src);
|
c->recurse (this+src);
|
||||||
c->funcs->pop_transform (c->data);
|
c->funcs->pop_transform (c->data);
|
||||||
@ -990,6 +1002,7 @@ struct PaintTranslate
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
float ddx = dx + c->instancer (varIdxBase, 0);
|
float ddx = dx + c->instancer (varIdxBase, 0);
|
||||||
float ddy = dy + c->instancer (varIdxBase, 1);
|
float ddy = dy + c->instancer (varIdxBase, 1);
|
||||||
|
|
||||||
@ -1038,6 +1051,7 @@ struct PaintScale
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
float sx = scaleX.to_float (c->instancer (varIdxBase, 0));
|
float sx = scaleX.to_float (c->instancer (varIdxBase, 0));
|
||||||
float sy = scaleY.to_float (c->instancer (varIdxBase, 1));
|
float sy = scaleY.to_float (c->instancer (varIdxBase, 1));
|
||||||
|
|
||||||
@ -1088,6 +1102,7 @@ struct PaintScaleAroundCenter
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
float sx = scaleX.to_float (c->instancer (varIdxBase, 0));
|
float sx = scaleX.to_float (c->instancer (varIdxBase, 0));
|
||||||
float sy = scaleY.to_float (c->instancer (varIdxBase, 1));
|
float sy = scaleY.to_float (c->instancer (varIdxBase, 1));
|
||||||
float tCenterX = centerX + c->instancer (varIdxBase, 2);
|
float tCenterX = centerX + c->instancer (varIdxBase, 2);
|
||||||
@ -1141,6 +1156,7 @@ struct PaintScaleUniform
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
float s = scale.to_float (c->instancer (varIdxBase, 0));
|
float s = scale.to_float (c->instancer (varIdxBase, 0));
|
||||||
|
|
||||||
bool p1 = c->funcs->push_scale (c->data, s, s);
|
bool p1 = c->funcs->push_scale (c->data, s, s);
|
||||||
@ -1188,6 +1204,7 @@ struct PaintScaleUniformAroundCenter
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
float s = scale.to_float (c->instancer (varIdxBase, 0));
|
float s = scale.to_float (c->instancer (varIdxBase, 0));
|
||||||
float tCenterX = centerX + c->instancer (varIdxBase, 1);
|
float tCenterX = centerX + c->instancer (varIdxBase, 1);
|
||||||
float tCenterY = centerY + c->instancer (varIdxBase, 2);
|
float tCenterY = centerY + c->instancer (varIdxBase, 2);
|
||||||
@ -1239,6 +1256,7 @@ struct PaintRotate
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
float a = angle.to_float (c->instancer (varIdxBase, 0));
|
float a = angle.to_float (c->instancer (varIdxBase, 0));
|
||||||
|
|
||||||
bool p1 = c->funcs->push_rotate (c->data, a);
|
bool p1 = c->funcs->push_rotate (c->data, a);
|
||||||
@ -1286,6 +1304,7 @@ struct PaintRotateAroundCenter
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
float a = angle.to_float (c->instancer (varIdxBase, 0));
|
float a = angle.to_float (c->instancer (varIdxBase, 0));
|
||||||
float tCenterX = centerX + c->instancer (varIdxBase, 1);
|
float tCenterX = centerX + c->instancer (varIdxBase, 1);
|
||||||
float tCenterY = centerY + c->instancer (varIdxBase, 2);
|
float tCenterY = centerY + c->instancer (varIdxBase, 2);
|
||||||
@ -1340,6 +1359,7 @@ struct PaintSkew
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
float sx = xSkewAngle.to_float(c->instancer (varIdxBase, 0));
|
float sx = xSkewAngle.to_float(c->instancer (varIdxBase, 0));
|
||||||
float sy = ySkewAngle.to_float(c->instancer (varIdxBase, 1));
|
float sy = ySkewAngle.to_float(c->instancer (varIdxBase, 1));
|
||||||
|
|
||||||
@ -1390,6 +1410,7 @@ struct PaintSkewAroundCenter
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
void paint_glyph (hb_paint_context_t *c, uint32_t varIdxBase) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
float sx = xSkewAngle.to_float(c->instancer (varIdxBase, 0));
|
float sx = xSkewAngle.to_float(c->instancer (varIdxBase, 0));
|
||||||
float sy = ySkewAngle.to_float(c->instancer (varIdxBase, 1));
|
float sy = ySkewAngle.to_float(c->instancer (varIdxBase, 1));
|
||||||
float tCenterX = centerX + c->instancer (varIdxBase, 2);
|
float tCenterX = centerX + c->instancer (varIdxBase, 2);
|
||||||
@ -1425,8 +1446,10 @@ struct PaintComposite
|
|||||||
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, instancer)) return_trace (false);
|
bool ret = false;
|
||||||
return_trace (out->backdrop.serialize_subset (c, backdrop, this, instancer));
|
ret |= out->src.serialize_subset (c, src, this, instancer);
|
||||||
|
ret |= out->backdrop.serialize_subset (c, backdrop, this, instancer);
|
||||||
|
return_trace (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
@ -1440,6 +1463,7 @@ struct PaintComposite
|
|||||||
|
|
||||||
void paint_glyph (hb_paint_context_t *c) const
|
void paint_glyph (hb_paint_context_t *c) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
c->recurse (this+backdrop);
|
c->recurse (this+backdrop);
|
||||||
c->funcs->push_group (c->data);
|
c->funcs->push_group (c->data);
|
||||||
c->recurse (this+src);
|
c->recurse (this+src);
|
||||||
@ -1898,15 +1922,16 @@ struct LayerList : Array32OfOffset32To<Paint>
|
|||||||
auto *out = c->serializer->start_embed (this);
|
auto *out = c->serializer->start_embed (this);
|
||||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
for (const auto& _ : + hb_enumerate (*this)
|
for (const auto& _ : + hb_enumerate (*this)
|
||||||
| hb_filter (c->plan->colrv1_layers, hb_first))
|
| hb_filter (c->plan->colrv1_layers, hb_first))
|
||||||
|
|
||||||
{
|
{
|
||||||
auto *o = out->serialize_append (c->serializer);
|
auto *o = out->serialize_append (c->serializer);
|
||||||
if (unlikely (!o) || !o->serialize_subset (c, _.second, this, instancer))
|
if (unlikely (!o)) return_trace (false);
|
||||||
return_trace (false);
|
ret |= o->serialize_subset (c, _.second, this, instancer);
|
||||||
}
|
}
|
||||||
return_trace (true);
|
return_trace (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
@ -2284,6 +2309,7 @@ struct COLR
|
|||||||
&(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);
|
||||||
|
c.current_glyphs.add (glyph);
|
||||||
|
|
||||||
if (version == 1)
|
if (version == 1)
|
||||||
{
|
{
|
||||||
@ -2399,18 +2425,42 @@ hb_paint_context_t::recurse (const Paint &paint)
|
|||||||
|
|
||||||
void PaintColrLayers::paint_glyph (hb_paint_context_t *c) const
|
void PaintColrLayers::paint_glyph (hb_paint_context_t *c) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
const LayerList &paint_offset_lists = c->get_colr_table ()->get_layerList ();
|
const LayerList &paint_offset_lists = c->get_colr_table ()->get_layerList ();
|
||||||
for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++)
|
for (unsigned i = firstLayerIndex; i < firstLayerIndex + numLayers; i++)
|
||||||
{
|
{
|
||||||
|
if (unlikely (c->current_layers.has (i)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
c->current_layers.add (i);
|
||||||
|
|
||||||
const Paint &paint = paint_offset_lists.get_paint (i);
|
const Paint &paint = paint_offset_lists.get_paint (i);
|
||||||
c->funcs->push_group (c->data);
|
c->funcs->push_group (c->data);
|
||||||
c->recurse (paint);
|
c->recurse (paint);
|
||||||
c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
|
c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
|
||||||
|
|
||||||
|
c->current_layers.del (i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PaintColrGlyph::paint_glyph (hb_paint_context_t *c) const
|
void PaintColrGlyph::paint_glyph (hb_paint_context_t *c) const
|
||||||
{
|
{
|
||||||
|
TRACE_PAINT (this);
|
||||||
|
|
||||||
|
if (unlikely (c->current_glyphs.has (gid)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
c->current_glyphs.add (gid);
|
||||||
|
|
||||||
|
c->funcs->push_inverse_root_transform (c->data, c->font);
|
||||||
|
if (c->funcs->color_glyph (c->data, gid, c->font))
|
||||||
|
{
|
||||||
|
c->funcs->pop_transform (c->data);
|
||||||
|
c->current_glyphs.del (gid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
c->funcs->pop_transform (c->data);
|
||||||
|
|
||||||
const COLR *colr_table = c->get_colr_table ();
|
const COLR *colr_table = c->get_colr_table ();
|
||||||
const Paint *paint = colr_table->get_base_glyph_paint (gid);
|
const Paint *paint = colr_table->get_base_glyph_paint (gid);
|
||||||
|
|
||||||
@ -2429,6 +2479,8 @@ void PaintColrGlyph::paint_glyph (hb_paint_context_t *c) const
|
|||||||
|
|
||||||
if (has_clip_box)
|
if (has_clip_box)
|
||||||
c->funcs->pop_clip (c->data);
|
c->funcs->pop_clip (c->data);
|
||||||
|
|
||||||
|
c->current_glyphs.del (gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace OT */
|
} /* namespace OT */
|
||||||
|
@ -65,14 +65,15 @@ struct AnchorMatrix
|
|||||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||||
|
|
||||||
out->rows = num_rows;
|
out->rows = num_rows;
|
||||||
|
bool ret = false;
|
||||||
for (const unsigned i : index_iter)
|
for (const unsigned i : index_iter)
|
||||||
{
|
{
|
||||||
auto *offset = c->serializer->embed (matrixZ[i]);
|
auto *offset = c->serializer->embed (matrixZ[i]);
|
||||||
if (!offset) return_trace (false);
|
if (!offset) return_trace (false);
|
||||||
offset->serialize_subset (c, matrixZ[i], this);
|
ret |= offset->serialize_subset (c, matrixZ[i], this);
|
||||||
}
|
}
|
||||||
|
|
||||||
return_trace (true);
|
return_trace (ret);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,16 +24,17 @@ struct EntryExitRecord
|
|||||||
(src_base+exitAnchor).collect_variation_indices (c);
|
(src_base+exitAnchor).collect_variation_indices (c);
|
||||||
}
|
}
|
||||||
|
|
||||||
EntryExitRecord* subset (hb_subset_context_t *c,
|
bool subset (hb_subset_context_t *c,
|
||||||
const void *src_base) const
|
const void *src_base) const
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
if (unlikely (!out)) return_trace (nullptr);
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
out->entryAnchor.serialize_subset (c, entryAnchor, src_base);
|
bool ret = false;
|
||||||
out->exitAnchor.serialize_subset (c, exitAnchor, src_base);
|
ret |= out->entryAnchor.serialize_subset (c, entryAnchor, src_base);
|
||||||
return_trace (out);
|
ret |= out->exitAnchor.serialize_subset (c, exitAnchor, src_base);
|
||||||
|
return_trace (ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -27,6 +27,7 @@ struct LigatureArray : List16OfOffset16To<LigatureAttach>
|
|||||||
auto *out = c->serializer->start_embed (this);
|
auto *out = c->serializer->start_embed (this);
|
||||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
for (const auto _ : + hb_zip (coverage, *this)
|
for (const auto _ : + hb_zip (coverage, *this)
|
||||||
| hb_filter (glyphset, hb_first))
|
| hb_filter (glyphset, hb_first))
|
||||||
{
|
{
|
||||||
@ -38,13 +39,13 @@ struct LigatureArray : List16OfOffset16To<LigatureAttach>
|
|||||||
+ hb_range (src.rows * class_count)
|
+ hb_range (src.rows * class_count)
|
||||||
| hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); })
|
| hb_filter ([=] (unsigned index) { return klass_mapping->has (index % class_count); })
|
||||||
;
|
;
|
||||||
matrix->serialize_subset (c,
|
ret |= matrix->serialize_subset (c,
|
||||||
_.second,
|
_.second,
|
||||||
this,
|
this,
|
||||||
src.rows,
|
src.rows,
|
||||||
indexes);
|
indexes);
|
||||||
}
|
}
|
||||||
return_trace (this->len);
|
return_trace (ret);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -82,10 +82,10 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Cove
|
|||||||
| hb_map (hb_second)
|
| hb_map (hb_second)
|
||||||
;
|
;
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
unsigned new_length = 0;
|
unsigned new_length = 0;
|
||||||
for (const auto& mark_record : mark_iter) {
|
for (const auto& mark_record : mark_iter) {
|
||||||
if (unlikely (!mark_record.subset (c, this, klass_mapping)))
|
ret |= mark_record.subset (c, this, klass_mapping);
|
||||||
return_trace (false);
|
|
||||||
new_length++;
|
new_length++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ struct MarkArray : Array16Of<MarkRecord> /* Array of MarkRecords--in Cove
|
|||||||
HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
|
HB_SERIALIZE_ERROR_ARRAY_OVERFLOW)))
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
|
|
||||||
return_trace (true);
|
return_trace (ret);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -197,9 +197,10 @@ struct MarkBasePosFormat1_2
|
|||||||
if (!out->markCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
|
if (!out->markCoverage.serialize_serialize (c->serializer, new_coverage.iter ()))
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
|
|
||||||
out->markArray.serialize_subset (c, markArray, this,
|
if (unlikely (!out->markArray.serialize_subset (c, markArray, this,
|
||||||
(this+markCoverage).iter (),
|
(this+markCoverage).iter (),
|
||||||
&klass_mapping);
|
&klass_mapping)))
|
||||||
|
return_trace (false);
|
||||||
|
|
||||||
unsigned basecount = (this+baseArray).rows;
|
unsigned basecount = (this+baseArray).rows;
|
||||||
auto base_iter =
|
auto base_iter =
|
||||||
@ -228,11 +229,9 @@ struct MarkBasePosFormat1_2
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
out->baseArray.serialize_subset (c, baseArray, this,
|
return_trace (out->baseArray.serialize_subset (c, baseArray, this,
|
||||||
base_iter.len (),
|
base_iter.len (),
|
||||||
base_indexes.iter ());
|
base_indexes.iter ()));
|
||||||
|
|
||||||
return_trace (true);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -195,9 +195,10 @@ struct MarkLigPosFormat1_2
|
|||||||
if (!out->markCoverage.serialize_serialize (c->serializer, new_mark_coverage))
|
if (!out->markCoverage.serialize_serialize (c->serializer, new_mark_coverage))
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
|
|
||||||
out->markArray.serialize_subset (c, markArray, this,
|
if (unlikely (!out->markArray.serialize_subset (c, markArray, this,
|
||||||
(this+markCoverage).iter (),
|
(this+markCoverage).iter (),
|
||||||
&klass_mapping);
|
&klass_mapping)))
|
||||||
|
return_trace (false);
|
||||||
|
|
||||||
auto new_ligature_coverage =
|
auto new_ligature_coverage =
|
||||||
+ hb_iter (this + ligatureCoverage)
|
+ hb_iter (this + ligatureCoverage)
|
||||||
@ -208,10 +209,9 @@ struct MarkLigPosFormat1_2
|
|||||||
if (!out->ligatureCoverage.serialize_serialize (c->serializer, new_ligature_coverage))
|
if (!out->ligatureCoverage.serialize_serialize (c->serializer, new_ligature_coverage))
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
|
|
||||||
out->ligatureArray.serialize_subset (c, ligatureArray, this,
|
return_trace (out->ligatureArray.serialize_subset (c, ligatureArray, this,
|
||||||
hb_iter (this+ligatureCoverage), classCount, &klass_mapping);
|
hb_iter (this+ligatureCoverage),
|
||||||
|
classCount, &klass_mapping));
|
||||||
return_trace (true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -183,9 +183,10 @@ struct MarkMarkPosFormat1_2
|
|||||||
if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
|
if (!out->mark1Coverage.serialize_serialize (c->serializer, new_coverage.iter ()))
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
|
|
||||||
out->mark1Array.serialize_subset (c, mark1Array, this,
|
if (unlikely (!out->mark1Array.serialize_subset (c, mark1Array, this,
|
||||||
(this+mark1Coverage).iter (),
|
(this+mark1Coverage).iter (),
|
||||||
&klass_mapping);
|
&klass_mapping)))
|
||||||
|
return_trace (false);
|
||||||
|
|
||||||
unsigned mark2count = (this+mark2Array).rows;
|
unsigned mark2count = (this+mark2Array).rows;
|
||||||
auto mark2_iter =
|
auto mark2_iter =
|
||||||
@ -214,9 +215,10 @@ struct MarkMarkPosFormat1_2
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
out->mark2Array.serialize_subset (c, mark2Array, this, mark2_iter.len (), mark2_indexes.iter ());
|
return_trace (out->mark2Array.serialize_subset (c, mark2Array, this,
|
||||||
|
mark2_iter.len (),
|
||||||
|
mark2_indexes.iter ()));
|
||||||
|
|
||||||
return_trace (true);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -24,17 +24,16 @@ struct MarkRecord
|
|||||||
return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
|
return_trace (c->check_struct (this) && markAnchor.sanitize (c, base));
|
||||||
}
|
}
|
||||||
|
|
||||||
MarkRecord *subset (hb_subset_context_t *c,
|
bool subset (hb_subset_context_t *c,
|
||||||
const void *src_base,
|
const void *src_base,
|
||||||
const hb_map_t *klass_mapping) const
|
const hb_map_t *klass_mapping) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
auto *out = c->serializer->embed (this);
|
auto *out = c->serializer->embed (this);
|
||||||
if (unlikely (!out)) return_trace (nullptr);
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
out->klass = klass_mapping->get (klass);
|
out->klass = klass_mapping->get (klass);
|
||||||
out->markAnchor.serialize_subset (c, markAnchor, src_base);
|
return_trace (out->markAnchor.serialize_subset (c, markAnchor, src_base));
|
||||||
return_trace (out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
void collect_variation_indices (hb_collect_variation_indices_context_t *c,
|
||||||
|
@ -163,7 +163,7 @@ struct PairPosFormat2_4
|
|||||||
|
|
||||||
|
|
||||||
/* Isolate simple kerning and apply it half to each side.
|
/* Isolate simple kerning and apply it half to each side.
|
||||||
* Results in better cursor positinoing / underline drawing.
|
* Results in better cursor positioning / underline drawing.
|
||||||
*
|
*
|
||||||
* Disabled, because causes issues... :-(
|
* Disabled, because causes issues... :-(
|
||||||
* https://github.com/harfbuzz/harfbuzz/issues/3408
|
* https://github.com/harfbuzz/harfbuzz/issues/3408
|
||||||
|
97
src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh
vendored
97
src/3rdparty/harfbuzz-ng/src/OT/glyf/Glyph.hh
vendored
@ -103,6 +103,63 @@ struct Glyph
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get_all_points_without_var (const hb_face_t *face,
|
||||||
|
contour_point_vector_t &points /* OUT */) const
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case SIMPLE:
|
||||||
|
if (unlikely (!SimpleGlyph (*header, bytes).get_contour_points (points)))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case COMPOSITE:
|
||||||
|
{
|
||||||
|
for (auto &item : get_composite_iterator ())
|
||||||
|
if (unlikely (!item.get_points (points))) return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#ifndef HB_NO_VAR_COMPOSITES
|
||||||
|
case VAR_COMPOSITE:
|
||||||
|
{
|
||||||
|
for (auto &item : get_var_composite_iterator ())
|
||||||
|
if (unlikely (!item.get_points (points))) return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
case EMPTY:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init phantom points */
|
||||||
|
if (unlikely (!points.resize (points.length + PHANTOM_COUNT))) return false;
|
||||||
|
hb_array_t<contour_point_t> phantoms = points.as_array ().sub_array (points.length - PHANTOM_COUNT, PHANTOM_COUNT);
|
||||||
|
{
|
||||||
|
int lsb = 0;
|
||||||
|
int h_delta = face->table.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb) ?
|
||||||
|
(int) header->xMin - lsb : 0;
|
||||||
|
HB_UNUSED int tsb = 0;
|
||||||
|
int v_orig = (int) header->yMax +
|
||||||
|
#ifndef HB_NO_VERTICAL
|
||||||
|
((void) face->table.vmtx->get_leading_bearing_without_var_unscaled (gid, &tsb), tsb)
|
||||||
|
#else
|
||||||
|
0
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
unsigned h_adv = face->table.hmtx->get_advance_without_var_unscaled (gid);
|
||||||
|
unsigned v_adv =
|
||||||
|
#ifndef HB_NO_VERTICAL
|
||||||
|
face->table.vmtx->get_advance_without_var_unscaled (gid)
|
||||||
|
#else
|
||||||
|
- face->get_upem ()
|
||||||
|
#endif
|
||||||
|
;
|
||||||
|
phantoms[PHANTOM_LEFT].x = h_delta;
|
||||||
|
phantoms[PHANTOM_RIGHT].x = (int) h_adv + h_delta;
|
||||||
|
phantoms[PHANTOM_TOP].y = v_orig;
|
||||||
|
phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void update_mtx (const hb_subset_plan_t *plan,
|
void update_mtx (const hb_subset_plan_t *plan,
|
||||||
int xMin, int xMax,
|
int xMin, int xMax,
|
||||||
int yMin, int yMax,
|
int yMin, int yMax,
|
||||||
@ -293,6 +350,7 @@ struct Glyph
|
|||||||
bool use_my_metrics = true,
|
bool use_my_metrics = true,
|
||||||
bool phantom_only = false,
|
bool phantom_only = false,
|
||||||
hb_array_t<int> coords = hb_array_t<int> (),
|
hb_array_t<int> coords = hb_array_t<int> (),
|
||||||
|
hb_map_t *current_glyphs = nullptr,
|
||||||
unsigned int depth = 0,
|
unsigned int depth = 0,
|
||||||
unsigned *edge_count = nullptr) const
|
unsigned *edge_count = nullptr) const
|
||||||
{
|
{
|
||||||
@ -302,6 +360,10 @@ struct Glyph
|
|||||||
if (unlikely (*edge_count > HB_GLYF_MAX_EDGE_COUNT)) return false;
|
if (unlikely (*edge_count > HB_GLYF_MAX_EDGE_COUNT)) return false;
|
||||||
(*edge_count)++;
|
(*edge_count)++;
|
||||||
|
|
||||||
|
hb_map_t current_glyphs_stack;
|
||||||
|
if (current_glyphs == nullptr)
|
||||||
|
current_glyphs = ¤t_glyphs_stack;
|
||||||
|
|
||||||
if (head_maxp_info)
|
if (head_maxp_info)
|
||||||
{
|
{
|
||||||
head_maxp_info->maxComponentDepth = hb_max (head_maxp_info->maxComponentDepth, depth);
|
head_maxp_info->maxComponentDepth = hb_max (head_maxp_info->maxComponentDepth, depth);
|
||||||
@ -396,10 +458,17 @@ struct Glyph
|
|||||||
unsigned int comp_index = 0;
|
unsigned int comp_index = 0;
|
||||||
for (auto &item : get_composite_iterator ())
|
for (auto &item : get_composite_iterator ())
|
||||||
{
|
{
|
||||||
|
hb_codepoint_t item_gid = item.get_gid ();
|
||||||
|
|
||||||
|
if (unlikely (current_glyphs->has (item_gid)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
current_glyphs->add (item_gid);
|
||||||
|
|
||||||
unsigned old_count = all_points.length;
|
unsigned old_count = all_points.length;
|
||||||
|
|
||||||
if (unlikely ((!phantom_only || (use_my_metrics && item.is_use_my_metrics ())) &&
|
if (unlikely ((!phantom_only || (use_my_metrics && item.is_use_my_metrics ())) &&
|
||||||
!glyf_accelerator.glyph_for_gid (item.get_gid ())
|
!glyf_accelerator.glyph_for_gid (item_gid)
|
||||||
.get_points (font,
|
.get_points (font,
|
||||||
glyf_accelerator,
|
glyf_accelerator,
|
||||||
all_points,
|
all_points,
|
||||||
@ -410,9 +479,13 @@ struct Glyph
|
|||||||
use_my_metrics,
|
use_my_metrics,
|
||||||
phantom_only,
|
phantom_only,
|
||||||
coords,
|
coords,
|
||||||
|
current_glyphs,
|
||||||
depth + 1,
|
depth + 1,
|
||||||
edge_count)))
|
edge_count)))
|
||||||
|
{
|
||||||
|
current_glyphs->del (item_gid);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto comp_points = all_points.as_array ().sub_array (old_count);
|
auto comp_points = all_points.as_array ().sub_array (old_count);
|
||||||
|
|
||||||
@ -448,9 +521,13 @@ struct Glyph
|
|||||||
all_points.resize (all_points.length - PHANTOM_COUNT);
|
all_points.resize (all_points.length - PHANTOM_COUNT);
|
||||||
|
|
||||||
if (all_points.length > HB_GLYF_MAX_POINTS)
|
if (all_points.length > HB_GLYF_MAX_POINTS)
|
||||||
|
{
|
||||||
|
current_glyphs->del (item_gid);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
comp_index++;
|
comp_index++;
|
||||||
|
current_glyphs->del (item_gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (head_maxp_info && depth == 0)
|
if (head_maxp_info && depth == 0)
|
||||||
@ -468,6 +545,13 @@ struct Glyph
|
|||||||
hb_array_t<contour_point_t> points_left = points.as_array ();
|
hb_array_t<contour_point_t> points_left = points.as_array ();
|
||||||
for (auto &item : get_var_composite_iterator ())
|
for (auto &item : get_var_composite_iterator ())
|
||||||
{
|
{
|
||||||
|
hb_codepoint_t item_gid = item.get_gid ();
|
||||||
|
|
||||||
|
if (unlikely (current_glyphs->has (item_gid)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
current_glyphs->add (item_gid);
|
||||||
|
|
||||||
unsigned item_num_points = item.get_num_points ();
|
unsigned item_num_points = item.get_num_points ();
|
||||||
hb_array_t<contour_point_t> record_points = points_left.sub_array (0, item_num_points);
|
hb_array_t<contour_point_t> record_points = points_left.sub_array (0, item_num_points);
|
||||||
assert (record_points.length == item_num_points);
|
assert (record_points.length == item_num_points);
|
||||||
@ -485,7 +569,7 @@ struct Glyph
|
|||||||
unsigned old_count = all_points.length;
|
unsigned old_count = all_points.length;
|
||||||
|
|
||||||
if (unlikely ((!phantom_only || (use_my_metrics && item.is_use_my_metrics ())) &&
|
if (unlikely ((!phantom_only || (use_my_metrics && item.is_use_my_metrics ())) &&
|
||||||
!glyf_accelerator.glyph_for_gid (item.get_gid ())
|
!glyf_accelerator.glyph_for_gid (item_gid)
|
||||||
.get_points (font,
|
.get_points (font,
|
||||||
glyf_accelerator,
|
glyf_accelerator,
|
||||||
all_points,
|
all_points,
|
||||||
@ -496,9 +580,13 @@ struct Glyph
|
|||||||
use_my_metrics,
|
use_my_metrics,
|
||||||
phantom_only,
|
phantom_only,
|
||||||
coord_setter.get_coords (),
|
coord_setter.get_coords (),
|
||||||
|
current_glyphs,
|
||||||
depth + 1,
|
depth + 1,
|
||||||
edge_count)))
|
edge_count)))
|
||||||
|
{
|
||||||
|
current_glyphs->del (item_gid);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto comp_points = all_points.as_array ().sub_array (old_count);
|
auto comp_points = all_points.as_array ().sub_array (old_count);
|
||||||
|
|
||||||
@ -514,9 +602,14 @@ struct Glyph
|
|||||||
all_points.resize (all_points.length - PHANTOM_COUNT);
|
all_points.resize (all_points.length - PHANTOM_COUNT);
|
||||||
|
|
||||||
if (all_points.length > HB_GLYF_MAX_POINTS)
|
if (all_points.length > HB_GLYF_MAX_POINTS)
|
||||||
|
{
|
||||||
|
current_glyphs->del (item_gid);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
points_left += item_num_points;
|
points_left += item_num_points;
|
||||||
|
|
||||||
|
current_glyphs->del (item_gid);
|
||||||
}
|
}
|
||||||
all_points.extend (phantoms);
|
all_points.extend (phantoms);
|
||||||
} break;
|
} break;
|
||||||
|
23
src/3rdparty/harfbuzz-ng/src/graph/graph.hh
vendored
23
src/3rdparty/harfbuzz-ng/src/graph/graph.hh
vendored
@ -290,7 +290,7 @@ struct graph_t
|
|||||||
new_parents.set (id_map[_.first], _.second);
|
new_parents.set (id_map[_.first], _.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new_parents.in_error ())
|
if (parents.in_error() || new_parents.in_error ())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
parents = std::move (new_parents);
|
parents = std::move (new_parents);
|
||||||
@ -310,8 +310,15 @@ struct graph_t
|
|||||||
if (parents.has (old_index, &pv))
|
if (parents.has (old_index, &pv))
|
||||||
{
|
{
|
||||||
unsigned v = *pv;
|
unsigned v = *pv;
|
||||||
parents.set (new_index, v);
|
if (!parents.set (new_index, v))
|
||||||
|
incoming_edges_ -= v;
|
||||||
parents.del (old_index);
|
parents.del (old_index);
|
||||||
|
|
||||||
|
if (incoming_edges_ == 1)
|
||||||
|
{
|
||||||
|
single_parent = *parents.keys ();
|
||||||
|
parents.reset ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -467,6 +474,18 @@ struct graph_t
|
|||||||
return root ().equals (other.root (), *this, other, 0);
|
return root ().equals (other.root (), *this, other, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print () const {
|
||||||
|
for (int i = vertices_.length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
const auto& v = vertices_[i];
|
||||||
|
printf("%d: %lu [", i, v.table_size());
|
||||||
|
for (const auto &l : v.obj.real_links) {
|
||||||
|
printf("%u, ", l.objidx);
|
||||||
|
}
|
||||||
|
printf("]\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Sorts links of all objects in a consistent manner and zeroes all offsets.
|
// Sorts links of all objects in a consistent manner and zeroes all offsets.
|
||||||
void normalize ()
|
void normalize ()
|
||||||
{
|
{
|
||||||
|
@ -40,7 +40,7 @@ struct gsubgpos_graph_context_t
|
|||||||
graph_t& graph;
|
graph_t& graph;
|
||||||
unsigned lookup_list_index;
|
unsigned lookup_list_index;
|
||||||
hb_hashmap_t<unsigned, graph::Lookup*> lookups;
|
hb_hashmap_t<unsigned, graph::Lookup*> lookups;
|
||||||
|
hb_hashmap_t<unsigned, unsigned> subtable_to_extension;
|
||||||
|
|
||||||
HB_INTERNAL gsubgpos_graph_context_t (hb_tag_t table_tag_,
|
HB_INTERNAL gsubgpos_graph_context_t (hb_tag_t table_tag_,
|
||||||
graph_t& graph_);
|
graph_t& graph_);
|
||||||
|
@ -299,23 +299,34 @@ struct Lookup : public OT::Lookup
|
|||||||
unsigned subtable_index)
|
unsigned subtable_index)
|
||||||
{
|
{
|
||||||
unsigned type = lookupType;
|
unsigned type = lookupType;
|
||||||
|
unsigned ext_index = -1;
|
||||||
|
unsigned* existing_ext_index = nullptr;
|
||||||
|
if (c.subtable_to_extension.has(subtable_index, &existing_ext_index)) {
|
||||||
|
ext_index = *existing_ext_index;
|
||||||
|
} else {
|
||||||
|
ext_index = create_extension_subtable(c, subtable_index, type);
|
||||||
|
c.subtable_to_extension.set(subtable_index, ext_index);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned ext_index = create_extension_subtable(c, subtable_index, type);
|
|
||||||
if (ext_index == (unsigned) -1)
|
if (ext_index == (unsigned) -1)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
auto& subtable_vertex = c.graph.vertices_[subtable_index];
|
||||||
auto& lookup_vertex = c.graph.vertices_[lookup_index];
|
auto& lookup_vertex = c.graph.vertices_[lookup_index];
|
||||||
for (auto& l : lookup_vertex.obj.real_links.writer ())
|
for (auto& l : lookup_vertex.obj.real_links.writer ())
|
||||||
{
|
{
|
||||||
if (l.objidx == subtable_index)
|
if (l.objidx == subtable_index) {
|
||||||
// Change lookup to point at the extension.
|
// Change lookup to point at the extension.
|
||||||
l.objidx = ext_index;
|
l.objidx = ext_index;
|
||||||
|
if (existing_ext_index)
|
||||||
|
subtable_vertex.remove_parent(lookup_index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make extension point at the subtable.
|
// Make extension point at the subtable.
|
||||||
auto& ext_vertex = c.graph.vertices_[ext_index];
|
auto& ext_vertex = c.graph.vertices_[ext_index];
|
||||||
auto& subtable_vertex = c.graph.vertices_[subtable_index];
|
|
||||||
ext_vertex.add_parent (lookup_index);
|
ext_vertex.add_parent (lookup_index);
|
||||||
|
if (!existing_ext_index)
|
||||||
subtable_vertex.remap_parent (lookup_index, ext_index);
|
subtable_vertex.remap_parent (lookup_index, ext_index);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -318,7 +318,9 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
|||||||
{
|
{
|
||||||
hb_vector_t<class_info_t> class_to_info;
|
hb_vector_t<class_info_t> class_to_info;
|
||||||
|
|
||||||
unsigned class_count= classCount;
|
unsigned class_count = classCount;
|
||||||
|
if (!class_count) return class_to_info;
|
||||||
|
|
||||||
if (!class_to_info.resize (class_count))
|
if (!class_to_info.resize (class_count))
|
||||||
return hb_vector_t<class_info_t>();
|
return hb_vector_t<class_info_t>();
|
||||||
|
|
||||||
|
4
src/3rdparty/harfbuzz-ng/src/hb-algs.hh
vendored
4
src/3rdparty/harfbuzz-ng/src/hb-algs.hh
vendored
@ -367,6 +367,10 @@ struct
|
|||||||
hb_enable_if (std::is_integral<T>::value && sizeof (T) > sizeof (uint32_t))> constexpr auto
|
hb_enable_if (std::is_integral<T>::value && sizeof (T) > sizeof (uint32_t))> constexpr auto
|
||||||
impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, (uint32_t) (v ^ (v >> 32)) * 2654435761u /* Knuth's multiplicative hash */)
|
impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, (uint32_t) (v ^ (v >> 32)) * 2654435761u /* Knuth's multiplicative hash */)
|
||||||
|
|
||||||
|
template <typename T,
|
||||||
|
hb_enable_if (std::is_floating_point<T>::value)> constexpr auto
|
||||||
|
impl (const T& v, hb_priority<1>) const HB_RETURN (uint32_t, fasthash32 (std::addressof (v), sizeof (T), 0xf437ffe6))
|
||||||
|
|
||||||
template <typename T> constexpr auto
|
template <typename T> constexpr auto
|
||||||
impl (const T& v, hb_priority<0>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))
|
impl (const T& v, hb_priority<0>) const HB_RETURN (uint32_t, std::hash<hb_decay<decltype (hb_deref (v))>>{} (hb_deref (v)))
|
||||||
|
|
||||||
|
2
src/3rdparty/harfbuzz-ng/src/hb-bimap.hh
vendored
2
src/3rdparty/harfbuzz-ng/src/hb-bimap.hh
vendored
@ -93,7 +93,7 @@ struct hb_bimap_t
|
|||||||
auto iter () const HB_AUTO_RETURN (+ forw_map.iter())
|
auto iter () const HB_AUTO_RETURN (+ forw_map.iter())
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Inremental bimap: only lhs is given, rhs is incrementally assigned */
|
/* Incremental bimap: only lhs is given, rhs is incrementally assigned */
|
||||||
struct hb_inc_bimap_t
|
struct hb_inc_bimap_t
|
||||||
{
|
{
|
||||||
bool in_error () const { return forw_map.in_error () || back_map.in_error (); }
|
bool in_error () const { return forw_map.in_error () || back_map.in_error (); }
|
||||||
|
3
src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh
vendored
3
src/3rdparty/harfbuzz-ng/src/hb-bit-page.hh
vendored
@ -97,6 +97,7 @@ struct hb_bit_page_t
|
|||||||
static inline constexpr unsigned len ()
|
static inline constexpr unsigned len ()
|
||||||
{ return ARRAY_LENGTH_CONST (v); }
|
{ return ARRAY_LENGTH_CONST (v); }
|
||||||
|
|
||||||
|
operator bool () const { return !is_empty (); }
|
||||||
bool is_empty () const
|
bool is_empty () const
|
||||||
{
|
{
|
||||||
if (has_population ()) return !population;
|
if (has_population ()) return !population;
|
||||||
@ -218,6 +219,7 @@ struct hb_bit_page_t
|
|||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator == (const hb_bit_page_t &other) const { return is_equal (other); }
|
||||||
bool is_equal (const hb_bit_page_t &other) const
|
bool is_equal (const hb_bit_page_t &other) const
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < len (); i++)
|
for (unsigned i = 0; i < len (); i++)
|
||||||
@ -225,6 +227,7 @@ struct hb_bit_page_t
|
|||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
bool operator <= (const hb_bit_page_t &larger_page) const { return is_subset (larger_page); }
|
||||||
bool is_subset (const hb_bit_page_t &larger_page) const
|
bool is_subset (const hb_bit_page_t &larger_page) const
|
||||||
{
|
{
|
||||||
if (has_population () && larger_page.has_population () &&
|
if (has_population () && larger_page.has_population () &&
|
||||||
|
4
src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh
vendored
4
src/3rdparty/harfbuzz-ng/src/hb-bit-set.hh
vendored
@ -913,7 +913,7 @@ struct hb_bit_set_t
|
|||||||
|
|
||||||
/* The extra page_map length is necessary; can't just rely on vector here,
|
/* The extra page_map length is necessary; can't just rely on vector here,
|
||||||
* since the next check would be tricked because a null page also has
|
* since the next check would be tricked because a null page also has
|
||||||
* major==0, which we can't distinguish from an actualy major==0 page... */
|
* major==0, which we can't distinguish from an actually major==0 page... */
|
||||||
unsigned i = last_page_lookup;
|
unsigned i = last_page_lookup;
|
||||||
if (likely (i < page_map.length))
|
if (likely (i < page_map.length))
|
||||||
{
|
{
|
||||||
@ -947,7 +947,7 @@ struct hb_bit_set_t
|
|||||||
|
|
||||||
/* The extra page_map length is necessary; can't just rely on vector here,
|
/* The extra page_map length is necessary; can't just rely on vector here,
|
||||||
* since the next check would be tricked because a null page also has
|
* since the next check would be tricked because a null page also has
|
||||||
* major==0, which we can't distinguish from an actualy major==0 page... */
|
* major==0, which we can't distinguish from an actually major==0 page... */
|
||||||
unsigned i = last_page_lookup;
|
unsigned i = last_page_lookup;
|
||||||
if (likely (i < page_map.length))
|
if (likely (i < page_map.length))
|
||||||
{
|
{
|
||||||
|
4
src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
vendored
4
src/3rdparty/harfbuzz-ng/src/hb-buffer.cc
vendored
@ -1327,7 +1327,7 @@ hb_buffer_get_invisible_glyph (const hb_buffer_t *buffer)
|
|||||||
* Sets the #hb_codepoint_t that replaces characters not found in
|
* Sets the #hb_codepoint_t that replaces characters not found in
|
||||||
* the font during shaping.
|
* the font during shaping.
|
||||||
*
|
*
|
||||||
* The not-found glyph defaults to zero, sometimes knows as the
|
* The not-found glyph defaults to zero, sometimes known as the
|
||||||
* ".notdef" glyph. This API allows for differentiating the two.
|
* ".notdef" glyph. This API allows for differentiating the two.
|
||||||
*
|
*
|
||||||
* Since: 3.1.0
|
* Since: 3.1.0
|
||||||
@ -2076,7 +2076,7 @@ hb_buffer_t::sort (unsigned int start, unsigned int end, int(*compar)(const hb_g
|
|||||||
* hb_buffer_diff:
|
* hb_buffer_diff:
|
||||||
* @buffer: a buffer.
|
* @buffer: a buffer.
|
||||||
* @reference: other buffer to compare to.
|
* @reference: other buffer to compare to.
|
||||||
* @dottedcircle_glyph: glyph id of U+25CC DOTTED CIRCLE, or (hb_codepont_t) -1.
|
* @dottedcircle_glyph: glyph id of U+25CC DOTTED CIRCLE, or (hb_codepoint_t) -1.
|
||||||
* @position_fuzz: allowed absolute difference in position values.
|
* @position_fuzz: allowed absolute difference in position values.
|
||||||
*
|
*
|
||||||
* If dottedcircle_glyph is (hb_codepoint_t) -1 then #HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT
|
* If dottedcircle_glyph is (hb_codepoint_t) -1 then #HB_BUFFER_DIFF_FLAG_DOTTED_CIRCLE_PRESENT
|
||||||
|
2
src/3rdparty/harfbuzz-ng/src/hb-buffer.h
vendored
2
src/3rdparty/harfbuzz-ng/src/hb-buffer.h
vendored
@ -99,7 +99,7 @@ typedef struct hb_glyph_info_t {
|
|||||||
* layout, by avoiding re-shaping of each line
|
* layout, by avoiding re-shaping of each line
|
||||||
* after line-breaking, by limiting the
|
* after line-breaking, by limiting the
|
||||||
* reshaping to a small piece around the
|
* reshaping to a small piece around the
|
||||||
* breaking positin only, even if the breaking
|
* breaking position only, even if the breaking
|
||||||
* position carries the
|
* position carries the
|
||||||
* #HB_GLYPH_FLAG_UNSAFE_TO_BREAK or when
|
* #HB_GLYPH_FLAG_UNSAFE_TO_BREAK or when
|
||||||
* hyphenation or other text transformation
|
* hyphenation or other text transformation
|
||||||
|
27
src/3rdparty/harfbuzz-ng/src/hb-cairo.cc
vendored
27
src/3rdparty/harfbuzz-ng/src/hb-cairo.cc
vendored
@ -166,6 +166,32 @@ hb_cairo_pop_transform (hb_paint_funcs_t *pfuncs HB_UNUSED,
|
|||||||
cairo_restore (cr);
|
cairo_restore (cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static hb_bool_t
|
||||||
|
hb_cairo_paint_color_glyph (hb_paint_funcs_t *pfuncs HB_UNUSED,
|
||||||
|
void *paint_data,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
hb_font_t *font,
|
||||||
|
void *user_data HB_UNUSED)
|
||||||
|
{
|
||||||
|
hb_cairo_context_t *c = (hb_cairo_context_t *) paint_data;
|
||||||
|
cairo_t *cr = c->cr;
|
||||||
|
|
||||||
|
cairo_save (cr);
|
||||||
|
|
||||||
|
hb_position_t x_scale, y_scale;
|
||||||
|
hb_font_get_scale (font, &x_scale, &y_scale);
|
||||||
|
cairo_scale (cr, x_scale, y_scale);
|
||||||
|
|
||||||
|
cairo_glyph_t cairo_glyph = { glyph, 0, 0 };
|
||||||
|
cairo_set_scaled_font (cr, c->scaled_font);
|
||||||
|
cairo_set_font_size (cr, 1);
|
||||||
|
cairo_show_glyphs (cr, &cairo_glyph, 1);
|
||||||
|
|
||||||
|
cairo_restore (cr);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
hb_cairo_push_clip_glyph (hb_paint_funcs_t *pfuncs HB_UNUSED,
|
hb_cairo_push_clip_glyph (hb_paint_funcs_t *pfuncs HB_UNUSED,
|
||||||
void *paint_data,
|
void *paint_data,
|
||||||
@ -397,6 +423,7 @@ static struct hb_cairo_paint_funcs_lazy_loader_t : hb_paint_funcs_lazy_loader_t<
|
|||||||
|
|
||||||
hb_paint_funcs_set_push_transform_func (funcs, hb_cairo_push_transform, nullptr, nullptr);
|
hb_paint_funcs_set_push_transform_func (funcs, hb_cairo_push_transform, nullptr, nullptr);
|
||||||
hb_paint_funcs_set_pop_transform_func (funcs, hb_cairo_pop_transform, nullptr, nullptr);
|
hb_paint_funcs_set_pop_transform_func (funcs, hb_cairo_pop_transform, nullptr, nullptr);
|
||||||
|
hb_paint_funcs_set_color_glyph_func (funcs, hb_cairo_paint_color_glyph, nullptr, nullptr);
|
||||||
hb_paint_funcs_set_push_clip_glyph_func (funcs, hb_cairo_push_clip_glyph, nullptr, nullptr);
|
hb_paint_funcs_set_push_clip_glyph_func (funcs, hb_cairo_push_clip_glyph, nullptr, nullptr);
|
||||||
hb_paint_funcs_set_push_clip_rectangle_func (funcs, hb_cairo_push_clip_rectangle, nullptr, nullptr);
|
hb_paint_funcs_set_push_clip_rectangle_func (funcs, hb_cairo_push_clip_rectangle, nullptr, nullptr);
|
||||||
hb_paint_funcs_set_pop_clip_func (funcs, hb_cairo_pop_clip, nullptr, nullptr);
|
hb_paint_funcs_set_pop_clip_func (funcs, hb_cairo_pop_clip, nullptr, nullptr);
|
||||||
|
2
src/3rdparty/harfbuzz-ng/src/hb-common.cc
vendored
2
src/3rdparty/harfbuzz-ng/src/hb-common.cc
vendored
@ -815,7 +815,7 @@ parse_tag (const char **pp, const char *end, hb_tag_t *tag)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *p = *pp;
|
const char *p = *pp;
|
||||||
while (*pp < end && (ISALNUM(**pp) || **pp == '_'))
|
while (*pp < end && (**pp != ' ' && **pp != '=' && **pp != '['))
|
||||||
(*pp)++;
|
(*pp)++;
|
||||||
|
|
||||||
if (p == *pp || *pp - p > 4)
|
if (p == *pp || *pp - p > 4)
|
||||||
|
19
src/3rdparty/harfbuzz-ng/src/hb-debug.hh
vendored
19
src/3rdparty/harfbuzz-ng/src/hb-debug.hh
vendored
@ -265,8 +265,9 @@ static inline void _hb_warn_no_return (bool returned)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
template <>
|
template <>
|
||||||
/*static*/ inline void _hb_warn_no_return<hb_empty_t> (bool returned HB_UNUSED)
|
/*static*/ inline void _hb_warn_no_return<hb_empty_t> (bool returned HB_UNUSED) {}
|
||||||
{}
|
template <>
|
||||||
|
/*static*/ inline void _hb_warn_no_return<void> (bool returned HB_UNUSED) {}
|
||||||
|
|
||||||
template <int max_level, typename ret_t>
|
template <int max_level, typename ret_t>
|
||||||
struct hb_auto_trace_t
|
struct hb_auto_trace_t
|
||||||
@ -450,12 +451,26 @@ struct hb_no_trace_t {
|
|||||||
#define HB_DEBUG_SUBSET_REPACK (HB_DEBUG+0)
|
#define HB_DEBUG_SUBSET_REPACK (HB_DEBUG+0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef HB_DEBUG_PAINT
|
||||||
|
#define HB_DEBUG_PAINT (HB_DEBUG+0)
|
||||||
|
#endif
|
||||||
|
#if HB_DEBUG_PAINT
|
||||||
|
#define TRACE_PAINT(this) \
|
||||||
|
HB_UNUSED hb_auto_trace_t<HB_DEBUG_PAINT, void> trace \
|
||||||
|
(&c->debug_depth, c->get_name (), this, HB_FUNC, \
|
||||||
|
" ")
|
||||||
|
#else
|
||||||
|
#define TRACE_PAINT(this) HB_UNUSED hb_no_trace_t<void> trace
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifndef HB_DEBUG_DISPATCH
|
#ifndef HB_DEBUG_DISPATCH
|
||||||
#define HB_DEBUG_DISPATCH ( \
|
#define HB_DEBUG_DISPATCH ( \
|
||||||
HB_DEBUG_APPLY + \
|
HB_DEBUG_APPLY + \
|
||||||
HB_DEBUG_SANITIZE + \
|
HB_DEBUG_SANITIZE + \
|
||||||
HB_DEBUG_SERIALIZE + \
|
HB_DEBUG_SERIALIZE + \
|
||||||
HB_DEBUG_SUBSET + \
|
HB_DEBUG_SUBSET + \
|
||||||
|
HB_DEBUG_PAINT + \
|
||||||
0)
|
0)
|
||||||
#endif
|
#endif
|
||||||
#if HB_DEBUG_DISPATCH
|
#if HB_DEBUG_DISPATCH
|
||||||
|
2
src/3rdparty/harfbuzz-ng/src/hb-font.cc
vendored
2
src/3rdparty/harfbuzz-ng/src/hb-font.cc
vendored
@ -1066,7 +1066,7 @@ hb_font_get_nominal_glyph (hb_font_t *font,
|
|||||||
* @glyph_stride: The stride between successive glyph IDs
|
* @glyph_stride: The stride between successive glyph IDs
|
||||||
*
|
*
|
||||||
* Fetches the nominal glyph IDs for a sequence of Unicode code points. Glyph
|
* Fetches the nominal glyph IDs for a sequence of Unicode code points. Glyph
|
||||||
* IDs must be returned in a #hb_codepoint_t output parameter. Stopes at the
|
* IDs must be returned in a #hb_codepoint_t output parameter. Stops at the
|
||||||
* first unsupported glyph ID.
|
* first unsupported glyph ID.
|
||||||
*
|
*
|
||||||
* Return value: the number of code points processed
|
* Return value: the number of code points processed
|
||||||
|
36
src/3rdparty/harfbuzz-ng/src/hb-ft-colr.hh
vendored
36
src/3rdparty/harfbuzz-ng/src/hb-ft-colr.hh
vendored
@ -105,6 +105,8 @@ struct hb_ft_paint_context_t
|
|||||||
FT_Color *palette;
|
FT_Color *palette;
|
||||||
unsigned palette_index;
|
unsigned palette_index;
|
||||||
hb_color_t foreground;
|
hb_color_t foreground;
|
||||||
|
hb_map_t current_glyphs;
|
||||||
|
hb_map_t current_layers;
|
||||||
int depth_left = HB_MAX_NESTING_LEVEL;
|
int depth_left = HB_MAX_NESTING_LEVEL;
|
||||||
int edge_count = HB_COLRV1_MAX_EDGE_COUNT;
|
int edge_count = HB_COLRV1_MAX_EDGE_COUNT;
|
||||||
};
|
};
|
||||||
@ -220,9 +222,18 @@ _hb_ft_paint (hb_ft_paint_context_t *c,
|
|||||||
&paint.u.colr_layers.layer_iterator,
|
&paint.u.colr_layers.layer_iterator,
|
||||||
&other_paint))
|
&other_paint))
|
||||||
{
|
{
|
||||||
|
unsigned i = paint.u.colr_layers.layer_iterator.layer;
|
||||||
|
|
||||||
|
if (unlikely (c->current_layers.has (i)))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
c->current_layers.add (i);
|
||||||
|
|
||||||
c->funcs->push_group (c->data);
|
c->funcs->push_group (c->data);
|
||||||
c->recurse (other_paint);
|
c->recurse (other_paint);
|
||||||
c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
|
c->funcs->pop_group (c->data, HB_PAINT_COMPOSITE_MODE_SRC_OVER);
|
||||||
|
|
||||||
|
c->current_layers.del (i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -320,8 +331,27 @@ _hb_ft_paint (hb_ft_paint_context_t *c,
|
|||||||
break;
|
break;
|
||||||
case FT_COLR_PAINTFORMAT_COLR_GLYPH:
|
case FT_COLR_PAINTFORMAT_COLR_GLYPH:
|
||||||
{
|
{
|
||||||
|
hb_codepoint_t gid = paint.u.colr_glyph.glyphID;
|
||||||
|
|
||||||
|
if (unlikely (c->current_glyphs.has (gid)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
c->current_glyphs.add (gid);
|
||||||
|
|
||||||
|
c->funcs->push_inverse_root_transform (c->data, c->font);
|
||||||
|
c->ft_font->lock.unlock ();
|
||||||
|
if (c->funcs->color_glyph (c->data, gid, c->font))
|
||||||
|
{
|
||||||
|
c->ft_font->lock.lock ();
|
||||||
|
c->funcs->pop_transform (c->data);
|
||||||
|
c->current_glyphs.del (gid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
c->ft_font->lock.lock ();
|
||||||
|
c->funcs->pop_transform (c->data);
|
||||||
|
|
||||||
FT_OpaquePaint other_paint = {0};
|
FT_OpaquePaint other_paint = {0};
|
||||||
if (FT_Get_Color_Glyph_Paint (ft_face, paint.u.colr_glyph.glyphID,
|
if (FT_Get_Color_Glyph_Paint (ft_face, gid,
|
||||||
FT_COLOR_NO_ROOT_TRANSFORM,
|
FT_COLOR_NO_ROOT_TRANSFORM,
|
||||||
&other_paint))
|
&other_paint))
|
||||||
{
|
{
|
||||||
@ -350,6 +380,8 @@ _hb_ft_paint (hb_ft_paint_context_t *c,
|
|||||||
|
|
||||||
if (has_clip_box)
|
if (has_clip_box)
|
||||||
c->funcs->pop_clip (c->data);
|
c->funcs->pop_clip (c->data);
|
||||||
|
|
||||||
|
c->current_glyphs.del (gid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -474,6 +506,7 @@ hb_ft_paint_glyph_colr (hb_font_t *font,
|
|||||||
hb_ft_paint_context_t c (ft_font, font,
|
hb_ft_paint_context_t c (ft_font, font,
|
||||||
paint_funcs, paint_data,
|
paint_funcs, paint_data,
|
||||||
palette, palette_index, foreground);
|
palette, palette_index, foreground);
|
||||||
|
c.current_glyphs.add (gid);
|
||||||
|
|
||||||
bool is_bounded = true;
|
bool is_bounded = true;
|
||||||
FT_ClipBox clip_box;
|
FT_ClipBox clip_box;
|
||||||
@ -497,6 +530,7 @@ hb_ft_paint_glyph_colr (hb_font_t *font,
|
|||||||
hb_ft_paint_context_t ce (ft_font, font,
|
hb_ft_paint_context_t ce (ft_font, font,
|
||||||
extents_funcs, &extents_data,
|
extents_funcs, &extents_data,
|
||||||
palette, palette_index, foreground);
|
palette, palette_index, foreground);
|
||||||
|
ce.current_glyphs.add (gid);
|
||||||
ce.funcs->push_root_transform (ce.data, font);
|
ce.funcs->push_root_transform (ce.data, font);
|
||||||
ce.recurse (paint);
|
ce.recurse (paint);
|
||||||
ce.funcs->pop_transform (ce.data);
|
ce.funcs->pop_transform (ce.data);
|
||||||
|
2
src/3rdparty/harfbuzz-ng/src/hb-limits.hh
vendored
2
src/3rdparty/harfbuzz-ng/src/hb-limits.hh
vendored
@ -106,7 +106,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef HB_COLRV1_MAX_EDGE_COUNT
|
#ifndef HB_COLRV1_MAX_EDGE_COUNT
|
||||||
#define HB_COLRV1_MAX_EDGE_COUNT 1024
|
#define HB_COLRV1_MAX_EDGE_COUNT 65536
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
2
src/3rdparty/harfbuzz-ng/src/hb-map.cc
vendored
2
src/3rdparty/harfbuzz-ng/src/hb-map.cc
vendored
@ -365,7 +365,7 @@ hb_map_update (hb_map_t *map,
|
|||||||
* @key: (out): Key retrieved
|
* @key: (out): Key retrieved
|
||||||
* @value: (out): Value retrieved
|
* @value: (out): Value retrieved
|
||||||
*
|
*
|
||||||
* Fetches the next key/value paire in @map.
|
* Fetches the next key/value pair in @map.
|
||||||
*
|
*
|
||||||
* Set @idx to -1 to get started.
|
* Set @idx to -1 to get started.
|
||||||
*
|
*
|
||||||
|
5
src/3rdparty/harfbuzz-ng/src/hb-map.hh
vendored
5
src/3rdparty/harfbuzz-ng/src/hb-map.hh
vendored
@ -276,6 +276,11 @@ struct hb_hashmap_t
|
|||||||
uint32_t hash = hb_hash (key);
|
uint32_t hash = hb_hash (key);
|
||||||
return set_with_hash (std::move (key), hash, std::forward<VV> (value), overwrite);
|
return set_with_hash (std::move (key), hash, std::forward<VV> (value), overwrite);
|
||||||
}
|
}
|
||||||
|
bool add (const K &key)
|
||||||
|
{
|
||||||
|
uint32_t hash = hb_hash (key);
|
||||||
|
return set_with_hash (key, hash, item_t::default_value ());
|
||||||
|
}
|
||||||
|
|
||||||
const V& get_with_hash (const K &key, uint32_t hash) const
|
const V& get_with_hash (const K &key, uint32_t hash) const
|
||||||
{
|
{
|
||||||
|
2
src/3rdparty/harfbuzz-ng/src/hb-null.hh
vendored
2
src/3rdparty/harfbuzz-ng/src/hb-null.hh
vendored
@ -85,7 +85,7 @@ using hb_null_size = _hb_null_size<T, void>;
|
|||||||
template <typename T, typename>
|
template <typename T, typename>
|
||||||
struct _hb_static_size : hb_integral_constant<unsigned, sizeof (T)> {};
|
struct _hb_static_size : hb_integral_constant<unsigned, sizeof (T)> {};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
struct _hb_static_size<T, hb_void_t<decltype (T::min_size)>> : hb_integral_constant<unsigned, T::static_size> {};
|
struct _hb_static_size<T, hb_void_t<decltype (T::static_size)>> : hb_integral_constant<unsigned, T::static_size> {};
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using hb_static_size = _hb_static_size<T, void>;
|
using hb_static_size = _hb_static_size<T, void>;
|
||||||
#define hb_static_size(T) hb_static_size<T>::value
|
#define hb_static_size(T) hb_static_size<T>::value
|
||||||
|
@ -3215,8 +3215,7 @@ struct FeatureTableSubstitutionRecord
|
|||||||
if (unlikely (!out)) return_trace (false);
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
out->featureIndex = c->feature_index_map->get (featureIndex);
|
out->featureIndex = c->feature_index_map->get (featureIndex);
|
||||||
bool ret = out->feature.serialize_subset (c->subset_context, feature, base, c);
|
return_trace (out->feature.serialize_subset (c->subset_context, feature, base, c));
|
||||||
return_trace (ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||||
|
2
src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
vendored
2
src/3rdparty/harfbuzz-ng/src/hb-ot-shape.cc
vendored
@ -1054,7 +1054,7 @@ hb_ot_position_plan (const hb_ot_shape_context_t *c)
|
|||||||
* direction is backward we don't shift and it will end up
|
* direction is backward we don't shift and it will end up
|
||||||
* hanging over the next glyph after the final reordering.
|
* hanging over the next glyph after the final reordering.
|
||||||
*
|
*
|
||||||
* Note: If fallback positinoing happens, we don't care about
|
* Note: If fallback positioning happens, we don't care about
|
||||||
* this as it will be overridden.
|
* this as it will be overridden.
|
||||||
*/
|
*/
|
||||||
bool adjust_offsets_when_zeroing = c->plan->adjust_mark_positioning_when_zeroing &&
|
bool adjust_offsets_when_zeroing = c->plan->adjust_mark_positioning_when_zeroing &&
|
||||||
|
@ -486,8 +486,10 @@ apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||||||
if (likely (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH)))
|
if (likely (!(buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_ARABIC_HAS_STCH)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* The Arabic shaper currently always processes in RTL mode, so we should
|
bool rtl = buffer->props.direction == HB_DIRECTION_RTL;
|
||||||
* stretch / position the stretched pieces to the left / preceding glyphs. */
|
|
||||||
|
if (!rtl)
|
||||||
|
buffer->reverse ();
|
||||||
|
|
||||||
/* We do a two pass implementation:
|
/* We do a two pass implementation:
|
||||||
* First pass calculates the exact number of extra glyphs we need,
|
* First pass calculates the exact number of extra glyphs we need,
|
||||||
@ -577,7 +579,10 @@ apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||||||
++n_copies;
|
++n_copies;
|
||||||
hb_position_t excess = (n_copies + 1) * sign * w_repeating - sign * w_remaining;
|
hb_position_t excess = (n_copies + 1) * sign * w_repeating - sign * w_remaining;
|
||||||
if (excess > 0)
|
if (excess > 0)
|
||||||
|
{
|
||||||
extra_repeat_overlap = excess / (n_copies * n_repeating);
|
extra_repeat_overlap = excess / (n_copies * n_repeating);
|
||||||
|
w_remaining = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (step == MEASURE)
|
if (step == MEASURE)
|
||||||
@ -588,7 +593,7 @@ apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
buffer->unsafe_to_break (context, end);
|
buffer->unsafe_to_break (context, end);
|
||||||
hb_position_t x_offset = 0;
|
hb_position_t x_offset = w_remaining / 2;
|
||||||
for (unsigned int k = end; k > start; k--)
|
for (unsigned int k = end; k > start; k--)
|
||||||
{
|
{
|
||||||
hb_position_t width = font->get_glyph_h_advance (info[k - 1].codepoint);
|
hb_position_t width = font->get_glyph_h_advance (info[k - 1].codepoint);
|
||||||
@ -599,16 +604,27 @@ apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||||||
|
|
||||||
DEBUG_MSG (ARABIC, nullptr, "appending %u copies of glyph %u; j=%u",
|
DEBUG_MSG (ARABIC, nullptr, "appending %u copies of glyph %u; j=%u",
|
||||||
repeat, info[k - 1].codepoint, j);
|
repeat, info[k - 1].codepoint, j);
|
||||||
|
pos[k - 1].x_advance = 0;
|
||||||
for (unsigned int n = 0; n < repeat; n++)
|
for (unsigned int n = 0; n < repeat; n++)
|
||||||
|
{
|
||||||
|
if (rtl)
|
||||||
{
|
{
|
||||||
x_offset -= width;
|
x_offset -= width;
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
x_offset += extra_repeat_overlap;
|
x_offset += extra_repeat_overlap;
|
||||||
|
}
|
||||||
pos[k - 1].x_offset = x_offset;
|
pos[k - 1].x_offset = x_offset;
|
||||||
/* Append copy. */
|
/* Append copy. */
|
||||||
--j;
|
--j;
|
||||||
info[j] = info[k - 1];
|
info[j] = info[k - 1];
|
||||||
pos[j] = pos[k - 1];
|
pos[j] = pos[k - 1];
|
||||||
|
|
||||||
|
if (!rtl)
|
||||||
|
{
|
||||||
|
x_offset += width;
|
||||||
|
if (n > 0)
|
||||||
|
x_offset -= extra_repeat_overlap;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -625,6 +641,9 @@ apply_stch (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||||||
buffer->len = new_len;
|
buffer->len = new_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!rtl)
|
||||||
|
buffer->reverse ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
269
src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh
vendored
269
src/3rdparty/harfbuzz-ng/src/hb-ot-var-common.hh
vendored
@ -230,7 +230,7 @@ struct VarStoreInstancer
|
|||||||
/* according to the spec, if colr table has varStore but does not have
|
/* according to the spec, if colr table has varStore but does not have
|
||||||
* varIdxMap, then an implicit identity mapping is used */
|
* 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 ? varIdxMap->map (VarIdx::add (varIdx, offset)) : varIdx + offset, coords); }
|
{ return coords ? varStore->get_delta (varIdxMap ? varIdxMap->map (VarIdx::add (varIdx, offset)) : varIdx + offset, coords) : 0; }
|
||||||
|
|
||||||
const VariationStore *varStore;
|
const VariationStore *varStore;
|
||||||
const DeltaSetIndexMap *varIdxMap;
|
const DeltaSetIndexMap *varIdxMap;
|
||||||
@ -449,17 +449,26 @@ struct tuple_delta_t
|
|||||||
hb_vector_t<char> compiled_tuple_header;
|
hb_vector_t<char> compiled_tuple_header;
|
||||||
hb_vector_t<char> compiled_deltas;
|
hb_vector_t<char> compiled_deltas;
|
||||||
|
|
||||||
|
/* compiled peak coords, empty for non-gvar tuples */
|
||||||
|
hb_vector_t<char> compiled_peak_coords;
|
||||||
|
|
||||||
tuple_delta_t () = default;
|
tuple_delta_t () = default;
|
||||||
tuple_delta_t (const tuple_delta_t& o) = default;
|
tuple_delta_t (const tuple_delta_t& o) = default;
|
||||||
|
|
||||||
tuple_delta_t (tuple_delta_t&& o) : tuple_delta_t ()
|
friend void swap (tuple_delta_t& a, tuple_delta_t& b)
|
||||||
{
|
{
|
||||||
axis_tuples = std::move (o.axis_tuples);
|
hb_swap (a.axis_tuples, b.axis_tuples);
|
||||||
indices = std::move (o.indices);
|
hb_swap (a.indices, b.indices);
|
||||||
deltas_x = std::move (o.deltas_x);
|
hb_swap (a.deltas_x, b.deltas_x);
|
||||||
deltas_y = std::move (o.deltas_y);
|
hb_swap (a.deltas_y, b.deltas_y);
|
||||||
|
hb_swap (a.compiled_tuple_header, b.compiled_tuple_header);
|
||||||
|
hb_swap (a.compiled_deltas, b.compiled_deltas);
|
||||||
|
hb_swap (a.compiled_peak_coords, b.compiled_peak_coords);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tuple_delta_t (tuple_delta_t&& o) : tuple_delta_t ()
|
||||||
|
{ hb_swap (*this, o); }
|
||||||
|
|
||||||
tuple_delta_t& operator = (tuple_delta_t&& o)
|
tuple_delta_t& operator = (tuple_delta_t&& o)
|
||||||
{
|
{
|
||||||
hb_swap (*this, o);
|
hb_swap (*this, o);
|
||||||
@ -552,13 +561,43 @@ struct tuple_delta_t
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool compile_peak_coords (const hb_map_t& axes_index_map,
|
||||||
|
const hb_map_t& axes_old_index_tag_map)
|
||||||
|
{
|
||||||
|
unsigned axis_count = axes_index_map.get_population ();
|
||||||
|
if (unlikely (!compiled_peak_coords.alloc (axis_count * F2DOT14::static_size)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
unsigned orig_axis_count = axes_old_index_tag_map.get_population ();
|
||||||
|
for (unsigned i = 0; i < orig_axis_count; i++)
|
||||||
|
{
|
||||||
|
if (!axes_index_map.has (i))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
hb_tag_t axis_tag = axes_old_index_tag_map.get (i);
|
||||||
|
Triple *coords;
|
||||||
|
F2DOT14 peak_coord;
|
||||||
|
if (axis_tuples.has (axis_tag, &coords))
|
||||||
|
peak_coord.set_float (coords->middle);
|
||||||
|
else
|
||||||
|
peak_coord.set_int (0);
|
||||||
|
|
||||||
|
/* push F2DOT14 value into char vector */
|
||||||
|
int16_t val = peak_coord.to_int ();
|
||||||
|
compiled_peak_coords.push (static_cast<char> (val >> 8));
|
||||||
|
compiled_peak_coords.push (static_cast<char> (val & 0xFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
return !compiled_peak_coords.in_error ();
|
||||||
|
}
|
||||||
|
|
||||||
/* deltas should be compiled already before we compile tuple
|
/* deltas should be compiled already before we compile tuple
|
||||||
* variation header cause we need to fill in the size of the
|
* variation header cause we need to fill in the size of the
|
||||||
* serialized data for this tuple variation */
|
* serialized data for this tuple variation */
|
||||||
//TODO(qxliu):add option to use sharedTuples in gvar
|
|
||||||
bool compile_tuple_var_header (const hb_map_t& axes_index_map,
|
bool compile_tuple_var_header (const hb_map_t& axes_index_map,
|
||||||
unsigned points_data_length,
|
unsigned points_data_length,
|
||||||
const hb_map_t& axes_old_index_tag_map)
|
const hb_map_t& axes_old_index_tag_map,
|
||||||
|
const hb_hashmap_t<const hb_vector_t<char>*, unsigned>* shared_tuples_idx_map)
|
||||||
{
|
{
|
||||||
if (!compiled_deltas) return false;
|
if (!compiled_deltas) return false;
|
||||||
|
|
||||||
@ -574,13 +613,24 @@ struct tuple_delta_t
|
|||||||
hb_array_t<F2DOT14> coords (p, end - p);
|
hb_array_t<F2DOT14> coords (p, end - p);
|
||||||
|
|
||||||
/* encode peak coords */
|
/* encode peak coords */
|
||||||
unsigned peak_count = encode_peak_coords(coords, flag, axes_index_map, axes_old_index_tag_map);
|
unsigned peak_count = 0;
|
||||||
|
unsigned *shared_tuple_idx;
|
||||||
|
if (shared_tuples_idx_map &&
|
||||||
|
shared_tuples_idx_map->has (&compiled_peak_coords, &shared_tuple_idx))
|
||||||
|
{
|
||||||
|
flag = *shared_tuple_idx;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
peak_count = encode_peak_coords(coords, flag, axes_index_map, axes_old_index_tag_map);
|
||||||
if (!peak_count) return false;
|
if (!peak_count) return false;
|
||||||
|
}
|
||||||
|
|
||||||
/* encode interim coords, it's optional so returned num could be 0 */
|
/* encode interim coords, it's optional so returned num could be 0 */
|
||||||
unsigned interim_count = encode_interm_coords (coords.sub_array (peak_count), flag, axes_index_map, axes_old_index_tag_map);
|
unsigned interim_count = encode_interm_coords (coords.sub_array (peak_count), flag, axes_index_map, axes_old_index_tag_map);
|
||||||
|
|
||||||
//TODO(qxliu): add option to use shared_points in gvar
|
/* pointdata length = 0 implies "use shared points" */
|
||||||
|
if (points_data_length)
|
||||||
flag |= TupleVariationHeader::TuppleIndex::PrivatePointNumbers;
|
flag |= TupleVariationHeader::TuppleIndex::PrivatePointNumbers;
|
||||||
|
|
||||||
unsigned serialized_data_size = points_data_length + compiled_deltas.length;
|
unsigned serialized_data_size = points_data_length + compiled_deltas.length;
|
||||||
@ -870,6 +920,111 @@ struct tuple_delta_t
|
|||||||
}
|
}
|
||||||
return encoded_len;
|
return encoded_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool calc_inferred_deltas (const contour_point_vector_t& orig_points)
|
||||||
|
{
|
||||||
|
unsigned point_count = orig_points.length;
|
||||||
|
if (point_count != indices.length)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
unsigned ref_count = 0;
|
||||||
|
hb_vector_t<unsigned> end_points;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < point_count; i++)
|
||||||
|
{
|
||||||
|
if (indices.arrayZ[i])
|
||||||
|
ref_count++;
|
||||||
|
if (orig_points.arrayZ[i].is_end_point)
|
||||||
|
end_points.push (i);
|
||||||
|
}
|
||||||
|
/* all points are referenced, nothing to do */
|
||||||
|
if (ref_count == point_count)
|
||||||
|
return true;
|
||||||
|
if (unlikely (end_points.in_error ())) return false;
|
||||||
|
|
||||||
|
hb_set_t inferred_idxes;
|
||||||
|
unsigned start_point = 0;
|
||||||
|
for (unsigned end_point : end_points)
|
||||||
|
{
|
||||||
|
/* Check the number of unreferenced points in a contour. If no unref points or no ref points, nothing to do. */
|
||||||
|
unsigned unref_count = 0;
|
||||||
|
for (unsigned i = start_point; i < end_point + 1; i++)
|
||||||
|
unref_count += indices.arrayZ[i];
|
||||||
|
unref_count = (end_point - start_point + 1) - unref_count;
|
||||||
|
|
||||||
|
unsigned j = start_point;
|
||||||
|
if (unref_count == 0 || unref_count > end_point - start_point)
|
||||||
|
goto no_more_gaps;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
/* Locate the next gap of unreferenced points between two referenced points prev and next.
|
||||||
|
* Note that a gap may wrap around at left (start_point) and/or at right (end_point).
|
||||||
|
*/
|
||||||
|
unsigned int prev, next, i;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
i = j;
|
||||||
|
j = next_index (i, start_point, end_point);
|
||||||
|
if (indices.arrayZ[i] && !indices.arrayZ[j]) break;
|
||||||
|
}
|
||||||
|
prev = j = i;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
i = j;
|
||||||
|
j = next_index (i, start_point, end_point);
|
||||||
|
if (!indices.arrayZ[i] && indices.arrayZ[j]) break;
|
||||||
|
}
|
||||||
|
next = j;
|
||||||
|
/* Infer deltas for all unref points in the gap between prev and next */
|
||||||
|
i = prev;
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
i = next_index (i, start_point, end_point);
|
||||||
|
if (i == next) break;
|
||||||
|
deltas_x.arrayZ[i] = infer_delta (orig_points.arrayZ[i].x, orig_points.arrayZ[prev].x, orig_points.arrayZ[next].x,
|
||||||
|
deltas_x.arrayZ[prev], deltas_x.arrayZ[next]);
|
||||||
|
deltas_y.arrayZ[i] = infer_delta (orig_points.arrayZ[i].y, orig_points.arrayZ[prev].y, orig_points.arrayZ[next].y,
|
||||||
|
deltas_y.arrayZ[prev], deltas_y.arrayZ[next]);
|
||||||
|
inferred_idxes.add (i);
|
||||||
|
if (--unref_count == 0) goto no_more_gaps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
no_more_gaps:
|
||||||
|
start_point = end_point + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < point_count; i++)
|
||||||
|
{
|
||||||
|
/* if points are not referenced and deltas are not inferred, set to 0.
|
||||||
|
* reference all points for gvar */
|
||||||
|
if ( !indices[i])
|
||||||
|
{
|
||||||
|
if (!inferred_idxes.has (i))
|
||||||
|
{
|
||||||
|
deltas_x.arrayZ[i] = 0.f;
|
||||||
|
deltas_y.arrayZ[i] = 0.f;
|
||||||
|
}
|
||||||
|
indices[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static float infer_delta (float target_val, float prev_val, float next_val, float prev_delta, float next_delta)
|
||||||
|
{
|
||||||
|
if (prev_val == next_val)
|
||||||
|
return (prev_delta == next_delta) ? prev_delta : 0.f;
|
||||||
|
else if (target_val <= hb_min (prev_val, next_val))
|
||||||
|
return (prev_val < next_val) ? prev_delta : next_delta;
|
||||||
|
else if (target_val >= hb_max (prev_val, next_val))
|
||||||
|
return (prev_val > next_val) ? prev_delta : next_delta;
|
||||||
|
|
||||||
|
float r = (target_val - prev_val) / (next_val - prev_val);
|
||||||
|
return prev_delta + r * (next_delta - prev_delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int next_index (unsigned int i, unsigned int start, unsigned int end)
|
||||||
|
{ return (i >= end) ? start : (i + 1); }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TupleVariationData
|
struct TupleVariationData
|
||||||
@ -910,7 +1065,22 @@ struct TupleVariationData
|
|||||||
/* referenced point set-> count map, used in finding shared points */
|
/* referenced point set-> count map, used in finding shared points */
|
||||||
hb_hashmap_t<const hb_vector_t<bool>*, unsigned> point_set_count_map;
|
hb_hashmap_t<const hb_vector_t<bool>*, unsigned> point_set_count_map;
|
||||||
|
|
||||||
|
/* empty for non-gvar tuples.
|
||||||
|
* shared_points_bytes is just a copy of some value in the point_data_map,
|
||||||
|
* which will be freed during map destruction. Save it for serialization, so
|
||||||
|
* no need to do find_shared_points () again */
|
||||||
|
hb_bytes_t shared_points_bytes;
|
||||||
|
|
||||||
|
/* total compiled byte size as TupleVariationData format, initialized to its
|
||||||
|
* min_size: 4 */
|
||||||
|
unsigned compiled_byte_size = 4;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
tuple_variations_t () = default;
|
||||||
|
tuple_variations_t (const tuple_variations_t&) = delete;
|
||||||
|
tuple_variations_t& operator=(const tuple_variations_t&) = delete;
|
||||||
|
tuple_variations_t (tuple_variations_t&&) = default;
|
||||||
|
tuple_variations_t& operator=(tuple_variations_t&&) = default;
|
||||||
~tuple_variations_t () { fini (); }
|
~tuple_variations_t () { fini (); }
|
||||||
void fini ()
|
void fini ()
|
||||||
{
|
{
|
||||||
@ -921,8 +1091,17 @@ struct TupleVariationData
|
|||||||
tuple_vars.fini ();
|
tuple_vars.fini ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
explicit operator bool () const { return bool (tuple_vars); }
|
||||||
unsigned get_var_count () const
|
unsigned get_var_count () const
|
||||||
{ return tuple_vars.length; }
|
{
|
||||||
|
unsigned count = tuple_vars.length;
|
||||||
|
if (shared_points_bytes.length)
|
||||||
|
count |= TupleVarCount::SharedPointNumbers;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned get_compiled_byte_size () const
|
||||||
|
{ return compiled_byte_size; }
|
||||||
|
|
||||||
bool create_from_tuple_var_data (tuple_iterator_t iterator,
|
bool create_from_tuple_var_data (tuple_iterator_t iterator,
|
||||||
unsigned tuple_var_count,
|
unsigned tuple_var_count,
|
||||||
@ -992,6 +1171,7 @@ struct TupleVariationData
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
void change_tuple_variations_axis_limits (const hb_hashmap_t<hb_tag_t, Triple>& normalized_axes_location,
|
void change_tuple_variations_axis_limits (const hb_hashmap_t<hb_tag_t, Triple>& normalized_axes_location,
|
||||||
const hb_hashmap_t<hb_tag_t, TripleDistances>& axes_triple_distances)
|
const hb_hashmap_t<hb_tag_t, TripleDistances>& axes_triple_distances)
|
||||||
{
|
{
|
||||||
@ -1025,7 +1205,7 @@ struct TupleVariationData
|
|||||||
void merge_tuple_variations ()
|
void merge_tuple_variations ()
|
||||||
{
|
{
|
||||||
hb_vector_t<tuple_delta_t> new_vars;
|
hb_vector_t<tuple_delta_t> new_vars;
|
||||||
hb_hashmap_t<hb_hashmap_t<hb_tag_t, Triple>, unsigned> m;
|
hb_hashmap_t<const hb_hashmap_t<hb_tag_t, Triple>*, unsigned> m;
|
||||||
unsigned i = 0;
|
unsigned i = 0;
|
||||||
for (const tuple_delta_t& var : tuple_vars)
|
for (const tuple_delta_t& var : tuple_vars)
|
||||||
{
|
{
|
||||||
@ -1033,14 +1213,14 @@ struct TupleVariationData
|
|||||||
if (var.axis_tuples.is_empty ()) continue;
|
if (var.axis_tuples.is_empty ()) continue;
|
||||||
|
|
||||||
unsigned *idx;
|
unsigned *idx;
|
||||||
if (m.has (var.axis_tuples, &idx))
|
if (m.has (&(var.axis_tuples), &idx))
|
||||||
{
|
{
|
||||||
new_vars[*idx] += var;
|
new_vars[*idx] += var;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
new_vars.push (var);
|
new_vars.push (var);
|
||||||
m.set (var.axis_tuples, i);
|
m.set (&(var.axis_tuples), i);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1187,19 +1367,45 @@ struct TupleVariationData
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void instantiate (const hb_hashmap_t<hb_tag_t, Triple>& normalized_axes_location,
|
bool calc_inferred_deltas (contour_point_vector_t& contour_points)
|
||||||
const hb_hashmap_t<hb_tag_t, TripleDistances>& axes_triple_distances)
|
|
||||||
{
|
{
|
||||||
|
for (tuple_delta_t& var : tuple_vars)
|
||||||
|
if (!var.calc_inferred_deltas (contour_points))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool instantiate (const hb_hashmap_t<hb_tag_t, Triple>& normalized_axes_location,
|
||||||
|
const hb_hashmap_t<hb_tag_t, TripleDistances>& axes_triple_distances,
|
||||||
|
contour_point_vector_t* contour_points = nullptr)
|
||||||
|
{
|
||||||
|
if (!tuple_vars) return true;
|
||||||
change_tuple_variations_axis_limits (normalized_axes_location, axes_triple_distances);
|
change_tuple_variations_axis_limits (normalized_axes_location, axes_triple_distances);
|
||||||
|
/* compute inferred deltas only for gvar */
|
||||||
|
if (contour_points)
|
||||||
|
if (!calc_inferred_deltas (*contour_points))
|
||||||
|
return false;
|
||||||
|
|
||||||
merge_tuple_variations ();
|
merge_tuple_variations ();
|
||||||
|
return !tuple_vars.in_error ();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool compile_bytes (const hb_map_t& axes_index_map,
|
bool compile_bytes (const hb_map_t& axes_index_map,
|
||||||
const hb_map_t& axes_old_index_tag_map)
|
const hb_map_t& axes_old_index_tag_map,
|
||||||
|
bool use_shared_points,
|
||||||
|
const hb_hashmap_t<const hb_vector_t<char>*, unsigned>* shared_tuples_idx_map = nullptr)
|
||||||
{
|
{
|
||||||
// compile points set and store data in hashmap
|
// compile points set and store data in hashmap
|
||||||
if (!compile_all_point_sets ())
|
if (!compile_all_point_sets ())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (use_shared_points)
|
||||||
|
{
|
||||||
|
shared_points_bytes = find_shared_points ();
|
||||||
|
compiled_byte_size += shared_points_bytes.length;
|
||||||
|
}
|
||||||
// compile delta and tuple var header for each tuple variation
|
// compile delta and tuple var header for each tuple variation
|
||||||
for (auto& tuple: tuple_vars)
|
for (auto& tuple: tuple_vars)
|
||||||
{
|
{
|
||||||
@ -1211,8 +1417,11 @@ struct TupleVariationData
|
|||||||
if (!tuple.compile_deltas ())
|
if (!tuple.compile_deltas ())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!tuple.compile_tuple_var_header (axes_index_map, points_data->length, axes_old_index_tag_map))
|
unsigned points_data_length = (*points_data != shared_points_bytes) ? points_data->length : 0;
|
||||||
|
if (!tuple.compile_tuple_var_header (axes_index_map, points_data_length, axes_old_index_tag_map,
|
||||||
|
shared_tuples_idx_map))
|
||||||
return false;
|
return false;
|
||||||
|
compiled_byte_size += tuple.compiled_tuple_header.length + points_data_length + tuple.compiled_deltas.length;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1229,9 +1438,12 @@ struct TupleVariationData
|
|||||||
return_trace (true);
|
return_trace (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool serialize_var_data (hb_serialize_context_t *c) const
|
bool serialize_var_data (hb_serialize_context_t *c, bool is_gvar) const
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
|
if (is_gvar)
|
||||||
|
shared_points_bytes.copy (c);
|
||||||
|
|
||||||
for (const auto& tuple: tuple_vars)
|
for (const auto& tuple: tuple_vars)
|
||||||
{
|
{
|
||||||
const hb_vector_t<bool>* points_set = &(tuple.indices);
|
const hb_vector_t<bool>* points_set = &(tuple.indices);
|
||||||
@ -1239,10 +1451,20 @@ struct TupleVariationData
|
|||||||
if (!point_data_map.has (points_set, &point_data))
|
if (!point_data_map.has (points_set, &point_data))
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
|
|
||||||
|
if (!is_gvar || *point_data != shared_points_bytes)
|
||||||
point_data->copy (c);
|
point_data->copy (c);
|
||||||
|
|
||||||
tuple.compiled_deltas.as_array ().copy (c);
|
tuple.compiled_deltas.as_array ().copy (c);
|
||||||
if (c->in_error ()) return_trace (false);
|
if (c->in_error ()) return_trace (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* padding for gvar */
|
||||||
|
if (is_gvar && (compiled_byte_size % 2))
|
||||||
|
{
|
||||||
|
HBUINT8 pad;
|
||||||
|
pad = 0;
|
||||||
|
if (!c->embed (pad)) return_trace (false);
|
||||||
|
}
|
||||||
return_trace (true);
|
return_trace (true);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1428,9 +1650,12 @@ struct TupleVariationData
|
|||||||
|
|
||||||
bool serialize (hb_serialize_context_t *c,
|
bool serialize (hb_serialize_context_t *c,
|
||||||
bool is_gvar,
|
bool is_gvar,
|
||||||
tuple_variations_t& tuple_variations) const
|
const tuple_variations_t& tuple_variations) const
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
|
/* empty tuple variations, just return and skip serialization. */
|
||||||
|
if (!tuple_variations) return_trace (true);
|
||||||
|
|
||||||
auto *out = c->start_embed (this);
|
auto *out = c->start_embed (this);
|
||||||
if (unlikely (!c->extend_min (out))) return_trace (false);
|
if (unlikely (!c->extend_min (out))) return_trace (false);
|
||||||
|
|
||||||
@ -1446,15 +1671,17 @@ struct TupleVariationData
|
|||||||
if (!is_gvar) data_offset += 4;
|
if (!is_gvar) data_offset += 4;
|
||||||
if (!c->check_assign (out->data, data_offset, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
|
if (!c->check_assign (out->data, data_offset, HB_SERIALIZE_ERROR_INT_OVERFLOW)) return_trace (false);
|
||||||
|
|
||||||
return tuple_variations.serialize_var_data (c);
|
return tuple_variations.serialize_var_data (c, is_gvar);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct TupleVarCount : HBUINT16
|
struct TupleVarCount : HBUINT16
|
||||||
{
|
{
|
||||||
|
friend struct tuple_variations_t;
|
||||||
bool has_shared_point_numbers () const { return ((*this) & SharedPointNumbers); }
|
bool has_shared_point_numbers () const { return ((*this) & SharedPointNumbers); }
|
||||||
unsigned int get_count () const { return (*this) & CountMask; }
|
unsigned int get_count () const { return (*this) & CountMask; }
|
||||||
TupleVarCount& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; }
|
TupleVarCount& operator = (uint16_t i) { HBUINT16::operator= (i); return *this; }
|
||||||
|
explicit operator bool () const { return get_count (); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum Flags
|
enum Flags
|
||||||
|
@ -131,6 +131,7 @@ struct cvar
|
|||||||
TupleVariationData::tuple_variations_t& tuple_variations) const
|
TupleVariationData::tuple_variations_t& tuple_variations) const
|
||||||
{
|
{
|
||||||
TRACE_SERIALIZE (this);
|
TRACE_SERIALIZE (this);
|
||||||
|
if (!tuple_variations) return_trace (false);
|
||||||
if (unlikely (!c->embed (version))) return_trace (false);
|
if (unlikely (!c->embed (version))) return_trace (false);
|
||||||
|
|
||||||
return_trace (tupleVariationData.serialize (c, false, tuple_variations));
|
return_trace (tupleVariationData.serialize (c, false, tuple_variations));
|
||||||
@ -168,8 +169,11 @@ struct cvar
|
|||||||
tuple_variations))
|
tuple_variations))
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
|
|
||||||
tuple_variations.instantiate (c->plan->axes_location, c->plan->axes_triple_distances);
|
if (!tuple_variations.instantiate (c->plan->axes_location, c->plan->axes_triple_distances))
|
||||||
if (!tuple_variations.compile_bytes (c->plan->axes_index_map, c->plan->axes_old_index_tag_map))
|
return_trace (false);
|
||||||
|
|
||||||
|
if (!tuple_variations.compile_bytes (c->plan->axes_index_map, c->plan->axes_old_index_tag_map,
|
||||||
|
false /* do not use shared points */))
|
||||||
return_trace (false);
|
return_trace (false);
|
||||||
|
|
||||||
return_trace (serialize (c->serializer, tuple_variations));
|
return_trace (serialize (c->serializer, tuple_variations));
|
||||||
|
373
src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh
vendored
373
src/3rdparty/harfbuzz-ng/src/hb-ot-var-gvar-table.hh
vendored
@ -39,43 +39,256 @@
|
|||||||
|
|
||||||
namespace OT {
|
namespace OT {
|
||||||
|
|
||||||
struct contour_point_t
|
|
||||||
{
|
|
||||||
void init (float x_ = 0.f, float y_ = 0.f, bool is_end_point_ = false)
|
|
||||||
{ flag = 0; x = x_; y = y_; is_end_point = is_end_point_; }
|
|
||||||
|
|
||||||
void transform (const float (&matrix)[4])
|
|
||||||
{
|
|
||||||
float x_ = x * matrix[0] + y * matrix[2];
|
|
||||||
y = x * matrix[1] + y * matrix[3];
|
|
||||||
x = x_;
|
|
||||||
}
|
|
||||||
HB_ALWAYS_INLINE
|
|
||||||
void translate (const contour_point_t &p) { x += p.x; y += p.y; }
|
|
||||||
|
|
||||||
|
|
||||||
float x;
|
|
||||||
float y;
|
|
||||||
uint8_t flag;
|
|
||||||
bool is_end_point;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct contour_point_vector_t : hb_vector_t<contour_point_t>
|
|
||||||
{
|
|
||||||
void extend (const hb_array_t<contour_point_t> &a)
|
|
||||||
{
|
|
||||||
unsigned int old_len = length;
|
|
||||||
if (unlikely (!resize (old_len + a.length, false)))
|
|
||||||
return;
|
|
||||||
auto arrayZ = this->arrayZ + old_len;
|
|
||||||
unsigned count = a.length;
|
|
||||||
hb_memcpy (arrayZ, a.arrayZ, count * sizeof (arrayZ[0]));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct GlyphVariationData : TupleVariationData
|
struct GlyphVariationData : TupleVariationData
|
||||||
{};
|
{};
|
||||||
|
|
||||||
|
struct glyph_variations_t
|
||||||
|
{
|
||||||
|
using tuple_variations_t = TupleVariationData::tuple_variations_t;
|
||||||
|
hb_vector_t<tuple_variations_t> glyph_variations;
|
||||||
|
|
||||||
|
hb_vector_t<char> compiled_shared_tuples;
|
||||||
|
private:
|
||||||
|
unsigned shared_tuples_count = 0;
|
||||||
|
|
||||||
|
/* shared coords-> index map after instantiation */
|
||||||
|
hb_hashmap_t<const hb_vector_t<char>*, unsigned> shared_tuples_idx_map;
|
||||||
|
|
||||||
|
public:
|
||||||
|
unsigned compiled_shared_tuples_count () const
|
||||||
|
{ return shared_tuples_count; }
|
||||||
|
|
||||||
|
unsigned compiled_byte_size () const
|
||||||
|
{
|
||||||
|
unsigned byte_size = 0;
|
||||||
|
for (const auto& _ : glyph_variations)
|
||||||
|
byte_size += _.get_compiled_byte_size ();
|
||||||
|
|
||||||
|
return byte_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool create_from_glyphs_var_data (unsigned axis_count,
|
||||||
|
const hb_array_t<const F2DOT14> shared_tuples,
|
||||||
|
const hb_subset_plan_t *plan,
|
||||||
|
const hb_hashmap_t<hb_codepoint_t, hb_bytes_t>& new_gid_var_data_map)
|
||||||
|
{
|
||||||
|
if (unlikely (!glyph_variations.alloc (plan->new_to_old_gid_list.length, true)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto it = hb_iter (plan->new_to_old_gid_list);
|
||||||
|
for (auto &_ : it)
|
||||||
|
{
|
||||||
|
hb_codepoint_t new_gid = _.first;
|
||||||
|
contour_point_vector_t *all_contour_points;
|
||||||
|
if (!new_gid_var_data_map.has (new_gid) ||
|
||||||
|
!plan->new_gid_contour_points_map.has (new_gid, &all_contour_points))
|
||||||
|
return false;
|
||||||
|
hb_bytes_t var_data = new_gid_var_data_map.get (new_gid);
|
||||||
|
|
||||||
|
const GlyphVariationData* p = reinterpret_cast<const GlyphVariationData*> (var_data.arrayZ);
|
||||||
|
hb_vector_t<unsigned> shared_indices;
|
||||||
|
GlyphVariationData::tuple_iterator_t iterator;
|
||||||
|
tuple_variations_t tuple_vars;
|
||||||
|
|
||||||
|
/* in case variation data is empty, push an empty struct into the vector,
|
||||||
|
* keep the vector in sync with the new_to_old_gid_list */
|
||||||
|
if (!var_data || ! p->has_data () || !all_contour_points->length ||
|
||||||
|
!GlyphVariationData::get_tuple_iterator (var_data, axis_count,
|
||||||
|
var_data.arrayZ,
|
||||||
|
shared_indices, &iterator))
|
||||||
|
{
|
||||||
|
glyph_variations.push (std::move (tuple_vars));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!p->decompile_tuple_variations (all_contour_points->length, true /* is_gvar */,
|
||||||
|
iterator, &(plan->axes_old_index_tag_map),
|
||||||
|
shared_indices, shared_tuples,
|
||||||
|
tuple_vars /* OUT */))
|
||||||
|
return false;
|
||||||
|
glyph_variations.push (std::move (tuple_vars));
|
||||||
|
}
|
||||||
|
return !glyph_variations.in_error () && glyph_variations.length == plan->new_to_old_gid_list.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool instantiate (const hb_subset_plan_t *plan)
|
||||||
|
{
|
||||||
|
unsigned count = plan->new_to_old_gid_list.length;
|
||||||
|
for (unsigned i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
hb_codepoint_t new_gid = plan->new_to_old_gid_list[i].first;
|
||||||
|
contour_point_vector_t *all_points;
|
||||||
|
if (!plan->new_gid_contour_points_map.has (new_gid, &all_points))
|
||||||
|
return false;
|
||||||
|
if (!glyph_variations[i].instantiate (plan->axes_location, plan->axes_triple_distances, all_points))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool compile_bytes (const hb_map_t& axes_index_map,
|
||||||
|
const hb_map_t& axes_old_index_tag_map)
|
||||||
|
{
|
||||||
|
if (!compile_shared_tuples (axes_index_map, axes_old_index_tag_map))
|
||||||
|
return false;
|
||||||
|
for (tuple_variations_t& vars: glyph_variations)
|
||||||
|
if (!vars.compile_bytes (axes_index_map, axes_old_index_tag_map,
|
||||||
|
true, /* use shared points*/
|
||||||
|
&shared_tuples_idx_map))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool compile_shared_tuples (const hb_map_t& axes_index_map,
|
||||||
|
const hb_map_t& axes_old_index_tag_map)
|
||||||
|
{
|
||||||
|
/* key is pointer to compiled_peak_coords inside each tuple, hashing
|
||||||
|
* function will always deref pointers first */
|
||||||
|
hb_hashmap_t<const hb_vector_t<char>*, unsigned> coords_count_map;
|
||||||
|
|
||||||
|
/* count the num of shared coords */
|
||||||
|
for (tuple_variations_t& vars: glyph_variations)
|
||||||
|
{
|
||||||
|
for (tuple_delta_t& var : vars.tuple_vars)
|
||||||
|
{
|
||||||
|
if (!var.compile_peak_coords (axes_index_map, axes_old_index_tag_map))
|
||||||
|
return false;
|
||||||
|
unsigned* count;
|
||||||
|
if (coords_count_map.has (&(var.compiled_peak_coords), &count))
|
||||||
|
coords_count_map.set (&(var.compiled_peak_coords), *count + 1);
|
||||||
|
else
|
||||||
|
coords_count_map.set (&(var.compiled_peak_coords), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!coords_count_map || coords_count_map.in_error ())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* add only those coords that are used more than once into the vector and sort */
|
||||||
|
hb_vector_t<const hb_vector_t<char>*> shared_coords;
|
||||||
|
if (unlikely (!shared_coords.alloc (coords_count_map.get_population ())))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (const auto _ : coords_count_map.iter ())
|
||||||
|
{
|
||||||
|
if (_.second == 1) continue;
|
||||||
|
shared_coords.push (_.first);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no shared tuples: no coords are used more than once */
|
||||||
|
if (!shared_coords) return true;
|
||||||
|
/* sorting based on the coords frequency first (high to low), then compare
|
||||||
|
* the coords bytes */
|
||||||
|
hb_qsort (shared_coords.arrayZ, shared_coords.length, sizeof (hb_vector_t<char>*), _cmp_coords, (void *) (&coords_count_map));
|
||||||
|
|
||||||
|
/* build shared_coords->idx map and shared tuples byte array */
|
||||||
|
|
||||||
|
shared_tuples_count = hb_min (0xFFFu + 1, shared_coords.length);
|
||||||
|
unsigned len = shared_tuples_count * (shared_coords[0]->length);
|
||||||
|
if (unlikely (!compiled_shared_tuples.alloc (len)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < shared_tuples_count; i++)
|
||||||
|
{
|
||||||
|
shared_tuples_idx_map.set (shared_coords[i], i);
|
||||||
|
/* add a concat() in hb_vector_t? */
|
||||||
|
for (char c : shared_coords[i]->iter ())
|
||||||
|
compiled_shared_tuples.push (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _cmp_coords (const void *pa, const void *pb, void *arg)
|
||||||
|
{
|
||||||
|
const hb_hashmap_t<const hb_vector_t<char>*, unsigned>* coords_count_map =
|
||||||
|
reinterpret_cast<const hb_hashmap_t<const hb_vector_t<char>*, unsigned>*> (arg);
|
||||||
|
|
||||||
|
/* shared_coords is hb_vector_t<const hb_vector_t<char>*> so casting pa/pb
|
||||||
|
* to be a pointer to a pointer */
|
||||||
|
const hb_vector_t<char>** a = reinterpret_cast<const hb_vector_t<char>**> (const_cast<void*>(pa));
|
||||||
|
const hb_vector_t<char>** b = reinterpret_cast<const hb_vector_t<char>**> (const_cast<void*>(pb));
|
||||||
|
|
||||||
|
bool has_a = coords_count_map->has (*a);
|
||||||
|
bool has_b = coords_count_map->has (*b);
|
||||||
|
|
||||||
|
if (has_a && has_b)
|
||||||
|
{
|
||||||
|
unsigned a_num = coords_count_map->get (*a);
|
||||||
|
unsigned b_num = coords_count_map->get (*b);
|
||||||
|
|
||||||
|
if (a_num != b_num)
|
||||||
|
return b_num - a_num;
|
||||||
|
|
||||||
|
return (*b)->as_array().cmp ((*a)->as_array ());
|
||||||
|
}
|
||||||
|
else if (has_a) return -1;
|
||||||
|
else if (has_b) return 1;
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Iterator,
|
||||||
|
hb_requires (hb_is_iterator (Iterator))>
|
||||||
|
bool serialize_glyph_var_data (hb_serialize_context_t *c,
|
||||||
|
Iterator it,
|
||||||
|
bool long_offset,
|
||||||
|
unsigned num_glyphs,
|
||||||
|
char* glyph_var_data_offsets /* OUT: glyph var data offsets array */) const
|
||||||
|
{
|
||||||
|
TRACE_SERIALIZE (this);
|
||||||
|
|
||||||
|
if (long_offset)
|
||||||
|
{
|
||||||
|
((HBUINT32 *) glyph_var_data_offsets)[0] = 0;
|
||||||
|
glyph_var_data_offsets += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
((HBUINT16 *) glyph_var_data_offsets)[0] = 0;
|
||||||
|
glyph_var_data_offsets += 2;
|
||||||
|
}
|
||||||
|
unsigned glyph_offset = 0;
|
||||||
|
hb_codepoint_t last_gid = 0;
|
||||||
|
unsigned idx = 0;
|
||||||
|
|
||||||
|
TupleVariationData* cur_glyph = c->start_embed<TupleVariationData> ();
|
||||||
|
if (!cur_glyph) return_trace (false);
|
||||||
|
for (auto &_ : it)
|
||||||
|
{
|
||||||
|
hb_codepoint_t gid = _.first;
|
||||||
|
if (long_offset)
|
||||||
|
for (; last_gid < gid; last_gid++)
|
||||||
|
((HBUINT32 *) glyph_var_data_offsets)[last_gid] = glyph_offset;
|
||||||
|
else
|
||||||
|
for (; last_gid < gid; last_gid++)
|
||||||
|
((HBUINT16 *) glyph_var_data_offsets)[last_gid] = glyph_offset / 2;
|
||||||
|
|
||||||
|
if (idx >= glyph_variations.length) return_trace (false);
|
||||||
|
if (!cur_glyph->serialize (c, true, glyph_variations[idx])) return_trace (false);
|
||||||
|
TupleVariationData* next_glyph = c->start_embed<TupleVariationData> ();
|
||||||
|
glyph_offset += (char *) next_glyph - (char *) cur_glyph;
|
||||||
|
|
||||||
|
if (long_offset)
|
||||||
|
((HBUINT32 *) glyph_var_data_offsets)[gid] = glyph_offset;
|
||||||
|
else
|
||||||
|
((HBUINT16 *) glyph_var_data_offsets)[gid] = glyph_offset / 2;
|
||||||
|
|
||||||
|
last_gid++;
|
||||||
|
idx++;
|
||||||
|
cur_glyph = next_glyph;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (long_offset)
|
||||||
|
for (; last_gid < num_glyphs; last_gid++)
|
||||||
|
((HBUINT32 *) glyph_var_data_offsets)[last_gid] = glyph_offset;
|
||||||
|
else
|
||||||
|
for (; last_gid < num_glyphs; last_gid++)
|
||||||
|
((HBUINT16 *) glyph_var_data_offsets)[last_gid] = glyph_offset / 2;
|
||||||
|
return_trace (true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct gvar
|
struct gvar
|
||||||
{
|
{
|
||||||
static constexpr hb_tag_t tableTag = HB_OT_TAG_gvar;
|
static constexpr hb_tag_t tableTag = HB_OT_TAG_gvar;
|
||||||
@ -94,9 +307,101 @@ struct gvar
|
|||||||
bool sanitize (hb_sanitize_context_t *c) const
|
bool sanitize (hb_sanitize_context_t *c) const
|
||||||
{ return sanitize_shallow (c); }
|
{ return sanitize_shallow (c); }
|
||||||
|
|
||||||
|
bool decompile_glyph_variations (hb_subset_context_t *c,
|
||||||
|
glyph_variations_t& glyph_vars /* OUT */) const
|
||||||
|
{
|
||||||
|
hb_hashmap_t<hb_codepoint_t, hb_bytes_t> new_gid_var_data_map;
|
||||||
|
auto it = hb_iter (c->plan->new_to_old_gid_list);
|
||||||
|
if (it->first == 0 && !(c->plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
|
||||||
|
{
|
||||||
|
new_gid_var_data_map.set (0, hb_bytes_t ());
|
||||||
|
it++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &_ : it)
|
||||||
|
{
|
||||||
|
hb_codepoint_t new_gid = _.first;
|
||||||
|
hb_codepoint_t old_gid = _.second;
|
||||||
|
hb_bytes_t var_data_bytes = get_glyph_var_data_bytes (c->source_blob, glyphCountX, old_gid);
|
||||||
|
new_gid_var_data_map.set (new_gid, var_data_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (new_gid_var_data_map.in_error ()) return false;
|
||||||
|
|
||||||
|
hb_array_t<const F2DOT14> shared_tuples = (this+sharedTuples).as_array ((unsigned) sharedTupleCount * (unsigned) axisCount);
|
||||||
|
return glyph_vars.create_from_glyphs_var_data (axisCount, shared_tuples, c->plan, new_gid_var_data_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Iterator,
|
||||||
|
hb_requires (hb_is_iterator (Iterator))>
|
||||||
|
bool serialize (hb_serialize_context_t *c,
|
||||||
|
const glyph_variations_t& glyph_vars,
|
||||||
|
Iterator it,
|
||||||
|
unsigned axis_count,
|
||||||
|
unsigned num_glyphs) const
|
||||||
|
{
|
||||||
|
TRACE_SERIALIZE (this);
|
||||||
|
gvar *out = c->allocate_min<gvar> ();
|
||||||
|
if (unlikely (!out)) return_trace (false);
|
||||||
|
|
||||||
|
out->version.major = 1;
|
||||||
|
out->version.minor = 0;
|
||||||
|
out->axisCount = axis_count;
|
||||||
|
out->glyphCountX = hb_min (0xFFFFu, num_glyphs);
|
||||||
|
|
||||||
|
unsigned glyph_var_data_size = glyph_vars.compiled_byte_size ();
|
||||||
|
bool long_offset = glyph_var_data_size & ~0xFFFFu;
|
||||||
|
out->flags = long_offset ? 1 : 0;
|
||||||
|
|
||||||
|
HBUINT8 *glyph_var_data_offsets = c->allocate_size<HBUINT8> ((long_offset ? 4 : 2) * (num_glyphs + 1), false);
|
||||||
|
if (!glyph_var_data_offsets) return_trace (false);
|
||||||
|
|
||||||
|
/* shared tuples */
|
||||||
|
unsigned shared_tuple_count = glyph_vars.compiled_shared_tuples_count ();
|
||||||
|
out->sharedTupleCount = shared_tuple_count;
|
||||||
|
|
||||||
|
if (!shared_tuple_count)
|
||||||
|
out->sharedTuples = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hb_array_t<const char> shared_tuples = glyph_vars.compiled_shared_tuples.as_array ().copy (c);
|
||||||
|
if (!shared_tuples.arrayZ) return_trace (false);
|
||||||
|
out->sharedTuples = shared_tuples.arrayZ - (char *) out;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *glyph_var_data = c->start_embed<char> ();
|
||||||
|
if (!glyph_var_data) return_trace (false);
|
||||||
|
out->dataZ = glyph_var_data - (char *) out;
|
||||||
|
|
||||||
|
return_trace (glyph_vars.serialize_glyph_var_data (c, it, long_offset, num_glyphs,
|
||||||
|
(char *) glyph_var_data_offsets));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool instantiate (hb_subset_context_t *c) const
|
||||||
|
{
|
||||||
|
TRACE_SUBSET (this);
|
||||||
|
glyph_variations_t glyph_vars;
|
||||||
|
if (!decompile_glyph_variations (c, glyph_vars))
|
||||||
|
return_trace (false);
|
||||||
|
|
||||||
|
if (!glyph_vars.instantiate (c->plan)) return_trace (false);
|
||||||
|
if (!glyph_vars.compile_bytes (c->plan->axes_index_map, c->plan->axes_old_index_tag_map))
|
||||||
|
return_trace (false);
|
||||||
|
|
||||||
|
unsigned axis_count = c->plan->axes_index_map.get_population ();
|
||||||
|
unsigned num_glyphs = c->plan->num_output_glyphs ();
|
||||||
|
auto it = hb_iter (c->plan->new_to_old_gid_list);
|
||||||
|
return_trace (serialize (c->serializer, glyph_vars, it, axis_count, num_glyphs));
|
||||||
|
}
|
||||||
|
|
||||||
bool subset (hb_subset_context_t *c) const
|
bool subset (hb_subset_context_t *c) const
|
||||||
{
|
{
|
||||||
TRACE_SUBSET (this);
|
TRACE_SUBSET (this);
|
||||||
|
if (c->plan->all_axes_pinned)
|
||||||
|
return_trace (false);
|
||||||
|
|
||||||
|
if (c->plan->normalized_coords)
|
||||||
|
return_trace (instantiate (c));
|
||||||
|
|
||||||
unsigned glyph_count = version.to_int () ? c->plan->source->get_num_glyphs () : 0;
|
unsigned glyph_count = version.to_int () ? c->plan->source->get_num_glyphs () : 0;
|
||||||
|
|
||||||
|
25
src/3rdparty/harfbuzz-ng/src/hb-paint.cc
vendored
25
src/3rdparty/harfbuzz-ng/src/hb-paint.cc
vendored
@ -54,6 +54,12 @@ static void
|
|||||||
hb_paint_pop_transform_nil (hb_paint_funcs_t *funcs, void *paint_data,
|
hb_paint_pop_transform_nil (hb_paint_funcs_t *funcs, void *paint_data,
|
||||||
void *user_data) {}
|
void *user_data) {}
|
||||||
|
|
||||||
|
static hb_bool_t
|
||||||
|
hb_paint_color_glyph_nil (hb_paint_funcs_t *funcs, void *paint_data,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
hb_font_t *font,
|
||||||
|
void *user_data) { return false; }
|
||||||
|
|
||||||
static void
|
static void
|
||||||
hb_paint_push_clip_glyph_nil (hb_paint_funcs_t *funcs, void *paint_data,
|
hb_paint_push_clip_glyph_nil (hb_paint_funcs_t *funcs, void *paint_data,
|
||||||
hb_codepoint_t glyph,
|
hb_codepoint_t glyph,
|
||||||
@ -473,6 +479,25 @@ hb_paint_pop_transform (hb_paint_funcs_t *funcs, void *paint_data)
|
|||||||
funcs->pop_transform (paint_data);
|
funcs->pop_transform (paint_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_paint_color_glyph:
|
||||||
|
* @funcs: paint functions
|
||||||
|
* @paint_data: associated data passed by the caller
|
||||||
|
* @glyph: the glyph ID
|
||||||
|
* @font: the font
|
||||||
|
*
|
||||||
|
* Perform a "color-glyph" paint operation.
|
||||||
|
*
|
||||||
|
* Since: 8.2.0
|
||||||
|
*/
|
||||||
|
hb_bool_t
|
||||||
|
hb_paint_color_glyph (hb_paint_funcs_t *funcs, void *paint_data,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
hb_font_t *font)
|
||||||
|
{
|
||||||
|
return funcs->color_glyph (paint_data, glyph, font);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_paint_push_clip_glyph:
|
* hb_paint_push_clip_glyph:
|
||||||
* @funcs: paint functions
|
* @funcs: paint functions
|
||||||
|
42
src/3rdparty/harfbuzz-ng/src/hb-paint.h
vendored
42
src/3rdparty/harfbuzz-ng/src/hb-paint.h
vendored
@ -136,6 +136,26 @@ typedef void (*hb_paint_pop_transform_func_t) (hb_paint_funcs_t *funcs,
|
|||||||
void *paint_data,
|
void *paint_data,
|
||||||
void *user_data);
|
void *user_data);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_paint_color_glyph_func_t:
|
||||||
|
* @funcs: paint functions object
|
||||||
|
* @paint_data: The data accompanying the paint functions in hb_font_paint_glyph()
|
||||||
|
* @glyph: the glyph ID
|
||||||
|
* @font: the font
|
||||||
|
* @user_data: User data pointer passed to hb_paint_funcs_set_color_glyph_func()
|
||||||
|
*
|
||||||
|
* A virtual method for the #hb_paint_funcs_t to render a color glyph by glyph index.
|
||||||
|
*
|
||||||
|
* Return value: %true if the glyph was painted, %false otherwise.
|
||||||
|
*
|
||||||
|
* Since: 8.2.0
|
||||||
|
*/
|
||||||
|
typedef hb_bool_t (*hb_paint_color_glyph_func_t) (hb_paint_funcs_t *funcs,
|
||||||
|
void *paint_data,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
hb_font_t *font,
|
||||||
|
void *user_data);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_paint_push_clip_glyph_func_t:
|
* hb_paint_push_clip_glyph_func_t:
|
||||||
* @funcs: paint functions object
|
* @funcs: paint functions object
|
||||||
@ -723,6 +743,23 @@ hb_paint_funcs_set_pop_transform_func (hb_paint_funcs_t *funcs,
|
|||||||
void *user_data,
|
void *user_data,
|
||||||
hb_destroy_func_t destroy);
|
hb_destroy_func_t destroy);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* hb_paint_funcs_set_color_glyph_func:
|
||||||
|
* @funcs: A paint functions struct
|
||||||
|
* @func: (closure user_data) (destroy destroy) (scope notified): The color-glyph callback
|
||||||
|
* @user_data: Data to pass to @func
|
||||||
|
* @destroy: (nullable): Function to call when @user_data is no longer needed
|
||||||
|
*
|
||||||
|
* Sets the color-glyph callback on the paint functions struct.
|
||||||
|
*
|
||||||
|
* Since: 8.2.0
|
||||||
|
*/
|
||||||
|
HB_EXTERN void
|
||||||
|
hb_paint_funcs_set_color_glyph_func (hb_paint_funcs_t *funcs,
|
||||||
|
hb_paint_color_glyph_func_t func,
|
||||||
|
void *user_data,
|
||||||
|
hb_destroy_func_t destroy);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* hb_paint_funcs_set_push_clip_glyph_func:
|
* hb_paint_funcs_set_push_clip_glyph_func:
|
||||||
* @funcs: A paint functions struct
|
* @funcs: A paint functions struct
|
||||||
@ -922,6 +959,11 @@ hb_paint_push_transform (hb_paint_funcs_t *funcs, void *paint_data,
|
|||||||
HB_EXTERN void
|
HB_EXTERN void
|
||||||
hb_paint_pop_transform (hb_paint_funcs_t *funcs, void *paint_data);
|
hb_paint_pop_transform (hb_paint_funcs_t *funcs, void *paint_data);
|
||||||
|
|
||||||
|
HB_EXTERN hb_bool_t
|
||||||
|
hb_paint_color_glyph (hb_paint_funcs_t *funcs, void *paint_data,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
hb_font_t *font);
|
||||||
|
|
||||||
HB_EXTERN void
|
HB_EXTERN void
|
||||||
hb_paint_push_clip_glyph (hb_paint_funcs_t *funcs, void *paint_data,
|
hb_paint_push_clip_glyph (hb_paint_funcs_t *funcs, void *paint_data,
|
||||||
hb_codepoint_t glyph,
|
hb_codepoint_t glyph,
|
||||||
|
8
src/3rdparty/harfbuzz-ng/src/hb-paint.hh
vendored
8
src/3rdparty/harfbuzz-ng/src/hb-paint.hh
vendored
@ -32,6 +32,7 @@
|
|||||||
#define HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS \
|
#define HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS \
|
||||||
HB_PAINT_FUNC_IMPLEMENT (push_transform) \
|
HB_PAINT_FUNC_IMPLEMENT (push_transform) \
|
||||||
HB_PAINT_FUNC_IMPLEMENT (pop_transform) \
|
HB_PAINT_FUNC_IMPLEMENT (pop_transform) \
|
||||||
|
HB_PAINT_FUNC_IMPLEMENT (color_glyph) \
|
||||||
HB_PAINT_FUNC_IMPLEMENT (push_clip_glyph) \
|
HB_PAINT_FUNC_IMPLEMENT (push_clip_glyph) \
|
||||||
HB_PAINT_FUNC_IMPLEMENT (push_clip_rectangle) \
|
HB_PAINT_FUNC_IMPLEMENT (push_clip_rectangle) \
|
||||||
HB_PAINT_FUNC_IMPLEMENT (pop_clip) \
|
HB_PAINT_FUNC_IMPLEMENT (pop_clip) \
|
||||||
@ -77,6 +78,13 @@ struct hb_paint_funcs_t
|
|||||||
void pop_transform (void *paint_data)
|
void pop_transform (void *paint_data)
|
||||||
{ func.pop_transform (this, paint_data,
|
{ func.pop_transform (this, paint_data,
|
||||||
!user_data ? nullptr : user_data->pop_transform); }
|
!user_data ? nullptr : user_data->pop_transform); }
|
||||||
|
bool color_glyph (void *paint_data,
|
||||||
|
hb_codepoint_t glyph,
|
||||||
|
hb_font_t *font)
|
||||||
|
{ return func.color_glyph (this, paint_data,
|
||||||
|
glyph,
|
||||||
|
font,
|
||||||
|
!user_data ? nullptr : user_data->push_clip_glyph); }
|
||||||
void push_clip_glyph (void *paint_data,
|
void push_clip_glyph (void *paint_data,
|
||||||
hb_codepoint_t glyph,
|
hb_codepoint_t glyph,
|
||||||
hb_font_t *font)
|
hb_font_t *font)
|
||||||
|
20
src/3rdparty/harfbuzz-ng/src/hb-repacker.hh
vendored
20
src/3rdparty/harfbuzz-ng/src/hb-repacker.hh
vendored
@ -79,7 +79,12 @@ bool _presplit_subtables_if_needed (graph::gsubgpos_graph_context_t& ext_context
|
|||||||
// pass after this processing is done. Not super necessary as splits are
|
// pass after this processing is done. Not super necessary as splits are
|
||||||
// only done where overflow is likely, so de-dup probably will get undone
|
// only done where overflow is likely, so de-dup probably will get undone
|
||||||
// later anyways.
|
// later anyways.
|
||||||
for (unsigned lookup_index : ext_context.lookups.keys ())
|
|
||||||
|
// The loop below can modify the contents of ext_context.lookups if new subtables are added
|
||||||
|
// to a lookup during a split. So save the initial set of lookup indices so the iteration doesn't
|
||||||
|
// risk access free'd memory if ext_context.lookups gets resized.
|
||||||
|
hb_set_t lookup_indices(ext_context.lookups.keys ());
|
||||||
|
for (unsigned lookup_index : lookup_indices)
|
||||||
{
|
{
|
||||||
graph::Lookup* lookup = ext_context.lookups.get(lookup_index);
|
graph::Lookup* lookup = ext_context.lookups.get(lookup_index);
|
||||||
if (!lookup->split_subtables_if_needed (ext_context, lookup_index))
|
if (!lookup->split_subtables_if_needed (ext_context, lookup_index))
|
||||||
@ -114,11 +119,15 @@ bool _promote_extensions_if_needed (graph::gsubgpos_graph_context_t& ext_context
|
|||||||
// TODO(grieger): skip this for the 24 bit case.
|
// TODO(grieger): skip this for the 24 bit case.
|
||||||
if (!ext_context.lookups) return true;
|
if (!ext_context.lookups) return true;
|
||||||
|
|
||||||
|
unsigned total_lookup_table_sizes = 0;
|
||||||
hb_vector_t<lookup_size_t> lookup_sizes;
|
hb_vector_t<lookup_size_t> lookup_sizes;
|
||||||
lookup_sizes.alloc (ext_context.lookups.get_population (), true);
|
lookup_sizes.alloc (ext_context.lookups.get_population (), true);
|
||||||
|
|
||||||
for (unsigned lookup_index : ext_context.lookups.keys ())
|
for (unsigned lookup_index : ext_context.lookups.keys ())
|
||||||
{
|
{
|
||||||
|
const auto& lookup_v = ext_context.graph.vertices_[lookup_index];
|
||||||
|
total_lookup_table_sizes += lookup_v.table_size ();
|
||||||
|
|
||||||
const graph::Lookup* lookup = ext_context.lookups.get(lookup_index);
|
const graph::Lookup* lookup = ext_context.lookups.get(lookup_index);
|
||||||
hb_set_t visited;
|
hb_set_t visited;
|
||||||
lookup_sizes.push (lookup_size_t {
|
lookup_sizes.push (lookup_size_t {
|
||||||
@ -131,14 +140,16 @@ bool _promote_extensions_if_needed (graph::gsubgpos_graph_context_t& ext_context
|
|||||||
lookup_sizes.qsort ();
|
lookup_sizes.qsort ();
|
||||||
|
|
||||||
size_t lookup_list_size = ext_context.graph.vertices_[ext_context.lookup_list_index].table_size ();
|
size_t lookup_list_size = ext_context.graph.vertices_[ext_context.lookup_list_index].table_size ();
|
||||||
size_t l2_l3_size = lookup_list_size; // Lookup List + Lookups
|
size_t l2_l3_size = lookup_list_size + total_lookup_table_sizes; // Lookup List + Lookups
|
||||||
size_t l3_l4_size = 0; // Lookups + SubTables
|
size_t l3_l4_size = total_lookup_table_sizes; // Lookups + SubTables
|
||||||
size_t l4_plus_size = 0; // SubTables + their descendants
|
size_t l4_plus_size = 0; // SubTables + their descendants
|
||||||
|
|
||||||
// Start by assuming all lookups are using extension subtables, this size will be removed later
|
// Start by assuming all lookups are using extension subtables, this size will be removed later
|
||||||
// if it's decided to not make a lookup extension.
|
// if it's decided to not make a lookup extension.
|
||||||
for (auto p : lookup_sizes)
|
for (auto p : lookup_sizes)
|
||||||
{
|
{
|
||||||
|
// TODO(garretrieger): this overestimates the extension subtables size because some extension subtables may be
|
||||||
|
// reused. However, we can't correct this until we have connected component analysis in place.
|
||||||
unsigned subtables_size = p.num_subtables * 8;
|
unsigned subtables_size = p.num_subtables * 8;
|
||||||
l3_l4_size += subtables_size;
|
l3_l4_size += subtables_size;
|
||||||
l4_plus_size += subtables_size;
|
l4_plus_size += subtables_size;
|
||||||
@ -159,8 +170,7 @@ bool _promote_extensions_if_needed (graph::gsubgpos_graph_context_t& ext_context
|
|||||||
size_t subtables_size = ext_context.graph.find_subgraph_size (p.lookup_index, visited, 1) - lookup_size;
|
size_t subtables_size = ext_context.graph.find_subgraph_size (p.lookup_index, visited, 1) - lookup_size;
|
||||||
size_t remaining_size = p.size - subtables_size - lookup_size;
|
size_t remaining_size = p.size - subtables_size - lookup_size;
|
||||||
|
|
||||||
l2_l3_size += lookup_size;
|
l3_l4_size += subtables_size;
|
||||||
l3_l4_size += lookup_size + subtables_size;
|
|
||||||
l3_l4_size -= p.num_subtables * 8;
|
l3_l4_size -= p.num_subtables * 8;
|
||||||
l4_plus_size += subtables_size + remaining_size;
|
l4_plus_size += subtables_size + remaining_size;
|
||||||
|
|
||||||
|
2
src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh
vendored
2
src/3rdparty/harfbuzz-ng/src/hb-sanitize.hh
vendored
@ -453,7 +453,7 @@ struct hb_sanitize_context_t :
|
|||||||
edit_count = 0;
|
edit_count = 0;
|
||||||
sane = t->sanitize (this);
|
sane = t->sanitize (this);
|
||||||
if (edit_count) {
|
if (edit_count) {
|
||||||
DEBUG_MSG_FUNC (SANITIZE, start, "requested %u edits in second round; FAILLING", edit_count);
|
DEBUG_MSG_FUNC (SANITIZE, start, "requested %u edits in second round; FAILING", edit_count);
|
||||||
sane = false;
|
sane = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
24
src/3rdparty/harfbuzz-ng/src/hb-set.cc
vendored
24
src/3rdparty/harfbuzz-ng/src/hb-set.cc
vendored
@ -200,7 +200,7 @@ hb_set_copy (const hb_set_t *set)
|
|||||||
void
|
void
|
||||||
hb_set_clear (hb_set_t *set)
|
hb_set_clear (hb_set_t *set)
|
||||||
{
|
{
|
||||||
/* Immutible-safe. */
|
/* Immutable-safe. */
|
||||||
set->clear ();
|
set->clear ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,7 +251,7 @@ void
|
|||||||
hb_set_add (hb_set_t *set,
|
hb_set_add (hb_set_t *set,
|
||||||
hb_codepoint_t codepoint)
|
hb_codepoint_t codepoint)
|
||||||
{
|
{
|
||||||
/* Immutible-safe. */
|
/* Immutable-safe. */
|
||||||
set->add (codepoint);
|
set->add (codepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,7 +272,7 @@ hb_set_add_sorted_array (hb_set_t *set,
|
|||||||
const hb_codepoint_t *sorted_codepoints,
|
const hb_codepoint_t *sorted_codepoints,
|
||||||
unsigned int num_codepoints)
|
unsigned int num_codepoints)
|
||||||
{
|
{
|
||||||
/* Immutible-safe. */
|
/* Immutable-safe. */
|
||||||
set->add_sorted_array (sorted_codepoints,
|
set->add_sorted_array (sorted_codepoints,
|
||||||
num_codepoints,
|
num_codepoints,
|
||||||
sizeof(hb_codepoint_t));
|
sizeof(hb_codepoint_t));
|
||||||
@ -294,7 +294,7 @@ hb_set_add_range (hb_set_t *set,
|
|||||||
hb_codepoint_t first,
|
hb_codepoint_t first,
|
||||||
hb_codepoint_t last)
|
hb_codepoint_t last)
|
||||||
{
|
{
|
||||||
/* Immutible-safe. */
|
/* Immutable-safe. */
|
||||||
set->add_range (first, last);
|
set->add_range (first, last);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -311,7 +311,7 @@ void
|
|||||||
hb_set_del (hb_set_t *set,
|
hb_set_del (hb_set_t *set,
|
||||||
hb_codepoint_t codepoint)
|
hb_codepoint_t codepoint)
|
||||||
{
|
{
|
||||||
/* Immutible-safe. */
|
/* Immutable-safe. */
|
||||||
set->del (codepoint);
|
set->del (codepoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,7 +334,7 @@ hb_set_del_range (hb_set_t *set,
|
|||||||
hb_codepoint_t first,
|
hb_codepoint_t first,
|
||||||
hb_codepoint_t last)
|
hb_codepoint_t last)
|
||||||
{
|
{
|
||||||
/* Immutible-safe. */
|
/* Immutable-safe. */
|
||||||
set->del_range (first, last);
|
set->del_range (first, last);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,7 +405,7 @@ void
|
|||||||
hb_set_set (hb_set_t *set,
|
hb_set_set (hb_set_t *set,
|
||||||
const hb_set_t *other)
|
const hb_set_t *other)
|
||||||
{
|
{
|
||||||
/* Immutible-safe. */
|
/* Immutable-safe. */
|
||||||
set->set (*other);
|
set->set (*other);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,7 +422,7 @@ void
|
|||||||
hb_set_union (hb_set_t *set,
|
hb_set_union (hb_set_t *set,
|
||||||
const hb_set_t *other)
|
const hb_set_t *other)
|
||||||
{
|
{
|
||||||
/* Immutible-safe. */
|
/* Immutable-safe. */
|
||||||
set->union_ (*other);
|
set->union_ (*other);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,7 +439,7 @@ void
|
|||||||
hb_set_intersect (hb_set_t *set,
|
hb_set_intersect (hb_set_t *set,
|
||||||
const hb_set_t *other)
|
const hb_set_t *other)
|
||||||
{
|
{
|
||||||
/* Immutible-safe. */
|
/* Immutable-safe. */
|
||||||
set->intersect (*other);
|
set->intersect (*other);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,7 +456,7 @@ void
|
|||||||
hb_set_subtract (hb_set_t *set,
|
hb_set_subtract (hb_set_t *set,
|
||||||
const hb_set_t *other)
|
const hb_set_t *other)
|
||||||
{
|
{
|
||||||
/* Immutible-safe. */
|
/* Immutable-safe. */
|
||||||
set->subtract (*other);
|
set->subtract (*other);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,7 +474,7 @@ void
|
|||||||
hb_set_symmetric_difference (hb_set_t *set,
|
hb_set_symmetric_difference (hb_set_t *set,
|
||||||
const hb_set_t *other)
|
const hb_set_t *other)
|
||||||
{
|
{
|
||||||
/* Immutible-safe. */
|
/* Immutable-safe. */
|
||||||
set->symmetric_difference (*other);
|
set->symmetric_difference (*other);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,7 +489,7 @@ hb_set_symmetric_difference (hb_set_t *set,
|
|||||||
void
|
void
|
||||||
hb_set_invert (hb_set_t *set)
|
hb_set_invert (hb_set_t *set)
|
||||||
{
|
{
|
||||||
/* Immutible-safe. */
|
/* Immutable-safe. */
|
||||||
set->invert ();
|
set->invert ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
20
src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc
vendored
20
src/3rdparty/harfbuzz-ng/src/hb-subset-input.cc
vendored
@ -75,7 +75,6 @@ hb_subset_input_t::hb_subset_input_t ()
|
|||||||
HB_TAG ('V', 'D', 'M', 'X'),
|
HB_TAG ('V', 'D', 'M', 'X'),
|
||||||
HB_TAG ('D', 'S', 'I', 'G'),
|
HB_TAG ('D', 'S', 'I', 'G'),
|
||||||
HB_TAG ('M', 'V', 'A', 'R'),
|
HB_TAG ('M', 'V', 'A', 'R'),
|
||||||
HB_TAG ('c', 'v', 'a', 'r'),
|
|
||||||
};
|
};
|
||||||
sets.no_subset_tables->add_array (default_no_subset_tables,
|
sets.no_subset_tables->add_array (default_no_subset_tables,
|
||||||
ARRAY_LENGTH (default_no_subset_tables));
|
ARRAY_LENGTH (default_no_subset_tables));
|
||||||
@ -479,16 +478,21 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input,
|
|||||||
* @axis_tag: Tag of the axis
|
* @axis_tag: Tag of the axis
|
||||||
* @axis_min_value: Minimum value of the axis variation range to set
|
* @axis_min_value: Minimum value of the axis variation range to set
|
||||||
* @axis_max_value: Maximum value of the axis variation range to set
|
* @axis_max_value: Maximum value of the axis variation range to set
|
||||||
|
* @axis_def_value: Default value of the axis variation range to set, in case of
|
||||||
|
* null, it'll be determined automatically
|
||||||
*
|
*
|
||||||
* Restricting the range of variation on an axis in the given subset input object.
|
* Restricting the range of variation on an axis in the given subset input object.
|
||||||
* New min/max values will be clamped if they're not within the fvar axis range.
|
* New min/default/max values will be clamped if they're not within the fvar axis range.
|
||||||
|
* If the new default value is null:
|
||||||
|
* If the fvar axis default value is within the new range, then new default
|
||||||
|
* value is the same as original default value.
|
||||||
* If the fvar axis default value is not within the new range, the new default
|
* If the fvar axis default value is not within the new range, the new default
|
||||||
* value will be changed to the new min or max value, whichever is closer to the fvar
|
* value will be changed to the new min or max value, whichever is closer to the fvar
|
||||||
* axis default.
|
* axis default.
|
||||||
*
|
*
|
||||||
* Note: input min value can not be bigger than input max value
|
* Note: input min value can not be bigger than input max value. If the input
|
||||||
* Note: currently this API does not support changing axis limits yet.It'd be only
|
* default value is not within the new min/max range, it'll be clamped.
|
||||||
* used internally for setting axis limits in the internal data structures
|
* Note: currently it supports gvar and cvar tables only.
|
||||||
*
|
*
|
||||||
* Return value: `true` if success, `false` otherwise
|
* Return value: `true` if success, `false` otherwise
|
||||||
*
|
*
|
||||||
@ -499,7 +503,8 @@ hb_subset_input_set_axis_range (hb_subset_input_t *input,
|
|||||||
hb_face_t *face,
|
hb_face_t *face,
|
||||||
hb_tag_t axis_tag,
|
hb_tag_t axis_tag,
|
||||||
float axis_min_value,
|
float axis_min_value,
|
||||||
float axis_max_value)
|
float axis_max_value,
|
||||||
|
float *axis_def_value /* IN, maybe NULL */)
|
||||||
{
|
{
|
||||||
if (axis_min_value > axis_max_value)
|
if (axis_min_value > axis_max_value)
|
||||||
return false;
|
return false;
|
||||||
@ -510,7 +515,8 @@ hb_subset_input_set_axis_range (hb_subset_input_t *input,
|
|||||||
|
|
||||||
float new_min_val = hb_clamp(axis_min_value, axis_info.min_value, axis_info.max_value);
|
float new_min_val = hb_clamp(axis_min_value, axis_info.min_value, axis_info.max_value);
|
||||||
float new_max_val = hb_clamp(axis_max_value, axis_info.min_value, axis_info.max_value);
|
float new_max_val = hb_clamp(axis_max_value, axis_info.min_value, axis_info.max_value);
|
||||||
float new_default_val = hb_clamp(axis_info.default_value, new_min_val, new_max_val);
|
float new_default_val = axis_def_value ? *axis_def_value : axis_info.default_value;
|
||||||
|
new_default_val = hb_clamp(new_default_val, new_min_val, new_max_val);
|
||||||
return input->axes_location.set (axis_tag, Triple (new_min_val, new_default_val, new_max_val));
|
return input->axes_location.set (axis_tag, Triple (new_min_val, new_default_val, new_max_val));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -123,6 +123,9 @@ HB_SUBSET_PLAN_MEMBER (mutable hb_vector_t<unsigned>, bounds_width_vec)
|
|||||||
//boundsHeight map: new gid->boundsHeight, boundsHeight=yMax - yMin
|
//boundsHeight map: new gid->boundsHeight, boundsHeight=yMax - yMin
|
||||||
HB_SUBSET_PLAN_MEMBER (mutable hb_vector_t<unsigned>, bounds_height_vec)
|
HB_SUBSET_PLAN_MEMBER (mutable hb_vector_t<unsigned>, bounds_height_vec)
|
||||||
|
|
||||||
|
//map: new_gid -> contour points vector
|
||||||
|
HB_SUBSET_PLAN_MEMBER (mutable hb_hashmap_t E(<hb_codepoint_t, contour_point_vector_t>), new_gid_contour_points_map)
|
||||||
|
|
||||||
#ifdef HB_EXPERIMENTAL_API
|
#ifdef HB_EXPERIMENTAL_API
|
||||||
// name table overrides map: hb_ot_name_record_ids_t-> name string new value or
|
// name table overrides map: hb_ot_name_record_ids_t-> name string new value or
|
||||||
// None to indicate should remove
|
// None to indicate should remove
|
||||||
|
32
src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc
vendored
32
src/3rdparty/harfbuzz-ng/src/hb-subset-plan.cc
vendored
@ -1045,6 +1045,36 @@ _update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan)
|
|||||||
if (vvar_store_cache)
|
if (vvar_store_cache)
|
||||||
_vmtx.var_table->get_var_store ().destroy_cache (vvar_store_cache);
|
_vmtx.var_table->get_var_store ().destroy_cache (vvar_store_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
_get_instance_glyphs_contour_points (hb_subset_plan_t *plan)
|
||||||
|
{
|
||||||
|
/* contour_points vector only needed for updating gvar table (infer delta)
|
||||||
|
* during partial instancing */
|
||||||
|
if (plan->user_axes_location.is_empty () || plan->all_axes_pinned)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
OT::glyf_accelerator_t glyf (plan->source);
|
||||||
|
|
||||||
|
for (auto &_ : plan->new_to_old_gid_list)
|
||||||
|
{
|
||||||
|
hb_codepoint_t new_gid = _.first;
|
||||||
|
contour_point_vector_t all_points;
|
||||||
|
if (new_gid == 0 && !(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
|
||||||
|
{
|
||||||
|
if (unlikely (!plan->new_gid_contour_points_map.set (new_gid, all_points)))
|
||||||
|
return false;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
hb_codepoint_t old_gid = _.second;
|
||||||
|
if (unlikely (!glyf.glyph_for_gid (old_gid).get_all_points_without_var (plan->source, all_points)))
|
||||||
|
return false;
|
||||||
|
if (unlikely (!plan->new_gid_contour_points_map.set (new_gid, all_points)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
#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,
|
||||||
@ -1148,6 +1178,8 @@ hb_subset_plan_t::hb_subset_plan_t (hb_face_t *face,
|
|||||||
|
|
||||||
#ifndef HB_NO_VAR
|
#ifndef HB_NO_VAR
|
||||||
_update_instance_metrics_map_from_cff2 (this);
|
_update_instance_metrics_map_from_cff2 (this);
|
||||||
|
if (!check_success (_get_instance_glyphs_contour_points (this)))
|
||||||
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (attach_accelerator_data)
|
if (attach_accelerator_data)
|
||||||
|
34
src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh
vendored
34
src/3rdparty/harfbuzz-ng/src/hb-subset-plan.hh
vendored
@ -67,6 +67,40 @@ struct head_maxp_info_t
|
|||||||
|
|
||||||
typedef struct head_maxp_info_t head_maxp_info_t;
|
typedef struct head_maxp_info_t head_maxp_info_t;
|
||||||
|
|
||||||
|
struct contour_point_t
|
||||||
|
{
|
||||||
|
void init (float x_ = 0.f, float y_ = 0.f, bool is_end_point_ = false)
|
||||||
|
{ flag = 0; x = x_; y = y_; is_end_point = is_end_point_; }
|
||||||
|
|
||||||
|
void transform (const float (&matrix)[4])
|
||||||
|
{
|
||||||
|
float x_ = x * matrix[0] + y * matrix[2];
|
||||||
|
y = x * matrix[1] + y * matrix[3];
|
||||||
|
x = x_;
|
||||||
|
}
|
||||||
|
HB_ALWAYS_INLINE
|
||||||
|
void translate (const contour_point_t &p) { x += p.x; y += p.y; }
|
||||||
|
|
||||||
|
|
||||||
|
float x;
|
||||||
|
float y;
|
||||||
|
uint8_t flag;
|
||||||
|
bool is_end_point;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct contour_point_vector_t : hb_vector_t<contour_point_t>
|
||||||
|
{
|
||||||
|
void extend (const hb_array_t<contour_point_t> &a)
|
||||||
|
{
|
||||||
|
unsigned int old_len = length;
|
||||||
|
if (unlikely (!resize (old_len + a.length, false)))
|
||||||
|
return;
|
||||||
|
auto arrayZ = this->arrayZ + old_len;
|
||||||
|
unsigned count = a.length;
|
||||||
|
hb_memcpy (arrayZ, a.arrayZ, count * sizeof (arrayZ[0]));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
namespace OT {
|
namespace OT {
|
||||||
struct cff1_subset_accelerator_t;
|
struct cff1_subset_accelerator_t;
|
||||||
struct cff2_subset_accelerator_t;
|
struct cff2_subset_accelerator_t;
|
||||||
|
3
src/3rdparty/harfbuzz-ng/src/hb-subset.cc
vendored
3
src/3rdparty/harfbuzz-ng/src/hb-subset.cc
vendored
@ -520,6 +520,9 @@ _subset_table (hb_subset_plan_t *plan,
|
|||||||
case HB_OT_TAG_avar:
|
case HB_OT_TAG_avar:
|
||||||
if (plan->user_axes_location.is_empty ()) return _passthrough (plan, tag);
|
if (plan->user_axes_location.is_empty ()) return _passthrough (plan, tag);
|
||||||
return _subset<const OT::avar> (plan, buf);
|
return _subset<const OT::avar> (plan, buf);
|
||||||
|
case HB_OT_TAG_cvar:
|
||||||
|
if (plan->user_axes_location.is_empty ()) return _passthrough (plan, tag);
|
||||||
|
return _subset<const OT::cvar> (plan, buf);
|
||||||
case HB_OT_TAG_STAT:
|
case HB_OT_TAG_STAT:
|
||||||
if (!plan->user_axes_location.is_empty ()) return _subset<const OT::STAT> (plan, buf);
|
if (!plan->user_axes_location.is_empty ()) return _subset<const OT::STAT> (plan, buf);
|
||||||
else return _passthrough (plan, tag);
|
else return _passthrough (plan, tag);
|
||||||
|
3
src/3rdparty/harfbuzz-ng/src/hb-subset.h
vendored
3
src/3rdparty/harfbuzz-ng/src/hb-subset.h
vendored
@ -181,7 +181,8 @@ hb_subset_input_set_axis_range (hb_subset_input_t *input,
|
|||||||
hb_face_t *face,
|
hb_face_t *face,
|
||||||
hb_tag_t axis_tag,
|
hb_tag_t axis_tag,
|
||||||
float axis_min_value,
|
float axis_min_value,
|
||||||
float axis_max_value);
|
float axis_max_value,
|
||||||
|
float *axis_def_value);
|
||||||
|
|
||||||
HB_EXTERN hb_bool_t
|
HB_EXTERN hb_bool_t
|
||||||
hb_subset_input_override_name_table (hb_subset_input_t *input,
|
hb_subset_input_override_name_table (hb_subset_input_t *input,
|
||||||
|
24
src/3rdparty/harfbuzz-ng/src/hb-vector.hh
vendored
24
src/3rdparty/harfbuzz-ng/src/hb-vector.hh
vendored
@ -102,7 +102,7 @@ struct hb_vector_t
|
|||||||
|
|
||||||
void fini ()
|
void fini ()
|
||||||
{
|
{
|
||||||
/* We allow a hack to make the vector point to a foriegn array
|
/* We allow a hack to make the vector point to a foreign array
|
||||||
* by the user. In that case length/arrayZ are non-zero but
|
* by the user. In that case length/arrayZ are non-zero but
|
||||||
* allocated is zero. Don't free anything. */
|
* allocated is zero. Don't free anything. */
|
||||||
if (allocated)
|
if (allocated)
|
||||||
@ -208,25 +208,7 @@ struct hb_vector_t
|
|||||||
return std::addressof (Crap (Type));
|
return std::addressof (Crap (Type));
|
||||||
return std::addressof (arrayZ[length - 1]);
|
return std::addressof (arrayZ[length - 1]);
|
||||||
}
|
}
|
||||||
template <typename T,
|
template <typename... Args> Type *push (Args&&... args)
|
||||||
typename T2 = Type,
|
|
||||||
hb_enable_if (!std::is_copy_constructible<T2>::value &&
|
|
||||||
std::is_copy_assignable<T>::value)>
|
|
||||||
Type *push (T&& v)
|
|
||||||
{
|
|
||||||
Type *p = push ();
|
|
||||||
if (p == std::addressof (Crap (Type)))
|
|
||||||
// If push failed to allocate then don't copy v, since this may cause
|
|
||||||
// the created copy to leak memory since we won't have stored a
|
|
||||||
// reference to it.
|
|
||||||
return p;
|
|
||||||
*p = std::forward<T> (v);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
template <typename T,
|
|
||||||
typename T2 = Type,
|
|
||||||
hb_enable_if (std::is_copy_constructible<T2>::value)>
|
|
||||||
Type *push (T&& v)
|
|
||||||
{
|
{
|
||||||
if (unlikely ((int) length >= allocated && !alloc (length + 1)))
|
if (unlikely ((int) length >= allocated && !alloc (length + 1)))
|
||||||
// If push failed to allocate then don't copy v, since this may cause
|
// If push failed to allocate then don't copy v, since this may cause
|
||||||
@ -236,7 +218,7 @@ struct hb_vector_t
|
|||||||
|
|
||||||
/* Emplace. */
|
/* Emplace. */
|
||||||
Type *p = std::addressof (arrayZ[length++]);
|
Type *p = std::addressof (arrayZ[length++]);
|
||||||
return new (p) Type (std::forward<T> (v));
|
return new (p) Type (std::forward<Args> (args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool in_error () const { return allocated < 0; }
|
bool in_error () const { return allocated < 0; }
|
||||||
|
6
src/3rdparty/harfbuzz-ng/src/hb-version.h
vendored
6
src/3rdparty/harfbuzz-ng/src/hb-version.h
vendored
@ -47,20 +47,20 @@ HB_BEGIN_DECLS
|
|||||||
*
|
*
|
||||||
* The minor component of the library version available at compile-time.
|
* The minor component of the library version available at compile-time.
|
||||||
*/
|
*/
|
||||||
#define HB_VERSION_MINOR 1
|
#define HB_VERSION_MINOR 2
|
||||||
/**
|
/**
|
||||||
* HB_VERSION_MICRO:
|
* HB_VERSION_MICRO:
|
||||||
*
|
*
|
||||||
* The micro component of the library version available at compile-time.
|
* The micro component of the library version available at compile-time.
|
||||||
*/
|
*/
|
||||||
#define HB_VERSION_MICRO 1
|
#define HB_VERSION_MICRO 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HB_VERSION_STRING:
|
* HB_VERSION_STRING:
|
||||||
*
|
*
|
||||||
* A string literal containing the library version available at compile-time.
|
* A string literal containing the library version available at compile-time.
|
||||||
*/
|
*/
|
||||||
#define HB_VERSION_STRING "8.1.1"
|
#define HB_VERSION_STRING "8.2.0"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HB_VERSION_ATLEAST:
|
* HB_VERSION_ATLEAST:
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
*
|
*
|
||||||
* - Build your font's wasm code importing the shared modules with the desired
|
* - Build your font's wasm code importing the shared modules with the desired
|
||||||
* name. This can be done eg.: __attribute__((import_module("graphite2")))
|
* name. This can be done eg.: __attribute__((import_module("graphite2")))
|
||||||
* before each symbol in the the shared-module's headers.
|
* before each symbol in the shared-module's headers.
|
||||||
*
|
*
|
||||||
* - Try shaping your font and hope for the best...
|
* - Try shaping your font and hope for the best...
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user