HarfBuzz: Update to version 5.3.1
This commit is contained in:
parent
72b845b287
commit
7afd76bba6
46 changed files with 1349 additions and 443 deletions
2
thirdparty/README.md
vendored
2
thirdparty/README.md
vendored
|
@ -214,7 +214,7 @@ Files extracted from upstream source:
|
|||
## harfbuzz
|
||||
|
||||
- Upstream: https://github.com/harfbuzz/harfbuzz
|
||||
- Version: 5.2.0 (4a1d891c6317d2c83e5f3c2607ec5f5ccedffcde, 2022)
|
||||
- Version: 5.3.1 (970321db7bddbe8c579b73751fc655a924ea3ce6, 2022)
|
||||
- License: MIT
|
||||
|
||||
Files extracted from upstream source:
|
||||
|
|
|
@ -39,7 +39,7 @@ struct GPOS : GSUBGPOS
|
|||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
hb_subset_layout_context_t l (c, tableTag, c->plan->gpos_lookups, c->plan->gpos_langsys, c->plan->gpos_features);
|
||||
hb_subset_layout_context_t l (c, tableTag);
|
||||
return GSUBGPOS::subset<PosLookup> (&l);
|
||||
}
|
||||
|
||||
|
|
|
@ -80,6 +80,24 @@ struct SinglePosFormat1
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
bool
|
||||
position_single (hb_font_t *font,
|
||||
hb_direction_t direction,
|
||||
hb_codepoint_t gid,
|
||||
hb_glyph_position_t &pos) const
|
||||
{
|
||||
unsigned int index = (this+coverage).get_coverage (gid);
|
||||
if (likely (index == NOT_COVERED)) return false;
|
||||
|
||||
/* This is ugly... */
|
||||
hb_buffer_t buffer;
|
||||
buffer.props.direction = direction;
|
||||
OT::hb_ot_apply_context_t c (1, font, &buffer);
|
||||
|
||||
valueFormat.apply_value (&c, this, values, pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename Iterator,
|
||||
typename SrcLookup,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
|
|
|
@ -68,7 +68,7 @@ struct SinglePosFormat2
|
|||
unsigned int index = (this+coverage).get_coverage (buffer->cur().codepoint);
|
||||
if (likely (index == NOT_COVERED)) return_trace (false);
|
||||
|
||||
if (likely (index >= valueCount)) return_trace (false);
|
||||
if (unlikely (index >= valueCount)) return_trace (false);
|
||||
|
||||
if (HB_BUFFER_MESSAGE_MORE && c->buffer->messaging ())
|
||||
{
|
||||
|
@ -92,6 +92,28 @@ struct SinglePosFormat2
|
|||
return_trace (true);
|
||||
}
|
||||
|
||||
bool
|
||||
position_single (hb_font_t *font,
|
||||
hb_direction_t direction,
|
||||
hb_codepoint_t gid,
|
||||
hb_glyph_position_t &pos) const
|
||||
{
|
||||
unsigned int index = (this+coverage).get_coverage (gid);
|
||||
if (likely (index == NOT_COVERED)) return false;
|
||||
if (unlikely (index >= valueCount)) return false;
|
||||
|
||||
/* This is ugly... */
|
||||
hb_buffer_t buffer;
|
||||
buffer.props.direction = direction;
|
||||
OT::hb_ot_apply_context_t c (1, font, &buffer);
|
||||
|
||||
valueFormat.apply_value (&c, this,
|
||||
&values[index * valueFormat.get_len ()],
|
||||
pos);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename Iterator,
|
||||
typename SrcLookup,
|
||||
hb_requires (hb_is_iterator (Iterator))>
|
||||
|
|
|
@ -27,7 +27,7 @@ struct GSUB : GSUBGPOS
|
|||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
hb_subset_layout_context_t l (c, tableTag, c->plan->gsub_lookups, c->plan->gsub_langsys, c->plan->gsub_features);
|
||||
hb_subset_layout_context_t l (c, tableTag);
|
||||
return GSUBGPOS::subset<SubstLookup> (&l);
|
||||
}
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ struct Ligature
|
|||
match_positions[i] += delta;
|
||||
if (i)
|
||||
*p++ = ',';
|
||||
sprintf (p, "%u", match_positions[i]);
|
||||
snprintf (p, sizeof(buf), "%u", match_positions[i]);
|
||||
p += strlen(p);
|
||||
}
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ struct Sequence
|
|||
{
|
||||
if (buf < p)
|
||||
*p++ = ',';
|
||||
sprintf (p, "%u", i);
|
||||
snprintf (p, sizeof(buf), "%u", i);
|
||||
p += strlen(p);
|
||||
}
|
||||
|
||||
|
|
66
thirdparty/harfbuzz/src/OT/glyf/Glyph.hh
vendored
66
thirdparty/harfbuzz/src/OT/glyf/Glyph.hh
vendored
|
@ -102,17 +102,19 @@ struct Glyph
|
|||
hb_bytes_t &dest_bytes /* OUT */) const
|
||||
{
|
||||
GlyphHeader *glyph_header = nullptr;
|
||||
if (all_points.length > 4)
|
||||
if (type != EMPTY && all_points.length > 4)
|
||||
{
|
||||
glyph_header = (GlyphHeader *) hb_calloc (1, GlyphHeader::static_size);
|
||||
if (unlikely (!glyph_header)) return false;
|
||||
}
|
||||
|
||||
int xMin, xMax;
|
||||
xMin = xMax = roundf (all_points[0].x);
|
||||
|
||||
int yMin, yMax;
|
||||
yMin = yMax = roundf (all_points[0].y);
|
||||
int xMin = 0, xMax = 0;
|
||||
int yMin = 0, yMax = 0;
|
||||
if (all_points.length > 4)
|
||||
{
|
||||
xMin = xMax = roundf (all_points[0].x);
|
||||
yMin = yMax = roundf (all_points[0].y);
|
||||
}
|
||||
|
||||
for (unsigned i = 1; i < all_points.length - 4; i++)
|
||||
{
|
||||
|
@ -128,7 +130,7 @@ struct Glyph
|
|||
|
||||
/*for empty glyphs: all_points only include phantom points.
|
||||
*just update metrics and then return */
|
||||
if (all_points.length == 4)
|
||||
if (!glyph_header)
|
||||
return true;
|
||||
|
||||
glyph_header->numberOfContours = header->numberOfContours;
|
||||
|
@ -145,10 +147,17 @@ struct Glyph
|
|||
hb_font_t *font,
|
||||
const glyf_accelerator_t &glyf,
|
||||
hb_bytes_t &dest_start, /* IN/OUT */
|
||||
hb_bytes_t &dest_end /* OUT */) const
|
||||
hb_bytes_t &dest_end /* OUT */)
|
||||
{
|
||||
contour_point_vector_t all_points, deltas;
|
||||
get_points (font, glyf, all_points, &deltas, false);
|
||||
if (!get_points (font, glyf, all_points, &deltas, false, false))
|
||||
return false;
|
||||
|
||||
// .notdef, set type to empty so we only update metrics and don't compile bytes for
|
||||
// it
|
||||
if (gid == 0 &&
|
||||
!(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
|
||||
type = EMPTY;
|
||||
|
||||
switch (type) {
|
||||
case COMPOSITE:
|
||||
|
@ -171,7 +180,12 @@ struct Glyph
|
|||
break;
|
||||
}
|
||||
|
||||
return compile_header_bytes (plan, all_points, dest_start);
|
||||
if (!compile_header_bytes (plan, all_points, dest_start))
|
||||
{
|
||||
dest_end.fini ();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -182,6 +196,7 @@ struct Glyph
|
|||
bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
|
||||
contour_point_vector_t &all_points /* OUT */,
|
||||
contour_point_vector_t *deltas = nullptr, /* OUT */
|
||||
bool shift_points_hori = true,
|
||||
bool use_my_metrics = true,
|
||||
bool phantom_only = false,
|
||||
unsigned int depth = 0) const
|
||||
|
@ -238,8 +253,7 @@ struct Glyph
|
|||
if (deltas != nullptr && depth == 0 && type == COMPOSITE)
|
||||
{
|
||||
if (unlikely (!deltas->resize (points.length))) return false;
|
||||
for (unsigned i = 0 ; i < points.length; i++)
|
||||
deltas->arrayZ[i] = points.arrayZ[i];
|
||||
deltas->copy_vector (points);
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
|
@ -271,14 +285,9 @@ struct Glyph
|
|||
comp_points.reset ();
|
||||
if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
|
||||
.get_points (font, glyf_accelerator, comp_points,
|
||||
deltas, use_my_metrics, phantom_only, depth + 1)))
|
||||
deltas, shift_points_hori, use_my_metrics, phantom_only, depth + 1)))
|
||||
return false;
|
||||
|
||||
/* Copy phantom points from component if USE_MY_METRICS flag set */
|
||||
if (use_my_metrics && item.is_use_my_metrics ())
|
||||
for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
|
||||
phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
|
||||
|
||||
/* Apply component transformation & translation */
|
||||
item.transform_points (comp_points);
|
||||
|
||||
|
@ -299,6 +308,11 @@ struct Glyph
|
|||
}
|
||||
}
|
||||
|
||||
/* Copy phantom points from component if USE_MY_METRICS flag set */
|
||||
if (use_my_metrics && item.is_use_my_metrics ())
|
||||
for (unsigned int i = 0; i < PHANTOM_COUNT; i++)
|
||||
phantoms[i] = comp_points[comp_points.length - PHANTOM_COUNT + i];
|
||||
|
||||
all_points.extend (comp_points.sub_array (0, comp_points.length - PHANTOM_COUNT));
|
||||
|
||||
comp_index++;
|
||||
|
@ -310,7 +324,7 @@ struct Glyph
|
|||
all_points.extend (phantoms);
|
||||
}
|
||||
|
||||
if (depth == 0) /* Apply at top level */
|
||||
if (depth == 0 && shift_points_hori) /* Apply at top level */
|
||||
{
|
||||
/* Undocumented rasterizer behavior:
|
||||
* Shift points horizontally by the updated left side bearing
|
||||
|
@ -332,10 +346,16 @@ struct Glyph
|
|||
|
||||
hb_bytes_t get_bytes () const { return bytes; }
|
||||
|
||||
Glyph (hb_bytes_t bytes_ = hb_bytes_t (),
|
||||
hb_codepoint_t gid_ = (hb_codepoint_t) -1) : bytes (bytes_),
|
||||
header (bytes.as<GlyphHeader> ()),
|
||||
gid (gid_)
|
||||
Glyph () : bytes (),
|
||||
header (bytes.as<GlyphHeader> ()),
|
||||
gid (-1),
|
||||
type(EMPTY)
|
||||
{}
|
||||
|
||||
Glyph (hb_bytes_t bytes_,
|
||||
hb_codepoint_t gid_ = (unsigned) -1) : bytes (bytes_),
|
||||
header (bytes.as<GlyphHeader> ()),
|
||||
gid (gid_)
|
||||
{
|
||||
int num_contours = header->numberOfContours;
|
||||
if (unlikely (num_contours == 0)) type = EMPTY;
|
||||
|
|
26
thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh
vendored
26
thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh
vendored
|
@ -271,31 +271,29 @@ struct SimpleGlyph
|
|||
}
|
||||
//convert absolute values to relative values
|
||||
unsigned num_points = all_points.length - 4;
|
||||
hb_vector_t<hb_pair_t<int, int>> deltas;
|
||||
deltas.resize (num_points);
|
||||
|
||||
for (unsigned i = 0; i < num_points; i++)
|
||||
{
|
||||
deltas[i].first = i == 0 ? roundf (all_points[i].x) : roundf (all_points[i].x) - roundf (all_points[i-1].x);
|
||||
deltas[i].second = i == 0 ? roundf (all_points[i].y) : roundf (all_points[i].y) - roundf (all_points[i-1].y);
|
||||
}
|
||||
|
||||
hb_vector_t<uint8_t> flags, x_coords, y_coords;
|
||||
flags.alloc (num_points);
|
||||
x_coords.alloc (2*num_points);
|
||||
y_coords.alloc (2*num_points);
|
||||
if (unlikely (!flags.alloc (num_points))) return false;
|
||||
if (unlikely (!x_coords.alloc (2*num_points))) return false;
|
||||
if (unlikely (!y_coords.alloc (2*num_points))) return false;
|
||||
|
||||
uint8_t lastflag = 0, repeat = 0;
|
||||
|
||||
int prev_x = 0.f, prev_y = 0.f;
|
||||
|
||||
for (unsigned i = 0; i < num_points; i++)
|
||||
{
|
||||
uint8_t flag = all_points[i].flag;
|
||||
flag &= FLAG_ON_CURVE + FLAG_OVERLAP_SIMPLE;
|
||||
|
||||
encode_coord (deltas[i].first, flag, FLAG_X_SHORT, FLAG_X_SAME, x_coords);
|
||||
encode_coord (deltas[i].second, flag, FLAG_Y_SHORT, FLAG_Y_SAME, y_coords);
|
||||
float cur_x = roundf (all_points[i].x);
|
||||
float cur_y = roundf (all_points[i].y);
|
||||
encode_coord (cur_x - prev_x, flag, FLAG_X_SHORT, FLAG_X_SAME, x_coords);
|
||||
encode_coord (cur_y - prev_y, flag, FLAG_Y_SHORT, FLAG_Y_SAME, y_coords);
|
||||
if (i == 0) lastflag = flag + 1; //make lastflag != flag for the first point
|
||||
encode_flag (flag, repeat, lastflag, flags);
|
||||
|
||||
prev_x = cur_x;
|
||||
prev_y = cur_y;
|
||||
}
|
||||
|
||||
unsigned len_before_instrs = 2 * header.numberOfContours + 2;
|
||||
|
|
|
@ -14,7 +14,6 @@ namespace glyf_impl {
|
|||
|
||||
struct SubsetGlyph
|
||||
{
|
||||
hb_codepoint_t new_gid;
|
||||
hb_codepoint_t old_gid;
|
||||
Glyph source_glyph;
|
||||
hb_bytes_t dest_start; /* region of source_glyph to copy first */
|
||||
|
|
71
thirdparty/harfbuzz/src/OT/glyf/glyf.hh
vendored
71
thirdparty/harfbuzz/src/OT/glyf/glyf.hh
vendored
|
@ -72,10 +72,13 @@ struct glyf
|
|||
if (unlikely (!c->serializer->check_success (glyf_prime))) return_trace (false);
|
||||
|
||||
hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
|
||||
_populate_subset_glyphs (c->plan, &glyphs);
|
||||
_populate_subset_glyphs (c->plan, glyphs);
|
||||
|
||||
if (!c->plan->pinned_at_default)
|
||||
_compile_subset_glyphs_with_deltas (c->plan, &glyphs);
|
||||
{
|
||||
if (!_compile_subset_glyphs_with_deltas (c->plan, &glyphs))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
auto padded_offsets =
|
||||
+ hb_iter (glyphs)
|
||||
|
@ -105,9 +108,9 @@ struct glyf
|
|||
|
||||
void
|
||||
_populate_subset_glyphs (const hb_subset_plan_t *plan,
|
||||
hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const;
|
||||
|
||||
void
|
||||
hb_vector_t<glyf_impl::SubsetGlyph> &glyphs /* OUT */) const;
|
||||
|
||||
bool
|
||||
_compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan,
|
||||
hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const;
|
||||
|
||||
|
@ -180,7 +183,7 @@ struct glyf_accelerator_t
|
|||
contour_point_vector_t all_points;
|
||||
|
||||
bool phantom_only = !consumer.is_consuming_contour_points ();
|
||||
if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, true, phantom_only)))
|
||||
if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, true, true, phantom_only)))
|
||||
return false;
|
||||
|
||||
if (consumer.is_consuming_contour_points ())
|
||||
|
@ -374,44 +377,43 @@ struct glyf_accelerator_t
|
|||
|
||||
inline void
|
||||
glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
|
||||
hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const
|
||||
hb_vector_t<glyf_impl::SubsetGlyph>& glyphs /* OUT */) const
|
||||
{
|
||||
OT::glyf_accelerator_t glyf (plan->source);
|
||||
unsigned num_glyphs = plan->num_output_glyphs ();
|
||||
if (!glyphs.resize (num_glyphs)) return;
|
||||
|
||||
+ hb_range (plan->num_output_glyphs ())
|
||||
| hb_map ([&] (hb_codepoint_t new_gid)
|
||||
{
|
||||
glyf_impl::SubsetGlyph subset_glyph = {0};
|
||||
subset_glyph.new_gid = new_gid;
|
||||
for (auto p : plan->glyph_map->iter ())
|
||||
{
|
||||
unsigned new_gid = p.second;
|
||||
glyf_impl::SubsetGlyph& subset_glyph = glyphs.arrayZ[new_gid];
|
||||
subset_glyph.old_gid = p.first;
|
||||
|
||||
/* should never fail: all old gids should be mapped */
|
||||
if (!plan->old_gid_for_new_gid (new_gid, &subset_glyph.old_gid))
|
||||
return subset_glyph;
|
||||
if (unlikely (new_gid == 0 &&
|
||||
!(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE)) &&
|
||||
plan->pinned_at_default)
|
||||
subset_glyph.source_glyph = glyf_impl::Glyph ();
|
||||
else
|
||||
subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
|
||||
|
||||
if (new_gid == 0 &&
|
||||
!(plan->flags & HB_SUBSET_FLAGS_NOTDEF_OUTLINE))
|
||||
subset_glyph.source_glyph = glyf_impl::Glyph ();
|
||||
else
|
||||
subset_glyph.source_glyph = glyf.glyph_for_gid (subset_glyph.old_gid, true);
|
||||
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
subset_glyph.drop_hints_bytes ();
|
||||
else
|
||||
subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
|
||||
return subset_glyph;
|
||||
})
|
||||
| hb_sink (glyphs)
|
||||
;
|
||||
if (plan->flags & HB_SUBSET_FLAGS_NO_HINTING)
|
||||
subset_glyph.drop_hints_bytes ();
|
||||
else
|
||||
subset_glyph.dest_start = subset_glyph.source_glyph.get_bytes ();
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
inline bool
|
||||
glyf::_compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan,
|
||||
hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const
|
||||
{
|
||||
OT::glyf_accelerator_t glyf (plan->source);
|
||||
hb_font_t *font = hb_font_create (plan->source);
|
||||
if (unlikely (!font)) return false;
|
||||
|
||||
hb_vector_t<hb_variation_t> vars;
|
||||
vars.alloc (plan->user_axes_location->get_population ());
|
||||
if (unlikely (!vars.alloc (plan->user_axes_location->get_population ())))
|
||||
return false;
|
||||
|
||||
for (auto _ : *plan->user_axes_location)
|
||||
{
|
||||
|
@ -423,9 +425,16 @@ glyf::_compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan,
|
|||
|
||||
hb_font_set_variations (font, vars.arrayZ, plan->user_axes_location->get_population ());
|
||||
for (auto& subset_glyph : *glyphs)
|
||||
const_cast<glyf_impl::SubsetGlyph &> (subset_glyph).compile_bytes_with_deltas (plan, font, glyf);
|
||||
{
|
||||
if (!const_cast<glyf_impl::SubsetGlyph &> (subset_glyph).compile_bytes_with_deltas (plan, font, glyf))
|
||||
{
|
||||
hb_font_destroy (font);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
hb_font_destroy (font);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
|
29
thirdparty/harfbuzz/src/graph/graph.hh
vendored
29
thirdparty/harfbuzz/src/graph/graph.hh
vendored
|
@ -70,8 +70,8 @@ struct graph_t
|
|||
{
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr,
|
||||
"vertex [%lu] bytes != [%lu] bytes, depth = %u",
|
||||
table_size (),
|
||||
other.table_size (),
|
||||
(unsigned long) table_size (),
|
||||
(unsigned long) other.table_size (),
|
||||
depth);
|
||||
|
||||
auto a = as_bytes ();
|
||||
|
@ -495,6 +495,12 @@ struct graph_t
|
|||
return as_table_from_index<T> (index_for_offset (parent, offset), std::forward<Ts>(ds)...);
|
||||
}
|
||||
|
||||
template <typename T, typename ...Ts>
|
||||
vertex_and_table_t<T> as_mutable_table (unsigned parent, const void* offset, Ts... ds)
|
||||
{
|
||||
return as_table_from_index<T> (mutable_index_for_offset (parent, offset), std::forward<Ts>(ds)...);
|
||||
}
|
||||
|
||||
template <typename T, typename ...Ts>
|
||||
vertex_and_table_t<T> as_table_from_index (unsigned index, Ts... ds)
|
||||
{
|
||||
|
@ -833,7 +839,20 @@ struct graph_t
|
|||
* parent to the clone. The copy is a shallow copy, objects
|
||||
* linked from child are not duplicated.
|
||||
*/
|
||||
bool duplicate (unsigned parent_idx, unsigned child_idx)
|
||||
unsigned duplicate_if_shared (unsigned parent_idx, unsigned child_idx)
|
||||
{
|
||||
unsigned new_idx = duplicate (parent_idx, child_idx);
|
||||
if (new_idx == (unsigned) -1) return child_idx;
|
||||
return new_idx;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Creates a copy of child and re-assigns the link from
|
||||
* parent to the clone. The copy is a shallow copy, objects
|
||||
* linked from child are not duplicated.
|
||||
*/
|
||||
unsigned duplicate (unsigned parent_idx, unsigned child_idx)
|
||||
{
|
||||
update_parents ();
|
||||
|
||||
|
@ -849,7 +868,7 @@ struct graph_t
|
|||
// to child are from parent.
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr, " Not duplicating %d => %d",
|
||||
parent_idx, child_idx);
|
||||
return false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
DEBUG_MSG (SUBSET_REPACK, nullptr, " Duplicating %d => %d",
|
||||
|
@ -869,7 +888,7 @@ struct graph_t
|
|||
reassign_link (l, parent_idx, clone_idx);
|
||||
}
|
||||
|
||||
return true;
|
||||
return clone_idx;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -131,8 +131,10 @@ struct Lookup : public OT::Lookup
|
|||
for (unsigned i = 0; i < subTable.len; i++)
|
||||
{
|
||||
unsigned subtable_index = c.graph.index_for_offset (this_index, &subTable[i]);
|
||||
unsigned parent_index = this_index;
|
||||
if (is_ext) {
|
||||
unsigned ext_subtable_index = subtable_index;
|
||||
parent_index = ext_subtable_index;
|
||||
ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>* extension =
|
||||
(ExtensionFormat1<OT::Layout::GSUB_impl::ExtensionSubst>*)
|
||||
c.graph.object (ext_subtable_index).head;
|
||||
|
@ -150,9 +152,9 @@ struct Lookup : public OT::Lookup
|
|||
switch (type)
|
||||
{
|
||||
case 2:
|
||||
new_sub_tables = split_subtable<PairPos> (c, subtable_index); break;
|
||||
new_sub_tables = split_subtable<PairPos> (c, parent_index, subtable_index); break;
|
||||
case 4:
|
||||
new_sub_tables = split_subtable<MarkBasePos> (c, subtable_index); break;
|
||||
new_sub_tables = split_subtable<MarkBasePos> (c, parent_index, subtable_index); break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -172,13 +174,14 @@ struct Lookup : public OT::Lookup
|
|||
|
||||
template<typename T>
|
||||
hb_vector_t<unsigned> split_subtable (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_idx,
|
||||
unsigned objidx)
|
||||
{
|
||||
T* sub_table = (T*) c.graph.object (objidx).head;
|
||||
if (!sub_table || !sub_table->sanitize (c.graph.vertices_[objidx]))
|
||||
return hb_vector_t<unsigned> ();
|
||||
|
||||
return sub_table->split_subtables (c, objidx);
|
||||
return sub_table->split_subtables (c, parent_idx, objidx);
|
||||
}
|
||||
|
||||
void add_sub_tables (gsubgpos_graph_context_t& c,
|
||||
|
|
|
@ -209,7 +209,9 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
|||
return vertex_len >= MarkBasePosFormat1::static_size;
|
||||
}
|
||||
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
hb_set_t visited;
|
||||
|
||||
|
@ -261,7 +263,7 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
|||
split_context_t split_context {
|
||||
c,
|
||||
this,
|
||||
this_index,
|
||||
c.graph.duplicate_if_shared (parent_index, this_index),
|
||||
std::move (class_to_info),
|
||||
c.graph.vertices_[mark_array_id].position_to_index_map (),
|
||||
};
|
||||
|
@ -365,8 +367,8 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
|||
|
||||
classCount = count;
|
||||
|
||||
auto mark_coverage = sc.c.graph.as_table<Coverage> (this_index,
|
||||
&markCoverage);
|
||||
auto mark_coverage = sc.c.graph.as_mutable_table<Coverage> (this_index,
|
||||
&markCoverage);
|
||||
if (!mark_coverage) return false;
|
||||
hb_set_t marks = sc.marks_for (0, count);
|
||||
auto new_coverage =
|
||||
|
@ -380,17 +382,17 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
|||
return false;
|
||||
|
||||
|
||||
auto base_array = sc.c.graph.as_table<AnchorMatrix> (this_index,
|
||||
&baseArray,
|
||||
old_count);
|
||||
auto base_array = sc.c.graph.as_mutable_table<AnchorMatrix> (this_index,
|
||||
&baseArray,
|
||||
old_count);
|
||||
if (!base_array || !base_array.table->shrink (sc.c,
|
||||
base_array.index,
|
||||
old_count,
|
||||
count))
|
||||
return false;
|
||||
|
||||
auto mark_array = sc.c.graph.as_table<MarkArray> (this_index,
|
||||
&markArray);
|
||||
auto mark_array = sc.c.graph.as_mutable_table<MarkArray> (this_index,
|
||||
&markArray);
|
||||
if (!mark_array || !mark_array.table->shrink (sc.c,
|
||||
sc.mark_array_links,
|
||||
mark_array.index,
|
||||
|
@ -469,11 +471,12 @@ struct MarkBasePosFormat1 : public OT::Layout::GPOS_impl::MarkBasePosFormat1_2<S
|
|||
struct MarkBasePos : public OT::Layout::GPOS_impl::MarkBasePos
|
||||
{
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
switch (u.format) {
|
||||
case 1:
|
||||
return ((MarkBasePosFormat1*)(&u.format1))->split_subtables (c, this_index);
|
||||
return ((MarkBasePosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
case 2: HB_FALLTHROUGH;
|
||||
// Don't split 24bit PairPos's.
|
||||
|
|
71
thirdparty/harfbuzz/src/graph/pairpos-graph.hh
vendored
71
thirdparty/harfbuzz/src/graph/pairpos-graph.hh
vendored
|
@ -47,7 +47,9 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
|||
min_size + pairSet.get_size () - pairSet.len.get_size();
|
||||
}
|
||||
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
hb_set_t visited;
|
||||
|
||||
|
@ -81,7 +83,7 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
|||
split_context_t split_context {
|
||||
c,
|
||||
this,
|
||||
this_index,
|
||||
c.graph.duplicate_if_shared (parent_index, this_index),
|
||||
};
|
||||
|
||||
return actuate_subtable_split<split_context_t> (split_context, split_points);
|
||||
|
@ -125,23 +127,19 @@ struct PairPosFormat1 : public OT::Layout::GPOS_impl::PairPosFormat1_3<SmallType
|
|||
pairSet.len = count;
|
||||
c.graph.vertices_[this_index].obj.tail -= (old_count - count) * SmallTypes::size;
|
||||
|
||||
unsigned coverage_id = c.graph.mutable_index_for_offset (this_index, &coverage);
|
||||
unsigned coverage_size = c.graph.vertices_[coverage_id].table_size ();
|
||||
auto& coverage_v = c.graph.vertices_[coverage_id];
|
||||
|
||||
Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
|
||||
if (!coverage_table || !coverage_table->sanitize (coverage_v))
|
||||
return false;
|
||||
auto coverage = c.graph.as_mutable_table<Coverage> (this_index, &this->coverage);
|
||||
if (!coverage) return false;
|
||||
|
||||
unsigned coverage_size = coverage.vertex->table_size ();
|
||||
auto new_coverage =
|
||||
+ hb_zip (coverage_table->iter (), hb_range ())
|
||||
+ hb_zip (coverage.table->iter (), hb_range ())
|
||||
| hb_filter ([&] (hb_pair_t<unsigned, unsigned> p) {
|
||||
return p.second < count;
|
||||
})
|
||||
| hb_map_retains_sorting (hb_first)
|
||||
;
|
||||
|
||||
return Coverage::make_coverage (c, new_coverage, coverage_id, coverage_size);
|
||||
return Coverage::make_coverage (c, new_coverage, coverage.index, coverage_size);
|
||||
}
|
||||
|
||||
// Create a new PairPos including PairSet's from start (inclusive) to end (exclusive).
|
||||
|
@ -206,7 +204,9 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
|
|||
min_size + class1_count * get_class1_record_size ();
|
||||
}
|
||||
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
const unsigned base_size = OT::Layout::GPOS_impl::PairPosFormat2_4<SmallTypes>::min_size;
|
||||
const unsigned class_def_2_size = size_of (c, this_index, &classDef2);
|
||||
|
@ -287,7 +287,7 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
|
|||
split_context_t split_context {
|
||||
c,
|
||||
this,
|
||||
this_index,
|
||||
c.graph.duplicate_if_shared (parent_index, this_index),
|
||||
class1_record_size,
|
||||
total_value_len,
|
||||
value_1_len,
|
||||
|
@ -508,40 +508,37 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
|
|||
graph.vertices_[split_context.this_index].obj.tail -=
|
||||
(old_count - count) * split_context.class1_record_size;
|
||||
|
||||
unsigned coverage_id =
|
||||
graph.mutable_index_for_offset (split_context.this_index, &coverage);
|
||||
unsigned class_def_1_id =
|
||||
graph.mutable_index_for_offset (split_context.this_index, &classDef1);
|
||||
auto& coverage_v = graph.vertices_[coverage_id];
|
||||
auto& class_def_1_v = graph.vertices_[class_def_1_id];
|
||||
Coverage* coverage_table = (Coverage*) coverage_v.obj.head;
|
||||
ClassDef* class_def_1_table = (ClassDef*) class_def_1_v.obj.head;
|
||||
if (!coverage_table
|
||||
|| !coverage_table->sanitize (coverage_v)
|
||||
|| !class_def_1_table
|
||||
|| !class_def_1_table->sanitize (class_def_1_v))
|
||||
return false;
|
||||
auto coverage =
|
||||
graph.as_mutable_table<Coverage> (split_context.this_index, &this->coverage);
|
||||
if (!coverage) return false;
|
||||
|
||||
auto class_def_1 =
|
||||
graph.as_mutable_table<ClassDef> (split_context.this_index, &classDef1);
|
||||
if (!class_def_1) return false;
|
||||
|
||||
auto klass_map =
|
||||
+ coverage_table->iter ()
|
||||
+ coverage.table->iter ()
|
||||
| hb_map_retains_sorting ([&] (hb_codepoint_t gid) {
|
||||
return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1_table->get_class (gid));
|
||||
return hb_pair_t<hb_codepoint_t, hb_codepoint_t> (gid, class_def_1.table->get_class (gid));
|
||||
})
|
||||
| hb_filter ([&] (hb_codepoint_t klass) {
|
||||
return klass < count;
|
||||
}, hb_second)
|
||||
;
|
||||
|
||||
auto new_coverage = + klass_map | hb_map_retains_sorting (hb_first);
|
||||
if (!Coverage::make_coverage (split_context.c,
|
||||
+ klass_map | hb_map_retains_sorting (hb_first),
|
||||
coverage_id,
|
||||
coverage_v.table_size ()))
|
||||
+ new_coverage,
|
||||
coverage.index,
|
||||
// existing ranges my not be kept, worst case size is a format 1
|
||||
// coverage table.
|
||||
4 + new_coverage.len() * 2))
|
||||
return false;
|
||||
|
||||
return ClassDef::make_class_def (split_context.c,
|
||||
+ klass_map,
|
||||
class_def_1_id,
|
||||
class_def_1_v.table_size ());
|
||||
class_def_1.index,
|
||||
class_def_1.vertex->table_size ());
|
||||
}
|
||||
|
||||
hb_hashmap_t<unsigned, unsigned>
|
||||
|
@ -605,13 +602,15 @@ struct PairPosFormat2 : public OT::Layout::GPOS_impl::PairPosFormat2_4<SmallType
|
|||
|
||||
struct PairPos : public OT::Layout::GPOS_impl::PairPos
|
||||
{
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c, unsigned this_index)
|
||||
hb_vector_t<unsigned> split_subtables (gsubgpos_graph_context_t& c,
|
||||
unsigned parent_index,
|
||||
unsigned this_index)
|
||||
{
|
||||
switch (u.format) {
|
||||
case 1:
|
||||
return ((PairPosFormat1*)(&u.format1))->split_subtables (c, this_index);
|
||||
return ((PairPosFormat1*)(&u.format1))->split_subtables (c, parent_index, this_index);
|
||||
case 2:
|
||||
return ((PairPosFormat2*)(&u.format2))->split_subtables (c, this_index);
|
||||
return ((PairPosFormat2*)(&u.format2))->split_subtables (c, parent_index, this_index);
|
||||
#ifndef HB_NO_BORING_EXPANSION
|
||||
case 3: HB_FALLTHROUGH;
|
||||
case 4: HB_FALLTHROUGH;
|
||||
|
|
|
@ -70,9 +70,9 @@ struct DecompositionAction
|
|||
|
||||
ActionSubrecordHeader
|
||||
header;
|
||||
HBFixed lowerLimit; /* If the distance factor is less than this value,
|
||||
F16DOT16 lowerLimit; /* If the distance factor is less than this value,
|
||||
* then the ligature is decomposed. */
|
||||
HBFixed upperLimit; /* If the distance factor is greater than this value,
|
||||
F16DOT16 upperLimit; /* If the distance factor is greater than this value,
|
||||
* then the ligature is decomposed. */
|
||||
HBUINT16 order; /* Numerical order in which this ligature will
|
||||
* be decomposed; you may want infrequent ligatures
|
||||
|
@ -118,7 +118,7 @@ struct ConditionalAddGlyphAction
|
|||
protected:
|
||||
ActionSubrecordHeader
|
||||
header;
|
||||
HBFixed substThreshold; /* Distance growth factor (in ems) at which
|
||||
F16DOT16 substThreshold; /* Distance growth factor (in ems) at which
|
||||
* this glyph is replaced and the growth factor
|
||||
* recalculated. */
|
||||
HBGlyphID16 addGlyph; /* Glyph to be added as kashida. If this value is
|
||||
|
@ -146,13 +146,13 @@ struct DuctileGlyphAction
|
|||
HBUINT32 variationAxis; /* The 4-byte tag identifying the ductile axis.
|
||||
* This would normally be 0x64756374 ('duct'),
|
||||
* but you may use any axis the font contains. */
|
||||
HBFixed minimumLimit; /* The lowest value for the ductility axis that
|
||||
F16DOT16 minimumLimit; /* The lowest value for the ductility axis that
|
||||
* still yields an acceptable appearance. Normally
|
||||
* this will be 1.0. */
|
||||
HBFixed noStretchValue; /* This is the default value that corresponds to
|
||||
F16DOT16 noStretchValue; /* This is the default value that corresponds to
|
||||
* no change in appearance. Normally, this will
|
||||
* be 1.0. */
|
||||
HBFixed maximumLimit; /* The highest value for the ductility axis that
|
||||
F16DOT16 maximumLimit; /* The highest value for the ductility axis that
|
||||
* still yields an acceptable appearance. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (22);
|
||||
|
@ -271,14 +271,14 @@ struct JustWidthDeltaEntry
|
|||
};
|
||||
|
||||
protected:
|
||||
HBFixed beforeGrowLimit;/* The ratio by which the advance width of the
|
||||
F16DOT16 beforeGrowLimit;/* The ratio by which the advance width of the
|
||||
* glyph is permitted to grow on the left or top side. */
|
||||
HBFixed beforeShrinkLimit;
|
||||
F16DOT16 beforeShrinkLimit;
|
||||
/* The ratio by which the advance width of the
|
||||
* glyph is permitted to shrink on the left or top side. */
|
||||
HBFixed afterGrowLimit; /* The ratio by which the advance width of the glyph
|
||||
F16DOT16 afterGrowLimit; /* The ratio by which the advance width of the glyph
|
||||
* is permitted to shrink on the left or top side. */
|
||||
HBFixed afterShrinkLimit;
|
||||
F16DOT16 afterShrinkLimit;
|
||||
/* The ratio by which the advance width of the glyph
|
||||
* is at most permitted to shrink on the right or
|
||||
* bottom side. */
|
||||
|
|
|
@ -62,7 +62,7 @@ struct TrackTableEntry
|
|||
}
|
||||
|
||||
protected:
|
||||
HBFixed track; /* Track value for this record. */
|
||||
F16DOT16 track; /* Track value for this record. */
|
||||
NameID trackNameID; /* The 'name' table index for this track.
|
||||
* (a short word or phrase like "loose"
|
||||
* or "very tight") */
|
||||
|
@ -82,7 +82,7 @@ struct TrackData
|
|||
const void *base) const
|
||||
{
|
||||
unsigned int sizes = nSizes;
|
||||
hb_array_t<const HBFixed> size_table ((base+sizeTable).arrayZ, sizes);
|
||||
hb_array_t<const F16DOT16> size_table ((base+sizeTable).arrayZ, sizes);
|
||||
|
||||
float s0 = size_table[idx].to_float ();
|
||||
float s1 = size_table[idx + 1].to_float ();
|
||||
|
@ -120,7 +120,7 @@ struct TrackData
|
|||
if (!sizes) return 0.;
|
||||
if (sizes == 1) return trackTableEntry->get_value (base, 0, sizes);
|
||||
|
||||
hb_array_t<const HBFixed> size_table ((base+sizeTable).arrayZ, sizes);
|
||||
hb_array_t<const F16DOT16> size_table ((base+sizeTable).arrayZ, sizes);
|
||||
unsigned int size_index;
|
||||
for (size_index = 0; size_index < sizes - 1; size_index++)
|
||||
if (size_table[size_index].to_float () >= ptem)
|
||||
|
@ -141,7 +141,7 @@ struct TrackData
|
|||
protected:
|
||||
HBUINT16 nTracks; /* Number of separate tracks included in this table. */
|
||||
HBUINT16 nSizes; /* Number of point sizes included in this table. */
|
||||
NNOffset32To<UnsizedArrayOf<HBFixed>>
|
||||
NNOffset32To<UnsizedArrayOf<F16DOT16>>
|
||||
sizeTable; /* Offset from start of the tracking table to
|
||||
* Array[nSizes] of size values.. */
|
||||
UnsizedArrayOf<TrackTableEntry>
|
||||
|
|
1
thirdparty/harfbuzz/src/hb-aat-layout.cc
vendored
1
thirdparty/harfbuzz/src/hb-aat-layout.cc
vendored
|
@ -131,6 +131,7 @@ static const hb_aat_feature_mapping_t feature_mappings[] =
|
|||
{HB_TAG ('p','n','u','m'), HB_AAT_LAYOUT_FEATURE_TYPE_NUMBER_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_NUMBERS, (hb_aat_layout_feature_selector_t) 4},
|
||||
{HB_TAG ('p','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_PROPORTIONAL_TEXT, (hb_aat_layout_feature_selector_t) 7},
|
||||
{HB_TAG ('q','w','i','d'), HB_AAT_LAYOUT_FEATURE_TYPE_TEXT_SPACING, HB_AAT_LAYOUT_FEATURE_SELECTOR_QUARTER_WIDTH_TEXT, (hb_aat_layout_feature_selector_t) 7},
|
||||
{HB_TAG ('r','l','i','g'), HB_AAT_LAYOUT_FEATURE_TYPE_LIGATURES, HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_REQUIRED_LIGATURES_OFF},
|
||||
{HB_TAG ('r','u','b','y'), HB_AAT_LAYOUT_FEATURE_TYPE_RUBY_KANA, HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_ON, HB_AAT_LAYOUT_FEATURE_SELECTOR_RUBY_KANA_OFF},
|
||||
{HB_TAG ('s','i','n','f'), HB_AAT_LAYOUT_FEATURE_TYPE_VERTICAL_POSITION, HB_AAT_LAYOUT_FEATURE_SELECTOR_SCIENTIFIC_INFERIORS, HB_AAT_LAYOUT_FEATURE_SELECTOR_NORMAL_POSITION},
|
||||
{HB_TAG ('s','m','c','p'), HB_AAT_LAYOUT_FEATURE_TYPE_LOWER_CASE, HB_AAT_LAYOUT_FEATURE_SELECTOR_LOWER_CASE_SMALL_CAPS, HB_AAT_LAYOUT_FEATURE_SELECTOR_DEFAULT_LOWER_CASE},
|
||||
|
|
1
thirdparty/harfbuzz/src/hb-config.hh
vendored
1
thirdparty/harfbuzz/src/hb-config.hh
vendored
|
@ -71,6 +71,7 @@
|
|||
#define HB_NO_LANGUAGE_PRIVATE_SUBTAG
|
||||
#define HB_NO_LAYOUT_FEATURE_PARAMS
|
||||
#define HB_NO_LAYOUT_COLLECT_GLYPHS
|
||||
#define HB_NO_LAYOUT_RARELY_USED
|
||||
#define HB_NO_LAYOUT_UNUSED
|
||||
#define HB_NO_MATH
|
||||
#define HB_NO_META
|
||||
|
|
6
thirdparty/harfbuzz/src/hb-cplusplus.hh
vendored
6
thirdparty/harfbuzz/src/hb-cplusplus.hh
vendored
|
@ -69,9 +69,9 @@ struct shared_ptr
|
|||
operator T * () const { return p; }
|
||||
T& operator * () const { return *get (); }
|
||||
T* operator -> () const { return get (); }
|
||||
operator bool () { return p; }
|
||||
bool operator == (const shared_ptr &o) { return p == o.p; }
|
||||
bool operator != (const shared_ptr &o) { return p != o.p; }
|
||||
operator bool () const { return p; }
|
||||
bool operator == (const shared_ptr &o) const { return p == o.p; }
|
||||
bool operator != (const shared_ptr &o) const { return p != o.p; }
|
||||
|
||||
static T* get_empty() { return v::get_empty (); }
|
||||
T* reference() { return v::reference (p); }
|
||||
|
|
76
thirdparty/harfbuzz/src/hb-face.cc
vendored
76
thirdparty/harfbuzz/src/hb-face.cc
vendored
|
@ -633,20 +633,29 @@ hb_face_collect_variation_unicodes (hb_face_t *face,
|
|||
* face-builder: A face that has add_table().
|
||||
*/
|
||||
|
||||
struct face_table_info_t
|
||||
{
|
||||
hb_blob_t* data;
|
||||
unsigned order;
|
||||
};
|
||||
|
||||
struct hb_face_builder_data_t
|
||||
{
|
||||
hb_hashmap_t<hb_tag_t, hb_blob_t *> tables;
|
||||
hb_hashmap_t<hb_tag_t, face_table_info_t> tables;
|
||||
};
|
||||
|
||||
static int compare_entries (const void* pa, const void* pb)
|
||||
{
|
||||
const auto& a = * (const hb_pair_t<hb_tag_t, hb_blob_t*> *) pa;
|
||||
const auto& b = * (const hb_pair_t<hb_tag_t, hb_blob_t*> *) pb;
|
||||
const auto& a = * (const hb_pair_t<hb_tag_t, face_table_info_t> *) pa;
|
||||
const auto& b = * (const hb_pair_t<hb_tag_t, face_table_info_t> *) pb;
|
||||
|
||||
/* Order by blob size first (smallest to largest) and then table tag */
|
||||
|
||||
if (a.second->length != b.second->length)
|
||||
return a.second->length < b.second->length ? -1 : +1;
|
||||
if (a.second.order != b.second.order)
|
||||
return a.second.order < b.second.order ? -1 : +1;
|
||||
|
||||
if (a.second.data->length != b.second.data->length)
|
||||
return a.second.data->length < b.second.data->length ? -1 : +1;
|
||||
|
||||
return a.first < b.first ? -1 : a.first == b.first ? 0 : +1;
|
||||
}
|
||||
|
@ -668,8 +677,8 @@ _hb_face_builder_data_destroy (void *user_data)
|
|||
{
|
||||
hb_face_builder_data_t *data = (hb_face_builder_data_t *) user_data;
|
||||
|
||||
for (hb_blob_t* b : data->tables.values())
|
||||
hb_blob_destroy (b);
|
||||
for (auto info : data->tables.values())
|
||||
hb_blob_destroy (info.data);
|
||||
|
||||
data->tables.fini ();
|
||||
|
||||
|
@ -683,8 +692,8 @@ _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
|
|||
unsigned int table_count = data->tables.get_population ();
|
||||
unsigned int face_length = table_count * 16 + 12;
|
||||
|
||||
for (hb_blob_t* b : data->tables.values())
|
||||
face_length += hb_ceil_to_4 (hb_blob_get_length (b));
|
||||
for (auto info : data->tables.values())
|
||||
face_length += hb_ceil_to_4 (hb_blob_get_length (info.data));
|
||||
|
||||
char *buf = (char *) hb_malloc (face_length);
|
||||
if (unlikely (!buf))
|
||||
|
@ -699,7 +708,7 @@ _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
|
|||
hb_tag_t sfnt_tag = is_cff ? OT::OpenTypeFontFile::CFFTag : OT::OpenTypeFontFile::TrueTypeTag;
|
||||
|
||||
// Sort the tags so that produced face is deterministic.
|
||||
hb_vector_t<hb_pair_t <hb_tag_t, hb_blob_t*>> sorted_entries;
|
||||
hb_vector_t<hb_pair_t <hb_tag_t, face_table_info_t>> sorted_entries;
|
||||
data->tables.iter () | hb_sink (sorted_entries);
|
||||
if (unlikely (sorted_entries.in_error ()))
|
||||
{
|
||||
|
@ -708,7 +717,13 @@ _hb_face_builder_data_reference_blob (hb_face_builder_data_t *data)
|
|||
}
|
||||
|
||||
sorted_entries.qsort (compare_entries);
|
||||
bool ret = f->serialize_single (&c, sfnt_tag, + sorted_entries.iter());
|
||||
|
||||
bool ret = f->serialize_single (&c,
|
||||
sfnt_tag,
|
||||
+ sorted_entries.iter()
|
||||
| hb_map ([&] (hb_pair_t<hb_tag_t, face_table_info_t> _) {
|
||||
return hb_pair_t<hb_tag_t, hb_blob_t*> (_.first, _.second.data);
|
||||
}));
|
||||
|
||||
c.end_serialize ();
|
||||
|
||||
|
@ -729,7 +744,7 @@ _hb_face_builder_reference_table (hb_face_t *face HB_UNUSED, hb_tag_t tag, void
|
|||
if (!tag)
|
||||
return _hb_face_builder_data_reference_blob (data);
|
||||
|
||||
return hb_blob_reference (data->tables[tag]);
|
||||
return hb_blob_reference (data->tables[tag].data);
|
||||
}
|
||||
|
||||
|
||||
|
@ -777,8 +792,8 @@ hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
|
|||
|
||||
hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
|
||||
|
||||
hb_blob_t* previous = data->tables.get (tag);
|
||||
if (!data->tables.set (tag, hb_blob_reference (blob)))
|
||||
hb_blob_t* previous = data->tables.get (tag).data;
|
||||
if (!data->tables.set (tag, face_table_info_t {hb_blob_reference (blob), 0}))
|
||||
{
|
||||
hb_blob_destroy (blob);
|
||||
return false;
|
||||
|
@ -787,3 +802,36 @@ hb_face_builder_add_table (hb_face_t *face, hb_tag_t tag, hb_blob_t *blob)
|
|||
hb_blob_destroy (previous);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_face_builder_sort_tables:
|
||||
* @face: A face object created with hb_face_builder_create()
|
||||
* @tags: (array zero-terminated=1): ordered list of table tags terminated by
|
||||
* %HB_TAG_NONE
|
||||
*
|
||||
* Set the ordering of tables for serialization. Any tables not
|
||||
* specified in the tags list will be ordered after the tables in
|
||||
* tags, ordered by the default sort ordering.
|
||||
*
|
||||
* Since: 5.3.0
|
||||
**/
|
||||
void
|
||||
hb_face_builder_sort_tables (hb_face_t *face,
|
||||
const hb_tag_t *tags)
|
||||
{
|
||||
hb_face_builder_data_t *data = (hb_face_builder_data_t *) face->user_data;
|
||||
|
||||
// Sort all unspecified tables after any specified tables.
|
||||
for (auto& info : data->tables.values_ref())
|
||||
info.order = -1;
|
||||
|
||||
unsigned order = 0;
|
||||
for (const hb_tag_t* tag = tags;
|
||||
*tag;
|
||||
tag++)
|
||||
{
|
||||
face_table_info_t* info;
|
||||
if (!data->tables.has (*tag, &info)) continue;
|
||||
info->order = order++;
|
||||
}
|
||||
}
|
||||
|
|
4
thirdparty/harfbuzz/src/hb-face.h
vendored
4
thirdparty/harfbuzz/src/hb-face.h
vendored
|
@ -171,6 +171,10 @@ hb_face_builder_add_table (hb_face_t *face,
|
|||
hb_tag_t tag,
|
||||
hb_blob_t *blob);
|
||||
|
||||
HB_EXTERN void
|
||||
hb_face_builder_sort_tables (hb_face_t *face,
|
||||
const hb_tag_t *tags);
|
||||
|
||||
|
||||
HB_END_DECLS
|
||||
|
||||
|
|
12
thirdparty/harfbuzz/src/hb-meta.hh
vendored
12
thirdparty/harfbuzz/src/hb-meta.hh
vendored
|
@ -133,6 +133,18 @@ struct
|
|||
|
||||
template <typename T> constexpr auto
|
||||
operator () (T *v) const HB_AUTO_RETURN (*v)
|
||||
|
||||
template <typename T> constexpr auto
|
||||
operator () (const hb::shared_ptr<T>& v) const HB_AUTO_RETURN (*v)
|
||||
|
||||
template <typename T> constexpr auto
|
||||
operator () (hb::shared_ptr<T>& v) const HB_AUTO_RETURN (*v)
|
||||
|
||||
template <typename T> constexpr auto
|
||||
operator () (const hb::unique_ptr<T>& v) const HB_AUTO_RETURN (*v)
|
||||
|
||||
template <typename T> constexpr auto
|
||||
operator () (hb::unique_ptr<T>& v) const HB_AUTO_RETURN (*v)
|
||||
}
|
||||
HB_FUNCOBJ (hb_deref);
|
||||
|
||||
|
|
29
thirdparty/harfbuzz/src/hb-open-type.hh
vendored
29
thirdparty/harfbuzz/src/hb-open-type.hh
vendored
|
@ -141,27 +141,24 @@ typedef HBINT32 FWORD32;
|
|||
/* 16-bit unsigned integer (HBUINT16) that describes a quantity in FUnits. */
|
||||
typedef HBUINT16 UFWORD;
|
||||
|
||||
/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
|
||||
struct F2DOT14 : HBINT16
|
||||
template <typename Type, unsigned fraction_bits>
|
||||
struct HBFixed : Type
|
||||
{
|
||||
F2DOT14& operator = (uint16_t i ) { HBINT16::operator= (i); return *this; }
|
||||
// 16384 means 1<<14
|
||||
float to_float () const { return ((int32_t) v) / 16384.f; }
|
||||
void set_float (float f) { v = roundf (f * 16384.f); }
|
||||
static constexpr float shift = (float) (1 << fraction_bits);
|
||||
static_assert (Type::static_size * 8 > fraction_bits, "");
|
||||
|
||||
HBFixed& operator = (typename Type::type i ) { Type::operator= (i); return *this; }
|
||||
float to_float () const { return ((int32_t) Type::v) / shift; }
|
||||
void set_float (float f) { Type::v = roundf (f * shift); }
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (2);
|
||||
DEFINE_SIZE_STATIC (Type::static_size);
|
||||
};
|
||||
|
||||
/* 16-bit signed fixed number with the low 14 bits of fraction (2.14). */
|
||||
using F2DOT14 = HBFixed<HBINT16, 14>;
|
||||
|
||||
/* 32-bit signed fixed-point number (16.16). */
|
||||
struct HBFixed : HBINT32
|
||||
{
|
||||
HBFixed& operator = (uint32_t i) { HBINT32::operator= (i); return *this; }
|
||||
// 65536 means 1<<16
|
||||
float to_float () const { return ((int32_t) v) / 65536.f; }
|
||||
void set_float (float f) { v = roundf (f * 65536.f); }
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (4);
|
||||
};
|
||||
using F16DOT16 = HBFixed<HBINT32, 16>;
|
||||
|
||||
/* Date represented in number of seconds since 12:00 midnight, January 1,
|
||||
* 1904. The value is represented as a signed 64-bit integer. */
|
||||
|
|
|
@ -358,14 +358,14 @@ struct Affine2x3
|
|||
return_trace (c->check_struct (this));
|
||||
}
|
||||
|
||||
HBFixed xx;
|
||||
HBFixed yx;
|
||||
HBFixed xy;
|
||||
HBFixed yy;
|
||||
HBFixed dx;
|
||||
HBFixed dy;
|
||||
F16DOT16 xx;
|
||||
F16DOT16 yx;
|
||||
F16DOT16 xy;
|
||||
F16DOT16 yy;
|
||||
F16DOT16 dx;
|
||||
F16DOT16 dy;
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6 * HBFixed::static_size);
|
||||
DEFINE_SIZE_STATIC (6 * F16DOT16::static_size);
|
||||
};
|
||||
|
||||
struct PaintColrLayers
|
||||
|
|
4
thirdparty/harfbuzz/src/hb-ot-color.cc
vendored
4
thirdparty/harfbuzz/src/hb-ot-color.cc
vendored
|
@ -295,8 +295,8 @@ hb_ot_color_has_png (hb_face_t *face)
|
|||
* @glyph: a glyph index
|
||||
*
|
||||
* Fetches the PNG image for a glyph. This function takes a font object, not a face object,
|
||||
* as input. To get an optimally sized PNG blob, the UPEM value must be set on the @font
|
||||
* object. If UPEM is unset, the blob returned will be the largest PNG available.
|
||||
* as input. To get an optimally sized PNG blob, the PPEM values must be set on the @font
|
||||
* object. If PPEM is unset, the blob returned will be the largest PNG available.
|
||||
*
|
||||
* If the glyph has no PNG image, the singleton empty blob is returned.
|
||||
*
|
||||
|
|
5
thirdparty/harfbuzz/src/hb-ot-font.cc
vendored
5
thirdparty/harfbuzz/src/hb-ot-font.cc
vendored
|
@ -40,7 +40,6 @@
|
|||
#include "hb-ot-cff1-table.hh"
|
||||
#include "hb-ot-cff2-table.hh"
|
||||
#include "hb-ot-hmtx-table.hh"
|
||||
#include "hb-ot-os2-table.hh"
|
||||
#include "hb-ot-post-table.hh"
|
||||
#include "hb-ot-stat-table.hh" // Just so we compile it; unused otherwise.
|
||||
#include "hb-ot-vorg-table.hh"
|
||||
|
@ -349,15 +348,13 @@ hb_ot_get_glyph_extents (hb_font_t *font,
|
|||
|
||||
#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
|
||||
if (ot_face->sbix->get_extents (font, glyph, extents)) return true;
|
||||
if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
|
||||
#endif
|
||||
if (ot_face->glyf->get_extents (font, glyph, extents)) return true;
|
||||
#ifndef HB_NO_OT_FONT_CFF
|
||||
if (ot_face->cff1->get_extents (font, glyph, extents)) return true;
|
||||
if (ot_face->cff2->get_extents (font, glyph, extents)) return true;
|
||||
#endif
|
||||
#if !defined(HB_NO_OT_FONT_BITMAP) && !defined(HB_NO_COLOR)
|
||||
if (ot_face->CBDT->get_extents (font, glyph, extents)) return true;
|
||||
#endif
|
||||
|
||||
// TODO Hook up side-bearings variations.
|
||||
return false;
|
||||
|
|
469
thirdparty/harfbuzz/src/hb-ot-layout-common.hh
vendored
469
thirdparty/harfbuzz/src/hb-ot-layout-common.hh
vendored
|
@ -94,6 +94,19 @@ static bool ClassDef_remap_and_serialize (
|
|||
hb_sorted_vector_t<hb_pair_t<hb_codepoint_t, hb_codepoint_t>> &glyph_and_klass, /* IN/OUT */
|
||||
hb_map_t *klass_map /*IN/OUT*/);
|
||||
|
||||
struct hb_collect_feature_substitutes_with_var_context_t
|
||||
{
|
||||
const hb_map_t *axes_index_tag_map;
|
||||
const hb_hashmap_t<hb_tag_t, int> *axes_location;
|
||||
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *record_cond_idx_map;
|
||||
hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map;
|
||||
|
||||
// not stored in subset_plan
|
||||
hb_set_t *feature_indices;
|
||||
bool apply;
|
||||
unsigned cur_record_idx;
|
||||
hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> *conditionset_map;
|
||||
};
|
||||
|
||||
struct hb_prune_langsys_context_t
|
||||
{
|
||||
|
@ -160,24 +173,40 @@ struct hb_subset_layout_context_t :
|
|||
const hb_map_t *lookup_index_map;
|
||||
const hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map;
|
||||
const hb_map_t *feature_index_map;
|
||||
const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map;
|
||||
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map;
|
||||
|
||||
unsigned cur_script_index;
|
||||
unsigned cur_feature_var_record_idx;
|
||||
|
||||
hb_subset_layout_context_t (hb_subset_context_t *c_,
|
||||
hb_tag_t tag_,
|
||||
hb_map_t *lookup_map_,
|
||||
hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> *script_langsys_map_,
|
||||
hb_map_t *feature_index_map_) :
|
||||
hb_tag_t tag_) :
|
||||
subset_context (c_),
|
||||
table_tag (tag_),
|
||||
lookup_index_map (lookup_map_),
|
||||
script_langsys_map (script_langsys_map_),
|
||||
feature_index_map (feature_index_map_),
|
||||
cur_script_index (0xFFFFu),
|
||||
cur_feature_var_record_idx (0u),
|
||||
script_count (0),
|
||||
langsys_count (0),
|
||||
feature_index_count (0),
|
||||
lookup_index_count (0)
|
||||
{}
|
||||
{
|
||||
if (tag_ == HB_OT_TAG_GSUB)
|
||||
{
|
||||
lookup_index_map = c_->plan->gsub_lookups;
|
||||
script_langsys_map = c_->plan->gsub_langsys;
|
||||
feature_index_map = c_->plan->gsub_features;
|
||||
feature_substitutes_map = c_->plan->gsub_feature_substitutes_map;
|
||||
feature_record_cond_idx_map = c_->plan->user_axes_location->is_empty () ? nullptr : c_->plan->gsub_feature_record_cond_idx_map;
|
||||
}
|
||||
else
|
||||
{
|
||||
lookup_index_map = c_->plan->gpos_lookups;
|
||||
script_langsys_map = c_->plan->gpos_langsys;
|
||||
feature_index_map = c_->plan->gpos_features;
|
||||
feature_substitutes_map = c_->plan->gpos_feature_substitutes_map;
|
||||
feature_record_cond_idx_map = c_->plan->user_axes_location->is_empty () ? nullptr : c_->plan->gpos_feature_record_cond_idx_map;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
unsigned script_count;
|
||||
|
@ -324,6 +353,31 @@ struct subset_record_array_t
|
|||
const void *base;
|
||||
};
|
||||
|
||||
template<typename OutputArray, typename Arg>
|
||||
struct subset_record_array_arg_t
|
||||
{
|
||||
subset_record_array_arg_t (hb_subset_layout_context_t *c_, OutputArray* out_,
|
||||
const void *base_,
|
||||
Arg &&arg_) : subset_layout_context (c_),
|
||||
out (out_), base (base_), arg (arg_) {}
|
||||
|
||||
template <typename T>
|
||||
void
|
||||
operator () (T&& record)
|
||||
{
|
||||
auto snap = subset_layout_context->subset_context->serializer->snapshot ();
|
||||
bool ret = record.subset (subset_layout_context, base, arg);
|
||||
if (!ret) subset_layout_context->subset_context->serializer->revert (snap);
|
||||
else out->len++;
|
||||
}
|
||||
|
||||
private:
|
||||
hb_subset_layout_context_t *subset_layout_context;
|
||||
OutputArray *out;
|
||||
const void *base;
|
||||
Arg &&arg;
|
||||
};
|
||||
|
||||
/*
|
||||
* Helper to subset a RecordList/record array. Subsets each Record in the array and
|
||||
* discards the record if the subset operation returns false.
|
||||
|
@ -335,6 +389,13 @@ struct
|
|||
operator () (hb_subset_layout_context_t *c, OutputArray* out,
|
||||
const void *base) const
|
||||
{ return subset_record_array_t<OutputArray> (c, out, base); }
|
||||
|
||||
/* Variant with one extra argument passed to subset */
|
||||
template<typename OutputArray, typename Arg>
|
||||
subset_record_array_arg_t<OutputArray, Arg>
|
||||
operator () (hb_subset_layout_context_t *c, OutputArray* out,
|
||||
const void *base, Arg &&arg) const
|
||||
{ return subset_record_array_arg_t<OutputArray, Arg> (c, out, base, arg); }
|
||||
}
|
||||
HB_FUNCOBJ (subset_record_array);
|
||||
|
||||
|
@ -431,94 +492,6 @@ struct IndexArray : Array16Of<Index>
|
|||
};
|
||||
|
||||
|
||||
struct Record_sanitize_closure_t {
|
||||
hb_tag_t tag;
|
||||
const void *list_base;
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct Record
|
||||
{
|
||||
int cmp (hb_tag_t a) const { return tag.cmp (a); }
|
||||
|
||||
bool subset (hb_subset_layout_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->subset_context->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
bool ret = out->offset.serialize_subset (c->subset_context, offset, base, c, &tag);
|
||||
return_trace (ret);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
const Record_sanitize_closure_t closure = {tag, base};
|
||||
return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
|
||||
}
|
||||
|
||||
Tag tag; /* 4-byte Tag identifier */
|
||||
Offset16To<Type>
|
||||
offset; /* Offset from beginning of object holding
|
||||
* the Record */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct RecordArrayOf : SortedArray16Of<Record<Type>>
|
||||
{
|
||||
const Offset16To<Type>& get_offset (unsigned int i) const
|
||||
{ return (*this)[i].offset; }
|
||||
Offset16To<Type>& get_offset (unsigned int i)
|
||||
{ return (*this)[i].offset; }
|
||||
const Tag& get_tag (unsigned int i) const
|
||||
{ return (*this)[i].tag; }
|
||||
unsigned int get_tags (unsigned int start_offset,
|
||||
unsigned int *record_count /* IN/OUT */,
|
||||
hb_tag_t *record_tags /* OUT */) const
|
||||
{
|
||||
if (record_count)
|
||||
{
|
||||
+ this->sub_array (start_offset, record_count)
|
||||
| hb_map (&Record<Type>::tag)
|
||||
| hb_sink (hb_array (record_tags, *record_count))
|
||||
;
|
||||
}
|
||||
return this->len;
|
||||
}
|
||||
bool find_index (hb_tag_t tag, unsigned int *index) const
|
||||
{
|
||||
return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct RecordListOf : RecordArrayOf<Type>
|
||||
{
|
||||
const Type& operator [] (unsigned int i) const
|
||||
{ return this+this->get_offset (i); }
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
hb_subset_layout_context_t *l) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
+ this->iter ()
|
||||
| hb_apply (subset_record_array (l, out, this))
|
||||
;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (RecordArrayOf<Type>::sanitize (c, this));
|
||||
}
|
||||
};
|
||||
|
||||
/* https://docs.microsoft.com/en-us/typography/opentype/spec/features_pt#size */
|
||||
struct FeatureParamsSize
|
||||
{
|
||||
|
@ -801,6 +774,10 @@ struct FeatureParams
|
|||
DEFINE_SIZE_MIN (0);
|
||||
};
|
||||
|
||||
struct Record_sanitize_closure_t {
|
||||
hb_tag_t tag;
|
||||
const void *list_base;
|
||||
};
|
||||
|
||||
struct Feature
|
||||
{
|
||||
|
@ -897,6 +874,103 @@ struct Feature
|
|||
DEFINE_SIZE_ARRAY_SIZED (4, lookupIndex);
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct Record
|
||||
{
|
||||
int cmp (hb_tag_t a) const { return tag.cmp (a); }
|
||||
|
||||
bool subset (hb_subset_layout_context_t *c, const void *base, const void *f_sub = nullptr) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->subset_context->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (!f_sub)
|
||||
return_trace (out->offset.serialize_subset (c->subset_context, offset, base, c, &tag));
|
||||
|
||||
const Feature& f = *reinterpret_cast<const Feature *> (f_sub);
|
||||
auto *s = c->subset_context->serializer;
|
||||
s->push ();
|
||||
|
||||
out->offset = 0;
|
||||
bool ret = f.subset (c->subset_context, c, &tag);
|
||||
if (ret)
|
||||
s->add_link (out->offset, s->pop_pack ());
|
||||
else
|
||||
s->pop_discard ();
|
||||
|
||||
return_trace (ret);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
const Record_sanitize_closure_t closure = {tag, base};
|
||||
return_trace (c->check_struct (this) && offset.sanitize (c, base, &closure));
|
||||
}
|
||||
|
||||
Tag tag; /* 4-byte Tag identifier */
|
||||
Offset16To<Type>
|
||||
offset; /* Offset from beginning of object holding
|
||||
* the Record */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct RecordArrayOf : SortedArray16Of<Record<Type>>
|
||||
{
|
||||
const Offset16To<Type>& get_offset (unsigned int i) const
|
||||
{ return (*this)[i].offset; }
|
||||
Offset16To<Type>& get_offset (unsigned int i)
|
||||
{ return (*this)[i].offset; }
|
||||
const Tag& get_tag (unsigned int i) const
|
||||
{ return (*this)[i].tag; }
|
||||
unsigned int get_tags (unsigned int start_offset,
|
||||
unsigned int *record_count /* IN/OUT */,
|
||||
hb_tag_t *record_tags /* OUT */) const
|
||||
{
|
||||
if (record_count)
|
||||
{
|
||||
+ this->sub_array (start_offset, record_count)
|
||||
| hb_map (&Record<Type>::tag)
|
||||
| hb_sink (hb_array (record_tags, *record_count))
|
||||
;
|
||||
}
|
||||
return this->len;
|
||||
}
|
||||
bool find_index (hb_tag_t tag, unsigned int *index) const
|
||||
{
|
||||
return this->bfind (tag, index, HB_NOT_FOUND_STORE, Index::NOT_FOUND_INDEX);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Type>
|
||||
struct RecordListOf : RecordArrayOf<Type>
|
||||
{
|
||||
const Type& operator [] (unsigned int i) const
|
||||
{ return this+this->get_offset (i); }
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
hb_subset_layout_context_t *l) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (*this);
|
||||
if (unlikely (!c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
+ this->iter ()
|
||||
| hb_apply (subset_record_array (l, out, this))
|
||||
;
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
return_trace (RecordArrayOf<Type>::sanitize (c, this));
|
||||
}
|
||||
};
|
||||
|
||||
struct RecordListOfFeature : RecordListOf<Feature>
|
||||
{
|
||||
bool subset (hb_subset_context_t *c,
|
||||
|
@ -907,11 +981,20 @@ struct RecordListOfFeature : RecordListOf<Feature>
|
|||
if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
unsigned count = this->len;
|
||||
|
||||
+ hb_zip (*this, hb_range (count))
|
||||
| hb_filter (l->feature_index_map, hb_second)
|
||||
| hb_map (hb_first)
|
||||
| hb_apply (subset_record_array (l, out, this))
|
||||
| hb_apply ([l, out, this] (const hb_pair_t<const Record<Feature>&, unsigned>& _)
|
||||
{
|
||||
const Feature *f_sub = nullptr;
|
||||
const Feature **f = nullptr;
|
||||
if (l->feature_substitutes_map->has (_.second, &f))
|
||||
f_sub = *f;
|
||||
|
||||
subset_record_array (l, out, this, f_sub) (_.first);
|
||||
})
|
||||
;
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
};
|
||||
|
@ -2692,6 +2775,13 @@ struct VariationStore
|
|||
/*
|
||||
* Feature Variations
|
||||
*/
|
||||
enum Cond_with_Var_flag_t
|
||||
{
|
||||
KEEP_COND_WITH_VAR = 0,
|
||||
DROP_COND_WITH_VAR = 1,
|
||||
DROP_RECORD_WITH_VAR = 2,
|
||||
MEM_ERR_WITH_VAR = 3,
|
||||
};
|
||||
|
||||
struct ConditionFormat1
|
||||
{
|
||||
|
@ -2702,10 +2792,52 @@ struct ConditionFormat1
|
|||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
return_trace (true);
|
||||
|
||||
const hb_map_t *index_map = c->plan->axes_index_map;
|
||||
if (index_map->is_empty ()) return_trace (true);
|
||||
|
||||
if (!index_map->has (axisIndex))
|
||||
return_trace (false);
|
||||
|
||||
return_trace (c->serializer->check_assign (out->axisIndex, index_map->get (axisIndex),
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW));
|
||||
}
|
||||
|
||||
private:
|
||||
Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
|
||||
hb_map_t *condition_map /* OUT */) const
|
||||
{
|
||||
//invalid axis index, drop the entire record
|
||||
if (!c->axes_index_tag_map->has (axisIndex))
|
||||
return DROP_RECORD_WITH_VAR;
|
||||
|
||||
hb_tag_t axis_tag = c->axes_index_tag_map->get (axisIndex);
|
||||
|
||||
//axis not pinned, keep the condition
|
||||
if (!c->axes_location->has (axis_tag))
|
||||
{
|
||||
// add axisIndex->value into the hashmap so we can check if the record is
|
||||
// unique with variations
|
||||
int16_t min_val = filterRangeMinValue;
|
||||
int16_t max_val = filterRangeMaxValue;
|
||||
hb_codepoint_t val = (max_val << 16) + min_val;
|
||||
|
||||
condition_map->set (axisIndex, val);
|
||||
return KEEP_COND_WITH_VAR;
|
||||
}
|
||||
|
||||
//axis pinned, check if condition is met
|
||||
//TODO: add check for axis Ranges
|
||||
int v = c->axes_location->get (axis_tag);
|
||||
|
||||
//condition not met, drop the entire record
|
||||
if (v < filterRangeMinValue || v > filterRangeMaxValue)
|
||||
return DROP_RECORD_WITH_VAR;
|
||||
|
||||
//axis pinned and condition met, drop the condition
|
||||
return DROP_COND_WITH_VAR;
|
||||
}
|
||||
|
||||
bool evaluate (const int *coords, unsigned int coord_len) const
|
||||
{
|
||||
int coord = axisIndex < coord_len ? coords[axisIndex] : 0;
|
||||
|
@ -2737,6 +2869,15 @@ struct Condition
|
|||
}
|
||||
}
|
||||
|
||||
Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
|
||||
hb_map_t *condition_map /* OUT */) const
|
||||
{
|
||||
switch (u.format) {
|
||||
case 1: return u.format1.keep_with_variations (c, condition_map);
|
||||
default:return KEEP_COND_WITH_VAR;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename context_t, typename ...Ts>
|
||||
typename context_t::return_t dispatch (context_t *c, Ts&&... ds) const
|
||||
{
|
||||
|
@ -2778,15 +2919,65 @@ struct ConditionSet
|
|||
return true;
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
Cond_with_Var_flag_t keep_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
|
||||
{
|
||||
hb_map_t *condition_map = hb_map_create ();
|
||||
if (unlikely (!condition_map)) return MEM_ERR_WITH_VAR;
|
||||
hb::shared_ptr<hb_map_t> p {condition_map};
|
||||
|
||||
hb_set_t *cond_set = hb_set_create ();
|
||||
if (unlikely (!cond_set)) return MEM_ERR_WITH_VAR;
|
||||
hb::shared_ptr<hb_set_t> s {cond_set};
|
||||
|
||||
unsigned num_kept_cond = 0, cond_idx = 0;
|
||||
for (const auto& offset : conditions)
|
||||
{
|
||||
Cond_with_Var_flag_t ret = (this+offset).keep_with_variations (c, condition_map);
|
||||
// one condition is not met, drop the entire record
|
||||
if (ret == DROP_RECORD_WITH_VAR)
|
||||
return DROP_RECORD_WITH_VAR;
|
||||
|
||||
// axis not pinned, keep this condition
|
||||
if (ret == KEEP_COND_WITH_VAR)
|
||||
{
|
||||
cond_set->add (cond_idx);
|
||||
num_kept_cond++;
|
||||
}
|
||||
cond_idx++;
|
||||
}
|
||||
|
||||
// all conditions met
|
||||
if (num_kept_cond == 0) return DROP_COND_WITH_VAR;
|
||||
|
||||
//check if condition_set is unique with variations
|
||||
if (c->conditionset_map->has (p))
|
||||
//duplicate found, drop the entire record
|
||||
return DROP_RECORD_WITH_VAR;
|
||||
|
||||
c->conditionset_map->set (p, 1);
|
||||
c->record_cond_idx_map->set (c->cur_record_idx, s);
|
||||
|
||||
return KEEP_COND_WITH_VAR;
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
hb_subset_layout_context_t *l) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->serializer->start_embed (this);
|
||||
if (unlikely (!out || !c->serializer->extend_min (out))) return_trace (false);
|
||||
|
||||
+ conditions.iter ()
|
||||
| hb_apply (subset_offset_array (c, out->conditions, this))
|
||||
;
|
||||
hb_set_t *retained_cond_set = nullptr;
|
||||
if (l->feature_record_cond_idx_map != nullptr)
|
||||
retained_cond_set = l->feature_record_cond_idx_map->get (l->cur_feature_var_record_idx);
|
||||
|
||||
unsigned int count = conditions.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (retained_cond_set != nullptr && !retained_cond_set->has (i))
|
||||
continue;
|
||||
subset_offset_array (c, out->conditions, this) (conditions[i]);
|
||||
}
|
||||
|
||||
return_trace (bool (out->conditions));
|
||||
}
|
||||
|
@ -2820,10 +3011,19 @@ struct FeatureTableSubstitutionRecord
|
|||
feature_indexes->add (featureIndex);
|
||||
}
|
||||
|
||||
void collect_feature_substitutes_with_variations (hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
|
||||
const hb_set_t *feature_indices,
|
||||
const void *base) const
|
||||
{
|
||||
if (feature_indices->has (featureIndex))
|
||||
feature_substitutes_map->set (featureIndex, &(base+feature));
|
||||
}
|
||||
|
||||
bool subset (hb_subset_layout_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
if (!c->feature_index_map->has (featureIndex)) {
|
||||
if (!c->feature_index_map->has (featureIndex) ||
|
||||
c->feature_substitutes_map->has (featureIndex)) {
|
||||
// Feature that is being substituted is not being retained, so we don't
|
||||
// need this.
|
||||
return_trace (false);
|
||||
|
@ -2865,10 +3065,16 @@ struct FeatureTableSubstitution
|
|||
}
|
||||
|
||||
void collect_lookups (const hb_set_t *feature_indexes,
|
||||
const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
|
||||
hb_set_t *lookup_indexes /* OUT */) const
|
||||
{
|
||||
+ hb_iter (substitutions)
|
||||
| hb_filter (feature_indexes, &FeatureTableSubstitutionRecord::featureIndex)
|
||||
| hb_filter ([feature_substitutes_map] (const FeatureTableSubstitutionRecord& record)
|
||||
{
|
||||
if (feature_substitutes_map == nullptr) return true;
|
||||
return !feature_substitutes_map->has (record.featureIndex);
|
||||
})
|
||||
| hb_apply ([this, lookup_indexes] (const FeatureTableSubstitutionRecord& r)
|
||||
{ r.collect_lookups (this, lookup_indexes); })
|
||||
;
|
||||
|
@ -2890,6 +3096,12 @@ struct FeatureTableSubstitution
|
|||
return false;
|
||||
}
|
||||
|
||||
void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
|
||||
{
|
||||
for (const FeatureTableSubstitutionRecord& record : substitutions)
|
||||
record.collect_feature_substitutes_with_variations (c->feature_substitutes_map, c->feature_indices, this);
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
hb_subset_layout_context_t *l) const
|
||||
{
|
||||
|
@ -2929,9 +3141,10 @@ struct FeatureVariationRecord
|
|||
|
||||
void collect_lookups (const void *base,
|
||||
const hb_set_t *feature_indexes,
|
||||
const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
|
||||
hb_set_t *lookup_indexes /* OUT */) const
|
||||
{
|
||||
return (base+substitutions).collect_lookups (feature_indexes, lookup_indexes);
|
||||
return (base+substitutions).collect_lookups (feature_indexes, feature_substitutes_map, lookup_indexes);
|
||||
}
|
||||
|
||||
void closure_features (const void *base,
|
||||
|
@ -2946,13 +3159,25 @@ struct FeatureVariationRecord
|
|||
return (base+substitutions).intersects_features (feature_index_map);
|
||||
}
|
||||
|
||||
void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c,
|
||||
const void *base) const
|
||||
{
|
||||
// ret == 1, all conditions met
|
||||
if ((base+conditions).keep_with_variations (c) == DROP_COND_WITH_VAR &&
|
||||
c->apply)
|
||||
{
|
||||
(base+substitutions).collect_feature_substitutes_with_variations (c);
|
||||
c->apply = false; // set variations only once
|
||||
}
|
||||
}
|
||||
|
||||
bool subset (hb_subset_layout_context_t *c, const void *base) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
auto *out = c->subset_context->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
out->conditions.serialize_subset (c->subset_context, conditions, base);
|
||||
out->conditions.serialize_subset (c->subset_context, conditions, base, c);
|
||||
out->substitutions.serialize_subset (c->subset_context, substitutions, base, c);
|
||||
|
||||
return_trace (true);
|
||||
|
@ -3002,6 +3227,16 @@ struct FeatureVariations
|
|||
return (this+record.substitutions).find_substitute (feature_index);
|
||||
}
|
||||
|
||||
void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
|
||||
{
|
||||
unsigned int count = varRecords.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
c->cur_record_idx = i;
|
||||
varRecords[i].collect_feature_substitutes_with_variations (c, this);
|
||||
}
|
||||
}
|
||||
|
||||
FeatureVariations* copy (hb_serialize_context_t *c) const
|
||||
{
|
||||
TRACE_SERIALIZE (this);
|
||||
|
@ -3009,17 +3244,25 @@ struct FeatureVariations
|
|||
}
|
||||
|
||||
void collect_lookups (const hb_set_t *feature_indexes,
|
||||
const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
|
||||
hb_set_t *lookup_indexes /* OUT */) const
|
||||
{
|
||||
for (const FeatureVariationRecord& r : varRecords)
|
||||
r.collect_lookups (this, feature_indexes, lookup_indexes);
|
||||
r.collect_lookups (this, feature_indexes, feature_substitutes_map, lookup_indexes);
|
||||
}
|
||||
|
||||
void closure_features (const hb_map_t *lookup_indexes,
|
||||
const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
|
||||
hb_set_t *feature_indexes /* OUT */) const
|
||||
{
|
||||
for (const FeatureVariationRecord& record : varRecords)
|
||||
record.closure_features (this, lookup_indexes, feature_indexes);
|
||||
unsigned int count = varRecords.len;
|
||||
for (unsigned int i = 0; i < count; i++)
|
||||
{
|
||||
if (feature_record_cond_idx_map != nullptr &&
|
||||
!feature_record_cond_idx_map->has (i))
|
||||
continue;
|
||||
varRecords[i].closure_features (this, lookup_indexes, feature_indexes);
|
||||
}
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
|
@ -3041,7 +3284,13 @@ struct FeatureVariations
|
|||
}
|
||||
|
||||
unsigned count = (unsigned) (keep_up_to + 1);
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
for (unsigned i = 0; i < count; i++)
|
||||
{
|
||||
if (l->feature_record_cond_idx_map != nullptr &&
|
||||
!l->feature_record_cond_idx_map->has (i))
|
||||
continue;
|
||||
|
||||
l->cur_feature_var_record_idx = i;
|
||||
subset_record_array (l, &(out->varRecords), this) (varRecords[i]);
|
||||
}
|
||||
return_trace (bool (out->varRecords));
|
||||
|
|
22
thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
vendored
22
thirdparty/harfbuzz/src/hb-ot-layout-gsubgpos.hh
vendored
|
@ -4236,13 +4236,19 @@ struct GSUBGPOS
|
|||
}
|
||||
|
||||
void feature_variation_collect_lookups (const hb_set_t *feature_indexes,
|
||||
const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map,
|
||||
hb_set_t *lookup_indexes /* OUT */) const
|
||||
{
|
||||
#ifndef HB_NO_VAR
|
||||
get_feature_variations ().collect_lookups (feature_indexes, lookup_indexes);
|
||||
get_feature_variations ().collect_lookups (feature_indexes, feature_substitutes_map, lookup_indexes);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
void collect_feature_substitutes_with_variations (hb_collect_feature_substitutes_with_var_context_t *c) const
|
||||
{ get_feature_variations ().collect_feature_substitutes_with_variations (c); }
|
||||
#endif
|
||||
|
||||
template <typename TLookup>
|
||||
void closure_lookups (hb_face_t *face,
|
||||
const hb_set_t *glyphs,
|
||||
|
@ -4278,6 +4284,8 @@ struct GSUBGPOS
|
|||
}
|
||||
|
||||
void prune_features (const hb_map_t *lookup_indices, /* IN */
|
||||
const hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, /* IN */
|
||||
const hb_hashmap_t<unsigned, const Feature*> *feature_substitutes_map, /* IN */
|
||||
hb_set_t *feature_indices /* IN/OUT */) const
|
||||
{
|
||||
#ifndef HB_NO_VAR
|
||||
|
@ -4285,7 +4293,7 @@ struct GSUBGPOS
|
|||
// if the FeatureVariation's table and the alternate version(s) intersect the
|
||||
// set of lookup indices.
|
||||
hb_set_t alternate_feature_indices;
|
||||
get_feature_variations ().closure_features (lookup_indices, &alternate_feature_indices);
|
||||
get_feature_variations ().closure_features (lookup_indices, feature_record_cond_idx_map, &alternate_feature_indices);
|
||||
if (unlikely (alternate_feature_indices.in_error()))
|
||||
{
|
||||
feature_indices->err ();
|
||||
|
@ -4295,7 +4303,6 @@ struct GSUBGPOS
|
|||
|
||||
for (unsigned i : feature_indices->iter())
|
||||
{
|
||||
const Feature& f = get_feature (i);
|
||||
hb_tag_t tag = get_feature_tag (i);
|
||||
if (tag == HB_TAG ('p', 'r', 'e', 'f'))
|
||||
// Note: Never ever drop feature 'pref', even if it's empty.
|
||||
|
@ -4305,11 +4312,16 @@ struct GSUBGPOS
|
|||
continue;
|
||||
|
||||
|
||||
if (!f.featureParams.is_null () &&
|
||||
const Feature *f = &(get_feature (i));
|
||||
const Feature** p = nullptr;
|
||||
if (feature_substitutes_map->has (i, &p))
|
||||
f = *p;
|
||||
|
||||
if (!f->featureParams.is_null () &&
|
||||
tag == HB_TAG ('s', 'i', 'z', 'e'))
|
||||
continue;
|
||||
|
||||
if (!f.intersects_lookup_indexes (lookup_indices)
|
||||
if (!f->intersects_lookup_indexes (lookup_indices)
|
||||
#ifndef HB_NO_VAR
|
||||
&& !alternate_feature_indices.has (i)
|
||||
#endif
|
||||
|
|
73
thirdparty/harfbuzz/src/hb-ot-layout.cc
vendored
73
thirdparty/harfbuzz/src/hb-ot-layout.cc
vendored
|
@ -1271,7 +1271,7 @@ hb_ot_layout_collect_lookups (hb_face_t *face,
|
|||
hb_set_next (&feature_indexes, &feature_index);)
|
||||
g.get_feature (feature_index).add_lookup_indexes_to (lookup_indexes);
|
||||
|
||||
g.feature_variation_collect_lookups (&feature_indexes, lookup_indexes);
|
||||
g.feature_variation_collect_lookups (&feature_indexes, nullptr, lookup_indexes);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1709,6 +1709,8 @@ hb_ot_layout_get_size_params (hb_face_t *face,
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hb_ot_layout_feature_get_name_ids:
|
||||
* @face: #hb_face_t to work upon
|
||||
|
@ -2341,6 +2343,7 @@ struct hb_get_glyph_alternates_dispatch_t :
|
|||
( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) )
|
||||
};
|
||||
|
||||
#ifndef HB_NO_LAYOUT_RARELY_USED
|
||||
/**
|
||||
* hb_ot_layout_lookup_get_glyph_alternates:
|
||||
* @face: a face.
|
||||
|
@ -2373,4 +2376,72 @@ hb_ot_layout_lookup_get_glyph_alternates (hb_face_t *face,
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
struct hb_position_single_dispatch_t :
|
||||
hb_dispatch_context_t<hb_position_single_dispatch_t, bool>
|
||||
{
|
||||
static return_t default_return_value () { return false; }
|
||||
bool stop_sublookup_iteration (return_t r) const { return r; }
|
||||
|
||||
private:
|
||||
template <typename T, typename ...Ts> auto
|
||||
_dispatch (const T &obj, hb_priority<1>, Ts&&... ds) HB_AUTO_RETURN
|
||||
( obj.position_single (std::forward<Ts> (ds)...) )
|
||||
template <typename T, typename ...Ts> auto
|
||||
_dispatch (const T &obj, hb_priority<0>, Ts&&... ds) HB_AUTO_RETURN
|
||||
( default_return_value () )
|
||||
public:
|
||||
template <typename T, typename ...Ts> auto
|
||||
dispatch (const T &obj, Ts&&... ds) HB_AUTO_RETURN
|
||||
( _dispatch (obj, hb_prioritize, std::forward<Ts> (ds)...) )
|
||||
};
|
||||
|
||||
/**
|
||||
* hb_ot_layout_lookup_get_optical_bound:
|
||||
* @font: a font.
|
||||
* @lookup_index: index of the feature lookup to query.
|
||||
* @direction: edge of the glyph to query.
|
||||
* @glyph: a glyph id.
|
||||
*
|
||||
* Fetches the optical bound of a glyph positioned at the margin of text.
|
||||
* The direction identifies which edge of the glyph to query.
|
||||
*
|
||||
* Return value: Adjustment value. Negative values mean the glyph will stick out of the margin.
|
||||
*
|
||||
* Since: 5.3.0
|
||||
**/
|
||||
hb_position_t
|
||||
hb_ot_layout_lookup_get_optical_bound (hb_font_t *font,
|
||||
unsigned lookup_index,
|
||||
hb_direction_t direction,
|
||||
hb_codepoint_t glyph)
|
||||
{
|
||||
const OT::PosLookup &lookup = font->face->table.GPOS->table->get_lookup (lookup_index);
|
||||
hb_glyph_position_t pos = {0};
|
||||
hb_position_single_dispatch_t c;
|
||||
lookup.dispatch (&c, font, direction, glyph, pos);
|
||||
hb_position_t ret = 0;
|
||||
switch (direction)
|
||||
{
|
||||
case HB_DIRECTION_LTR:
|
||||
ret = pos.x_offset;
|
||||
break;
|
||||
case HB_DIRECTION_RTL:
|
||||
ret = pos.x_advance - pos.x_offset;
|
||||
break;
|
||||
case HB_DIRECTION_TTB:
|
||||
ret = pos.y_offset;
|
||||
break;
|
||||
case HB_DIRECTION_BTT:
|
||||
ret = pos.y_advance - pos.y_offset;
|
||||
break;
|
||||
case HB_DIRECTION_INVALID:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
|
11
thirdparty/harfbuzz/src/hb-ot-layout.h
vendored
11
thirdparty/harfbuzz/src/hb-ot-layout.h
vendored
|
@ -403,6 +403,16 @@ hb_ot_layout_get_size_params (hb_face_t *face,
|
|||
unsigned int *range_start, /* OUT. May be NULL */
|
||||
unsigned int *range_end /* OUT. May be NULL */);
|
||||
|
||||
HB_EXTERN hb_position_t
|
||||
hb_ot_layout_lookup_get_optical_bound (hb_font_t *font,
|
||||
unsigned lookup_index,
|
||||
hb_direction_t direction,
|
||||
hb_codepoint_t glyph);
|
||||
|
||||
|
||||
/*
|
||||
* GSUB/GPOS
|
||||
*/
|
||||
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_ot_layout_feature_get_name_ids (hb_face_t *face,
|
||||
|
@ -423,6 +433,7 @@ hb_ot_layout_feature_get_characters (hb_face_t *face,
|
|||
unsigned int *char_count /* IN/OUT. May be NULL */,
|
||||
hb_codepoint_t *characters /* OUT. May be NULL */);
|
||||
|
||||
|
||||
/*
|
||||
* BASE
|
||||
*/
|
||||
|
|
2
thirdparty/harfbuzz/src/hb-ot-post-table.hh
vendored
2
thirdparty/harfbuzz/src/hb-ot-post-table.hh
vendored
|
@ -282,7 +282,7 @@ struct post
|
|||
* 0x00020000 for version 2.0
|
||||
* 0x00025000 for version 2.5 (deprecated)
|
||||
* 0x00030000 for version 3.0 */
|
||||
HBFixed italicAngle; /* Italic angle in counter-clockwise degrees
|
||||
F16DOT16 italicAngle; /* Italic angle in counter-clockwise degrees
|
||||
* from the vertical. Zero for upright text,
|
||||
* negative for text that leans to the right
|
||||
* (forward). */
|
||||
|
|
8
thirdparty/harfbuzz/src/hb-ot-shape.cc
vendored
8
thirdparty/harfbuzz/src/hb-ot-shape.cc
vendored
|
@ -527,18 +527,20 @@ hb_set_unicode_props (hb_buffer_t *buffer)
|
|||
}
|
||||
#endif
|
||||
/* Or part of the Other_Grapheme_Extend that is not marks.
|
||||
* As of Unicode 11 that is just:
|
||||
* As of Unicode 15 that is just:
|
||||
*
|
||||
* 200C ; Other_Grapheme_Extend # Cf ZERO WIDTH NON-JOINER
|
||||
* FF9E..FF9F ; Other_Grapheme_Extend # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
|
||||
* E0020..E007F ; Other_Grapheme_Extend # Cf [96] TAG SPACE..CANCEL TAG
|
||||
*
|
||||
* ZWNJ is special, we don't want to merge it as there's no need, and keeping
|
||||
* it separate results in more granular clusters. Ignore Katakana for now.
|
||||
* it separate results in more granular clusters.
|
||||
* Tags are used for Emoji sub-region flag sequences:
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/1556
|
||||
* Katakana ones were requested:
|
||||
* https://github.com/harfbuzz/harfbuzz/issues/3844
|
||||
*/
|
||||
else if (unlikely (hb_in_range<hb_codepoint_t> (info[i].codepoint, 0xE0020u, 0xE007Fu)))
|
||||
else if (unlikely (hb_in_ranges<hb_codepoint_t> (info[i].codepoint, 0xFF9Eu, 0xFF9Fu, 0xE0020u, 0xE007Fu)))
|
||||
_hb_glyph_info_set_continuation (&info[i]);
|
||||
}
|
||||
}
|
||||
|
|
120
thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh
vendored
120
thirdparty/harfbuzz/src/hb-ot-shaper-use-table.hh
vendored
|
@ -25,6 +25,7 @@
|
|||
* # Updated for Unicode 12.1 by Andrew Glass 2019-05-24
|
||||
* # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
|
||||
* # Updated for Unicode 14.0 by Andrew Glass 2021-09-25
|
||||
* # Updated for Unicode 15.0 by Andrew Glass 2022-09-16
|
||||
* # Override values For Indic_Positional_Category
|
||||
* # Not derivable
|
||||
* # Initial version based on Unicode 7.0 by Andrew Glass 2014-03-17
|
||||
|
@ -34,6 +35,7 @@
|
|||
* # Updated for Unicode 12.1 by Andrew Glass 2019-05-30
|
||||
* # Updated for Unicode 13.0 by Andrew Glass 2020-07-28
|
||||
* # Updated for Unicode 14.0 by Andrew Glass 2021-09-28
|
||||
* # Updated for Unicode 15.0 by Andrew Glass 2022-09-16
|
||||
* UnicodeData.txt does not have a header.
|
||||
*/
|
||||
|
||||
|
@ -90,7 +92,7 @@
|
|||
#pragma GCC diagnostic pop
|
||||
|
||||
static const uint8_t
|
||||
hb_use_u8[3115] =
|
||||
hb_use_u8[3141] =
|
||||
{
|
||||
16, 50, 51, 51, 51, 52, 51, 83, 118, 131, 51, 57, 58, 179, 195, 61,
|
||||
51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
|
||||
|
@ -125,11 +127,11 @@ hb_use_u8[3115] =
|
|||
2, 2, 2, 2, 2, 2, 2, 2, 2, 88, 89, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 90, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 91, 2, 2, 92, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 93, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 94, 94, 95, 96, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
|
||||
94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, 94,
|
||||
94, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||
2, 2, 2, 91, 2, 2, 92, 2, 2, 2, 93, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 94, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 95, 95, 96, 97, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
|
||||
95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95,
|
||||
95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||
0, 2, 2, 2, 2, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 4,
|
||||
0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 6, 7, 0, 0, 0, 0, 0, 0,
|
||||
|
@ -226,70 +228,72 @@ hb_use_u8[3115] =
|
|||
0, 9, 47, 2, 2, 2, 2, 2, 2, 2, 2, 2, 125, 18, 20, 151,
|
||||
20, 19, 152, 153, 2, 2, 2, 2, 2, 0, 0, 63, 154, 0, 0, 0,
|
||||
0, 2, 11, 0, 0, 0, 0, 0, 0, 2, 63, 23, 18, 18, 18, 20,
|
||||
20, 106, 155, 0, 0, 156, 157, 29, 158, 28, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 21, 17, 20, 20, 159, 42, 0, 0, 0,
|
||||
20, 106, 155, 0, 0, 54, 156, 29, 157, 28, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 21, 17, 20, 20, 158, 42, 0, 0, 0,
|
||||
47, 125, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 7, 7, 2, 2,
|
||||
28, 2, 2, 2, 2, 2, 2, 2, 28, 2, 2, 2, 2, 2, 2, 2,
|
||||
8, 16, 17, 19, 20, 160, 29, 0, 0, 9, 9, 28, 2, 2, 2, 7,
|
||||
8, 16, 17, 19, 20, 159, 29, 0, 0, 9, 9, 28, 2, 2, 2, 7,
|
||||
28, 7, 2, 28, 2, 2, 56, 15, 21, 14, 21, 45, 30, 31, 30, 32,
|
||||
0, 0, 0, 0, 33, 0, 0, 0, 2, 2, 21, 0, 9, 9, 9, 44,
|
||||
0, 9, 9, 44, 0, 0, 0, 0, 0, 2, 2, 63, 23, 18, 18, 18,
|
||||
20, 21, 123, 13, 15, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0,
|
||||
161, 162, 0, 0, 0, 0, 0, 0, 0, 16, 17, 18, 18, 64, 97, 23,
|
||||
158, 9, 163, 7, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2,
|
||||
63, 23, 18, 18, 0, 46, 46, 9, 164, 35, 0, 0, 0, 0, 0, 0,
|
||||
160, 161, 0, 0, 0, 0, 0, 0, 0, 16, 17, 18, 18, 64, 97, 23,
|
||||
157, 9, 162, 7, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2,
|
||||
63, 23, 18, 18, 0, 46, 46, 9, 163, 35, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 2, 2, 18, 0, 21, 17, 18, 18, 19, 14, 80,
|
||||
164, 36, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 8, 165,
|
||||
23, 18, 20, 20, 163, 7, 0, 0, 0, 2, 2, 2, 2, 2, 7, 41,
|
||||
163, 36, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 8, 164,
|
||||
23, 18, 20, 20, 162, 7, 0, 0, 0, 2, 2, 2, 2, 2, 7, 41,
|
||||
133, 21, 20, 18, 74, 19, 20, 0, 0, 2, 2, 2, 7, 0, 0, 0,
|
||||
0, 2, 2, 2, 2, 2, 2, 16, 17, 18, 19, 20, 103, 164, 35, 0,
|
||||
0, 2, 2, 2, 2, 2, 2, 16, 17, 18, 19, 20, 103, 163, 35, 0,
|
||||
0, 2, 2, 2, 7, 28, 0, 2, 2, 2, 2, 28, 7, 2, 2, 2,
|
||||
2, 21, 21, 16, 30, 31, 10, 166, 167, 168, 169, 0, 0, 0, 0, 0,
|
||||
2, 21, 21, 16, 30, 31, 10, 165, 166, 167, 168, 0, 0, 0, 0, 0,
|
||||
0, 2, 2, 2, 2, 0, 2, 2, 2, 63, 23, 18, 18, 0, 20, 21,
|
||||
27, 106, 0, 31, 0, 0, 0, 0, 0, 50, 18, 20, 20, 20, 137, 2,
|
||||
2, 2, 170, 171, 9, 13, 172, 70, 173, 0, 0, 1, 144, 0, 0, 0,
|
||||
0, 50, 18, 20, 14, 17, 18, 2, 2, 2, 2, 155, 155, 155, 174, 174,
|
||||
174, 174, 174, 174, 13, 175, 0, 28, 0, 20, 18, 18, 29, 20, 20, 9,
|
||||
164, 0, 59, 59, 59, 59, 59, 59, 59, 64, 19, 80, 44, 0, 0, 0,
|
||||
2, 2, 169, 170, 9, 13, 171, 70, 172, 0, 0, 1, 144, 0, 0, 0,
|
||||
0, 50, 18, 20, 14, 17, 18, 2, 2, 2, 2, 155, 155, 155, 173, 173,
|
||||
173, 173, 173, 173, 13, 174, 0, 28, 0, 20, 18, 18, 29, 20, 20, 9,
|
||||
163, 0, 59, 59, 59, 59, 59, 59, 59, 64, 19, 80, 44, 0, 0, 0,
|
||||
0, 2, 2, 2, 7, 2, 28, 2, 2, 50, 20, 20, 29, 0, 36, 20,
|
||||
25, 9, 157, 176, 172, 0, 0, 0, 0, 2, 2, 2, 28, 7, 2, 2,
|
||||
25, 9, 156, 175, 171, 0, 0, 0, 0, 2, 2, 2, 28, 7, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 21, 21, 45, 20, 33, 80, 66, 0, 0, 0,
|
||||
0, 2, 177, 64, 45, 0, 0, 0, 0, 9, 178, 2, 2, 2, 2, 2,
|
||||
0, 2, 176, 64, 45, 0, 0, 0, 0, 9, 177, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 21, 20, 18, 29, 0, 46, 14, 140, 0, 0, 0, 0, 0,
|
||||
0, 179, 179, 179, 106, 7, 0, 0, 0, 9, 9, 9, 44, 0, 0, 0,
|
||||
0, 2, 2, 2, 2, 2, 7, 0, 56, 180, 18, 18, 18, 18, 18, 18,
|
||||
0, 178, 178, 178, 106, 179, 178, 0, 0, 145, 2, 2, 180, 114, 114, 114,
|
||||
114, 114, 114, 114, 0, 0, 0, 0, 0, 9, 9, 9, 44, 0, 0, 0,
|
||||
0, 2, 2, 2, 2, 2, 7, 0, 56, 181, 18, 18, 18, 18, 18, 18,
|
||||
18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 0, 0, 0,
|
||||
38, 114, 24, 0, 0, 0, 0, 0, 0, 0, 0, 7, 0, 0, 0, 0,
|
||||
0, 2, 2, 2, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 56,
|
||||
35, 0, 4, 118, 118, 118, 119, 0, 0, 9, 9, 9, 47, 2, 2, 2,
|
||||
0, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
44, 2, 2, 2, 2, 2, 2, 9, 9, 2, 2, 42, 42, 42, 90, 0,
|
||||
0, O, O, O, GB, B, B, GB, O, O, WJ,FMPst,FMPst, O, CGJ, B,
|
||||
O, B,VMAbv,VMAbv,VMAbv, O,VMAbv, B,CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw,
|
||||
B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw, VAbv, VAbv, VAbv, VPst, VPst, VPst, H, VPre,
|
||||
VPst,VMBlw, O, O, VAbv, GB,VMAbv,VMPst,VMPst, O, B, VBlw, O, O, VPre, VPre,
|
||||
O, VPre, H, O, VPst,FMAbv, O,CMBlw, O, VAbv, O, VAbv, H, O,VMBlw,VMAbv,
|
||||
CMAbv, GB, GB, O, MBlw,CMAbv,CMAbv, VPst, VAbv,VMAbv, O, VPst, O, VPre, VPre,VMAbv,
|
||||
B, O, CS, CS,VMPst, B, VAbv, VAbv, B, R, O, HVM, O, O, FBlw, O,
|
||||
CMAbv, O,CMBlw, VAbv, VBlw, B, SUB, SUB, SUB, O, SUB, SUB, O, FBlw, O, B,
|
||||
VPst, VBlw, VPre,VMAbv,VMBlw,VMPst, IS, VAbv, MPst, MPre, MBlw, MBlw, B, MBlw, MBlw, VPst,
|
||||
VMPst,VMPst, B, MBlw, VPst, VPre, VAbv, VAbv,VMPst,VMPst,VMBlw, B,VMPst, VBlw, VPst, CGJ,
|
||||
CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv,VMAbv,FMAbv, VAbv, IS,FMAbv, B,FMAbv, B,
|
||||
CGJ, WJ, CGJ, GB,CMAbv,CMAbv, B, GB, B, VAbv, SUB, FPst, FPst,VMBlw, FPst, FPst,
|
||||
FBlw,VMAbv,FMBlw, VAbv, VPre, B, MPre, MBlw, SUB, FAbv, FAbv, MAbv, SUB, Sk, VPst, VAbv,
|
||||
VMAbv,VMAbv, FAbv,CMAbv, VPst, H, B, O,SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst, IS, VBlw,
|
||||
FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv, CS, O,FMAbv, ZWNJ, CGJ, WJ, WJ, WJ,
|
||||
O,FMPst, O, O, H, MPst, VPst, H,VMAbv, VAbv,VMBlw, B, VBlw, FPst, VPst, FAbv,
|
||||
VMPst, B,CMAbv, VAbv, MBlw, MPst, MBlw, H, O, VBlw, MPst, MPre, MAbv, MBlw, O, B,
|
||||
FAbv, FAbv, FPst, VBlw, B, B, VPre, O,VMPst, IS, O,VMPst, VBlw, VPst,VMBlw,VMBlw,
|
||||
VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst, CS, CS, B, N, N, O, HN, VPre,
|
||||
VBlw, VAbv, IS,CMAbv, O, VPst, B, R, R, O,FMBlw,CMBlw, VAbv, VPre,VMAbv,VMAbv,
|
||||
H, VAbv,CMBlw,FMAbv, B, CS, CS, H,CMBlw,VMPst, H,VMPst, VAbv,VMAbv, VPst, IS,
|
||||
R, MPst, R, MPst,CMBlw, B,FMBlw, VBlw,VMAbv, R, MBlw, MBlw, GB, FBlw, FBlw,CMAbv,
|
||||
IS, VBlw, IS, GB, VAbv, R,VMPst, H, H, O, VBlw,
|
||||
44, 2, 2, 2, 2, 2, 2, 9, 9, 2, 2, 2, 2, 2, 2, 20,
|
||||
20, 2, 2, 42, 42, 42, 90, 0, 0, O, O, O, GB, B, B, GB,
|
||||
O, O, WJ,FMPst,FMPst, O, CGJ, B, O, B,VMAbv,VMAbv,VMAbv, O,VMAbv, B,
|
||||
CMBlw,CMBlw,CMBlw,VMAbv,VMPst, VAbv, VPst,CMBlw, B, VPst, VPre, VPst, VBlw, VBlw, VBlw, VBlw,
|
||||
VAbv, VAbv, VAbv, VPst, VPst, VPst, H, VPre, VPst,VMBlw, O, O, VAbv, GB,VMAbv,VMPst,
|
||||
VMPst, O, B, VBlw, O, O, VPre, VPre, O, VPre, H, O, VPst,FMAbv, O,CMBlw,
|
||||
O, VAbv, O, VAbv, H, O,VMBlw,VMAbv,CMAbv, GB, GB, O, MBlw,CMAbv,CMAbv, VPst,
|
||||
VAbv,VMAbv, O, VPst, O, VPre, VPre,VMAbv, B, O, CS, CS,VMPst, B, VAbv, VAbv,
|
||||
B, R, O, HVM, O, O,FMBlw, O,CMAbv, O,CMBlw, VAbv, VBlw, B, SUB, SUB,
|
||||
SUB, O, SUB, SUB, O,FMBlw, O, B, VPst, VBlw, VPre,VMAbv,VMBlw,VMPst, IS, VAbv,
|
||||
MPst, MPre, MBlw, MBlw, B, MBlw, MBlw, VPst,VMPst,VMPst, B, MBlw, VPst, VPre, VAbv, VAbv,
|
||||
VMPst,VMPst,VMBlw, B,VMPst, VBlw, VPst, CGJ, CGJ, VPst,VMAbv,VMAbv,FMAbv, FAbv,CMAbv,FMAbv,
|
||||
VMAbv,FMAbv, VAbv, IS,FMAbv, B,FMAbv, B, CGJ, WJ, CGJ, GB,CMAbv,CMAbv, B, GB,
|
||||
B, VAbv, SUB, FPst, FPst,VMBlw, FPst, FPst, FBlw,VMAbv,FMBlw, VAbv, VPre, B, MPre, MBlw,
|
||||
SUB, FAbv, FAbv, MAbv, SUB, Sk, VPst, VAbv,VMAbv,VMAbv, FAbv,CMAbv, VPst, H, B, O,
|
||||
SMAbv,SMBlw,SMAbv,SMAbv,SMAbv, VPst, IS, VBlw, FAbv,VMPre,VMPre,FMAbv,CMBlw,VMBlw,VMBlw,VMAbv,
|
||||
CS, O,FMAbv, ZWNJ, CGJ, WJ, WJ, WJ, O,FMPst, O, O, H, MPst, VPst, H,
|
||||
VMAbv, VAbv,VMBlw, B, VBlw, FPst, VPst, FAbv,VMPst, B,CMAbv, VAbv, MBlw, MPst, MBlw, H,
|
||||
O, VBlw, MPst, MPre, MAbv, MBlw, O, B, FAbv, FAbv, FPst, VBlw, B, B, VPre, O,
|
||||
VMPst, IS, O,VMPst, VBlw, VPst,VMBlw,VMBlw,VMAbv, O, IS,VMBlw, B,VMPst,VMAbv,VMPst,
|
||||
CS, CS, B, N, N, O, HN, VPre, VBlw, VAbv, IS,CMAbv, O, VPst, B, R,
|
||||
R,CMBlw, VAbv, VPre,VMAbv,VMAbv, H, VAbv,CMBlw,FMAbv, B, CS, CS, H,CMBlw,VMPst,
|
||||
H,VMPst, VAbv,VMAbv, VPst, IS, R, MPst, R, MPst,CMBlw, B,FMBlw, VBlw,VMAbv, R,
|
||||
MBlw, MBlw, GB, FBlw, FBlw,CMAbv, IS, VBlw, IS, GB, VAbv, R,VMPst, H, H, B,
|
||||
H, B,VMBlw, O, VBlw,
|
||||
};
|
||||
static const uint16_t
|
||||
hb_use_u16[776] =
|
||||
hb_use_u16[784] =
|
||||
{
|
||||
0, 0, 1, 2, 0, 0, 0, 0, 0, 0, 3, 4, 0, 5, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0,
|
||||
|
@ -332,14 +336,14 @@ hb_use_u16[776] =
|
|||
9,242, 73,243, 0, 0, 0, 0,244, 9, 9,245,246, 2,247, 9,
|
||||
248,249, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9,250,
|
||||
251, 48, 9,252,253, 2, 0, 0, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||
9, 9, 98,254, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
|
||||
9, 9, 9,255, 0, 0, 0, 0, 9, 9, 9, 9,256,257,258,258,
|
||||
259,260, 0, 0, 0, 0,261, 0, 9, 9, 9, 9, 9,262, 0, 0,
|
||||
9, 9, 9, 9, 9, 9,105, 70, 94,263, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,264, 9, 9, 70,265,266, 0, 0, 0,
|
||||
0, 9,267, 0, 9, 9,268, 2, 9, 9, 9, 9,269, 2, 0, 0,
|
||||
129,129,129,129,129,129,129,129,160,160,160,160,160,160,160,160,
|
||||
160,160,160,160,160,160,160,129,
|
||||
9, 9, 9,254,255,256, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0,
|
||||
9, 9, 9,257, 0, 0, 0, 0, 9, 9, 9, 9,258,259,260,260,
|
||||
261,262, 0, 0, 0, 0,263, 0, 9, 9, 9, 9, 9,264, 0, 0,
|
||||
9, 9, 9, 9, 9, 9,105, 70, 94,265, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,266, 9, 9, 70,267,268, 0, 0, 0,
|
||||
0, 9,269, 0, 9, 9,270, 2, 0, 0, 0, 0, 0, 9,271, 2,
|
||||
9, 9, 9, 9,272, 2, 0, 0,129,129,129,129,129,129,129,129,
|
||||
160,160,160,160,160,160,160,160,160,160,160,160,160,160,160,129,
|
||||
};
|
||||
|
||||
static inline unsigned
|
||||
|
@ -350,7 +354,7 @@ hb_use_b4 (const uint8_t* a, unsigned i)
|
|||
static inline uint_fast8_t
|
||||
hb_use_get_category (unsigned u)
|
||||
{
|
||||
return u<921600u?hb_use_u8[2753+(((hb_use_u8[593+(((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<921600u?hb_use_u8[2777+(((hb_use_u8[593+(((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;
|
||||
}
|
||||
|
||||
#undef B
|
||||
|
|
|
@ -342,6 +342,40 @@ _hb_preprocess_text_vowel_constraints (const hb_ot_shape_plan_t *plan HB_UNUSED,
|
|||
}
|
||||
break;
|
||||
|
||||
case HB_SCRIPT_KHOJKI:
|
||||
for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
|
||||
{
|
||||
bool matched = false;
|
||||
switch (buffer->cur ().codepoint)
|
||||
{
|
||||
case 0x11200u:
|
||||
switch (buffer->cur (1).codepoint)
|
||||
{
|
||||
case 0x1122Cu: case 0x11231u: case 0x11233u:
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x11206u:
|
||||
matched = 0x1122Cu == buffer->cur (1).codepoint;
|
||||
break;
|
||||
case 0x1122Cu:
|
||||
switch (buffer->cur (1).codepoint)
|
||||
{
|
||||
case 0x11230u: case 0x11231u:
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 0x11240u:
|
||||
matched = 0x1122Eu == buffer->cur (1).codepoint;
|
||||
break;
|
||||
}
|
||||
(void) buffer->next_glyph ();
|
||||
if (matched) _output_with_dotted_circle (buffer);
|
||||
}
|
||||
break;
|
||||
|
||||
case HB_SCRIPT_KHUDAWADI:
|
||||
for (buffer->idx = 0; buffer->idx + 1 < count && buffer->successful;)
|
||||
{
|
||||
|
|
14
thirdparty/harfbuzz/src/hb-ot-stat-table.hh
vendored
14
thirdparty/harfbuzz/src/hb-ot-stat-table.hh
vendored
|
@ -136,7 +136,7 @@ struct AxisValueFormat1
|
|||
NameID valueNameID; /* The name ID for entries in the 'name' table
|
||||
* that provide a display string for this
|
||||
* attribute value. */
|
||||
HBFixed value; /* A numeric value for this attribute value. */
|
||||
F16DOT16 value; /* A numeric value for this attribute value. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (12);
|
||||
};
|
||||
|
@ -195,10 +195,10 @@ struct AxisValueFormat2
|
|||
NameID valueNameID; /* The name ID for entries in the 'name' table
|
||||
* that provide a display string for this
|
||||
* attribute value. */
|
||||
HBFixed nominalValue; /* A numeric value for this attribute value. */
|
||||
HBFixed rangeMinValue; /* The minimum value for a range associated
|
||||
F16DOT16 nominalValue; /* A numeric value for this attribute value. */
|
||||
F16DOT16 rangeMinValue; /* The minimum value for a range associated
|
||||
* with the specified name ID. */
|
||||
HBFixed rangeMaxValue; /* The maximum value for a range associated
|
||||
F16DOT16 rangeMaxValue; /* The maximum value for a range associated
|
||||
* with the specified name ID. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (20);
|
||||
|
@ -258,8 +258,8 @@ struct AxisValueFormat3
|
|||
NameID valueNameID; /* The name ID for entries in the 'name' table
|
||||
* that provide a display string for this
|
||||
* attribute value. */
|
||||
HBFixed value; /* A numeric value for this attribute value. */
|
||||
HBFixed linkedValue; /* The numeric value for a style-linked mapping
|
||||
F16DOT16 value; /* A numeric value for this attribute value. */
|
||||
F16DOT16 linkedValue; /* The numeric value for a style-linked mapping
|
||||
* from this value. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (16);
|
||||
|
@ -280,7 +280,7 @@ struct AxisValueRecord
|
|||
HBUINT16 axisIndex; /* Zero-base index into the axis record array
|
||||
* identifying the axis to which this value
|
||||
* applies. Must be less than designAxisCount. */
|
||||
HBFixed value; /* A numeric value for this attribute value. */
|
||||
F16DOT16 value; /* A numeric value for this attribute value. */
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (6);
|
||||
};
|
||||
|
|
98
thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
vendored
98
thirdparty/harfbuzz/src/hb-ot-var-fvar-table.hh
vendored
|
@ -44,9 +44,47 @@ struct InstanceRecord
|
|||
{
|
||||
friend struct fvar;
|
||||
|
||||
hb_array_t<const HBFixed> get_coordinates (unsigned int axis_count) const
|
||||
hb_array_t<const F16DOT16> get_coordinates (unsigned int axis_count) const
|
||||
{ return coordinatesZ.as_array (axis_count); }
|
||||
|
||||
bool subset (hb_subset_context_t *c,
|
||||
unsigned axis_count,
|
||||
bool has_postscript_nameid) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
if (unlikely (!c->serializer->embed (subfamilyNameID))) return_trace (false);
|
||||
if (unlikely (!c->serializer->embed (flags))) return_trace (false);
|
||||
|
||||
const hb_array_t<const F16DOT16> coords = get_coordinates (axis_count);
|
||||
const hb_hashmap_t<hb_tag_t, float> *axes_location = c->plan->user_axes_location;
|
||||
for (unsigned i = 0 ; i < axis_count; i++)
|
||||
{
|
||||
unsigned *axis_tag;
|
||||
// only keep instances whose coordinates == pinned axis location
|
||||
if (!c->plan->axes_old_index_tag_map->has (i, &axis_tag)) continue;
|
||||
|
||||
if (axes_location->has (*axis_tag) &&
|
||||
fabsf (axes_location->get (*axis_tag) - coords[i].to_float ()) > 0.001f)
|
||||
return_trace (false);
|
||||
|
||||
if (!c->plan->axes_index_map->has (i))
|
||||
continue;
|
||||
|
||||
if (!c->serializer->embed (coords[i]))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
if (has_postscript_nameid)
|
||||
{
|
||||
NameID name_id;
|
||||
name_id = StructAfter<NameID> (coords);
|
||||
if (!c->serializer->embed (name_id))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
bool sanitize (hb_sanitize_context_t *c, unsigned int axis_count) const
|
||||
{
|
||||
TRACE_SANITIZE (this);
|
||||
|
@ -58,7 +96,7 @@ struct InstanceRecord
|
|||
NameID subfamilyNameID;/* The name ID for entries in the 'name' table
|
||||
* that provide subfamily names for this instance. */
|
||||
HBUINT16 flags; /* Reserved for future use — set to 0. */
|
||||
UnsizedArrayOf<HBFixed>
|
||||
UnsizedArrayOf<F16DOT16>
|
||||
coordinatesZ; /* The coordinates array for this instance. */
|
||||
//NameID postScriptNameIDX;/*Optional. The name ID for entries in the 'name'
|
||||
// * table that provide PostScript names for this
|
||||
|
@ -151,9 +189,9 @@ struct AxisRecord
|
|||
public:
|
||||
Tag axisTag; /* Tag identifying the design variation for the axis. */
|
||||
protected:
|
||||
HBFixed minValue; /* The minimum coordinate value for the axis. */
|
||||
HBFixed defaultValue; /* The default coordinate value for the axis. */
|
||||
HBFixed maxValue; /* The maximum coordinate value for the axis. */
|
||||
F16DOT16 minValue; /* The minimum coordinate value for the axis. */
|
||||
F16DOT16 defaultValue; /* The default coordinate value for the axis. */
|
||||
F16DOT16 maxValue; /* The maximum coordinate value for the axis. */
|
||||
public:
|
||||
HBUINT16 flags; /* Axis flags. */
|
||||
NameID axisNameID; /* The name ID for entries in the 'name' table that
|
||||
|
@ -268,7 +306,7 @@ struct fvar
|
|||
|
||||
if (coords_length && *coords_length)
|
||||
{
|
||||
hb_array_t<const HBFixed> instanceCoords = instance->get_coordinates (axisCount)
|
||||
hb_array_t<const F16DOT16> instanceCoords = instance->get_coordinates (axisCount)
|
||||
.sub_array (0, coords_length);
|
||||
for (unsigned int i = 0; i < instanceCoords.length; i++)
|
||||
coords[i] = instanceCoords.arrayZ[i].to_float ();
|
||||
|
@ -301,7 +339,7 @@ struct fvar
|
|||
|
||||
if (hb_any (+ hb_zip (instance->get_coordinates (axisCount), hb_range ((unsigned)axisCount))
|
||||
| hb_filter (pinned_axes, hb_second)
|
||||
| hb_map ([&] (const hb_pair_t<const HBFixed&, unsigned>& _)
|
||||
| hb_map ([&] (const hb_pair_t<const F16DOT16&, unsigned>& _)
|
||||
{
|
||||
hb_tag_t axis_tag = pinned_axes.get (_.second);
|
||||
float location = user_axes_location->get (axis_tag);
|
||||
|
@ -321,6 +359,48 @@ struct fvar
|
|||
}
|
||||
}
|
||||
|
||||
bool subset (hb_subset_context_t *c) const
|
||||
{
|
||||
TRACE_SUBSET (this);
|
||||
unsigned retained_axis_count = c->plan->axes_index_map->get_population ();
|
||||
if (!retained_axis_count) //all axes are pinned
|
||||
return_trace (false);
|
||||
|
||||
fvar *out = c->serializer->embed (this);
|
||||
if (unlikely (!out)) return_trace (false);
|
||||
|
||||
if (!c->serializer->check_assign (out->axisCount, retained_axis_count, HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
|
||||
bool has_postscript_nameid = false;
|
||||
if (instanceSize >= axisCount * 4 + 6)
|
||||
has_postscript_nameid = true;
|
||||
|
||||
if (!c->serializer->check_assign (out->instanceSize, retained_axis_count * 4 + (has_postscript_nameid ? 6 : 4),
|
||||
HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
|
||||
auto axes_records = get_axes ();
|
||||
for (unsigned i = 0 ; i < (unsigned)axisCount; i++)
|
||||
{
|
||||
if (!c->plan->axes_index_map->has (i)) continue;
|
||||
if (unlikely (!c->serializer->embed (axes_records[i])))
|
||||
return_trace (false);
|
||||
}
|
||||
|
||||
if (!c->serializer->check_assign (out->firstAxis, get_size (), HB_SERIALIZE_ERROR_INT_OVERFLOW))
|
||||
return_trace (false);
|
||||
|
||||
for (unsigned i = 0 ; i < (unsigned)instanceCount; i++)
|
||||
{
|
||||
const InstanceRecord *instance = get_instance (i);
|
||||
auto snap = c->serializer->snapshot ();
|
||||
if (!instance->subset (c, axisCount, has_postscript_nameid))
|
||||
c->serializer->revert (snap);
|
||||
}
|
||||
return_trace (true);
|
||||
}
|
||||
|
||||
public:
|
||||
hb_array_t<const AxisRecord> get_axes () const
|
||||
{ return hb_array (&(this+firstAxis), axisCount); }
|
||||
|
@ -346,8 +426,8 @@ struct fvar
|
|||
HBUINT16 instanceCount; /* The number of named instances defined in the font
|
||||
* (the number of records in the instances array). */
|
||||
HBUINT16 instanceSize; /* The size in bytes of each InstanceRecord — set
|
||||
* to either axisCount * sizeof(HBFixed) + 4, or to
|
||||
* axisCount * sizeof(HBFixed) + 6. */
|
||||
* to either axisCount * sizeof(F16DOT16) + 4, or to
|
||||
* axisCount * sizeof(F16DOT16) + 6. */
|
||||
|
||||
public:
|
||||
DEFINE_SIZE_STATIC (16);
|
||||
|
|
2
thirdparty/harfbuzz/src/hb-repacker.hh
vendored
2
thirdparty/harfbuzz/src/hb-repacker.hh
vendored
|
@ -244,7 +244,7 @@ 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 (!sorted_graph.duplicate (r.parent, r.child)) continue;
|
||||
if (sorted_graph.duplicate (r.parent, r.child) == (unsigned) -1) continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
76
thirdparty/harfbuzz/src/hb-subset-accelerator.hh
vendored
Normal file
76
thirdparty/harfbuzz/src/hb-subset-accelerator.hh
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright © 2022 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 HB_SUBSET_ACCELERATOR_HH
|
||||
#define HB_SUBSET_ACCELERATOR_HH
|
||||
|
||||
|
||||
#include "hb.hh"
|
||||
|
||||
#include "hb-map.hh"
|
||||
#include "hb-set.hh"
|
||||
|
||||
struct hb_subset_accelerator_t
|
||||
{
|
||||
static hb_user_data_key_t* user_data_key()
|
||||
{
|
||||
static hb_user_data_key_t key;
|
||||
return &key;
|
||||
}
|
||||
|
||||
static hb_subset_accelerator_t* create(const hb_map_t& unicode_to_gid_,
|
||||
const hb_set_t& unicodes_) {
|
||||
hb_subset_accelerator_t* accel =
|
||||
(hb_subset_accelerator_t*) hb_malloc (sizeof(hb_subset_accelerator_t));
|
||||
new (accel) hb_subset_accelerator_t (unicode_to_gid_, unicodes_);
|
||||
return accel;
|
||||
}
|
||||
|
||||
static void destroy(void* value) {
|
||||
if (!value) return;
|
||||
|
||||
hb_subset_accelerator_t* accel = (hb_subset_accelerator_t*) value;
|
||||
accel->~hb_subset_accelerator_t ();
|
||||
hb_free (accel);
|
||||
}
|
||||
|
||||
hb_subset_accelerator_t(const hb_map_t& unicode_to_gid_,
|
||||
const hb_set_t& unicodes_)
|
||||
: unicode_to_gid(unicode_to_gid_), unicodes(unicodes_) {}
|
||||
|
||||
const hb_map_t unicode_to_gid;
|
||||
const hb_set_t unicodes;
|
||||
// TODO(garretrieger): cumulative glyf checksum map
|
||||
// TODO(garretrieger): sanitized table cache.
|
||||
|
||||
bool in_error () const
|
||||
{
|
||||
return unicode_to_gid.in_error() || unicodes.in_error ();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif /* HB_SUBSET_ACCELERATOR_HH */
|
55
thirdparty/harfbuzz/src/hb-subset-input.cc
vendored
55
thirdparty/harfbuzz/src/hb-subset-input.cc
vendored
|
@ -49,7 +49,7 @@ hb_subset_input_create_or_fail (void)
|
|||
set = hb_set_create ();
|
||||
|
||||
input->axes_location = hb_hashmap_create<hb_tag_t, float> ();
|
||||
|
||||
|
||||
if (!input->axes_location || input->in_error ())
|
||||
{
|
||||
hb_subset_input_destroy (input);
|
||||
|
@ -89,7 +89,6 @@ hb_subset_input_create_or_fail (void)
|
|||
|
||||
hb_tag_t default_no_subset_tables[] = {
|
||||
HB_TAG ('a', 'v', 'a', 'r'),
|
||||
HB_TAG ('f', 'v', 'a', 'r'),
|
||||
HB_TAG ('g', 'a', 's', 'p'),
|
||||
HB_TAG ('c', 'v', 't', ' '),
|
||||
HB_TAG ('f', 'p', 'g', 'm'),
|
||||
|
@ -393,7 +392,7 @@ hb_subset_input_get_user_data (const hb_subset_input_t *input,
|
|||
*
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
hb_bool_t
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_subset_input_pin_axis_to_default (hb_subset_input_t *input,
|
||||
hb_face_t *face,
|
||||
hb_tag_t axis_tag)
|
||||
|
@ -417,7 +416,7 @@ hb_subset_input_pin_axis_to_default (hb_subset_input_t *input,
|
|||
*
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
hb_bool_t
|
||||
HB_EXTERN hb_bool_t
|
||||
hb_subset_input_pin_axis_location (hb_subset_input_t *input,
|
||||
hb_face_t *face,
|
||||
hb_tag_t axis_tag,
|
||||
|
@ -432,3 +431,51 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input,
|
|||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
/**
|
||||
* hb_subset_preprocess
|
||||
* @input: a #hb_face_t object.
|
||||
*
|
||||
* Preprocesses the face and attaches data that will be needed by the
|
||||
* subsetter. Future subsetting operations can then use the precomputed data
|
||||
* to speed up the subsetting operation.
|
||||
*
|
||||
* Since: EXPERIMENTAL
|
||||
**/
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_subset_preprocess (hb_face_t *source)
|
||||
{
|
||||
hb_subset_input_t* input = hb_subset_input_create_or_fail ();
|
||||
|
||||
hb_set_clear (hb_subset_input_set(input, HB_SUBSET_SETS_UNICODE));
|
||||
hb_set_invert (hb_subset_input_set(input, HB_SUBSET_SETS_UNICODE));
|
||||
|
||||
hb_set_clear (hb_subset_input_set(input,
|
||||
HB_SUBSET_SETS_LAYOUT_FEATURE_TAG));
|
||||
hb_set_invert (hb_subset_input_set(input,
|
||||
HB_SUBSET_SETS_LAYOUT_FEATURE_TAG));
|
||||
|
||||
hb_set_clear (hb_subset_input_set(input,
|
||||
HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG));
|
||||
hb_set_invert (hb_subset_input_set(input,
|
||||
HB_SUBSET_SETS_LAYOUT_SCRIPT_TAG));
|
||||
|
||||
hb_set_clear (hb_subset_input_set(input,
|
||||
HB_SUBSET_SETS_NAME_ID));
|
||||
hb_set_invert (hb_subset_input_set(input,
|
||||
HB_SUBSET_SETS_NAME_ID));
|
||||
|
||||
hb_subset_input_set_flags(input,
|
||||
HB_SUBSET_FLAGS_NOTDEF_OUTLINE |
|
||||
HB_SUBSET_FLAGS_GLYPH_NAMES |
|
||||
HB_SUBSET_FLAGS_RETAIN_GIDS);
|
||||
input->attach_accelerator_data = true;
|
||||
|
||||
hb_face_t* new_source = hb_subset_or_fail (source, input);
|
||||
hb_subset_input_destroy (input);
|
||||
|
||||
return new_source;
|
||||
}
|
||||
#endif
|
||||
|
|
1
thirdparty/harfbuzz/src/hb-subset-input.hh
vendored
1
thirdparty/harfbuzz/src/hb-subset-input.hh
vendored
|
@ -59,6 +59,7 @@ struct hb_subset_input_t
|
|||
};
|
||||
|
||||
unsigned flags;
|
||||
bool attach_accelerator_data = false;
|
||||
hb_hashmap_t<hb_tag_t, float> *axes_location;
|
||||
|
||||
inline unsigned num_sets () const
|
||||
|
|
199
thirdparty/harfbuzz/src/hb-subset-plan.cc
vendored
199
thirdparty/harfbuzz/src/hb-subset-plan.cc
vendored
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#include "hb-subset-plan.hh"
|
||||
#include "hb-subset-accelerator.hh"
|
||||
#include "hb-map.hh"
|
||||
#include "hb-set.hh"
|
||||
|
||||
|
@ -129,7 +130,9 @@ template <typename T>
|
|||
static void _collect_layout_indices (hb_subset_plan_t *plan,
|
||||
const T& table,
|
||||
hb_set_t *lookup_indices, /* OUT */
|
||||
hb_set_t *feature_indices /* OUT */)
|
||||
hb_set_t *feature_indices, /* OUT */
|
||||
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map, /* OUT */
|
||||
hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map /* OUT */)
|
||||
{
|
||||
unsigned num_features = table.get_feature_count ();
|
||||
hb_vector_t<hb_tag_t> features;
|
||||
|
@ -154,16 +157,37 @@ static void _collect_layout_indices (hb_subset_plan_t *plan,
|
|||
retain_all_features ? nullptr : features.arrayZ,
|
||||
feature_indices);
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
// collect feature substitutes with variations
|
||||
if (!plan->user_axes_location->is_empty ())
|
||||
{
|
||||
hb_hashmap_t<hb::shared_ptr<hb_map_t>, unsigned> conditionset_map;
|
||||
OT::hb_collect_feature_substitutes_with_var_context_t c =
|
||||
{
|
||||
plan->axes_old_index_tag_map,
|
||||
plan->axes_location,
|
||||
feature_record_cond_idx_map,
|
||||
feature_substitutes_map,
|
||||
feature_indices,
|
||||
true,
|
||||
0,
|
||||
&conditionset_map
|
||||
};
|
||||
table.collect_feature_substitutes_with_variations (&c);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (unsigned feature_index : *feature_indices)
|
||||
{
|
||||
//TODO: replace HB_OT_LAYOUT_NO_VARIATIONS_INDEX with variation_index for
|
||||
//instancing
|
||||
const OT::Feature &f = table.get_feature_variation (feature_index, HB_OT_LAYOUT_NO_VARIATIONS_INDEX);
|
||||
f.add_lookup_indexes_to (lookup_indices);
|
||||
const OT::Feature* f = &(table.get_feature (feature_index));
|
||||
const OT::Feature **p = nullptr;
|
||||
if (feature_substitutes_map->has (feature_index, &p))
|
||||
f = *p;
|
||||
|
||||
f->add_lookup_indexes_to (lookup_indices);
|
||||
}
|
||||
|
||||
//TODO: update for instancing: only collect lookups from feature_indexes that have no variations
|
||||
table.feature_variation_collect_lookups (feature_indices, lookup_indices);
|
||||
table.feature_variation_collect_lookups (feature_indices, feature_substitutes_map, lookup_indices);
|
||||
}
|
||||
|
||||
|
||||
|
@ -171,6 +195,7 @@ static inline void
|
|||
_GSUBGPOS_find_duplicate_features (const OT::GSUBGPOS &g,
|
||||
const hb_map_t *lookup_indices,
|
||||
const hb_set_t *feature_indices,
|
||||
const hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map,
|
||||
hb_map_t *duplicate_feature_map /* OUT */)
|
||||
{
|
||||
if (feature_indices->is_empty ()) return;
|
||||
|
@ -195,16 +220,22 @@ _GSUBGPOS_find_duplicate_features (const OT::GSUBGPOS &g,
|
|||
hb_set_t* same_tag_features = unique_features.get (t);
|
||||
for (unsigned other_f_index : same_tag_features->iter ())
|
||||
{
|
||||
const OT::Feature& f = g.get_feature (i);
|
||||
const OT::Feature& other_f = g.get_feature (other_f_index);
|
||||
const OT::Feature* f = &(g.get_feature (i));
|
||||
const OT::Feature **p = nullptr;
|
||||
if (feature_substitutes_map->has (i, &p))
|
||||
f = *p;
|
||||
|
||||
const OT::Feature* other_f = &(g.get_feature (other_f_index));
|
||||
if (feature_substitutes_map->has (other_f_index, &p))
|
||||
f = *p;
|
||||
|
||||
auto f_iter =
|
||||
+ hb_iter (f.lookupIndex)
|
||||
+ hb_iter (f->lookupIndex)
|
||||
| hb_filter (lookup_indices)
|
||||
;
|
||||
|
||||
auto other_f_iter =
|
||||
+ hb_iter (other_f.lookupIndex)
|
||||
+ hb_iter (other_f->lookupIndex)
|
||||
| hb_filter (lookup_indices)
|
||||
;
|
||||
|
||||
|
@ -237,7 +268,9 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan,
|
|||
hb_set_t *gids_to_retain,
|
||||
hb_map_t *lookups,
|
||||
hb_map_t *features,
|
||||
script_langsys_map *langsys_map)
|
||||
script_langsys_map *langsys_map,
|
||||
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *feature_record_cond_idx_map,
|
||||
hb_hashmap_t<unsigned, const OT::Feature*> *feature_substitutes_map)
|
||||
{
|
||||
hb_blob_ptr_t<T> table = plan->source_table<T> ();
|
||||
hb_tag_t table_tag = table->tableTag;
|
||||
|
@ -245,7 +278,9 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan,
|
|||
_collect_layout_indices<T> (plan,
|
||||
*table,
|
||||
&lookup_indices,
|
||||
&feature_indices);
|
||||
&feature_indices,
|
||||
feature_record_cond_idx_map,
|
||||
feature_substitutes_map);
|
||||
|
||||
if (table_tag == HB_OT_TAG_GSUB)
|
||||
hb_ot_layout_lookups_substitute_closure (plan->source,
|
||||
|
@ -257,9 +292,12 @@ _closure_glyphs_lookups_features (hb_subset_plan_t *plan,
|
|||
_remap_indexes (&lookup_indices, lookups);
|
||||
|
||||
// prune features
|
||||
table->prune_features (lookups, &feature_indices);
|
||||
table->prune_features (lookups,
|
||||
plan->user_axes_location->is_empty () ? nullptr : feature_record_cond_idx_map,
|
||||
feature_substitutes_map,
|
||||
&feature_indices);
|
||||
hb_map_t duplicate_feature_map;
|
||||
_GSUBGPOS_find_duplicate_features (*table, lookups, &feature_indices, &duplicate_feature_map);
|
||||
_GSUBGPOS_find_duplicate_features (*table, lookups, &feature_indices, feature_substitutes_map, &duplicate_feature_map);
|
||||
|
||||
feature_indices.clear ();
|
||||
table->prune_langsys (&duplicate_feature_map, plan->layout_scripts, langsys_map, &feature_indices);
|
||||
|
@ -419,41 +457,73 @@ _populate_unicodes_to_retain (const hb_set_t *unicodes,
|
|||
hb_subset_plan_t *plan)
|
||||
{
|
||||
OT::cmap::accelerator_t cmap (plan->source);
|
||||
|
||||
unsigned size_threshold = plan->source->get_num_glyphs ();
|
||||
if (glyphs->is_empty () && unicodes->get_population () < size_threshold)
|
||||
{
|
||||
|
||||
const hb_map_t* unicode_to_gid = nullptr;
|
||||
if (plan->accelerator)
|
||||
unicode_to_gid = &plan->accelerator->unicode_to_gid;
|
||||
|
||||
// This is approach to collection is faster, but can only be used if glyphs
|
||||
// are not being explicitly added to the subset and the input unicodes set is
|
||||
// not excessively large (eg. an inverted set).
|
||||
plan->unicode_to_new_gid_list.alloc (unicodes->get_population ());
|
||||
for (hb_codepoint_t cp : *unicodes)
|
||||
{
|
||||
hb_codepoint_t gid;
|
||||
if (!cmap.get_nominal_glyph (cp, &gid))
|
||||
if (!unicode_to_gid) {
|
||||
for (hb_codepoint_t cp : *unicodes)
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
|
||||
continue;
|
||||
}
|
||||
hb_codepoint_t gid;
|
||||
if (!cmap.get_nominal_glyph (cp, &gid))
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
|
||||
continue;
|
||||
}
|
||||
|
||||
plan->codepoint_to_glyph->set (cp, gid);
|
||||
plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
|
||||
plan->codepoint_to_glyph->set (cp, gid);
|
||||
plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
|
||||
}
|
||||
} else {
|
||||
// Use in memory unicode to gid map it's faster then looking up from
|
||||
// the map. This code is mostly duplicated from above to avoid doing
|
||||
// conditionals on the presence of the unicode_to_gid map each
|
||||
// iteration.
|
||||
for (hb_codepoint_t cp : *unicodes)
|
||||
{
|
||||
hb_codepoint_t gid = unicode_to_gid->get (cp);
|
||||
if (gid == HB_MAP_VALUE_INVALID)
|
||||
{
|
||||
DEBUG_MSG(SUBSET, nullptr, "Drop U+%04X; no gid", cp);
|
||||
continue;
|
||||
}
|
||||
|
||||
plan->codepoint_to_glyph->set (cp, gid);
|
||||
plan->unicode_to_new_gid_list.push (hb_pair (cp, gid));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// This approach is slower, but can handle adding in glyphs to the subset and will match
|
||||
// them with cmap entries.
|
||||
hb_map_t unicode_glyphid_map;
|
||||
hb_set_t cmap_unicodes;
|
||||
cmap.collect_mapping (&cmap_unicodes, &unicode_glyphid_map);
|
||||
plan->unicode_to_new_gid_list.alloc (hb_min(unicodes->get_population ()
|
||||
+ glyphs->get_population (),
|
||||
cmap_unicodes.get_population ()));
|
||||
|
||||
for (hb_codepoint_t cp : cmap_unicodes)
|
||||
hb_map_t unicode_glyphid_map_storage;
|
||||
hb_set_t cmap_unicodes_storage;
|
||||
const hb_map_t* unicode_glyphid_map = &unicode_glyphid_map_storage;
|
||||
const hb_set_t* cmap_unicodes = &cmap_unicodes_storage;
|
||||
|
||||
if (!plan->accelerator) {
|
||||
cmap.collect_mapping (&cmap_unicodes_storage, &unicode_glyphid_map_storage);
|
||||
plan->unicode_to_new_gid_list.alloc (hb_min(unicodes->get_population ()
|
||||
+ glyphs->get_population (),
|
||||
cmap_unicodes->get_population ()));
|
||||
} else {
|
||||
unicode_glyphid_map = &plan->accelerator->unicode_to_gid;
|
||||
cmap_unicodes = &plan->accelerator->unicodes;
|
||||
}
|
||||
|
||||
for (hb_codepoint_t cp : *cmap_unicodes)
|
||||
{
|
||||
hb_codepoint_t gid = unicode_glyphid_map[cp];
|
||||
hb_codepoint_t gid = (*unicode_glyphid_map)[cp];
|
||||
if (!unicodes->has (cp) && !glyphs->has (gid))
|
||||
continue;
|
||||
|
||||
|
@ -509,9 +579,7 @@ _glyf_add_gid_and_children (const OT::glyf_accelerator_t &glyf,
|
|||
|
||||
static void
|
||||
_populate_gids_to_retain (hb_subset_plan_t* plan,
|
||||
bool close_over_gsub,
|
||||
bool close_over_gpos,
|
||||
bool close_over_gdef)
|
||||
hb_set_t* drop_tables)
|
||||
{
|
||||
OT::glyf_accelerator_t glyf (plan->source);
|
||||
#ifndef HB_NO_SUBSET_CFF
|
||||
|
@ -523,32 +591,42 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
|
|||
_cmap_closure (plan->source, plan->unicodes, plan->_glyphset_gsub);
|
||||
|
||||
#ifndef HB_NO_SUBSET_LAYOUT
|
||||
if (close_over_gsub)
|
||||
if (!drop_tables->has (HB_OT_TAG_GSUB))
|
||||
// closure all glyphs/lookups/features needed for GSUB substitutions.
|
||||
_closure_glyphs_lookups_features<GSUB> (
|
||||
plan,
|
||||
plan->_glyphset_gsub,
|
||||
plan->gsub_lookups,
|
||||
plan->gsub_features,
|
||||
plan->gsub_langsys);
|
||||
plan->gsub_langsys,
|
||||
plan->gsub_feature_record_cond_idx_map,
|
||||
plan->gsub_feature_substitutes_map);
|
||||
|
||||
if (close_over_gpos)
|
||||
if (!drop_tables->has (HB_OT_TAG_GPOS))
|
||||
_closure_glyphs_lookups_features<GPOS> (
|
||||
plan,
|
||||
plan->_glyphset_gsub,
|
||||
plan->gpos_lookups,
|
||||
plan->gpos_features,
|
||||
plan->gpos_langsys);
|
||||
plan->gpos_langsys,
|
||||
plan->gpos_feature_record_cond_idx_map,
|
||||
plan->gpos_feature_substitutes_map);
|
||||
#endif
|
||||
_remove_invalid_gids (plan->_glyphset_gsub, plan->source->get_num_glyphs ());
|
||||
|
||||
hb_set_set (plan->_glyphset_mathed, plan->_glyphset_gsub);
|
||||
_math_closure (plan, plan->_glyphset_mathed);
|
||||
_remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ());
|
||||
if (!drop_tables->has (HB_OT_TAG_MATH))
|
||||
{
|
||||
_math_closure (plan, plan->_glyphset_mathed);
|
||||
_remove_invalid_gids (plan->_glyphset_mathed, plan->source->get_num_glyphs ());
|
||||
}
|
||||
|
||||
hb_set_t cur_glyphset = *plan->_glyphset_mathed;
|
||||
_colr_closure (plan->source, plan->colrv1_layers, plan->colr_palettes, &cur_glyphset);
|
||||
_remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ());
|
||||
if (!drop_tables->has (HB_OT_TAG_COLR))
|
||||
{
|
||||
_colr_closure (plan->source, plan->colrv1_layers, plan->colr_palettes, &cur_glyphset);
|
||||
_remove_invalid_gids (&cur_glyphset, plan->source->get_num_glyphs ());
|
||||
}
|
||||
|
||||
hb_set_set (plan->_glyphset_colred, &cur_glyphset);
|
||||
|
||||
|
@ -570,7 +648,7 @@ _populate_gids_to_retain (hb_subset_plan_t* plan,
|
|||
|
||||
|
||||
#ifndef HB_NO_VAR
|
||||
if (close_over_gdef)
|
||||
if (!drop_tables->has (HB_OT_TAG_GDEF))
|
||||
_collect_layout_variation_indices (plan);
|
||||
#endif
|
||||
}
|
||||
|
@ -659,18 +737,22 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
|
|||
seg_maps = face->table.avar->get_segment_maps ();
|
||||
|
||||
bool axis_not_pinned = false;
|
||||
unsigned axis_count = 0;
|
||||
unsigned old_axis_idx = 0, new_axis_idx = 0;
|
||||
for (const auto& axis : axes)
|
||||
{
|
||||
hb_tag_t axis_tag = axis.get_axis_tag ();
|
||||
plan->axes_old_index_tag_map->set (old_axis_idx, axis_tag);
|
||||
|
||||
if (!plan->user_axes_location->has (axis_tag))
|
||||
{
|
||||
axis_not_pinned = true;
|
||||
plan->axes_index_map->set (old_axis_idx, new_axis_idx);
|
||||
new_axis_idx++;
|
||||
}
|
||||
else
|
||||
{
|
||||
int normalized_v = axis.normalize_axis_value (plan->user_axes_location->get (axis_tag));
|
||||
if (has_avar && axis_count < face->table.avar->get_axis_count ())
|
||||
if (has_avar && old_axis_idx < face->table.avar->get_axis_count ())
|
||||
{
|
||||
normalized_v = seg_maps->map (normalized_v);
|
||||
}
|
||||
|
@ -681,7 +763,7 @@ _normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan)
|
|||
if (has_avar)
|
||||
seg_maps = &StructAfter<OT::SegmentMaps> (*seg_maps);
|
||||
|
||||
axis_count++;
|
||||
old_axis_idx++;
|
||||
}
|
||||
plan->all_axes_pinned = !axis_not_pinned;
|
||||
}
|
||||
|
@ -741,6 +823,13 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
|
|||
|
||||
plan->gsub_features = hb_map_create ();
|
||||
plan->gpos_features = hb_map_create ();
|
||||
|
||||
plan->check_success (plan->gsub_feature_record_cond_idx_map = hb_hashmap_create<unsigned, hb::shared_ptr<hb_set_t>> ());
|
||||
plan->check_success (plan->gpos_feature_record_cond_idx_map = hb_hashmap_create<unsigned, hb::shared_ptr<hb_set_t>> ());
|
||||
|
||||
plan->check_success (plan->gsub_feature_substitutes_map = hb_hashmap_create<unsigned, const OT::Feature*> ());
|
||||
plan->check_success (plan->gpos_feature_substitutes_map = hb_hashmap_create<unsigned, const OT::Feature*> ());
|
||||
|
||||
plan->colrv1_layers = hb_map_create ();
|
||||
plan->colr_palettes = hb_map_create ();
|
||||
plan->check_success (plan->layout_variation_idx_delta_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ());
|
||||
|
@ -751,12 +840,21 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
|
|||
plan->check_success (plan->user_axes_location = hb_hashmap_create<hb_tag_t, float> ());
|
||||
if (plan->user_axes_location && input->axes_location)
|
||||
*plan->user_axes_location = *input->axes_location;
|
||||
plan->check_success (plan->axes_index_map = hb_map_create ());
|
||||
plan->check_success (plan->axes_old_index_tag_map = hb_map_create ());
|
||||
plan->all_axes_pinned = false;
|
||||
plan->pinned_at_default = true;
|
||||
|
||||
plan->check_success (plan->vmtx_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ());
|
||||
plan->check_success (plan->hmtx_map = hb_hashmap_create<unsigned, hb_pair_t<unsigned, int>> ());
|
||||
|
||||
void* accel = hb_face_get_user_data(face, hb_subset_accelerator_t::user_data_key());
|
||||
|
||||
plan->attach_accelerator_data = input->attach_accelerator_data;
|
||||
if (accel)
|
||||
plan->accelerator = (hb_subset_accelerator_t*) accel;
|
||||
|
||||
|
||||
if (unlikely (plan->in_error ())) {
|
||||
hb_subset_plan_destroy (plan);
|
||||
return nullptr;
|
||||
|
@ -768,10 +866,7 @@ hb_subset_plan_create_or_fail (hb_face_t *face,
|
|||
|
||||
_populate_unicodes_to_retain (input->sets.unicodes, input->sets.glyphs, plan);
|
||||
|
||||
_populate_gids_to_retain (plan,
|
||||
!input->sets.drop_tables->has (HB_OT_TAG_GSUB),
|
||||
!input->sets.drop_tables->has (HB_OT_TAG_GPOS),
|
||||
!input->sets.drop_tables->has (HB_OT_TAG_GDEF));
|
||||
_populate_gids_to_retain (plan, input->sets.drop_tables);
|
||||
|
||||
_create_old_gid_to_new_gid_map (face,
|
||||
input->flags & HB_SUBSET_FLAGS_RETAIN_GIDS,
|
||||
|
|
27
thirdparty/harfbuzz/src/hb-subset-plan.hh
vendored
27
thirdparty/harfbuzz/src/hb-subset-plan.hh
vendored
|
@ -31,11 +31,16 @@
|
|||
|
||||
#include "hb-subset.h"
|
||||
#include "hb-subset-input.hh"
|
||||
#include "hb-subset-accelerator.hh"
|
||||
|
||||
#include "hb-map.hh"
|
||||
#include "hb-bimap.hh"
|
||||
#include "hb-set.hh"
|
||||
|
||||
namespace OT {
|
||||
struct Feature;
|
||||
}
|
||||
|
||||
struct hb_subset_plan_t
|
||||
{
|
||||
hb_subset_plan_t ()
|
||||
|
@ -67,9 +72,15 @@ struct hb_subset_plan_t
|
|||
hb_map_destroy (gpos_features);
|
||||
hb_map_destroy (colrv1_layers);
|
||||
hb_map_destroy (colr_palettes);
|
||||
hb_map_destroy (axes_index_map);
|
||||
hb_map_destroy (axes_old_index_tag_map);
|
||||
|
||||
hb_hashmap_destroy (gsub_langsys);
|
||||
hb_hashmap_destroy (gpos_langsys);
|
||||
hb_hashmap_destroy (gsub_feature_record_cond_idx_map);
|
||||
hb_hashmap_destroy (gpos_feature_record_cond_idx_map);
|
||||
hb_hashmap_destroy (gsub_feature_substitutes_map);
|
||||
hb_hashmap_destroy (gpos_feature_substitutes_map);
|
||||
hb_hashmap_destroy (axes_location);
|
||||
hb_hashmap_destroy (sanitized_table_cache);
|
||||
hb_hashmap_destroy (hmtx_map);
|
||||
|
@ -87,6 +98,7 @@ struct hb_subset_plan_t
|
|||
|
||||
bool successful;
|
||||
unsigned flags;
|
||||
bool attach_accelerator_data = false;
|
||||
|
||||
// For each cp that we'd like to retain maps to the corresponding gid.
|
||||
hb_set_t *unicodes;
|
||||
|
@ -143,6 +155,15 @@ struct hb_subset_plan_t
|
|||
hb_map_t *gsub_features;
|
||||
hb_map_t *gpos_features;
|
||||
|
||||
//active feature variation records/condition index with variations
|
||||
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *gsub_feature_record_cond_idx_map;
|
||||
hb_hashmap_t<unsigned, hb::shared_ptr<hb_set_t>> *gpos_feature_record_cond_idx_map;
|
||||
|
||||
//feature index-> address of substituation feature table mapping with
|
||||
//variations
|
||||
hb_hashmap_t<unsigned, const OT::Feature*> *gsub_feature_substitutes_map;
|
||||
hb_hashmap_t<unsigned, const OT::Feature*> *gpos_feature_substitutes_map;
|
||||
|
||||
//active layers/palettes we'd like to retain
|
||||
hb_map_t *colrv1_layers;
|
||||
hb_map_t *colr_palettes;
|
||||
|
@ -158,6 +179,10 @@ struct hb_subset_plan_t
|
|||
hb_hashmap_t<hb_tag_t, int> *axes_location;
|
||||
//user specified axes location map
|
||||
hb_hashmap_t<hb_tag_t, float> *user_axes_location;
|
||||
//retained old axis index -> new axis index mapping in fvar axis array
|
||||
hb_map_t *axes_index_map;
|
||||
//axis_index->axis_tag mapping in fvar axis array
|
||||
hb_map_t *axes_old_index_tag_map;
|
||||
bool all_axes_pinned;
|
||||
bool pinned_at_default;
|
||||
|
||||
|
@ -166,6 +191,8 @@ struct hb_subset_plan_t
|
|||
//vmtx metrics map: new gid->(advance, lsb)
|
||||
hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> *vmtx_map;
|
||||
|
||||
const hb_subset_accelerator_t* accelerator;
|
||||
|
||||
public:
|
||||
|
||||
template<typename T>
|
||||
|
|
30
thirdparty/harfbuzz/src/hb-subset.cc
vendored
30
thirdparty/harfbuzz/src/hb-subset.cc
vendored
|
@ -50,11 +50,13 @@
|
|||
#include "hb-ot-color-cbdt-table.hh"
|
||||
#include "hb-ot-layout-gsub-table.hh"
|
||||
#include "hb-ot-layout-gpos-table.hh"
|
||||
#include "hb-ot-var-fvar-table.hh"
|
||||
#include "hb-ot-var-gvar-table.hh"
|
||||
#include "hb-ot-var-hvar-table.hh"
|
||||
#include "hb-ot-math-table.hh"
|
||||
#include "hb-ot-stat-table.hh"
|
||||
#include "hb-repacker.hh"
|
||||
#include "hb-subset-accelerator.hh"
|
||||
|
||||
using OT::Layout::GSUB;
|
||||
using OT::Layout::GPOS;
|
||||
|
@ -475,6 +477,9 @@ _subset_table (hb_subset_plan_t *plan,
|
|||
case HB_OT_TAG_HVAR: return _subset<const OT::HVAR> (plan, buf);
|
||||
case HB_OT_TAG_VVAR: return _subset<const OT::VVAR> (plan, buf);
|
||||
#endif
|
||||
case HB_OT_TAG_fvar:
|
||||
if (plan->user_axes_location->is_empty ()) return _passthrough (plan, tag);
|
||||
return _subset<const OT::fvar> (plan, buf);
|
||||
case HB_OT_TAG_STAT:
|
||||
/*TODO(qxliu): change the condition as we support more complex
|
||||
* instancing operation*/
|
||||
|
@ -490,6 +495,27 @@ _subset_table (hb_subset_plan_t *plan,
|
|||
}
|
||||
}
|
||||
|
||||
static void _attach_accelerator_data (const hb_subset_plan_t* plan,
|
||||
hb_face_t* face /* IN/OUT */)
|
||||
{
|
||||
hb_subset_accelerator_t* accel =
|
||||
hb_subset_accelerator_t::create (*plan->codepoint_to_glyph,
|
||||
*plan->unicodes);
|
||||
|
||||
if (accel->in_error ())
|
||||
{
|
||||
hb_subset_accelerator_t::destroy (accel);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hb_face_set_user_data(face,
|
||||
hb_subset_accelerator_t::user_data_key(),
|
||||
accel,
|
||||
hb_subset_accelerator_t::destroy,
|
||||
true))
|
||||
hb_subset_accelerator_t::destroy (accel);
|
||||
}
|
||||
|
||||
/**
|
||||
* hb_subset_or_fail:
|
||||
* @source: font face data to be subset.
|
||||
|
@ -572,6 +598,10 @@ hb_subset_plan_execute_or_fail (hb_subset_plan_t *plan)
|
|||
offset += num_tables;
|
||||
}
|
||||
|
||||
if (success && plan->attach_accelerator_data) {
|
||||
_attach_accelerator_data (plan, plan->dest);
|
||||
}
|
||||
|
||||
end:
|
||||
return success ? hb_face_reference (plan->dest) : nullptr;
|
||||
}
|
||||
|
|
17
thirdparty/harfbuzz/src/hb-subset.h
vendored
17
thirdparty/harfbuzz/src/hb-subset.h
vendored
|
@ -70,6 +70,14 @@ typedef struct hb_subset_plan_t hb_subset_plan_t;
|
|||
* in the final subset.
|
||||
* @HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES: If set then the unicode ranges in
|
||||
* OS/2 will not be recalculated.
|
||||
* @HB_SUBSET_FLAGS_PATCH_MODE: If set the subsetter behaviour will be modified
|
||||
* to produce a subset that is better suited to patching. For example cmap
|
||||
* subtable format will be kept stable.
|
||||
* @HB_SUBSET_FLAGS_OMIT_GLYF: If set the subsetter won't actually produce the final
|
||||
* glyf table bytes. The table directory will include and entry as if the table was
|
||||
* there but the actual final font blob will be truncated prior to the glyf data. This
|
||||
* is a useful performance optimization when a font aware binary patching algorithm
|
||||
* is being used to diff two subsets.
|
||||
*
|
||||
* List of boolean properties that can be configured on the subset input.
|
||||
*
|
||||
|
@ -86,6 +94,8 @@ typedef enum { /*< flags >*/
|
|||
HB_SUBSET_FLAGS_NOTDEF_OUTLINE = 0x00000040u,
|
||||
HB_SUBSET_FLAGS_GLYPH_NAMES = 0x00000080u,
|
||||
HB_SUBSET_FLAGS_NO_PRUNE_UNICODE_RANGES = 0x00000100u,
|
||||
// Not supported yet: HB_SUBSET_FLAGS_PATCH_MODE = 0x00000200u,
|
||||
// Not supported yet: HB_SUBSET_FLAGS_OMIT_GLYF = 0x00000400u,
|
||||
} hb_subset_flags_t;
|
||||
|
||||
/**
|
||||
|
@ -169,6 +179,13 @@ hb_subset_input_pin_axis_location (hb_subset_input_t *input,
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_subset_preprocess (hb_face_t *source);
|
||||
|
||||
#endif
|
||||
|
||||
HB_EXTERN hb_face_t *
|
||||
hb_subset_or_fail (hb_face_t *source, const hb_subset_input_t *input);
|
||||
|
||||
|
|
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 0
|
||||
#define HB_VERSION_MICRO 1
|
||||
|
||||
/**
|
||||
* HB_VERSION_STRING:
|
||||
*
|
||||
* A string literal containing the library version available at compile-time.
|
||||
*/
|
||||
#define HB_VERSION_STRING "5.2.0"
|
||||
#define HB_VERSION_STRING "5.3.1"
|
||||
|
||||
/**
|
||||
* HB_VERSION_ATLEAST:
|
||||
|
|
Loading…
Reference in a new issue