1*2d1272b8SAndroid Build Coastguard Worker /* 2*2d1272b8SAndroid Build Coastguard Worker * Copyright © 2011,2012 Google, Inc. 3*2d1272b8SAndroid Build Coastguard Worker * 4*2d1272b8SAndroid Build Coastguard Worker * This is part of HarfBuzz, a text shaping library. 5*2d1272b8SAndroid Build Coastguard Worker * 6*2d1272b8SAndroid Build Coastguard Worker * Permission is hereby granted, without written agreement and without 7*2d1272b8SAndroid Build Coastguard Worker * license or royalty fees, to use, copy, modify, and distribute this 8*2d1272b8SAndroid Build Coastguard Worker * software and its documentation for any purpose, provided that the 9*2d1272b8SAndroid Build Coastguard Worker * above copyright notice and the following two paragraphs appear in 10*2d1272b8SAndroid Build Coastguard Worker * all copies of this software. 11*2d1272b8SAndroid Build Coastguard Worker * 12*2d1272b8SAndroid Build Coastguard Worker * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13*2d1272b8SAndroid Build Coastguard Worker * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14*2d1272b8SAndroid Build Coastguard Worker * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15*2d1272b8SAndroid Build Coastguard Worker * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16*2d1272b8SAndroid Build Coastguard Worker * DAMAGE. 17*2d1272b8SAndroid Build Coastguard Worker * 18*2d1272b8SAndroid Build Coastguard Worker * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19*2d1272b8SAndroid Build Coastguard Worker * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20*2d1272b8SAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21*2d1272b8SAndroid Build Coastguard Worker * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22*2d1272b8SAndroid Build Coastguard Worker * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23*2d1272b8SAndroid Build Coastguard Worker * 24*2d1272b8SAndroid Build Coastguard Worker * Google Author(s): Behdad Esfahbod, Roderick Sheeter 25*2d1272b8SAndroid Build Coastguard Worker */ 26*2d1272b8SAndroid Build Coastguard Worker 27*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_OT_HMTX_TABLE_HH 28*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_HMTX_TABLE_HH 29*2d1272b8SAndroid Build Coastguard Worker 30*2d1272b8SAndroid Build Coastguard Worker #include "hb-open-type.hh" 31*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-maxp-table.hh" 32*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-hhea-table.hh" 33*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-os2-table.hh" 34*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-var-hvar-table.hh" 35*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-var-mvar-table.hh" 36*2d1272b8SAndroid Build Coastguard Worker #include "hb-ot-metrics.hh" 37*2d1272b8SAndroid Build Coastguard Worker 38*2d1272b8SAndroid Build Coastguard Worker /* 39*2d1272b8SAndroid Build Coastguard Worker * hmtx -- Horizontal Metrics 40*2d1272b8SAndroid Build Coastguard Worker * https://docs.microsoft.com/en-us/typography/opentype/spec/hmtx 41*2d1272b8SAndroid Build Coastguard Worker * vmtx -- Vertical Metrics 42*2d1272b8SAndroid Build Coastguard Worker * https://docs.microsoft.com/en-us/typography/opentype/spec/vmtx 43*2d1272b8SAndroid Build Coastguard Worker */ 44*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_TAG_hmtx HB_TAG('h','m','t','x') 45*2d1272b8SAndroid Build Coastguard Worker #define HB_OT_TAG_vmtx HB_TAG('v','m','t','x') 46*2d1272b8SAndroid Build Coastguard Worker 47*2d1272b8SAndroid Build Coastguard Worker 48*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL bool 49*2d1272b8SAndroid Build Coastguard Worker _glyf_get_leading_bearing_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical, int *lsb); 50*2d1272b8SAndroid Build Coastguard Worker 51*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL unsigned 52*2d1272b8SAndroid Build Coastguard Worker _glyf_get_advance_with_var_unscaled (hb_font_t *font, hb_codepoint_t glyph, bool is_vertical); 53*2d1272b8SAndroid Build Coastguard Worker 54*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL bool 55*2d1272b8SAndroid Build Coastguard Worker _glyf_get_leading_bearing_without_var_unscaled (hb_face_t *face, hb_codepoint_t gid, bool is_vertical, int *lsb); 56*2d1272b8SAndroid Build Coastguard Worker 57*2d1272b8SAndroid Build Coastguard Worker 58*2d1272b8SAndroid Build Coastguard Worker namespace OT { 59*2d1272b8SAndroid Build Coastguard Worker 60*2d1272b8SAndroid Build Coastguard Worker 61*2d1272b8SAndroid Build Coastguard Worker struct LongMetric 62*2d1272b8SAndroid Build Coastguard Worker { 63*2d1272b8SAndroid Build Coastguard Worker UFWORD advance; /* Advance width/height. */ 64*2d1272b8SAndroid Build Coastguard Worker FWORD sb; /* Leading (left/top) side bearing. */ 65*2d1272b8SAndroid Build Coastguard Worker public: 66*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_STATIC (4); 67*2d1272b8SAndroid Build Coastguard Worker }; 68*2d1272b8SAndroid Build Coastguard Worker 69*2d1272b8SAndroid Build Coastguard Worker 70*2d1272b8SAndroid Build Coastguard Worker template <typename T/*Data table type*/, typename H/*Header table type*/, typename V/*Var table type*/> 71*2d1272b8SAndroid Build Coastguard Worker struct hmtxvmtx 72*2d1272b8SAndroid Build Coastguard Worker { sanitizeOT::hmtxvmtx73*2d1272b8SAndroid Build Coastguard Worker bool sanitize (hb_sanitize_context_t *c HB_UNUSED) const 74*2d1272b8SAndroid Build Coastguard Worker { 75*2d1272b8SAndroid Build Coastguard Worker TRACE_SANITIZE (this); 76*2d1272b8SAndroid Build Coastguard Worker /* We don't check for anything specific here. The users of the 77*2d1272b8SAndroid Build Coastguard Worker * struct do all the hard work... */ 78*2d1272b8SAndroid Build Coastguard Worker return_trace (true); 79*2d1272b8SAndroid Build Coastguard Worker } 80*2d1272b8SAndroid Build Coastguard Worker get_mtx_mapOT::hmtxvmtx81*2d1272b8SAndroid Build Coastguard Worker const hb_hashmap_t<hb_codepoint_t, hb_pair_t<unsigned, int>>* get_mtx_map (const hb_subset_plan_t *plan) const 82*2d1272b8SAndroid Build Coastguard Worker { return T::is_horizontal ? &plan->hmtx_map : &plan->vmtx_map; } 83*2d1272b8SAndroid Build Coastguard Worker subset_update_headerOT::hmtxvmtx84*2d1272b8SAndroid Build Coastguard Worker bool subset_update_header (hb_subset_context_t *c, 85*2d1272b8SAndroid Build Coastguard Worker unsigned int num_hmetrics, 86*2d1272b8SAndroid Build Coastguard Worker const hb_hashmap_t<hb_codepoint_t, hb_pair_t<unsigned, int>> *mtx_map, 87*2d1272b8SAndroid Build Coastguard Worker const hb_vector_t<unsigned> &bounds_vec) const 88*2d1272b8SAndroid Build Coastguard Worker { 89*2d1272b8SAndroid Build Coastguard Worker hb_blob_t *src_blob = hb_sanitize_context_t ().reference_table<H> (c->plan->source, H::tableTag); 90*2d1272b8SAndroid Build Coastguard Worker hb_blob_t *dest_blob = hb_blob_copy_writable_or_fail (src_blob); 91*2d1272b8SAndroid Build Coastguard Worker hb_blob_destroy (src_blob); 92*2d1272b8SAndroid Build Coastguard Worker 93*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!dest_blob)) { 94*2d1272b8SAndroid Build Coastguard Worker return false; 95*2d1272b8SAndroid Build Coastguard Worker } 96*2d1272b8SAndroid Build Coastguard Worker 97*2d1272b8SAndroid Build Coastguard Worker unsigned int length; 98*2d1272b8SAndroid Build Coastguard Worker H *table = (H *) hb_blob_get_data (dest_blob, &length); 99*2d1272b8SAndroid Build Coastguard Worker c->serializer->check_assign (table->numberOfLongMetrics, num_hmetrics, HB_SERIALIZE_ERROR_INT_OVERFLOW); 100*2d1272b8SAndroid Build Coastguard Worker 101*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR 102*2d1272b8SAndroid Build Coastguard Worker if (c->plan->normalized_coords) 103*2d1272b8SAndroid Build Coastguard Worker { 104*2d1272b8SAndroid Build Coastguard Worker auto &MVAR = *c->plan->source->table.MVAR; 105*2d1272b8SAndroid Build Coastguard Worker if (T::is_horizontal) 106*2d1272b8SAndroid Build Coastguard Worker { 107*2d1272b8SAndroid Build Coastguard Worker HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_HORIZONTAL_CARET_RISE, caretSlopeRise); 108*2d1272b8SAndroid Build Coastguard Worker HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_HORIZONTAL_CARET_RUN, caretSlopeRun); 109*2d1272b8SAndroid Build Coastguard Worker HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_HORIZONTAL_CARET_OFFSET, caretOffset); 110*2d1272b8SAndroid Build Coastguard Worker } 111*2d1272b8SAndroid Build Coastguard Worker else 112*2d1272b8SAndroid Build Coastguard Worker { 113*2d1272b8SAndroid Build Coastguard Worker HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_VERTICAL_CARET_RISE, caretSlopeRise); 114*2d1272b8SAndroid Build Coastguard Worker HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_VERTICAL_CARET_RUN, caretSlopeRun); 115*2d1272b8SAndroid Build Coastguard Worker HB_ADD_MVAR_VAR (HB_OT_METRICS_TAG_VERTICAL_CARET_OFFSET, caretOffset); 116*2d1272b8SAndroid Build Coastguard Worker } 117*2d1272b8SAndroid Build Coastguard Worker 118*2d1272b8SAndroid Build Coastguard Worker bool empty = true; 119*2d1272b8SAndroid Build Coastguard Worker int min_lsb = 0x7FFF; 120*2d1272b8SAndroid Build Coastguard Worker int min_rsb = 0x7FFF; 121*2d1272b8SAndroid Build Coastguard Worker int max_extent = -0x7FFF; 122*2d1272b8SAndroid Build Coastguard Worker unsigned max_adv = 0; 123*2d1272b8SAndroid Build Coastguard Worker for (const auto _ : *mtx_map) 124*2d1272b8SAndroid Build Coastguard Worker { 125*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t gid = _.first; 126*2d1272b8SAndroid Build Coastguard Worker unsigned adv = _.second.first; 127*2d1272b8SAndroid Build Coastguard Worker int lsb = _.second.second; 128*2d1272b8SAndroid Build Coastguard Worker max_adv = hb_max (max_adv, adv); 129*2d1272b8SAndroid Build Coastguard Worker 130*2d1272b8SAndroid Build Coastguard Worker if (bounds_vec[gid] != 0xFFFFFFFF) 131*2d1272b8SAndroid Build Coastguard Worker { 132*2d1272b8SAndroid Build Coastguard Worker empty = false; 133*2d1272b8SAndroid Build Coastguard Worker unsigned bound_width = bounds_vec[gid]; 134*2d1272b8SAndroid Build Coastguard Worker int rsb = adv - lsb - bound_width; 135*2d1272b8SAndroid Build Coastguard Worker int extent = lsb + bound_width; 136*2d1272b8SAndroid Build Coastguard Worker min_lsb = hb_min (min_lsb, lsb); 137*2d1272b8SAndroid Build Coastguard Worker min_rsb = hb_min (min_rsb, rsb); 138*2d1272b8SAndroid Build Coastguard Worker max_extent = hb_max (max_extent, extent); 139*2d1272b8SAndroid Build Coastguard Worker } 140*2d1272b8SAndroid Build Coastguard Worker } 141*2d1272b8SAndroid Build Coastguard Worker 142*2d1272b8SAndroid Build Coastguard Worker table->advanceMax = max_adv; 143*2d1272b8SAndroid Build Coastguard Worker if (!empty) 144*2d1272b8SAndroid Build Coastguard Worker { 145*2d1272b8SAndroid Build Coastguard Worker table->minLeadingBearing = min_lsb; 146*2d1272b8SAndroid Build Coastguard Worker table->minTrailingBearing = min_rsb; 147*2d1272b8SAndroid Build Coastguard Worker table->maxExtent = max_extent; 148*2d1272b8SAndroid Build Coastguard Worker } 149*2d1272b8SAndroid Build Coastguard Worker 150*2d1272b8SAndroid Build Coastguard Worker if (T::is_horizontal) 151*2d1272b8SAndroid Build Coastguard Worker { 152*2d1272b8SAndroid Build Coastguard Worker const auto &OS2 = *c->plan->source->table.OS2; 153*2d1272b8SAndroid Build Coastguard Worker if (OS2.has_data () && 154*2d1272b8SAndroid Build Coastguard Worker table->ascender == OS2.sTypoAscender && 155*2d1272b8SAndroid Build Coastguard Worker table->descender == OS2.sTypoDescender && 156*2d1272b8SAndroid Build Coastguard Worker table->lineGap == OS2.sTypoLineGap) 157*2d1272b8SAndroid Build Coastguard Worker { 158*2d1272b8SAndroid Build Coastguard Worker table->ascender = static_cast<int> (roundf (OS2.sTypoAscender + 159*2d1272b8SAndroid Build Coastguard Worker MVAR.get_var (HB_OT_METRICS_TAG_HORIZONTAL_ASCENDER, 160*2d1272b8SAndroid Build Coastguard Worker c->plan->normalized_coords.arrayZ, 161*2d1272b8SAndroid Build Coastguard Worker c->plan->normalized_coords.length))); 162*2d1272b8SAndroid Build Coastguard Worker table->descender = static_cast<int> (roundf (OS2.sTypoDescender + 163*2d1272b8SAndroid Build Coastguard Worker MVAR.get_var (HB_OT_METRICS_TAG_HORIZONTAL_DESCENDER, 164*2d1272b8SAndroid Build Coastguard Worker c->plan->normalized_coords.arrayZ, 165*2d1272b8SAndroid Build Coastguard Worker c->plan->normalized_coords.length))); 166*2d1272b8SAndroid Build Coastguard Worker table->lineGap = static_cast<int> (roundf (OS2.sTypoLineGap + 167*2d1272b8SAndroid Build Coastguard Worker MVAR.get_var (HB_OT_METRICS_TAG_HORIZONTAL_LINE_GAP, 168*2d1272b8SAndroid Build Coastguard Worker c->plan->normalized_coords.arrayZ, 169*2d1272b8SAndroid Build Coastguard Worker c->plan->normalized_coords.length))); 170*2d1272b8SAndroid Build Coastguard Worker } 171*2d1272b8SAndroid Build Coastguard Worker } 172*2d1272b8SAndroid Build Coastguard Worker } 173*2d1272b8SAndroid Build Coastguard Worker #endif 174*2d1272b8SAndroid Build Coastguard Worker 175*2d1272b8SAndroid Build Coastguard Worker bool result = c->plan->add_table (H::tableTag, dest_blob); 176*2d1272b8SAndroid Build Coastguard Worker hb_blob_destroy (dest_blob); 177*2d1272b8SAndroid Build Coastguard Worker 178*2d1272b8SAndroid Build Coastguard Worker return result; 179*2d1272b8SAndroid Build Coastguard Worker } 180*2d1272b8SAndroid Build Coastguard Worker 181*2d1272b8SAndroid Build Coastguard Worker template<typename Iterator, 182*2d1272b8SAndroid Build Coastguard Worker hb_requires (hb_is_iterator (Iterator))> serializeOT::hmtxvmtx183*2d1272b8SAndroid Build Coastguard Worker void serialize (hb_serialize_context_t *c, 184*2d1272b8SAndroid Build Coastguard Worker Iterator it, 185*2d1272b8SAndroid Build Coastguard Worker const hb_vector_t<hb_codepoint_pair_t> new_to_old_gid_list, 186*2d1272b8SAndroid Build Coastguard Worker unsigned num_long_metrics, 187*2d1272b8SAndroid Build Coastguard Worker unsigned total_num_metrics) 188*2d1272b8SAndroid Build Coastguard Worker { 189*2d1272b8SAndroid Build Coastguard Worker LongMetric* long_metrics = c->allocate_size<LongMetric> (num_long_metrics * LongMetric::static_size); 190*2d1272b8SAndroid Build Coastguard Worker FWORD* short_metrics = c->allocate_size<FWORD> ((total_num_metrics - num_long_metrics) * FWORD::static_size); 191*2d1272b8SAndroid Build Coastguard Worker if (!long_metrics || !short_metrics) return; 192*2d1272b8SAndroid Build Coastguard Worker 193*2d1272b8SAndroid Build Coastguard Worker short_metrics -= num_long_metrics; 194*2d1272b8SAndroid Build Coastguard Worker 195*2d1272b8SAndroid Build Coastguard Worker for (auto _ : new_to_old_gid_list) 196*2d1272b8SAndroid Build Coastguard Worker { 197*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t gid = _.first; 198*2d1272b8SAndroid Build Coastguard Worker auto mtx = *it++; 199*2d1272b8SAndroid Build Coastguard Worker 200*2d1272b8SAndroid Build Coastguard Worker if (gid < num_long_metrics) 201*2d1272b8SAndroid Build Coastguard Worker { 202*2d1272b8SAndroid Build Coastguard Worker LongMetric& lm = long_metrics[gid]; 203*2d1272b8SAndroid Build Coastguard Worker lm.advance = mtx.first; 204*2d1272b8SAndroid Build Coastguard Worker lm.sb = mtx.second; 205*2d1272b8SAndroid Build Coastguard Worker } 206*2d1272b8SAndroid Build Coastguard Worker // TODO(beyond-64k): This assumes that maxp.numGlyphs is 0xFFFF. 207*2d1272b8SAndroid Build Coastguard Worker else if (gid < 0x10000u) 208*2d1272b8SAndroid Build Coastguard Worker short_metrics[gid] = mtx.second; 209*2d1272b8SAndroid Build Coastguard Worker else 210*2d1272b8SAndroid Build Coastguard Worker ((UFWORD*) short_metrics)[gid] = mtx.first; 211*2d1272b8SAndroid Build Coastguard Worker } 212*2d1272b8SAndroid Build Coastguard Worker } 213*2d1272b8SAndroid Build Coastguard Worker subsetOT::hmtxvmtx214*2d1272b8SAndroid Build Coastguard Worker bool subset (hb_subset_context_t *c) const 215*2d1272b8SAndroid Build Coastguard Worker { 216*2d1272b8SAndroid Build Coastguard Worker TRACE_SUBSET (this); 217*2d1272b8SAndroid Build Coastguard Worker 218*2d1272b8SAndroid Build Coastguard Worker auto *table_prime = c->serializer->start_embed <T> (); 219*2d1272b8SAndroid Build Coastguard Worker 220*2d1272b8SAndroid Build Coastguard Worker accelerator_t _mtx (c->plan->source); 221*2d1272b8SAndroid Build Coastguard Worker unsigned num_long_metrics; 222*2d1272b8SAndroid Build Coastguard Worker const hb_hashmap_t<hb_codepoint_t, hb_pair_t<unsigned, int>> *mtx_map = get_mtx_map (c->plan); 223*2d1272b8SAndroid Build Coastguard Worker { 224*2d1272b8SAndroid Build Coastguard Worker /* Determine num_long_metrics to encode. */ 225*2d1272b8SAndroid Build Coastguard Worker auto& plan = c->plan; 226*2d1272b8SAndroid Build Coastguard Worker 227*2d1272b8SAndroid Build Coastguard Worker // TODO Don't consider retaingid holes here. 228*2d1272b8SAndroid Build Coastguard Worker 229*2d1272b8SAndroid Build Coastguard Worker num_long_metrics = hb_min (plan->num_output_glyphs (), 0xFFFFu); 230*2d1272b8SAndroid Build Coastguard Worker unsigned int last_advance = get_new_gid_advance_unscaled (plan, mtx_map, num_long_metrics - 1, _mtx); 231*2d1272b8SAndroid Build Coastguard Worker while (num_long_metrics > 1 && 232*2d1272b8SAndroid Build Coastguard Worker last_advance == get_new_gid_advance_unscaled (plan, mtx_map, num_long_metrics - 2, _mtx)) 233*2d1272b8SAndroid Build Coastguard Worker { 234*2d1272b8SAndroid Build Coastguard Worker num_long_metrics--; 235*2d1272b8SAndroid Build Coastguard Worker } 236*2d1272b8SAndroid Build Coastguard Worker } 237*2d1272b8SAndroid Build Coastguard Worker 238*2d1272b8SAndroid Build Coastguard Worker auto it = 239*2d1272b8SAndroid Build Coastguard Worker + hb_iter (c->plan->new_to_old_gid_list) 240*2d1272b8SAndroid Build Coastguard Worker | hb_map ([c, &_mtx, mtx_map] (hb_codepoint_pair_t _) 241*2d1272b8SAndroid Build Coastguard Worker { 242*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t new_gid = _.first; 243*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t old_gid = _.second; 244*2d1272b8SAndroid Build Coastguard Worker 245*2d1272b8SAndroid Build Coastguard Worker hb_pair_t<unsigned, int> *v = nullptr; 246*2d1272b8SAndroid Build Coastguard Worker if (!mtx_map->has (new_gid, &v)) 247*2d1272b8SAndroid Build Coastguard Worker { 248*2d1272b8SAndroid Build Coastguard Worker int lsb = 0; 249*2d1272b8SAndroid Build Coastguard Worker if (!_mtx.get_leading_bearing_without_var_unscaled (old_gid, &lsb)) 250*2d1272b8SAndroid Build Coastguard Worker (void) _glyf_get_leading_bearing_without_var_unscaled (c->plan->source, old_gid, !T::is_horizontal, &lsb); 251*2d1272b8SAndroid Build Coastguard Worker return hb_pair (_mtx.get_advance_without_var_unscaled (old_gid), +lsb); 252*2d1272b8SAndroid Build Coastguard Worker } 253*2d1272b8SAndroid Build Coastguard Worker return *v; 254*2d1272b8SAndroid Build Coastguard Worker }) 255*2d1272b8SAndroid Build Coastguard Worker ; 256*2d1272b8SAndroid Build Coastguard Worker 257*2d1272b8SAndroid Build Coastguard Worker table_prime->serialize (c->serializer, 258*2d1272b8SAndroid Build Coastguard Worker it, 259*2d1272b8SAndroid Build Coastguard Worker c->plan->new_to_old_gid_list, 260*2d1272b8SAndroid Build Coastguard Worker num_long_metrics, 261*2d1272b8SAndroid Build Coastguard Worker c->plan->num_output_glyphs ()); 262*2d1272b8SAndroid Build Coastguard Worker 263*2d1272b8SAndroid Build Coastguard Worker if (unlikely (c->serializer->in_error ())) 264*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 265*2d1272b8SAndroid Build Coastguard Worker 266*2d1272b8SAndroid Build Coastguard Worker // Amend header num hmetrics 267*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!subset_update_header (c, num_long_metrics, mtx_map, 268*2d1272b8SAndroid Build Coastguard Worker T::is_horizontal ? c->plan->bounds_width_vec : c->plan->bounds_height_vec))) 269*2d1272b8SAndroid Build Coastguard Worker return_trace (false); 270*2d1272b8SAndroid Build Coastguard Worker 271*2d1272b8SAndroid Build Coastguard Worker return_trace (true); 272*2d1272b8SAndroid Build Coastguard Worker } 273*2d1272b8SAndroid Build Coastguard Worker 274*2d1272b8SAndroid Build Coastguard Worker struct accelerator_t 275*2d1272b8SAndroid Build Coastguard Worker { 276*2d1272b8SAndroid Build Coastguard Worker friend struct hmtxvmtx; 277*2d1272b8SAndroid Build Coastguard Worker accelerator_tOT::hmtxvmtx::accelerator_t278*2d1272b8SAndroid Build Coastguard Worker accelerator_t (hb_face_t *face) 279*2d1272b8SAndroid Build Coastguard Worker { 280*2d1272b8SAndroid Build Coastguard Worker table = hb_sanitize_context_t ().reference_table<hmtxvmtx> (face, T::tableTag); 281*2d1272b8SAndroid Build Coastguard Worker var_table = hb_sanitize_context_t ().reference_table<V> (face, T::variationsTag); 282*2d1272b8SAndroid Build Coastguard Worker 283*2d1272b8SAndroid Build Coastguard Worker default_advance = T::is_horizontal ? hb_face_get_upem (face) / 2 : hb_face_get_upem (face); 284*2d1272b8SAndroid Build Coastguard Worker 285*2d1272b8SAndroid Build Coastguard Worker /* Populate count variables and sort them out as we go */ 286*2d1272b8SAndroid Build Coastguard Worker 287*2d1272b8SAndroid Build Coastguard Worker unsigned int len = table.get_length (); 288*2d1272b8SAndroid Build Coastguard Worker if (len & 1) 289*2d1272b8SAndroid Build Coastguard Worker len--; 290*2d1272b8SAndroid Build Coastguard Worker 291*2d1272b8SAndroid Build Coastguard Worker num_long_metrics = T::is_horizontal ? 292*2d1272b8SAndroid Build Coastguard Worker face->table.hhea->numberOfLongMetrics : 293*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VERTICAL 294*2d1272b8SAndroid Build Coastguard Worker face->table.vhea->numberOfLongMetrics 295*2d1272b8SAndroid Build Coastguard Worker #else 296*2d1272b8SAndroid Build Coastguard Worker 0 297*2d1272b8SAndroid Build Coastguard Worker #endif 298*2d1272b8SAndroid Build Coastguard Worker ; 299*2d1272b8SAndroid Build Coastguard Worker if (unlikely (num_long_metrics * 4 > len)) 300*2d1272b8SAndroid Build Coastguard Worker num_long_metrics = len / 4; 301*2d1272b8SAndroid Build Coastguard Worker len -= num_long_metrics * 4; 302*2d1272b8SAndroid Build Coastguard Worker 303*2d1272b8SAndroid Build Coastguard Worker num_bearings = face->table.maxp->get_num_glyphs (); 304*2d1272b8SAndroid Build Coastguard Worker 305*2d1272b8SAndroid Build Coastguard Worker if (unlikely (num_bearings < num_long_metrics)) 306*2d1272b8SAndroid Build Coastguard Worker num_bearings = num_long_metrics; 307*2d1272b8SAndroid Build Coastguard Worker if (unlikely ((num_bearings - num_long_metrics) * 2 > len)) 308*2d1272b8SAndroid Build Coastguard Worker num_bearings = num_long_metrics + len / 2; 309*2d1272b8SAndroid Build Coastguard Worker len -= (num_bearings - num_long_metrics) * 2; 310*2d1272b8SAndroid Build Coastguard Worker 311*2d1272b8SAndroid Build Coastguard Worker /* We MUST set num_bearings to zero if num_long_metrics is zero. 312*2d1272b8SAndroid Build Coastguard Worker * Our get_advance() depends on that. */ 313*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!num_long_metrics)) 314*2d1272b8SAndroid Build Coastguard Worker num_bearings = num_long_metrics = 0; 315*2d1272b8SAndroid Build Coastguard Worker 316*2d1272b8SAndroid Build Coastguard Worker num_advances = num_bearings + len / 2; 317*2d1272b8SAndroid Build Coastguard Worker num_glyphs = face->get_num_glyphs (); 318*2d1272b8SAndroid Build Coastguard Worker if (num_glyphs < num_advances) 319*2d1272b8SAndroid Build Coastguard Worker num_glyphs = num_advances; 320*2d1272b8SAndroid Build Coastguard Worker } ~accelerator_tOT::hmtxvmtx::accelerator_t321*2d1272b8SAndroid Build Coastguard Worker ~accelerator_t () 322*2d1272b8SAndroid Build Coastguard Worker { 323*2d1272b8SAndroid Build Coastguard Worker table.destroy (); 324*2d1272b8SAndroid Build Coastguard Worker var_table.destroy (); 325*2d1272b8SAndroid Build Coastguard Worker } 326*2d1272b8SAndroid Build Coastguard Worker has_dataOT::hmtxvmtx::accelerator_t327*2d1272b8SAndroid Build Coastguard Worker bool has_data () const { return (bool) num_bearings; } 328*2d1272b8SAndroid Build Coastguard Worker get_leading_bearing_without_var_unscaledOT::hmtxvmtx::accelerator_t329*2d1272b8SAndroid Build Coastguard Worker bool get_leading_bearing_without_var_unscaled (hb_codepoint_t glyph, 330*2d1272b8SAndroid Build Coastguard Worker int *lsb) const 331*2d1272b8SAndroid Build Coastguard Worker { 332*2d1272b8SAndroid Build Coastguard Worker if (glyph < num_long_metrics) 333*2d1272b8SAndroid Build Coastguard Worker { 334*2d1272b8SAndroid Build Coastguard Worker *lsb = table->longMetricZ[glyph].sb; 335*2d1272b8SAndroid Build Coastguard Worker return true; 336*2d1272b8SAndroid Build Coastguard Worker } 337*2d1272b8SAndroid Build Coastguard Worker 338*2d1272b8SAndroid Build Coastguard Worker if (unlikely (glyph >= num_bearings)) 339*2d1272b8SAndroid Build Coastguard Worker return false; 340*2d1272b8SAndroid Build Coastguard Worker 341*2d1272b8SAndroid Build Coastguard Worker const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics]; 342*2d1272b8SAndroid Build Coastguard Worker *lsb = bearings[glyph - num_long_metrics]; 343*2d1272b8SAndroid Build Coastguard Worker return true; 344*2d1272b8SAndroid Build Coastguard Worker } 345*2d1272b8SAndroid Build Coastguard Worker get_leading_bearing_with_var_unscaledOT::hmtxvmtx::accelerator_t346*2d1272b8SAndroid Build Coastguard Worker bool get_leading_bearing_with_var_unscaled (hb_font_t *font, 347*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t glyph, 348*2d1272b8SAndroid Build Coastguard Worker int *lsb) const 349*2d1272b8SAndroid Build Coastguard Worker { 350*2d1272b8SAndroid Build Coastguard Worker if (!font->num_coords) 351*2d1272b8SAndroid Build Coastguard Worker return get_leading_bearing_without_var_unscaled (glyph, lsb); 352*2d1272b8SAndroid Build Coastguard Worker 353*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR 354*2d1272b8SAndroid Build Coastguard Worker float delta; 355*2d1272b8SAndroid Build Coastguard Worker if (var_table->get_lsb_delta_unscaled (glyph, font->coords, font->num_coords, &delta) && 356*2d1272b8SAndroid Build Coastguard Worker get_leading_bearing_without_var_unscaled (glyph, lsb)) 357*2d1272b8SAndroid Build Coastguard Worker { 358*2d1272b8SAndroid Build Coastguard Worker *lsb += roundf (delta); 359*2d1272b8SAndroid Build Coastguard Worker return true; 360*2d1272b8SAndroid Build Coastguard Worker } 361*2d1272b8SAndroid Build Coastguard Worker 362*2d1272b8SAndroid Build Coastguard Worker return _glyf_get_leading_bearing_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx, lsb); 363*2d1272b8SAndroid Build Coastguard Worker #else 364*2d1272b8SAndroid Build Coastguard Worker return false; 365*2d1272b8SAndroid Build Coastguard Worker #endif 366*2d1272b8SAndroid Build Coastguard Worker } 367*2d1272b8SAndroid Build Coastguard Worker get_advance_without_var_unscaledOT::hmtxvmtx::accelerator_t368*2d1272b8SAndroid Build Coastguard Worker unsigned int get_advance_without_var_unscaled (hb_codepoint_t glyph) const 369*2d1272b8SAndroid Build Coastguard Worker { 370*2d1272b8SAndroid Build Coastguard Worker /* OpenType case. */ 371*2d1272b8SAndroid Build Coastguard Worker if (glyph < num_bearings) 372*2d1272b8SAndroid Build Coastguard Worker return table->longMetricZ[hb_min (glyph, (uint32_t) num_long_metrics - 1)].advance; 373*2d1272b8SAndroid Build Coastguard Worker 374*2d1272b8SAndroid Build Coastguard Worker /* If num_advances is zero, it means we don't have the metrics table 375*2d1272b8SAndroid Build Coastguard Worker * for this direction: return default advance. Otherwise, there's a 376*2d1272b8SAndroid Build Coastguard Worker * well-defined answer. */ 377*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!num_advances)) 378*2d1272b8SAndroid Build Coastguard Worker return default_advance; 379*2d1272b8SAndroid Build Coastguard Worker 380*2d1272b8SAndroid Build Coastguard Worker #ifdef HB_NO_BEYOND_64K 381*2d1272b8SAndroid Build Coastguard Worker return 0; 382*2d1272b8SAndroid Build Coastguard Worker #endif 383*2d1272b8SAndroid Build Coastguard Worker 384*2d1272b8SAndroid Build Coastguard Worker if (unlikely (glyph >= num_glyphs)) 385*2d1272b8SAndroid Build Coastguard Worker return 0; 386*2d1272b8SAndroid Build Coastguard Worker 387*2d1272b8SAndroid Build Coastguard Worker /* num_bearings <= glyph < num_glyphs; 388*2d1272b8SAndroid Build Coastguard Worker * num_bearings <= num_advances */ 389*2d1272b8SAndroid Build Coastguard Worker 390*2d1272b8SAndroid Build Coastguard Worker if (num_bearings == num_advances) 391*2d1272b8SAndroid Build Coastguard Worker return get_advance_without_var_unscaled (num_bearings - 1); 392*2d1272b8SAndroid Build Coastguard Worker 393*2d1272b8SAndroid Build Coastguard Worker const FWORD *bearings = (const FWORD *) &table->longMetricZ[num_long_metrics]; 394*2d1272b8SAndroid Build Coastguard Worker const UFWORD *advances = (const UFWORD *) &bearings[num_bearings - num_long_metrics]; 395*2d1272b8SAndroid Build Coastguard Worker 396*2d1272b8SAndroid Build Coastguard Worker return advances[hb_min (glyph - num_bearings, num_advances - num_bearings - 1)]; 397*2d1272b8SAndroid Build Coastguard Worker } 398*2d1272b8SAndroid Build Coastguard Worker get_advance_with_var_unscaledOT::hmtxvmtx::accelerator_t399*2d1272b8SAndroid Build Coastguard Worker unsigned get_advance_with_var_unscaled (hb_codepoint_t glyph, 400*2d1272b8SAndroid Build Coastguard Worker hb_font_t *font, 401*2d1272b8SAndroid Build Coastguard Worker ItemVariationStore::cache_t *store_cache = nullptr) const 402*2d1272b8SAndroid Build Coastguard Worker { 403*2d1272b8SAndroid Build Coastguard Worker unsigned int advance = get_advance_without_var_unscaled (glyph); 404*2d1272b8SAndroid Build Coastguard Worker 405*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_VAR 406*2d1272b8SAndroid Build Coastguard Worker if (unlikely (glyph >= num_bearings) || !font->num_coords) 407*2d1272b8SAndroid Build Coastguard Worker return advance; 408*2d1272b8SAndroid Build Coastguard Worker 409*2d1272b8SAndroid Build Coastguard Worker if (var_table.get_length ()) 410*2d1272b8SAndroid Build Coastguard Worker return advance + roundf (var_table->get_advance_delta_unscaled (glyph, 411*2d1272b8SAndroid Build Coastguard Worker font->coords, font->num_coords, 412*2d1272b8SAndroid Build Coastguard Worker store_cache)); 413*2d1272b8SAndroid Build Coastguard Worker 414*2d1272b8SAndroid Build Coastguard Worker unsigned glyf_advance = _glyf_get_advance_with_var_unscaled (font, glyph, T::tableTag == HB_OT_TAG_vmtx); 415*2d1272b8SAndroid Build Coastguard Worker return glyf_advance ? glyf_advance : advance; 416*2d1272b8SAndroid Build Coastguard Worker #else 417*2d1272b8SAndroid Build Coastguard Worker return advance; 418*2d1272b8SAndroid Build Coastguard Worker #endif 419*2d1272b8SAndroid Build Coastguard Worker } 420*2d1272b8SAndroid Build Coastguard Worker 421*2d1272b8SAndroid Build Coastguard Worker protected: 422*2d1272b8SAndroid Build Coastguard Worker // 0 <= num_long_metrics <= num_bearings <= num_advances <= num_glyphs 423*2d1272b8SAndroid Build Coastguard Worker unsigned num_long_metrics; 424*2d1272b8SAndroid Build Coastguard Worker unsigned num_bearings; 425*2d1272b8SAndroid Build Coastguard Worker unsigned num_advances; 426*2d1272b8SAndroid Build Coastguard Worker unsigned num_glyphs; 427*2d1272b8SAndroid Build Coastguard Worker 428*2d1272b8SAndroid Build Coastguard Worker unsigned int default_advance; 429*2d1272b8SAndroid Build Coastguard Worker 430*2d1272b8SAndroid Build Coastguard Worker public: 431*2d1272b8SAndroid Build Coastguard Worker hb_blob_ptr_t<hmtxvmtx> table; 432*2d1272b8SAndroid Build Coastguard Worker hb_blob_ptr_t<V> var_table; 433*2d1272b8SAndroid Build Coastguard Worker }; 434*2d1272b8SAndroid Build Coastguard Worker 435*2d1272b8SAndroid Build Coastguard Worker /* get advance: when no variations, call get_advance_without_var_unscaled. 436*2d1272b8SAndroid Build Coastguard Worker * when there're variations, get advance value from mtx_map in subset_plan*/ get_new_gid_advance_unscaledOT::hmtxvmtx437*2d1272b8SAndroid Build Coastguard Worker unsigned get_new_gid_advance_unscaled (const hb_subset_plan_t *plan, 438*2d1272b8SAndroid Build Coastguard Worker const hb_hashmap_t<hb_codepoint_t, hb_pair_t<unsigned, int>> *mtx_map, 439*2d1272b8SAndroid Build Coastguard Worker unsigned new_gid, 440*2d1272b8SAndroid Build Coastguard Worker const accelerator_t &_mtx) const 441*2d1272b8SAndroid Build Coastguard Worker { 442*2d1272b8SAndroid Build Coastguard Worker if (mtx_map->is_empty ()) 443*2d1272b8SAndroid Build Coastguard Worker { 444*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t old_gid = 0; 445*2d1272b8SAndroid Build Coastguard Worker return plan->old_gid_for_new_gid (new_gid, &old_gid) ? 446*2d1272b8SAndroid Build Coastguard Worker _mtx.get_advance_without_var_unscaled (old_gid) : 0; 447*2d1272b8SAndroid Build Coastguard Worker } 448*2d1272b8SAndroid Build Coastguard Worker return mtx_map->get (new_gid).first; 449*2d1272b8SAndroid Build Coastguard Worker } 450*2d1272b8SAndroid Build Coastguard Worker 451*2d1272b8SAndroid Build Coastguard Worker protected: 452*2d1272b8SAndroid Build Coastguard Worker UnsizedArrayOf<LongMetric> 453*2d1272b8SAndroid Build Coastguard Worker longMetricZ; /* Paired advance width and leading 454*2d1272b8SAndroid Build Coastguard Worker * bearing values for each glyph. The 455*2d1272b8SAndroid Build Coastguard Worker * value numOfHMetrics comes from 456*2d1272b8SAndroid Build Coastguard Worker * the 'hhea' table. If the font is 457*2d1272b8SAndroid Build Coastguard Worker * monospaced, only one entry need 458*2d1272b8SAndroid Build Coastguard Worker * be in the array, but that entry is 459*2d1272b8SAndroid Build Coastguard Worker * required. The last entry applies to 460*2d1272b8SAndroid Build Coastguard Worker * all subsequent glyphs. */ 461*2d1272b8SAndroid Build Coastguard Worker /*UnsizedArrayOf<FWORD> leadingBearingX;*/ 462*2d1272b8SAndroid Build Coastguard Worker /* Here the advance is assumed 463*2d1272b8SAndroid Build Coastguard Worker * to be the same as the advance 464*2d1272b8SAndroid Build Coastguard Worker * for the last entry above. The 465*2d1272b8SAndroid Build Coastguard Worker * number of entries in this array is 466*2d1272b8SAndroid Build Coastguard Worker * derived from numGlyphs (from 'maxp' 467*2d1272b8SAndroid Build Coastguard Worker * table) minus numberOfLongMetrics. 468*2d1272b8SAndroid Build Coastguard Worker * This generally is used with a run 469*2d1272b8SAndroid Build Coastguard Worker * of monospaced glyphs (e.g., Kanji 470*2d1272b8SAndroid Build Coastguard Worker * fonts or Courier fonts). Only one 471*2d1272b8SAndroid Build Coastguard Worker * run is allowed and it must be at 472*2d1272b8SAndroid Build Coastguard Worker * the end. This allows a monospaced 473*2d1272b8SAndroid Build Coastguard Worker * font to vary the side bearing 474*2d1272b8SAndroid Build Coastguard Worker * values for each glyph. */ 475*2d1272b8SAndroid Build Coastguard Worker /*UnsizedArrayOf<UFWORD>advancesX;*/ 476*2d1272b8SAndroid Build Coastguard Worker /* TODO Document. */ 477*2d1272b8SAndroid Build Coastguard Worker public: 478*2d1272b8SAndroid Build Coastguard Worker DEFINE_SIZE_ARRAY (0, longMetricZ); 479*2d1272b8SAndroid Build Coastguard Worker }; 480*2d1272b8SAndroid Build Coastguard Worker 481*2d1272b8SAndroid Build Coastguard Worker struct hmtx : hmtxvmtx<hmtx, hhea, HVAR> { 482*2d1272b8SAndroid Build Coastguard Worker static constexpr hb_tag_t tableTag = HB_OT_TAG_hmtx; 483*2d1272b8SAndroid Build Coastguard Worker static constexpr hb_tag_t variationsTag = HB_OT_TAG_HVAR; 484*2d1272b8SAndroid Build Coastguard Worker static constexpr bool is_horizontal = true; 485*2d1272b8SAndroid Build Coastguard Worker }; 486*2d1272b8SAndroid Build Coastguard Worker struct vmtx : hmtxvmtx<vmtx, vhea, VVAR> { 487*2d1272b8SAndroid Build Coastguard Worker static constexpr hb_tag_t tableTag = HB_OT_TAG_vmtx; 488*2d1272b8SAndroid Build Coastguard Worker static constexpr hb_tag_t variationsTag = HB_OT_TAG_VVAR; 489*2d1272b8SAndroid Build Coastguard Worker static constexpr bool is_horizontal = false; 490*2d1272b8SAndroid Build Coastguard Worker }; 491*2d1272b8SAndroid Build Coastguard Worker 492*2d1272b8SAndroid Build Coastguard Worker struct hmtx_accelerator_t : hmtx::accelerator_t { hmtx_accelerator_tOT::hmtx_accelerator_t493*2d1272b8SAndroid Build Coastguard Worker hmtx_accelerator_t (hb_face_t *face) : hmtx::accelerator_t (face) {} 494*2d1272b8SAndroid Build Coastguard Worker }; 495*2d1272b8SAndroid Build Coastguard Worker struct vmtx_accelerator_t : vmtx::accelerator_t { vmtx_accelerator_tOT::vmtx_accelerator_t496*2d1272b8SAndroid Build Coastguard Worker vmtx_accelerator_t (hb_face_t *face) : vmtx::accelerator_t (face) {} 497*2d1272b8SAndroid Build Coastguard Worker }; 498*2d1272b8SAndroid Build Coastguard Worker 499*2d1272b8SAndroid Build Coastguard Worker } /* namespace OT */ 500*2d1272b8SAndroid Build Coastguard Worker 501*2d1272b8SAndroid Build Coastguard Worker 502*2d1272b8SAndroid Build Coastguard Worker #endif /* HB_OT_HMTX_TABLE_HH */ 503