mirror of
https://github.com/godotengine/godot.git
synced 2025-12-07 22:00:10 +00:00
harfbuzz: Update to 11.3.2
This commit is contained in:
parent
71a9948157
commit
37f506c33d
72 changed files with 3901 additions and 2395 deletions
4
thirdparty/README.md
vendored
4
thirdparty/README.md
vendored
|
|
@ -436,7 +436,7 @@ Patches:
|
|||
## harfbuzz
|
||||
|
||||
- Upstream: https://github.com/harfbuzz/harfbuzz
|
||||
- Version: 11.2.1 (33a3f8de60dcad7535f14f07d6710144548853ac, 2025)
|
||||
- Version: 11.3.2 (4e3df1c1383481ed5717603d5dd3453a04fb16ba, 2025)
|
||||
- License: MIT
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
|
@ -444,7 +444,7 @@ Files extracted from upstream source:
|
|||
- `AUTHORS`, `COPYING`, `THANKS`
|
||||
- From the `src` folder, recursively:
|
||||
- All the `.cc`, `.h`, `.hh` files
|
||||
- Except `main.cc`, `harfbuzz*.cc`, `failing-alloc.c`, `test*.cc`, `hb-wasm*.*`, `wasm/*`
|
||||
- Except `main.cc`, `harfbuzz*.cc`, `failing-alloc.c`, `test*.cc`, `hb-wasm*.*`, `hb-harfrust.cc`, `wasm/*`, `ms-use/*`, `rust/*`
|
||||
|
||||
|
||||
## hidapi
|
||||
|
|
|
|||
57
thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh
vendored
57
thirdparty/harfbuzz/src/OT/Color/COLR/COLR.hh
vendored
|
|
@ -104,7 +104,7 @@ public:
|
|||
foreground (foreground_),
|
||||
instancer (instancer_)
|
||||
{
|
||||
if (font->is_synthetic ())
|
||||
if (font->is_synthetic)
|
||||
{
|
||||
font = hb_font_create_sub_font (font);
|
||||
hb_font_set_synthetic_bold (font, 0, 0, true);
|
||||
|
|
@ -1075,9 +1075,9 @@ struct PaintTranslate
|
|||
float ddx = dx + c->instancer (varIdxBase, 0);
|
||||
float ddy = dy + c->instancer (varIdxBase, 1);
|
||||
|
||||
bool p1 = c->funcs->push_translate (c->data, ddx, ddy);
|
||||
c->funcs->push_translate (c->data, ddx, ddy);
|
||||
c->recurse (this+src);
|
||||
if (p1) c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 14(noVar) or 15 (Var) */
|
||||
|
|
@ -1124,9 +1124,9 @@ struct PaintScale
|
|||
float sx = scaleX.to_float (c->instancer (varIdxBase, 0));
|
||||
float sy = scaleY.to_float (c->instancer (varIdxBase, 1));
|
||||
|
||||
bool p1 = c->funcs->push_scale (c->data, sx, sy);
|
||||
c->funcs->push_scale (c->data, sx, sy);
|
||||
c->recurse (this+src);
|
||||
if (p1) c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 16 (noVar) or 17(Var) */
|
||||
|
|
@ -1177,13 +1177,9 @@ struct PaintScaleAroundCenter
|
|||
float tCenterX = centerX + c->instancer (varIdxBase, 2);
|
||||
float tCenterY = centerY + c->instancer (varIdxBase, 3);
|
||||
|
||||
bool p1 = c->funcs->push_translate (c->data, +tCenterX, +tCenterY);
|
||||
bool p2 = c->funcs->push_scale (c->data, sx, sy);
|
||||
bool p3 = c->funcs->push_translate (c->data, -tCenterX, -tCenterY);
|
||||
c->funcs->push_scale_around_center (c->data, sx, sy, tCenterX, tCenterY);
|
||||
c->recurse (this+src);
|
||||
if (p3) c->funcs->pop_transform (c->data);
|
||||
if (p2) c->funcs->pop_transform (c->data);
|
||||
if (p1) c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 18 (noVar) or 19(Var) */
|
||||
|
|
@ -1228,9 +1224,9 @@ struct PaintScaleUniform
|
|||
TRACE_PAINT (this);
|
||||
float s = scale.to_float (c->instancer (varIdxBase, 0));
|
||||
|
||||
bool p1 = c->funcs->push_scale (c->data, s, s);
|
||||
c->funcs->push_scale (c->data, s, s);
|
||||
c->recurse (this+src);
|
||||
if (p1) c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 20 (noVar) or 21(Var) */
|
||||
|
|
@ -1278,13 +1274,9 @@ struct PaintScaleUniformAroundCenter
|
|||
float tCenterX = centerX + c->instancer (varIdxBase, 1);
|
||||
float tCenterY = centerY + c->instancer (varIdxBase, 2);
|
||||
|
||||
bool p1 = c->funcs->push_translate (c->data, +tCenterX, +tCenterY);
|
||||
bool p2 = c->funcs->push_scale (c->data, s, s);
|
||||
bool p3 = c->funcs->push_translate (c->data, -tCenterX, -tCenterY);
|
||||
c->funcs->push_scale_around_center (c->data, s, s, tCenterX, tCenterY);
|
||||
c->recurse (this+src);
|
||||
if (p3) c->funcs->pop_transform (c->data);
|
||||
if (p2) c->funcs->pop_transform (c->data);
|
||||
if (p1) c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 22 (noVar) or 23(Var) */
|
||||
|
|
@ -1328,9 +1320,9 @@ struct PaintRotate
|
|||
TRACE_PAINT (this);
|
||||
float a = angle.to_float (c->instancer (varIdxBase, 0));
|
||||
|
||||
bool p1 = c->funcs->push_rotate (c->data, a);
|
||||
c->funcs->push_rotate (c->data, a);
|
||||
c->recurse (this+src);
|
||||
if (p1) c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 24 (noVar) or 25(Var) */
|
||||
|
|
@ -1378,13 +1370,9 @@ struct PaintRotateAroundCenter
|
|||
float tCenterX = centerX + c->instancer (varIdxBase, 1);
|
||||
float tCenterY = centerY + c->instancer (varIdxBase, 2);
|
||||
|
||||
bool p1 = c->funcs->push_translate (c->data, +tCenterX, +tCenterY);
|
||||
bool p2 = c->funcs->push_rotate (c->data, a);
|
||||
bool p3 = c->funcs->push_translate (c->data, -tCenterX, -tCenterY);
|
||||
c->funcs->push_rotate_around_center (c->data, a, tCenterX, tCenterY);
|
||||
c->recurse (this+src);
|
||||
if (p3) c->funcs->pop_transform (c->data);
|
||||
if (p2) c->funcs->pop_transform (c->data);
|
||||
if (p1) c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 26 (noVar) or 27(Var) */
|
||||
|
|
@ -1432,9 +1420,9 @@ struct PaintSkew
|
|||
float sx = xSkewAngle.to_float(c->instancer (varIdxBase, 0));
|
||||
float sy = ySkewAngle.to_float(c->instancer (varIdxBase, 1));
|
||||
|
||||
bool p1 = c->funcs->push_skew (c->data, sx, sy);
|
||||
c->funcs->push_skew (c->data, sx, sy);
|
||||
c->recurse (this+src);
|
||||
if (p1) c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 28(noVar) or 29 (Var) */
|
||||
|
|
@ -1485,13 +1473,9 @@ struct PaintSkewAroundCenter
|
|||
float tCenterX = centerX + c->instancer (varIdxBase, 2);
|
||||
float tCenterY = centerY + c->instancer (varIdxBase, 3);
|
||||
|
||||
bool p1 = c->funcs->push_translate (c->data, +tCenterX, +tCenterY);
|
||||
bool p2 = c->funcs->push_skew (c->data, sx, sy);
|
||||
bool p3 = c->funcs->push_translate (c->data, -tCenterX, -tCenterY);
|
||||
c->funcs->push_skew_around_center (c->data, sx, sy, tCenterX, tCenterY);
|
||||
c->recurse (this+src);
|
||||
if (p3) c->funcs->pop_transform (c->data);
|
||||
if (p2) c->funcs->pop_transform (c->data);
|
||||
if (p1) c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
|
||||
HBUINT8 format; /* format = 30(noVar) or 31 (Var) */
|
||||
|
|
@ -2693,7 +2677,8 @@ struct COLR
|
|||
{
|
||||
ItemVarStoreInstancer instancer (get_var_store_ptr (),
|
||||
get_delta_set_index_map_ptr (),
|
||||
hb_array (font->coords, font->num_coords));
|
||||
hb_array (font->coords,
|
||||
font->has_nonzero_coords ? font->num_coords : 0));
|
||||
hb_paint_context_t c (this, funcs, data, font, palette_index, foreground, instancer);
|
||||
|
||||
hb_decycler_node_t node (c.glyphs_decycler);
|
||||
|
|
|
|||
|
|
@ -37,12 +37,12 @@ struct AnchorFormat3
|
|||
*x = font->em_fscale_x (xCoordinate);
|
||||
*y = font->em_fscale_y (yCoordinate);
|
||||
|
||||
if ((font->x_ppem || font->num_coords) && xDeviceTable.sanitize (&c->sanitizer, this))
|
||||
if ((font->x_ppem || font->has_nonzero_coords) && xDeviceTable.sanitize (&c->sanitizer, this))
|
||||
{
|
||||
hb_barrier ();
|
||||
*x += (this+xDeviceTable).get_x_delta (font, c->var_store, c->var_store_cache);
|
||||
}
|
||||
if ((font->y_ppem || font->num_coords) && yDeviceTable.sanitize (&c->sanitizer, this))
|
||||
if ((font->y_ppem || font->has_nonzero_coords) && yDeviceTable.sanitize (&c->sanitizer, this))
|
||||
{
|
||||
hb_barrier ();
|
||||
*y += (this+yDeviceTable).get_y_delta (font, c->var_store, c->var_store_cache);
|
||||
|
|
@ -63,7 +63,7 @@ struct AnchorFormat3
|
|||
hb_pair_t<unsigned, int> *new_varidx_delta;
|
||||
if (!c->plan->layout_variation_idx_delta_map.has (x_varidx, &new_varidx_delta))
|
||||
return_trace (false);
|
||||
|
||||
|
||||
x_varidx = hb_first (*new_varidx_delta);
|
||||
int delta = hb_second (*new_varidx_delta);
|
||||
if (delta != 0)
|
||||
|
|
@ -91,10 +91,13 @@ struct AnchorFormat3
|
|||
}
|
||||
}
|
||||
|
||||
/* in case that all axes are pinned or no variations after instantiation,
|
||||
* both var_idxes will be mapped to HB_OT_LAYOUT_NO_VARIATIONS_INDEX */
|
||||
if (x_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX &&
|
||||
y_varidx == HB_OT_LAYOUT_NO_VARIATIONS_INDEX)
|
||||
|
||||
bool no_downgrade = (!xDeviceTable.is_null () && !(this+xDeviceTable).is_variation_device ()) ||
|
||||
x_varidx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX ||
|
||||
y_varidx != HB_OT_LAYOUT_NO_VARIATIONS_INDEX ||
|
||||
(!yDeviceTable.is_null () && !(this+yDeviceTable).is_variation_device ());
|
||||
|
||||
if (!no_downgrade)
|
||||
return_trace (c->serializer->check_assign (out->format, 1, HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
|
||||
if (!c->serializer->embed (xDeviceTable)) return_trace (false);
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ struct ValueFormat : HBUINT16
|
|||
* PosTable (may be NULL) */
|
||||
#endif
|
||||
|
||||
IntType& operator = (uint16_t i) { v = i; return *this; }
|
||||
NumType& operator = (uint16_t i) { v = i; return *this; }
|
||||
|
||||
unsigned int get_len () const { return hb_popcount ((unsigned int) *this); }
|
||||
unsigned int get_size () const { return get_len () * Value::static_size; }
|
||||
|
|
@ -111,8 +111,8 @@ struct ValueFormat : HBUINT16
|
|||
|
||||
if (!has_device ()) return ret;
|
||||
|
||||
bool use_x_device = font->x_ppem || font->num_coords;
|
||||
bool use_y_device = font->y_ppem || font->num_coords;
|
||||
bool use_x_device = font->x_ppem || font->has_nonzero_coords;
|
||||
bool use_y_device = font->y_ppem || font->has_nonzero_coords;
|
||||
|
||||
if (!use_x_device && !use_y_device) return ret;
|
||||
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@ namespace GSUB_impl {
|
|||
template <typename Types>
|
||||
struct LigatureSet
|
||||
{
|
||||
protected:
|
||||
public:
|
||||
Array16OfOffset16To<Ligature<Types>>
|
||||
ligature; /* Array LigatureSet tables
|
||||
* ordered by preference */
|
||||
public:
|
||||
|
||||
DEFINE_SIZE_ARRAY (2, ligature);
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ struct Sequence
|
|||
|
||||
for (unsigned i = c->buffer->idx - count; i < c->buffer->idx; i++)
|
||||
{
|
||||
if (buf < p)
|
||||
if (buf < p && sizeof(buf) - 1u > unsigned (p - buf))
|
||||
*p++ = ',';
|
||||
snprintf (p, sizeof(buf) - (p - buf), "%u", i);
|
||||
p += strlen(p);
|
||||
|
|
|
|||
56
thirdparty/harfbuzz/src/OT/Var/VARC/VARC.cc
vendored
56
thirdparty/harfbuzz/src/OT/Var/VARC/VARC.cc
vendored
|
|
@ -13,7 +13,7 @@ namespace OT {
|
|||
|
||||
struct hb_transforming_pen_context_t
|
||||
{
|
||||
hb_transform_t transform;
|
||||
hb_transform_t<> transform;
|
||||
hb_draw_funcs_t *dfuncs;
|
||||
void *data;
|
||||
hb_draw_state_t *st;
|
||||
|
|
@ -130,9 +130,9 @@ hb_ubytes_t
|
|||
VarComponent::get_path_at (const hb_varc_context_t &c,
|
||||
hb_codepoint_t parent_gid,
|
||||
hb_array_t<const int> coords,
|
||||
hb_transform_t total_transform,
|
||||
hb_transform_t<> total_transform,
|
||||
hb_ubytes_t total_record,
|
||||
VarRegionList::cache_t *cache) const
|
||||
hb_scalar_cache_t *cache) const
|
||||
{
|
||||
const unsigned char *end = total_record.arrayZ + total_record.length;
|
||||
const unsigned char *record = total_record.arrayZ;
|
||||
|
|
@ -216,7 +216,7 @@ VarComponent::get_path_at (const hb_varc_context_t &c,
|
|||
* limit on the max number of coords for now. */
|
||||
if ((flags & (unsigned) flags_t::RESET_UNSPECIFIED_AXES) ||
|
||||
coords.length > HB_VAR_COMPOSITE_MAX_AXES)
|
||||
component_coords = hb_array<int> (c.font->coords, c.font->num_coords);
|
||||
component_coords = hb_array (c.font->coords, c.font->num_coords);
|
||||
|
||||
// Transform
|
||||
|
||||
|
|
@ -226,28 +226,28 @@ VarComponent::get_path_at (const hb_varc_context_t &c,
|
|||
|
||||
#define PROCESS_TRANSFORM_COMPONENTS \
|
||||
HB_STMT_START { \
|
||||
PROCESS_TRANSFORM_COMPONENT (FWORD, HAVE_TRANSLATE_X, translateX); \
|
||||
PROCESS_TRANSFORM_COMPONENT (FWORD, HAVE_TRANSLATE_Y, translateY); \
|
||||
PROCESS_TRANSFORM_COMPONENT (F4DOT12, HAVE_ROTATION, rotation); \
|
||||
PROCESS_TRANSFORM_COMPONENT (F6DOT10, HAVE_SCALE_X, scaleX); \
|
||||
PROCESS_TRANSFORM_COMPONENT (F6DOT10, HAVE_SCALE_Y, scaleY); \
|
||||
PROCESS_TRANSFORM_COMPONENT (F4DOT12, HAVE_SKEW_X, skewX); \
|
||||
PROCESS_TRANSFORM_COMPONENT (F4DOT12, HAVE_SKEW_Y, skewY); \
|
||||
PROCESS_TRANSFORM_COMPONENT (FWORD, HAVE_TCENTER_X, tCenterX); \
|
||||
PROCESS_TRANSFORM_COMPONENT (FWORD, HAVE_TCENTER_Y, tCenterY); \
|
||||
PROCESS_TRANSFORM_COMPONENT (FWORD, 1.0f, HAVE_TRANSLATE_X, translateX); \
|
||||
PROCESS_TRANSFORM_COMPONENT (FWORD, 1.0f, HAVE_TRANSLATE_Y, translateY); \
|
||||
PROCESS_TRANSFORM_COMPONENT (F4DOT12, HB_PI, HAVE_ROTATION, rotation); \
|
||||
PROCESS_TRANSFORM_COMPONENT (F6DOT10, 1.0f, HAVE_SCALE_X, scaleX); \
|
||||
PROCESS_TRANSFORM_COMPONENT (F6DOT10, 1.0f, HAVE_SCALE_Y, scaleY); \
|
||||
PROCESS_TRANSFORM_COMPONENT (F4DOT12, HB_PI, HAVE_SKEW_X, skewX); \
|
||||
PROCESS_TRANSFORM_COMPONENT (F4DOT12, HB_PI, HAVE_SKEW_Y, skewY); \
|
||||
PROCESS_TRANSFORM_COMPONENT (FWORD, 1.0f, HAVE_TCENTER_X, tCenterX); \
|
||||
PROCESS_TRANSFORM_COMPONENT (FWORD, 1.0f, HAVE_TCENTER_Y, tCenterY); \
|
||||
} HB_STMT_END
|
||||
|
||||
hb_transform_decomposed_t transform;
|
||||
hb_transform_decomposed_t<> transform;
|
||||
|
||||
// Read transform components
|
||||
#define PROCESS_TRANSFORM_COMPONENT(type, flag, name) \
|
||||
#define PROCESS_TRANSFORM_COMPONENT(type, mult, flag, name) \
|
||||
if (flags & (unsigned) flags_t::flag) \
|
||||
{ \
|
||||
static_assert (type::static_size == HBINT16::static_size, ""); \
|
||||
if (unlikely (unsigned (end - record) < HBINT16::static_size)) \
|
||||
return hb_ubytes_t (); \
|
||||
hb_barrier (); \
|
||||
transform.name = * (const HBINT16 *) record; \
|
||||
transform.name = mult * * (const HBINT16 *) record; \
|
||||
record += HBINT16::static_size; \
|
||||
}
|
||||
PROCESS_TRANSFORM_COMPONENTS;
|
||||
|
|
@ -279,22 +279,22 @@ VarComponent::get_path_at (const hb_varc_context_t &c,
|
|||
{
|
||||
float transformValues[9];
|
||||
unsigned numTransformValues = 0;
|
||||
#define PROCESS_TRANSFORM_COMPONENT(type, flag, name) \
|
||||
#define PROCESS_TRANSFORM_COMPONENT(type, mult, flag, name) \
|
||||
if (flags & (unsigned) flags_t::flag) \
|
||||
transformValues[numTransformValues++] = transform.name;
|
||||
transformValues[numTransformValues++] = transform.name / mult;
|
||||
PROCESS_TRANSFORM_COMPONENTS;
|
||||
#undef PROCESS_TRANSFORM_COMPONENT
|
||||
varStore.get_delta (transformVarIdx, coords, hb_array (transformValues, numTransformValues), cache);
|
||||
numTransformValues = 0;
|
||||
#define PROCESS_TRANSFORM_COMPONENT(type, flag, name) \
|
||||
#define PROCESS_TRANSFORM_COMPONENT(type, mult, flag, name) \
|
||||
if (flags & (unsigned) flags_t::flag) \
|
||||
transform.name = transformValues[numTransformValues++];
|
||||
transform.name = transformValues[numTransformValues++] * mult;
|
||||
PROCESS_TRANSFORM_COMPONENTS;
|
||||
#undef PROCESS_TRANSFORM_COMPONENT
|
||||
}
|
||||
|
||||
// Divide them by their divisors
|
||||
#define PROCESS_TRANSFORM_COMPONENT(type, flag, name) \
|
||||
#define PROCESS_TRANSFORM_COMPONENT(type, mult, flag, name) \
|
||||
if (flags & (unsigned) flags_t::flag) \
|
||||
{ \
|
||||
HBINT16 int_v; \
|
||||
|
|
@ -334,9 +334,9 @@ bool
|
|||
VARC::get_path_at (const hb_varc_context_t &c,
|
||||
hb_codepoint_t glyph,
|
||||
hb_array_t<const int> coords,
|
||||
hb_transform_t transform,
|
||||
hb_transform_t<> transform,
|
||||
hb_codepoint_t parent_glyph,
|
||||
VarRegionList::cache_t *parent_cache) const
|
||||
hb_scalar_cache_t *parent_cache) const
|
||||
{
|
||||
// Don't recurse on the same glyph.
|
||||
unsigned idx = glyph == parent_glyph ?
|
||||
|
|
@ -372,7 +372,7 @@ VARC::get_path_at (const hb_varc_context_t &c,
|
|||
#endif
|
||||
return false;
|
||||
|
||||
hb_extents_t comp_extents (glyph_extents);
|
||||
hb_extents_t<> comp_extents (glyph_extents);
|
||||
transform.transform_extents (comp_extents);
|
||||
c.extents->union_ (comp_extents);
|
||||
}
|
||||
|
|
@ -392,10 +392,10 @@ VARC::get_path_at (const hb_varc_context_t &c,
|
|||
|
||||
hb_ubytes_t record = (this+glyphRecords)[idx];
|
||||
|
||||
VarRegionList::cache_t static_cache[sizeof (void *) * 16];
|
||||
VarRegionList::cache_t *cache = parent_cache ?
|
||||
hb_scalar_cache_t static_cache;
|
||||
hb_scalar_cache_t *cache = parent_cache ?
|
||||
parent_cache :
|
||||
(this+varStore).create_cache (hb_array (static_cache));
|
||||
(this+varStore).create_cache (&static_cache);
|
||||
|
||||
transform.scale (c.font->x_multf, c.font->y_multf);
|
||||
|
||||
|
|
@ -406,7 +406,7 @@ VARC::get_path_at (const hb_varc_context_t &c,
|
|||
cache);
|
||||
|
||||
if (cache != parent_cache)
|
||||
(this+varStore).destroy_cache (cache, hb_array (static_cache));
|
||||
(this+varStore).destroy_cache (cache, &static_cache);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
18
thirdparty/harfbuzz/src/OT/Var/VARC/VARC.hh
vendored
18
thirdparty/harfbuzz/src/OT/Var/VARC/VARC.hh
vendored
|
|
@ -32,7 +32,7 @@ struct hb_varc_context_t
|
|||
{
|
||||
hb_font_t *font;
|
||||
hb_draw_session_t *draw_session;
|
||||
hb_extents_t *extents;
|
||||
hb_extents_t<> *extents;
|
||||
mutable hb_decycler_t decycler;
|
||||
mutable signed edges_left;
|
||||
mutable signed depth_left;
|
||||
|
|
@ -65,9 +65,9 @@ struct VarComponent
|
|||
get_path_at (const hb_varc_context_t &c,
|
||||
hb_codepoint_t parent_gid,
|
||||
hb_array_t<const int> coords,
|
||||
hb_transform_t transform,
|
||||
hb_transform_t<> transform,
|
||||
hb_ubytes_t record,
|
||||
VarRegionList::cache_t *cache = nullptr) const;
|
||||
hb_scalar_cache_t *cache = nullptr) const;
|
||||
};
|
||||
|
||||
struct VarCompositeGlyph
|
||||
|
|
@ -76,9 +76,9 @@ struct VarCompositeGlyph
|
|||
get_path_at (const hb_varc_context_t &c,
|
||||
hb_codepoint_t gid,
|
||||
hb_array_t<const int> coords,
|
||||
hb_transform_t transform,
|
||||
hb_transform_t<> transform,
|
||||
hb_ubytes_t record,
|
||||
VarRegionList::cache_t *cache)
|
||||
hb_scalar_cache_t *cache)
|
||||
{
|
||||
while (record)
|
||||
{
|
||||
|
|
@ -104,9 +104,9 @@ struct VARC
|
|||
get_path_at (const hb_varc_context_t &c,
|
||||
hb_codepoint_t gid,
|
||||
hb_array_t<const int> coords,
|
||||
hb_transform_t transform = HB_TRANSFORM_IDENTITY,
|
||||
hb_transform_t<> transform = HB_TRANSFORM_IDENTITY,
|
||||
hb_codepoint_t parent_gid = HB_CODEPOINT_INVALID,
|
||||
VarRegionList::cache_t *parent_cache = nullptr) const;
|
||||
hb_scalar_cache_t *parent_cache = nullptr) const;
|
||||
|
||||
bool
|
||||
get_path (hb_font_t *font,
|
||||
|
|
@ -129,7 +129,7 @@ struct VARC
|
|||
bool
|
||||
get_extents (hb_font_t *font,
|
||||
hb_codepoint_t gid,
|
||||
hb_extents_t *extents,
|
||||
hb_extents_t<> *extents,
|
||||
hb_varc_scratch_t &scratch) const
|
||||
{
|
||||
hb_varc_context_t c {font,
|
||||
|
|
@ -196,7 +196,7 @@ struct VARC
|
|||
{
|
||||
if (!table->has_data ()) return false;
|
||||
|
||||
hb_extents_t f_extents;
|
||||
hb_extents_t<> f_extents;
|
||||
|
||||
auto *scratch = acquire_scratch ();
|
||||
if (unlikely (!scratch)) return true;
|
||||
|
|
|
|||
38
thirdparty/harfbuzz/src/OT/glyf/Glyph.hh
vendored
38
thirdparty/harfbuzz/src/OT/glyf/Glyph.hh
vendored
|
|
@ -102,17 +102,15 @@ struct Glyph
|
|||
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);
|
||||
{
|
||||
// Duplicated code.
|
||||
int lsb = 0;
|
||||
int h_delta = face->table.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb) ?
|
||||
(int) header->xMin - lsb : 0;
|
||||
face->table.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb);
|
||||
int h_delta = (int) header->xMin - lsb;
|
||||
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
|
||||
face->table.vmtx->get_leading_bearing_without_var_unscaled (gid, &tsb);
|
||||
#endif
|
||||
;
|
||||
int v_orig = (int) header->yMax + tsb;
|
||||
unsigned h_adv = face->table.hmtx->get_advance_without_var_unscaled (gid);
|
||||
unsigned v_adv =
|
||||
#ifndef HB_NO_VERTICAL
|
||||
|
|
@ -314,6 +312,7 @@ struct Glyph
|
|||
bool use_my_metrics = true,
|
||||
bool phantom_only = false,
|
||||
hb_array_t<const int> coords = hb_array_t<const int> (),
|
||||
hb_scalar_cache_t *gvar_cache = nullptr,
|
||||
unsigned int depth = 0,
|
||||
unsigned *edge_count = nullptr) const
|
||||
{
|
||||
|
|
@ -328,7 +327,7 @@ struct Glyph
|
|||
head_maxp_info->maxComponentDepth = hb_max (head_maxp_info->maxComponentDepth, depth);
|
||||
}
|
||||
|
||||
if (!coords)
|
||||
if (!coords && font->has_nonzero_coords)
|
||||
coords = hb_array (font->coords, font->num_coords);
|
||||
|
||||
contour_point_vector_t &points = type == SIMPLE ? all_points : scratch.comp_points;
|
||||
|
|
@ -357,25 +356,23 @@ struct Glyph
|
|||
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);
|
||||
{
|
||||
// Duplicated code.
|
||||
int lsb = 0;
|
||||
int h_delta = glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb) ?
|
||||
(int) header->xMin - lsb : 0;
|
||||
glyf_accelerator.hmtx->get_leading_bearing_without_var_unscaled (gid, &lsb);
|
||||
int h_delta = (int) header->xMin - lsb;
|
||||
HB_UNUSED int tsb = 0;
|
||||
int v_orig = (int) header->yMax +
|
||||
#ifndef HB_NO_VERTICAL
|
||||
((void) glyf_accelerator.vmtx->get_leading_bearing_without_var_unscaled (gid, &tsb), tsb)
|
||||
#else
|
||||
0
|
||||
glyf_accelerator.vmtx->get_leading_bearing_without_var_unscaled (gid, &tsb);
|
||||
#endif
|
||||
;
|
||||
int v_orig = (int) header->yMax + tsb;
|
||||
unsigned h_adv = glyf_accelerator.hmtx->get_advance_without_var_unscaled (gid);
|
||||
unsigned v_adv =
|
||||
#ifndef HB_NO_VERTICAL
|
||||
glyf_accelerator.vmtx->get_advance_without_var_unscaled (gid)
|
||||
glyf_accelerator.vmtx->get_advance_without_var_unscaled (gid)
|
||||
#else
|
||||
- font->face->get_upem ()
|
||||
- font->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;
|
||||
|
|
@ -383,7 +380,7 @@ struct Glyph
|
|||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
if (coords)
|
||||
if (hb_any (coords))
|
||||
{
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
if (glyf_accelerator.GVAR->has_data ())
|
||||
|
|
@ -391,6 +388,7 @@ struct Glyph
|
|||
coords,
|
||||
points.as_array ().sub_array (old_length),
|
||||
scratch,
|
||||
gvar_cache,
|
||||
phantom_only && type == SIMPLE);
|
||||
else
|
||||
#endif
|
||||
|
|
@ -398,6 +396,7 @@ struct Glyph
|
|||
coords,
|
||||
points.as_array ().sub_array (old_length),
|
||||
scratch,
|
||||
gvar_cache,
|
||||
phantom_only && type == SIMPLE);
|
||||
}
|
||||
#endif
|
||||
|
|
@ -447,6 +446,7 @@ struct Glyph
|
|||
use_my_metrics,
|
||||
phantom_only,
|
||||
coords,
|
||||
gvar_cache,
|
||||
depth + 1,
|
||||
edge_count)))
|
||||
{
|
||||
|
|
|
|||
148
thirdparty/harfbuzz/src/OT/glyf/glyf.hh
vendored
148
thirdparty/harfbuzz/src/OT/glyf/glyf.hh
vendored
|
|
@ -220,7 +220,8 @@ struct glyf_accelerator_t
|
|||
template<typename T>
|
||||
bool get_points (hb_font_t *font, hb_codepoint_t gid, T consumer,
|
||||
hb_array_t<const int> coords,
|
||||
hb_glyf_scratch_t &scratch) const
|
||||
hb_glyf_scratch_t &scratch,
|
||||
hb_scalar_cache_t *gvar_cache = nullptr) const
|
||||
{
|
||||
if (gid >= num_glyphs) return false;
|
||||
|
||||
|
|
@ -228,7 +229,7 @@ struct glyf_accelerator_t
|
|||
all_points.resize (0);
|
||||
|
||||
bool phantom_only = !consumer.is_consuming_contour_points ();
|
||||
if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, scratch, nullptr, nullptr, nullptr, true, true, phantom_only, coords)))
|
||||
if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, scratch, nullptr, nullptr, nullptr, true, true, phantom_only, coords, gvar_cache)))
|
||||
return false;
|
||||
|
||||
unsigned count = all_points.length;
|
||||
|
|
@ -371,28 +372,28 @@ struct glyf_accelerator_t
|
|||
contour_point_t *get_phantoms_sink () { return phantoms; }
|
||||
};
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
unsigned
|
||||
get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t gid, bool is_vertical) const
|
||||
get_advance_with_var_unscaled (hb_codepoint_t gid,
|
||||
hb_font_t *font,
|
||||
bool is_vertical,
|
||||
hb_glyf_scratch_t &scratch,
|
||||
hb_scalar_cache_t *gvar_cache = nullptr) const
|
||||
{
|
||||
if (unlikely (gid >= num_glyphs)) return 0;
|
||||
|
||||
bool success = false;
|
||||
|
||||
contour_point_t phantoms[glyf_impl::PHANTOM_COUNT];
|
||||
if (font->num_coords)
|
||||
{
|
||||
hb_glyf_scratch_t scratch;
|
||||
success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms, false),
|
||||
hb_array (font->coords, font->num_coords),
|
||||
scratch);
|
||||
}
|
||||
|
||||
success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms, false),
|
||||
hb_array (font->coords,
|
||||
font->has_nonzero_coords ? font->num_coords : 0),
|
||||
scratch, gvar_cache);
|
||||
if (unlikely (!success))
|
||||
return
|
||||
#ifndef HB_NO_VERTICAL
|
||||
is_vertical ? vmtx->get_advance_without_var_unscaled (gid) :
|
||||
#endif
|
||||
hmtx->get_advance_without_var_unscaled (gid);
|
||||
{
|
||||
unsigned upem = font->face->get_upem ();
|
||||
return is_vertical ? upem : upem / 2;
|
||||
}
|
||||
|
||||
float result = is_vertical
|
||||
? phantoms[glyf_impl::PHANTOM_TOP].y - phantoms[glyf_impl::PHANTOM_BOTTOM].y
|
||||
|
|
@ -400,40 +401,38 @@ struct glyf_accelerator_t
|
|||
return hb_clamp (roundf (result), 0.f, (float) UINT_MAX / 2);
|
||||
}
|
||||
|
||||
bool get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t gid, bool is_vertical, int *lsb) const
|
||||
float
|
||||
get_v_origin_with_var_unscaled (hb_codepoint_t gid,
|
||||
hb_font_t *font,
|
||||
hb_glyf_scratch_t &scratch,
|
||||
hb_scalar_cache_t *gvar_cache = nullptr) const
|
||||
{
|
||||
if (unlikely (gid >= num_glyphs)) return false;
|
||||
if (unlikely (gid >= num_glyphs)) return 0;
|
||||
|
||||
bool success = false;
|
||||
|
||||
hb_glyph_extents_t extents;
|
||||
hb_glyf_scratch_t scratch;
|
||||
contour_point_t phantoms[glyf_impl::PHANTOM_COUNT];
|
||||
if (unlikely (!get_points (font, gid, points_aggregator_t (font, &extents, phantoms, false),
|
||||
hb_array (font->coords, font->num_coords),
|
||||
scratch)))
|
||||
return false;
|
||||
success = get_points (font, gid, points_aggregator_t (font, nullptr, phantoms, false),
|
||||
hb_array (font->coords,
|
||||
font->has_nonzero_coords ? font->num_coords : 0),
|
||||
scratch, gvar_cache);
|
||||
if (unlikely (!success))
|
||||
{
|
||||
return font->face->get_upem ();
|
||||
}
|
||||
|
||||
*lsb = is_vertical
|
||||
? roundf (phantoms[glyf_impl::PHANTOM_TOP].y) - extents.y_bearing
|
||||
: roundf (phantoms[glyf_impl::PHANTOM_LEFT].x);
|
||||
return true;
|
||||
return phantoms[glyf_impl::PHANTOM_TOP].y;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool get_leading_bearing_without_var_unscaled (hb_codepoint_t gid, bool is_vertical, int *lsb) const
|
||||
{
|
||||
if (unlikely (gid >= num_glyphs)) return false;
|
||||
if (is_vertical) return false; // TODO Humm, what to do here?
|
||||
|
||||
*lsb = glyph_for_gid (gid).get_header ()->xMin;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
bool get_extents (hb_font_t *font,
|
||||
hb_codepoint_t gid,
|
||||
hb_glyph_extents_t *extents) const
|
||||
{ return get_extents_at (font, gid, extents, hb_array (font->coords, font->num_coords)); }
|
||||
{ return get_extents_at (font, gid, extents, hb_array (font->coords,
|
||||
font->has_nonzero_coords ? font->num_coords : 0)); }
|
||||
|
||||
bool get_extents_at (hb_font_t *font,
|
||||
hb_codepoint_t gid,
|
||||
|
|
@ -445,12 +444,16 @@ struct glyf_accelerator_t
|
|||
#ifndef HB_NO_VAR
|
||||
if (coords)
|
||||
{
|
||||
hb_glyf_scratch_t scratch;
|
||||
return get_points (font,
|
||||
gid,
|
||||
points_aggregator_t (font, extents, nullptr, true),
|
||||
coords,
|
||||
scratch);
|
||||
hb_glyf_scratch_t *scratch = acquire_scratch ();
|
||||
if (unlikely (!scratch))
|
||||
return false;
|
||||
bool ret = get_points (font,
|
||||
gid,
|
||||
points_aggregator_t (font, extents, nullptr, true),
|
||||
coords,
|
||||
*scratch);
|
||||
release_scratch (scratch);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
return glyph_for_gid (gid).get_extents_without_var_scaled (font, *this, extents);
|
||||
|
|
@ -485,33 +488,21 @@ struct glyf_accelerator_t
|
|||
}
|
||||
|
||||
bool
|
||||
get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session) const
|
||||
get_path (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session, hb_scalar_cache_t *gvar_cache = nullptr) const
|
||||
{
|
||||
if (!has_data ()) return false;
|
||||
|
||||
hb_glyf_scratch_t *scratch;
|
||||
|
||||
// Borrow the cached strach buffer.
|
||||
{
|
||||
scratch = cached_scratch.get_acquire ();
|
||||
if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
|
||||
{
|
||||
scratch = (hb_glyf_scratch_t *) hb_calloc (1, sizeof (hb_glyf_scratch_t));
|
||||
if (unlikely (!scratch))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
hb_glyf_scratch_t *scratch = acquire_scratch ();
|
||||
if (unlikely (!scratch))
|
||||
return true;
|
||||
|
||||
bool ret = get_points (font, gid, glyf_impl::path_builder_t (font, draw_session),
|
||||
hb_array (font->coords, font->num_coords),
|
||||
*scratch);
|
||||
hb_array (font->coords,
|
||||
font->has_nonzero_coords ? font->num_coords : 0),
|
||||
*scratch,
|
||||
gvar_cache);
|
||||
|
||||
// Put it back.
|
||||
if (!cached_scratch.cmpexch (nullptr, scratch))
|
||||
{
|
||||
scratch->~hb_glyf_scratch_t ();
|
||||
hb_free (scratch);
|
||||
}
|
||||
release_scratch (scratch);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -519,12 +510,35 @@ struct glyf_accelerator_t
|
|||
bool
|
||||
get_path_at (hb_font_t *font, hb_codepoint_t gid, hb_draw_session_t &draw_session,
|
||||
hb_array_t<const int> coords,
|
||||
hb_glyf_scratch_t &scratch) const
|
||||
hb_glyf_scratch_t &scratch,
|
||||
hb_scalar_cache_t *gvar_cache = nullptr) const
|
||||
{
|
||||
if (!has_data ()) return false;
|
||||
return get_points (font, gid, glyf_impl::path_builder_t (font, draw_session),
|
||||
coords,
|
||||
scratch);
|
||||
scratch,
|
||||
gvar_cache);
|
||||
}
|
||||
|
||||
|
||||
hb_glyf_scratch_t *acquire_scratch () const
|
||||
{
|
||||
hb_glyf_scratch_t *scratch = cached_scratch.get_acquire ();
|
||||
if (!scratch || unlikely (!cached_scratch.cmpexch (scratch, nullptr)))
|
||||
{
|
||||
scratch = (hb_glyf_scratch_t *) hb_calloc (1, sizeof (hb_glyf_scratch_t));
|
||||
if (unlikely (!scratch))
|
||||
return nullptr;
|
||||
}
|
||||
return scratch;
|
||||
}
|
||||
void release_scratch (hb_glyf_scratch_t *scratch) const
|
||||
{
|
||||
if (!cached_scratch.cmpexch (nullptr, scratch))
|
||||
{
|
||||
scratch->~hb_glyf_scratch_t ();
|
||||
hb_free (scratch);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ struct ClassDef : public OT::ClassDef
|
|||
class_def_link->width = SmallTypes::size;
|
||||
class_def_link->objidx = class_def_prime_id;
|
||||
class_def_link->position = link_position;
|
||||
class_def_prime_vertex.add_parent (parent_id);
|
||||
class_def_prime_vertex.add_parent (parent_id, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
24
thirdparty/harfbuzz/src/graph/coverage-graph.hh
vendored
24
thirdparty/harfbuzz/src/graph/coverage-graph.hh
vendored
|
|
@ -98,11 +98,33 @@ struct Coverage : public OT::Layout::Common::Coverage
|
|||
coverage_link->width = SmallTypes::size;
|
||||
coverage_link->objidx = coverage_prime_id;
|
||||
coverage_link->position = link_position;
|
||||
coverage_prime_vertex.add_parent (parent_id);
|
||||
coverage_prime_vertex.add_parent (parent_id, false);
|
||||
|
||||
return (Coverage*) coverage_prime_vertex.obj.head;
|
||||
}
|
||||
|
||||
// Filter an existing coverage table to glyphs at indices [start, end) and replace it with the filtered version.
|
||||
static bool filter_coverage (gsubgpos_graph_context_t& c,
|
||||
unsigned existing_coverage,
|
||||
unsigned start, unsigned end) {
|
||||
unsigned coverage_size = c.graph.vertices_[existing_coverage].table_size ();
|
||||
auto& coverage_v = c.graph.vertices_[existing_coverage];
|
||||
Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
|
||||
if (!coverage_table || !coverage_table->sanitize (coverage_v))
|
||||
return false;
|
||||
|
||||
auto new_coverage =
|
||||
+ hb_zip (coverage_table->iter (), hb_range ())
|
||||
| hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
|
||||
return p.second >= start && p.second < end;
|
||||
})
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
|
||||
return make_coverage (c, new_coverage, existing_coverage, coverage_size * 2 + 100);
|
||||
}
|
||||
|
||||
// Replace the coverage table at dest obj with one covering 'glyphs'.
|
||||
template<typename It>
|
||||
static bool make_coverage (gsubgpos_graph_context_t& c,
|
||||
It glyphs,
|
||||
|
|
|
|||
83
thirdparty/harfbuzz/src/graph/graph.hh
vendored
83
thirdparty/harfbuzz/src/graph/graph.hh
vendored
|
|
@ -50,6 +50,7 @@ struct graph_t
|
|||
private:
|
||||
unsigned incoming_edges_ = 0;
|
||||
unsigned single_parent = (unsigned) -1;
|
||||
bool has_incoming_virtual_edges_ = false;
|
||||
hb_hashmap_t<unsigned, unsigned> parents;
|
||||
public:
|
||||
|
||||
|
|
@ -66,6 +67,11 @@ struct graph_t
|
|||
return parents.in_error ();
|
||||
}
|
||||
|
||||
bool has_incoming_virtual_edges () const
|
||||
{
|
||||
return has_incoming_virtual_edges_;
|
||||
}
|
||||
|
||||
bool link_positions_valid (unsigned num_objects, bool removed_nil)
|
||||
{
|
||||
hb_set_t assigned_bytes;
|
||||
|
|
@ -121,7 +127,9 @@ struct graph_t
|
|||
}
|
||||
}
|
||||
|
||||
bool equals (const vertex_t& other,
|
||||
bool equals (unsigned this_index,
|
||||
unsigned other_index,
|
||||
const vertex_t& other,
|
||||
const graph_t& graph,
|
||||
const graph_t& other_graph,
|
||||
unsigned depth) const
|
||||
|
|
@ -129,8 +137,10 @@ struct graph_t
|
|||
if (!(as_bytes () == other.as_bytes ()))
|
||||
{
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
||||
"vertex [%lu] bytes != [%lu] bytes, depth = %u",
|
||||
"vertex %u [%lu bytes] != %u [%lu bytes], depth = %u",
|
||||
this_index,
|
||||
(unsigned long) table_size (),
|
||||
other_index,
|
||||
(unsigned long) other.table_size (),
|
||||
depth);
|
||||
|
||||
|
|
@ -162,6 +172,7 @@ struct graph_t
|
|||
hb_swap (a.single_parent, b.single_parent);
|
||||
hb_swap (a.parents, b.parents);
|
||||
hb_swap (a.incoming_edges_, b.incoming_edges_);
|
||||
hb_swap (a.has_incoming_virtual_edges_, b.has_incoming_virtual_edges_);
|
||||
hb_swap (a.start, b.start);
|
||||
hb_swap (a.end, b.end);
|
||||
hb_swap (a.priority, b.priority);
|
||||
|
|
@ -207,13 +218,16 @@ struct graph_t
|
|||
void reset_parents ()
|
||||
{
|
||||
incoming_edges_ = 0;
|
||||
has_incoming_virtual_edges_ = false;
|
||||
single_parent = (unsigned) -1;
|
||||
parents.reset ();
|
||||
}
|
||||
|
||||
void add_parent (unsigned parent_index)
|
||||
void add_parent (unsigned parent_index, bool is_virtual)
|
||||
{
|
||||
assert (parent_index != (unsigned) -1);
|
||||
has_incoming_virtual_edges_ |= is_virtual;
|
||||
|
||||
if (incoming_edges_ == 0)
|
||||
{
|
||||
single_parent = parent_index;
|
||||
|
|
@ -408,7 +422,7 @@ struct graph_t
|
|||
link_a.bias != link_b.bias)
|
||||
return false;
|
||||
|
||||
if (!graph.vertices_[link_a.objidx].equals (
|
||||
if (!graph.vertices_[link_a.objidx].equals (link_a.objidx, link_b.objidx,
|
||||
other_graph.vertices_[link_b.objidx], graph, other_graph, depth + 1))
|
||||
return false;
|
||||
|
||||
|
|
@ -490,7 +504,7 @@ struct graph_t
|
|||
|
||||
bool operator== (const graph_t& other) const
|
||||
{
|
||||
return root ().equals (other.root (), *this, other, 0);
|
||||
return root ().equals (root_idx(), other.root_idx(), other.root (), *this, other, 0);
|
||||
}
|
||||
|
||||
void print () const {
|
||||
|
|
@ -501,6 +515,9 @@ struct graph_t
|
|||
for (const auto &l : v.obj.real_links) {
|
||||
printf("%u, ", l.objidx);
|
||||
}
|
||||
for (const auto &l : v.obj.virtual_links) {
|
||||
printf("v%u, ", l.objidx);
|
||||
}
|
||||
printf("]\n");
|
||||
}
|
||||
}
|
||||
|
|
@ -556,7 +573,7 @@ struct graph_t
|
|||
link->width = 2;
|
||||
link->objidx = child_id;
|
||||
link->position = (char*) offset - (char*) v.obj.head;
|
||||
vertices_[child_id].add_parent (parent_id);
|
||||
vertices_[child_id].add_parent (parent_id, false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -943,9 +960,11 @@ struct graph_t
|
|||
/*
|
||||
* Moves the child of old_parent_idx pointed to by old_offset to a new
|
||||
* vertex at the new_offset.
|
||||
*
|
||||
* Returns the id of the child node that was moved.
|
||||
*/
|
||||
template<typename O>
|
||||
void move_child (unsigned old_parent_idx,
|
||||
unsigned move_child (unsigned old_parent_idx,
|
||||
const O* old_offset,
|
||||
unsigned new_parent_idx,
|
||||
const O* new_offset)
|
||||
|
|
@ -965,10 +984,12 @@ struct graph_t
|
|||
new_link->position = (const char*) new_offset - (const char*) new_v.obj.head;
|
||||
|
||||
auto& child = vertices_[child_id];
|
||||
child.add_parent (new_parent_idx);
|
||||
child.add_parent (new_parent_idx, false);
|
||||
|
||||
old_v.remove_real_link (child_id, old_offset);
|
||||
child.remove_parent (old_parent_idx);
|
||||
|
||||
return child_id;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1015,12 +1036,12 @@ struct graph_t
|
|||
for (const auto& l : child.obj.real_links)
|
||||
{
|
||||
clone->obj.real_links.push (l);
|
||||
vertices_[l.objidx].add_parent (clone_idx);
|
||||
vertices_[l.objidx].add_parent (clone_idx, false);
|
||||
}
|
||||
for (const auto& l : child.obj.virtual_links)
|
||||
{
|
||||
clone->obj.virtual_links.push (l);
|
||||
vertices_[l.objidx].add_parent (clone_idx);
|
||||
vertices_[l.objidx].add_parent (clone_idx, true);
|
||||
}
|
||||
|
||||
check_success (!clone->obj.real_links.in_error ());
|
||||
|
|
@ -1073,10 +1094,15 @@ struct graph_t
|
|||
const auto& child = vertices_[child_idx];
|
||||
unsigned links_to_child = child.incoming_edges_from_parent(parent_idx);
|
||||
|
||||
if (child.incoming_edges () <= links_to_child)
|
||||
if (child.incoming_edges () <= links_to_child || child.has_incoming_virtual_edges())
|
||||
{
|
||||
// Can't duplicate this node, doing so would orphan the original one as all remaining links
|
||||
// to child are from parent.
|
||||
//
|
||||
// We don't allow duplication of nodes with incoming virtual edges because we don't track
|
||||
// the number of virtual vs real incoming edges. As a result we can't tell if a node
|
||||
// with virtual edges may end up orphaned by duplication (ie. where one copy is only pointed
|
||||
// to by virtual edges).
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %u => %u",
|
||||
parent_idx, child_idx);
|
||||
return -1;
|
||||
|
|
@ -1091,12 +1117,15 @@ struct graph_t
|
|||
if (parent_idx == clone_idx) parent_idx++;
|
||||
|
||||
auto& parent = vertices_[parent_idx];
|
||||
unsigned count = 0;
|
||||
unsigned num_real = parent.obj.real_links.length;
|
||||
for (auto& l : parent.obj.all_links_writer ())
|
||||
{
|
||||
count++;
|
||||
if (l.objidx != child_idx)
|
||||
continue;
|
||||
|
||||
reassign_link (l, parent_idx, clone_idx);
|
||||
reassign_link (l, parent_idx, clone_idx, count > num_real);
|
||||
}
|
||||
|
||||
return clone_idx;
|
||||
|
|
@ -1129,10 +1158,15 @@ struct graph_t
|
|||
links_to_child += child.incoming_edges_from_parent(parent_idx);
|
||||
}
|
||||
|
||||
if (child.incoming_edges () <= links_to_child)
|
||||
if (child.incoming_edges () <= links_to_child || child.has_incoming_virtual_edges())
|
||||
{
|
||||
// Can't duplicate this node, doing so would orphan the original one as all remaining links
|
||||
// to child are from parent.
|
||||
//
|
||||
// We don't allow duplication of nodes with incoming virtual edges because we don't track
|
||||
// the number of virtual vs real incoming edges. As a result we can't tell if a node
|
||||
// with virtual edges may end up orphaned by duplication (ie. where one copy is only pointed
|
||||
// to by virtual edges).
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %u, ..., %u => %u", first_parent, last_parent, child_idx);
|
||||
return -1;
|
||||
}
|
||||
|
|
@ -1146,12 +1180,15 @@ struct graph_t
|
|||
// duplicate shifts the root node idx, so if parent_idx was root update it.
|
||||
if (parent_idx == clone_idx) parent_idx++;
|
||||
auto& parent = vertices_[parent_idx];
|
||||
unsigned count = 0;
|
||||
unsigned num_real = parent.obj.real_links.length;
|
||||
for (auto& l : parent.obj.all_links_writer ())
|
||||
{
|
||||
count++;
|
||||
if (l.objidx != child_idx)
|
||||
continue;
|
||||
|
||||
reassign_link (l, parent_idx, clone_idx);
|
||||
reassign_link (l, parent_idx, clone_idx, count > num_real);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1279,6 +1316,7 @@ struct graph_t
|
|||
if (!DEBUG_ENABLED(SUBSET_REPACK)) return;
|
||||
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr, "Graph is not fully connected.");
|
||||
|
||||
parents_invalid = true;
|
||||
update_parents();
|
||||
|
||||
|
|
@ -1398,8 +1436,11 @@ struct graph_t
|
|||
|
||||
for (unsigned p = 0; p < count; p++)
|
||||
{
|
||||
for (auto& l : vertices_.arrayZ[p].obj.all_links ())
|
||||
vertices_[l.objidx].add_parent (p);
|
||||
for (auto& l : vertices_.arrayZ[p].obj.real_links)
|
||||
vertices_[l.objidx].add_parent (p, false);
|
||||
|
||||
for (auto& l : vertices_.arrayZ[p].obj.virtual_links)
|
||||
vertices_[l.objidx].add_parent (p, true);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
|
|
@ -1502,12 +1543,13 @@ struct graph_t
|
|||
*/
|
||||
void reassign_link (hb_serialize_context_t::object_t::link_t& link,
|
||||
unsigned parent_idx,
|
||||
unsigned new_idx)
|
||||
unsigned new_idx,
|
||||
bool is_virtual)
|
||||
{
|
||||
unsigned old_idx = link.objidx;
|
||||
link.objidx = new_idx;
|
||||
vertices_[old_idx].remove_parent (parent_idx);
|
||||
vertices_[new_idx].add_parent (parent_idx);
|
||||
vertices_[new_idx].add_parent (parent_idx, is_virtual);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1521,13 +1563,16 @@ struct graph_t
|
|||
if (!id_map) return;
|
||||
for (unsigned i : subgraph)
|
||||
{
|
||||
unsigned num_real = vertices_[i].obj.real_links.length;
|
||||
unsigned count = 0;
|
||||
for (auto& link : vertices_[i].obj.all_links_writer ())
|
||||
{
|
||||
count++;
|
||||
const uint32_t *v;
|
||||
if (!id_map.has (link.objidx, &v)) continue;
|
||||
if (only_wide && !(link.width == 4 && !link.is_signed)) continue;
|
||||
|
||||
reassign_link (link, i, *v);
|
||||
reassign_link (link, i, *v, count > num_real);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
74
thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh
vendored
74
thirdparty/harfbuzz/src/graph/gsubgpos-graph.hh
vendored
|
|
@ -27,9 +27,11 @@
|
|||
#include "graph.hh"
|
||||
#include "../hb-ot-layout-gsubgpos.hh"
|
||||
#include "../OT/Layout/GSUB/ExtensionSubst.hh"
|
||||
#include "../OT/Layout/GSUB/SubstLookupSubTable.hh"
|
||||
#include "gsubgpos-context.hh"
|
||||
#include "pairpos-graph.hh"
|
||||
#include "markbasepos-graph.hh"
|
||||
#include "ligature-graph.hh"
|
||||
|
||||
#ifndef GRAPH_GSUBGPOS_GRAPH_HH
|
||||
#define GRAPH_GSUBGPOS_GRAPH_HH
|
||||
|
|
@ -120,12 +122,10 @@ struct Lookup : public OT::Lookup
|
|||
unsigned type = lookupType;
|
||||
bool is_ext = is_extension (c.table_tag);
|
||||
|
||||
if (c.table_tag != HB_OT_TAG_GPOS)
|
||||
if (c.table_tag != HB_OT_TAG_GPOS && c.table_tag != HB_OT_TAG_GSUB)
|
||||
return true;
|
||||
|
||||
if (!is_ext &&
|
||||
type != OT::Layout::GPOS_impl::PosLookupSubTable::Type::Pair &&
|
||||
type != OT::Layout::GPOS_impl::PosLookupSubTable::Type::MarkBase)
|
||||
if (!is_ext && !is_supported_gpos_type(type, c) && !is_supported_gsub_type(type, c))
|
||||
return true;
|
||||
|
||||
hb_vector_t<hb_pair_t<unsigned, hb_vector_t<unsigned>>> all_new_subtables;
|
||||
|
|
@ -144,21 +144,32 @@ struct Lookup : public OT::Lookup
|
|||
|
||||
subtable_index = extension->get_subtable_index (c.graph, ext_subtable_index);
|
||||
type = extension->get_lookup_type ();
|
||||
if (type != OT::Layout::GPOS_impl::PosLookupSubTable::Type::Pair
|
||||
&& type != OT::Layout::GPOS_impl::PosLookupSubTable::Type::MarkBase)
|
||||
if (!is_supported_gpos_type(type, c) && !is_supported_gsub_type(type, c))
|
||||
continue;
|
||||
}
|
||||
|
||||
hb_vector_t<unsigned> new_sub_tables;
|
||||
switch (type)
|
||||
{
|
||||
case 2:
|
||||
new_sub_tables = split_subtable<PairPos> (c, parent_index, subtable_index); break;
|
||||
case 4:
|
||||
new_sub_tables = split_subtable<MarkBasePos> (c, parent_index, subtable_index); break;
|
||||
default:
|
||||
break;
|
||||
|
||||
if (c.table_tag == HB_OT_TAG_GPOS) {
|
||||
switch (type)
|
||||
{
|
||||
case 2:
|
||||
new_sub_tables = split_subtable<PairPos> (c, parent_index, subtable_index); break;
|
||||
case 4:
|
||||
new_sub_tables = split_subtable<MarkBasePos> (c, parent_index, subtable_index); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (c.table_tag == HB_OT_TAG_GSUB) {
|
||||
switch (type)
|
||||
{
|
||||
case 4:
|
||||
new_sub_tables = split_subtable<graph::LigatureSubst> (c, parent_index, subtable_index); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_sub_tables.in_error ()) return false;
|
||||
if (!new_sub_tables) continue;
|
||||
hb_pair_t<unsigned, hb_vector_t<unsigned>>* entry = all_new_subtables.push ();
|
||||
|
|
@ -191,14 +202,14 @@ struct Lookup : public OT::Lookup
|
|||
hb_vector_t<hb_pair_t<unsigned, hb_vector_t<unsigned>>>& subtable_ids)
|
||||
{
|
||||
bool is_ext = is_extension (c.table_tag);
|
||||
auto& v = c.graph.vertices_[this_index];
|
||||
auto* v = &c.graph.vertices_[this_index];
|
||||
fix_existing_subtable_links (c, this_index, subtable_ids);
|
||||
|
||||
unsigned new_subtable_count = 0;
|
||||
for (const auto& p : subtable_ids)
|
||||
new_subtable_count += p.second.length;
|
||||
|
||||
size_t new_size = v.table_size ()
|
||||
size_t new_size = v->table_size ()
|
||||
+ new_subtable_count * OT::Offset16::static_size;
|
||||
char* buffer = (char*) hb_calloc (1, new_size);
|
||||
if (!buffer) return false;
|
||||
|
|
@ -207,10 +218,10 @@ struct Lookup : public OT::Lookup
|
|||
hb_free (buffer);
|
||||
return false;
|
||||
}
|
||||
hb_memcpy (buffer, v.obj.head, v.table_size());
|
||||
hb_memcpy (buffer, v->obj.head, v->table_size());
|
||||
|
||||
v.obj.head = buffer;
|
||||
v.obj.tail = buffer + new_size;
|
||||
v->obj.head = buffer;
|
||||
v->obj.tail = buffer + new_size;
|
||||
|
||||
Lookup* new_lookup = (Lookup*) buffer;
|
||||
|
||||
|
|
@ -226,21 +237,23 @@ struct Lookup : public OT::Lookup
|
|||
if (is_ext)
|
||||
{
|
||||
unsigned ext_id = create_extension_subtable (c, subtable_id, type);
|
||||
c.graph.vertices_[subtable_id].add_parent (ext_id);
|
||||
c.graph.vertices_[subtable_id].add_parent (ext_id, false);
|
||||
subtable_id = ext_id;
|
||||
// the reference to v may have changed on adding a node, so reassign it.
|
||||
v = &c.graph.vertices_[this_index];
|
||||
}
|
||||
|
||||
auto* link = v.obj.real_links.push ();
|
||||
auto* link = v->obj.real_links.push ();
|
||||
link->width = 2;
|
||||
link->objidx = subtable_id;
|
||||
link->position = (char*) &new_lookup->subTable[offset_index++] -
|
||||
(char*) new_lookup;
|
||||
c.graph.vertices_[subtable_id].add_parent (this_index);
|
||||
c.graph.vertices_[subtable_id].add_parent (this_index, false);
|
||||
}
|
||||
}
|
||||
|
||||
// Repacker sort order depends on link order, which we've messed up so resort it.
|
||||
v.obj.real_links.qsort ();
|
||||
v->obj.real_links.qsort ();
|
||||
|
||||
// The head location of the lookup has changed, invalidating the lookups map entry
|
||||
// in the context. Update the map.
|
||||
|
|
@ -326,7 +339,7 @@ struct Lookup : public OT::Lookup
|
|||
|
||||
// Make extension point at the subtable.
|
||||
auto& ext_vertex = c.graph.vertices_[ext_index];
|
||||
ext_vertex.add_parent (lookup_index);
|
||||
ext_vertex.add_parent (lookup_index, false);
|
||||
if (!existing_ext_index)
|
||||
subtable_vertex.remap_parent (lookup_index, ext_index);
|
||||
|
||||
|
|
@ -334,6 +347,19 @@ struct Lookup : public OT::Lookup
|
|||
}
|
||||
|
||||
private:
|
||||
bool is_supported_gsub_type(unsigned type, gsubgpos_graph_context_t& c) const {
|
||||
return (c.table_tag == HB_OT_TAG_GSUB) && (
|
||||
type == OT::Layout::GSUB_impl::SubstLookupSubTable::Type::Ligature
|
||||
);
|
||||
}
|
||||
|
||||
bool is_supported_gpos_type(unsigned type, gsubgpos_graph_context_t& c) const {
|
||||
return (c.table_tag == HB_OT_TAG_GPOS) && (
|
||||
type == OT::Layout::GPOS_impl::PosLookupSubTable::Type::Pair ||
|
||||
type == OT::Layout::GPOS_impl::PosLookupSubTable::Type::MarkBase
|
||||
);
|
||||
}
|
||||
|
||||
unsigned extension_type (hb_tag_t table_tag) const
|
||||
{
|
||||
switch (table_tag)
|
||||
|
|
|
|||
480
thirdparty/harfbuzz/src/graph/ligature-graph.hh
vendored
Normal file
480
thirdparty/harfbuzz/src/graph/ligature-graph.hh
vendored
Normal file
|
|
@ -0,0 +1,480 @@
|
|||
/*
|
||||
* Copyright © 2025 Google, Inc.
|
||||
*
|
||||
* This is part of HarfBuzz, a text shaping library.
|
||||
*
|
||||
* Permission is hereby granted, without written agreement and without
|
||||
* license or royalty fees, to use, copy, modify, and distribute this
|
||||
* software and its documentation for any purpose, provided that the
|
||||
* above copyright notice and the following two paragraphs appear in
|
||||
* all copies of this software.
|
||||
*
|
||||
* IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
||||
* ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
|
||||
* IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
|
||||
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
|
||||
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
|
||||
*
|
||||
* Google Author(s): Garret Rieger
|
||||
*/
|
||||
|
||||
#ifndef GRAPH_LIGATURE_GRAPH_HH
|
||||
#define GRAPH_LIGATURE_GRAPH_HH
|
||||
|
||||
#include "graph.hh"
|
||||
#include "../OT/Layout/GSUB/LigatureSubst.hh"
|
||||
#include "../OT/Layout/GSUB/LigatureSubstFormat1.hh"
|
||||
#include "../OT/Layout/GSUB/LigatureSet.hh"
|
||||
#include "../OT/Layout/types.hh"
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
namespace graph {
|
||||
|
||||
struct LigatureSet : public OT::Layout::GSUB_impl::LigatureSet<SmallTypes>
|
||||
{
|
||||
bool sanitize (graph_t::vertex_t& vertex) const
|
||||
{
|
||||
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
|
||||
if (vertex_len < OT::Layout::GSUB_impl::LigatureSet<SmallTypes>::min_size) return false;
|
||||
hb_barrier ();
|
||||
|
||||
int64_t total_len = ligature.get_size() + OT::Layout::GSUB_impl::LigatureSet<SmallTypes>::min_size - ligature.len.get_size();
|
||||
if (vertex_len < total_len) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
struct LigatureSubstFormat1 : public OT::Layout::GSUB_impl::LigatureSubstFormat1_2<SmallTypes>
|
||||
{
|
||||
bool sanitize (graph_t::vertex_t& vertex) const
|
||||
{
|
||||
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
|
||||
unsigned min_size = OT::Layout::GSUB_impl::LigatureSubstFormat1_2<SmallTypes>::min_size;
|
||||
if (vertex_len < min_size) return false;
|
||||
hb_barrier ();
|
||||
|
||||
return vertex_len >=
|
||||
min_size + ligatureSet.get_size() - ligatureSet.len.get_size();
|
||||
}
|
||||
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
auto split_points = compute_split_points(c, parent_index, this_index);
|
||||
split_context_t split_context {
|
||||
c,
|
||||
this,
|
||||
c.graph.duplicate_if_shared (parent_index, this_index),
|
||||
total_number_ligas(c, this_index),
|
||||
liga_counts(c, this_index),
|
||||
};
|
||||
return actuate_subtable_split<split_context_t> (split_context, split_points);
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned total_number_ligas(gsubgpos_graph_context_t& c, unsigned this_index) const {
|
||||
unsigned total = 0;
|
||||
for (unsigned i = 0; i < ligatureSet.len; i++)
|
||||
{
|
||||
auto liga_set = c.graph.as_table<LigatureSet>(this_index, &ligatureSet[i]);
|
||||
if (!liga_set.table) {
|
||||
return 0;
|
||||
}
|
||||
total += liga_set.table->ligature.len;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
hb_vector_t<unsigned> liga_counts(gsubgpos_graph_context_t& c, unsigned this_index) const {
|
||||
hb_vector_t<unsigned> result;
|
||||
for (unsigned i = 0; i < ligatureSet.len; i++)
|
||||
{
|
||||
auto liga_set = c.graph.as_table<LigatureSet>(this_index, &ligatureSet[i]);
|
||||
result.push(!liga_set.table ? 0 : liga_set.table->ligature.len);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
hb_vector_t<unsigned> compute_split_points(gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index) const
|
||||
{
|
||||
// For ligature subst coverage is always packed last, and as a result is where an overflow
|
||||
// will happen if there is one, so we can check the estimate length of the
|
||||
// LigatureSubstFormat1 -> Coverage offset length which is the sum of all data in the
|
||||
// retained sub graph except for the coverage table itself.
|
||||
const unsigned base_size = OT::Layout::GSUB_impl::LigatureSubstFormat1_2<SmallTypes>::min_size;
|
||||
unsigned accumulated = base_size;
|
||||
|
||||
unsigned ligature_index = 0;
|
||||
hb_vector_t<unsigned> split_points;
|
||||
for (unsigned i = 0; i < ligatureSet.len; i++)
|
||||
{
|
||||
accumulated += OT::HBUINT16::static_size; // for ligature set offset
|
||||
accumulated += OT::Layout::GSUB_impl::LigatureSet<SmallTypes>::min_size; // for ligature set table
|
||||
|
||||
auto liga_set = c.graph.as_table<LigatureSet>(this_index, &ligatureSet[i]);
|
||||
if (!liga_set.table) {
|
||||
return hb_vector_t<unsigned> {};
|
||||
}
|
||||
|
||||
for (unsigned j = 0; j < liga_set.table->ligature.len; j++)
|
||||
{
|
||||
const unsigned liga_id = c.graph.index_for_offset (liga_set.index, &liga_set.table->ligature[j]);
|
||||
const unsigned liga_size = c.graph.vertices_[liga_id].table_size ();
|
||||
|
||||
accumulated += OT::HBUINT16::static_size; // for ligature offset
|
||||
accumulated += liga_size; // for the ligature table
|
||||
|
||||
if (accumulated >= (1 << 16))
|
||||
{
|
||||
split_points.push(ligature_index);
|
||||
// We're going to split such that the current ligature will be in the new sub table.
|
||||
// That means we'll have one ligature subst (base_base), one ligature set, and one liga table
|
||||
accumulated = base_size + // for liga subst subtable
|
||||
(OT::HBUINT16::static_size * 2) + // for liga set and liga offset
|
||||
OT::Layout::GSUB_impl::LigatureSet<SmallTypes>::min_size + // for liga set subtable
|
||||
liga_size; // for liga sub table
|
||||
}
|
||||
|
||||
ligature_index++;
|
||||
}
|
||||
}
|
||||
|
||||
return split_points;
|
||||
}
|
||||
|
||||
|
||||
struct split_context_t
|
||||
{
|
||||
gsubgpos_graph_context_t& c;
|
||||
LigatureSubstFormat1* thiz;
|
||||
unsigned this_index;
|
||||
unsigned original_count_;
|
||||
hb_vector_t<unsigned> liga_counts;
|
||||
|
||||
unsigned original_count ()
|
||||
{
|
||||
return original_count_;
|
||||
}
|
||||
|
||||
unsigned clone_range (unsigned start, unsigned end)
|
||||
{
|
||||
return thiz->clone_range (c, this_index, liga_counts, start, end);
|
||||
}
|
||||
|
||||
bool shrink (unsigned count)
|
||||
{
|
||||
return thiz->shrink (c, this_index, original_count(), liga_counts, count);
|
||||
}
|
||||
};
|
||||
|
||||
hb_pair_t<unsigned, LigatureSet*> new_liga_set(gsubgpos_graph_context_t& c, unsigned count) const {
|
||||
unsigned prime_size = OT::Layout::GSUB_impl::LigatureSet<SmallTypes>::min_size
|
||||
+ count * SmallTypes::size;
|
||||
|
||||
unsigned prime_id = c.create_node (prime_size);
|
||||
if (prime_id == (unsigned) -1) return hb_pair(-1, nullptr);
|
||||
|
||||
LigatureSet* prime = (LigatureSet*) c.graph.object (prime_id).head;
|
||||
prime->ligature.len = count;
|
||||
return hb_pair(prime_id, prime);
|
||||
}
|
||||
|
||||
void clear_virtual_links (gsubgpos_graph_context_t& c, unsigned node_index) const
|
||||
{
|
||||
auto& obj = c.graph.vertices_[node_index].obj;
|
||||
for (const auto& l : obj.virtual_links)
|
||||
{
|
||||
auto& child = c.graph.vertices_[l.objidx];
|
||||
child.remove_parent(node_index);
|
||||
}
|
||||
obj.virtual_links.clear();
|
||||
}
|
||||
|
||||
void add_virtual_link(gsubgpos_graph_context_t& c, unsigned from, unsigned to) const {
|
||||
auto& from_obj = c.graph.vertices_[from].obj;
|
||||
c.graph.vertices_[to].add_parent(from, true);
|
||||
auto& link = *from_obj.virtual_links.push ();
|
||||
link.objidx = to;
|
||||
}
|
||||
|
||||
hb_pair_t<unsigned, unsigned> current_liga_set_bounds (gsubgpos_graph_context_t& c,
|
||||
unsigned liga_set_index,
|
||||
const hb_serialize_context_t::object_t& liga_set) const
|
||||
{
|
||||
// Finds the actual liga indices present in the liga set currently. Takes
|
||||
// into account those that have been removed by processing.
|
||||
unsigned min_index = (unsigned) -1;
|
||||
unsigned max_index = 0;
|
||||
for (const auto& l : liga_set.real_links) {
|
||||
if (l.position < 2) continue;
|
||||
|
||||
unsigned liga_index = (l.position - 2) / 2;
|
||||
min_index = hb_min(min_index, liga_index);
|
||||
max_index = hb_max(max_index, liga_index);
|
||||
}
|
||||
return hb_pair(min_index, max_index + 1);
|
||||
}
|
||||
|
||||
void compact_liga_set (gsubgpos_graph_context_t& c, LigatureSet* table, hb_serialize_context_t::object_t& obj) const
|
||||
{
|
||||
if (table->ligature.len <= obj.real_links.length) return;
|
||||
|
||||
// compact the remaining linked liga offsets into a continous array and shrink the node as needed.
|
||||
unsigned to_remove = table->ligature.len - obj.real_links.length;
|
||||
unsigned new_position = SmallTypes::size;
|
||||
obj.real_links.qsort(); // for this to work we need to process links in order of position.
|
||||
for (auto& l : obj.real_links)
|
||||
{
|
||||
l.position = new_position;
|
||||
new_position += SmallTypes::size;
|
||||
}
|
||||
|
||||
table->ligature.len = obj.real_links.length;
|
||||
obj.tail -= to_remove * SmallTypes::size;
|
||||
}
|
||||
|
||||
unsigned clone_range (gsubgpos_graph_context_t& c,
|
||||
unsigned this_index,
|
||||
hb_vector_t<unsigned> liga_counts,
|
||||
unsigned start, unsigned end) const
|
||||
{
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
||||
" Cloning LigatureSubstFormat1 (%u) range [%u, %u).", this_index, start, end);
|
||||
|
||||
// Create an oversized new liga subst, we'll adjust the size down later. We don't know
|
||||
// the final size until we process it but we also need it to exist while we're processing
|
||||
// so that nodes can be moved to it as needed.
|
||||
unsigned prime_size = OT::Layout::GSUB_impl::LigatureSubstFormat1_2<SmallTypes>::min_size
|
||||
+ ligatureSet.get_size() - ligatureSet.len.get_size();
|
||||
|
||||
unsigned liga_subst_prime_id = c.create_node (prime_size);
|
||||
if (liga_subst_prime_id == (unsigned) -1) return -1;
|
||||
|
||||
LigatureSubstFormat1* liga_subst_prime = (LigatureSubstFormat1*) c.graph.object (liga_subst_prime_id).head;
|
||||
liga_subst_prime->format = this->format;
|
||||
liga_subst_prime->ligatureSet.len = this->ligatureSet.len;
|
||||
|
||||
// Create a place holder coverage prime id since we need to add virtual links to it while
|
||||
// generating liga and liga sets. Afterwards it will be updated to have the correct coverage.
|
||||
unsigned coverage_id = c.graph.index_for_offset (this_index, &coverage);
|
||||
unsigned coverage_prime_id = c.graph.duplicate(coverage_id);
|
||||
auto& coverage_prime_vertex = c.graph.vertices_[coverage_prime_id];
|
||||
auto* coverage_prime_link = c.graph.vertices_[liga_subst_prime_id].obj.real_links.push ();
|
||||
coverage_prime_link->width = SmallTypes::size;
|
||||
coverage_prime_link->objidx = coverage_prime_id;
|
||||
coverage_prime_link->position = 2;
|
||||
coverage_prime_vertex.add_parent (liga_subst_prime_id, false);
|
||||
|
||||
// Locate all liga sets with ligas between start and end.
|
||||
// Clone or move them as needed.
|
||||
unsigned count = 0;
|
||||
unsigned liga_set_count = 0;
|
||||
unsigned liga_set_start = -1;
|
||||
unsigned liga_set_end = 0; // inclusive
|
||||
for (unsigned i = 0; i < liga_counts.length; i++)
|
||||
{
|
||||
unsigned num_ligas = liga_counts[i];
|
||||
|
||||
unsigned current_start = count;
|
||||
unsigned current_end = count + num_ligas;
|
||||
|
||||
if (current_start >= end || start >= current_end) {
|
||||
// No intersection, so just skip
|
||||
count += num_ligas;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto liga_set_index = c.graph.index_for_offset(this_index, &ligatureSet[i]);
|
||||
auto liga_set = c.graph.as_table<LigatureSet>(this_index, &ligatureSet[i]);
|
||||
if (!liga_set.table) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Bounds may need to be adjusted if some ligas have been previously removed.
|
||||
hb_pair_t<unsigned, unsigned> liga_bounds = current_liga_set_bounds(c, liga_set_index, liga_set.vertex->obj);
|
||||
current_start = hb_max(count + liga_bounds.first, current_start);
|
||||
current_end = hb_min(count + liga_bounds.second, current_end);
|
||||
|
||||
unsigned liga_set_prime_id;
|
||||
if (current_start >= start && current_end <= end) {
|
||||
// This liga set is fully contined within [start, end)
|
||||
// We can move the entire ligaset to the new liga subset object.
|
||||
liga_set_end = i;
|
||||
if (i < liga_set_start) liga_set_start = i;
|
||||
liga_set_prime_id = c.graph.move_child<> (this_index,
|
||||
&ligatureSet[i],
|
||||
liga_subst_prime_id,
|
||||
&liga_subst_prime->ligatureSet[liga_set_count++]);
|
||||
compact_liga_set(c, liga_set.table, liga_set.vertex->obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This liga set partially overlaps [start, end). We'll need to create
|
||||
// a new liga set sub table and move the intersecting ligas to it.
|
||||
unsigned liga_count = hb_min(end, current_end) - hb_max(start, current_start);
|
||||
auto result = new_liga_set(c, liga_count);
|
||||
liga_set_prime_id = result.first;
|
||||
LigatureSet* prime = result.second;
|
||||
if (liga_set_prime_id == (unsigned) -1) return -1;
|
||||
|
||||
unsigned new_index = 0;
|
||||
for (unsigned j = hb_max(start, current_start) - count; j < hb_min(end, current_end) - count; j++) {
|
||||
c.graph.move_child<> (liga_set_index,
|
||||
&liga_set.table->ligature[j],
|
||||
liga_set_prime_id,
|
||||
&prime->ligature[new_index++]);
|
||||
}
|
||||
|
||||
liga_set_end = i;
|
||||
if (i < liga_set_start) liga_set_start = i;
|
||||
c.graph.add_link(&liga_subst_prime->ligatureSet[liga_set_count++], liga_subst_prime_id, liga_set_prime_id);
|
||||
}
|
||||
|
||||
// The new liga and all children set needs to have a virtual link to the new coverage table:
|
||||
auto& liga_set_prime = c.graph.vertices_[liga_set_prime_id].obj;
|
||||
clear_virtual_links(c, liga_set_prime_id);
|
||||
add_virtual_link(c, liga_set_prime_id, coverage_prime_id);
|
||||
for (const auto& l : liga_set_prime.real_links) {
|
||||
clear_virtual_links(c, l.objidx);
|
||||
add_virtual_link(c, l.objidx, coverage_prime_id);
|
||||
}
|
||||
|
||||
count += num_ligas;
|
||||
}
|
||||
|
||||
c.graph.vertices_[liga_subst_prime_id].obj.tail -= (liga_subst_prime->ligatureSet.len - liga_set_count) * SmallTypes::size;
|
||||
liga_subst_prime->ligatureSet.len = liga_set_count;
|
||||
|
||||
if (!Coverage::filter_coverage (c,
|
||||
coverage_prime_id,
|
||||
liga_set_start, liga_set_end + 1))
|
||||
return -1;
|
||||
|
||||
return liga_subst_prime_id;
|
||||
}
|
||||
|
||||
bool shrink (gsubgpos_graph_context_t& c,
|
||||
unsigned this_index,
|
||||
unsigned old_count,
|
||||
hb_vector_t<unsigned> liga_counts,
|
||||
unsigned count)
|
||||
{
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
||||
" Shrinking LigatureSubstFormat1 (%u) to [0, %u).",
|
||||
this_index,
|
||||
count);
|
||||
if (count >= old_count)
|
||||
return true;
|
||||
|
||||
hb_set_t retained_indices;
|
||||
unsigned new_liga_set_count = 0;
|
||||
for (unsigned i = 0; i < liga_counts.length; i++)
|
||||
{
|
||||
auto liga_set = c.graph.as_table<LigatureSet>(this_index, &ligatureSet[i]);
|
||||
if (!liga_set.table) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We need the virtual links to coverage removed from all descendants on this liga subst.
|
||||
// If any are left when we try to mutate the coverage table later it will be unnessecarily
|
||||
// duplicated. Code later on will re-add the virtual links as needed (via retained_indices).
|
||||
clear_virtual_links(c, liga_set.index);
|
||||
retained_indices.add(liga_set.index);
|
||||
for (const auto& liga_offset : liga_set.table->ligature) {
|
||||
unsigned liga_index = c.graph.index_for_offset(liga_set.index, &liga_offset);
|
||||
if (liga_index != (unsigned) -1) {
|
||||
clear_virtual_links(c, liga_index);
|
||||
retained_indices.add(liga_index);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned num_ligas = liga_counts[i];
|
||||
if (num_ligas >= count) {
|
||||
// drop the trailing liga's from this set and all subsequent liga sets
|
||||
unsigned num_ligas_to_remove = num_ligas - count;
|
||||
new_liga_set_count = i + 1;
|
||||
c.graph.vertices_[liga_set.index].obj.tail -= num_ligas_to_remove * SmallTypes::size;
|
||||
liga_set.table->ligature.len = count;
|
||||
break;
|
||||
} else {
|
||||
count -= num_ligas;
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust liga set array
|
||||
c.graph.vertices_[this_index].obj.tail -= (ligatureSet.len - new_liga_set_count) * SmallTypes::size;
|
||||
ligatureSet.len = new_liga_set_count;
|
||||
|
||||
// Coverage matches the number of liga sets so rebuild as needed
|
||||
auto coverage = c.graph.as_mutable_table<Coverage> (this_index, &this->coverage);
|
||||
if (!coverage) return false;
|
||||
|
||||
for (unsigned i : retained_indices.iter())
|
||||
add_virtual_link(c, i, coverage.index);
|
||||
|
||||
unsigned coverage_size = coverage.vertex->table_size ();
|
||||
auto new_coverage =
|
||||
+ hb_zip (coverage.table->iter (), hb_range ())
|
||||
| hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
|
||||
return p.second < new_liga_set_count;
|
||||
})
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
|
||||
return Coverage::make_coverage (c, new_coverage, coverage.index, coverage_size);
|
||||
}
|
||||
};
|
||||
|
||||
struct LigatureSubst : public OT::Layout::GSUB_impl::LigatureSubst
|
||||
{
|
||||
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
switch (u.format) {
|
||||
case 1:
|
||||
return ((LigatureSubstFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 2: HB_FALLTHROUGH;
|
||||
// Don't split 24bit Ligature Subs
|
||||
#endif
|
||||
default:
|
||||
return hb_vector_t<unsigned> ();
|
||||
}
|
||||
}
|
||||
|
||||
bool sanitize (graph_t::vertex_t& vertex) const
|
||||
{
|
||||
int64_t vertex_len = vertex.obj.tail - vertex.obj.head;
|
||||
if (vertex_len < u.format.get_size ()) return false;
|
||||
hb_barrier ();
|
||||
|
||||
switch (u.format) {
|
||||
case 1:
|
||||
return ((LigatureSubstFormat1*)(&u.format1))->sanitize (vertex);
|
||||
#ifndef HB_NO_BEYOND_64K
|
||||
case 2: HB_FALLTHROUGH;
|
||||
#endif
|
||||
default:
|
||||
// We don't handle format 2 here.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // GRAPH_LIGATURE_GRAPH_HH
|
||||
|
|
@ -423,7 +423,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
|
|||
class_def_link->width = SmallTypes::size;
|
||||
class_def_link->objidx = class_def_2_id;
|
||||
class_def_link->position = 10;
|
||||
graph.vertices_[class_def_2_id].add_parent (pair_pos_prime_id);
|
||||
graph.vertices_[class_def_2_id].add_parent (pair_pos_prime_id, false);
|
||||
graph.duplicate (pair_pos_prime_id, class_def_2_id);
|
||||
|
||||
return pair_pos_prime_id;
|
||||
|
|
|
|||
16
thirdparty/harfbuzz/src/graph/serialize.hh
vendored
16
thirdparty/harfbuzz/src/graph/serialize.hh
vendored
|
|
@ -172,8 +172,11 @@ void print_overflows (graph_t& graph,
|
|||
template <typename O> inline void
|
||||
serialize_link_of_type (const hb_serialize_context_t::object_t::link_t& link,
|
||||
char* head,
|
||||
unsigned size,
|
||||
hb_serialize_context_t* c)
|
||||
{
|
||||
assert(link.position + link.width <= size);
|
||||
|
||||
OT::Offset<O>* offset = reinterpret_cast<OT::Offset<O>*> (head + link.position);
|
||||
*offset = 0;
|
||||
c->add_link (*offset,
|
||||
|
|
@ -187,6 +190,7 @@ serialize_link_of_type (const hb_serialize_context_t::object_t::link_t& link,
|
|||
inline
|
||||
void serialize_link (const hb_serialize_context_t::object_t::link_t& link,
|
||||
char* head,
|
||||
unsigned size,
|
||||
hb_serialize_context_t* c)
|
||||
{
|
||||
switch (link.width)
|
||||
|
|
@ -197,21 +201,21 @@ void serialize_link (const hb_serialize_context_t::object_t::link_t& link,
|
|||
case 4:
|
||||
if (link.is_signed)
|
||||
{
|
||||
serialize_link_of_type<OT::HBINT32> (link, head, c);
|
||||
serialize_link_of_type<OT::HBINT32> (link, head, size, c);
|
||||
} else {
|
||||
serialize_link_of_type<OT::HBUINT32> (link, head, c);
|
||||
serialize_link_of_type<OT::HBUINT32> (link, head, size, c);
|
||||
}
|
||||
return;
|
||||
case 2:
|
||||
if (link.is_signed)
|
||||
{
|
||||
serialize_link_of_type<OT::HBINT16> (link, head, c);
|
||||
serialize_link_of_type<OT::HBINT16> (link, head, size, c);
|
||||
} else {
|
||||
serialize_link_of_type<OT::HBUINT16> (link, head, c);
|
||||
serialize_link_of_type<OT::HBUINT16> (link, head, size, c);
|
||||
}
|
||||
return;
|
||||
case 3:
|
||||
serialize_link_of_type<OT::HBUINT24> (link, head, c);
|
||||
serialize_link_of_type<OT::HBUINT24> (link, head, size, c);
|
||||
return;
|
||||
default:
|
||||
// Unexpected link width.
|
||||
|
|
@ -251,7 +255,7 @@ inline hb_blob_t* serialize (const graph_t& graph)
|
|||
|
||||
// Only real links needs to be serialized.
|
||||
for (const auto& link : vertices[i].obj.real_links)
|
||||
serialize_link (link, start, &c);
|
||||
serialize_link (link, start, size, &c);
|
||||
|
||||
// All duplications are already encoded in the graph, so don't
|
||||
// enable sharing during packing.
|
||||
|
|
|
|||
247
thirdparty/harfbuzz/src/hb-algs.hh
vendored
247
thirdparty/harfbuzz/src/hb-algs.hh
vendored
|
|
@ -78,129 +78,220 @@
|
|||
|
||||
|
||||
/*
|
||||
* Big-endian integers.
|
||||
* Fixed-endian integers / floats.
|
||||
*/
|
||||
|
||||
|
||||
/* Endian swap, used in Windows related backends */
|
||||
static inline constexpr uint16_t hb_uint16_swap (uint16_t v)
|
||||
{ return (v >> 8) | (v << 8); }
|
||||
static inline constexpr uint32_t hb_uint32_swap (uint32_t v)
|
||||
{ return (hb_uint16_swap (v) << 16) | hb_uint16_swap (v >> 16); }
|
||||
|
||||
#ifndef HB_FAST_INT_ACCESS
|
||||
template <typename Type>
|
||||
struct __attribute__((packed)) hb_packed_t { Type v; };
|
||||
|
||||
#ifndef HB_FAST_NUM_ACCESS
|
||||
#if defined(__OPTIMIZE__) && \
|
||||
defined(__BYTE_ORDER) && \
|
||||
(__BYTE_ORDER == __BIG_ENDIAN || \
|
||||
(__BYTE_ORDER == __LITTLE_ENDIAN && \
|
||||
hb_has_builtin(__builtin_bswap16) && \
|
||||
hb_has_builtin(__builtin_bswap32)))
|
||||
#define HB_FAST_INT_ACCESS 1
|
||||
#define HB_FAST_NUM_ACCESS 1
|
||||
#else
|
||||
#define HB_FAST_INT_ACCESS 0
|
||||
#define HB_FAST_NUM_ACCESS 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
template <typename Type, int Bytes = sizeof (Type)>
|
||||
struct BEInt;
|
||||
template <typename Type>
|
||||
struct BEInt<Type, 1>
|
||||
template <bool BE, typename Type, int Bytes = sizeof (Type)>
|
||||
struct HBInt;
|
||||
template <bool BE, typename Type>
|
||||
struct HBInt<BE, Type, 1>
|
||||
{
|
||||
public:
|
||||
BEInt () = default;
|
||||
constexpr BEInt (Type V) : v {uint8_t (V)} {}
|
||||
HBInt () = default;
|
||||
constexpr HBInt (Type V) : v {uint8_t (V)} {}
|
||||
constexpr operator Type () const { return v; }
|
||||
private: uint8_t v;
|
||||
};
|
||||
template <typename Type>
|
||||
struct BEInt<Type, 2>
|
||||
template <bool BE, typename Type>
|
||||
struct HBInt<BE, Type, 2>
|
||||
{
|
||||
struct __attribute__((packed)) packed_uint16_t { uint16_t v; };
|
||||
|
||||
public:
|
||||
BEInt () = default;
|
||||
HBInt () = default;
|
||||
|
||||
BEInt (Type V)
|
||||
#if HB_FAST_INT_ACCESS
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
{ ((packed_uint16_t *) v)->v = __builtin_bswap16 (V); }
|
||||
#else /* __BYTE_ORDER == __BIG_ENDIAN */
|
||||
{ ((packed_uint16_t *) v)->v = V; }
|
||||
#endif
|
||||
HBInt (Type V)
|
||||
#if HB_FAST_NUM_ACCESS
|
||||
{
|
||||
if (BE == (__BYTE_ORDER == __BIG_ENDIAN))
|
||||
((hb_packed_t<uint16_t> *) v)->v = V;
|
||||
else
|
||||
((hb_packed_t<uint16_t> *) v)->v = __builtin_bswap16 (V);
|
||||
}
|
||||
#else
|
||||
: v {uint8_t ((V >> 8) & 0xFF),
|
||||
uint8_t ((V ) & 0xFF)} {}
|
||||
: v {BE ? uint8_t ((V >> 8) & 0xFF) : uint8_t ((V ) & 0xFF),
|
||||
BE ? uint8_t ((V ) & 0xFF) : uint8_t ((V >> 8) & 0xFF)} {}
|
||||
#endif
|
||||
|
||||
constexpr operator Type () const {
|
||||
#if HB_FAST_INT_ACCESS
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
return __builtin_bswap16 (((packed_uint16_t *) v)->v);
|
||||
#else /* __BYTE_ORDER == __BIG_ENDIAN */
|
||||
return ((packed_uint16_t *) v)->v;
|
||||
#endif
|
||||
constexpr operator Type () const
|
||||
{
|
||||
#if HB_FAST_NUM_ACCESS
|
||||
return (BE == (__BYTE_ORDER == __BIG_ENDIAN)) ?
|
||||
((const hb_packed_t<uint16_t> *) v)->v
|
||||
:
|
||||
__builtin_bswap16 (((const hb_packed_t<uint16_t> *) v)->v)
|
||||
;
|
||||
#else
|
||||
return (v[0] << 8)
|
||||
+ (v[1] );
|
||||
return (BE ? (v[0] << 8) : (v[0] ))
|
||||
+ (BE ? (v[1] ) : (v[1] << 8));
|
||||
#endif
|
||||
}
|
||||
private: uint8_t v[2];
|
||||
};
|
||||
template <typename Type>
|
||||
struct BEInt<Type, 3>
|
||||
template <bool BE, typename Type>
|
||||
struct HBInt<BE, Type, 3>
|
||||
{
|
||||
static_assert (!std::is_signed<Type>::value, "");
|
||||
public:
|
||||
BEInt () = default;
|
||||
constexpr BEInt (Type V) : v {uint8_t ((V >> 16) & 0xFF),
|
||||
uint8_t ((V >> 8) & 0xFF),
|
||||
uint8_t ((V ) & 0xFF)} {}
|
||||
HBInt () = default;
|
||||
constexpr HBInt (Type V) : v {BE ? uint8_t ((V >> 16) & 0xFF) : uint8_t ((V >> 16) & 0xFF),
|
||||
BE ? uint8_t ((V >> 8) & 0xFF) : uint8_t ((V >> 8) & 0xFF),
|
||||
BE ? uint8_t ((V ) & 0xFF) : uint8_t ((V ) & 0xFF)} {}
|
||||
|
||||
constexpr operator Type () const { return (v[0] << 16)
|
||||
+ (v[1] << 8)
|
||||
+ (v[2] ); }
|
||||
constexpr operator Type () const { return (BE ? (v[0] << 16) : (v[0] ))
|
||||
+ (BE ? (v[1] << 8) : (v[1] << 8))
|
||||
+ (BE ? (v[2] ) : (v[2] << 16)); }
|
||||
private: uint8_t v[3];
|
||||
};
|
||||
template <typename Type>
|
||||
struct BEInt<Type, 4>
|
||||
template <bool BE, typename Type>
|
||||
struct HBInt<BE, Type, 4>
|
||||
{
|
||||
struct __attribute__((packed)) packed_uint32_t { uint32_t v; };
|
||||
template <bool, typename, int>
|
||||
friend struct HBFloat;
|
||||
|
||||
public:
|
||||
BEInt () = default;
|
||||
HBInt () = default;
|
||||
|
||||
BEInt (Type V)
|
||||
#if HB_FAST_INT_ACCESS
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
{ ((packed_uint32_t *) v)->v = __builtin_bswap32 (V); }
|
||||
#else /* __BYTE_ORDER == __BIG_ENDIAN */
|
||||
{ ((packed_uint32_t *) v)->v = V; }
|
||||
#endif
|
||||
HBInt (Type V)
|
||||
#if HB_FAST_NUM_ACCESS
|
||||
{
|
||||
if (BE == (__BYTE_ORDER == __BIG_ENDIAN))
|
||||
((hb_packed_t<uint32_t> *) v)->v = V;
|
||||
else
|
||||
((hb_packed_t<uint32_t> *) v)->v = __builtin_bswap32 (V);
|
||||
}
|
||||
#else
|
||||
: v {uint8_t ((V >> 24) & 0xFF),
|
||||
uint8_t ((V >> 16) & 0xFF),
|
||||
uint8_t ((V >> 8) & 0xFF),
|
||||
uint8_t ((V ) & 0xFF)} {}
|
||||
: v {BE ? uint8_t ((V >> 24) & 0xFF) : uint8_t ((V ) & 0xFF),
|
||||
BE ? uint8_t ((V >> 16) & 0xFF) : uint8_t ((V >> 8) & 0xFF),
|
||||
BE ? uint8_t ((V >> 8) & 0xFF) : uint8_t ((V >> 16) & 0xFF),
|
||||
BE ? uint8_t ((V ) & 0xFF) : uint8_t ((V >> 24) & 0xFF)} {}
|
||||
#endif
|
||||
|
||||
constexpr operator Type () const {
|
||||
#if HB_FAST_INT_ACCESS
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
return __builtin_bswap32 (((packed_uint32_t *) v)->v);
|
||||
#else /* __BYTE_ORDER == __BIG_ENDIAN */
|
||||
return ((packed_uint32_t *) v)->v;
|
||||
#endif
|
||||
#if HB_FAST_NUM_ACCESS
|
||||
return (BE == (__BYTE_ORDER == __BIG_ENDIAN)) ?
|
||||
((const hb_packed_t<uint32_t> *) v)->v
|
||||
:
|
||||
__builtin_bswap32 (((const hb_packed_t<uint32_t> *) v)->v)
|
||||
;
|
||||
#else
|
||||
return (v[0] << 24)
|
||||
+ (v[1] << 16)
|
||||
+ (v[2] << 8)
|
||||
+ (v[3] );
|
||||
return (BE ? (v[0] << 24) : (v[0] ))
|
||||
+ (BE ? (v[1] << 16) : (v[1] << 8))
|
||||
+ (BE ? (v[2] << 8) : (v[2] << 16))
|
||||
+ (BE ? (v[3] ) : (v[3] << 24));
|
||||
#endif
|
||||
}
|
||||
private: uint8_t v[4];
|
||||
};
|
||||
template <bool BE, typename Type>
|
||||
struct HBInt<BE, Type, 8>
|
||||
{
|
||||
template <bool, typename, int>
|
||||
friend struct HBFloat;
|
||||
|
||||
public:
|
||||
HBInt () = default;
|
||||
|
||||
HBInt (Type V)
|
||||
: v {BE ? uint8_t ((V >> 56) & 0xFF) : uint8_t ((V ) & 0xFF),
|
||||
BE ? uint8_t ((V >> 48) & 0xFF) : uint8_t ((V >> 8) & 0xFF),
|
||||
BE ? uint8_t ((V >> 40) & 0xFF) : uint8_t ((V >> 16) & 0xFF),
|
||||
BE ? uint8_t ((V >> 32) & 0xFF) : uint8_t ((V >> 24) & 0xFF),
|
||||
BE ? uint8_t ((V >> 24) & 0xFF) : uint8_t ((V >> 32) & 0xFF),
|
||||
BE ? uint8_t ((V >> 16) & 0xFF) : uint8_t ((V >> 40) & 0xFF),
|
||||
BE ? uint8_t ((V >> 8) & 0xFF) : uint8_t ((V >> 48) & 0xFF),
|
||||
BE ? uint8_t ((V ) & 0xFF) : uint8_t ((V >> 56) & 0xFF)} {}
|
||||
|
||||
constexpr operator Type () const {
|
||||
return (BE ? (uint64_t (v[0]) << 56) : (uint64_t (v[0]) ))
|
||||
+ (BE ? (uint64_t (v[1]) << 48) : (uint64_t (v[1]) << 8))
|
||||
+ (BE ? (uint64_t (v[2]) << 40) : (uint64_t (v[2]) << 16))
|
||||
+ (BE ? (uint64_t (v[3]) << 32) : (uint64_t (v[3]) << 24))
|
||||
+ (BE ? (uint64_t (v[4]) << 24) : (uint64_t (v[4]) << 32))
|
||||
+ (BE ? (uint64_t (v[5]) << 16) : (uint64_t (v[5]) << 40))
|
||||
+ (BE ? (uint64_t (v[6]) << 8) : (uint64_t (v[6]) << 48))
|
||||
+ (BE ? (uint64_t (v[7]) ) : (uint64_t (v[7]) << 56));
|
||||
}
|
||||
private: uint8_t v[8];
|
||||
};
|
||||
|
||||
/* Floats. */
|
||||
|
||||
template <bool BE, typename Type, int Bytes>
|
||||
struct HBFloat
|
||||
{
|
||||
using IntType = typename std::conditional<Bytes == 4, uint32_t, uint64_t>::type;
|
||||
|
||||
public:
|
||||
HBFloat () = default;
|
||||
|
||||
HBFloat (Type V)
|
||||
{
|
||||
#if HB_FAST_NUM_ACCESS
|
||||
{
|
||||
if (BE == (__BYTE_ORDER == __BIG_ENDIAN))
|
||||
{
|
||||
((hb_packed_t<Type> *) v)->v = V;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
union {
|
||||
hb_packed_t<Type> f;
|
||||
hb_packed_t<IntType> i;
|
||||
} u = {{V}};
|
||||
|
||||
const HBInt<BE, IntType> I = u.i.v;
|
||||
for (unsigned i = 0; i < Bytes; i++)
|
||||
v[i] = I.v[i];
|
||||
}
|
||||
|
||||
/* c++14 constexpr */ operator Type () const
|
||||
{
|
||||
#if HB_FAST_NUM_ACCESS
|
||||
{
|
||||
if (BE == (__BYTE_ORDER == __BIG_ENDIAN))
|
||||
return ((const hb_packed_t<Type> *) v)->v;
|
||||
}
|
||||
#endif
|
||||
|
||||
HBInt<BE, IntType> I;
|
||||
for (unsigned i = 0; i < Bytes; i++)
|
||||
I.v[i] = v[i];
|
||||
|
||||
union {
|
||||
hb_packed_t<IntType> i;
|
||||
hb_packed_t<Type> f;
|
||||
} u = {{I}};
|
||||
|
||||
return u.f.v;
|
||||
}
|
||||
private: uint8_t v[Bytes];
|
||||
};
|
||||
|
||||
|
||||
/* We want our rounding towards +infinity. */
|
||||
static inline double
|
||||
_hb_roundf (double x) { return floor (x + .5); }
|
||||
|
|
@ -210,6 +301,27 @@ _hb_roundf (float x) { return floorf (x + .5f); }
|
|||
|
||||
#define roundf(x) _hb_roundf(x)
|
||||
|
||||
static inline void
|
||||
hb_sincos (float rotation, float &s, float &c)
|
||||
{
|
||||
#ifdef HAVE_SINCOSF
|
||||
sincosf (rotation, &s, &c);
|
||||
#else
|
||||
c = cosf (rotation);
|
||||
s = sinf (rotation);
|
||||
#endif
|
||||
}
|
||||
static inline void
|
||||
hb_sincos (double rotation, double &s, double &c)
|
||||
{
|
||||
#ifdef HAVE_SINCOS
|
||||
sincos (rotation, &s, &c);
|
||||
#else
|
||||
c = cos (rotation);
|
||||
s = sin (rotation);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Encodes three unsigned integers in one 64-bit number. If the inputs have more than 21 bits,
|
||||
* values will be truncated / overlap, and might not decode exactly. */
|
||||
|
|
@ -1070,6 +1182,7 @@ _hb_cmp_operator (const void *pkey, const void *pval)
|
|||
}
|
||||
|
||||
template <typename V, typename K, typename ...Ts>
|
||||
HB_HOT
|
||||
static inline bool
|
||||
hb_bsearch_impl (unsigned *pos, /* Out */
|
||||
const K& key,
|
||||
|
|
|
|||
7
thirdparty/harfbuzz/src/hb-cache.hh
vendored
7
thirdparty/harfbuzz/src/hb-cache.hh
vendored
|
|
@ -83,6 +83,7 @@ struct hb_cache_t
|
|||
v = -1;
|
||||
}
|
||||
|
||||
HB_HOT
|
||||
bool get (unsigned int key, unsigned int *value) const
|
||||
{
|
||||
unsigned int k = key & ((1u<<cache_bits)-1);
|
||||
|
|
@ -94,14 +95,14 @@ struct hb_cache_t
|
|||
return true;
|
||||
}
|
||||
|
||||
bool set (unsigned int key, unsigned int value)
|
||||
HB_HOT
|
||||
void set (unsigned int key, unsigned int value)
|
||||
{
|
||||
if (unlikely ((key >> key_bits) || (value >> value_bits)))
|
||||
return false; /* Overflows */
|
||||
return; /* Overflows */
|
||||
unsigned int k = key & ((1u<<cache_bits)-1);
|
||||
unsigned int v = ((key>>cache_bits)<<value_bits) | value;
|
||||
values[k] = v;
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
2
thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh
vendored
2
thirdparty/harfbuzz/src/hb-cff2-interp-cs.hh
vendored
|
|
@ -77,7 +77,7 @@ struct cff2_cs_interp_env_t : cs_interp_env_t<ELEM, CFF2Subrs>
|
|||
coords = coords_;
|
||||
num_coords = num_coords_;
|
||||
varStore = acc.varStore;
|
||||
do_blend = num_coords && coords && varStore->size;
|
||||
do_blend = num_coords && varStore->size;
|
||||
set_ivs (acc.privateDicts[fd].ivs);
|
||||
}
|
||||
|
||||
|
|
|
|||
7
thirdparty/harfbuzz/src/hb-common.cc
vendored
7
thirdparty/harfbuzz/src/hb-common.cc
vendored
|
|
@ -545,8 +545,11 @@ hb_script_to_iso15924_tag (hb_script_t script)
|
|||
* Fetches the #hb_direction_t of a script when it is
|
||||
* set horizontally. All right-to-left scripts will return
|
||||
* #HB_DIRECTION_RTL. All left-to-right scripts will return
|
||||
* #HB_DIRECTION_LTR. Scripts that can be written either
|
||||
* horizontally or vertically will return #HB_DIRECTION_INVALID.
|
||||
* #HB_DIRECTION_LTR.
|
||||
*
|
||||
* Scripts that can be written either right-to-left or
|
||||
* left-to-right will return #HB_DIRECTION_INVALID.
|
||||
*
|
||||
* Unknown scripts will return #HB_DIRECTION_LTR.
|
||||
*
|
||||
* Return value: The horizontal #hb_direction_t of @script
|
||||
|
|
|
|||
11
thirdparty/harfbuzz/src/hb-coretext-shape.cc
vendored
11
thirdparty/harfbuzz/src/hb-coretext-shape.cc
vendored
|
|
@ -73,9 +73,7 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
unsigned num_axes = hb_ot_var_get_axis_count (face);
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/5163
|
||||
if (num_axes)
|
||||
if (font->num_coords)
|
||||
{
|
||||
CFMutableDictionaryRef variations =
|
||||
CFDictionaryCreateMutable (kCFAllocatorDefault,
|
||||
|
|
@ -83,15 +81,14 @@ _hb_coretext_shaper_font_data_create (hb_font_t *font)
|
|||
&kCFTypeDictionaryKeyCallBacks,
|
||||
&kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
unsigned count = hb_max (num_axes, font->num_coords);
|
||||
unsigned count = font->num_coords;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
hb_ot_var_axis_info_t info;
|
||||
unsigned int c = 1;
|
||||
hb_ot_var_get_axis_infos (font->face, i, &c, &info);
|
||||
float v = i < font->num_coords ?
|
||||
hb_clamp (font->design_coords[i], info.min_value, info.max_value) :
|
||||
info.default_value;
|
||||
|
||||
float v = hb_clamp (font->design_coords[i], info.min_value, info.max_value);
|
||||
|
||||
CFNumberRef tag_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberIntType, &info.tag);
|
||||
CFNumberRef value_number = CFNumberCreate (kCFAllocatorDefault, kCFNumberFloatType, &v);
|
||||
|
|
|
|||
3
thirdparty/harfbuzz/src/hb-coretext.cc
vendored
3
thirdparty/harfbuzz/src/hb-coretext.cc
vendored
|
|
@ -206,8 +206,9 @@ create_cg_font (hb_blob_t *blob, unsigned int index)
|
|||
if (unlikely (named_instance_index != 0))
|
||||
{
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/5300
|
||||
// https://github.com/harfbuzz/harfbuzz/issues/5354
|
||||
#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED >= 110000) || \
|
||||
(defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101300) || \
|
||||
(defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101500) || \
|
||||
(defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED >= 110000) || \
|
||||
(defined(__WATCH_OS_VERSION_MIN_REQUIRED) && __WATCH_OS_VERSION_MIN_REQUIRED >= 40000) || \
|
||||
(defined(__MACCATALYST_VERSION_MIN_REQUIRED) && __MACCATALYST_VERSION_MIN_REQUIRED >= 130100) || \
|
||||
|
|
|
|||
8
thirdparty/harfbuzz/src/hb-deprecated.h
vendored
8
thirdparty/harfbuzz/src/hb-deprecated.h
vendored
|
|
@ -287,7 +287,7 @@ typedef void (*hb_font_get_glyph_shape_func_t) (hb_font_t *font, void *font_data
|
|||
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* XDeprecated: REPLACEME: Use hb_font_draw_glyph_func_or_fail_t instead.
|
||||
* Deprecated: 11.2.0: Use hb_font_draw_glyph_func_or_fail_t instead.
|
||||
**/
|
||||
typedef void (*hb_font_draw_glyph_func_t) (hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
|
|
@ -308,7 +308,7 @@ typedef void (*hb_font_draw_glyph_func_t) (hb_font_t *font, void *font_data,
|
|||
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* XDeprecated: REPLACEME: Use hb_font_paint_glyph_or_fail_func_t instead.
|
||||
* Deprecated: 11.2.0: Use hb_font_paint_glyph_or_fail_func_t instead.
|
||||
*/
|
||||
typedef hb_bool_t (*hb_font_paint_glyph_func_t) (hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
|
|
@ -346,7 +346,7 @@ hb_font_funcs_set_glyph_shape_func (hb_font_funcs_t *ffuncs,
|
|||
* Sets the implementation function for #hb_font_draw_glyph_func_t.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* XDeprecated: REPLACEME: Use hb_font_funcs_set_draw_glyph_or_fail_func instead.
|
||||
* Deprecated: 11.2.0: Use hb_font_funcs_set_draw_glyph_or_fail_func instead.
|
||||
**/
|
||||
HB_DEPRECATED_FOR (hb_font_funcs_set_draw_glyph_or_fail_func)
|
||||
HB_EXTERN void
|
||||
|
|
@ -364,7 +364,7 @@ hb_font_funcs_set_draw_glyph_func (hb_font_funcs_t *ffuncs,
|
|||
* Sets the implementation function for #hb_font_paint_glyph_func_t.
|
||||
*
|
||||
* Since: 7.0.0
|
||||
* XDeprecated: REPLACEME: Use hb_font_funcs_set_paint_glyph_or_fail_func() instead.
|
||||
* Deprecated: 11.2.0: Use hb_font_funcs_set_paint_glyph_or_fail_func() instead.
|
||||
*/
|
||||
HB_DEPRECATED_FOR (hb_font_funcs_set_paint_glyph_or_fail_func)
|
||||
HB_EXTERN void
|
||||
|
|
|
|||
55
thirdparty/harfbuzz/src/hb-directwrite.cc
vendored
55
thirdparty/harfbuzz/src/hb-directwrite.cc
vendored
|
|
@ -161,6 +161,58 @@ _hb_directwrite_table_data_release (void *data)
|
|||
hb_free (context);
|
||||
}
|
||||
|
||||
static hb_blob_t *
|
||||
_hb_directwrite_get_file_blob (IDWriteFontFace *dw_face)
|
||||
{
|
||||
UINT32 file_count;
|
||||
if (FAILED (dw_face->GetFiles(&file_count, NULL)))
|
||||
return nullptr;
|
||||
|
||||
IDWriteFontFile **files = new IDWriteFontFile*[file_count];
|
||||
if (FAILED (dw_face->GetFiles(&file_count, files)))
|
||||
{
|
||||
delete [] files;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
hb_blob_t *blob = nullptr;
|
||||
for (UINT32 i = 0; i < file_count; i++)
|
||||
{
|
||||
LPCVOID reference_key;
|
||||
UINT32 reference_key_size;
|
||||
if (FAILED (files[i]->GetReferenceKey(&reference_key, &reference_key_size)))
|
||||
continue;
|
||||
|
||||
IDWriteFontFileLoader *loader;
|
||||
if (FAILED (files[i]->GetLoader(&loader)))
|
||||
continue;
|
||||
|
||||
IDWriteFontFileStream *stream;
|
||||
if (FAILED (loader->CreateStreamFromKey (reference_key, reference_key_size, &stream)))
|
||||
{
|
||||
loader->Release ();
|
||||
continue;
|
||||
}
|
||||
|
||||
UINT64 file_size;
|
||||
const void *fragment;
|
||||
void *context;
|
||||
if (FAILED (stream->GetFileSize(&file_size)) ||
|
||||
FAILED (stream->ReadFileFragment (&fragment, 0, file_size, &context)))
|
||||
{
|
||||
loader->Release ();
|
||||
continue;
|
||||
}
|
||||
blob = hb_blob_create ((const char *) fragment, file_size, HB_MEMORY_MODE_DUPLICATE, NULL, NULL);
|
||||
stream->ReleaseFileFragment (context);
|
||||
loader->Release ();
|
||||
break;
|
||||
}
|
||||
|
||||
delete [] files;
|
||||
return blob;
|
||||
}
|
||||
|
||||
static hb_blob_t *
|
||||
_hb_directwrite_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data)
|
||||
{
|
||||
|
|
@ -169,6 +221,9 @@ _hb_directwrite_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *
|
|||
uint32_t length;
|
||||
void *table_context;
|
||||
BOOL exists;
|
||||
if (tag == HB_TAG_NONE)
|
||||
return _hb_directwrite_get_file_blob (dw_face);
|
||||
|
||||
if (FAILED (dw_face->TryGetFontTable (hb_uint32_swap (tag), &data,
|
||||
&length, &table_context, &exists)))
|
||||
return nullptr;
|
||||
|
|
|
|||
22
thirdparty/harfbuzz/src/hb-draw.cc
vendored
22
thirdparty/harfbuzz/src/hb-draw.cc
vendored
|
|
@ -63,14 +63,14 @@ hb_draw_quadratic_to_nil (hb_draw_funcs_t *dfuncs, void *draw_data,
|
|||
float to_x, float to_y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
#define HB_ONE_THIRD 0.33333333f
|
||||
#define HB_TWO_THIRD 0.66666666666666666666666667f
|
||||
dfuncs->emit_cubic_to (draw_data, *st,
|
||||
(st->current_x + 2.f * control_x) * HB_ONE_THIRD,
|
||||
(st->current_y + 2.f * control_y) * HB_ONE_THIRD,
|
||||
(to_x + 2.f * control_x) * HB_ONE_THIRD,
|
||||
(to_y + 2.f * control_y) * HB_ONE_THIRD,
|
||||
st->current_x + (control_x - st->current_x) * HB_TWO_THIRD,
|
||||
st->current_y + (control_y - st->current_y) * HB_TWO_THIRD,
|
||||
to_x + (control_x - to_x) * HB_TWO_THIRD,
|
||||
to_y + (control_y - to_y) * HB_TWO_THIRD,
|
||||
to_x, to_y);
|
||||
#undef HB_ONE_THIRD
|
||||
#undef HB_TWO_THIRD
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -277,7 +277,7 @@ hb_draw_funcs_destroy (hb_draw_funcs_t *dfuncs)
|
|||
* @destroy: (nullable): A callback to call when @data is not needed anymore
|
||||
* @replace: Whether to replace an existing data with the same key
|
||||
*
|
||||
* Attaches a user-data key/data pair to the specified draw-functions structure.
|
||||
* Attaches a user-data key/data pair to the specified draw-functions structure.
|
||||
*
|
||||
* Return value: `true` if success, `false` otherwise
|
||||
*
|
||||
|
|
@ -467,7 +467,7 @@ hb_draw_extents_move_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
|||
float to_x, float to_y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_extents_t *extents = (hb_extents_t *) data;
|
||||
hb_extents_t<> *extents = (hb_extents_t<> *) data;
|
||||
|
||||
extents->add_point (to_x, to_y);
|
||||
}
|
||||
|
|
@ -479,7 +479,7 @@ hb_draw_extents_line_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
|||
float to_x, float to_y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_extents_t *extents = (hb_extents_t *) data;
|
||||
hb_extents_t<> *extents = (hb_extents_t<> *) data;
|
||||
|
||||
extents->add_point (to_x, to_y);
|
||||
}
|
||||
|
|
@ -492,7 +492,7 @@ hb_draw_extents_quadratic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
|||
float to_x, float to_y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_extents_t *extents = (hb_extents_t *) data;
|
||||
hb_extents_t<> *extents = (hb_extents_t<> *) data;
|
||||
|
||||
extents->add_point (control_x, control_y);
|
||||
extents->add_point (to_x, to_y);
|
||||
|
|
@ -507,7 +507,7 @@ hb_draw_extents_cubic_to (hb_draw_funcs_t *dfuncs HB_UNUSED,
|
|||
float to_x, float to_y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
hb_extents_t *extents = (hb_extents_t *) data;
|
||||
hb_extents_t<> *extents = (hb_extents_t<> *) data;
|
||||
|
||||
extents->add_point (control1_x, control1_y);
|
||||
extents->add_point (control2_x, control2_y);
|
||||
|
|
|
|||
3
thirdparty/harfbuzz/src/hb-face-builder.cc
vendored
3
thirdparty/harfbuzz/src/hb-face-builder.cc
vendored
|
|
@ -169,8 +169,7 @@ _hb_face_builder_get_table_tags (const hb_face_t *face HB_UNUSED,
|
|||
|
||||
if (unlikely (start_offset >= population))
|
||||
{
|
||||
if (table_count)
|
||||
*table_count = 0;
|
||||
*table_count = 0;
|
||||
return population;
|
||||
}
|
||||
|
||||
|
|
|
|||
2
thirdparty/harfbuzz/src/hb-face.cc
vendored
2
thirdparty/harfbuzz/src/hb-face.cc
vendored
|
|
@ -329,7 +329,7 @@ hb_face_create_from_file_or_fail (const char *file_name,
|
|||
return face;
|
||||
}
|
||||
|
||||
static struct supported_face_loaders_t {
|
||||
static const struct supported_face_loaders_t {
|
||||
char name[16];
|
||||
hb_face_t * (*from_file) (const char *font_file, unsigned face_index);
|
||||
hb_face_t * (*from_blob) (hb_blob_t *blob, unsigned face_index);
|
||||
|
|
|
|||
248
thirdparty/harfbuzz/src/hb-font.cc
vendored
248
thirdparty/harfbuzz/src/hb-font.cc
vendored
|
|
@ -246,7 +246,6 @@ hb_font_get_glyph_v_advance_nil (hb_font_t *font,
|
|||
hb_codepoint_t glyph HB_UNUSED,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
/* TODO use font_extents.ascender+descender */
|
||||
return -font->y_scale;
|
||||
}
|
||||
|
||||
|
|
@ -352,6 +351,10 @@ hb_font_get_glyph_h_origin_default (hb_font_t *font,
|
|||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->has_glyph_h_origins_func_set ())
|
||||
{
|
||||
return font->get_glyph_h_origins (1, &glyph, 0, x, 0, y, 0, false);
|
||||
}
|
||||
hb_bool_t ret = font->parent->get_glyph_h_origin (glyph, x, y);
|
||||
if (ret)
|
||||
font->parent_scale_position (x, y);
|
||||
|
|
@ -366,7 +369,6 @@ hb_font_get_glyph_v_origin_nil (hb_font_t *font HB_UNUSED,
|
|||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
*x = *y = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -378,12 +380,100 @@ hb_font_get_glyph_v_origin_default (hb_font_t *font,
|
|||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->has_glyph_v_origins_func_set ())
|
||||
{
|
||||
return font->get_glyph_v_origins (1, &glyph, 0, x, 0, y, 0, false);
|
||||
}
|
||||
hb_bool_t ret = font->parent->get_glyph_v_origin (glyph, x, y);
|
||||
if (ret)
|
||||
font->parent_scale_position (x, y);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define hb_font_get_glyph_h_origins_nil hb_font_get_glyph_h_origins_default
|
||||
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_h_origins_default (hb_font_t *font HB_UNUSED,
|
||||
void *font_data HB_UNUSED,
|
||||
unsigned int count,
|
||||
const hb_codepoint_t *first_glyph HB_UNUSED,
|
||||
unsigned glyph_stride HB_UNUSED,
|
||||
hb_position_t *first_x,
|
||||
unsigned x_stride,
|
||||
hb_position_t *first_y,
|
||||
unsigned y_stride,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->has_glyph_h_origin_func_set ())
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
font->get_glyph_h_origin (*first_glyph, first_x, first_y, false);
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
|
||||
first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
hb_bool_t ret = font->parent->get_glyph_h_origins (count,
|
||||
first_glyph, glyph_stride,
|
||||
first_x, x_stride,
|
||||
first_y, y_stride);
|
||||
if (ret)
|
||||
{
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
font->parent_scale_position (first_x, first_y);
|
||||
first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
|
||||
first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define hb_font_get_glyph_v_origins_nil hb_font_get_glyph_v_origins_default
|
||||
|
||||
static hb_bool_t
|
||||
hb_font_get_glyph_v_origins_default (hb_font_t *font HB_UNUSED,
|
||||
void *font_data HB_UNUSED,
|
||||
unsigned int count,
|
||||
const hb_codepoint_t *first_glyph HB_UNUSED,
|
||||
unsigned glyph_stride HB_UNUSED,
|
||||
hb_position_t *first_x,
|
||||
unsigned x_stride,
|
||||
hb_position_t *first_y,
|
||||
unsigned y_stride,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
if (font->has_glyph_v_origin_func_set ())
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
font->get_glyph_v_origin (*first_glyph, first_x, first_y, false);
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
|
||||
first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
hb_bool_t ret = font->parent->get_glyph_v_origins (count,
|
||||
first_glyph, glyph_stride,
|
||||
first_x, x_stride,
|
||||
first_y, y_stride);
|
||||
if (ret)
|
||||
{
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
font->parent_scale_position (first_x, first_y);
|
||||
first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
|
||||
first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static hb_position_t
|
||||
hb_font_get_glyph_h_kerning_nil (hb_font_t *font HB_UNUSED,
|
||||
void *font_data HB_UNUSED,
|
||||
|
|
@ -1256,6 +1346,77 @@ hb_font_get_glyph_v_origin (hb_font_t *font,
|
|||
return font->get_glyph_v_origin (glyph, x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_get_glyph_h_origins:
|
||||
* @font: #hb_font_t to work upon
|
||||
* @count: The number of glyph IDs in the sequence queried
|
||||
* @first_glyph: The first glyph ID to query
|
||||
* @glyph_stride: The stride between successive glyph IDs
|
||||
* @first_x: (out): The first X coordinate of the origin retrieved
|
||||
* @x_stride: The stride between successive X coordinates
|
||||
* @first_y: (out): The first Y coordinate of the origin retrieved
|
||||
* @y_stride: The stride between successive Y coordinates
|
||||
*
|
||||
* Fetches the (X,Y) coordinates of the origin for requested glyph IDs
|
||||
* in the specified font, for horizontal text segments.
|
||||
*
|
||||
* Return value: `true` if data found, `false` otherwise
|
||||
*
|
||||
* Since: 11.3.0
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_font_get_glyph_h_origins (hb_font_t *font,
|
||||
unsigned int count,
|
||||
const hb_codepoint_t *first_glyph,
|
||||
unsigned int glyph_stride,
|
||||
hb_position_t *first_x,
|
||||
unsigned int x_stride,
|
||||
hb_position_t *first_y,
|
||||
unsigned int y_stride)
|
||||
|
||||
{
|
||||
return font->get_glyph_h_origins (count,
|
||||
first_glyph, glyph_stride,
|
||||
first_x, x_stride,
|
||||
first_y, y_stride);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_font_get_glyph_v_origins:
|
||||
* @font: #hb_font_t to work upon
|
||||
* @count: The number of glyph IDs in the sequence queried
|
||||
* @first_glyph: The first glyph ID to query
|
||||
* @glyph_stride: The stride between successive glyph IDs
|
||||
* @first_x: (out): The first X coordinate of the origin retrieved
|
||||
* @x_stride: The stride between successive X coordinates
|
||||
* @first_y: (out): The first Y coordinate of the origin retrieved
|
||||
* @y_stride: The stride between successive Y coordinates
|
||||
*
|
||||
* Fetches the (X,Y) coordinates of the origin for requested glyph IDs
|
||||
* in the specified font, for vertical text segments.
|
||||
*
|
||||
* Return value: `true` if data found, `false` otherwise
|
||||
*
|
||||
* Since: 11.3.0
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_font_get_glyph_v_origins (hb_font_t *font,
|
||||
unsigned int count,
|
||||
const hb_codepoint_t *first_glyph,
|
||||
unsigned int glyph_stride,
|
||||
hb_position_t *first_x,
|
||||
unsigned int x_stride,
|
||||
hb_position_t *first_y,
|
||||
unsigned int y_stride)
|
||||
|
||||
{
|
||||
return font->get_glyph_v_origins (count,
|
||||
first_glyph, glyph_stride,
|
||||
first_x, x_stride,
|
||||
first_y, y_stride);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hb_font_get_glyph_h_kerning:
|
||||
* @font: #hb_font_t to work upon
|
||||
|
|
@ -1443,7 +1604,7 @@ hb_font_get_glyph_shape (hb_font_t *font,
|
|||
*
|
||||
* Return value: `true` if glyph was drawn, `false` otherwise
|
||||
*
|
||||
* XSince: REPLACEME
|
||||
* Since: 11.2.0
|
||||
**/
|
||||
hb_bool_t
|
||||
hb_font_draw_glyph_or_fail (hb_font_t *font,
|
||||
|
|
@ -1480,7 +1641,7 @@ hb_font_draw_glyph_or_fail (hb_font_t *font,
|
|||
*
|
||||
* Return value: `true` if glyph was painted, `false` otherwise
|
||||
*
|
||||
* XSince: REPLACEME
|
||||
* Since: 11.2.0
|
||||
*/
|
||||
hb_bool_t
|
||||
hb_font_paint_glyph_or_fail (hb_font_t *font,
|
||||
|
|
@ -1883,6 +2044,7 @@ DEFINE_NULL_INSTANCE (hb_font_t) =
|
|||
|
||||
1000, /* x_scale */
|
||||
1000, /* y_scale */
|
||||
false, /* is_synthetic */
|
||||
0.f, /* x_embolden */
|
||||
0.f, /* y_embolden */
|
||||
true, /* embolden_in_place */
|
||||
|
|
@ -1900,6 +2062,7 @@ DEFINE_NULL_INSTANCE (hb_font_t) =
|
|||
0, /* ptem */
|
||||
|
||||
HB_FONT_NO_VAR_NAMED_INSTANCE, /* instance_index */
|
||||
false, /* has_nonzero_coords */
|
||||
0, /* num_coords */
|
||||
nullptr, /* coords */
|
||||
nullptr, /* design_coords */
|
||||
|
|
@ -1960,8 +2123,14 @@ hb_font_create (hb_face_t *face)
|
|||
hb_font_set_funcs_using (font, nullptr);
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
if (face && face->index >> 16)
|
||||
hb_font_set_var_named_instance (font, (face->index >> 16) - 1);
|
||||
// Initialize variations.
|
||||
if (likely (face))
|
||||
{
|
||||
if (face->index >> 16)
|
||||
hb_font_set_var_named_instance (font, (face->index >> 16) - 1);
|
||||
else
|
||||
hb_font_set_variations (font, nullptr, 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
return font;
|
||||
|
|
@ -1979,6 +2148,7 @@ _hb_font_adopt_var_coords (hb_font_t *font,
|
|||
font->coords = coords;
|
||||
font->design_coords = design_coords;
|
||||
font->num_coords = coords_length;
|
||||
font->has_nonzero_coords = hb_any (hb_array (coords, coords_length));
|
||||
|
||||
font->changed ();
|
||||
font->serial_coords = font->serial;
|
||||
|
|
@ -2393,7 +2563,7 @@ hb_font_set_funcs_data (hb_font_t *font,
|
|||
font->changed ();
|
||||
}
|
||||
|
||||
static struct supported_font_funcs_t {
|
||||
static const struct supported_font_funcs_t {
|
||||
char name[16];
|
||||
void (*func) (hb_font_t *);
|
||||
} supported_font_funcs[] =
|
||||
|
|
@ -2450,6 +2620,9 @@ hb_bool_t
|
|||
hb_font_set_funcs_using (hb_font_t *font,
|
||||
const char *name)
|
||||
{
|
||||
if (unlikely (hb_object_is_immutable (font)))
|
||||
return false;
|
||||
|
||||
bool retry = false;
|
||||
|
||||
if (!name || !*name)
|
||||
|
|
@ -2704,12 +2877,12 @@ hb_font_get_ptem (hb_font_t *font)
|
|||
*
|
||||
* Return value: `true` if the font is synthetic, `false` otherwise.
|
||||
*
|
||||
* XSince: REPLACEME
|
||||
* Since: 11.2.0
|
||||
*/
|
||||
hb_bool_t
|
||||
hb_font_is_synthetic (hb_font_t *font)
|
||||
{
|
||||
return font->is_synthetic ();
|
||||
return font->is_synthetic;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2858,12 +3031,6 @@ hb_font_set_variations (hb_font_t *font,
|
|||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
if (!variations_length && font->instance_index == HB_FONT_NO_VAR_NAMED_INSTANCE)
|
||||
{
|
||||
hb_font_set_var_coords_normalized (font, nullptr, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
const OT::fvar &fvar = *font->face->table.fvar;
|
||||
auto axes = fvar.get_axes ();
|
||||
const unsigned coords_length = axes.length;
|
||||
|
|
@ -2970,7 +3137,6 @@ hb_font_set_variation (hb_font_t *font,
|
|||
|
||||
hb_ot_var_normalize_coords (font->face, coords_length, design_coords, normalized);
|
||||
_hb_font_adopt_var_coords (font, normalized, design_coords, coords_length);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2991,11 +3157,16 @@ hb_font_set_variation (hb_font_t *font,
|
|||
void
|
||||
hb_font_set_var_coords_design (hb_font_t *font,
|
||||
const float *coords,
|
||||
unsigned int coords_length)
|
||||
unsigned int input_coords_length)
|
||||
{
|
||||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
const OT::fvar &fvar = *font->face->table.fvar;
|
||||
auto axes = fvar.get_axes ();
|
||||
const unsigned coords_length = axes.length;
|
||||
|
||||
input_coords_length = hb_min (input_coords_length, coords_length);
|
||||
int *normalized = coords_length ? (int *) hb_calloc (coords_length, sizeof (int)) : nullptr;
|
||||
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (float)) : nullptr;
|
||||
|
||||
|
|
@ -3006,8 +3177,11 @@ hb_font_set_var_coords_design (hb_font_t *font,
|
|||
return;
|
||||
}
|
||||
|
||||
if (coords_length)
|
||||
hb_memcpy (design_coords, coords, coords_length * sizeof (font->design_coords[0]));
|
||||
if (input_coords_length)
|
||||
hb_memcpy (design_coords, coords, input_coords_length * sizeof (font->design_coords[0]));
|
||||
// Fill in the rest with default values
|
||||
for (unsigned int i = input_coords_length; i < coords_length; i++)
|
||||
design_coords[i] = axes[i].get_default ();
|
||||
|
||||
hb_ot_var_normalize_coords (font->face, coords_length, coords, normalized);
|
||||
_hb_font_adopt_var_coords (font, normalized, design_coords, coords_length);
|
||||
|
|
@ -3072,34 +3246,31 @@ hb_font_get_var_named_instance (hb_font_t *font)
|
|||
void
|
||||
hb_font_set_var_coords_normalized (hb_font_t *font,
|
||||
const int *coords, /* 2.14 normalized */
|
||||
unsigned int coords_length)
|
||||
unsigned int input_coords_length)
|
||||
{
|
||||
if (hb_object_is_immutable (font))
|
||||
return;
|
||||
|
||||
const OT::fvar &fvar = *font->face->table.fvar;
|
||||
auto axes = fvar.get_axes ();
|
||||
unsigned coords_length = axes.length;
|
||||
|
||||
input_coords_length = hb_min (input_coords_length, coords_length);
|
||||
int *copy = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
|
||||
int *unmapped = coords_length ? (int *) hb_calloc (coords_length, sizeof (coords[0])) : nullptr;
|
||||
float *design_coords = coords_length ? (float *) hb_calloc (coords_length, sizeof (design_coords[0])) : nullptr;
|
||||
|
||||
if (unlikely (coords_length && !(copy && unmapped && design_coords)))
|
||||
if (unlikely (coords_length && !(copy && design_coords)))
|
||||
{
|
||||
hb_free (copy);
|
||||
hb_free (unmapped);
|
||||
hb_free (design_coords);
|
||||
return;
|
||||
}
|
||||
|
||||
if (coords_length)
|
||||
{
|
||||
hb_memcpy (copy, coords, coords_length * sizeof (coords[0]));
|
||||
hb_memcpy (unmapped, coords, coords_length * sizeof (coords[0]));
|
||||
}
|
||||
if (input_coords_length)
|
||||
hb_memcpy (copy, coords, input_coords_length * sizeof (coords[0]));
|
||||
|
||||
/* Best effort design coords simulation */
|
||||
font->face->table.avar->unmap_coords (unmapped, coords_length);
|
||||
for (unsigned int i = 0; i < coords_length; ++i)
|
||||
design_coords[i] = font->face->table.fvar->unnormalize_axis_value (i, unmapped[i]);
|
||||
hb_free (unmapped);
|
||||
design_coords[i] = NAN;
|
||||
|
||||
_hb_font_adopt_var_coords (font, copy, design_coords, coords_length);
|
||||
}
|
||||
|
|
@ -3112,8 +3283,8 @@ hb_font_set_var_coords_normalized (hb_font_t *font,
|
|||
* Fetches the list of normalized variation coordinates currently
|
||||
* set on a font.
|
||||
*
|
||||
* Note that this returned array may only contain values for some
|
||||
* (or none) of the axes; omitted axes effectively have zero values.
|
||||
* <note>Note that if no variation coordinates are set, this function may
|
||||
* return %NULL.</note>
|
||||
*
|
||||
* Return value is valid as long as variation coordinates of the font
|
||||
* are not modified.
|
||||
|
|
@ -3140,9 +3311,12 @@ hb_font_get_var_coords_normalized (hb_font_t *font,
|
|||
* Fetches the list of variation coordinates (in design-space units) currently
|
||||
* set on a font.
|
||||
*
|
||||
* Note that this returned array may only contain values for some
|
||||
* (or none) of the axes; omitted axes effectively have their default
|
||||
* values.
|
||||
* <note>Note that if no variation coordinates are set, this function may
|
||||
* return %NULL.</note>
|
||||
*
|
||||
* <note>If variations have been set on the font using normalized coordinates
|
||||
* (i.e. via hb_font_set_var_coords_normalized()), the design coordinates will
|
||||
* have NaN (Not a Number) values.</note>
|
||||
*
|
||||
* Return value is valid as long as variation coordinates of the font
|
||||
* are not modified.
|
||||
|
|
|
|||
129
thirdparty/harfbuzz/src/hb-font.h
vendored
129
thirdparty/harfbuzz/src/hb-font.h
vendored
|
|
@ -97,7 +97,7 @@ hb_font_funcs_is_immutable (hb_font_funcs_t *ffuncs);
|
|||
* @descender: The depth of typographic descenders.
|
||||
* @line_gap: The suggested line-spacing gap.
|
||||
*
|
||||
* Font-wide extent values, measured in font units.
|
||||
* Font-wide extent values, measured in scaled units.
|
||||
*
|
||||
* Note that typically @ascender is positive and @descender
|
||||
* negative, in coordinate systems that grow up.
|
||||
|
|
@ -332,7 +332,7 @@ typedef hb_font_get_glyph_advances_func_t hb_font_get_glyph_v_advances_func_t;
|
|||
*
|
||||
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
|
||||
*
|
||||
* This method should retrieve the (X,Y) coordinates (in font units) of the
|
||||
* This method should retrieve the (X,Y) coordinates (in scaled units) of the
|
||||
* origin for a glyph. Each coordinate must be returned in an #hb_position_t
|
||||
* output parameter.
|
||||
*
|
||||
|
|
@ -349,7 +349,7 @@ typedef hb_bool_t (*hb_font_get_glyph_origin_func_t) (hb_font_t *font, void *fon
|
|||
*
|
||||
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
|
||||
*
|
||||
* This method should retrieve the (X,Y) coordinates (in font units) of the
|
||||
* This method should retrieve the (X,Y) coordinates (in scaled units) of the
|
||||
* origin for a glyph, for horizontal-direction text segments. Each
|
||||
* coordinate must be returned in an #hb_position_t output parameter.
|
||||
*
|
||||
|
|
@ -361,13 +361,72 @@ typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_h_origin_func_t;
|
|||
*
|
||||
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
|
||||
*
|
||||
* This method should retrieve the (X,Y) coordinates (in font units) of the
|
||||
* This method should retrieve the (X,Y) coordinates (in scaled units) of the
|
||||
* origin for a glyph, for vertical-direction text segments. Each coordinate
|
||||
* must be returned in an #hb_position_t output parameter.
|
||||
*
|
||||
**/
|
||||
typedef hb_font_get_glyph_origin_func_t hb_font_get_glyph_v_origin_func_t;
|
||||
|
||||
/**
|
||||
* hb_font_get_glyph_origins_func_t:
|
||||
* @font: #hb_font_t to work upon
|
||||
* @font_data: @font user data pointer
|
||||
* @first_glyph: The first glyph ID to query
|
||||
* @count: number of glyphs to query
|
||||
* @glyph_stride: The stride between successive glyph IDs
|
||||
* @first_x: (out): The first origin X coordinate retrieved
|
||||
* @x_stride: The stride between successive origin X coordinates
|
||||
* @first_y: (out): The first origin Y coordinate retrieved
|
||||
* @y_stride: The stride between successive origin Y coordinates
|
||||
* @user_data: User data pointer passed by the caller
|
||||
*
|
||||
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
|
||||
*
|
||||
* This method should retrieve the (X,Y) coordinates (in scaled units) of the
|
||||
* origin for each requested glyph. Each coordinate value must be returned in
|
||||
* an #hb_position_t in the two output parameters.
|
||||
*
|
||||
* Return value: `true` if data found, `false` otherwise
|
||||
*
|
||||
* Since: 11.3.0
|
||||
**/
|
||||
typedef hb_bool_t (*hb_font_get_glyph_origins_func_t) (hb_font_t *font, void *font_data,
|
||||
unsigned int count,
|
||||
const hb_codepoint_t *first_glyph,
|
||||
unsigned glyph_stride,
|
||||
hb_position_t *first_x,
|
||||
unsigned x_stride,
|
||||
hb_position_t *first_y,
|
||||
unsigned y_stride,
|
||||
void *user_data);
|
||||
|
||||
/**
|
||||
* hb_font_get_glyph_h_origins_func_t:
|
||||
*
|
||||
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
|
||||
*
|
||||
* This method should retrieve the (X,Y) coordinates (in scaled units) of the
|
||||
* origin for requested glyph, for horizontal-direction text segments. Each
|
||||
* coordinate must be returned in a the x/y #hb_position_t output parameters.
|
||||
*
|
||||
* Since: 11.3.0
|
||||
**/
|
||||
typedef hb_font_get_glyph_origins_func_t hb_font_get_glyph_h_origins_func_t;
|
||||
|
||||
/**
|
||||
* hb_font_get_glyph_v_origins_func_t:
|
||||
*
|
||||
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
|
||||
*
|
||||
* This method should retrieve the (X,Y) coordinates (in scaled units) of the
|
||||
* origin for requested glyph, for vertical-direction text segments. Each
|
||||
* coordinate must be returned in a the x/y #hb_position_t output parameters.
|
||||
*
|
||||
* Since: 11.3.0
|
||||
**/
|
||||
typedef hb_font_get_glyph_origins_func_t hb_font_get_glyph_v_origins_func_t;
|
||||
|
||||
/**
|
||||
* hb_font_get_glyph_kerning_func_t:
|
||||
* @font: #hb_font_t to work upon
|
||||
|
|
@ -428,7 +487,7 @@ typedef hb_bool_t (*hb_font_get_glyph_extents_func_t) (hb_font_t *font, void *fo
|
|||
*
|
||||
* A virtual method for the #hb_font_funcs_t of an #hb_font_t object.
|
||||
*
|
||||
* This method should retrieve the (X,Y) coordinates (in font units) for a
|
||||
* This method should retrieve the (X,Y) coordinates (in scaled units) for a
|
||||
* specified contour point in a glyph. Each coordinate must be returned as
|
||||
* an #hb_position_t output parameter.
|
||||
*
|
||||
|
|
@ -498,7 +557,7 @@ typedef hb_bool_t (*hb_font_get_glyph_from_name_func_t) (hb_font_t *font, void *
|
|||
*
|
||||
* Return value: `true` if glyph was drawn, `false` otherwise
|
||||
*
|
||||
* XSince: REPLACEME
|
||||
* Since: 11.2.0
|
||||
**/
|
||||
typedef hb_bool_t (*hb_font_draw_glyph_or_fail_func_t) (hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
|
|
@ -520,7 +579,7 @@ typedef hb_bool_t (*hb_font_draw_glyph_or_fail_func_t) (hb_font_t *font, void *f
|
|||
*
|
||||
* Return value: `true` if glyph was painted, `false` otherwise
|
||||
*
|
||||
* XSince: REPLACEME
|
||||
* Since: 11.2.0
|
||||
*/
|
||||
typedef hb_bool_t (*hb_font_paint_glyph_or_fail_func_t) (hb_font_t *font, void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
|
|
@ -707,6 +766,38 @@ hb_font_funcs_set_glyph_v_origin_func (hb_font_funcs_t *ffuncs,
|
|||
hb_font_get_glyph_v_origin_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
/**
|
||||
* hb_font_funcs_set_glyph_h_origins_func:
|
||||
* @ffuncs: A font-function structure
|
||||
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
|
||||
* @user_data: Data to pass to @func
|
||||
* @destroy: (nullable): The function to call when @user_data is not needed anymore
|
||||
*
|
||||
* Sets the implementation function for #hb_font_get_glyph_h_origins_func_t.
|
||||
*
|
||||
* Since: 11.3.0
|
||||
**/
|
||||
HB_EXTERN void
|
||||
hb_font_funcs_set_glyph_h_origins_func (hb_font_funcs_t *ffuncs,
|
||||
hb_font_get_glyph_h_origins_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
/**
|
||||
* hb_font_funcs_set_glyph_v_origins_func:
|
||||
* @ffuncs: A font-function structure
|
||||
* @func: (closure user_data) (destroy destroy) (scope notified): The callback function to assign
|
||||
* @user_data: Data to pass to @func
|
||||
* @destroy: (nullable): The function to call when @user_data is not needed anymore
|
||||
*
|
||||
* Sets the implementation function for #hb_font_get_glyph_v_origins_func_t.
|
||||
*
|
||||
* Since: 11.3.0
|
||||
**/
|
||||
HB_EXTERN void
|
||||
hb_font_funcs_set_glyph_v_origins_func (hb_font_funcs_t *ffuncs,
|
||||
hb_font_get_glyph_v_origins_func_t func,
|
||||
void *user_data, hb_destroy_func_t destroy);
|
||||
|
||||
/**
|
||||
* hb_font_funcs_set_glyph_h_kerning_func:
|
||||
* @ffuncs: A font-function structure
|
||||
|
|
@ -796,7 +887,7 @@ hb_font_funcs_set_glyph_from_name_func (hb_font_funcs_t *ffuncs,
|
|||
*
|
||||
* Sets the implementation function for #hb_font_draw_glyph_or_fail_func_t.
|
||||
*
|
||||
* XSince: REPLACEME
|
||||
* Since: 11.2.0
|
||||
**/
|
||||
HB_EXTERN void
|
||||
hb_font_funcs_set_draw_glyph_or_fail_func (hb_font_funcs_t *ffuncs,
|
||||
|
|
@ -812,7 +903,7 @@ hb_font_funcs_set_draw_glyph_or_fail_func (hb_font_funcs_t *ffuncs,
|
|||
*
|
||||
* Sets the implementation function for #hb_font_paint_glyph_or_fail_func_t.
|
||||
*
|
||||
* XSince: REPLACEME
|
||||
* Since: 11.2.0
|
||||
*/
|
||||
HB_EXTERN void
|
||||
hb_font_funcs_set_paint_glyph_or_fail_func (hb_font_funcs_t *ffuncs,
|
||||
|
|
@ -876,6 +967,26 @@ hb_font_get_glyph_v_origin (hb_font_t *font,
|
|||
hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y);
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_font_get_glyph_h_origins (hb_font_t *font,
|
||||
unsigned int count,
|
||||
const hb_codepoint_t *first_glyph,
|
||||
unsigned glyph_stride,
|
||||
hb_position_t *first_x,
|
||||
unsigned x_stride,
|
||||
hb_position_t *first_y,
|
||||
unsigned y_stride);
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_font_get_glyph_v_origins (hb_font_t *font,
|
||||
unsigned int count,
|
||||
const hb_codepoint_t *first_glyph,
|
||||
unsigned glyph_stride,
|
||||
hb_position_t *first_x,
|
||||
unsigned x_stride,
|
||||
hb_position_t *first_y,
|
||||
unsigned y_stride);
|
||||
|
||||
HB_EXTERN hb_position_t
|
||||
hb_font_get_glyph_h_kerning (hb_font_t *font,
|
||||
hb_codepoint_t left_glyph, hb_codepoint_t right_glyph);
|
||||
|
|
|
|||
357
thirdparty/harfbuzz/src/hb-font.hh
vendored
357
thirdparty/harfbuzz/src/hb-font.hh
vendored
|
|
@ -55,6 +55,8 @@
|
|||
HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_advances) \
|
||||
HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_origin) \
|
||||
HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_origin) \
|
||||
HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_origins) \
|
||||
HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_origins) \
|
||||
HB_FONT_FUNC_IMPLEMENT (get_,glyph_h_kerning) \
|
||||
HB_IF_NOT_DEPRECATED (HB_FONT_FUNC_IMPLEMENT (get_,glyph_v_kerning)) \
|
||||
HB_FONT_FUNC_IMPLEMENT (get_,glyph_extents) \
|
||||
|
|
@ -118,6 +120,8 @@ struct hb_font_t
|
|||
int32_t x_scale;
|
||||
int32_t y_scale;
|
||||
|
||||
bool is_synthetic;
|
||||
|
||||
float x_embolden;
|
||||
float y_embolden;
|
||||
bool embolden_in_place;
|
||||
|
|
@ -139,6 +143,7 @@ struct hb_font_t
|
|||
|
||||
/* Font variation coordinates. */
|
||||
unsigned int instance_index;
|
||||
bool has_nonzero_coords;
|
||||
unsigned int num_coords;
|
||||
int *coords;
|
||||
float *design_coords;
|
||||
|
|
@ -430,21 +435,135 @@ struct hb_font_t
|
|||
}
|
||||
|
||||
hb_bool_t get_glyph_h_origin (hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
hb_position_t *x, hb_position_t *y,
|
||||
bool synthetic = true)
|
||||
{
|
||||
*x = *y = 0;
|
||||
return klass->get.f.glyph_h_origin (this, user_data,
|
||||
glyph, x, y,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_h_origin);
|
||||
bool ret = klass->get.f.glyph_h_origin (this, user_data,
|
||||
glyph, x, y,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_h_origin);
|
||||
|
||||
if (synthetic && ret)
|
||||
{
|
||||
/* Slant */
|
||||
if (slant_xy)
|
||||
*x += roundf (*y * slant_xy);
|
||||
|
||||
/* Embolden */
|
||||
if (!embolden_in_place)
|
||||
{
|
||||
*x += x_scale < 0 ? -x_strength : x_strength;
|
||||
*y += y_scale < 0 ? -y_strength : y_strength;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
hb_bool_t get_glyph_v_origin (hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
hb_position_t *x, hb_position_t *y,
|
||||
bool synthetic = true)
|
||||
{
|
||||
*x = *y = 0;
|
||||
return klass->get.f.glyph_v_origin (this, user_data,
|
||||
glyph, x, y,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_v_origin);
|
||||
bool ret = klass->get.f.glyph_v_origin (this, user_data,
|
||||
glyph, x, y,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_v_origin);
|
||||
|
||||
if (synthetic && ret)
|
||||
{
|
||||
/* Slant */
|
||||
if (slant_xy)
|
||||
*x += roundf (*y * slant_xy);
|
||||
|
||||
/* Embolden */
|
||||
if (!embolden_in_place)
|
||||
{
|
||||
*x += x_scale < 0 ? -x_strength : x_strength;
|
||||
*y += y_scale < 0 ? -y_strength : y_strength;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
hb_bool_t get_glyph_h_origins (unsigned int count,
|
||||
const hb_codepoint_t *first_glyph,
|
||||
unsigned int glyph_stride,
|
||||
hb_position_t *first_x,
|
||||
unsigned int x_stride,
|
||||
hb_position_t *first_y,
|
||||
unsigned int y_stride,
|
||||
bool synthetic = true)
|
||||
|
||||
{
|
||||
bool ret = klass->get.f.glyph_h_origins (this, user_data,
|
||||
count,
|
||||
first_glyph, glyph_stride,
|
||||
first_x, x_stride, first_y, y_stride,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_h_origins);
|
||||
|
||||
if (synthetic && ret)
|
||||
{
|
||||
hb_position_t x_shift = x_scale < 0 ? -x_strength : x_strength;
|
||||
hb_position_t y_shift = y_scale < 0 ? -y_strength : y_strength;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
/* Slant */
|
||||
if (slant_xy)
|
||||
*first_x += roundf (*first_y * slant_xy);
|
||||
|
||||
/* Embolden */
|
||||
if (!embolden_in_place)
|
||||
{
|
||||
*first_x += x_shift;
|
||||
*first_y += y_shift;
|
||||
}
|
||||
}
|
||||
first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
|
||||
first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
hb_bool_t get_glyph_v_origins (unsigned int count,
|
||||
const hb_codepoint_t *first_glyph,
|
||||
unsigned int glyph_stride,
|
||||
hb_position_t *first_x,
|
||||
unsigned int x_stride,
|
||||
hb_position_t *first_y,
|
||||
unsigned int y_stride,
|
||||
bool synthetic = true)
|
||||
|
||||
{
|
||||
bool ret = klass->get.f.glyph_v_origins (this, user_data,
|
||||
count,
|
||||
first_glyph, glyph_stride,
|
||||
first_x, x_stride, first_y, y_stride,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_v_origins);
|
||||
|
||||
if (synthetic && is_synthetic && ret)
|
||||
{
|
||||
hb_position_t x_shift = x_scale < 0 ? -x_strength : x_strength;
|
||||
hb_position_t y_shift = y_scale < 0 ? -y_strength : y_strength;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
/* Slant */
|
||||
if (slant_xy)
|
||||
*first_x += roundf (*first_y * slant_xy);
|
||||
|
||||
/* Embolden */
|
||||
if (!embolden_in_place)
|
||||
{
|
||||
*first_x += x_shift;
|
||||
*first_y += y_shift;
|
||||
}
|
||||
}
|
||||
first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
|
||||
first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
hb_position_t get_glyph_h_kerning (hb_codepoint_t left_glyph,
|
||||
|
|
@ -486,7 +605,7 @@ struct hb_font_t
|
|||
extents,
|
||||
!klass->user_data ? nullptr : klass->user_data->glyph_extents);
|
||||
}
|
||||
if (!is_synthetic () &&
|
||||
if (!is_synthetic &&
|
||||
klass->get.f.glyph_extents (this, user_data,
|
||||
glyph,
|
||||
extents,
|
||||
|
|
@ -508,7 +627,7 @@ struct hb_font_t
|
|||
#endif
|
||||
|
||||
#ifndef HB_NO_DRAW
|
||||
hb_extents_t draw_extents;
|
||||
hb_extents_t<> draw_extents;
|
||||
if (draw_glyph_or_fail (glyph,
|
||||
hb_draw_extents_get_funcs (), &draw_extents))
|
||||
{
|
||||
|
|
@ -714,6 +833,28 @@ struct hb_font_t
|
|||
get_glyph_v_advances (count, first_glyph, glyph_stride, first_advance, advance_stride);
|
||||
}
|
||||
|
||||
void apply_offset (hb_position_t *x, hb_position_t *y,
|
||||
hb_position_t dx, hb_position_t dy,
|
||||
signed mult)
|
||||
{
|
||||
assert (mult == -1 || mult == +1);
|
||||
|
||||
*x += dx * mult;
|
||||
*y += dy * mult;
|
||||
}
|
||||
void add_offset (hb_position_t *x, hb_position_t *y,
|
||||
hb_position_t dx, hb_position_t dy)
|
||||
{
|
||||
*x += dx;
|
||||
*y += dy;
|
||||
}
|
||||
void subtract_offset (hb_position_t *x, hb_position_t *y,
|
||||
hb_position_t dx, hb_position_t dy)
|
||||
{
|
||||
*x -= dx;
|
||||
*y -= dy;
|
||||
}
|
||||
|
||||
void guess_v_origin_minus_h_origin (hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
{
|
||||
|
|
@ -724,6 +865,141 @@ struct hb_font_t
|
|||
*y = extents.ascender;
|
||||
}
|
||||
|
||||
void apply_glyph_h_origins_with_fallback (hb_buffer_t *buf, int mult)
|
||||
{
|
||||
bool has_ascender = false;
|
||||
hb_position_t ascender = 0;
|
||||
|
||||
struct { hb_position_t x, y; } origins[32];
|
||||
|
||||
unsigned int offset = 0;
|
||||
unsigned int count = buf->len;
|
||||
while (offset < count)
|
||||
{
|
||||
unsigned n = hb_min (count - offset, ARRAY_LENGTH (origins));
|
||||
if (!get_glyph_h_origins (n,
|
||||
&buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
|
||||
&origins[0].x, sizeof (origins[0]),
|
||||
&origins[0].y, sizeof (origins[0])))
|
||||
{
|
||||
if (get_glyph_v_origins (n,
|
||||
&buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
|
||||
&origins[0].x, sizeof (origins[0]),
|
||||
&origins[0].y, sizeof (origins[0])))
|
||||
{
|
||||
if (!has_ascender)
|
||||
{
|
||||
hb_font_extents_t extents;
|
||||
get_h_extents_with_fallback (&extents);
|
||||
ascender = extents.ascender;
|
||||
has_ascender = true;
|
||||
}
|
||||
|
||||
/* We got the v_origins, adjust them to h_origins. */
|
||||
for (unsigned j = 0; j < n; j++)
|
||||
{
|
||||
hb_codepoint_t glyph = buf->info[offset + j].codepoint;
|
||||
origins[j].x -= get_glyph_h_advance (glyph) / 2;
|
||||
origins[j].y -= ascender;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned j = 0; j < n; j++)
|
||||
{
|
||||
origins[j].x = 0;
|
||||
origins[j].y = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert (mult == -1 || mult == +1);
|
||||
if (mult == +1)
|
||||
for (unsigned j = 0; j < n; j++)
|
||||
{
|
||||
hb_glyph_position_t *pos = &buf->pos[offset + j];
|
||||
add_offset (&pos->x_offset, &pos->y_offset,
|
||||
origins[j].x, origins[j].y);
|
||||
}
|
||||
else /* mult == -1 */
|
||||
for (unsigned j = 0; j < n; j++)
|
||||
{
|
||||
hb_glyph_position_t *pos = &buf->pos[offset + j];
|
||||
subtract_offset (&pos->x_offset, &pos->y_offset,
|
||||
origins[j].x, origins[j].y);
|
||||
}
|
||||
|
||||
offset += n;
|
||||
}
|
||||
}
|
||||
void apply_glyph_v_origins_with_fallback (hb_buffer_t *buf, int mult)
|
||||
{
|
||||
bool has_ascender = false;
|
||||
hb_position_t ascender = 0;
|
||||
|
||||
struct { hb_position_t x, y; } origins[32];
|
||||
|
||||
unsigned int offset = 0;
|
||||
unsigned int count = buf->len;
|
||||
while (offset < count)
|
||||
{
|
||||
unsigned n = hb_min (count - offset, ARRAY_LENGTH (origins));
|
||||
if (!get_glyph_v_origins (n,
|
||||
&buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
|
||||
&origins[0].x, sizeof (origins[0]),
|
||||
&origins[0].y, sizeof (origins[0])))
|
||||
{
|
||||
if (get_glyph_h_origins (n,
|
||||
&buf->info[offset].codepoint, sizeof (hb_glyph_info_t),
|
||||
&origins[0].x, sizeof (origins[0]),
|
||||
&origins[0].y, sizeof (origins[0])))
|
||||
{
|
||||
if (!has_ascender)
|
||||
{
|
||||
hb_font_extents_t extents;
|
||||
get_h_extents_with_fallback (&extents);
|
||||
ascender = extents.ascender;
|
||||
has_ascender = true;
|
||||
}
|
||||
|
||||
/* We got the h_origins, adjust them to v_origins. */
|
||||
for (unsigned j = 0; j < n; j++)
|
||||
{
|
||||
hb_codepoint_t glyph = buf->info[offset + j].codepoint;
|
||||
origins[j].x += get_glyph_h_advance (glyph) / 2;
|
||||
origins[j].y += ascender;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned j = 0; j < n; j++)
|
||||
{
|
||||
origins[j].x = 0;
|
||||
origins[j].y = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert (mult == -1 || mult == +1);
|
||||
if (mult == +1)
|
||||
for (unsigned j = 0; j < n; j++)
|
||||
{
|
||||
hb_glyph_position_t *pos = &buf->pos[offset + j];
|
||||
add_offset (&pos->x_offset, &pos->y_offset,
|
||||
origins[j].x, origins[j].y);
|
||||
}
|
||||
else /* mult == -1 */
|
||||
for (unsigned j = 0; j < n; j++)
|
||||
{
|
||||
hb_glyph_position_t *pos = &buf->pos[offset + j];
|
||||
subtract_offset (&pos->x_offset, &pos->y_offset,
|
||||
origins[j].x, origins[j].y);
|
||||
}
|
||||
|
||||
offset += n;
|
||||
}
|
||||
}
|
||||
|
||||
void get_glyph_h_origin_with_fallback (hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
{
|
||||
|
|
@ -732,7 +1008,7 @@ struct hb_font_t
|
|||
{
|
||||
hb_position_t dx, dy;
|
||||
guess_v_origin_minus_h_origin (glyph, &dx, &dy);
|
||||
*x -= dx; *y -= dy;
|
||||
subtract_offset (x, y, dx, dy);
|
||||
}
|
||||
}
|
||||
void get_glyph_v_origin_with_fallback (hb_codepoint_t glyph,
|
||||
|
|
@ -743,7 +1019,7 @@ struct hb_font_t
|
|||
{
|
||||
hb_position_t dx, dy;
|
||||
guess_v_origin_minus_h_origin (glyph, &dx, &dy);
|
||||
*x += dx; *y += dy;
|
||||
add_offset (x, y, dx, dy);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -757,68 +1033,38 @@ struct hb_font_t
|
|||
get_glyph_v_origin_with_fallback (glyph, x, y);
|
||||
}
|
||||
|
||||
void add_glyph_h_origin (hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
void add_glyph_h_origins (hb_buffer_t *buf)
|
||||
{
|
||||
hb_position_t origin_x, origin_y;
|
||||
|
||||
get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
|
||||
|
||||
*x += origin_x;
|
||||
*y += origin_y;
|
||||
apply_glyph_h_origins_with_fallback (buf, +1);
|
||||
}
|
||||
void add_glyph_v_origin (hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
void add_glyph_v_origins (hb_buffer_t *buf)
|
||||
{
|
||||
hb_position_t origin_x, origin_y;
|
||||
|
||||
get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
|
||||
|
||||
*x += origin_x;
|
||||
*y += origin_y;
|
||||
apply_glyph_v_origins_with_fallback (buf, +1);
|
||||
}
|
||||
void add_glyph_origin_for_direction (hb_codepoint_t glyph,
|
||||
hb_direction_t direction,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
{
|
||||
hb_position_t origin_x, origin_y;
|
||||
|
||||
get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
|
||||
|
||||
*x += origin_x;
|
||||
*y += origin_y;
|
||||
add_offset (x, y, origin_x, origin_y);
|
||||
}
|
||||
|
||||
void subtract_glyph_h_origin (hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
void subtract_glyph_h_origins (hb_buffer_t *buf)
|
||||
{
|
||||
hb_position_t origin_x, origin_y;
|
||||
|
||||
get_glyph_h_origin_with_fallback (glyph, &origin_x, &origin_y);
|
||||
|
||||
*x -= origin_x;
|
||||
*y -= origin_y;
|
||||
apply_glyph_h_origins_with_fallback (buf, -1);
|
||||
}
|
||||
void subtract_glyph_v_origin (hb_codepoint_t glyph,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
void subtract_glyph_v_origins (hb_buffer_t *buf)
|
||||
{
|
||||
hb_position_t origin_x, origin_y;
|
||||
|
||||
get_glyph_v_origin_with_fallback (glyph, &origin_x, &origin_y);
|
||||
|
||||
*x -= origin_x;
|
||||
*y -= origin_y;
|
||||
apply_glyph_v_origins_with_fallback (buf, -1);
|
||||
}
|
||||
void subtract_glyph_origin_for_direction (hb_codepoint_t glyph,
|
||||
hb_direction_t direction,
|
||||
hb_position_t *x, hb_position_t *y)
|
||||
{
|
||||
hb_position_t origin_x, origin_y;
|
||||
|
||||
get_glyph_origin_for_direction (glyph, direction, &origin_x, &origin_y);
|
||||
|
||||
*x -= origin_x;
|
||||
*y -= origin_y;
|
||||
subtract_offset (x, y, origin_x, origin_y);
|
||||
}
|
||||
|
||||
void get_glyph_kerning_for_direction (hb_codepoint_t first_glyph, hb_codepoint_t second_glyph,
|
||||
|
|
@ -900,11 +1146,6 @@ struct hb_font_t
|
|||
return false;
|
||||
}
|
||||
|
||||
bool is_synthetic () const
|
||||
{
|
||||
return x_embolden || y_embolden || slant;
|
||||
}
|
||||
|
||||
void changed ()
|
||||
{
|
||||
float upem = face->get_upem ();
|
||||
|
|
@ -916,6 +1157,8 @@ struct hb_font_t
|
|||
bool y_neg = y_scale < 0;
|
||||
y_mult = (y_neg ? -((int64_t) -y_scale << 16) : ((int64_t) y_scale << 16)) / upem;
|
||||
|
||||
is_synthetic = x_embolden || y_embolden || slant;
|
||||
|
||||
x_strength = roundf (abs (x_scale) * x_embolden);
|
||||
y_strength = roundf (abs (y_scale) * y_embolden);
|
||||
|
||||
|
|
|
|||
30
thirdparty/harfbuzz/src/hb-ft-colr.hh
vendored
30
thirdparty/harfbuzz/src/hb-ft-colr.hh
vendored
|
|
@ -90,7 +90,7 @@ struct hb_ft_paint_context_t
|
|||
funcs (paint_funcs), data (paint_data),
|
||||
palette (palette), palette_index (palette_index), foreground (foreground)
|
||||
{
|
||||
if (font->is_synthetic ())
|
||||
if (font->is_synthetic)
|
||||
{
|
||||
font = hb_font_create_sub_font (font);
|
||||
hb_font_set_synthetic_bold (font, 0, 0, true);
|
||||
|
|
@ -412,9 +412,9 @@ _hb_ft_paint (hb_ft_paint_context_t *c,
|
|||
float dx = paint.u.translate.dx / 65536.f;
|
||||
float dy = paint.u.translate.dy / 65536.f;
|
||||
|
||||
bool p1 = c->funcs->push_translate (c->data, dx, dy);
|
||||
c->funcs->push_translate (c->data, dx, dy);
|
||||
c->recurse (paint.u.translate.paint);
|
||||
if (p1) c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_SCALE:
|
||||
|
|
@ -424,13 +424,9 @@ _hb_ft_paint (hb_ft_paint_context_t *c,
|
|||
float sx = paint.u.scale.scale_x / 65536.f;
|
||||
float sy = paint.u.scale.scale_y / 65536.f;
|
||||
|
||||
bool p1 = c->funcs->push_translate (c->data, +dx, +dy);
|
||||
bool p2 = c->funcs->push_scale (c->data, sx, sy);
|
||||
bool p3 = c->funcs->push_translate (c->data, -dx, -dy);
|
||||
c->funcs->push_scale_around_center (c->data, sx, sy, dx, dy);
|
||||
c->recurse (paint.u.scale.paint);
|
||||
if (p3) c->funcs->pop_transform (c->data);
|
||||
if (p2) c->funcs->pop_transform (c->data);
|
||||
if (p1) c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_ROTATE:
|
||||
|
|
@ -439,13 +435,9 @@ _hb_ft_paint (hb_ft_paint_context_t *c,
|
|||
float dy = paint.u.rotate.center_y / 65536.f;
|
||||
float a = paint.u.rotate.angle / 65536.f;
|
||||
|
||||
bool p1 = c->funcs->push_translate (c->data, +dx, +dy);
|
||||
bool p2 = c->funcs->push_rotate (c->data, a);
|
||||
bool p3 = c->funcs->push_translate (c->data, -dx, -dy);
|
||||
c->funcs->push_rotate_around_center (c->data, a, dx, dy);
|
||||
c->recurse (paint.u.rotate.paint);
|
||||
if (p3) c->funcs->pop_transform (c->data);
|
||||
if (p2) c->funcs->pop_transform (c->data);
|
||||
if (p1) c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_SKEW:
|
||||
|
|
@ -455,13 +447,9 @@ _hb_ft_paint (hb_ft_paint_context_t *c,
|
|||
float sx = paint.u.skew.x_skew_angle / 65536.f;
|
||||
float sy = paint.u.skew.y_skew_angle / 65536.f;
|
||||
|
||||
bool p1 = c->funcs->push_translate (c->data, +dx, +dy);
|
||||
bool p2 = c->funcs->push_skew (c->data, sx, sy);
|
||||
bool p3 = c->funcs->push_translate (c->data, -dx, -dy);
|
||||
c->funcs->push_skew_around_center (c->data, sx, sy, dx, dy);
|
||||
c->recurse (paint.u.skew.paint);
|
||||
if (p3) c->funcs->pop_transform (c->data);
|
||||
if (p2) c->funcs->pop_transform (c->data);
|
||||
if (p1) c->funcs->pop_transform (c->data);
|
||||
c->funcs->pop_transform (c->data);
|
||||
}
|
||||
break;
|
||||
case FT_COLR_PAINTFORMAT_COMPOSITE:
|
||||
|
|
|
|||
30
thirdparty/harfbuzz/src/hb-ft.cc
vendored
30
thirdparty/harfbuzz/src/hb-ft.cc
vendored
|
|
@ -143,6 +143,9 @@ _hb_ft_font_destroy (void *data)
|
|||
/* hb_font changed, update FT_Face. */
|
||||
static void _hb_ft_hb_font_changed (hb_font_t *font, FT_Face ft_face)
|
||||
{
|
||||
if (unlikely (font->destroy != (hb_destroy_func_t) _hb_ft_font_destroy))
|
||||
return;
|
||||
|
||||
hb_ft_font_t *ft_font = (hb_ft_font_t *) font->user_data;
|
||||
|
||||
float x_mult = 1.f, y_mult = 1.f;
|
||||
|
|
@ -184,12 +187,14 @@ static void _hb_ft_hb_font_changed (hb_font_t *font, FT_Face ft_face)
|
|||
FT_Set_Transform (ft_face, &matrix, nullptr);
|
||||
ft_font->transform = true;
|
||||
}
|
||||
else
|
||||
FT_Set_Transform (ft_face, nullptr, nullptr);
|
||||
|
||||
#if defined(HAVE_FT_GET_VAR_BLEND_COORDINATES) && !defined(HB_NO_VAR)
|
||||
unsigned int num_coords;
|
||||
const float *coords = hb_font_get_var_coords_design (font, &num_coords);
|
||||
if (num_coords)
|
||||
if (font->has_nonzero_coords)
|
||||
{
|
||||
unsigned int num_coords;
|
||||
const float *coords = hb_font_get_var_coords_design (font, &num_coords);
|
||||
FT_Fixed *ft_coords = (FT_Fixed *) hb_calloc (num_coords, sizeof (FT_Fixed));
|
||||
if (ft_coords)
|
||||
{
|
||||
|
|
@ -199,6 +204,12 @@ static void _hb_ft_hb_font_changed (hb_font_t *font, FT_Face ft_face)
|
|||
hb_free (ft_coords);
|
||||
}
|
||||
}
|
||||
else if (font->num_coords)
|
||||
{
|
||||
// Some old versions of FreeType crash if we
|
||||
// call this function on non-variable fonts.
|
||||
FT_Set_Var_Design_Coordinates (ft_face, 0, nullptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -1093,6 +1104,10 @@ _hb_ft_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void *user_data
|
|||
FT_ULong length = 0;
|
||||
FT_Error error;
|
||||
|
||||
/* In new FreeType, a tag value of 1 loads the SFNT table directory. Reject it. */
|
||||
if (tag == 1)
|
||||
return nullptr;
|
||||
|
||||
/* Note: FreeType like HarfBuzz uses the NONE tag for fetching the entire blob */
|
||||
|
||||
error = FT_Load_Sfnt_Table (ft_face, tag, 0, nullptr, &length);
|
||||
|
|
@ -1366,7 +1381,7 @@ hb_ft_font_changed (hb_font_t *font)
|
|||
|
||||
for (unsigned int i = 0; i < mm_var->num_axis; ++i)
|
||||
{
|
||||
coords[i] = ft_coords[i] >>= 2;
|
||||
coords[i] = (ft_coords[i] + 2) >> 2;
|
||||
nonzero = nonzero || coords[i];
|
||||
}
|
||||
|
||||
|
|
@ -1717,7 +1732,12 @@ hb_ft_font_set_funcs (hb_font_t *font)
|
|||
ft_face->generic.finalizer = _release_blob;
|
||||
|
||||
// And the FT_Library to the blob
|
||||
hb_blob_set_user_data (blob, &ft_library_key, ft_library, destroy_ft_library, true);
|
||||
if (unlikely (!hb_blob_set_user_data (blob, &ft_library_key, ft_library, destroy_ft_library, true)))
|
||||
{
|
||||
DEBUG_MSG (FT, font, "hb_blob_set_user_data() failed");
|
||||
FT_Done_Face (ft_face);
|
||||
return;
|
||||
}
|
||||
|
||||
_hb_ft_font_set_funcs (font, ft_face, true);
|
||||
hb_ft_font_set_load_flags (font, FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING);
|
||||
|
|
|
|||
249
thirdparty/harfbuzz/src/hb-geometry.hh
vendored
249
thirdparty/harfbuzz/src/hb-geometry.hh
vendored
|
|
@ -26,7 +26,10 @@
|
|||
|
||||
#include "hb.hh"
|
||||
|
||||
#include "hb-algs.hh"
|
||||
|
||||
|
||||
template <typename Float = float>
|
||||
struct hb_extents_t
|
||||
{
|
||||
hb_extents_t () {}
|
||||
|
|
@ -35,7 +38,7 @@ struct hb_extents_t
|
|||
ymin (hb_min (extents.y_bearing, extents.y_bearing + extents.height)),
|
||||
xmax (hb_max (extents.x_bearing, extents.x_bearing + extents.width)),
|
||||
ymax (hb_max (extents.y_bearing, extents.y_bearing + extents.height)) {}
|
||||
hb_extents_t (float xmin, float ymin, float xmax, float ymax) :
|
||||
hb_extents_t (Float xmin, Float ymin, Float xmax, Float ymax) :
|
||||
xmin (xmin), ymin (ymin), xmax (xmax), ymax (ymax) {}
|
||||
|
||||
bool is_empty () const { return xmin >= xmax || ymin >= ymax; }
|
||||
|
|
@ -69,7 +72,7 @@ struct hb_extents_t
|
|||
}
|
||||
|
||||
void
|
||||
add_point (float x, float y)
|
||||
add_point (Float x, Float y)
|
||||
{
|
||||
if (unlikely (is_void ()))
|
||||
{
|
||||
|
|
@ -97,62 +100,69 @@ struct hb_extents_t
|
|||
yneg ? y1 - y0 : y0 - y1};
|
||||
}
|
||||
|
||||
float xmin = 0.f;
|
||||
float ymin = 0.f;
|
||||
float xmax = -1.f;
|
||||
float ymax = -1.f;
|
||||
Float xmin = 0;
|
||||
Float ymin = 0;
|
||||
Float xmax = -1;
|
||||
Float ymax = -1;
|
||||
};
|
||||
|
||||
template <typename Float = float>
|
||||
struct hb_transform_t
|
||||
{
|
||||
hb_transform_t () {}
|
||||
hb_transform_t (float xx, float yx,
|
||||
float xy, float yy,
|
||||
float x0, float y0) :
|
||||
hb_transform_t (Float xx, Float yx,
|
||||
Float xy, Float yy,
|
||||
Float x0, Float y0) :
|
||||
xx (xx), yx (yx), xy (xy), yy (yy), x0 (x0), y0 (y0) {}
|
||||
|
||||
bool is_identity () const
|
||||
{
|
||||
return xx == 1.f && yx == 0.f &&
|
||||
xy == 0.f && yy == 1.f &&
|
||||
x0 == 0.f && y0 == 0.f;
|
||||
return xx == 1 && yx == 0 &&
|
||||
xy == 0 && yy == 1 &&
|
||||
x0 == 0 && y0 == 0;
|
||||
}
|
||||
bool is_translation () const
|
||||
{
|
||||
return xx == 1 && yx == 0 &&
|
||||
xy == 0 && yy == 1;
|
||||
}
|
||||
|
||||
void multiply (const hb_transform_t &o)
|
||||
void multiply (const hb_transform_t &o, bool before=false)
|
||||
{
|
||||
/* Copied from cairo, with "o" being "a" there and "this" being "b" there. */
|
||||
hb_transform_t r;
|
||||
|
||||
r.xx = o.xx * xx + o.yx * xy;
|
||||
r.yx = o.xx * yx + o.yx * yy;
|
||||
|
||||
r.xy = o.xy * xx + o.yy * xy;
|
||||
r.yy = o.xy * yx + o.yy * yy;
|
||||
|
||||
r.x0 = o.x0 * xx + o.y0 * xy + x0;
|
||||
r.y0 = o.x0 * yx + o.y0 * yy + y0;
|
||||
|
||||
*this = r;
|
||||
// Copied from cairo-matrix.c
|
||||
const hb_transform_t &a = before ? o : *this;
|
||||
const hb_transform_t &b = before ? *this : o;
|
||||
*this = {
|
||||
a.xx * b.xx + a.xy * b.yx,
|
||||
a.yx * b.xx + a.yy * b.yx,
|
||||
a.xx * b.xy + a.xy * b.yy,
|
||||
a.yx * b.xy + a.yy * b.yy,
|
||||
a.xx * b.x0 + a.xy * b.y0 + a.x0,
|
||||
a.yx * b.x0 + a.yy * b.y0 + a.y0
|
||||
};
|
||||
}
|
||||
|
||||
void transform_distance (float &dx, float &dy) const
|
||||
HB_ALWAYS_INLINE
|
||||
void transform_distance (Float &dx, Float &dy) const
|
||||
{
|
||||
float new_x = xx * dx + xy * dy;
|
||||
float new_y = yx * dx + yy * dy;
|
||||
Float new_x = xx * dx + xy * dy;
|
||||
Float new_y = yx * dx + yy * dy;
|
||||
dx = new_x;
|
||||
dy = new_y;
|
||||
}
|
||||
|
||||
void transform_point (float &x, float &y) const
|
||||
HB_ALWAYS_INLINE
|
||||
void transform_point (Float &x, Float &y) const
|
||||
{
|
||||
transform_distance (x, y);
|
||||
x += x0;
|
||||
y += y0;
|
||||
Float new_x = x0 + xx * x + xy * y;
|
||||
Float new_y = y0 + yx * x + yy * y;
|
||||
x = new_x;
|
||||
y = new_y;
|
||||
}
|
||||
|
||||
void transform_extents (hb_extents_t &extents) const
|
||||
void transform_extents (hb_extents_t<Float> &extents) const
|
||||
{
|
||||
float quad_x[4], quad_y[4];
|
||||
Float quad_x[4], quad_y[4];
|
||||
|
||||
quad_x[0] = extents.xmin;
|
||||
quad_y[0] = extents.ymin;
|
||||
|
|
@ -163,7 +173,7 @@ struct hb_transform_t
|
|||
quad_x[3] = extents.xmax;
|
||||
quad_y[3] = extents.ymax;
|
||||
|
||||
extents = hb_extents_t {};
|
||||
extents = hb_extents_t<Float> {};
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
{
|
||||
transform_point (quad_x[i], quad_y[i]);
|
||||
|
|
@ -171,20 +181,36 @@ struct hb_transform_t
|
|||
}
|
||||
}
|
||||
|
||||
void transform (const hb_transform_t &o) { multiply (o); }
|
||||
void transform (const hb_transform_t &o, bool before=false) { multiply (o, before); }
|
||||
|
||||
void translate (float x, float y)
|
||||
static hb_transform_t translation (Float x, Float y)
|
||||
{
|
||||
if (x == 0.f && y == 0.f)
|
||||
return;
|
||||
return {1, 0, 0, 1, x, y};
|
||||
}
|
||||
void translate (Float x, Float y, bool before=false)
|
||||
{
|
||||
if (before)
|
||||
{
|
||||
x0 += x;
|
||||
y0 += y;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x == 0 && y == 0)
|
||||
return;
|
||||
|
||||
x0 += xx * x + xy * y;
|
||||
y0 += yx * x + yy * y;
|
||||
x0 += xx * x + xy * y;
|
||||
y0 += yx * x + yy * y;
|
||||
}
|
||||
}
|
||||
|
||||
void scale (float scaleX, float scaleY)
|
||||
static hb_transform_t scaling (Float scaleX, Float scaleY)
|
||||
{
|
||||
if (scaleX == 1.f && scaleY == 1.f)
|
||||
return {scaleX, 0, 0, scaleY, 0, 0};
|
||||
}
|
||||
void scale (Float scaleX, Float scaleY)
|
||||
{
|
||||
if (scaleX == 1 && scaleY == 1)
|
||||
return;
|
||||
|
||||
xx *= scaleX;
|
||||
|
|
@ -192,52 +218,94 @@ struct hb_transform_t
|
|||
xy *= scaleY;
|
||||
yy *= scaleY;
|
||||
}
|
||||
|
||||
void rotate (float rotation)
|
||||
static hb_transform_t scaling_around_center (Float scaleX, Float scaleY, Float center_x, Float center_y)
|
||||
{
|
||||
if (rotation == 0.f)
|
||||
return {scaleX, 0, 0, scaleY,
|
||||
center_x ? (1 - scaleX) * center_x : 0,
|
||||
center_y ? (1 - scaleY) * center_y : 0};
|
||||
}
|
||||
void scale_around_center (Float scaleX, Float scaleY, Float center_x, Float center_y)
|
||||
{
|
||||
if (scaleX == 1 && scaleY == 1)
|
||||
return;
|
||||
|
||||
transform (scaling_around_center (scaleX, scaleY, center_x, center_y));
|
||||
}
|
||||
|
||||
static hb_transform_t rotation (Float radians)
|
||||
{
|
||||
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L240
|
||||
rotation = rotation * HB_PI;
|
||||
float c;
|
||||
float s;
|
||||
#ifdef HAVE_SINCOSF
|
||||
sincosf (rotation, &s, &c);
|
||||
#else
|
||||
c = cosf (rotation);
|
||||
s = sinf (rotation);
|
||||
#endif
|
||||
auto other = hb_transform_t{c, s, -s, c, 0.f, 0.f};
|
||||
transform (other);
|
||||
Float c;
|
||||
Float s;
|
||||
hb_sincos (radians, s, c);
|
||||
return {c, s, -s, c, 0, 0};
|
||||
}
|
||||
|
||||
void skew (float skewX, float skewY)
|
||||
void rotate (Float radians, bool before=false)
|
||||
{
|
||||
if (skewX == 0.f && skewY == 0.f)
|
||||
if (radians == 0)
|
||||
return;
|
||||
|
||||
// https://github.com/fonttools/fonttools/blob/f66ee05f71c8b57b5f519ee975e95edcd1466e14/Lib/fontTools/misc/transform.py#L255
|
||||
skewX = skewX * HB_PI;
|
||||
skewY = skewY * HB_PI;
|
||||
auto other = hb_transform_t{1.f,
|
||||
skewY ? tanf (skewY) : 0.f,
|
||||
skewX ? tanf (skewX) : 0.f,
|
||||
1.f,
|
||||
0.f, 0.f};
|
||||
transform (other);
|
||||
transform (rotation (radians), before);
|
||||
}
|
||||
|
||||
float xx = 1.f;
|
||||
float yx = 0.f;
|
||||
float xy = 0.f;
|
||||
float yy = 1.f;
|
||||
float x0 = 0.f;
|
||||
float y0 = 0.f;
|
||||
static hb_transform_t rotation_around_center (Float radians, Float center_x, Float center_y)
|
||||
{
|
||||
Float s, c;
|
||||
hb_sincos (radians, s, c);
|
||||
return {
|
||||
c, s, -s, c,
|
||||
(1 - c) * center_x + s * center_y,
|
||||
-s * center_x + (1 - c) * center_y
|
||||
};
|
||||
}
|
||||
void rotate_around_center (Float radians, Float center_x, Float center_y, bool before=false)
|
||||
{
|
||||
if (radians == 0)
|
||||
return;
|
||||
|
||||
transform (rotation_around_center (radians, center_x, center_y), before);
|
||||
}
|
||||
|
||||
static hb_transform_t skewing (Float skewX, Float skewY)
|
||||
{
|
||||
return {1, skewY ? tanf (skewY) : 0, skewX ? tanf (skewX) : 0, 1, 0, 0};
|
||||
}
|
||||
void skew (Float skewX, Float skewY)
|
||||
{
|
||||
if (skewX == 0 && skewY == 0)
|
||||
return;
|
||||
|
||||
transform (skewing (skewX, skewY));
|
||||
}
|
||||
static hb_transform_t skewing_around_center (Float skewX, Float skewY, Float center_x, Float center_y)
|
||||
{
|
||||
skewX = skewX ? tanf (skewX) : 0;
|
||||
skewY = skewY ? tanf (skewY) : 0;
|
||||
return {
|
||||
1, skewY, skewX, 1,
|
||||
center_y ? -skewX * center_y : 0,
|
||||
center_x ? -skewY * center_x : 0
|
||||
};
|
||||
}
|
||||
void skew_around_center (Float skewX, Float skewY, Float center_x, Float center_y)
|
||||
{
|
||||
if (skewX == 0 && skewY == 0)
|
||||
return;
|
||||
|
||||
transform (skewing_around_center (skewX, skewY, center_x, center_y));
|
||||
}
|
||||
|
||||
Float xx = 1;
|
||||
Float yx = 0;
|
||||
Float xy = 0;
|
||||
Float yy = 1;
|
||||
Float x0 = 0;
|
||||
Float y0 = 0;
|
||||
};
|
||||
|
||||
#define HB_TRANSFORM_IDENTITY hb_transform_t{1.f, 0.f, 0.f, 1.f, 0.f, 0.f}
|
||||
#define HB_TRANSFORM_IDENTITY {1, 0, 0, 1, 0, 0}
|
||||
|
||||
template <typename Float = float>
|
||||
struct hb_bounds_t
|
||||
{
|
||||
enum status_t {
|
||||
|
|
@ -247,7 +315,7 @@ struct hb_bounds_t
|
|||
};
|
||||
|
||||
hb_bounds_t (status_t status = UNBOUNDED) : status (status) {}
|
||||
hb_bounds_t (const hb_extents_t &extents) :
|
||||
hb_bounds_t (const hb_extents_t<Float> &extents) :
|
||||
status (extents.is_empty () ? EMPTY : BOUNDED), extents (extents) {}
|
||||
|
||||
void union_ (const hb_bounds_t &o)
|
||||
|
|
@ -281,20 +349,21 @@ struct hb_bounds_t
|
|||
}
|
||||
|
||||
status_t status;
|
||||
hb_extents_t extents;
|
||||
hb_extents_t<Float> extents;
|
||||
};
|
||||
|
||||
template <typename Float = float>
|
||||
struct hb_transform_decomposed_t
|
||||
{
|
||||
float translateX = 0;
|
||||
float translateY = 0;
|
||||
float rotation = 0; // in degrees, counter-clockwise
|
||||
float scaleX = 1;
|
||||
float scaleY = 1;
|
||||
float skewX = 0; // in degrees, counter-clockwise
|
||||
float skewY = 0; // in degrees, counter-clockwise
|
||||
float tCenterX = 0;
|
||||
float tCenterY = 0;
|
||||
Float translateX = 0;
|
||||
Float translateY = 0;
|
||||
Float rotation = 0; // in radians, counter-clockwise
|
||||
Float scaleX = 1;
|
||||
Float scaleY = 1;
|
||||
Float skewX = 0; // in radians, counter-clockwise
|
||||
Float skewY = 0; // in radians, counter-clockwise
|
||||
Float tCenterX = 0;
|
||||
Float tCenterY = 0;
|
||||
|
||||
operator bool () const
|
||||
{
|
||||
|
|
@ -305,9 +374,9 @@ struct hb_transform_decomposed_t
|
|||
tCenterX || tCenterY;
|
||||
}
|
||||
|
||||
hb_transform_t to_transform () const
|
||||
hb_transform_t<Float> to_transform () const
|
||||
{
|
||||
hb_transform_t t;
|
||||
hb_transform_t<Float> t;
|
||||
t.translate (translateX + tCenterX, translateY + tCenterY);
|
||||
t.rotate (rotation);
|
||||
t.scale (scaleX, scaleY);
|
||||
|
|
|
|||
8
thirdparty/harfbuzz/src/hb-glib.cc
vendored
8
thirdparty/harfbuzz/src/hb-glib.cc
vendored
|
|
@ -127,11 +127,7 @@ hb_glib_unicode_compose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
|||
hb_codepoint_t *ab,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
#if GLIB_CHECK_VERSION(2,29,12)
|
||||
return g_unichar_compose (a, b, ab);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static hb_bool_t
|
||||
|
|
@ -141,11 +137,7 @@ hb_glib_unicode_decompose (hb_unicode_funcs_t *ufuncs HB_UNUSED,
|
|||
hb_codepoint_t *b,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
#if GLIB_CHECK_VERSION(2,29,12)
|
||||
return g_unichar_decompose (ab, a, b);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -51,12 +51,6 @@
|
|||
|
||||
/* g++ didn't like older gtype.h gcc-only code path. */
|
||||
#include <glib.h>
|
||||
#if !GLIB_CHECK_VERSION(2,29,16)
|
||||
#undef __GNUC__
|
||||
#undef __GNUC_MINOR__
|
||||
#define __GNUC__ 2
|
||||
#define __GNUC_MINOR__ 6
|
||||
#endif
|
||||
|
||||
#include "hb-gobject.h"
|
||||
|
||||
|
|
|
|||
17
thirdparty/harfbuzz/src/hb-machinery.hh
vendored
17
thirdparty/harfbuzz/src/hb-machinery.hh
vendored
|
|
@ -66,13 +66,15 @@ static inline Type& StructAtOffsetUnaligned(void *P, unsigned int offset)
|
|||
}
|
||||
|
||||
/* StructAfter<T>(X) returns the struct T& that is placed after X.
|
||||
* Works with X of variable size also. X must implement get_size() */
|
||||
template<typename Type, typename TObject>
|
||||
static inline const Type& StructAfter(const TObject &X)
|
||||
{ return StructAtOffset<Type>(&X, X.get_size()); }
|
||||
template<typename Type, typename TObject>
|
||||
static inline Type& StructAfter(TObject &X)
|
||||
{ return StructAtOffset<Type>(&X, X.get_size()); }
|
||||
* Works with X of variable size also. X must implement get_size().
|
||||
* Any extra arguments are forwarded to get_size, so for example
|
||||
* it can work with UnsizedArrayOf<> as well. */
|
||||
template <typename Type, typename TObject, typename ...Ts>
|
||||
static inline const Type& StructAfter(const TObject &X, Ts... args)
|
||||
{ return StructAtOffset<Type>(&X, X.get_size(args...)); }
|
||||
template <typename Type, typename TObject, typename ...Ts>
|
||||
static inline Type& StructAfter(TObject &X, Ts... args)
|
||||
{ return StructAtOffset<Type>(&X, X.get_size(args...)); }
|
||||
|
||||
|
||||
/*
|
||||
|
|
@ -132,7 +134,6 @@ static inline Type& StructAfter(TObject &X)
|
|||
DEFINE_SIZE_ARRAY(size, array)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Lazy loaders.
|
||||
*
|
||||
|
|
|
|||
102
thirdparty/harfbuzz/src/hb-open-type.hh
vendored
102
thirdparty/harfbuzz/src/hb-open-type.hh
vendored
|
|
@ -54,35 +54,40 @@ namespace OT {
|
|||
*/
|
||||
|
||||
/* Integer types in big-endian order and no alignment requirement */
|
||||
template <typename Type,
|
||||
template <bool BE,
|
||||
typename Type,
|
||||
unsigned int Size = sizeof (Type)>
|
||||
struct IntType
|
||||
struct NumType
|
||||
{
|
||||
typedef Type type;
|
||||
|
||||
IntType () = default;
|
||||
explicit constexpr IntType (Type V) : v {V} {}
|
||||
IntType& operator = (Type i) { v = i; return *this; }
|
||||
/* For reason we define cast out operator for signed/unsigned, instead of Type, see:
|
||||
* https://github.com/harfbuzz/harfbuzz/pull/2875/commits/09836013995cab2b9f07577a179ad7b024130467 */
|
||||
operator typename std::conditional<std::is_signed<Type>::value, signed, unsigned>::type () const { return v; }
|
||||
typedef typename std::conditional<std::is_integral<Type>::value,
|
||||
typename std::conditional<std::is_signed<Type>::value, signed, unsigned>::type,
|
||||
Type>::type WideType;
|
||||
|
||||
bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; }
|
||||
bool operator != (const IntType &o) const { return !(*this == o); }
|
||||
NumType () = default;
|
||||
explicit constexpr NumType (Type V) : v {V} {}
|
||||
NumType& operator = (Type V) { v = V; return *this; }
|
||||
|
||||
IntType& operator += (unsigned count) { *this = *this + count; return *this; }
|
||||
IntType& operator -= (unsigned count) { *this = *this - count; return *this; }
|
||||
IntType& operator ++ () { *this += 1; return *this; }
|
||||
IntType& operator -- () { *this -= 1; return *this; }
|
||||
IntType operator ++ (int) { IntType c (*this); ++*this; return c; }
|
||||
IntType operator -- (int) { IntType c (*this); --*this; return c; }
|
||||
operator WideType () const { return v; }
|
||||
|
||||
HB_INTERNAL static int cmp (const IntType *a, const IntType *b)
|
||||
bool operator == (const NumType &o) const { return (Type) v == (Type) o.v; }
|
||||
bool operator != (const NumType &o) const { return !(*this == o); }
|
||||
|
||||
NumType& operator += (WideType count) { *this = *this + count; return *this; }
|
||||
NumType& operator -= (WideType count) { *this = *this - count; return *this; }
|
||||
NumType& operator ++ () { *this += 1; return *this; }
|
||||
NumType& operator -- () { *this -= 1; return *this; }
|
||||
NumType operator ++ (int) { NumType c (*this); ++*this; return c; }
|
||||
NumType operator -- (int) { NumType c (*this); --*this; return c; }
|
||||
|
||||
HB_INTERNAL static int cmp (const NumType *a, const NumType *b)
|
||||
{ return b->cmp (*a); }
|
||||
HB_INTERNAL static int cmp (const void *a, const void *b)
|
||||
{
|
||||
IntType *pa = (IntType *) a;
|
||||
IntType *pb = (IntType *) b;
|
||||
NumType *pa = (NumType *) a;
|
||||
NumType *pb = (NumType *) b;
|
||||
|
||||
return pb->cmp (*pa);
|
||||
}
|
||||
|
|
@ -99,20 +104,32 @@ struct IntType
|
|||
return_trace (c->check_struct (this));
|
||||
}
|
||||
protected:
|
||||
BEInt<Type, Size> v;
|
||||
typename std::conditional<std::is_integral<Type>::value,
|
||||
HBInt<BE, Type, Size>,
|
||||
HBFloat<BE, Type, Size>>::type v;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (Size);
|
||||
};
|
||||
|
||||
typedef IntType<uint8_t> HBUINT8; /* 8-bit unsigned integer. */
|
||||
typedef IntType<int8_t> HBINT8; /* 8-bit signed integer. */
|
||||
typedef IntType<uint16_t> HBUINT16; /* 16-bit unsigned integer. */
|
||||
typedef IntType<int16_t> HBINT16; /* 16-bit signed integer. */
|
||||
typedef IntType<uint32_t> HBUINT32; /* 32-bit unsigned integer. */
|
||||
typedef IntType<int32_t> HBINT32; /* 32-bit signed integer. */
|
||||
typedef NumType<true, uint8_t> HBUINT8; /* 8-bit big-endian unsigned integer. */
|
||||
typedef NumType<true, int8_t> HBINT8; /* 8-bit big-endian signed integer. */
|
||||
typedef NumType<true, uint16_t> HBUINT16; /* 16-bit big-endian unsigned integer. */
|
||||
typedef NumType<true, int16_t> HBINT16; /* 16-bit big-endian signed integer. */
|
||||
typedef NumType<true, uint32_t> HBUINT32; /* 32-bit big-endian unsigned integer. */
|
||||
typedef NumType<true, int32_t> HBINT32; /* 32-bit big-endian signed integer. */
|
||||
/* Note: we cannot defined a signed HBINT24 because there's no corresponding C type.
|
||||
* Works for unsigned, but not signed, since we rely on compiler for sign-extension. */
|
||||
typedef IntType<uint32_t, 3> HBUINT24; /* 24-bit unsigned integer. */
|
||||
typedef NumType<true, uint32_t, 3> HBUINT24; /* 24-bit big-endian unsigned integer. */
|
||||
|
||||
typedef NumType<false, uint16_t> HBUINT16LE; /* 16-bit little-endian unsigned integer. */
|
||||
typedef NumType<false, int16_t> HBINT16LE; /* 16-bit little-endian signed integer. */
|
||||
typedef NumType<false, uint32_t> HBUINT32LE; /* 32-bit little-endian unsigned integer. */
|
||||
typedef NumType<false, int32_t> HBINT32LE; /* 32-bit little-endian signed integer. */
|
||||
|
||||
typedef NumType<true, float> HBFLOAT32BE; /* 32-bit little-endian floating point number. */
|
||||
typedef NumType<true, double> HBFLOAT64BE; /* 64-bit little-endian floating point number. */
|
||||
typedef NumType<false, float> HBFLOAT32LE; /* 32-bit little-endian floating point number. */
|
||||
typedef NumType<false, double> HBFLOAT64LE; /* 64-bit little-endian floating point number. */
|
||||
|
||||
/* 15-bit unsigned number; top bit used for extension. */
|
||||
struct HBUINT15 : HBUINT16
|
||||
|
|
@ -218,7 +235,7 @@ typedef HBUINT16 UFWORD;
|
|||
template <typename Type, unsigned fraction_bits>
|
||||
struct HBFixed : Type
|
||||
{
|
||||
static constexpr float shift = (float) (1 << fraction_bits);
|
||||
static constexpr float mult = 1.f / (1 << fraction_bits);
|
||||
static_assert (Type::static_size * 8 > fraction_bits, "");
|
||||
|
||||
operator signed () const = delete;
|
||||
|
|
@ -226,8 +243,8 @@ struct HBFixed : Type
|
|||
explicit operator float () const { return to_float (); }
|
||||
typename Type::type to_int () const { return Type::v; }
|
||||
void set_int (typename Type::type i ) { Type::v = i; }
|
||||
float to_float (float offset = 0) const { return ((int32_t) Type::v + offset) / shift; }
|
||||
void set_float (float f) { Type::v = roundf (f * shift); }
|
||||
float to_float (float offset = 0) const { return ((int32_t) Type::v + offset) * mult; }
|
||||
void set_float (float f) { Type::v = roundf (f / mult); }
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (Type::static_size);
|
||||
};
|
||||
|
|
@ -1707,7 +1724,8 @@ struct TupleValues
|
|||
static bool decompile (const HBUINT8 *&p /* IN/OUT */,
|
||||
hb_vector_t<T> &values /* IN/OUT */,
|
||||
const HBUINT8 *end,
|
||||
bool consume_all = false)
|
||||
bool consume_all = false,
|
||||
unsigned start = 0)
|
||||
{
|
||||
unsigned i = 0;
|
||||
unsigned count = consume_all ? UINT_MAX : values.length;
|
||||
|
|
@ -1725,6 +1743,10 @@ struct TupleValues
|
|||
}
|
||||
unsigned stop = i + run_count;
|
||||
if (unlikely (stop > count)) return false;
|
||||
|
||||
unsigned skip = i < start ? hb_min (start - i, run_count) : 0;
|
||||
i += skip;
|
||||
|
||||
if ((control & VALUES_SIZE_MASK) == VALUES_ARE_ZEROS)
|
||||
{
|
||||
for (; i < stop; i++)
|
||||
|
|
@ -1733,6 +1755,7 @@ struct TupleValues
|
|||
else if ((control & VALUES_SIZE_MASK) == VALUES_ARE_WORDS)
|
||||
{
|
||||
if (unlikely (p + run_count * HBINT16::static_size > end)) return false;
|
||||
p += skip * HBINT16::static_size;
|
||||
#ifndef HB_OPTIMIZE_SIZE
|
||||
for (; i + 3 < stop; i += 4)
|
||||
{
|
||||
|
|
@ -1755,6 +1778,7 @@ struct TupleValues
|
|||
else if ((control & VALUES_SIZE_MASK) == VALUES_ARE_LONGS)
|
||||
{
|
||||
if (unlikely (p + run_count * HBINT32::static_size > end)) return false;
|
||||
p += skip * HBINT32::static_size;
|
||||
for (; i < stop; i++)
|
||||
{
|
||||
values.arrayZ[i] = * (const HBINT32 *) p;
|
||||
|
|
@ -1764,6 +1788,7 @@ struct TupleValues
|
|||
else if ((control & VALUES_SIZE_MASK) == VALUES_ARE_BYTES)
|
||||
{
|
||||
if (unlikely (p + run_count > end)) return false;
|
||||
p += skip * HBINT8::static_size;
|
||||
#ifndef HB_OPTIMIZE_SIZE
|
||||
for (; i + 3 < stop; i += 4)
|
||||
{
|
||||
|
|
@ -2038,6 +2063,23 @@ struct TupleList : CFF2Index
|
|||
};
|
||||
|
||||
|
||||
// Alignment
|
||||
|
||||
template <unsigned int alignment>
|
||||
struct Align
|
||||
{
|
||||
unsigned get_size (const void *base) const
|
||||
{
|
||||
unsigned offset = (const char *) this - (const char *) base;
|
||||
return (alignment - offset) & (alignment - 1);
|
||||
}
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_MIN (0);
|
||||
};
|
||||
|
||||
|
||||
|
||||
} /* namespace OT */
|
||||
|
||||
|
||||
|
|
|
|||
6
thirdparty/harfbuzz/src/hb-ot-cff2-table.cc
vendored
6
thirdparty/harfbuzz/src/hb-ot-cff2-table.cc
vendored
|
|
@ -202,7 +202,11 @@ struct cff2_cs_opset_path_t : cff2_cs_opset_t<cff2_cs_opset_path_t, cff2_path_pa
|
|||
|
||||
bool OT::cff2::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
|
||||
{
|
||||
return get_path_at (font, glyph, draw_session, hb_array (font->coords, font->num_coords));
|
||||
return get_path_at (font,
|
||||
glyph,
|
||||
draw_session,
|
||||
hb_array (font->coords,
|
||||
font->has_nonzero_coords ? font->num_coords : 0));
|
||||
}
|
||||
|
||||
bool OT::cff2::accelerator_t::get_path_at (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session, hb_array_t<const int> coords) const
|
||||
|
|
|
|||
6
thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
vendored
6
thirdparty/harfbuzz/src/hb-ot-cmap-table.hh
vendored
|
|
@ -501,10 +501,6 @@ struct CmapSubtableFormat4
|
|||
this->length = c->length () - table_initpos;
|
||||
if ((long long) this->length != (long long) c->length () - table_initpos)
|
||||
{
|
||||
// Length overflowed. Discard the current object before setting the error condition, otherwise
|
||||
// discard is a noop which prevents the higher level code from reverting the serializer to the
|
||||
// pre-error state in cmap4 overflow handling code.
|
||||
c->pop_discard ();
|
||||
c->err (HB_SERIALIZE_ERROR_INT_OVERFLOW);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1646,7 +1642,7 @@ struct EncodingRecord
|
|||
CmapSubtable *cmapsubtable = c->push<CmapSubtable> ();
|
||||
unsigned origin_length = c->length ();
|
||||
cmapsubtable->serialize (c, it, format, plan, &(base+subtable));
|
||||
if (c->length () - origin_length > 0) *objidx = c->pop_pack ();
|
||||
if (c->length () - origin_length > 0 && !c->in_error()) *objidx = c->pop_pack ();
|
||||
else c->pop_discard ();
|
||||
}
|
||||
|
||||
|
|
|
|||
564
thirdparty/harfbuzz/src/hb-ot-font.cc
vendored
564
thirdparty/harfbuzz/src/hb-ot-font.cc
vendored
|
|
@ -37,6 +37,7 @@
|
|||
|
||||
#include "hb-ot-cmap-table.hh"
|
||||
#include "hb-ot-glyf-table.hh"
|
||||
#include "hb-ot-var-gvar-table.hh"
|
||||
#include "hb-ot-cff2-table.hh"
|
||||
#include "hb-ot-cff1-table.hh"
|
||||
#include "hb-ot-hmtx-table.hh"
|
||||
|
|
@ -64,18 +65,22 @@
|
|||
using hb_ot_font_advance_cache_t = hb_cache_t<24, 16>;
|
||||
static_assert (sizeof (hb_ot_font_advance_cache_t) == 1024, "");
|
||||
|
||||
using hb_ot_font_origin_cache_t = hb_cache_t<20, 20>;
|
||||
static_assert (sizeof (hb_ot_font_origin_cache_t) == 1024, "");
|
||||
|
||||
struct hb_ot_font_t
|
||||
{
|
||||
const hb_ot_face_t *ot_face;
|
||||
|
||||
/* h_advance caching */
|
||||
mutable hb_atomic_t<int> cached_serial;
|
||||
mutable hb_atomic_t<int> cached_coords_serial;
|
||||
struct advance_cache_t
|
||||
|
||||
struct direction_cache_t
|
||||
{
|
||||
mutable hb_atomic_t<hb_ot_font_advance_cache_t *> advance_cache;
|
||||
mutable hb_atomic_t<OT::ItemVariationStore::cache_t *> varStore_cache;
|
||||
mutable hb_atomic_t<OT::hb_scalar_cache_t *> varStore_cache;
|
||||
|
||||
~advance_cache_t ()
|
||||
~direction_cache_t ()
|
||||
{
|
||||
clear ();
|
||||
}
|
||||
|
|
@ -116,7 +121,7 @@ struct hb_ot_font_t
|
|||
goto retry;
|
||||
}
|
||||
|
||||
OT::ItemVariationStore::cache_t *acquire_varStore_cache (const OT::ItemVariationStore &varStore) const
|
||||
OT::hb_scalar_cache_t *acquire_varStore_cache (const OT::ItemVariationStore &varStore) const
|
||||
{
|
||||
retry:
|
||||
auto *cache = varStore_cache.get_acquire ();
|
||||
|
|
@ -127,7 +132,7 @@ struct hb_ot_font_t
|
|||
else
|
||||
goto retry;
|
||||
}
|
||||
void release_varStore_cache (OT::ItemVariationStore::cache_t *cache) const
|
||||
void release_varStore_cache (OT::hb_scalar_cache_t *cache) const
|
||||
{
|
||||
if (!cache)
|
||||
return;
|
||||
|
|
@ -154,17 +159,157 @@ struct hb_ot_font_t
|
|||
|
||||
} h, v;
|
||||
|
||||
struct origin_cache_t
|
||||
{
|
||||
mutable hb_atomic_t<hb_ot_font_origin_cache_t *> origin_cache;
|
||||
mutable hb_atomic_t<OT::hb_scalar_cache_t *> varStore_cache;
|
||||
|
||||
~origin_cache_t ()
|
||||
{
|
||||
clear ();
|
||||
}
|
||||
|
||||
hb_ot_font_origin_cache_t *acquire_origin_cache () const
|
||||
{
|
||||
retry:
|
||||
auto *cache = origin_cache.get_acquire ();
|
||||
if (!cache)
|
||||
{
|
||||
cache = (hb_ot_font_origin_cache_t *) hb_malloc (sizeof (hb_ot_font_origin_cache_t));
|
||||
if (!cache)
|
||||
return nullptr;
|
||||
new (cache) hb_ot_font_origin_cache_t;
|
||||
return cache;
|
||||
}
|
||||
if (origin_cache.cmpexch (cache, nullptr))
|
||||
return cache;
|
||||
else
|
||||
goto retry;
|
||||
}
|
||||
void release_origin_cache (hb_ot_font_origin_cache_t *cache) const
|
||||
{
|
||||
if (!cache)
|
||||
return;
|
||||
if (!origin_cache.cmpexch (nullptr, cache))
|
||||
hb_free (cache);
|
||||
}
|
||||
void clear_origin_cache () const
|
||||
{
|
||||
retry:
|
||||
auto *cache = origin_cache.get_acquire ();
|
||||
if (!cache)
|
||||
return;
|
||||
if (origin_cache.cmpexch (cache, nullptr))
|
||||
hb_free (cache);
|
||||
else
|
||||
goto retry;
|
||||
}
|
||||
|
||||
OT::hb_scalar_cache_t *acquire_varStore_cache (const OT::ItemVariationStore &varStore) const
|
||||
{
|
||||
retry:
|
||||
auto *cache = varStore_cache.get_acquire ();
|
||||
if (!cache)
|
||||
return varStore.create_cache ();
|
||||
if (varStore_cache.cmpexch (cache, nullptr))
|
||||
return cache;
|
||||
else
|
||||
goto retry;
|
||||
}
|
||||
void release_varStore_cache (OT::hb_scalar_cache_t *cache) const
|
||||
{
|
||||
if (!cache)
|
||||
return;
|
||||
if (!varStore_cache.cmpexch (nullptr, cache))
|
||||
OT::ItemVariationStore::destroy_cache (cache);
|
||||
}
|
||||
void clear_varStore_cache () const
|
||||
{
|
||||
retry:
|
||||
auto *cache = varStore_cache.get_acquire ();
|
||||
if (!cache)
|
||||
return;
|
||||
if (varStore_cache.cmpexch (cache, nullptr))
|
||||
OT::ItemVariationStore::destroy_cache (cache);
|
||||
else
|
||||
goto retry;
|
||||
}
|
||||
|
||||
void clear () const
|
||||
{
|
||||
clear_origin_cache ();
|
||||
clear_varStore_cache ();
|
||||
}
|
||||
} v_origin;
|
||||
|
||||
struct draw_cache_t
|
||||
{
|
||||
mutable hb_atomic_t<OT::hb_scalar_cache_t *> gvar_cache;
|
||||
|
||||
~draw_cache_t ()
|
||||
{
|
||||
clear ();
|
||||
}
|
||||
|
||||
OT::hb_scalar_cache_t *acquire_gvar_cache (const OT::gvar_accelerator_t &gvar) const
|
||||
{
|
||||
retry:
|
||||
auto *cache = gvar_cache.get_acquire ();
|
||||
if (!cache)
|
||||
return gvar.create_cache ();
|
||||
if (gvar_cache.cmpexch (cache, nullptr))
|
||||
return cache;
|
||||
else
|
||||
goto retry;
|
||||
}
|
||||
void release_gvar_cache (OT::hb_scalar_cache_t *cache) const
|
||||
{
|
||||
if (!cache)
|
||||
return;
|
||||
if (!gvar_cache.cmpexch (nullptr, cache))
|
||||
OT::gvar_accelerator_t::destroy_cache (cache);
|
||||
}
|
||||
void clear_gvar_cache () const
|
||||
{
|
||||
retry:
|
||||
auto *cache = gvar_cache.get_acquire ();
|
||||
if (!cache)
|
||||
return;
|
||||
if (gvar_cache.cmpexch (cache, nullptr))
|
||||
OT::gvar_accelerator_t::destroy_cache (cache);
|
||||
else
|
||||
goto retry;
|
||||
}
|
||||
|
||||
void clear () const
|
||||
{
|
||||
clear_gvar_cache ();
|
||||
}
|
||||
} draw;
|
||||
|
||||
void check_serial (hb_font_t *font) const
|
||||
{
|
||||
int font_serial = font->serial_coords.get_acquire ();
|
||||
if (cached_serial.get_acquire () != font_serial)
|
||||
{
|
||||
/* These caches are dependent on scale and synthetic settings.
|
||||
* Any change to the font invalidates them. */
|
||||
v_origin.clear ();
|
||||
|
||||
if (cached_coords_serial.get_acquire () == font_serial)
|
||||
return;
|
||||
cached_serial.set_release (font_serial);
|
||||
}
|
||||
|
||||
h.clear ();
|
||||
v.clear ();
|
||||
int font_serial_coords = font->serial_coords.get_acquire ();
|
||||
if (cached_coords_serial.get_acquire () != font_serial_coords)
|
||||
{
|
||||
/* These caches are independent of scale or synthetic settings.
|
||||
* Just variation changes will invalidate them. */
|
||||
h.clear ();
|
||||
v.clear ();
|
||||
draw.clear ();
|
||||
|
||||
cached_coords_serial.set_release (font_serial);
|
||||
cached_coords_serial.set_release (font_serial_coords);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -242,37 +387,59 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
|||
unsigned advance_stride,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
// Duplicated in v_advances. Ugly. Keep in sync'ish.
|
||||
|
||||
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
||||
const hb_ot_face_t *ot_face = ot_font->ot_face;
|
||||
const OT::hmtx_accelerator_t &hmtx = *ot_face->hmtx;
|
||||
|
||||
ot_font->check_serial (font);
|
||||
const OT::HVAR &HVAR = *hmtx.var_table;
|
||||
const OT::ItemVariationStore &varStore = &HVAR + HVAR.varStore;
|
||||
OT::ItemVariationStore::cache_t *varStore_cache = ot_font->h.acquire_varStore_cache (varStore);
|
||||
|
||||
hb_ot_font_advance_cache_t *advance_cache = nullptr;
|
||||
|
||||
bool use_cache = font->num_coords;
|
||||
if (use_cache)
|
||||
{
|
||||
advance_cache = ot_font->h.acquire_advance_cache ();
|
||||
if (!advance_cache)
|
||||
use_cache = false;
|
||||
}
|
||||
|
||||
if (!use_cache)
|
||||
if (unlikely (!hmtx.has_data ()))
|
||||
{
|
||||
hb_position_t advance = font->face->get_upem () / 2;
|
||||
advance = font->em_scale_x (advance);
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = font->em_scale_x (hmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache));
|
||||
*first_advance = advance;
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
if (!font->has_nonzero_coords)
|
||||
{
|
||||
fallback:
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
// Just plain htmx data. No need to cache.
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = font->em_scale_x (hmtx.get_advance_without_var_unscaled (*first_glyph));
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{ /* Use cache. */
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
/* has_nonzero_coords. */
|
||||
|
||||
ot_font->check_serial (font);
|
||||
hb_ot_font_advance_cache_t *advance_cache = ot_font->h.acquire_advance_cache ();
|
||||
if (!advance_cache)
|
||||
{
|
||||
// malloc failure. Just use the fallback non-variable path.
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
/* If HVAR is present, use it.*/
|
||||
const OT::HVAR &HVAR = *hmtx.var_table;
|
||||
if (HVAR.has_data ())
|
||||
{
|
||||
const OT::ItemVariationStore &varStore = &HVAR + HVAR.varStore;
|
||||
OT::hb_scalar_cache_t *varStore_cache = ot_font->h.acquire_varStore_cache (varStore);
|
||||
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
hb_position_t v;
|
||||
|
|
@ -289,10 +456,44 @@ hb_ot_get_glyph_h_advances (hb_font_t* font, void* font_data,
|
|||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
|
||||
ot_font->h.release_varStore_cache (varStore_cache);
|
||||
ot_font->h.release_advance_cache (advance_cache);
|
||||
return;
|
||||
}
|
||||
|
||||
ot_font->h.release_varStore_cache (varStore_cache);
|
||||
const auto &gvar = *ot_face->gvar;
|
||||
if (gvar.has_data ())
|
||||
{
|
||||
const auto &glyf = *ot_face->glyf;
|
||||
auto *scratch = glyf.acquire_scratch ();
|
||||
OT::hb_scalar_cache_t *gvar_cache = ot_font->draw.acquire_gvar_cache (gvar);
|
||||
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
hb_position_t v;
|
||||
unsigned cv;
|
||||
if (advance_cache->get (*first_glyph, &cv))
|
||||
v = cv;
|
||||
else
|
||||
{
|
||||
v = glyf.get_advance_with_var_unscaled (*first_glyph, font, false, *scratch, gvar_cache);
|
||||
advance_cache->set (*first_glyph, v);
|
||||
}
|
||||
*first_advance = font->em_scale_x (v);
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
|
||||
ot_font->draw.release_gvar_cache (gvar_cache);
|
||||
glyf.release_scratch (scratch);
|
||||
ot_font->h.release_advance_cache (advance_cache);
|
||||
return;
|
||||
}
|
||||
|
||||
ot_font->h.release_advance_cache (advance_cache);
|
||||
// No HVAR or GVAR. Just use the fallback non-variable path.
|
||||
goto fallback;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
|
|
@ -305,99 +506,281 @@ hb_ot_get_glyph_v_advances (hb_font_t* font, void* font_data,
|
|||
unsigned advance_stride,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
// Duplicated from h_advances. Ugly. Keep in sync'ish.
|
||||
|
||||
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
||||
const hb_ot_face_t *ot_face = ot_font->ot_face;
|
||||
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
|
||||
|
||||
if (vmtx.has_data ())
|
||||
if (unlikely (!vmtx.has_data ()))
|
||||
{
|
||||
hb_font_extents_t font_extents;
|
||||
font->get_h_extents_with_fallback (&font_extents);
|
||||
hb_position_t advance = font_extents.ascender - font_extents.descender;
|
||||
advance = font->em_scale_y (- (int) advance);
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = advance;
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
if (!font->has_nonzero_coords)
|
||||
{
|
||||
fallback:
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
// Just plain vtmx data. No need to cache.
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = font->em_scale_y (- (int) vmtx.get_advance_without_var_unscaled (*first_glyph));
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
/* has_nonzero_coords. */
|
||||
|
||||
ot_font->check_serial (font);
|
||||
hb_ot_font_advance_cache_t *advance_cache = ot_font->v.acquire_advance_cache ();
|
||||
if (!advance_cache)
|
||||
{
|
||||
// malloc failure. Just use the fallback non-variable path.
|
||||
goto fallback;
|
||||
}
|
||||
|
||||
/* If VVAR is present, use it.*/
|
||||
const OT::VVAR &VVAR = *vmtx.var_table;
|
||||
if (VVAR.has_data ())
|
||||
{
|
||||
ot_font->check_serial (font);
|
||||
const OT::VVAR &VVAR = *vmtx.var_table;
|
||||
const OT::ItemVariationStore &varStore = &VVAR + VVAR.varStore;
|
||||
OT::ItemVariationStore::cache_t *varStore_cache = ot_font->v.acquire_varStore_cache (varStore);
|
||||
// TODO Use advance_cache.
|
||||
OT::hb_scalar_cache_t *varStore_cache = ot_font->v.acquire_varStore_cache (varStore);
|
||||
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = font->em_scale_y (-(int) vmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache));
|
||||
hb_position_t v;
|
||||
unsigned cv;
|
||||
if (advance_cache->get (*first_glyph, &cv))
|
||||
v = cv;
|
||||
else
|
||||
{
|
||||
v = vmtx.get_advance_with_var_unscaled (*first_glyph, font, varStore_cache);
|
||||
advance_cache->set (*first_glyph, v);
|
||||
}
|
||||
*first_advance = font->em_scale_y (- (int) v);
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
|
||||
ot_font->v.release_varStore_cache (varStore_cache);
|
||||
ot_font->v.release_advance_cache (advance_cache);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
const auto &gvar = *ot_face->gvar;
|
||||
if (gvar.has_data ())
|
||||
{
|
||||
hb_font_extents_t font_extents;
|
||||
font->get_h_extents_with_fallback (&font_extents);
|
||||
hb_position_t advance = -(font_extents.ascender - font_extents.descender);
|
||||
const auto &glyf = *ot_face->glyf;
|
||||
auto *scratch = glyf.acquire_scratch ();
|
||||
OT::hb_scalar_cache_t *gvar_cache = ot_font->draw.acquire_gvar_cache (gvar);
|
||||
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
*first_advance = advance;
|
||||
hb_position_t v;
|
||||
unsigned cv;
|
||||
if (advance_cache->get (*first_glyph, &cv))
|
||||
v = cv;
|
||||
else
|
||||
{
|
||||
v = glyf.get_advance_with_var_unscaled (*first_glyph, font, true, *scratch, gvar_cache);
|
||||
advance_cache->set (*first_glyph, v);
|
||||
}
|
||||
*first_advance = font->em_scale_y (- (int) v);
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_advance = &StructAtOffsetUnaligned<hb_position_t> (first_advance, advance_stride);
|
||||
}
|
||||
|
||||
ot_font->draw.release_gvar_cache (gvar_cache);
|
||||
glyf.release_scratch (scratch);
|
||||
ot_font->v.release_advance_cache (advance_cache);
|
||||
return;
|
||||
}
|
||||
|
||||
ot_font->v.release_advance_cache (advance_cache);
|
||||
// No VVAR or GVAR. Just use the fallback non-variable path.
|
||||
goto fallback;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
HB_HOT
|
||||
static hb_bool_t
|
||||
hb_ot_get_glyph_v_origin (hb_font_t *font,
|
||||
void *font_data,
|
||||
hb_codepoint_t glyph,
|
||||
hb_position_t *x,
|
||||
hb_position_t *y,
|
||||
void *user_data HB_UNUSED)
|
||||
hb_ot_get_glyph_v_origins (hb_font_t *font,
|
||||
void *font_data,
|
||||
unsigned int count,
|
||||
const hb_codepoint_t *first_glyph,
|
||||
unsigned glyph_stride,
|
||||
hb_position_t *first_x,
|
||||
unsigned x_stride,
|
||||
hb_position_t *first_y,
|
||||
unsigned y_stride,
|
||||
void *user_data HB_UNUSED)
|
||||
{
|
||||
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
||||
const hb_ot_face_t *ot_face = ot_font->ot_face;
|
||||
|
||||
*x = font->get_glyph_h_advance (glyph) / 2;
|
||||
|
||||
const OT::VORG &VORG = *ot_face->VORG;
|
||||
if (VORG.has_data ())
|
||||
/* First, set all the x values to half the advance width. */
|
||||
font->get_glyph_h_advances (count,
|
||||
first_glyph, glyph_stride,
|
||||
first_x, x_stride);
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
float delta = 0;
|
||||
*first_x /= 2;
|
||||
first_x = &StructAtOffsetUnaligned<hb_position_t> (first_x, x_stride);
|
||||
}
|
||||
|
||||
/* The vertical origin business is messy...
|
||||
*
|
||||
* We allocate the cache, then have various code paths that use the cache.
|
||||
* Each one is responsible to free it before returning.
|
||||
*/
|
||||
hb_ot_font_origin_cache_t *origin_cache = ot_font->v_origin.acquire_origin_cache ();
|
||||
|
||||
/* If there is VORG, always use it. It uses VVAR for variations if necessary. */
|
||||
const OT::VORG &VORG = *ot_face->VORG;
|
||||
if (origin_cache && VORG.has_data ())
|
||||
{
|
||||
#ifndef HB_NO_VAR
|
||||
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
|
||||
const OT::VVAR &VVAR = *vmtx.var_table;
|
||||
if (font->num_coords)
|
||||
VVAR.get_vorg_delta_unscaled (glyph,
|
||||
font->coords, font->num_coords,
|
||||
&delta);
|
||||
if (!font->has_nonzero_coords)
|
||||
#endif
|
||||
{
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
hb_position_t origin;
|
||||
unsigned cv;
|
||||
if (origin_cache->get (*first_glyph, &cv))
|
||||
origin = font->y_scale < 0 ? -cv : cv;
|
||||
else
|
||||
{
|
||||
origin = font->em_scalef_y (VORG.get_y_origin (*first_glyph));
|
||||
origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin);
|
||||
}
|
||||
|
||||
*y = font->em_scalef_y (VORG.get_y_origin (glyph) + delta);
|
||||
*first_y = origin;
|
||||
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
|
||||
}
|
||||
}
|
||||
#ifndef HB_NO_VAR
|
||||
else
|
||||
{
|
||||
const OT::VVAR &VVAR = *ot_face->vmtx->var_table;
|
||||
const auto &varStore = &VVAR + VVAR.varStore;
|
||||
auto *varStore_cache = ot_font->v_origin.acquire_varStore_cache (varStore);
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
hb_position_t origin;
|
||||
unsigned cv;
|
||||
if (origin_cache->get (*first_glyph, &cv))
|
||||
origin = font->y_scale < 0 ? -cv : cv;
|
||||
else
|
||||
{
|
||||
origin = font->em_scalef_y (VORG.get_y_origin (*first_glyph) +
|
||||
VVAR.get_vorg_delta_unscaled (*first_glyph,
|
||||
font->coords, font->num_coords,
|
||||
varStore_cache));
|
||||
origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin);
|
||||
}
|
||||
|
||||
*first_y = origin;
|
||||
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
|
||||
}
|
||||
ot_font->v_origin.release_varStore_cache (varStore_cache);
|
||||
}
|
||||
#endif
|
||||
ot_font->v_origin.release_origin_cache (origin_cache);
|
||||
return true;
|
||||
}
|
||||
|
||||
hb_glyph_extents_t extents = {0};
|
||||
|
||||
if (hb_font_get_glyph_extents (font, glyph, &extents))
|
||||
/* If and only if `vmtx` is present and it's a `glyf` font,
|
||||
* we use the top phantom point, deduced from vmtx,glyf[,gvar]. */
|
||||
const auto &vmtx = *ot_face->vmtx;
|
||||
const auto &glyf = *ot_face->glyf;
|
||||
if (origin_cache && vmtx.has_data() && glyf.has_data ())
|
||||
{
|
||||
const OT::vmtx_accelerator_t &vmtx = *ot_face->vmtx;
|
||||
int tsb = 0;
|
||||
if (vmtx.get_leading_bearing_with_var_unscaled (font, glyph, &tsb))
|
||||
auto *scratch = glyf.acquire_scratch ();
|
||||
OT::hb_scalar_cache_t *gvar_cache = font->has_nonzero_coords ?
|
||||
ot_font->draw.acquire_gvar_cache (*ot_face->gvar) :
|
||||
nullptr;
|
||||
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
*y = extents.y_bearing + font->em_scale_y (tsb);
|
||||
return true;
|
||||
hb_position_t origin;
|
||||
unsigned cv;
|
||||
if (origin_cache->get (*first_glyph, &cv))
|
||||
origin = font->y_scale < 0 ? -cv : cv;
|
||||
else
|
||||
{
|
||||
origin = font->em_scalef_y (glyf.get_v_origin_with_var_unscaled (*first_glyph, font, *scratch, gvar_cache));
|
||||
origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin);
|
||||
}
|
||||
|
||||
*first_y = origin;
|
||||
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
|
||||
}
|
||||
|
||||
hb_font_extents_t font_extents;
|
||||
font->get_h_extents_with_fallback (&font_extents);
|
||||
hb_position_t advance = font_extents.ascender - font_extents.descender;
|
||||
hb_position_t diff = advance - -extents.height;
|
||||
*y = extents.y_bearing + (diff >> 1);
|
||||
if (gvar_cache)
|
||||
ot_font->draw.release_gvar_cache (gvar_cache);
|
||||
glyf.release_scratch (scratch);
|
||||
ot_font->v_origin.release_origin_cache (origin_cache);
|
||||
return true;
|
||||
}
|
||||
|
||||
hb_font_extents_t font_extents;
|
||||
font->get_h_extents_with_fallback (&font_extents);
|
||||
*y = font_extents.ascender;
|
||||
/* Otherwise, use glyph extents to center the glyph vertically.
|
||||
* If getting glyph extents failed, just use the font ascender. */
|
||||
if (origin_cache && font->has_glyph_extents_func ())
|
||||
{
|
||||
hb_font_extents_t font_extents;
|
||||
font->get_h_extents_with_fallback (&font_extents);
|
||||
hb_position_t font_advance = font_extents.ascender - font_extents.descender;
|
||||
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
hb_position_t origin;
|
||||
unsigned cv;
|
||||
|
||||
if (origin_cache->get (*first_glyph, &cv))
|
||||
origin = font->y_scale < 0 ? -cv : cv;
|
||||
else
|
||||
{
|
||||
hb_glyph_extents_t extents = {0};
|
||||
if (likely (font->get_glyph_extents (*first_glyph, &extents)))
|
||||
origin = extents.y_bearing + ((font_advance - -extents.height) >> 1);
|
||||
else
|
||||
origin = font_extents.ascender;
|
||||
|
||||
origin_cache->set (*first_glyph, font->y_scale < 0 ? -origin : origin);
|
||||
}
|
||||
|
||||
*first_y = origin;
|
||||
|
||||
first_glyph = &StructAtOffsetUnaligned<hb_codepoint_t> (first_glyph, glyph_stride);
|
||||
first_y = &StructAtOffsetUnaligned<hb_position_t> (first_y, y_stride);
|
||||
}
|
||||
}
|
||||
|
||||
ot_font->v_origin.release_origin_cache (origin_cache);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
|
@ -498,17 +881,33 @@ hb_ot_draw_glyph_or_fail (hb_font_t *font,
|
|||
hb_draw_funcs_t *draw_funcs, void *draw_data,
|
||||
void *user_data)
|
||||
{
|
||||
const hb_ot_font_t *ot_font = (const hb_ot_font_t *) font_data;
|
||||
hb_draw_session_t draw_session {draw_funcs, draw_data};
|
||||
bool ret = false;
|
||||
|
||||
OT::hb_scalar_cache_t *gvar_cache = nullptr;
|
||||
if (font->num_coords)
|
||||
{
|
||||
ot_font->check_serial (font);
|
||||
gvar_cache = ot_font->draw.acquire_gvar_cache (*ot_font->ot_face->gvar);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR_COMPOSITES
|
||||
if (font->face->table.VARC->get_path (font, glyph, draw_session)) return true;
|
||||
if (font->face->table.VARC->get_path (font, glyph, draw_session)) { ret = true; goto done; }
|
||||
#endif
|
||||
// Keep the following in synch with VARC::get_path_at()
|
||||
if (font->face->table.glyf->get_path (font, glyph, draw_session)) return true;
|
||||
if (font->face->table.glyf->get_path (font, glyph, draw_session, gvar_cache)) { ret = true; goto done; }
|
||||
|
||||
#ifndef HB_NO_CFF
|
||||
if (font->face->table.cff2->get_path (font, glyph, draw_session)) return true;
|
||||
if (font->face->table.cff1->get_path (font, glyph, draw_session)) return true;
|
||||
if (font->face->table.cff2->get_path (font, glyph, draw_session)) { ret = true; goto done; }
|
||||
if (font->face->table.cff1->get_path (font, glyph, draw_session)) { ret = true; goto done; }
|
||||
#endif
|
||||
return false;
|
||||
|
||||
done:
|
||||
|
||||
ot_font->draw.release_gvar_cache (gvar_cache);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -548,12 +947,11 @@ static struct hb_ot_font_funcs_lazy_loader_t : hb_font_funcs_lazy_loader_t<hb_ot
|
|||
|
||||
hb_font_funcs_set_font_h_extents_func (funcs, hb_ot_get_font_h_extents, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_h_advances_func (funcs, hb_ot_get_glyph_h_advances, nullptr, nullptr);
|
||||
//hb_font_funcs_set_glyph_h_origin_func (funcs, hb_ot_get_glyph_h_origin, nullptr, nullptr);
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
hb_font_funcs_set_font_v_extents_func (funcs, hb_ot_get_font_v_extents, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_v_advances_func (funcs, hb_ot_get_glyph_v_advances, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_v_origin_func (funcs, hb_ot_get_glyph_v_origin, nullptr, nullptr);
|
||||
hb_font_funcs_set_glyph_v_origins_func (funcs, hb_ot_get_glyph_v_origins, nullptr, nullptr);
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_DRAW
|
||||
|
|
|
|||
79
thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
vendored
79
thirdparty/harfbuzz/src/hb-ot-hmtx-table.hh
vendored
|
|
@ -45,16 +45,6 @@
|
|||
#define HB_OT_TAG_vmtx HB_TAG('v','m','t','x')
|
||||
|
||||
|
||||
HB_INTERNAL bool
|
||||
_glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical, int *lsb);
|
||||
|
||||
HB_INTERNAL unsigned
|
||||
_glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
|
||||
|
||||
HB_INTERNAL bool
|
||||
_glyf_get_leading_bearing_without_var_unscaled (hb_face_t *face, hb_codepoint_t gid, bool is_vertical, int *lsb);
|
||||
|
||||
|
||||
namespace OT {
|
||||
|
||||
|
||||
|
|
@ -237,7 +227,7 @@ struct hmtxvmtx
|
|||
|
||||
auto it =
|
||||
+ hb_iter (c->plan->new_to_old_gid_list)
|
||||
| hb_map ([c, &_mtx, mtx_map] (hb_codepoint_pair_t _)
|
||||
| hb_map ([&_mtx, mtx_map] (hb_codepoint_pair_t _)
|
||||
{
|
||||
hb_codepoint_t new_gid = _.first;
|
||||
hb_codepoint_t old_gid = _.second;
|
||||
|
|
@ -246,8 +236,7 @@ struct hmtxvmtx
|
|||
if (!mtx_map->has (new_gid, &v))
|
||||
{
|
||||
int lsb = 0;
|
||||
if (!_mtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb))
|
||||
(void) _glyf_get_leading_bearing_without_var_unscaled (c->plan->source, old_gid, !T::is_horizontal, &lsb);
|
||||
_mtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb);
|
||||
return hb_pair (_mtx.get_advance_without_var_unscaled (old_gid), +lsb);
|
||||
}
|
||||
return *v;
|
||||
|
|
@ -326,49 +315,23 @@ struct hmtxvmtx
|
|||
|
||||
bool has_data () const { return (bool) num_bearings; }
|
||||
|
||||
bool get_leading_bearing_without_var_unscaled (hb_codepoint_t glyph,
|
||||
void get_leading_bearing_without_var_unscaled (hb_codepoint_t glyph,
|
||||
int *lsb) const
|
||||
{
|
||||
if (glyph < num_long_metrics)
|
||||
{
|
||||
*lsb = table->longMetricZ[glyph].sb;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (unlikely (glyph >= num_bearings))
|
||||
return false;
|
||||
{
|
||||
*lsb = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics];
|
||||
*lsb = bearings[glyph - num_long_metrics];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_leading_bearing_with_var_unscaled (hb_font_t *font,
|
||||
hb_codepoint_t glyph,
|
||||
int *lsb) const
|
||||
{
|
||||
if (!font->num_coords)
|
||||
return get_leading_bearing_without_var_unscaled (glyph, lsb);
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
float delta;
|
||||
if (var_table->get_lsb_delta_unscaled (glyph, font->coords, font->num_coords, &delta) &&
|
||||
get_leading_bearing_without_var_unscaled (glyph, lsb))
|
||||
{
|
||||
*lsb += roundf (delta);
|
||||
return true;
|
||||
}
|
||||
|
||||
// If there's no vmtx data, the phantom points from glyf table are not accurate,
|
||||
// so we cannot take the next path.
|
||||
bool is_vertical = T::tableTag == HB_OT_TAG_vmtx;
|
||||
if (is_vertical && !has_data ())
|
||||
return false;
|
||||
|
||||
return _glyf_get_leading_bearing_with_var_unscaled (font, glyph, is_vertical, lsb);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned int get_advance_without_var_unscaled (hb_codepoint_t glyph) const
|
||||
|
|
@ -402,27 +365,17 @@ struct hmtxvmtx
|
|||
return advances[hb_min (glyph - num_bearings, num_advances - num_bearings - 1)];
|
||||
}
|
||||
|
||||
unsigned get_advance_with_var_unscaled (hb_codepoint_t glyph,
|
||||
hb_font_t *font,
|
||||
ItemVariationStore::cache_t *store_cache = nullptr) const
|
||||
#ifndef HB_NO_VAR
|
||||
unsigned get_advance_with_var_unscaled (hb_codepoint_t glyph,
|
||||
hb_font_t *font,
|
||||
hb_scalar_cache_t *store_cache = nullptr) const
|
||||
{
|
||||
unsigned int advance = get_advance_without_var_unscaled (glyph);
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
if (unlikely (glyph >= num_bearings) || !font->num_coords)
|
||||
return advance;
|
||||
|
||||
if (var_table.get_length ())
|
||||
return advance + roundf (var_table->get_advance_delta_unscaled (glyph,
|
||||
font->coords, font->num_coords,
|
||||
store_cache));
|
||||
|
||||
unsigned glyf_advance = _glyf_get_advance_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
|
||||
return glyf_advance ? glyf_advance : advance;
|
||||
#else
|
||||
return advance;
|
||||
#endif
|
||||
return advance + roundf (var_table->get_advance_delta_unscaled (glyph,
|
||||
font->coords, font->num_coords,
|
||||
store_cache));
|
||||
}
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// 0 <= num_long_metrics <= num_bearings <= num_advances <= num_glyphs
|
||||
|
|
|
|||
336
thirdparty/harfbuzz/src/hb-ot-layout-common.hh
vendored
336
thirdparty/harfbuzz/src/hb-ot-layout-common.hh
vendored
|
|
@ -2548,32 +2548,94 @@ struct SparseVarRegionAxis
|
|||
DEFINE_SIZE_STATIC (8);
|
||||
};
|
||||
|
||||
#define REGION_CACHE_ITEM_CACHE_INVALID INT_MIN
|
||||
#define REGION_CACHE_ITEM_MULTIPLIER (float (1 << ((sizeof (int) * 8) - 2)))
|
||||
#define REGION_CACHE_ITEM_DIVISOR (1.f / float (1 << ((sizeof (int) * 8) - 2)))
|
||||
struct hb_scalar_cache_t
|
||||
{
|
||||
private:
|
||||
static constexpr unsigned STATIC_LENGTH = 16;
|
||||
static constexpr int INVALID = INT_MIN;
|
||||
static constexpr float MULTIPLIER = 1 << ((sizeof (int) * 8) - 2);
|
||||
static constexpr float DIVISOR = 1.f / MULTIPLIER;
|
||||
|
||||
public:
|
||||
hb_scalar_cache_t () : length (STATIC_LENGTH) { clear (); }
|
||||
|
||||
hb_scalar_cache_t (const hb_scalar_cache_t&) = delete;
|
||||
hb_scalar_cache_t (hb_scalar_cache_t&&) = delete;
|
||||
hb_scalar_cache_t& operator= (const hb_scalar_cache_t&) = delete;
|
||||
hb_scalar_cache_t& operator= (hb_scalar_cache_t&&) = delete;
|
||||
|
||||
static hb_scalar_cache_t *create (unsigned int count,
|
||||
hb_scalar_cache_t *scratch_cache = nullptr)
|
||||
{
|
||||
if (!count) return (hb_scalar_cache_t *) &Null(hb_scalar_cache_t);
|
||||
|
||||
if (scratch_cache && count <= scratch_cache->length)
|
||||
{
|
||||
scratch_cache->clear ();
|
||||
return scratch_cache;
|
||||
}
|
||||
|
||||
auto *cache = (hb_scalar_cache_t *) hb_malloc (sizeof (hb_scalar_cache_t) - sizeof (values) + sizeof (values[0]) * count);
|
||||
if (unlikely (!cache)) return (hb_scalar_cache_t *) &Null(hb_scalar_cache_t);
|
||||
|
||||
cache->length = count;
|
||||
cache->clear ();
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
static void destroy (hb_scalar_cache_t *cache,
|
||||
hb_scalar_cache_t *scratch_cache = nullptr)
|
||||
{
|
||||
if (cache != &Null(hb_scalar_cache_t) && cache != scratch_cache)
|
||||
hb_free (cache);
|
||||
}
|
||||
|
||||
void clear ()
|
||||
{
|
||||
for (unsigned i = 0; i < length; i++)
|
||||
values[i] = INVALID;
|
||||
}
|
||||
|
||||
HB_ALWAYS_INLINE
|
||||
bool get (unsigned i, float *value) const
|
||||
{
|
||||
if (unlikely (i >= length))
|
||||
{
|
||||
*value = 0.f;
|
||||
return true;
|
||||
}
|
||||
auto *cached_value = &values[i];
|
||||
if (*cached_value != INVALID)
|
||||
{
|
||||
*value = *cached_value ? *cached_value * DIVISOR : 0.f;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
HB_ALWAYS_INLINE
|
||||
void set (unsigned i, float value)
|
||||
{
|
||||
if (unlikely (i >= length)) return;
|
||||
auto *cached_value = &values[i];
|
||||
*cached_value = roundf(value * MULTIPLIER);
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned length;
|
||||
mutable hb_atomic_t<int> values[STATIC_LENGTH];
|
||||
};
|
||||
|
||||
struct VarRegionList
|
||||
{
|
||||
using cache_t = hb_atomic_t<int>;
|
||||
|
||||
float evaluate (unsigned int region_index,
|
||||
const int *coords, unsigned int coord_len,
|
||||
cache_t *cache = nullptr) const
|
||||
private:
|
||||
float evaluate_impl (unsigned int region_index,
|
||||
const int *coords, unsigned int coord_len) const
|
||||
{
|
||||
if (unlikely (region_index >= regionCount))
|
||||
return 0.;
|
||||
|
||||
cache_t *cached_value = nullptr;
|
||||
if (cache)
|
||||
{
|
||||
cached_value = &(cache[region_index]);
|
||||
if (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID)
|
||||
return *cached_value * REGION_CACHE_ITEM_DIVISOR;
|
||||
}
|
||||
|
||||
const VarRegionAxis *axes = axesZ.arrayZ + (region_index * axisCount);
|
||||
float v = 1.f;
|
||||
|
||||
float v = 1.;
|
||||
unsigned int count = axisCount;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
|
|
@ -2581,15 +2643,32 @@ struct VarRegionList
|
|||
float factor = axes[i].evaluate (coord);
|
||||
if (factor == 0.f)
|
||||
{
|
||||
if (cache)
|
||||
*cached_value = 0.;
|
||||
return 0.;
|
||||
v = 0.f;
|
||||
break;
|
||||
}
|
||||
v *= factor;
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public:
|
||||
HB_ALWAYS_INLINE
|
||||
float evaluate (unsigned int region_index,
|
||||
const int *coords, unsigned int coord_len,
|
||||
hb_scalar_cache_t *cache = nullptr) const
|
||||
{
|
||||
if (unlikely (region_index >= regionCount))
|
||||
return 0.;
|
||||
|
||||
float v;
|
||||
if (cache && cache->get (region_index, &v))
|
||||
return v;
|
||||
|
||||
v = evaluate_impl (region_index, coords, coord_len);
|
||||
|
||||
if (cache)
|
||||
*cached_value = v * REGION_CACHE_ITEM_MULTIPLIER;
|
||||
cache->set (region_index, v);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
|
@ -2732,29 +2811,24 @@ struct SparseVariationRegion : Array16Of<SparseVarRegionAxis>
|
|||
|
||||
struct SparseVarRegionList
|
||||
{
|
||||
using cache_t = hb_atomic_t<int>;
|
||||
|
||||
HB_ALWAYS_INLINE
|
||||
float evaluate (unsigned int region_index,
|
||||
const int *coords, unsigned int coord_len,
|
||||
cache_t *cache = nullptr) const
|
||||
hb_scalar_cache_t *cache = nullptr) const
|
||||
{
|
||||
if (unlikely (region_index >= regions.len))
|
||||
return 0.;
|
||||
|
||||
cache_t *cached_value = nullptr;
|
||||
if (cache)
|
||||
{
|
||||
cached_value = &(cache[region_index]);
|
||||
if (*cached_value != REGION_CACHE_ITEM_CACHE_INVALID)
|
||||
return *cached_value * REGION_CACHE_ITEM_DIVISOR;
|
||||
}
|
||||
float v;
|
||||
if (cache && cache->get (region_index, &v))
|
||||
return v;
|
||||
|
||||
const SparseVariationRegion ®ion = this+regions[region_index];
|
||||
|
||||
float v = region.evaluate (coords, coord_len);
|
||||
|
||||
v = region.evaluate (coords, coord_len);
|
||||
if (cache)
|
||||
*cached_value = v * REGION_CACHE_ITEM_MULTIPLIER;
|
||||
cache->set (region_index, v);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
|
@ -2792,46 +2866,62 @@ struct VarData
|
|||
+ itemCount * get_row_size ();
|
||||
}
|
||||
|
||||
float get_delta (unsigned int inner,
|
||||
const int *coords, unsigned int coord_count,
|
||||
const VarRegionList ®ions,
|
||||
VarRegionList::cache_t *cache = nullptr) const
|
||||
float _get_delta (unsigned int inner,
|
||||
const int *coords, unsigned int coord_count,
|
||||
const VarRegionList ®ions,
|
||||
hb_scalar_cache_t *cache = nullptr) const
|
||||
{
|
||||
if (unlikely (inner >= itemCount))
|
||||
return 0.;
|
||||
bool is_long = longWords ();
|
||||
unsigned int count = regionIndices.len;
|
||||
unsigned word_count = wordCount ();
|
||||
unsigned int scount = is_long ? count : word_count;
|
||||
unsigned int lcount = is_long ? word_count : 0;
|
||||
|
||||
unsigned int count = regionIndices.len;
|
||||
bool is_long = longWords ();
|
||||
unsigned word_count = wordCount ();
|
||||
unsigned int scount = is_long ? count : word_count;
|
||||
unsigned int lcount = is_long ? word_count : 0;
|
||||
const HBUINT8 *bytes = get_delta_bytes ();
|
||||
const HBUINT8 *row = bytes + inner * get_row_size ();
|
||||
|
||||
const HBUINT8 *bytes = get_delta_bytes ();
|
||||
const HBUINT8 *row = bytes + inner * get_row_size ();
|
||||
float delta = 0.;
|
||||
unsigned int i = 0;
|
||||
|
||||
float delta = 0.;
|
||||
unsigned int i = 0;
|
||||
const HBINT32 *lcursor = reinterpret_cast<const HBINT32 *> (row);
|
||||
for (; i < lcount; i++)
|
||||
{
|
||||
float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
|
||||
if (scalar)
|
||||
delta += scalar * *lcursor;
|
||||
lcursor++;
|
||||
}
|
||||
const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (lcursor);
|
||||
for (; i < scount; i++)
|
||||
{
|
||||
float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
|
||||
if (scalar)
|
||||
delta += scalar * *scursor;
|
||||
scursor++;
|
||||
}
|
||||
const HBINT8 *bcursor = reinterpret_cast<const HBINT8 *> (scursor);
|
||||
for (; i < count; i++)
|
||||
{
|
||||
float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
|
||||
if (scalar)
|
||||
delta += scalar * *bcursor;
|
||||
bcursor++;
|
||||
}
|
||||
|
||||
const HBINT32 *lcursor = reinterpret_cast<const HBINT32 *> (row);
|
||||
for (; i < lcount; i++)
|
||||
{
|
||||
float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
|
||||
delta += scalar * *lcursor++;
|
||||
}
|
||||
const HBINT16 *scursor = reinterpret_cast<const HBINT16 *> (lcursor);
|
||||
for (; i < scount; i++)
|
||||
{
|
||||
float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
|
||||
delta += scalar * *scursor++;
|
||||
}
|
||||
const HBINT8 *bcursor = reinterpret_cast<const HBINT8 *> (scursor);
|
||||
for (; i < count; i++)
|
||||
{
|
||||
float scalar = regions.evaluate (regionIndices.arrayZ[i], coords, coord_count, cache);
|
||||
delta += scalar * *bcursor++;
|
||||
}
|
||||
return delta;
|
||||
}
|
||||
|
||||
return delta;
|
||||
HB_ALWAYS_INLINE
|
||||
float get_delta (unsigned int inner,
|
||||
const int *coords, unsigned int coord_count,
|
||||
const VarRegionList ®ions,
|
||||
hb_scalar_cache_t *cache = nullptr) const
|
||||
{
|
||||
unsigned int count = regionIndices.len;
|
||||
if (!count) return 0.f; // This is quite common, so optimize it.
|
||||
return _get_delta (inner, coords, coord_count, regions, cache);
|
||||
}
|
||||
|
||||
void get_region_scalars (const int *coords, unsigned int coord_count,
|
||||
|
|
@ -2869,7 +2959,7 @@ struct VarData
|
|||
return false;
|
||||
}
|
||||
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
if (unlikely (!c->extend_min (this))) return_trace (false);
|
||||
itemCount = row_count;
|
||||
|
||||
int min_threshold = has_long ? -65536 : -128;
|
||||
|
|
@ -3150,7 +3240,7 @@ struct MultiVarData
|
|||
const int *coords, unsigned int coord_count,
|
||||
const SparseVarRegionList ®ions,
|
||||
hb_array_t<float> out,
|
||||
SparseVarRegionList::cache_t *cache = nullptr) const
|
||||
hb_scalar_cache_t *cache = nullptr) const
|
||||
{
|
||||
auto &deltaSets = StructAfter<decltype (deltaSetsX)> (regionIndices);
|
||||
|
||||
|
|
@ -3187,31 +3277,24 @@ struct MultiVarData
|
|||
struct ItemVariationStore
|
||||
{
|
||||
friend struct item_variations_t;
|
||||
using cache_t = VarRegionList::cache_t;
|
||||
|
||||
cache_t *create_cache () const
|
||||
hb_scalar_cache_t *create_cache () const
|
||||
{
|
||||
#ifdef HB_NO_VAR
|
||||
return nullptr;
|
||||
return hb_scalar_cache_t::create (0);
|
||||
#endif
|
||||
unsigned count = (this+regions).regionCount;
|
||||
if (!count) return nullptr;
|
||||
|
||||
cache_t *cache = (cache_t *) hb_malloc (sizeof (float) * count);
|
||||
if (unlikely (!cache)) return nullptr;
|
||||
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
cache[i] = REGION_CACHE_ITEM_CACHE_INVALID;
|
||||
|
||||
return cache;
|
||||
return hb_scalar_cache_t::create ((this+regions).regionCount);
|
||||
}
|
||||
|
||||
static void destroy_cache (cache_t *cache) { hb_free (cache); }
|
||||
static void destroy_cache (hb_scalar_cache_t *cache)
|
||||
{
|
||||
hb_scalar_cache_t::destroy (cache);
|
||||
}
|
||||
|
||||
private:
|
||||
float get_delta (unsigned int outer, unsigned int inner,
|
||||
const int *coords, unsigned int coord_count,
|
||||
VarRegionList::cache_t *cache = nullptr) const
|
||||
hb_scalar_cache_t *cache = nullptr) const
|
||||
{
|
||||
#ifdef HB_NO_VAR
|
||||
return 0.f;
|
||||
|
|
@ -3229,7 +3312,7 @@ struct ItemVariationStore
|
|||
public:
|
||||
float get_delta (unsigned int index,
|
||||
const int *coords, unsigned int coord_count,
|
||||
VarRegionList::cache_t *cache = nullptr) const
|
||||
hb_scalar_cache_t *cache = nullptr) const
|
||||
{
|
||||
unsigned int outer = index >> 16;
|
||||
unsigned int inner = index & 0xFFFF;
|
||||
|
|
@ -3237,7 +3320,7 @@ struct ItemVariationStore
|
|||
}
|
||||
float get_delta (unsigned int index,
|
||||
hb_array_t<const int> coords,
|
||||
VarRegionList::cache_t *cache = nullptr) const
|
||||
hb_scalar_cache_t *cache = nullptr) const
|
||||
{
|
||||
return get_delta (index,
|
||||
coords.arrayZ, coords.length,
|
||||
|
|
@ -3445,43 +3528,28 @@ struct ItemVariationStore
|
|||
|
||||
struct MultiItemVariationStore
|
||||
{
|
||||
using cache_t = SparseVarRegionList::cache_t;
|
||||
|
||||
cache_t *create_cache (hb_array_t<cache_t> static_cache = hb_array_t<cache_t> ()) const
|
||||
hb_scalar_cache_t *create_cache (hb_scalar_cache_t *static_cache = nullptr) const
|
||||
{
|
||||
#ifdef HB_NO_VAR
|
||||
return nullptr;
|
||||
return hb_scalar_cache_t::create (0);
|
||||
#endif
|
||||
auto &r = this+regions;
|
||||
unsigned count = r.regions.len;
|
||||
|
||||
cache_t *cache;
|
||||
if (count <= static_cache.length)
|
||||
cache = static_cache.arrayZ;
|
||||
else
|
||||
{
|
||||
cache = (cache_t *) hb_malloc (sizeof (float) * count);
|
||||
if (unlikely (!cache)) return nullptr;
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
cache[i] = REGION_CACHE_ITEM_CACHE_INVALID;
|
||||
|
||||
return cache;
|
||||
return hb_scalar_cache_t::create (count, static_cache);
|
||||
}
|
||||
|
||||
static void destroy_cache (cache_t *cache,
|
||||
hb_array_t<cache_t> static_cache = hb_array_t<cache_t> ())
|
||||
static void destroy_cache (hb_scalar_cache_t *cache,
|
||||
hb_scalar_cache_t *static_cache = nullptr)
|
||||
{
|
||||
if (cache != static_cache.arrayZ)
|
||||
hb_free (cache);
|
||||
hb_scalar_cache_t::destroy (cache, static_cache);
|
||||
}
|
||||
|
||||
private:
|
||||
void get_delta (unsigned int outer, unsigned int inner,
|
||||
const int *coords, unsigned int coord_count,
|
||||
hb_array_t<float> out,
|
||||
VarRegionList::cache_t *cache = nullptr) const
|
||||
hb_scalar_cache_t *cache = nullptr) const
|
||||
{
|
||||
#ifdef HB_NO_VAR
|
||||
return;
|
||||
|
|
@ -3501,7 +3569,7 @@ struct MultiItemVariationStore
|
|||
void get_delta (unsigned int index,
|
||||
const int *coords, unsigned int coord_count,
|
||||
hb_array_t<float> out,
|
||||
VarRegionList::cache_t *cache = nullptr) const
|
||||
hb_scalar_cache_t *cache = nullptr) const
|
||||
{
|
||||
unsigned int outer = index >> 16;
|
||||
unsigned int inner = index & 0xFFFF;
|
||||
|
|
@ -3510,7 +3578,7 @@ struct MultiItemVariationStore
|
|||
void get_delta (unsigned int index,
|
||||
hb_array_t<const int> coords,
|
||||
hb_array_t<float> out,
|
||||
VarRegionList::cache_t *cache = nullptr) const
|
||||
hb_scalar_cache_t *cache = nullptr) const
|
||||
{
|
||||
return get_delta (index,
|
||||
coords.arrayZ, coords.length,
|
||||
|
|
@ -3540,8 +3608,6 @@ struct MultiItemVariationStore
|
|||
DEFINE_SIZE_ARRAY_SIZED (8, dataSets);
|
||||
};
|
||||
|
||||
#undef REGION_CACHE_ITEM_CACHE_INVALID
|
||||
|
||||
template <typename MapCountT>
|
||||
struct DeltaSetIndexMapFormat01
|
||||
{
|
||||
|
|
@ -3592,13 +3658,19 @@ struct DeltaSetIndexMapFormat01
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
HB_ALWAYS_INLINE
|
||||
uint32_t map (unsigned int v) const /* Returns 16.16 outer.inner. */
|
||||
{
|
||||
/* If count is zero, pass value unchanged. This takes
|
||||
* care of direct mapping for advance map. */
|
||||
if (!mapCount)
|
||||
return v;
|
||||
return _map (v);
|
||||
}
|
||||
|
||||
HB_HOT
|
||||
uint32_t _map (unsigned int v) const /* Returns 16.16 outer.inner. */
|
||||
{
|
||||
if (v >= mapCount)
|
||||
v = mapCount - 1;
|
||||
|
||||
|
|
@ -3736,7 +3808,7 @@ struct ItemVarStoreInstancer
|
|||
ItemVarStoreInstancer (const ItemVariationStore *varStore_,
|
||||
const DeltaSetIndexMap *varIdxMap,
|
||||
hb_array_t<const int> coords,
|
||||
VarRegionList::cache_t *cache = nullptr) :
|
||||
hb_scalar_cache_t *cache = nullptr) :
|
||||
varStore (varStore_), varIdxMap (varIdxMap), coords (coords), cache (cache)
|
||||
{
|
||||
if (!varStore)
|
||||
|
|
@ -3762,7 +3834,7 @@ struct ItemVarStoreInstancer
|
|||
const ItemVariationStore *varStore;
|
||||
const DeltaSetIndexMap *varIdxMap;
|
||||
hb_array_t<const int> coords;
|
||||
VarRegionList::cache_t *cache;
|
||||
hb_scalar_cache_t *cache;
|
||||
};
|
||||
|
||||
struct MultiItemVarStoreInstancer
|
||||
|
|
@ -3770,7 +3842,7 @@ struct MultiItemVarStoreInstancer
|
|||
MultiItemVarStoreInstancer (const MultiItemVariationStore *varStore,
|
||||
const DeltaSetIndexMap *varIdxMap,
|
||||
hb_array_t<const int> coords,
|
||||
SparseVarRegionList::cache_t *cache = nullptr) :
|
||||
hb_scalar_cache_t *cache = nullptr) :
|
||||
varStore (varStore), varIdxMap (varIdxMap), coords (coords), cache (cache)
|
||||
{
|
||||
if (!varStore)
|
||||
|
|
@ -3803,7 +3875,7 @@ struct MultiItemVarStoreInstancer
|
|||
const MultiItemVariationStore *varStore;
|
||||
const DeltaSetIndexMap *varIdxMap;
|
||||
hb_array_t<const int> coords;
|
||||
SparseVarRegionList::cache_t *cache;
|
||||
hb_scalar_cache_t *cache;
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -4783,13 +4855,13 @@ struct VariationDevice
|
|||
|
||||
hb_position_t get_x_delta (hb_font_t *font,
|
||||
const ItemVariationStore &store,
|
||||
ItemVariationStore::cache_t *store_cache = nullptr) const
|
||||
{ return !font->num_coords ? 0 : font->em_scalef_x (get_delta (font, store, store_cache)); }
|
||||
hb_scalar_cache_t *store_cache = nullptr) const
|
||||
{ return !font->has_nonzero_coords ? 0 : font->em_scalef_x (get_delta (font, store, store_cache)); }
|
||||
|
||||
hb_position_t get_y_delta (hb_font_t *font,
|
||||
const ItemVariationStore &store,
|
||||
ItemVariationStore::cache_t *store_cache = nullptr) const
|
||||
{ return !font->num_coords ? 0 : font->em_scalef_y (get_delta (font, store, store_cache)); }
|
||||
hb_scalar_cache_t *store_cache = nullptr) const
|
||||
{ return !font->has_nonzero_coords ? 0 : font->em_scalef_y (get_delta (font, store, store_cache)); }
|
||||
|
||||
VariationDevice* copy (hb_serialize_context_t *c,
|
||||
const hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *layout_variation_idx_delta_map) const
|
||||
|
|
@ -4823,9 +4895,9 @@ struct VariationDevice
|
|||
|
||||
float get_delta (hb_font_t *font,
|
||||
const ItemVariationStore &store,
|
||||
ItemVariationStore::cache_t *store_cache = nullptr) const
|
||||
hb_scalar_cache_t *store_cache = nullptr) const
|
||||
{
|
||||
return store.get_delta (varIdx, font->coords, font->num_coords, (ItemVariationStore::cache_t *) store_cache);
|
||||
return store.get_delta (varIdx, font->coords, font->num_coords, store_cache);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
@ -4850,7 +4922,7 @@ struct Device
|
|||
{
|
||||
hb_position_t get_x_delta (hb_font_t *font,
|
||||
const ItemVariationStore &store=Null (ItemVariationStore),
|
||||
ItemVariationStore::cache_t *store_cache = nullptr) const
|
||||
hb_scalar_cache_t *store_cache = nullptr) const
|
||||
{
|
||||
switch (u.b.format)
|
||||
{
|
||||
|
|
@ -4868,7 +4940,7 @@ struct Device
|
|||
}
|
||||
hb_position_t get_y_delta (hb_font_t *font,
|
||||
const ItemVariationStore &store=Null (ItemVariationStore),
|
||||
ItemVariationStore::cache_t *store_cache = nullptr) const
|
||||
hb_scalar_cache_t *store_cache = nullptr) const
|
||||
{
|
||||
switch (u.b.format)
|
||||
{
|
||||
|
|
@ -4954,6 +5026,18 @@ struct Device
|
|||
}
|
||||
}
|
||||
|
||||
bool is_variation_device () const
|
||||
{
|
||||
switch (u.b.format) {
|
||||
#ifndef HB_NO_VAR
|
||||
case 0x8000:
|
||||
return true;
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
union {
|
||||
DeviceHeader b;
|
||||
|
|
|
|||
|
|
@ -700,7 +700,7 @@ struct hb_ot_apply_context_t :
|
|||
const GDEF::accelerator_t &gdef_accel;
|
||||
const hb_ot_layout_lookup_accelerator_t *lookup_accel = nullptr;
|
||||
const ItemVariationStore &var_store;
|
||||
ItemVariationStore::cache_t *var_store_cache;
|
||||
hb_scalar_cache_t *var_store_cache;
|
||||
hb_set_digest_t digest;
|
||||
|
||||
hb_direction_t direction;
|
||||
|
|
@ -723,7 +723,7 @@ struct hb_ot_apply_context_t :
|
|||
hb_font_t *font_,
|
||||
hb_buffer_t *buffer_,
|
||||
hb_blob_t *table_blob_,
|
||||
ItemVariationStore::cache_t *var_store_cache_ = nullptr) :
|
||||
hb_scalar_cache_t *var_store_cache_ = nullptr) :
|
||||
table_index (table_index_),
|
||||
font (font_), face (font->face), buffer (buffer_),
|
||||
sanitizer (table_blob_),
|
||||
|
|
|
|||
52
thirdparty/harfbuzz/src/hb-ot-layout.cc
vendored
52
thirdparty/harfbuzz/src/hb-ot-layout.cc
vendored
|
|
@ -343,7 +343,7 @@ hb_ot_layout_get_glyphs_in_class (hb_face_t *face,
|
|||
* @face: The #hb_face_t to work on
|
||||
* @glyph: The #hb_codepoint_t code point to query
|
||||
* @start_offset: offset of the first attachment point to retrieve
|
||||
* @point_count: (inout) (optional): Input = the maximum number of attachment points to return;
|
||||
* @point_count: (inout) (nullable): Input = the maximum number of attachment points to return;
|
||||
* Output = the actual number of attachment points returned (may be zero)
|
||||
* @point_array: (out) (array length=point_count): The array of attachment points found for the query
|
||||
*
|
||||
|
|
@ -373,7 +373,7 @@ hb_ot_layout_get_attach_points (hb_face_t *face,
|
|||
* @direction: The #hb_direction_t text direction to use
|
||||
* @glyph: The #hb_codepoint_t code point to query
|
||||
* @start_offset: offset of the first caret position to retrieve
|
||||
* @caret_count: (inout) (optional): Input = the maximum number of caret positions to return;
|
||||
* @caret_count: (inout) (nullable): Input = the maximum number of caret positions to return;
|
||||
* Output = the actual number of caret positions returned (may be zero)
|
||||
* @caret_array: (out) (array length=caret_count): The array of caret positions found for the query
|
||||
*
|
||||
|
|
@ -444,7 +444,7 @@ get_gsubgpos_table (hb_face_t *face,
|
|||
* @face: #hb_face_t to work upon
|
||||
* @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
|
||||
* @start_offset: offset of the first script tag to retrieve
|
||||
* @script_count: (inout) (optional): Input = the maximum number of script tags to return;
|
||||
* @script_count: (inout) (nullable): Input = the maximum number of script tags to return;
|
||||
* Output = the actual number of script tags returned (may be zero)
|
||||
* @script_tags: (out) (array length=script_count): The array of #hb_tag_t script tags found for the query
|
||||
*
|
||||
|
|
@ -541,8 +541,8 @@ hb_ot_layout_table_choose_script (hb_face_t *face,
|
|||
* @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
|
||||
* @script_count: Number of script tags in the array
|
||||
* @script_tags: Array of #hb_tag_t script tags
|
||||
* @script_index: (out) (optional): The index of the requested script
|
||||
* @chosen_script: (out) (optional): #hb_tag_t of the requested script
|
||||
* @script_index: (out) (nullable): The index of the requested script
|
||||
* @chosen_script: (out) (nullable): #hb_tag_t of the requested script
|
||||
*
|
||||
* Selects an OpenType script for @table_tag from the @script_tags array.
|
||||
*
|
||||
|
|
@ -613,7 +613,7 @@ hb_ot_layout_table_select_script (hb_face_t *face,
|
|||
* @face: #hb_face_t to work upon
|
||||
* @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
|
||||
* @start_offset: offset of the first feature tag to retrieve
|
||||
* @feature_count: (inout) (optional): Input = the maximum number of feature tags to return;
|
||||
* @feature_count: (inout) (nullable): Input = the maximum number of feature tags to return;
|
||||
* Output = the actual number of feature tags returned (may be zero)
|
||||
* @feature_tags: (out) (array length=feature_count): Array of feature tags found in the table
|
||||
*
|
||||
|
|
@ -683,7 +683,7 @@ hb_ot_layout_table_find_feature (hb_face_t *face,
|
|||
* @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
|
||||
* @script_index: The index of the requested script tag
|
||||
* @start_offset: offset of the first language tag to retrieve
|
||||
* @language_count: (inout) (optional): Input = the maximum number of language tags to return;
|
||||
* @language_count: (inout) (nullable): Input = the maximum number of language tags to return;
|
||||
* Output = the actual number of language tags returned (may be zero)
|
||||
* @language_tags: (out) (array length=language_count): Array of language tags found in the table
|
||||
*
|
||||
|
|
@ -911,7 +911,7 @@ hb_ot_layout_language_get_required_feature (hb_face_t *face,
|
|||
* @script_index: The index of the requested script tag
|
||||
* @language_index: The index of the requested language tag
|
||||
* @start_offset: offset of the first feature tag to retrieve
|
||||
* @feature_count: (inout) (optional): Input = the maximum number of feature tags to return;
|
||||
* @feature_count: (inout) (nullable): Input = the maximum number of feature tags to return;
|
||||
* Output: the actual number of feature tags returned (may be zero)
|
||||
* @feature_indexes: (out) (array length=feature_count): The array of feature indexes found for the query
|
||||
*
|
||||
|
|
@ -947,7 +947,7 @@ hb_ot_layout_language_get_feature_indexes (hb_face_t *face,
|
|||
* @script_index: The index of the requested script tag
|
||||
* @language_index: The index of the requested language tag
|
||||
* @start_offset: offset of the first feature tag to retrieve
|
||||
* @feature_count: (inout) (optional): Input = the maximum number of feature tags to return;
|
||||
* @feature_count: (inout) (nullable): Input = the maximum number of feature tags to return;
|
||||
* Output = the actual number of feature tags returned (may be zero)
|
||||
* @feature_tags: (out) (array length=feature_count): The array of #hb_tag_t feature tags found for the query
|
||||
*
|
||||
|
|
@ -1035,7 +1035,7 @@ hb_ot_layout_language_find_feature (hb_face_t *face,
|
|||
* @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
|
||||
* @feature_index: The index of the requested feature
|
||||
* @start_offset: offset of the first lookup to retrieve
|
||||
* @lookup_count: (inout) (optional): Input = the maximum number of lookups to return;
|
||||
* @lookup_count: (inout) (nullable): Input = the maximum number of lookups to return;
|
||||
* Output = the actual number of lookups returned (may be zero)
|
||||
* @lookup_indexes: (out) (array length=lookup_count): The array of lookup indexes found for the query
|
||||
*
|
||||
|
|
@ -1386,10 +1386,10 @@ hb_ot_layout_collect_lookups (hb_face_t *face,
|
|||
* @face: #hb_face_t to work upon
|
||||
* @table_tag: #HB_OT_TAG_GSUB or #HB_OT_TAG_GPOS
|
||||
* @lookup_index: The index of the feature lookup to query
|
||||
* @glyphs_before: (out): Array of glyphs preceding the substitution range
|
||||
* @glyphs_input: (out): Array of input glyphs that would be substituted by the lookup
|
||||
* @glyphs_after: (out): Array of glyphs following the substitution range
|
||||
* @glyphs_output: (out): Array of glyphs that would be the substituted output of the lookup
|
||||
* @glyphs_before: (out) (nullable): Array of glyphs preceding the substitution range
|
||||
* @glyphs_input: (out) (nullable): Array of input glyphs that would be substituted by the lookup
|
||||
* @glyphs_after: (out) (nullable): Array of glyphs following the substitution range
|
||||
* @glyphs_output: (out) (nullable): Array of glyphs that would be the substituted output of the lookup
|
||||
*
|
||||
* Fetches a list of all glyphs affected by the specified lookup in the
|
||||
* specified face's GSUB table or GPOS table.
|
||||
|
|
@ -1473,7 +1473,7 @@ hb_ot_layout_table_find_feature_variations (hb_face_t *face,
|
|||
* @feature_index: The index of the feature to query
|
||||
* @variations_index: The index of the feature variation to query
|
||||
* @start_offset: offset of the first lookup to retrieve
|
||||
* @lookup_count: (inout) (optional): Input = the maximum number of lookups to return;
|
||||
* @lookup_count: (inout) (nullable): Input = the maximum number of lookups to return;
|
||||
* Output = the actual number of lookups returned (may be zero)
|
||||
* @lookup_indexes: (out) (array length=lookup_count): The array of lookups found for the query
|
||||
*
|
||||
|
|
@ -1777,15 +1777,15 @@ hb_ot_layout_get_size_params (hb_face_t *face,
|
|||
* @face: #hb_face_t to work upon
|
||||
* @table_tag: table tag to query, "GSUB" or "GPOS".
|
||||
* @feature_index: index of feature to query.
|
||||
* @label_id: (out) (optional): The ‘name’ table name ID that specifies a string
|
||||
* for a user-interface label for this feature. (May be NULL.)
|
||||
* @tooltip_id: (out) (optional): The ‘name’ table name ID that specifies a string
|
||||
* @label_id: (out) (nullable): The ‘name’ table name ID that specifies a string
|
||||
* for a user-interface label for this feature.
|
||||
* @tooltip_id: (out) (nullable): The ‘name’ table name ID that specifies a string
|
||||
* that an application can use for tooltip text for this
|
||||
* feature. (May be NULL.)
|
||||
* @sample_id: (out) (optional): The ‘name’ table name ID that specifies sample text
|
||||
* that illustrates the effect of this feature. (May be NULL.)
|
||||
* @num_named_parameters: (out) (optional): Number of named parameters. (May be zero.)
|
||||
* @first_param_id: (out) (optional): The first ‘name’ table name ID used to specify
|
||||
* feature.
|
||||
* @sample_id: (out) (nullable): The ‘name’ table name ID that specifies sample text
|
||||
* that illustrates the effect of this feature.
|
||||
* @num_named_parameters: (out) (nullable): Number of named parameters.
|
||||
* @first_param_id: (out) (nullable): The first ‘name’ table name ID used to specify
|
||||
* strings for user-interface labels for the feature
|
||||
* parameters. (Must be zero if numParameters is zero.)
|
||||
*
|
||||
|
|
@ -1852,7 +1852,7 @@ hb_ot_layout_feature_get_name_ids (hb_face_t *face,
|
|||
* @table_tag: table tag to query, "GSUB" or "GPOS".
|
||||
* @feature_index: index of feature to query.
|
||||
* @start_offset: offset of the first character to retrieve
|
||||
* @char_count: (inout) (optional): Input = the maximum number of characters to return;
|
||||
* @char_count: (inout) (nullable): Input = the maximum number of characters to return;
|
||||
* Output = the actual number of characters returned (may be zero)
|
||||
* @characters: (out caller-allocates) (array length=char_count): A buffer pointer.
|
||||
* The Unicode codepoints of the characters for which this feature provides
|
||||
|
|
@ -2017,7 +2017,7 @@ inline void hb_ot_map_t::apply (const Proxy &proxy,
|
|||
unsigned int i = 0;
|
||||
|
||||
auto *font_data = font->data.ot.get ();
|
||||
auto *var_store_cache = font_data == HB_SHAPER_DATA_SUCCEEDED ? nullptr : (OT::ItemVariationStore::cache_t *) font_data;
|
||||
auto *var_store_cache = (OT::hb_scalar_cache_t *) font_data;
|
||||
|
||||
OT::hb_ot_apply_context_t c (table_index, font, buffer, proxy.accel.get_blob (), var_store_cache);
|
||||
c.set_recurse_func (Proxy::Lookup::template dispatch_recurse_func<OT::hb_ot_apply_context_t>);
|
||||
|
|
@ -2627,7 +2627,7 @@ struct hb_get_glyph_alternates_dispatch_t :
|
|||
* @lookup_index: index of the feature lookup to query.
|
||||
* @glyph: a glyph id.
|
||||
* @start_offset: starting offset.
|
||||
* @alternate_count: (inout) (optional): Input = the maximum number of alternate glyphs to return;
|
||||
* @alternate_count: (inout) (nullable): Input = the maximum number of alternate glyphs to return;
|
||||
* Output = the actual number of alternate glyphs returned (may be zero).
|
||||
* @alternate_glyphs: (out caller-allocates) (array length=alternate_count): A glyphs buffer.
|
||||
* Alternate glyphs associated with the glyph id.
|
||||
|
|
|
|||
106
thirdparty/harfbuzz/src/hb-ot-shape.cc
vendored
106
thirdparty/harfbuzz/src/hb-ot-shape.cc
vendored
|
|
@ -44,6 +44,7 @@
|
|||
#include "hb-ot-face.hh"
|
||||
|
||||
#include "hb-set.hh"
|
||||
#include "hb-unicode.hh"
|
||||
|
||||
#include "hb-aat-layout.hh"
|
||||
#include "hb-ot-layout-gdef-table.hh"
|
||||
|
|
@ -425,25 +426,20 @@ _hb_ot_shaper_face_data_destroy (hb_ot_face_data_t *data)
|
|||
*/
|
||||
|
||||
struct hb_ot_font_data_t {
|
||||
OT::ItemVariationStore::cache_t unused; // Just for alignment
|
||||
OT::hb_scalar_cache_t unused; // Just for alignment
|
||||
};
|
||||
|
||||
hb_ot_font_data_t *
|
||||
_hb_ot_shaper_font_data_create (hb_font_t *font)
|
||||
{
|
||||
if (!font->num_coords)
|
||||
return (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
||||
|
||||
const OT::ItemVariationStore &var_store = font->face->table.GDEF->table->get_var_store ();
|
||||
auto *cache = (hb_ot_font_data_t *) var_store.create_cache ();
|
||||
return cache ? cache : (hb_ot_font_data_t *) HB_SHAPER_DATA_SUCCEEDED;
|
||||
return (hb_ot_font_data_t *) var_store.create_cache ();
|
||||
}
|
||||
|
||||
void
|
||||
_hb_ot_shaper_font_data_destroy (hb_ot_font_data_t *data)
|
||||
{
|
||||
if (data == HB_SHAPER_DATA_SUCCEEDED) return;
|
||||
OT::ItemVariationStore::destroy_cache ((OT::ItemVariationStore::cache_t *) data);
|
||||
OT::ItemVariationStore::destroy_cache ((OT::hb_scalar_cache_t *) data);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -651,59 +647,6 @@ hb_ensure_native_direction (hb_buffer_t *buffer)
|
|||
* Substitute
|
||||
*/
|
||||
|
||||
#ifndef HB_NO_VERTICAL
|
||||
static hb_codepoint_t
|
||||
hb_vert_char_for (hb_codepoint_t u)
|
||||
{
|
||||
switch (u >> 8)
|
||||
{
|
||||
case 0x20: switch (u) {
|
||||
case 0x2013u: return 0xfe32u; // EN DASH
|
||||
case 0x2014u: return 0xfe31u; // EM DASH
|
||||
case 0x2025u: return 0xfe30u; // TWO DOT LEADER
|
||||
case 0x2026u: return 0xfe19u; // HORIZONTAL ELLIPSIS
|
||||
} break;
|
||||
case 0x30: switch (u) {
|
||||
case 0x3001u: return 0xfe11u; // IDEOGRAPHIC COMMA
|
||||
case 0x3002u: return 0xfe12u; // IDEOGRAPHIC FULL STOP
|
||||
case 0x3008u: return 0xfe3fu; // LEFT ANGLE BRACKET
|
||||
case 0x3009u: return 0xfe40u; // RIGHT ANGLE BRACKET
|
||||
case 0x300au: return 0xfe3du; // LEFT DOUBLE ANGLE BRACKET
|
||||
case 0x300bu: return 0xfe3eu; // RIGHT DOUBLE ANGLE BRACKET
|
||||
case 0x300cu: return 0xfe41u; // LEFT CORNER BRACKET
|
||||
case 0x300du: return 0xfe42u; // RIGHT CORNER BRACKET
|
||||
case 0x300eu: return 0xfe43u; // LEFT WHITE CORNER BRACKET
|
||||
case 0x300fu: return 0xfe44u; // RIGHT WHITE CORNER BRACKET
|
||||
case 0x3010u: return 0xfe3bu; // LEFT BLACK LENTICULAR BRACKET
|
||||
case 0x3011u: return 0xfe3cu; // RIGHT BLACK LENTICULAR BRACKET
|
||||
case 0x3014u: return 0xfe39u; // LEFT TORTOISE SHELL BRACKET
|
||||
case 0x3015u: return 0xfe3au; // RIGHT TORTOISE SHELL BRACKET
|
||||
case 0x3016u: return 0xfe17u; // LEFT WHITE LENTICULAR BRACKET
|
||||
case 0x3017u: return 0xfe18u; // RIGHT WHITE LENTICULAR BRACKET
|
||||
} break;
|
||||
case 0xfe: switch (u) {
|
||||
case 0xfe4fu: return 0xfe34u; // WAVY LOW LINE
|
||||
} break;
|
||||
case 0xff: switch (u) {
|
||||
case 0xff01u: return 0xfe15u; // FULLWIDTH EXCLAMATION MARK
|
||||
case 0xff08u: return 0xfe35u; // FULLWIDTH LEFT PARENTHESIS
|
||||
case 0xff09u: return 0xfe36u; // FULLWIDTH RIGHT PARENTHESIS
|
||||
case 0xff0cu: return 0xfe10u; // FULLWIDTH COMMA
|
||||
case 0xff1au: return 0xfe13u; // FULLWIDTH COLON
|
||||
case 0xff1bu: return 0xfe14u; // FULLWIDTH SEMICOLON
|
||||
case 0xff1fu: return 0xfe16u; // FULLWIDTH QUESTION MARK
|
||||
case 0xff3bu: return 0xfe47u; // FULLWIDTH LEFT SQUARE BRACKET
|
||||
case 0xff3du: return 0xfe48u; // FULLWIDTH RIGHT SQUARE BRACKET
|
||||
case 0xff3fu: return 0xfe33u; // FULLWIDTH LOW LINE
|
||||
case 0xff5bu: return 0xfe37u; // FULLWIDTH LEFT CURLY BRACKET
|
||||
case 0xff5du: return 0xfe38u; // FULLWIDTH RIGHT CURLY BRACKET
|
||||
} break;
|
||||
}
|
||||
|
||||
return u;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void
|
||||
hb_ot_rotate_chars (const hb_ot_shape_context_t *c)
|
||||
{
|
||||
|
|
@ -729,7 +672,7 @@ hb_ot_rotate_chars (const hb_ot_shape_context_t *c)
|
|||
if (HB_DIRECTION_IS_VERTICAL (c->target_direction) && !c->plan->has_vert)
|
||||
{
|
||||
for (unsigned int i = 0; i < count; i++) {
|
||||
hb_codepoint_t codepoint = hb_vert_char_for (info[i].codepoint);
|
||||
hb_codepoint_t codepoint = hb_unicode_funcs_t::vertical_char_for (info[i].codepoint);
|
||||
if (unlikely (codepoint != info[i].codepoint && c->font->has_glyph (codepoint)))
|
||||
info[i].codepoint = codepoint;
|
||||
}
|
||||
|
|
@ -1054,23 +997,16 @@ hb_ot_position_default (const hb_ot_shape_context_t *c)
|
|||
{
|
||||
c->font->get_glyph_h_advances (count, &info[0].codepoint, sizeof(info[0]),
|
||||
&pos[0].x_advance, sizeof(pos[0]));
|
||||
/* The nil glyph_h_origin() func returns 0, so no need to apply it. */
|
||||
if (c->font->has_glyph_h_origin_func ())
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
c->font->subtract_glyph_h_origin (info[i].codepoint,
|
||||
&pos[i].x_offset,
|
||||
&pos[i].y_offset);
|
||||
// h_origin defaults to zero; only apply it if the font has it.
|
||||
if (c->font->has_glyph_h_origin_func () || c->font->has_glyph_h_origins_func ())
|
||||
c->font->subtract_glyph_h_origins (c->buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
c->font->get_glyph_v_advances (count, &info[0].codepoint, sizeof(info[0]),
|
||||
&pos[0].y_advance, sizeof(pos[0]));
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
c->font->subtract_glyph_v_origin (info[i].codepoint,
|
||||
&pos[i].x_offset,
|
||||
&pos[i].y_offset);
|
||||
}
|
||||
// v_origin defaults to non-zero; apply even if only fallback is there.
|
||||
c->font->subtract_glyph_v_origins (c->buffer);
|
||||
}
|
||||
if (c->buffer->scratch_flags & HB_BUFFER_SCRATCH_FLAG_HAS_SPACE_FALLBACK)
|
||||
_hb_ot_shape_fallback_spaces (c->plan, c->font, c->buffer);
|
||||
|
|
@ -1079,10 +1015,6 @@ hb_ot_position_default (const hb_ot_shape_context_t *c)
|
|||
static inline void
|
||||
hb_ot_position_plan (const hb_ot_shape_context_t *c)
|
||||
{
|
||||
unsigned int count = c->buffer->len;
|
||||
hb_glyph_info_t *info = c->buffer->info;
|
||||
hb_glyph_position_t *pos = c->buffer->pos;
|
||||
|
||||
/* If the font has no GPOS and direction is forward, then when
|
||||
* zeroing mark widths, we shift the mark with it, such that the
|
||||
* mark is positioned hanging over the previous glyph. When
|
||||
|
|
@ -1097,12 +1029,9 @@ hb_ot_position_plan (const hb_ot_shape_context_t *c)
|
|||
|
||||
/* We change glyph origin to what GPOS expects (horizontal), apply GPOS, change it back. */
|
||||
|
||||
/* The nil glyph_h_origin() func returns 0, so no need to apply it. */
|
||||
if (c->font->has_glyph_h_origin_func ())
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
c->font->add_glyph_h_origin (info[i].codepoint,
|
||||
&pos[i].x_offset,
|
||||
&pos[i].y_offset);
|
||||
// h_origin defaults to zero; only apply it if the font has it.
|
||||
if (c->font->has_glyph_h_origin_func () || c->font->has_glyph_h_origins_func ())
|
||||
c->font->add_glyph_h_origins (c->buffer);
|
||||
|
||||
hb_ot_layout_position_start (c->font, c->buffer);
|
||||
|
||||
|
|
@ -1139,12 +1068,9 @@ hb_ot_position_plan (const hb_ot_shape_context_t *c)
|
|||
hb_ot_zero_width_default_ignorables (c->buffer);
|
||||
hb_ot_layout_position_finish_offsets (c->font, c->buffer);
|
||||
|
||||
/* The nil glyph_h_origin() func returns 0, so no need to apply it. */
|
||||
if (c->font->has_glyph_h_origin_func ())
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
c->font->subtract_glyph_h_origin (info[i].codepoint,
|
||||
&pos[i].x_offset,
|
||||
&pos[i].y_offset);
|
||||
// h_origin defaults to zero; only apply it if the font has it.
|
||||
if (c->font->has_glyph_h_origin_func () || c->font->has_glyph_h_origins_func ())
|
||||
c->font->subtract_glyph_h_origins (c->buffer);
|
||||
|
||||
if (c->plan->fallback_mark_positioning)
|
||||
_hb_ot_shape_fallback_mark_position (c->plan, c->font, c->buffer,
|
||||
|
|
|
|||
|
|
@ -654,7 +654,7 @@ postprocess_glyphs_arabic (const hb_ot_shape_plan_t *plan,
|
|||
|
||||
/* https://www.unicode.org/reports/tr53/ */
|
||||
|
||||
static hb_codepoint_t
|
||||
static const hb_codepoint_t
|
||||
modifier_combining_marks[] =
|
||||
{
|
||||
0x0654u, /* ARABIC HAMZA ABOVE */
|
||||
|
|
|
|||
2
thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc
vendored
2
thirdparty/harfbuzz/src/hb-ot-shaper-thai.cc
vendored
|
|
@ -163,7 +163,7 @@ thai_pua_shape (hb_codepoint_t u, thai_action_t action, hb_font_t *font)
|
|||
}
|
||||
|
||||
|
||||
static enum thai_above_state_t
|
||||
static const enum thai_above_state_t
|
||||
{ /* Cluster above looks like: */
|
||||
T0, /* ⣤ */
|
||||
T1, /* ⣼ */
|
||||
|
|
|
|||
|
|
@ -101,8 +101,9 @@
|
|||
|
||||
#ifndef HB_OPTIMIZE_SIZE
|
||||
|
||||
static const uint8_t
|
||||
hb_use_u8[3345] =
|
||||
#include <stdint.h>
|
||||
|
||||
static const uint8_t hb_use_u8[3345]=
|
||||
{
|
||||
16, 50, 51, 51, 51, 52, 51, 83, 118, 131, 57, 58, 59, 195, 211, 62,
|
||||
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
|
||||
|
|
@ -315,8 +316,7 @@ hb_use_u8[3345] =
|
|||
J, HR, G, G, HM, HM, HM, G, O, MPre, MPre, MPst,VMAbv, MBlw, VBlw, O,
|
||||
VBlw,
|
||||
};
|
||||
static const uint16_t
|
||||
hb_use_u16[856] =
|
||||
static const uint16_t hb_use_u16[856]=
|
||||
{
|
||||
0, 0, 1, 2, 0, 3, 0, 3, 0, 0, 4, 5, 0, 6, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0,
|
||||
|
|
@ -374,22 +374,21 @@ hb_use_u16[856] =
|
|||
163,163,163,163,163,163,163,130,
|
||||
};
|
||||
|
||||
static inline unsigned
|
||||
hb_use_b4 (const uint8_t* a, unsigned i)
|
||||
static inline uint8_t hb_use_b4 (const uint8_t* a, unsigned i)
|
||||
{
|
||||
return (a[i>>1]>>((i&1u)<<2))&15u;
|
||||
return (a[i>>1]>>((i&1)<<2))&15;
|
||||
}
|
||||
static inline uint_fast8_t
|
||||
hb_use_get_category (unsigned u)
|
||||
static inline uint8_t hb_use_get_category (unsigned u)
|
||||
{
|
||||
return u<921600u?hb_use_u8[2953+(((hb_use_u8[625+(((hb_use_u16[((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31u))])<<3)+((u>>1>>3)&7u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
|
||||
return u<921600 ? hb_use_u8[2953u+(((hb_use_u8[625u+(((hb_use_u16[((hb_use_u8[113u+(((hb_use_b4(hb_use_u8,u>>1>>3>>3>>5))<<5)+((u>>1>>3>>3)&31))])<<3)+((u>>1>>3)&7)])<<3)+((u>>1)&7))])<<1)+((u)&1))] : O;
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
static const uint8_t
|
||||
hb_use_u8[3657] =
|
||||
#include <stdint.h>
|
||||
|
||||
static const uint8_t hb_use_u8[3657]=
|
||||
{
|
||||
16, 50, 51, 51, 51, 52, 51, 83, 118, 131, 57, 58, 59, 195, 211, 62,
|
||||
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
|
||||
|
|
@ -621,8 +620,7 @@ hb_use_u8[3657] =
|
|||
VMPst, G, G, J, J, J, SB, SE, J, HR, G, G, HM, HM, HM, G,
|
||||
O, MPre, MPre, MPst,VMAbv, MBlw, VBlw, O, VBlw,
|
||||
};
|
||||
static const uint16_t
|
||||
hb_use_u16[486] =
|
||||
static const uint16_t hb_use_u16[486]=
|
||||
{
|
||||
0, 0, 1, 2, 0, 3, 4, 5, 0, 6, 7, 0, 8, 0, 9, 10,
|
||||
11, 12, 10, 13, 14, 10, 10, 15, 16, 17, 18, 19, 20, 21, 22, 23,
|
||||
|
|
@ -657,15 +655,13 @@ hb_use_u16[486] =
|
|||
130,130,163,163,163,130,
|
||||
};
|
||||
|
||||
static inline unsigned
|
||||
hb_use_b4 (const uint8_t* a, unsigned i)
|
||||
static inline uint8_t hb_use_b4 (const uint8_t* a, unsigned i)
|
||||
{
|
||||
return (a[i>>1]>>((i&1u)<<2))&15u;
|
||||
return (a[i>>1]>>((i&1)<<2))&15;
|
||||
}
|
||||
static inline uint_fast8_t
|
||||
hb_use_get_category (unsigned u)
|
||||
static inline uint8_t hb_use_get_category (unsigned u)
|
||||
{
|
||||
return u<921600u?hb_use_u8[3265+(((hb_use_u8[937+(((hb_use_u16[((hb_use_u8[369+(((hb_use_u8[113+(((hb_use_b4(hb_use_u8,u>>1>>3>>1>>3>>4))<<4)+((u>>1>>3>>1>>3)&15u))])<<3)+((u>>1>>3>>1)&7u))])<<1)+((u>>1>>3)&1u)])<<3)+((u>>1)&7u))])<<1)+((u)&1u))]:O;
|
||||
return u<921600 ? hb_use_u8[3265u+(((hb_use_u8[937u+(((hb_use_u16[((hb_use_u8[369u+(((hb_use_u8[113u+(((hb_use_b4(hb_use_u8,u>>1>>3>>1>>3>>4))<<4)+((u>>1>>3>>1>>3)&15))])<<3)+((u>>1>>3>>1)&7))])<<1)+((u>>1>>3)&1)])<<3)+((u>>1)&7))])<<1)+((u)&1))] : O;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
4
thirdparty/harfbuzz/src/hb-ot-tag-table.hh
vendored
4
thirdparty/harfbuzz/src/hb-ot-tag-table.hh
vendored
|
|
@ -6,8 +6,8 @@
|
|||
*
|
||||
* on files with these headers:
|
||||
*
|
||||
* <meta name="updated_at" content="2024-12-06 06:35 AM" />
|
||||
* File-Date: 2025-01-21
|
||||
* <meta name="updated_at" content="2024-12-06T06:35:00Z" />
|
||||
* File-Date: 2025-03-10
|
||||
*/
|
||||
|
||||
#ifndef HB_OT_TAG_TABLE_HH
|
||||
|
|
|
|||
141
thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh
vendored
141
thirdparty/harfbuzz/src/hb-ot-var-avar-table.hh
vendored
|
|
@ -143,10 +143,13 @@ struct AxisValueMap
|
|||
|
||||
struct SegmentMaps : Array16Of<AxisValueMap>
|
||||
{
|
||||
int map (int value, unsigned int from_offset = 0, unsigned int to_offset = 1) const
|
||||
float map_float (float value, unsigned int from_offset = 0, unsigned int to_offset = 1) const
|
||||
{
|
||||
#define fromCoord coords[from_offset].to_int ()
|
||||
#define toCoord coords[to_offset].to_int ()
|
||||
#define fromCoord coords[from_offset].to_float ()
|
||||
#define toCoord coords[to_offset].to_float ()
|
||||
|
||||
const auto *map = arrayZ;
|
||||
|
||||
/* The following special-cases are not part of OpenType, which requires
|
||||
* that at least -1, 0, and +1 must be mapped. But we include these as
|
||||
* part of a better error recovery scheme. */
|
||||
|
|
@ -155,47 +158,98 @@ struct SegmentMaps : Array16Of<AxisValueMap>
|
|||
if (!len)
|
||||
return value;
|
||||
else /* len == 1*/
|
||||
return value - arrayZ[0].fromCoord + arrayZ[0].toCoord;
|
||||
return value - map[0].fromCoord + map[0].toCoord;
|
||||
}
|
||||
|
||||
if (value <= arrayZ[0].fromCoord)
|
||||
return value - arrayZ[0].fromCoord + arrayZ[0].toCoord;
|
||||
// At least two mappings now.
|
||||
|
||||
unsigned int i;
|
||||
unsigned int count = len - 1;
|
||||
for (i = 1; i < count && value > arrayZ[i].fromCoord; i++)
|
||||
;
|
||||
/* CoreText is wild...
|
||||
* PingFangUI avar needs all this special-casing...
|
||||
* So we implement an extended version of the spec here,
|
||||
* which is more robust and more likely to be compatible with
|
||||
* the wild. */
|
||||
|
||||
if (value >= arrayZ[i].fromCoord)
|
||||
return value - arrayZ[i].fromCoord + arrayZ[i].toCoord;
|
||||
unsigned start = 0;
|
||||
unsigned end = len;
|
||||
if (map[start].fromCoord == -1 && map[start].toCoord == -1 && map[start+1].fromCoord == -1)
|
||||
start++;
|
||||
if (map[end-1].fromCoord == +1 && map[end-1].toCoord == +1 && map[end-2].fromCoord == +1)
|
||||
end--;
|
||||
|
||||
if (unlikely (arrayZ[i-1].fromCoord == arrayZ[i].fromCoord))
|
||||
return arrayZ[i-1].toCoord;
|
||||
/* Look for exact match first, and do lots of special-casing. */
|
||||
unsigned i;
|
||||
for (i = start; i < end; i++)
|
||||
if (value == map[i].fromCoord)
|
||||
break;
|
||||
if (i < end)
|
||||
{
|
||||
// There's at least one exact match. See if there are more.
|
||||
unsigned j = i;
|
||||
for (; j + 1 < end; j++)
|
||||
if (value != map[j + 1].fromCoord)
|
||||
break;
|
||||
|
||||
// [i,j] inclusive are all exact matches:
|
||||
|
||||
// If there's only one, return it. This is the only spec-compliant case.
|
||||
if (i == j)
|
||||
return map[i].toCoord;
|
||||
// If there's exactly three, return the middle one.
|
||||
if (i + 2 == j)
|
||||
return map[i + 1].toCoord;
|
||||
|
||||
// Ignore the middle ones. Return the one mapping closer to 0.
|
||||
if (value < 0) return map[j].toCoord;
|
||||
if (value > 0) return map[i].toCoord;
|
||||
|
||||
// Mapping 0? CoreText seems confused. It seems to prefer 0 here...
|
||||
// So we'll just return the smallest one. lol
|
||||
return fabsf (map[i].toCoord) < fabsf (map[j].toCoord) ? map[i].toCoord : map[j].toCoord;
|
||||
|
||||
// Mapping 0? Return one not mapping to 0.
|
||||
if (map[i].toCoord == 0)
|
||||
return map[j].toCoord;
|
||||
else
|
||||
return map[i].toCoord;
|
||||
}
|
||||
|
||||
/* There's at least two and we're not an exact match. Prepare to lerp. */
|
||||
|
||||
// Find the segment we're in.
|
||||
for (i = start; i < end; i++)
|
||||
if (value < map[i].fromCoord)
|
||||
break;
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
// Value before all segments; Shift.
|
||||
return value - map[0].fromCoord + map[0].toCoord;
|
||||
}
|
||||
if (i == end)
|
||||
{
|
||||
// Value after all segments; Shift.
|
||||
return value - map[end - 1].fromCoord + map[end - 1].toCoord;
|
||||
}
|
||||
|
||||
// Actually interpolate.
|
||||
auto &before = map[i-1];
|
||||
auto &after = map[i];
|
||||
float denom = after.fromCoord - before.fromCoord; // Can't be zero by now.
|
||||
return before.toCoord + ((after.toCoord - before.toCoord) * (value - before.fromCoord)) / denom;
|
||||
|
||||
int denom = arrayZ[i].fromCoord - arrayZ[i-1].fromCoord;
|
||||
return roundf (arrayZ[i-1].toCoord + ((float) (arrayZ[i].toCoord - arrayZ[i-1].toCoord) *
|
||||
(value - arrayZ[i-1].fromCoord)) / denom);
|
||||
#undef toCoord
|
||||
#undef fromCoord
|
||||
}
|
||||
|
||||
int unmap (int value) const { return map (value, 1, 0); }
|
||||
float unmap_float (float value) const { return map_float (value, 1, 0); }
|
||||
|
||||
|
||||
// TODO Kill this.
|
||||
Triple unmap_axis_range (const Triple& axis_range) const
|
||||
{
|
||||
F2DOT14 val, unmapped_val;
|
||||
|
||||
val.set_float (axis_range.minimum);
|
||||
unmapped_val.set_int (unmap (val.to_int ()));
|
||||
float unmapped_min = unmapped_val.to_float ();
|
||||
|
||||
val.set_float (axis_range.middle);
|
||||
unmapped_val.set_int (unmap (val.to_int ()));
|
||||
float unmapped_middle = unmapped_val.to_float ();
|
||||
|
||||
val.set_float (axis_range.maximum);
|
||||
unmapped_val.set_int (unmap (val.to_int ()));
|
||||
float unmapped_max = unmapped_val.to_float ();
|
||||
float unmapped_min = unmap_float (axis_range.minimum);
|
||||
float unmapped_middle = unmap_float (axis_range.middle);
|
||||
float unmapped_max = unmap_float (axis_range.maximum);
|
||||
|
||||
return Triple{(double) unmapped_min, (double) unmapped_middle, (double) unmapped_max};
|
||||
}
|
||||
|
|
@ -203,6 +257,11 @@ struct SegmentMaps : Array16Of<AxisValueMap>
|
|||
bool subset (hb_subset_context_t *c, hb_tag_t axis_tag) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
||||
/* This function cannot work on avar2 table (and currently doesn't).
|
||||
* We should instead keep the design coords in the shape plan and use
|
||||
* those. unmap_axis_range needs to be killed. */
|
||||
|
||||
/* avar mapped normalized axis range*/
|
||||
Triple *axis_range;
|
||||
if (!c->plan->axes_location.has (axis_tag, &axis_range))
|
||||
|
|
@ -304,14 +363,14 @@ struct avar
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
void map_coords (int *coords, unsigned int coords_length) const
|
||||
void map_coords_16_16 (int *coords, unsigned int coords_length) const
|
||||
{
|
||||
unsigned int count = hb_min (coords_length, axisCount);
|
||||
|
||||
const SegmentMaps *map = &firstAxisSegmentMaps;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
coords[i] = map->map (coords[i]);
|
||||
coords[i] = roundf (map->map_float (coords[i] / 65536.f) * 65536.f);
|
||||
map = &StructAfter<SegmentMaps> (*map);
|
||||
}
|
||||
|
||||
|
|
@ -336,8 +395,8 @@ struct avar
|
|||
int v = coords[i];
|
||||
uint32_t varidx = varidx_map.map (i);
|
||||
float delta = var_store.get_delta (varidx, coords, coords_length, var_store_cache);
|
||||
v += roundf (delta);
|
||||
v = hb_clamp (v, -(1<<14), +(1<<14));
|
||||
v += roundf (delta * 4); // 2.14 -> 16.16
|
||||
v = hb_clamp (v, -(1<<16), +(1<<16));
|
||||
out.push (v);
|
||||
}
|
||||
for (unsigned i = 0; i < coords_length; i++)
|
||||
|
|
@ -347,18 +406,6 @@ struct avar
|
|||
#endif
|
||||
}
|
||||
|
||||
void unmap_coords (int *coords, unsigned int coords_length) const
|
||||
{
|
||||
unsigned int count = hb_min (coords_length, axisCount);
|
||||
|
||||
const SegmentMaps *map = &firstAxisSegmentMaps;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
coords[i] = map->unmap (coords[i]);
|
||||
map = &StructAfter<SegmentMaps> (*map);
|
||||
}
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
|
|
|
|||
115
thirdparty/harfbuzz/src/hb-ot-var-common.hh
vendored
115
thirdparty/harfbuzz/src/hb-ot-var-common.hh
vendored
|
|
@ -33,7 +33,6 @@
|
|||
|
||||
namespace OT {
|
||||
|
||||
|
||||
/* https://docs.microsoft.com/en-us/typography/opentype/spec/otvarcommonformats#tuplevariationheader */
|
||||
struct TupleVariationHeader
|
||||
{
|
||||
|
|
@ -53,7 +52,7 @@ struct TupleVariationHeader
|
|||
{
|
||||
const F2DOT14 *peak_tuple = nullptr;
|
||||
if (has_peak ())
|
||||
peak_tuple = get_peak_tuple (axis_count).arrayZ;
|
||||
peak_tuple = get_peak_tuple (axis_count);
|
||||
else
|
||||
{
|
||||
unsigned int index = get_index ();
|
||||
|
|
@ -68,8 +67,8 @@ struct TupleVariationHeader
|
|||
|
||||
if (has_interm)
|
||||
{
|
||||
start_tuple = get_start_tuple (axis_count).arrayZ;
|
||||
end_tuple = get_end_tuple (axis_count).arrayZ;
|
||||
start_tuple = get_start_tuple (axis_count);
|
||||
end_tuple = get_end_tuple (axis_count);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < axis_count; i++)
|
||||
|
|
@ -98,60 +97,56 @@ struct TupleVariationHeader
|
|||
return true;
|
||||
}
|
||||
|
||||
HB_ALWAYS_INLINE
|
||||
double calculate_scalar (hb_array_t<const int> coords, unsigned int coord_count,
|
||||
const hb_array_t<const F2DOT14> shared_tuples,
|
||||
const hb_vector_t<hb_pair_t<int,int>> *shared_tuple_active_idx = nullptr) const
|
||||
hb_scalar_cache_t *shared_tuple_scalar_cache = nullptr) const
|
||||
{
|
||||
unsigned tuple_index = tupleIndex;
|
||||
|
||||
const F2DOT14 *peak_tuple;
|
||||
|
||||
unsigned start_idx = 0;
|
||||
unsigned end_idx = coord_count;
|
||||
unsigned step = 1;
|
||||
bool has_interm = tuple_index & TuppleIndex::IntermediateRegion; // Inlined for performance
|
||||
if (unlikely (has_interm))
|
||||
shared_tuple_scalar_cache = nullptr;
|
||||
|
||||
if (has_peak ())
|
||||
peak_tuple = get_peak_tuple (coord_count).arrayZ;
|
||||
if (unlikely (tuple_index & TuppleIndex::EmbeddedPeakTuple)) // Inlined for performance
|
||||
{
|
||||
peak_tuple = get_peak_tuple (coord_count);
|
||||
shared_tuple_scalar_cache = nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int index = get_index ();
|
||||
unsigned int index = tuple_index & TuppleIndex::TupleIndexMask; // Inlined for performance
|
||||
|
||||
float scalar;
|
||||
if (shared_tuple_scalar_cache &&
|
||||
shared_tuple_scalar_cache->get (index, &scalar))
|
||||
return (double) scalar;
|
||||
|
||||
if (unlikely ((index + 1) * coord_count > shared_tuples.length))
|
||||
return 0.0;
|
||||
peak_tuple = shared_tuples.sub_array (coord_count * index, coord_count).arrayZ;
|
||||
peak_tuple = shared_tuples.arrayZ + (coord_count * index);
|
||||
|
||||
if (shared_tuple_active_idx)
|
||||
{
|
||||
if (unlikely (index >= shared_tuple_active_idx->length))
|
||||
return 0.0;
|
||||
auto _ = (*shared_tuple_active_idx).arrayZ[index];
|
||||
if (_.second != -1)
|
||||
{
|
||||
start_idx = _.first;
|
||||
end_idx = _.second + 1;
|
||||
step = _.second - _.first;
|
||||
}
|
||||
else if (_.first != -1)
|
||||
{
|
||||
start_idx = _.first;
|
||||
end_idx = start_idx + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const F2DOT14 *start_tuple = nullptr;
|
||||
const F2DOT14 *end_tuple = nullptr;
|
||||
bool has_interm = has_intermediate ();
|
||||
|
||||
if (has_interm)
|
||||
{
|
||||
start_tuple = get_start_tuple (coord_count).arrayZ;
|
||||
end_tuple = get_end_tuple (coord_count).arrayZ;
|
||||
start_tuple = get_start_tuple (coord_count);
|
||||
end_tuple = get_end_tuple (coord_count);
|
||||
}
|
||||
|
||||
double scalar = 1.0;
|
||||
for (unsigned int i = start_idx; i < end_idx; i += step)
|
||||
for (unsigned int i = 0; i < coord_count; i++)
|
||||
{
|
||||
int peak = peak_tuple[i].to_int ();
|
||||
if (!peak) continue;
|
||||
|
||||
int v = coords[i];
|
||||
if (!v) { scalar = 0.0; break; }
|
||||
if (v == peak) continue;
|
||||
|
||||
if (has_interm)
|
||||
|
|
@ -160,16 +155,18 @@ struct TupleVariationHeader
|
|||
int end = end_tuple[i].to_int ();
|
||||
if (unlikely (start > peak || peak > end ||
|
||||
(start < 0 && end > 0 && peak))) continue;
|
||||
if (v < start || v > end) return 0.0;
|
||||
if (v < start || v > end) { scalar = 0.0; break; }
|
||||
if (v < peak)
|
||||
{ if (peak != start) scalar *= (double) (v - start) / (peak - start); }
|
||||
else
|
||||
{ if (peak != end) scalar *= (double) (end - v) / (end - peak); }
|
||||
}
|
||||
else if (!v || v < hb_min (0, peak) || v > hb_max (0, peak)) return 0.0;
|
||||
else if (v < hb_min (0, peak) || v > hb_max (0, peak)) { scalar = 0.0; break; }
|
||||
else
|
||||
scalar *= (double) v / peak;
|
||||
}
|
||||
if (shared_tuple_scalar_cache)
|
||||
shared_tuple_scalar_cache->set (get_index (), scalar);
|
||||
return scalar;
|
||||
}
|
||||
|
||||
|
|
@ -194,12 +191,14 @@ struct TupleVariationHeader
|
|||
|
||||
hb_array_t<const F2DOT14> get_all_tuples (unsigned axis_count) const
|
||||
{ return StructAfter<UnsizedArrayOf<F2DOT14>> (tupleIndex).as_array ((has_peak () + has_intermediate () * 2) * axis_count); }
|
||||
hb_array_t<const F2DOT14> get_peak_tuple (unsigned axis_count) const
|
||||
{ return get_all_tuples (axis_count).sub_array (0, axis_count); }
|
||||
hb_array_t<const F2DOT14> get_start_tuple (unsigned axis_count) const
|
||||
{ return get_all_tuples (axis_count).sub_array (has_peak () * axis_count, axis_count); }
|
||||
hb_array_t<const F2DOT14> get_end_tuple (unsigned axis_count) const
|
||||
{ return get_all_tuples (axis_count).sub_array (has_peak () * axis_count + axis_count, axis_count); }
|
||||
const F2DOT14* get_all_tuples_base (unsigned axis_count) const
|
||||
{ return StructAfter<UnsizedArrayOf<F2DOT14>> (tupleIndex).arrayZ; }
|
||||
const F2DOT14* get_peak_tuple (unsigned axis_count) const
|
||||
{ return get_all_tuples_base (axis_count); }
|
||||
const F2DOT14* get_start_tuple (unsigned axis_count) const
|
||||
{ return get_all_tuples_base (axis_count) + has_peak () * axis_count; }
|
||||
const F2DOT14* get_end_tuple (unsigned axis_count) const
|
||||
{ return get_all_tuples_base (axis_count) + has_peak () * axis_count + axis_count; }
|
||||
|
||||
HBUINT16 varDataSize; /* The size in bytes of the serialized
|
||||
* data for this tuple variation table. */
|
||||
|
|
@ -1330,7 +1329,7 @@ struct TupleVariationData
|
|||
{
|
||||
var_data_bytes = var_data_bytes_;
|
||||
var_data = var_data_bytes_.as<TupleVariationData> ();
|
||||
index = 0;
|
||||
tuples_left = var_data->tupleVarCount.get_count ();
|
||||
axis_count = axis_count_;
|
||||
current_tuple = &var_data->get_tuple_var_header ();
|
||||
data_offset = 0;
|
||||
|
|
@ -1349,30 +1348,41 @@ struct TupleVariationData
|
|||
return true;
|
||||
}
|
||||
|
||||
bool is_valid () const
|
||||
bool is_valid ()
|
||||
{
|
||||
return (index < var_data->tupleVarCount.get_count ()) &&
|
||||
var_data_bytes.check_range (current_tuple, TupleVariationHeader::min_size) &&
|
||||
var_data_bytes.check_range (current_tuple, hb_max (current_tuple->get_data_size (),
|
||||
current_tuple->get_size (axis_count)));
|
||||
if (unlikely (tuples_left <= 0))
|
||||
return false;
|
||||
|
||||
current_tuple_size = TupleVariationHeader::min_size;
|
||||
if (unlikely (!var_data_bytes.check_range (current_tuple, current_tuple_size)))
|
||||
return false;
|
||||
|
||||
current_tuple_size = current_tuple->get_size (axis_count);
|
||||
if (unlikely (!var_data_bytes.check_range (current_tuple, current_tuple_size)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
HB_ALWAYS_INLINE
|
||||
bool move_to_next ()
|
||||
{
|
||||
data_offset += current_tuple->get_data_size ();
|
||||
current_tuple = ¤t_tuple->get_next (axis_count);
|
||||
index++;
|
||||
current_tuple = &StructAtOffset<TupleVariationHeader> (current_tuple, current_tuple_size);
|
||||
tuples_left--;
|
||||
return is_valid ();
|
||||
}
|
||||
|
||||
// TODO: Make it return (sanitized) hb_bytes_t
|
||||
const HBUINT8 *get_serialized_data () const
|
||||
{ return &(table_base+var_data->data) + data_offset; }
|
||||
|
||||
private:
|
||||
signed tuples_left;
|
||||
const TupleVariationData *var_data;
|
||||
unsigned int index;
|
||||
unsigned int axis_count;
|
||||
unsigned int data_offset;
|
||||
unsigned int current_tuple_size;
|
||||
const void *table_base;
|
||||
|
||||
public:
|
||||
|
|
@ -1449,9 +1459,10 @@ struct TupleVariationData
|
|||
static bool decompile_deltas (const HBUINT8 *&p /* IN/OUT */,
|
||||
hb_vector_t<T> &deltas /* IN/OUT */,
|
||||
const HBUINT8 *end,
|
||||
bool consume_all = false)
|
||||
bool consume_all = false,
|
||||
unsigned start = 0)
|
||||
{
|
||||
return TupleValues::decompile (p, deltas, end, consume_all);
|
||||
return TupleValues::decompile (p, deltas, end, consume_all, start);
|
||||
}
|
||||
|
||||
bool has_data () const { return tupleVarCount; }
|
||||
|
|
|
|||
29
thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
vendored
29
thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
vendored
|
|
@ -78,7 +78,7 @@ struct InstanceRecord
|
|||
return false;
|
||||
if (!axes_location->has (*axis_tag))
|
||||
continue;
|
||||
|
||||
|
||||
Triple axis_limit = axes_location->get (*axis_tag);
|
||||
if (!axis_coord_pinned_or_within_axis_range (coords, i, axis_limit))
|
||||
return false;
|
||||
|
|
@ -106,7 +106,7 @@ struct InstanceRecord
|
|||
{
|
||||
if (!axis_coord_pinned_or_within_axis_range (coords, i, *axis_limit))
|
||||
return_trace (false);
|
||||
|
||||
|
||||
//skip pinned axis
|
||||
if (axis_limit->is_point ())
|
||||
continue;
|
||||
|
|
@ -179,7 +179,7 @@ struct AxisRecord
|
|||
|
||||
hb_tag_t get_axis_tag () const { return axisTag; }
|
||||
|
||||
int normalize_axis_value (float v) const
|
||||
float normalize_axis_value (float v) const
|
||||
{
|
||||
float min_value, default_value, max_value;
|
||||
get_coordinates (min_value, default_value, max_value);
|
||||
|
|
@ -189,23 +189,9 @@ struct AxisRecord
|
|||
if (v == default_value)
|
||||
return 0;
|
||||
else if (v < default_value)
|
||||
v = (v - default_value) / (default_value - min_value);
|
||||
return (v - default_value) / (default_value - min_value);
|
||||
else
|
||||
v = (v - default_value) / (max_value - default_value);
|
||||
return roundf (v * 16384.f);
|
||||
}
|
||||
|
||||
float unnormalize_axis_value (int v) const
|
||||
{
|
||||
float min_value, default_value, max_value;
|
||||
get_coordinates (min_value, default_value, max_value);
|
||||
|
||||
if (v == 0)
|
||||
return default_value;
|
||||
else if (v < 0)
|
||||
return v * (default_value - min_value) / 16384.f + default_value;
|
||||
else
|
||||
return v * (max_value - default_value) / 16384.f + default_value;
|
||||
return (v - default_value) / (max_value - default_value);
|
||||
}
|
||||
|
||||
hb_ot_name_id_t get_name_id () const { return axisNameID; }
|
||||
|
|
@ -341,12 +327,9 @@ struct fvar
|
|||
return axes.lfind (tag, &i) && ((void) axes[i].get_axis_info (i, info), true);
|
||||
}
|
||||
|
||||
int normalize_axis_value (unsigned int axis_index, float v) const
|
||||
float normalize_axis_value (unsigned int axis_index, float v) const
|
||||
{ return get_axes ()[axis_index].normalize_axis_value (v); }
|
||||
|
||||
float unnormalize_axis_value (unsigned int axis_index, int v) const
|
||||
{ return get_axes ()[axis_index].unnormalize_axis_value (v); }
|
||||
|
||||
unsigned int get_instance_count () const { return instanceCount; }
|
||||
|
||||
hb_ot_name_id_t get_instance_subfamily_name_id (unsigned int instance_index) const
|
||||
|
|
|
|||
54
thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
vendored
54
thirdparty/harfbuzz/src/hb-ot-var-gvar-table.hh
vendored
|
|
@ -582,6 +582,17 @@ struct gvar_GVAR
|
|||
public:
|
||||
struct accelerator_t
|
||||
{
|
||||
|
||||
hb_scalar_cache_t *create_cache () const
|
||||
{
|
||||
return hb_scalar_cache_t::create (table->sharedTupleCount);
|
||||
}
|
||||
|
||||
static void destroy_cache (hb_scalar_cache_t *cache)
|
||||
{
|
||||
hb_scalar_cache_t::destroy (cache);
|
||||
}
|
||||
|
||||
bool has_data () const { return table->has_data (); }
|
||||
|
||||
accelerator_t (hb_face_t *face)
|
||||
|
|
@ -589,36 +600,6 @@ struct gvar_GVAR
|
|||
table = hb_sanitize_context_t ().reference_table<gvar_GVAR> (face);
|
||||
/* If sanitize failed, set glyphCount to 0. */
|
||||
glyphCount = table->version.to_int () ? face->get_num_glyphs () : 0;
|
||||
|
||||
/* For shared tuples that only have one or two axes active, shared the index
|
||||
* of that axis as a cache. This will speed up caclulate_scalar() a lot
|
||||
* for fonts with lots of axes and many "monovar" or "duovar" tuples. */
|
||||
hb_array_t<const F2DOT14> shared_tuples = (table+table->sharedTuples).as_array (table->sharedTupleCount * table->axisCount);
|
||||
unsigned count = table->sharedTupleCount;
|
||||
if (unlikely (!shared_tuple_active_idx.resize (count, false))) return;
|
||||
unsigned axis_count = table->axisCount;
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
hb_array_t<const F2DOT14> tuple = shared_tuples.sub_array (axis_count * i, axis_count);
|
||||
int idx1 = -1, idx2 = -1;
|
||||
for (unsigned j = 0; j < axis_count; j++)
|
||||
{
|
||||
const F2DOT14 &peak = tuple.arrayZ[j];
|
||||
if (peak.to_int () != 0)
|
||||
{
|
||||
if (idx1 == -1)
|
||||
idx1 = j;
|
||||
else if (idx2 == -1)
|
||||
idx2 = j;
|
||||
else
|
||||
{
|
||||
idx1 = idx2 = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
shared_tuple_active_idx.arrayZ[i] = {idx1, idx2};
|
||||
}
|
||||
}
|
||||
~accelerator_t () { table.destroy (); }
|
||||
|
||||
|
|
@ -655,6 +636,7 @@ struct gvar_GVAR
|
|||
hb_array_t<const int> coords,
|
||||
const hb_array_t<contour_point_t> points,
|
||||
hb_glyf_scratch_t &scratch,
|
||||
hb_scalar_cache_t *gvar_cache = nullptr,
|
||||
bool phantom_only = false) const
|
||||
{
|
||||
if (unlikely (glyph >= glyphCount)) return true;
|
||||
|
|
@ -690,10 +672,12 @@ struct gvar_GVAR
|
|||
|
||||
unsigned count = points.length;
|
||||
bool flush = false;
|
||||
|
||||
do
|
||||
{
|
||||
float scalar = iterator.current_tuple->calculate_scalar (coords, num_coords, shared_tuples,
|
||||
&shared_tuple_active_idx);
|
||||
gvar_cache);
|
||||
|
||||
if (scalar == 0.f) continue;
|
||||
const HBUINT8 *p = iterator.get_serialized_data ();
|
||||
unsigned int length = iterator.current_tuple->get_data_size ();
|
||||
|
|
@ -717,11 +701,12 @@ struct gvar_GVAR
|
|||
const hb_array_t<unsigned int> &indices = has_private_points ? private_indices : shared_indices;
|
||||
|
||||
bool apply_to_all = (indices.length == 0);
|
||||
unsigned int num_deltas = apply_to_all ? points.length : indices.length;
|
||||
unsigned num_deltas = apply_to_all ? points.length : indices.length;
|
||||
unsigned start_deltas = (phantom_only && num_deltas >= 4 ? num_deltas - 4 : 0);
|
||||
if (unlikely (!x_deltas.resize (num_deltas, false))) return false;
|
||||
if (unlikely (!GlyphVariationData::decompile_deltas (p, x_deltas, end))) return false;
|
||||
if (unlikely (!GlyphVariationData::decompile_deltas (p, x_deltas, end, false, start_deltas))) return false;
|
||||
if (unlikely (!y_deltas.resize (num_deltas, false))) return false;
|
||||
if (unlikely (!GlyphVariationData::decompile_deltas (p, y_deltas, end))) return false;
|
||||
if (unlikely (!GlyphVariationData::decompile_deltas (p, y_deltas, end, false, start_deltas))) return false;
|
||||
|
||||
if (!apply_to_all)
|
||||
{
|
||||
|
|
@ -884,7 +869,6 @@ struct gvar_GVAR
|
|||
private:
|
||||
hb_blob_ptr_t<gvar_GVAR> table;
|
||||
unsigned glyphCount;
|
||||
hb_vector_t<hb_pair_t<int, int>> shared_tuple_active_idx;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
|
|
|||
31
thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh
vendored
31
thirdparty/harfbuzz/src/hb-ot-var-hvar-table.hh
vendored
|
|
@ -156,7 +156,7 @@ struct index_map_subset_plan_t
|
|||
unsigned outer = (*new_varidx) >> 16;
|
||||
unsigned bit_count = (outer == 0) ? 1 : hb_bit_storage (outer);
|
||||
outer_bit_count = hb_max (bit_count, outer_bit_count);
|
||||
|
||||
|
||||
unsigned inner = (*new_varidx) & 0xFFFF;
|
||||
bit_count = (inner == 0) ? 1 : hb_bit_storage (inner);
|
||||
inner_bit_count = hb_max (bit_count, inner_bit_count);
|
||||
|
|
@ -284,6 +284,8 @@ struct HVARVVAR
|
|||
static constexpr hb_tag_t HVARTag = HB_OT_TAG_HVAR;
|
||||
static constexpr hb_tag_t VVARTag = HB_OT_TAG_VVAR;
|
||||
|
||||
bool has_data () const { return version.major != 0; }
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
|
@ -382,9 +384,10 @@ struct HVARVVAR
|
|||
hvar_plan.index_map_plans.as_array ()));
|
||||
}
|
||||
|
||||
HB_ALWAYS_INLINE
|
||||
float get_advance_delta_unscaled (hb_codepoint_t glyph,
|
||||
const int *coords, unsigned int coord_count,
|
||||
ItemVariationStore::cache_t *store_cache = nullptr) const
|
||||
hb_scalar_cache_t *store_cache = nullptr) const
|
||||
{
|
||||
uint32_t varidx = (this+advMap).map (glyph);
|
||||
return (this+varStore).get_delta (varidx,
|
||||
|
|
@ -392,16 +395,6 @@ struct HVARVVAR
|
|||
store_cache);
|
||||
}
|
||||
|
||||
bool get_lsb_delta_unscaled (hb_codepoint_t glyph,
|
||||
const int *coords, unsigned int coord_count,
|
||||
float *lsb) const
|
||||
{
|
||||
if (!lsbMap) return false;
|
||||
uint32_t varidx = (this+lsbMap).map (glyph);
|
||||
*lsb = (this+varStore).get_delta (varidx, coords, coord_count);
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
FixedVersion<>version; /* Version of the metrics variation table
|
||||
* initially set to 0x00010000u */
|
||||
|
|
@ -454,14 +447,16 @@ struct VVAR : HVARVVAR {
|
|||
|
||||
bool subset (hb_subset_context_t *c) const { return HVARVVAR::_subset<VVAR> (c); }
|
||||
|
||||
bool get_vorg_delta_unscaled (hb_codepoint_t glyph,
|
||||
const int *coords, unsigned int coord_count,
|
||||
float *delta) const
|
||||
HB_ALWAYS_INLINE
|
||||
float get_vorg_delta_unscaled (hb_codepoint_t glyph,
|
||||
const int *coords, unsigned int coord_count,
|
||||
hb_scalar_cache_t *store_cache = nullptr) const
|
||||
{
|
||||
if (!vorgMap) return false;
|
||||
if (!vorgMap) return 0.f;
|
||||
uint32_t varidx = (this+vorgMap).map (glyph);
|
||||
*delta = (this+varStore).get_delta (varidx, coords, coord_count);
|
||||
return true;
|
||||
return (this+varStore).get_delta (varidx,
|
||||
coords, coord_count,
|
||||
store_cache);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
|
|||
26
thirdparty/harfbuzz/src/hb-ot-var.cc
vendored
26
thirdparty/harfbuzz/src/hb-ot-var.cc
vendored
|
|
@ -70,7 +70,7 @@ hb_ot_var_has_data (hb_face_t *face)
|
|||
* hb_ot_var_get_axis_count:
|
||||
* @face: The #hb_face_t to work on
|
||||
*
|
||||
* Fetches the number of OpenType variation axes included in the face.
|
||||
* Fetches the number of OpenType variation axes included in the face.
|
||||
*
|
||||
* Return value: the number of variation axes defined
|
||||
*
|
||||
|
|
@ -183,7 +183,7 @@ hb_ot_var_find_axis_info (hb_face_t *face,
|
|||
* hb_ot_var_get_named_instance_count:
|
||||
* @face: The #hb_face_t to work on
|
||||
*
|
||||
* Fetches the number of named instances included in the face.
|
||||
* Fetches the number of named instances included in the face.
|
||||
*
|
||||
* Return value: the number of named instances defined
|
||||
*
|
||||
|
|
@ -263,7 +263,7 @@ hb_ot_var_named_instance_get_design_coords (hb_face_t *face,
|
|||
* @face: The #hb_face_t to work on
|
||||
* @variations: The array of variations to normalize
|
||||
* @variations_length: The number of variations to normalize
|
||||
* @coords: (out) (array length=coords_length): The array of normalized coordinates
|
||||
* @coords: (out) (array length=coords_length): The array of normalized coordinates
|
||||
* @coords_length: The length of the coordinate array
|
||||
*
|
||||
* Normalizes all of the coordinates in the given list of variation axes.
|
||||
|
|
@ -286,10 +286,14 @@ hb_ot_var_normalize_variations (hb_face_t *face,
|
|||
hb_ot_var_axis_info_t info;
|
||||
if (hb_ot_var_find_axis_info (face, variations[i].tag, &info) &&
|
||||
info.axis_index < coords_length)
|
||||
coords[info.axis_index] = fvar.normalize_axis_value (info.axis_index, variations[i].value);
|
||||
coords[info.axis_index] = roundf (fvar.normalize_axis_value (info.axis_index, variations[i].value) * 65536.0f);
|
||||
}
|
||||
|
||||
face->table.avar->map_coords (coords, coords_length);
|
||||
face->table.avar->map_coords_16_16 (coords, coords_length);
|
||||
|
||||
// Round to 2.14
|
||||
for (unsigned i = 0; i < coords_length; i++)
|
||||
coords[i] = (coords[i] + 2) >> 2;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -309,6 +313,10 @@ hb_ot_var_normalize_variations (hb_face_t *face,
|
|||
* Any additional scaling defined in the face's `avar` table is also
|
||||
* applied, as described at https://docs.microsoft.com/en-us/typography/opentype/spec/avar
|
||||
*
|
||||
* Note: @coords_length must be the same as the number of axes in the face, as
|
||||
* for example returned by hb_ot_var_get_axis_count().
|
||||
* Otherwise, the behavior is undefined.
|
||||
*
|
||||
* Since: 1.4.2
|
||||
**/
|
||||
void
|
||||
|
|
@ -319,9 +327,13 @@ hb_ot_var_normalize_coords (hb_face_t *face,
|
|||
{
|
||||
const OT::fvar &fvar = *face->table.fvar;
|
||||
for (unsigned int i = 0; i < coords_length; i++)
|
||||
normalized_coords[i] = fvar.normalize_axis_value (i, design_coords[i]);
|
||||
normalized_coords[i] = roundf (fvar.normalize_axis_value (i, design_coords[i]) * 65536.0f);
|
||||
|
||||
face->table.avar->map_coords (normalized_coords, coords_length);
|
||||
face->table.avar->map_coords_16_16 (normalized_coords, coords_length);
|
||||
|
||||
// Round to 2.14
|
||||
for (unsigned i = 0; i < coords_length; i++)
|
||||
normalized_coords[i] = (normalized_coords[i] + 2) >> 2;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
1
thirdparty/harfbuzz/src/hb-ot-vorg-table.hh
vendored
1
thirdparty/harfbuzz/src/hb-ot-vorg-table.hh
vendored
|
|
@ -61,6 +61,7 @@ struct VORG
|
|||
|
||||
bool has_data () const { return version.to_int (); }
|
||||
|
||||
HB_ALWAYS_INLINE
|
||||
int get_y_origin (hb_codepoint_t glyph) const
|
||||
{
|
||||
unsigned int i;
|
||||
|
|
|
|||
14
thirdparty/harfbuzz/src/hb-paint-extents.cc
vendored
14
thirdparty/harfbuzz/src/hb-paint-extents.cc
vendored
|
|
@ -49,7 +49,7 @@ hb_paint_extents_push_transform (hb_paint_funcs_t *funcs HB_UNUSED,
|
|||
{
|
||||
hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
|
||||
|
||||
c->push_transform (hb_transform_t {xx, yx, xy, yy, dx, dy});
|
||||
c->push_transform (hb_transform_t<> {xx, yx, xy, yy, dx, dy});
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -71,7 +71,7 @@ hb_paint_extents_push_clip_glyph (hb_paint_funcs_t *funcs HB_UNUSED,
|
|||
{
|
||||
hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
|
||||
|
||||
hb_extents_t extents;
|
||||
hb_extents_t<> extents;
|
||||
hb_draw_funcs_t *draw_extent_funcs = hb_draw_extents_get_funcs ();
|
||||
hb_font_draw_glyph (font, glyph, draw_extent_funcs, &extents);
|
||||
c->push_clip (extents);
|
||||
|
|
@ -85,7 +85,7 @@ hb_paint_extents_push_clip_rectangle (hb_paint_funcs_t *funcs HB_UNUSED,
|
|||
{
|
||||
hb_paint_extents_context_t *c = (hb_paint_extents_context_t *) paint_data;
|
||||
|
||||
hb_extents_t extents = {xmin, ymin, xmax, ymax};
|
||||
hb_extents_t<> extents = {xmin, ymin, xmax, ymax};
|
||||
c->push_clip (extents);
|
||||
}
|
||||
|
||||
|
|
@ -136,10 +136,10 @@ hb_paint_extents_paint_image (hb_paint_funcs_t *funcs HB_UNUSED,
|
|||
if (!glyph_extents)
|
||||
return false; // Happens with SVG images.
|
||||
|
||||
hb_extents_t extents = {(float) glyph_extents->x_bearing,
|
||||
(float) glyph_extents->y_bearing + glyph_extents->height,
|
||||
(float) glyph_extents->x_bearing + glyph_extents->width,
|
||||
(float) glyph_extents->y_bearing};
|
||||
hb_extents_t<> extents = {(float) glyph_extents->x_bearing,
|
||||
(float) glyph_extents->y_bearing + glyph_extents->height,
|
||||
(float) glyph_extents->x_bearing + glyph_extents->width,
|
||||
(float) glyph_extents->y_bearing};
|
||||
c->push_clip (extents);
|
||||
c->paint ();
|
||||
c->pop_clip ();
|
||||
|
|
|
|||
38
thirdparty/harfbuzz/src/hb-paint-extents.hh
vendored
38
thirdparty/harfbuzz/src/hb-paint-extents.hh
vendored
|
|
@ -41,9 +41,9 @@ struct hb_paint_extents_context_t
|
|||
clips.clear ();
|
||||
groups.clear ();
|
||||
|
||||
transforms.push (hb_transform_t{});
|
||||
clips.push (hb_bounds_t{hb_bounds_t::UNBOUNDED});
|
||||
groups.push (hb_bounds_t{hb_bounds_t::EMPTY});
|
||||
transforms.push (hb_transform_t<>{});
|
||||
clips.push (hb_bounds_t<>{hb_bounds_t<>::UNBOUNDED});
|
||||
groups.push (hb_bounds_t<>{hb_bounds_t<>::EMPTY});
|
||||
}
|
||||
|
||||
hb_paint_extents_context_t ()
|
||||
|
|
@ -51,19 +51,19 @@ struct hb_paint_extents_context_t
|
|||
clear ();
|
||||
}
|
||||
|
||||
hb_extents_t get_extents ()
|
||||
hb_extents_t<> get_extents ()
|
||||
{
|
||||
return groups.tail().extents;
|
||||
}
|
||||
|
||||
bool is_bounded ()
|
||||
{
|
||||
return groups.tail().status != hb_bounds_t::UNBOUNDED;
|
||||
return groups.tail().status != hb_bounds_t<>::UNBOUNDED;
|
||||
}
|
||||
|
||||
void push_transform (const hb_transform_t &trans)
|
||||
void push_transform (const hb_transform_t<> &trans)
|
||||
{
|
||||
hb_transform_t t = transforms.tail ();
|
||||
hb_transform_t<> t = transforms.tail ();
|
||||
t.multiply (trans);
|
||||
transforms.push (t);
|
||||
}
|
||||
|
|
@ -73,13 +73,13 @@ struct hb_paint_extents_context_t
|
|||
transforms.pop ();
|
||||
}
|
||||
|
||||
void push_clip (hb_extents_t extents)
|
||||
void push_clip (hb_extents_t<> extents)
|
||||
{
|
||||
/* Transform extents and push a new clip. */
|
||||
const hb_transform_t &t = transforms.tail ();
|
||||
const hb_transform_t<> &t = transforms.tail ();
|
||||
t.transform_extents (extents);
|
||||
|
||||
auto bounds = hb_bounds_t {extents};
|
||||
auto bounds = hb_bounds_t<> {extents};
|
||||
bounds.intersect (clips.tail ());
|
||||
|
||||
clips.push (bounds);
|
||||
|
|
@ -92,19 +92,19 @@ struct hb_paint_extents_context_t
|
|||
|
||||
void push_group ()
|
||||
{
|
||||
groups.push (hb_bounds_t {hb_bounds_t::EMPTY});
|
||||
groups.push (hb_bounds_t<> {hb_bounds_t<>::EMPTY});
|
||||
}
|
||||
|
||||
void pop_group (hb_paint_composite_mode_t mode)
|
||||
{
|
||||
const hb_bounds_t src_bounds = groups.pop ();
|
||||
hb_bounds_t &backdrop_bounds = groups.tail ();
|
||||
const hb_bounds_t<> src_bounds = groups.pop ();
|
||||
hb_bounds_t<> &backdrop_bounds = groups.tail ();
|
||||
|
||||
// https://learn.microsoft.com/en-us/typography/opentype/spec/colr#format-32-paintcomposite
|
||||
switch ((int) mode)
|
||||
{
|
||||
case HB_PAINT_COMPOSITE_MODE_CLEAR:
|
||||
backdrop_bounds.status = hb_bounds_t::EMPTY;
|
||||
backdrop_bounds.status = hb_bounds_t<>::EMPTY;
|
||||
break;
|
||||
case HB_PAINT_COMPOSITE_MODE_SRC:
|
||||
case HB_PAINT_COMPOSITE_MODE_SRC_OUT:
|
||||
|
|
@ -125,16 +125,16 @@ struct hb_paint_extents_context_t
|
|||
|
||||
void paint ()
|
||||
{
|
||||
const hb_bounds_t &clip = clips.tail ();
|
||||
hb_bounds_t &group = groups.tail ();
|
||||
const hb_bounds_t<> &clip = clips.tail ();
|
||||
hb_bounds_t<> &group = groups.tail ();
|
||||
|
||||
group.union_ (clip);
|
||||
}
|
||||
|
||||
protected:
|
||||
hb_vector_t<hb_transform_t> transforms;
|
||||
hb_vector_t<hb_bounds_t> clips;
|
||||
hb_vector_t<hb_bounds_t> groups;
|
||||
hb_vector_t<hb_transform_t<>> transforms;
|
||||
hb_vector_t<hb_bounds_t<>> clips;
|
||||
hb_vector_t<hb_bounds_t<>> groups;
|
||||
};
|
||||
|
||||
HB_INTERNAL hb_paint_funcs_t *
|
||||
|
|
|
|||
76
thirdparty/harfbuzz/src/hb-paint.hh
vendored
76
thirdparty/harfbuzz/src/hb-paint.hh
vendored
|
|
@ -28,6 +28,7 @@
|
|||
#include "hb.hh"
|
||||
#include "hb-face.hh"
|
||||
#include "hb-font.hh"
|
||||
#include "hb-geometry.hh"
|
||||
|
||||
#define HB_PAINT_FUNCS_IMPLEMENT_CALLBACKS \
|
||||
HB_PAINT_FUNC_IMPLEMENT (push_transform) \
|
||||
|
|
@ -72,7 +73,11 @@ struct hb_paint_funcs_t
|
|||
float xx, float yx,
|
||||
float xy, float yy,
|
||||
float dx, float dy)
|
||||
{ func.push_transform (this, paint_data,
|
||||
{
|
||||
// Handle -0.f to avoid -0.f == 0.f in the transform matrix.
|
||||
if (dx == -0.f) dx = 0.f;
|
||||
if (dy == -0.f) dy = 0.f;
|
||||
func.push_transform (this, paint_data,
|
||||
xx, yx, xy, yy, dx, dy,
|
||||
!user_data ? nullptr : user_data->push_transform); }
|
||||
void pop_transform (void *paint_data)
|
||||
|
|
@ -182,54 +187,59 @@ struct hb_paint_funcs_t
|
|||
0, 0);
|
||||
}
|
||||
|
||||
HB_NODISCARD
|
||||
bool push_translate (void *paint_data,
|
||||
void push_transform (void *paint_data, hb_transform_t<float> t)
|
||||
{
|
||||
push_transform (paint_data, t.xx, t.yx, t.xy, t.yy, t.x0, t.y0);
|
||||
}
|
||||
|
||||
void push_translate (void *paint_data,
|
||||
float dx, float dy)
|
||||
{
|
||||
if (!dx && !dy)
|
||||
return false;
|
||||
|
||||
push_transform (paint_data,
|
||||
1.f, 0.f, 0.f, 1.f, dx, dy);
|
||||
return true;
|
||||
hb_transform_t<float>::translation (dx, dy));
|
||||
}
|
||||
|
||||
HB_NODISCARD
|
||||
bool push_scale (void *paint_data,
|
||||
void push_scale (void *paint_data,
|
||||
float sx, float sy)
|
||||
{
|
||||
if (sx == 1.f && sy == 1.f)
|
||||
return false;
|
||||
|
||||
push_transform (paint_data,
|
||||
sx, 0.f, 0.f, sy, 0.f, 0.f);
|
||||
return true;
|
||||
hb_transform_t<float>::scaling (sx, sy));
|
||||
}
|
||||
void push_scale_around_center (void *paint_data,
|
||||
float sx, float sy,
|
||||
float cx, float cy)
|
||||
{
|
||||
push_transform (paint_data,
|
||||
hb_transform_t<float>::scaling_around_center (sx, sy, cx, cy));
|
||||
}
|
||||
|
||||
HB_NODISCARD
|
||||
bool push_rotate (void *paint_data,
|
||||
void push_rotate (void *paint_data,
|
||||
float a)
|
||||
{
|
||||
if (!a)
|
||||
return false;
|
||||
|
||||
float cc = cosf (a * HB_PI);
|
||||
float ss = sinf (a * HB_PI);
|
||||
push_transform (paint_data, cc, ss, -ss, cc, 0.f, 0.f);
|
||||
return true;
|
||||
push_transform (paint_data,
|
||||
hb_transform_t<float>::rotation (a * HB_PI));
|
||||
}
|
||||
|
||||
HB_NODISCARD
|
||||
bool push_skew (void *paint_data,
|
||||
void push_rotate_around_center (void *paint_data,
|
||||
float a,
|
||||
float cx, float cy)
|
||||
{
|
||||
push_transform (paint_data,
|
||||
hb_transform_t<float>::rotation_around_center (a * HB_PI, cx, cy));
|
||||
}
|
||||
|
||||
void push_skew (void *paint_data,
|
||||
float sx, float sy)
|
||||
{
|
||||
if (!sx && !sy)
|
||||
return false;
|
||||
|
||||
float x = tanf (-sx * HB_PI);
|
||||
float y = tanf (+sy * HB_PI);
|
||||
push_transform (paint_data, 1.f, y, x, 1.f, 0.f, 0.f);
|
||||
return true;
|
||||
push_transform (paint_data,
|
||||
hb_transform_t<float>::skewing (-sx * HB_PI, sy * HB_PI));
|
||||
}
|
||||
void push_skew_around_center (void *paint_data,
|
||||
float sx, float sy,
|
||||
float cx, float cy)
|
||||
{
|
||||
push_transform (paint_data,
|
||||
hb_transform_t<float>::skewing_around_center (-sx * HB_PI, sy * HB_PI, cx, cy));
|
||||
}
|
||||
};
|
||||
DECLARE_NULL_INSTANCE (hb_paint_funcs_t);
|
||||
|
|
|
|||
11
thirdparty/harfbuzz/src/hb-repacker.hh
vendored
11
thirdparty/harfbuzz/src/hb-repacker.hh
vendored
|
|
@ -266,7 +266,7 @@ bool _resolve_shared_overflow(const hb_vector_t<graph::overflow_record_t>& overf
|
|||
result = sorted_graph.duplicate(&parents, r.child);
|
||||
}
|
||||
|
||||
if (result == (unsigned) -1) return result;
|
||||
if (result == (unsigned) -1) return false;
|
||||
|
||||
if (parents.get_population() > 1) {
|
||||
// If the duplicated node has more than one parent pre-emptively raise it's priority to the maximum.
|
||||
|
|
@ -283,7 +283,7 @@ bool _resolve_shared_overflow(const hb_vector_t<graph::overflow_record_t>& overf
|
|||
sorted_graph.vertices_[result].give_max_priority();
|
||||
}
|
||||
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline
|
||||
|
|
@ -302,8 +302,11 @@ bool _process_overflows (const hb_vector_t<graph::overflow_record_t>& overflows,
|
|||
{
|
||||
// The child object is shared, we may be able to eliminate the overflow
|
||||
// by duplicating it.
|
||||
if (!_resolve_shared_overflow(overflows, i, sorted_graph)) continue;
|
||||
return true;
|
||||
if (_resolve_shared_overflow(overflows, i, sorted_graph))
|
||||
return true;
|
||||
|
||||
// Sometimes we can't duplicate a node which looks shared because it's not actually shared
|
||||
// (eg. all links from the same parent) in this case continue on to other resolution options.
|
||||
}
|
||||
|
||||
if (child.is_leaf () && !priority_bumped_parents.has (r.parent))
|
||||
|
|
|
|||
26
thirdparty/harfbuzz/src/hb-sanitize.hh
vendored
26
thirdparty/harfbuzz/src/hb-sanitize.hh
vendored
|
|
@ -120,8 +120,8 @@
|
|||
struct hb_sanitize_context_t :
|
||||
hb_dispatch_context_t<hb_sanitize_context_t, bool, HB_DEBUG_SANITIZE>
|
||||
{
|
||||
hb_sanitize_context_t () :
|
||||
start (nullptr), end (nullptr),
|
||||
hb_sanitize_context_t (const char *start_ = nullptr, const char *end_ = nullptr) :
|
||||
start (start_), end (end_),
|
||||
length (0),
|
||||
max_ops (0), max_subtables (0),
|
||||
recursion_depth (0),
|
||||
|
|
@ -212,14 +212,22 @@ struct hb_sanitize_context_t :
|
|||
|
||||
void reset_object ()
|
||||
{
|
||||
this->start = this->blob->data;
|
||||
this->end = this->start + this->blob->length;
|
||||
if (this->blob)
|
||||
{
|
||||
this->start = this->blob->data;
|
||||
this->end = this->start + this->blob->length;
|
||||
}
|
||||
this->length = this->end - this->start;
|
||||
assert (this->start <= this->end); /* Must not overflow. */
|
||||
}
|
||||
|
||||
void start_processing ()
|
||||
void start_processing (const char *start_ = nullptr, const char *end_ = nullptr)
|
||||
{
|
||||
if (start_)
|
||||
{
|
||||
this->start = start_;
|
||||
this->end = end_;
|
||||
}
|
||||
reset_object ();
|
||||
unsigned m;
|
||||
if (unlikely (hb_unsigned_mul_overflows (this->end - this->start, HB_SANITIZE_MAX_OPS_FACTOR, &m)))
|
||||
|
|
@ -463,9 +471,11 @@ struct hb_sanitize_context_t :
|
|||
}
|
||||
else
|
||||
{
|
||||
if (edit_count && !writable) {
|
||||
start = hb_blob_get_data_writable (blob, nullptr);
|
||||
end = start + blob->length;
|
||||
if (edit_count && !writable)
|
||||
{
|
||||
unsigned length;
|
||||
start = hb_blob_get_data_writable (blob, &length);
|
||||
end = start + length;
|
||||
|
||||
if (start)
|
||||
{
|
||||
|
|
|
|||
3
thirdparty/harfbuzz/src/hb-serialize.hh
vendored
3
thirdparty/harfbuzz/src/hb-serialize.hh
vendored
|
|
@ -794,7 +794,8 @@ struct hb_serialize_context_t
|
|||
template <typename T, unsigned Size = sizeof (T)>
|
||||
void assign_offset (const object_t* parent, const object_t::link_t &link, unsigned offset)
|
||||
{
|
||||
auto &off = * ((BEInt<T, Size> *) (parent->head + link.position));
|
||||
// XXX We should stop assuming big-endian!
|
||||
auto &off = * ((HBInt<true, T, Size> *) (parent->head + link.position));
|
||||
assert (0 == off);
|
||||
check_assign (off, offset, HB_SERIALIZE_ERROR_OFFSET_OVERFLOW);
|
||||
}
|
||||
|
|
|
|||
4
thirdparty/harfbuzz/src/hb-shaper-list.hh
vendored
4
thirdparty/harfbuzz/src/hb-shaper-list.hh
vendored
|
|
@ -57,8 +57,8 @@ HB_SHAPER_IMPLEMENT (directwrite)
|
|||
HB_SHAPER_IMPLEMENT (coretext)
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_HARFRUZZ
|
||||
HB_SHAPER_IMPLEMENT (harfruzz)
|
||||
#ifdef HAVE_HARFRUST
|
||||
HB_SHAPER_IMPLEMENT (harfrust)
|
||||
#endif
|
||||
|
||||
#ifndef HB_NO_FALLBACK_SHAPE
|
||||
|
|
|
|||
23
thirdparty/harfbuzz/src/hb-static.cc
vendored
23
thirdparty/harfbuzz/src/hb-static.cc
vendored
|
|
@ -113,27 +113,4 @@ hb_face_t::load_upem () const
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
bool
|
||||
_glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical,
|
||||
int *lsb)
|
||||
{
|
||||
return font->face->table.glyf->get_leading_bearing_with_var_unscaled (font, glyph, is_vertical, lsb);
|
||||
}
|
||||
|
||||
unsigned
|
||||
_glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical)
|
||||
{
|
||||
return font->face->table.glyf->get_advance_with_var_unscaled (font, glyph, is_vertical);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
_glyf_get_leading_bearing_without_var_unscaled (hb_face_t *face, hb_codepoint_t gid, bool is_vertical, int *lsb)
|
||||
{
|
||||
return face->table.glyf->get_leading_bearing_without_var_unscaled (gid, is_vertical, lsb);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
103
thirdparty/harfbuzz/src/hb-subset-plan-var.cc
vendored
103
thirdparty/harfbuzz/src/hb-subset-plan-var.cc
vendored
|
|
@ -42,30 +42,30 @@
|
|||
hb_vector_t<hb_inc_bimap_t> &inner_maps /* OUT */)
|
||||
{
|
||||
if (varidx_set.is_empty () || subtable_count == 0) return;
|
||||
|
||||
|
||||
if (unlikely (!inner_maps.resize (subtable_count))) return;
|
||||
for (unsigned idx : varidx_set)
|
||||
{
|
||||
uint16_t major = idx >> 16;
|
||||
uint16_t minor = idx & 0xFFFF;
|
||||
|
||||
|
||||
if (major >= subtable_count)
|
||||
continue;
|
||||
inner_maps[major].add (minor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline hb_font_t*
|
||||
_get_hb_font_with_variations (const hb_subset_plan_t *plan)
|
||||
{
|
||||
hb_font_t *font = hb_font_create (plan->source);
|
||||
|
||||
|
||||
hb_vector_t<hb_variation_t> vars;
|
||||
if (!vars.alloc (plan->user_axes_location.get_population ())) {
|
||||
hb_font_destroy (font);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
for (auto _ : plan->user_axes_location)
|
||||
{
|
||||
hb_variation_t var;
|
||||
|
|
@ -73,11 +73,11 @@
|
|||
var.value = _.second.middle;
|
||||
vars.push (var);
|
||||
}
|
||||
|
||||
|
||||
hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location.get_population ());
|
||||
return font;
|
||||
}
|
||||
|
||||
|
||||
template<typename ItemVarStore>
|
||||
void
|
||||
remap_variation_indices (const ItemVarStore &var_store,
|
||||
|
|
@ -90,7 +90,7 @@
|
|||
if (&var_store == &Null (OT::ItemVariationStore)) return;
|
||||
unsigned subtable_count = var_store.get_sub_table_count ();
|
||||
auto *store_cache = var_store.create_cache ();
|
||||
|
||||
|
||||
unsigned new_major = 0, new_minor = 0;
|
||||
unsigned last_major = (variation_indices.get_min ()) >> 16;
|
||||
for (unsigned idx : variation_indices)
|
||||
|
|
@ -99,13 +99,13 @@
|
|||
if (calculate_delta)
|
||||
delta = roundf (var_store.get_delta (idx, normalized_coords.arrayZ,
|
||||
normalized_coords.length, store_cache));
|
||||
|
||||
|
||||
if (no_variations)
|
||||
{
|
||||
variation_idx_delta_map.set (idx, hb_pair_t<unsigned, int> (HB_OT_LAYOUT_NO_VARIATIONS_INDEX, delta));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
uint16_t major = idx >> 16;
|
||||
if (major >= subtable_count) break;
|
||||
if (major != last_major)
|
||||
|
|
@ -113,7 +113,7 @@
|
|||
new_minor = 0;
|
||||
++new_major;
|
||||
}
|
||||
|
||||
|
||||
unsigned new_idx = (new_major << 16) + new_minor;
|
||||
variation_idx_delta_map.set (idx, hb_pair_t<unsigned, int> (new_idx, delta));
|
||||
++new_minor;
|
||||
|
|
@ -121,7 +121,7 @@
|
|||
}
|
||||
var_store.destroy_cache (store_cache);
|
||||
}
|
||||
|
||||
|
||||
template
|
||||
void
|
||||
remap_variation_indices<OT::ItemVariationStore> (const OT::ItemVariationStore &var_store,
|
||||
|
|
@ -130,7 +130,7 @@
|
|||
bool calculate_delta, /* not pinned at default */
|
||||
bool no_variations, /* all axes pinned */
|
||||
hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> &variation_idx_delta_map /* OUT */);
|
||||
|
||||
|
||||
#ifndef HB_NO_BASE
|
||||
void
|
||||
collect_base_variation_indices (hb_subset_plan_t* plan)
|
||||
|
|
@ -141,23 +141,23 @@
|
|||
base.destroy ();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
hb_set_t varidx_set;
|
||||
base->collect_variation_indices (plan, varidx_set);
|
||||
const OT::ItemVariationStore &var_store = base->get_var_store ();
|
||||
unsigned subtable_count = var_store.get_sub_table_count ();
|
||||
|
||||
|
||||
|
||||
|
||||
remap_variation_indices (var_store, varidx_set,
|
||||
plan->normalized_coords,
|
||||
!plan->pinned_at_default,
|
||||
plan->all_axes_pinned,
|
||||
plan->base_variation_idx_map);
|
||||
generate_varstore_inner_maps (varidx_set, subtable_count, plan->base_varstore_inner_maps);
|
||||
|
||||
|
||||
base.destroy ();
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
|
|
@ -199,24 +199,44 @@ normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
|
|||
{
|
||||
plan->axes_triple_distances.set (axis_tag, axis.get_triple_distances ());
|
||||
|
||||
int normalized_min = axis.normalize_axis_value (axis_range->minimum);
|
||||
int normalized_default = axis.normalize_axis_value (axis_range->middle);
|
||||
int normalized_max = axis.normalize_axis_value (axis_range->maximum);
|
||||
float normalized_min = axis.normalize_axis_value (axis_range->minimum);
|
||||
float normalized_default = axis.normalize_axis_value (axis_range->middle);
|
||||
float normalized_max = axis.normalize_axis_value (axis_range->maximum);
|
||||
|
||||
// TODO(behdad): Spec says axis normalization should be done in 16.16;
|
||||
// We used to do it in 2.14, but that's not correct. I fixed this in
|
||||
// the fvar/avar code, but keeping 2.14 here for now to keep tests
|
||||
// happy. We might need to adjust fonttools as well.
|
||||
// I'm only fairly confident in the above statement. Anyway,
|
||||
// we should look deeper into this, and also update fonttools if
|
||||
// needed.
|
||||
|
||||
// Round to 2.14
|
||||
normalized_min = roundf (normalized_min * 16384.f) / 16384.f;
|
||||
normalized_default = roundf (normalized_default * 16384.f) / 16384.f;
|
||||
normalized_max = roundf (normalized_max * 16384.f) / 16384.f;
|
||||
|
||||
if (has_avar && old_axis_idx < avar_axis_count)
|
||||
{
|
||||
normalized_min = seg_maps->map (normalized_min);
|
||||
normalized_default = seg_maps->map (normalized_default);
|
||||
normalized_max = seg_maps->map (normalized_max);
|
||||
}
|
||||
plan->axes_location.set (axis_tag, Triple (static_cast<double> (normalized_min / 16384.0),
|
||||
static_cast<double> (normalized_default / 16384.0),
|
||||
static_cast<double> (normalized_max / 16384.0)));
|
||||
normalized_min = seg_maps->map_float (normalized_min);
|
||||
normalized_default = seg_maps->map_float (normalized_default);
|
||||
normalized_max = seg_maps->map_float (normalized_max);
|
||||
|
||||
if (normalized_default != 0)
|
||||
// Round to 2.14
|
||||
normalized_min = roundf (normalized_min * 16384.f) / 16384.f;
|
||||
normalized_default = roundf (normalized_default * 16384.f) / 16384.f;
|
||||
normalized_max = roundf (normalized_max * 16384.f) / 16384.f;
|
||||
}
|
||||
plan->axes_location.set (axis_tag, Triple ((double) normalized_min,
|
||||
(double) normalized_default,
|
||||
(double) normalized_max));
|
||||
|
||||
if (normalized_default == -0.f)
|
||||
normalized_default = 0.f; // Normalize -0 to 0
|
||||
if (normalized_default != 0.f)
|
||||
plan->pinned_at_default = false;
|
||||
|
||||
plan->normalized_coords[old_axis_idx] = normalized_default;
|
||||
plan->normalized_coords[old_axis_idx] = roundf (normalized_default * 16384.f);
|
||||
}
|
||||
|
||||
old_axis_idx++;
|
||||
|
|
@ -243,12 +263,12 @@ update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan)
|
|||
|
||||
hb_glyph_extents_t extents = {0x7FFF, -0x7FFF};
|
||||
OT::hmtx_accelerator_t _hmtx (plan->source);
|
||||
OT::ItemVariationStore::cache_t *hvar_store_cache = nullptr;
|
||||
OT::hb_scalar_cache_t *hvar_store_cache = nullptr;
|
||||
if (_hmtx.has_data () && _hmtx.var_table.get_length ())
|
||||
hvar_store_cache = _hmtx.var_table->get_var_store ().create_cache ();
|
||||
|
||||
OT::vmtx_accelerator_t _vmtx (plan->source);
|
||||
OT::ItemVariationStore::cache_t *vvar_store_cache = nullptr;
|
||||
OT::hb_scalar_cache_t *vvar_store_cache = nullptr;
|
||||
if (_vmtx.has_data () && _vmtx.var_table.get_length ())
|
||||
vvar_store_cache = _vmtx.var_table->get_var_store ().create_cache ();
|
||||
|
||||
|
|
@ -279,8 +299,7 @@ update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan)
|
|||
int lsb = extents.x_bearing;
|
||||
if (!has_bounds_info)
|
||||
{
|
||||
if (!_hmtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb))
|
||||
continue;
|
||||
_hmtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb);
|
||||
}
|
||||
plan->hmtx_map.set (new_gid, hb_pair ((unsigned) hori_aw, lsb));
|
||||
plan->bounds_width_vec[new_gid] = extents.width;
|
||||
|
|
@ -292,13 +311,17 @@ update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan)
|
|||
if (_vmtx.var_table.get_length ())
|
||||
vert_aw += (int) roundf (_vmtx.var_table->get_advance_delta_unscaled (old_gid, font->coords, font->num_coords,
|
||||
vvar_store_cache));
|
||||
|
||||
int tsb = extents.y_bearing;
|
||||
if (!has_bounds_info)
|
||||
hb_position_t vorg_x = 0;
|
||||
hb_position_t vorg_y = 0;
|
||||
int tsb = 0;
|
||||
if (has_bounds_info &&
|
||||
hb_font_get_glyph_v_origin (font, old_gid, &vorg_x, &vorg_y))
|
||||
{
|
||||
if (!_vmtx.get_leading_bearing_without_var_unscaled (old_gid, &tsb))
|
||||
continue;
|
||||
tsb = vorg_y - extents.y_bearing;
|
||||
} else {
|
||||
_vmtx.get_leading_bearing_without_var_unscaled (old_gid, &tsb);
|
||||
}
|
||||
|
||||
plan->vmtx_map.set (new_gid, hb_pair ((unsigned) vert_aw, tsb));
|
||||
plan->bounds_height_vec[new_gid] = extents.height;
|
||||
}
|
||||
|
|
@ -385,4 +408,4 @@ remap_colrv1_delta_set_index_indices<OT::DeltaSetIndexMap> (const OT::DeltaSetIn
|
|||
hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> &variation_idx_delta_map, /* IN/OUT */
|
||||
hb_map_t &new_deltaset_idx_varidx_map /* OUT */);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
4
thirdparty/harfbuzz/src/hb-subset-plan.cc
vendored
4
thirdparty/harfbuzz/src/hb-subset-plan.cc
vendored
|
|
@ -248,7 +248,7 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes_in,
|
|||
!(plan->flags & HB_SUBSET_FLAGS_NO_BIDI_CLOSURE));
|
||||
|
||||
OT::cmap::accelerator_t cmap (plan->source);
|
||||
unsigned size_threshold = plan->source->get_num_glyphs ();
|
||||
unsigned size_threshold = plan->source->get_num_glyphs ();
|
||||
|
||||
if (glyphs->is_empty () && unicodes.get_population () < size_threshold)
|
||||
{
|
||||
|
|
@ -376,7 +376,7 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes_in,
|
|||
// so record those first.
|
||||
plan->os2_info.min_cmap_codepoint = plan->unicodes.get_min();
|
||||
plan->os2_info.max_cmap_codepoint = plan->unicodes.get_max();
|
||||
|
||||
|
||||
hb_set_t variation_selectors_to_retain;
|
||||
cmap.collect_variation_selectors(&variation_selectors_to_retain);
|
||||
+ variation_selectors_to_retain.iter()
|
||||
|
|
|
|||
1745
thirdparty/harfbuzz/src/hb-ucd-table.hh
vendored
1745
thirdparty/harfbuzz/src/hb-ucd-table.hh
vendored
File diff suppressed because it is too large
Load diff
|
|
@ -23,8 +23,9 @@
|
|||
|
||||
#include "hb-unicode.hh"
|
||||
|
||||
static const uint8_t
|
||||
_hb_emoji_u8[464] =
|
||||
#include <stdint.h>
|
||||
|
||||
static const uint8_t _hb_emoji_u8[464]=
|
||||
{
|
||||
16, 17, 17, 17, 50, 20, 21, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17,
|
||||
|
|
@ -57,20 +58,17 @@ _hb_emoji_u8[464] =
|
|||
0,192,255,255, 0,240,255,255,255,255,255,247,191,255,255,255,
|
||||
};
|
||||
|
||||
static inline unsigned
|
||||
_hb_emoji_b4 (const uint8_t* a, unsigned i)
|
||||
static inline uint8_t _hb_emoji_b4 (const uint8_t* a, unsigned i)
|
||||
{
|
||||
return (a[i>>1]>>((i&1u)<<2))&15u;
|
||||
return (a[i>>1]>>((i&1)<<2))&15;
|
||||
}
|
||||
static inline unsigned
|
||||
_hb_emoji_b1 (const uint8_t* a, unsigned i)
|
||||
static inline uint8_t _hb_emoji_b1 (const uint8_t* a, unsigned i)
|
||||
{
|
||||
return (a[i>>3]>>((i&7u)<<0))&1u;
|
||||
return (a[i>>3]>>((i&7)<<0))&1;
|
||||
}
|
||||
static inline uint_fast8_t
|
||||
_hb_emoji_is_Extended_Pictographic (unsigned u)
|
||||
static inline uint8_t _hb_emoji_is_Extended_Pictographic (unsigned u)
|
||||
{
|
||||
return u<131070u?_hb_emoji_b1(264+_hb_emoji_u8,((_hb_emoji_u8[144+(((_hb_emoji_u8[64+(((_hb_emoji_b4(_hb_emoji_u8,u>>5>>2>>3))<<3)+((u>>5>>2)&7u))])<<2)+((u>>5)&3u))])<<5)+((u)&31u)):0;
|
||||
return u<131070 ? _hb_emoji_b1(_hb_emoji_u8+264u,((_hb_emoji_u8[144u+(((_hb_emoji_u8[64u+(((_hb_emoji_b4(_hb_emoji_u8,u>>5>>2>>3))<<3)+((u>>5>>2)&7))])<<2)+((u>>5)&3))])<<5)+((u)&31)) : 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
51
thirdparty/harfbuzz/src/hb-unicode.hh
vendored
51
thirdparty/harfbuzz/src/hb-unicode.hh
vendored
|
|
@ -241,6 +241,57 @@ HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS_SIMPLE
|
|||
}
|
||||
}
|
||||
|
||||
static hb_codepoint_t
|
||||
vertical_char_for (hb_codepoint_t u)
|
||||
{
|
||||
switch (u >> 8)
|
||||
{
|
||||
case 0x20: switch (u) {
|
||||
case 0x2013u: return 0xfe32u; // EN DASH
|
||||
case 0x2014u: return 0xfe31u; // EM DASH
|
||||
case 0x2025u: return 0xfe30u; // TWO DOT LEADER
|
||||
case 0x2026u: return 0xfe19u; // HORIZONTAL ELLIPSIS
|
||||
} break;
|
||||
case 0x30: switch (u) {
|
||||
case 0x3001u: return 0xfe11u; // IDEOGRAPHIC COMMA
|
||||
case 0x3002u: return 0xfe12u; // IDEOGRAPHIC FULL STOP
|
||||
case 0x3008u: return 0xfe3fu; // LEFT ANGLE BRACKET
|
||||
case 0x3009u: return 0xfe40u; // RIGHT ANGLE BRACKET
|
||||
case 0x300au: return 0xfe3du; // LEFT DOUBLE ANGLE BRACKET
|
||||
case 0x300bu: return 0xfe3eu; // RIGHT DOUBLE ANGLE BRACKET
|
||||
case 0x300cu: return 0xfe41u; // LEFT CORNER BRACKET
|
||||
case 0x300du: return 0xfe42u; // RIGHT CORNER BRACKET
|
||||
case 0x300eu: return 0xfe43u; // LEFT WHITE CORNER BRACKET
|
||||
case 0x300fu: return 0xfe44u; // RIGHT WHITE CORNER BRACKET
|
||||
case 0x3010u: return 0xfe3bu; // LEFT BLACK LENTICULAR BRACKET
|
||||
case 0x3011u: return 0xfe3cu; // RIGHT BLACK LENTICULAR BRACKET
|
||||
case 0x3014u: return 0xfe39u; // LEFT TORTOISE SHELL BRACKET
|
||||
case 0x3015u: return 0xfe3au; // RIGHT TORTOISE SHELL BRACKET
|
||||
case 0x3016u: return 0xfe17u; // LEFT WHITE LENTICULAR BRACKET
|
||||
case 0x3017u: return 0xfe18u; // RIGHT WHITE LENTICULAR BRACKET
|
||||
} break;
|
||||
case 0xfe: switch (u) {
|
||||
case 0xfe4fu: return 0xfe34u; // WAVY LOW LINE
|
||||
} break;
|
||||
case 0xff: switch (u) {
|
||||
case 0xff01u: return 0xfe15u; // FULLWIDTH EXCLAMATION MARK
|
||||
case 0xff08u: return 0xfe35u; // FULLWIDTH LEFT PARENTHESIS
|
||||
case 0xff09u: return 0xfe36u; // FULLWIDTH RIGHT PARENTHESIS
|
||||
case 0xff0cu: return 0xfe10u; // FULLWIDTH COMMA
|
||||
case 0xff1au: return 0xfe13u; // FULLWIDTH COLON
|
||||
case 0xff1bu: return 0xfe14u; // FULLWIDTH SEMICOLON
|
||||
case 0xff1fu: return 0xfe16u; // FULLWIDTH QUESTION MARK
|
||||
case 0xff3bu: return 0xfe47u; // FULLWIDTH LEFT SQUARE BRACKET
|
||||
case 0xff3du: return 0xfe48u; // FULLWIDTH RIGHT SQUARE BRACKET
|
||||
case 0xff3fu: return 0xfe33u; // FULLWIDTH LOW LINE
|
||||
case 0xff5bu: return 0xfe37u; // FULLWIDTH LEFT CURLY BRACKET
|
||||
case 0xff5du: return 0xfe38u; // FULLWIDTH RIGHT CURLY BRACKET
|
||||
} break;
|
||||
}
|
||||
|
||||
return u;
|
||||
}
|
||||
|
||||
struct {
|
||||
#define HB_UNICODE_FUNC_IMPLEMENT(name) hb_unicode_##name##_func_t name;
|
||||
HB_UNICODE_FUNCS_IMPLEMENT_CALLBACKS
|
||||
|
|
|
|||
6
thirdparty/harfbuzz/src/hb-version.h
vendored
6
thirdparty/harfbuzz/src/hb-version.h
vendored
|
|
@ -47,20 +47,20 @@ HB_BEGIN_DECLS
|
|||
*
|
||||
* The minor component of the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_MINOR 2
|
||||
#define HB_VERSION_MINOR 3
|
||||
/**
|
||||
* HB_VERSION_MICRO:
|
||||
*
|
||||
* The micro component of the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_MICRO 1
|
||||
#define HB_VERSION_MICRO 2
|
||||
|
||||
/**
|
||||
* HB_VERSION_STRING:
|
||||
*
|
||||
* A string literal containing the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_STRING "11.2.1"
|
||||
#define HB_VERSION_STRING "11.3.2"
|
||||
|
||||
/**
|
||||
* HB_VERSION_ATLEAST:
|
||||
|
|
|
|||
4
thirdparty/harfbuzz/src/hb.hh
vendored
4
thirdparty/harfbuzz/src/hb.hh
vendored
|
|
@ -314,6 +314,10 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef HB_HOT
|
||||
#define HB_HOT __attribute__((hot))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Borrowed from https://bugzilla.mozilla.org/show_bug.cgi?id=1215411
|
||||
* HB_FALLTHROUGH is an annotation to suppress compiler warnings about switch
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue