summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh')
-rw-r--r--src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh293
1 files changed, 212 insertions, 81 deletions
diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh
index e710aee42e..e20b372622 100644
--- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh
+++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh
@@ -21,42 +21,50 @@
* ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
- * Google Author(s): Behdad Esfahbod
+ * Google Author(s): Behdad Esfahbod, Roderick Sheeter
*/
#ifndef HB_OT_HMTX_TABLE_HH
#define HB_OT_HMTX_TABLE_HH
-#include "hb-open-type-private.hh"
+#include "hb-open-type.hh"
#include "hb-ot-hhea-table.hh"
-#include "hb-ot-os2-table.hh"
#include "hb-ot-var-hvar-table.hh"
-
-
-namespace OT {
-
+#include "hb-ot-metrics.hh"
/*
- * hmtx -- The Horizontal Metrics Table
- * vmtx -- The Vertical Metrics Table
+ * hmtx -- Horizontal Metrics
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/hmtx
+ * vmtx -- Vertical Metrics
+ * https://docs.microsoft.com/en-us/typography/opentype/spec/vmtx
*/
-
#define HB_OT_TAG_hmtx HB_TAG('h','m','t','x')
#define HB_OT_TAG_vmtx HB_TAG('v','m','t','x')
+HB_INTERNAL int
+_glyf_get_side_bearing_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
+
+HB_INTERNAL unsigned
+_glyf_get_advance_var (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical);
+
+
+namespace OT {
+
+
struct LongMetric
{
UFWORD advance; /* Advance width/height. */
- FWORD lsb; /* Leading (left/top) side bearing. */
+ FWORD sb; /* Leading (left/top) side bearing. */
public:
DEFINE_SIZE_STATIC (4);
};
-template <typename T>
+
+template <typename T, typename H>
struct hmtxvmtx
{
- inline bool sanitize (hb_sanitize_context_t *c) const
+ bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const
{
TRACE_SANITIZE (this);
/* We don't check for anything specific here. The users of the
@@ -64,47 +72,107 @@ struct hmtxvmtx
return_trace (true);
}
- struct accelerator_t
+
+ bool subset_update_header (hb_subset_plan_t *plan,
+ unsigned int num_hmetrics) const
{
- inline void init (hb_face_t *face,
- unsigned int default_advance_ = 0)
- {
- default_advance = default_advance_ ? default_advance_ : face->get_upem ();
+ hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table<H> (plan->source, H::tableTag);
+ hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob);
+ hb_blob_destroy (src_blob);
- bool got_font_extents = false;
- if (T::os2Tag)
- {
- hb_blob_t *os2_blob = Sanitizer<os2>::sanitize (face->reference_table (T::os2Tag));
- const os2 *os2_table = Sanitizer<os2>::lock_instance (os2_blob);
-#define USE_TYPO_METRICS (1u<<7)
- if (0 != (os2_table->fsSelection & USE_TYPO_METRICS))
- {
- ascender = os2_table->sTypoAscender;
- descender = os2_table->sTypoDescender;
- line_gap = os2_table->sTypoLineGap;
- got_font_extents = (ascender | descender) != 0;
- }
- hb_blob_destroy (os2_blob);
- }
+ if (unlikely (!dest_blob)) {
+ return false;
+ }
- hb_blob_t *_hea_blob = Sanitizer<_hea>::sanitize (face->reference_table (T::headerTag));
- const _hea *_hea_table = Sanitizer<_hea>::lock_instance (_hea_blob);
- num_advances = _hea_table->numberOfLongMetrics;
- if (!got_font_extents)
- {
- ascender = _hea_table->ascender;
- descender = _hea_table->descender;
- line_gap = _hea_table->lineGap;
- got_font_extents = (ascender | descender) != 0;
- }
- hb_blob_destroy (_hea_blob);
+ unsigned int length;
+ H *table = (H *) hb_blob_get_data (dest_blob, &length);
+ table->numberOfLongMetrics = num_hmetrics;
+
+ bool result = plan->add_table (H::tableTag, dest_blob);
+ hb_blob_destroy (dest_blob);
+
+ return result;
+ }
+
+ template<typename Iterator,
+ hb_requires (hb_is_iterator (Iterator))>
+ void serialize (hb_serialize_context_t *c,
+ Iterator it,
+ unsigned num_advances)
+ {
+ unsigned idx = 0;
+ + it
+ | hb_apply ([c, &idx, num_advances] (const hb_item_type<Iterator>& _)
+ {
+ if (idx < num_advances)
+ {
+ LongMetric lm;
+ lm.advance = _.first;
+ lm.sb = _.second;
+ if (unlikely (!c->embed<LongMetric> (&lm))) return;
+ }
+ else
+ {
+ FWORD *sb = c->allocate_size<FWORD> (FWORD::static_size);
+ if (unlikely (!sb)) return;
+ *sb = _.second;
+ }
+ idx++;
+ })
+ ;
+ }
+
+ bool subset (hb_subset_context_t *c) const
+ {
+ TRACE_SUBSET (this);
+
+ T *table_prime = c->serializer->start_embed <T> ();
+ if (unlikely (!table_prime)) return_trace (false);
+
+ accelerator_t _mtx;
+ _mtx.init (c->plan->source);
+ unsigned num_advances = _mtx.num_advances_for_subset (c->plan);
+
+ auto it =
+ + hb_range (c->plan->num_output_glyphs ())
+ | hb_map ([c, &_mtx] (unsigned _)
+ {
+ hb_codepoint_t old_gid;
+ if (!c->plan->old_gid_for_new_gid (_, &old_gid))
+ return hb_pair (0u, 0);
+ return hb_pair (_mtx.get_advance (old_gid), _mtx.get_side_bearing (old_gid));
+ })
+ ;
+
+ table_prime->serialize (c->serializer, it, num_advances);
+
+ _mtx.fini ();
+
+ if (unlikely (c->serializer->ran_out_of_room || c->serializer->in_error ()))
+ return_trace (false);
+
+ // Amend header num hmetrics
+ if (unlikely (!subset_update_header (c->plan, num_advances)))
+ return_trace (false);
+
+ return_trace (true);
+ }
- has_font_extents = got_font_extents;
+ struct accelerator_t
+ {
+ friend struct hmtxvmtx;
- blob = Sanitizer<hmtxvmtx>::sanitize (face->reference_table (T::tableTag));
+ void init (hb_face_t *face,
+ unsigned int default_advance_ = 0)
+ {
+ default_advance = default_advance_ ? default_advance_ : hb_face_get_upem (face);
+
+ num_advances = T::is_horizontal ? face->table.hhea->numberOfLongMetrics : face->table.vhea->numberOfLongMetrics;
+
+ table = hb_sanitize_context_t().reference_table<hmtxvmtx> (face, T::tableTag);
/* Cap num_metrics() and num_advances() based on table length. */
- unsigned int len = hb_blob_get_length (blob);
+ unsigned int len = table.get_length ();
if (unlikely (num_advances * 4 > len))
num_advances = len / 4;
num_metrics = num_advances + (len - 4 * num_advances) / 2;
@@ -114,23 +182,49 @@ struct hmtxvmtx
if (unlikely (!num_advances))
{
num_metrics = num_advances = 0;
- hb_blob_destroy (blob);
- blob = hb_blob_get_empty ();
+ table.destroy ();
+ table = hb_blob_get_empty ();
}
- table = Sanitizer<hmtxvmtx>::lock_instance (blob);
- var_blob = Sanitizer<HVARVVAR>::sanitize (face->reference_table (T::variationsTag));
- var_table = Sanitizer<HVARVVAR>::lock_instance (var_blob);
+ var_table = hb_sanitize_context_t().reference_table<HVARVVAR> (face, T::variationsTag);
+ }
+
+ void fini ()
+ {
+ table.destroy ();
+ var_table.destroy ();
}
- inline void fini (void)
+ int get_side_bearing (hb_codepoint_t glyph) const
{
- hb_blob_destroy (blob);
- hb_blob_destroy (var_blob);
+ if (glyph < num_advances)
+ return table->longMetricZ[glyph].sb;
+
+ if (unlikely (glyph >= num_metrics))
+ return 0;
+
+ const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_advances];
+ return bearings[glyph - num_advances];
+ }
+
+ int get_side_bearing (hb_font_t *font, hb_codepoint_t glyph) const
+ {
+ int side_bearing = get_side_bearing (glyph);
+
+#ifndef HB_NO_VAR
+ if (unlikely (glyph >= num_metrics) || !font->num_coords)
+ return side_bearing;
+
+ if (var_table.get_length ())
+ return side_bearing + var_table->get_side_bearing_var (glyph, font->coords, font->num_coords); // TODO Optimize?!
+
+ return _glyf_get_side_bearing_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
+#else
+ return side_bearing;
+#endif
}
- inline unsigned int get_advance (hb_codepoint_t glyph,
- hb_font_t *font) const
+ unsigned int get_advance (hb_codepoint_t glyph) const
{
if (unlikely (glyph >= num_metrics))
{
@@ -143,29 +237,65 @@ struct hmtxvmtx
return default_advance;
}
- return table->longMetric[MIN (glyph, (uint32_t) num_advances - 1)].advance
- + var_table->get_advance_var (glyph, font->coords, font->num_coords); // TODO Optimize?!
+ return table->longMetricZ[hb_min (glyph, (uint32_t) num_advances - 1)].advance;
}
- public:
- bool has_font_extents;
- unsigned short ascender;
- unsigned short descender;
- unsigned short line_gap;
+ unsigned int get_advance (hb_codepoint_t glyph,
+ hb_font_t *font) const
+ {
+ unsigned int advance = get_advance (glyph);
+
+#ifndef HB_NO_VAR
+ if (unlikely (glyph >= num_metrics) || !font->num_coords)
+ return advance;
+
+ if (var_table.get_length ())
+ return advance + roundf (var_table->get_advance_var (font, glyph)); // TODO Optimize?!
+
+ return _glyf_get_advance_var (font, glyph, T::tableTag == HB_OT_TAG_vmtx);
+#else
+ return advance;
+#endif
+ }
+
+ unsigned int num_advances_for_subset (const hb_subset_plan_t *plan) const
+ {
+ unsigned int num_advances = plan->num_output_glyphs ();
+ unsigned int last_advance = _advance_for_new_gid (plan,
+ num_advances - 1);
+ while (num_advances > 1 &&
+ last_advance == _advance_for_new_gid (plan,
+ num_advances - 2))
+ {
+ num_advances--;
+ }
+
+ return num_advances;
+ }
private:
+ unsigned int _advance_for_new_gid (const hb_subset_plan_t *plan,
+ hb_codepoint_t new_gid) const
+ {
+ hb_codepoint_t old_gid;
+ if (!plan->old_gid_for_new_gid (new_gid, &old_gid))
+ return 0;
+
+ return get_advance (old_gid);
+ }
+
+ protected:
unsigned int num_metrics;
unsigned int num_advances;
unsigned int default_advance;
- const hmtxvmtx *table;
- hb_blob_t *blob;
- const HVARVVAR *var_table;
- hb_blob_t *var_blob;
+ private:
+ hb_blob_ptr_t<hmtxvmtx> table;
+ hb_blob_ptr_t<HVARVVAR> var_table;
};
protected:
- LongMetric longMetric[VAR]; /* Paired advance width and leading
+ UnsizedArrayOf<LongMetric>longMetricZ;/* Paired advance width and leading
* bearing values for each glyph. The
* value numOfHMetrics comes from
* the 'hhea' table. If the font is
@@ -173,7 +303,7 @@ struct hmtxvmtx
* be in the array, but that entry is
* required. The last entry applies to
* all subsequent glyphs. */
- FWORD leadingBearingX[VAR]; /* Here the advance is assumed
+/*UnsizedArrayOf<FWORD> leadingBearingX;*//* Here the advance is assumed
* to be the same as the advance
* for the last entry above. The
* number of entries in this array is
@@ -187,22 +317,23 @@ struct hmtxvmtx
* font to vary the side bearing
* values for each glyph. */
public:
- DEFINE_SIZE_ARRAY2 (0, longMetric, leadingBearingX);
+ DEFINE_SIZE_ARRAY (0, longMetricZ);
};
-struct hmtx : hmtxvmtx<hmtx> {
- static const hb_tag_t tableTag = HB_OT_TAG_hmtx;
- static const hb_tag_t headerTag = HB_OT_TAG_hhea;
- static const hb_tag_t variationsTag = HB_OT_TAG_HVAR;
- static const hb_tag_t os2Tag = HB_OT_TAG_os2;
+struct hmtx : hmtxvmtx<hmtx, hhea> {
+ static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx;
+ static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR;
+ static constexpr bool is_horizontal = true;
};
-struct vmtx : hmtxvmtx<vmtx> {
- static const hb_tag_t tableTag = HB_OT_TAG_vmtx;
- static const hb_tag_t headerTag = HB_OT_TAG_vhea;
- static const hb_tag_t variationsTag = HB_OT_TAG_VVAR;
- static const hb_tag_t os2Tag = HB_TAG_NONE;
+struct vmtx : hmtxvmtx<vmtx, vhea> {
+ static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx;
+ static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR;
+ static constexpr bool is_horizontal = false;
};
+struct hmtx_accelerator_t : hmtx::accelerator_t {};
+struct vmtx_accelerator_t : vmtx::accelerator_t {};
+
} /* namespace OT */