summaryrefslogtreecommitdiff
path: root/thirdparty/harfbuzz/src/OT/glyf
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/harfbuzz/src/OT/glyf')
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh118
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/Glyph.hh127
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh126
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh14
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/glyf-helpers.hh2
-rw-r--r--thirdparty/harfbuzz/src/OT/glyf/glyf.hh42
6 files changed, 424 insertions, 5 deletions
diff --git a/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh
index 98c2ee4e73..fc8e309bc9 100644
--- a/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh
+++ b/thirdparty/harfbuzz/src/OT/glyf/CompositeGlyph.hh
@@ -105,6 +105,67 @@ struct CompositeGlyphRecord
}
}
+ unsigned compile_with_deltas (const contour_point_t &p_delta,
+ char *out) const
+ {
+ const HBINT8 *p = &StructAfter<const HBINT8> (flags);
+#ifndef HB_NO_BEYOND_64K
+ if (flags & GID_IS_24BIT)
+ p += HBGlyphID24::static_size;
+ else
+#endif
+ p += HBGlyphID16::static_size;
+
+ unsigned len = get_size ();
+ unsigned len_before_val = (const char *)p - (const char *)this;
+ if (flags & ARG_1_AND_2_ARE_WORDS)
+ {
+ // no overflow, copy and update value with deltas
+ memcpy (out, this, len);
+
+ const HBINT16 *px = reinterpret_cast<const HBINT16 *> (p);
+ HBINT16 *o = reinterpret_cast<HBINT16 *> (out + len_before_val);
+ o[0] = px[0] + roundf (p_delta.x);
+ o[1] = px[1] + roundf (p_delta.y);
+ }
+ else
+ {
+ int new_x = p[0] + roundf (p_delta.x);
+ int new_y = p[1] + roundf (p_delta.y);
+ if (new_x <= 127 && new_x >= -128 &&
+ new_y <= 127 && new_y >= -128)
+ {
+ memcpy (out, this, len);
+ HBINT8 *o = reinterpret_cast<HBINT8 *> (out + len_before_val);
+ o[0] = new_x;
+ o[1] = new_y;
+ }
+ else
+ {
+ // int8 overflows after deltas applied
+ memcpy (out, this, len_before_val);
+
+ //update flags
+ CompositeGlyphRecord *o = reinterpret_cast<CompositeGlyphRecord *> (out);
+ o->flags = flags | ARG_1_AND_2_ARE_WORDS;
+ out += len_before_val;
+
+ HBINT16 new_value;
+ new_value = new_x;
+ memcpy (out, &new_value, HBINT16::static_size);
+ out += HBINT16::static_size;
+
+ new_value = new_y;
+ memcpy (out, &new_value, HBINT16::static_size);
+ out += HBINT16::static_size;
+
+ memcpy (out, p+2, len - len_before_val - 2);
+ len += 2;
+ }
+ }
+ return len;
+ }
+
protected:
bool scaled_offsets () const
{ return (flags & (SCALED_COMPONENT_OFFSET | UNSCALED_COMPONENT_OFFSET)) == SCALED_COMPONENT_OFFSET; }
@@ -288,6 +349,63 @@ struct CompositeGlyph
return;
glyph_chain.set_overlaps_flag ();
}
+
+ bool compile_bytes_with_deltas (const hb_bytes_t &source_bytes,
+ const contour_point_vector_t &deltas,
+ hb_bytes_t &dest_bytes /* OUT */)
+ {
+ if (source_bytes.length <= GlyphHeader::static_size ||
+ header.numberOfContours != -1)
+ {
+ dest_bytes = hb_bytes_t ();
+ return true;
+ }
+
+ unsigned source_len = source_bytes.length - GlyphHeader::static_size;
+
+ /* try to allocate more memories than source glyph bytes
+ * in case that there might be an overflow for int8 value
+ * and we would need to use int16 instead */
+ char *o = (char *) hb_calloc (source_len + source_len/2, sizeof (char));
+ if (unlikely (!o)) return false;
+
+ const CompositeGlyphRecord *c = reinterpret_cast<const CompositeGlyphRecord *> (source_bytes.arrayZ + GlyphHeader::static_size);
+ auto it = composite_iter_t (hb_bytes_t ((const char *)c, source_len), c);
+
+ char *p = o;
+ unsigned i = 0, source_comp_len = 0;
+ for (const auto &component : it)
+ {
+ /* last 4 points in deltas are phantom points and should not be included */
+ if (i >= deltas.length - 4) return false;
+
+ unsigned comp_len = component.get_size ();
+ if (component.is_anchored ())
+ {
+ memcpy (p, &component, comp_len);
+ p += comp_len;
+ }
+ else
+ {
+ unsigned new_len = component.compile_with_deltas (deltas[i], p);
+ p += new_len;
+ }
+ i++;
+ source_comp_len += comp_len;
+ }
+
+ //copy instructions if any
+ if (source_len > source_comp_len)
+ {
+ unsigned instr_len = source_len - source_comp_len;
+ memcpy (p, (const char *)c + source_comp_len, instr_len);
+ p += instr_len;
+ }
+
+ unsigned len = p - o;
+ dest_bytes = hb_bytes_t (o, len);
+ return true;
+ }
};
diff --git a/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh b/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh
index 3efe538f37..afcb5dc834 100644
--- a/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh
+++ b/thirdparty/harfbuzz/src/OT/glyf/Glyph.hh
@@ -72,12 +72,117 @@ struct Glyph
}
}
+ void update_mtx (const hb_subset_plan_t *plan,
+ int xMin, int yMax,
+ const contour_point_vector_t &all_points) const
+ {
+ hb_codepoint_t new_gid = 0;
+ if (!plan->new_gid_for_old_gid (gid, &new_gid))
+ return;
+
+ unsigned len = all_points.length;
+ float leftSideX = all_points[len - 4].x;
+ float rightSideX = all_points[len - 3].x;
+ float topSideY = all_points[len - 2].y;
+ float bottomSideY = all_points[len - 1].y;
+
+ int hori_aw = roundf (rightSideX - leftSideX);
+ if (hori_aw < 0) hori_aw = 0;
+ int lsb = roundf (xMin - leftSideX);
+ plan->hmtx_map->set (new_gid, hb_pair (hori_aw, lsb));
+
+ int vert_aw = roundf (topSideY - bottomSideY);
+ if (vert_aw < 0) vert_aw = 0;
+ int tsb = roundf (topSideY - yMax);
+ plan->vmtx_map->set (new_gid, hb_pair (vert_aw, tsb));
+ }
+
+ bool compile_header_bytes (const hb_subset_plan_t *plan,
+ const contour_point_vector_t &all_points,
+ hb_bytes_t &dest_bytes /* OUT */) const
+ {
+ GlyphHeader *glyph_header = nullptr;
+ if (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);
+
+ for (unsigned i = 1; i < all_points.length - 4; i++)
+ {
+ float rounded_x = roundf (all_points[i].x);
+ float rounded_y = roundf (all_points[i].y);
+ xMin = hb_min (xMin, rounded_x);
+ xMax = hb_max (xMax, rounded_x);
+ yMin = hb_min (yMin, rounded_y);
+ yMax = hb_max (yMax, rounded_y);
+ }
+
+ update_mtx (plan, xMin, yMax, all_points);
+
+ /*for empty glyphs: all_points only include phantom points.
+ *just update metrics and then return */
+ if (all_points.length == 4)
+ return true;
+
+ glyph_header->numberOfContours = header->numberOfContours;
+ glyph_header->xMin = xMin;
+ glyph_header->yMin = yMin;
+ glyph_header->xMax = xMax;
+ glyph_header->yMax = yMax;
+
+ dest_bytes = hb_bytes_t ((const char *)glyph_header, GlyphHeader::static_size);
+ return true;
+ }
+
+ bool compile_bytes_with_deltas (const hb_subset_plan_t *plan,
+ hb_font_t *font,
+ const glyf_accelerator_t &glyf,
+ hb_bytes_t &dest_start, /* IN/OUT */
+ hb_bytes_t &dest_end /* OUT */) const
+ {
+ contour_point_vector_t all_points, deltas;
+ get_points (font, glyf, all_points, &deltas, false);
+
+ switch (type) {
+ case COMPOSITE:
+ if (!CompositeGlyph (*header, bytes).compile_bytes_with_deltas (dest_start,
+ deltas,
+ dest_end))
+ return false;
+ break;
+ case SIMPLE:
+ if (!SimpleGlyph (*header, bytes).compile_bytes_with_deltas (all_points,
+ plan->flags & HB_SUBSET_FLAGS_NO_HINTING,
+ dest_end))
+ return false;
+ break;
+ default:
+ /* set empty bytes for empty glyph
+ * do not use source glyph's pointers */
+ dest_start = hb_bytes_t ();
+ dest_end = hb_bytes_t ();
+ break;
+ }
+
+ return compile_header_bytes (plan, all_points, dest_start);
+ }
+
+
/* Note: Recursively calls itself.
* all_points includes phantom points
*/
template <typename accelerator_t>
bool get_points (hb_font_t *font, const accelerator_t &glyf_accelerator,
contour_point_vector_t &all_points /* OUT */,
+ contour_point_vector_t *deltas = nullptr, /* OUT */
+ bool use_my_metrics = true,
bool phantom_only = false,
unsigned int depth = 0) const
{
@@ -130,10 +235,28 @@ struct Glyph
phantoms[PHANTOM_BOTTOM].y = v_orig - (int) v_adv;
}
+ 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];
+ }
+
#ifndef HB_NO_VAR
glyf_accelerator.gvar->apply_deltas_to_points (gid, font, points.as_array ());
#endif
+ // mainly used by CompositeGlyph calculating new X/Y offset value so no need to extend it
+ // with child glyphs' points
+ if (deltas != nullptr && depth == 0 && type == COMPOSITE)
+ {
+ for (unsigned i = 0 ; i < points.length; i++)
+ {
+ deltas->arrayZ[i].x = points.arrayZ[i].x - deltas->arrayZ[i].x;
+ deltas->arrayZ[i].y = points.arrayZ[i].y - deltas->arrayZ[i].y;
+ }
+ }
+
switch (type) {
case SIMPLE:
if (!inplace)
@@ -148,11 +271,11 @@ struct Glyph
comp_points.reset ();
if (unlikely (!glyf_accelerator.glyph_for_gid (item.get_gid ())
.get_points (font, glyf_accelerator, comp_points,
- phantom_only, depth + 1)))
+ deltas, use_my_metrics, phantom_only, depth + 1)))
return false;
/* Copy phantom points from component if USE_MY_METRICS flag set */
- if (item.is_use_my_metrics ())
+ 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];
diff --git a/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh
index 6df978cf13..b99665d6a0 100644
--- a/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh
+++ b/thirdparty/harfbuzz/src/OT/glyf/SimpleGlyph.hh
@@ -206,6 +206,132 @@ struct SimpleGlyph
&& read_points (p, points_, end, &contour_point_t::y,
FLAG_Y_SHORT, FLAG_Y_SAME);
}
+
+ static void encode_coord (int value,
+ uint8_t &flag,
+ const simple_glyph_flag_t short_flag,
+ const simple_glyph_flag_t same_flag,
+ hb_vector_t<uint8_t> &coords /* OUT */)
+ {
+ if (value == 0)
+ {
+ flag |= same_flag;
+ }
+ else if (value >= -255 && value <= 255)
+ {
+ flag |= short_flag;
+ if (value > 0) flag |= same_flag;
+ else value = -value;
+
+ coords.push ((uint8_t)value);
+ }
+ else
+ {
+ int16_t val = value;
+ coords.push (val >> 8);
+ coords.push (val & 0xff);
+ }
+ }
+
+ static void encode_flag (uint8_t &flag,
+ uint8_t &repeat,
+ uint8_t &lastflag,
+ hb_vector_t<uint8_t> &flags /* OUT */)
+ {
+ if (flag == lastflag && repeat != 255)
+ {
+ repeat = repeat + 1;
+ if (repeat == 1)
+ {
+ flags.push(flag);
+ }
+ else
+ {
+ unsigned len = flags.length;
+ flags[len-2] = flag | FLAG_REPEAT;
+ flags[len-1] = repeat;
+ }
+ }
+ else
+ {
+ repeat = 0;
+ flags.push (flag);
+ }
+ lastflag = flag;
+ }
+
+ bool compile_bytes_with_deltas (const contour_point_vector_t &all_points,
+ bool no_hinting,
+ hb_bytes_t &dest_bytes /* OUT */)
+ {
+ if (header.numberOfContours == 0 || all_points.length <= 4)
+ {
+ dest_bytes = hb_bytes_t ();
+ return true;
+ }
+ //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);
+
+ uint8_t lastflag = 0, repeat = 0;
+
+ 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);
+ if (i == 0) lastflag = flag + 1; //make lastflag != flag for the first point
+ encode_flag (flag, repeat, lastflag, flags);
+ }
+
+ unsigned len_before_instrs = 2 * header.numberOfContours + 2;
+ unsigned len_instrs = instructions_length ();
+ unsigned total_len = len_before_instrs + flags.length + x_coords.length + y_coords.length;
+
+ if (!no_hinting)
+ total_len += len_instrs;
+
+ char *p = (char *) hb_calloc (total_len, sizeof (char));
+ if (unlikely (!p)) return false;
+
+ const char *src = bytes.arrayZ + GlyphHeader::static_size;
+ char *cur = p;
+ memcpy (p, src, len_before_instrs);
+
+ cur += len_before_instrs;
+ src += len_before_instrs;
+
+ if (!no_hinting)
+ {
+ memcpy (cur, src, len_instrs);
+ cur += len_instrs;
+ }
+
+ memcpy (cur, flags.arrayZ, flags.length);
+ cur += flags.length;
+
+ memcpy (cur, x_coords.arrayZ, x_coords.length);
+ cur += x_coords.length;
+
+ memcpy (cur, y_coords.arrayZ, y_coords.length);
+
+ dest_bytes = hb_bytes_t (p, total_len);
+ return true;
+ }
};
diff --git a/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh b/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh
index 7ae8fe3078..7ddefc5a91 100644
--- a/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh
+++ b/thirdparty/harfbuzz/src/OT/glyf/SubsetGlyph.hh
@@ -6,6 +6,9 @@
namespace OT {
+
+struct glyf_accelerator_t;
+
namespace glyf_impl {
@@ -55,6 +58,17 @@ struct SubsetGlyph
return_trace (true);
}
+ bool compile_bytes_with_deltas (const hb_subset_plan_t *plan,
+ hb_font_t *font,
+ const glyf_accelerator_t &glyf)
+ { return source_glyph.compile_bytes_with_deltas (plan, font, glyf, dest_start, dest_end); }
+
+ void free_compiled_bytes ()
+ {
+ dest_start.fini ();
+ dest_end.fini ();
+ }
+
void drop_hints_bytes ()
{ source_glyph.drop_hints_bytes (dest_start, dest_end); }
diff --git a/thirdparty/harfbuzz/src/OT/glyf/glyf-helpers.hh b/thirdparty/harfbuzz/src/OT/glyf/glyf-helpers.hh
index f51f7a81fc..181c33d06d 100644
--- a/thirdparty/harfbuzz/src/OT/glyf/glyf-helpers.hh
+++ b/thirdparty/harfbuzz/src/OT/glyf/glyf-helpers.hh
@@ -16,7 +16,7 @@ template<typename IteratorIn, typename IteratorOut,
hb_requires (hb_is_source_of (IteratorIn, unsigned int)),
hb_requires (hb_is_sink_of (IteratorOut, unsigned))>
static void
-_write_loca (IteratorIn it, bool short_offsets, IteratorOut dest)
+_write_loca (IteratorIn&& it, bool short_offsets, IteratorOut&& dest)
{
unsigned right_shift = short_offsets ? 1 : 0;
unsigned int offset = 0;
diff --git a/thirdparty/harfbuzz/src/OT/glyf/glyf.hh b/thirdparty/harfbuzz/src/OT/glyf/glyf.hh
index bcaf44fc1e..be2cb1d0dc 100644
--- a/thirdparty/harfbuzz/src/OT/glyf/glyf.hh
+++ b/thirdparty/harfbuzz/src/OT/glyf/glyf.hh
@@ -24,7 +24,6 @@ namespace OT {
*/
#define HB_OT_TAG_glyf HB_TAG('g','l','y','f')
-
struct glyf
{
friend struct glyf_accelerator_t;
@@ -75,6 +74,9 @@ struct glyf
hb_vector_t<glyf_impl::SubsetGlyph> glyphs;
_populate_subset_glyphs (c->plan, &glyphs);
+ if (!c->plan->pinned_at_default)
+ _compile_subset_glyphs_with_deltas (c->plan, &glyphs);
+
auto padded_offsets =
+ hb_iter (glyphs)
| hb_map (&glyf_impl::SubsetGlyph::padded_size)
@@ -93,6 +95,8 @@ struct glyf
}
+ if (!c->plan->pinned_at_default)
+ _free_compiled_subset_glyphs (&glyphs);
if (unlikely (c->serializer->in_error ())) return_trace (false);
return_trace (c->serializer->check_success (glyf_impl::_add_loca_and_head (c->plan,
padded_offsets,
@@ -102,6 +106,16 @@ struct glyf
void
_populate_subset_glyphs (const hb_subset_plan_t *plan,
hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const;
+
+ void
+ _compile_subset_glyphs_with_deltas (const hb_subset_plan_t *plan,
+ hb_vector_t<glyf_impl::SubsetGlyph> *glyphs /* OUT */) const;
+
+ void _free_compiled_subset_glyphs (hb_vector_t<glyf_impl::SubsetGlyph> *glyphs) const
+ {
+ for (auto _ : *glyphs)
+ _.free_compiled_bytes ();
+ }
protected:
UnsizedArrayOf<HBUINT8>
@@ -166,7 +180,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, phantom_only)))
+ if (unlikely (!glyph_for_gid (gid).get_points (font, *this, all_points, nullptr, true, phantom_only)))
return false;
if (consumer.is_consuming_contour_points ())
@@ -389,6 +403,30 @@ glyf::_populate_subset_glyphs (const hb_subset_plan_t *plan,
;
}
+inline void
+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);
+
+ hb_vector_t<hb_variation_t> vars;
+ vars.alloc (plan->user_axes_location->get_population ());
+
+ for (auto _ : *plan->user_axes_location)
+ {
+ hb_variation_t var;
+ var.tag = _.first;
+ var.value = _.second;
+ vars.push (var);
+ }
+
+ 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);
+
+ hb_font_destroy (font);
+}
} /* namespace OT */