diff options
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.hh | 293 |
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 */ |