1*2d1272b8SAndroid Build Coastguard Worker /* 2*2d1272b8SAndroid Build Coastguard Worker * Copyright © 2018 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): Garret Rieger, Roderick Sheeter 25*2d1272b8SAndroid Build Coastguard Worker */ 26*2d1272b8SAndroid Build Coastguard Worker 27*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_SUBSET_PLAN_HH 28*2d1272b8SAndroid Build Coastguard Worker #define HB_SUBSET_PLAN_HH 29*2d1272b8SAndroid Build Coastguard Worker 30*2d1272b8SAndroid Build Coastguard Worker #include "hb.hh" 31*2d1272b8SAndroid Build Coastguard Worker 32*2d1272b8SAndroid Build Coastguard Worker #include "hb-subset.h" 33*2d1272b8SAndroid Build Coastguard Worker #include "hb-subset-input.hh" 34*2d1272b8SAndroid Build Coastguard Worker #include "hb-subset-accelerator.hh" 35*2d1272b8SAndroid Build Coastguard Worker 36*2d1272b8SAndroid Build Coastguard Worker #include "hb-map.hh" 37*2d1272b8SAndroid Build Coastguard Worker #include "hb-bimap.hh" 38*2d1272b8SAndroid Build Coastguard Worker #include "hb-set.hh" 39*2d1272b8SAndroid Build Coastguard Worker 40*2d1272b8SAndroid Build Coastguard Worker namespace OT { 41*2d1272b8SAndroid Build Coastguard Worker struct Feature; 42*2d1272b8SAndroid Build Coastguard Worker } 43*2d1272b8SAndroid Build Coastguard Worker 44*2d1272b8SAndroid Build Coastguard Worker struct head_maxp_info_t 45*2d1272b8SAndroid Build Coastguard Worker { head_maxp_info_thead_maxp_info_t46*2d1272b8SAndroid Build Coastguard Worker head_maxp_info_t () 47*2d1272b8SAndroid Build Coastguard Worker :xMin (0x7FFF), xMax (-0x7FFF), yMin (0x7FFF), yMax (-0x7FFF), 48*2d1272b8SAndroid Build Coastguard Worker maxPoints (0), maxContours (0), 49*2d1272b8SAndroid Build Coastguard Worker maxCompositePoints (0), 50*2d1272b8SAndroid Build Coastguard Worker maxCompositeContours (0), 51*2d1272b8SAndroid Build Coastguard Worker maxComponentElements (0), 52*2d1272b8SAndroid Build Coastguard Worker maxComponentDepth (0), 53*2d1272b8SAndroid Build Coastguard Worker allXMinIsLsb (true) {} 54*2d1272b8SAndroid Build Coastguard Worker 55*2d1272b8SAndroid Build Coastguard Worker int xMin; 56*2d1272b8SAndroid Build Coastguard Worker int xMax; 57*2d1272b8SAndroid Build Coastguard Worker int yMin; 58*2d1272b8SAndroid Build Coastguard Worker int yMax; 59*2d1272b8SAndroid Build Coastguard Worker unsigned maxPoints; 60*2d1272b8SAndroid Build Coastguard Worker unsigned maxContours; 61*2d1272b8SAndroid Build Coastguard Worker unsigned maxCompositePoints; 62*2d1272b8SAndroid Build Coastguard Worker unsigned maxCompositeContours; 63*2d1272b8SAndroid Build Coastguard Worker unsigned maxComponentElements; 64*2d1272b8SAndroid Build Coastguard Worker unsigned maxComponentDepth; 65*2d1272b8SAndroid Build Coastguard Worker bool allXMinIsLsb; 66*2d1272b8SAndroid Build Coastguard Worker }; 67*2d1272b8SAndroid Build Coastguard Worker 68*2d1272b8SAndroid Build Coastguard Worker typedef struct head_maxp_info_t head_maxp_info_t; 69*2d1272b8SAndroid Build Coastguard Worker 70*2d1272b8SAndroid Build Coastguard Worker struct contour_point_t 71*2d1272b8SAndroid Build Coastguard Worker { initcontour_point_t72*2d1272b8SAndroid Build Coastguard Worker void init (float x_ = 0.f, float y_ = 0.f, bool is_end_point_ = false) 73*2d1272b8SAndroid Build Coastguard Worker { flag = 0; x = x_; y = y_; is_end_point = is_end_point_; } 74*2d1272b8SAndroid Build Coastguard Worker transformcontour_point_t75*2d1272b8SAndroid Build Coastguard Worker void transform (const float (&matrix)[4]) 76*2d1272b8SAndroid Build Coastguard Worker { 77*2d1272b8SAndroid Build Coastguard Worker float x_ = x * matrix[0] + y * matrix[2]; 78*2d1272b8SAndroid Build Coastguard Worker y = x * matrix[1] + y * matrix[3]; 79*2d1272b8SAndroid Build Coastguard Worker x = x_; 80*2d1272b8SAndroid Build Coastguard Worker } 81*2d1272b8SAndroid Build Coastguard Worker add_deltacontour_point_t82*2d1272b8SAndroid Build Coastguard Worker void add_delta (float delta_x, float delta_y) 83*2d1272b8SAndroid Build Coastguard Worker { 84*2d1272b8SAndroid Build Coastguard Worker x += delta_x; 85*2d1272b8SAndroid Build Coastguard Worker y += delta_y; 86*2d1272b8SAndroid Build Coastguard Worker } 87*2d1272b8SAndroid Build Coastguard Worker 88*2d1272b8SAndroid Build Coastguard Worker HB_ALWAYS_INLINE translatecontour_point_t89*2d1272b8SAndroid Build Coastguard Worker void translate (const contour_point_t &p) { x += p.x; y += p.y; } 90*2d1272b8SAndroid Build Coastguard Worker 91*2d1272b8SAndroid Build Coastguard Worker 92*2d1272b8SAndroid Build Coastguard Worker float x; 93*2d1272b8SAndroid Build Coastguard Worker float y; 94*2d1272b8SAndroid Build Coastguard Worker uint8_t flag; 95*2d1272b8SAndroid Build Coastguard Worker bool is_end_point; 96*2d1272b8SAndroid Build Coastguard Worker }; 97*2d1272b8SAndroid Build Coastguard Worker 98*2d1272b8SAndroid Build Coastguard Worker struct contour_point_vector_t : hb_vector_t<contour_point_t> 99*2d1272b8SAndroid Build Coastguard Worker { extendcontour_point_vector_t100*2d1272b8SAndroid Build Coastguard Worker void extend (const hb_array_t<contour_point_t> &a) 101*2d1272b8SAndroid Build Coastguard Worker { 102*2d1272b8SAndroid Build Coastguard Worker unsigned int old_len = length; 103*2d1272b8SAndroid Build Coastguard Worker if (unlikely (!resize (old_len + a.length, false))) 104*2d1272b8SAndroid Build Coastguard Worker return; 105*2d1272b8SAndroid Build Coastguard Worker auto arrayZ = this->arrayZ + old_len; 106*2d1272b8SAndroid Build Coastguard Worker unsigned count = a.length; 107*2d1272b8SAndroid Build Coastguard Worker hb_memcpy (arrayZ, a.arrayZ, count * sizeof (arrayZ[0])); 108*2d1272b8SAndroid Build Coastguard Worker } 109*2d1272b8SAndroid Build Coastguard Worker add_deltascontour_point_vector_t110*2d1272b8SAndroid Build Coastguard Worker bool add_deltas (const hb_vector_t<float> deltas_x, 111*2d1272b8SAndroid Build Coastguard Worker const hb_vector_t<float> deltas_y, 112*2d1272b8SAndroid Build Coastguard Worker const hb_vector_t<bool> indices) 113*2d1272b8SAndroid Build Coastguard Worker { 114*2d1272b8SAndroid Build Coastguard Worker if (indices.length != deltas_x.length || 115*2d1272b8SAndroid Build Coastguard Worker indices.length != deltas_y.length) 116*2d1272b8SAndroid Build Coastguard Worker return false; 117*2d1272b8SAndroid Build Coastguard Worker 118*2d1272b8SAndroid Build Coastguard Worker for (unsigned i = 0; i < indices.length; i++) 119*2d1272b8SAndroid Build Coastguard Worker { 120*2d1272b8SAndroid Build Coastguard Worker if (!indices.arrayZ[i]) continue; 121*2d1272b8SAndroid Build Coastguard Worker arrayZ[i].add_delta (deltas_x.arrayZ[i], deltas_y.arrayZ[i]); 122*2d1272b8SAndroid Build Coastguard Worker } 123*2d1272b8SAndroid Build Coastguard Worker return true; 124*2d1272b8SAndroid Build Coastguard Worker } 125*2d1272b8SAndroid Build Coastguard Worker }; 126*2d1272b8SAndroid Build Coastguard Worker 127*2d1272b8SAndroid Build Coastguard Worker namespace OT { 128*2d1272b8SAndroid Build Coastguard Worker struct cff1_subset_accelerator_t; 129*2d1272b8SAndroid Build Coastguard Worker struct cff2_subset_accelerator_t; 130*2d1272b8SAndroid Build Coastguard Worker } 131*2d1272b8SAndroid Build Coastguard Worker 132*2d1272b8SAndroid Build Coastguard Worker struct hb_subset_plan_t 133*2d1272b8SAndroid Build Coastguard Worker { 134*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL hb_subset_plan_t (hb_face_t *, 135*2d1272b8SAndroid Build Coastguard Worker const hb_subset_input_t *input); 136*2d1272b8SAndroid Build Coastguard Worker 137*2d1272b8SAndroid Build Coastguard Worker HB_INTERNAL ~hb_subset_plan_t(); 138*2d1272b8SAndroid Build Coastguard Worker 139*2d1272b8SAndroid Build Coastguard Worker hb_object_header_t header; 140*2d1272b8SAndroid Build Coastguard Worker 141*2d1272b8SAndroid Build Coastguard Worker bool successful; 142*2d1272b8SAndroid Build Coastguard Worker unsigned flags; 143*2d1272b8SAndroid Build Coastguard Worker bool attach_accelerator_data = false; 144*2d1272b8SAndroid Build Coastguard Worker bool force_long_loca = false; 145*2d1272b8SAndroid Build Coastguard Worker 146*2d1272b8SAndroid Build Coastguard Worker // The glyph subset 147*2d1272b8SAndroid Build Coastguard Worker hb_map_t *codepoint_to_glyph; // Needs to be heap-allocated 148*2d1272b8SAndroid Build Coastguard Worker 149*2d1272b8SAndroid Build Coastguard Worker // Old -> New glyph id mapping 150*2d1272b8SAndroid Build Coastguard Worker hb_map_t *glyph_map; // Needs to be heap-allocated 151*2d1272b8SAndroid Build Coastguard Worker hb_map_t *reverse_glyph_map; // Needs to be heap-allocated 152*2d1272b8SAndroid Build Coastguard Worker 153*2d1272b8SAndroid Build Coastguard Worker // Plan is only good for a specific source/dest so keep them with it 154*2d1272b8SAndroid Build Coastguard Worker hb_face_t *source; 155*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_SUBSET_CFF 156*2d1272b8SAndroid Build Coastguard Worker // These have to be immediately after source: 157*2d1272b8SAndroid Build Coastguard Worker hb_face_lazy_loader_t<OT::cff1_subset_accelerator_t, 1> cff1_accel; 158*2d1272b8SAndroid Build Coastguard Worker hb_face_lazy_loader_t<OT::cff2_subset_accelerator_t, 2> cff2_accel; 159*2d1272b8SAndroid Build Coastguard Worker #endif 160*2d1272b8SAndroid Build Coastguard Worker 161*2d1272b8SAndroid Build Coastguard Worker hb_face_t *dest; 162*2d1272b8SAndroid Build Coastguard Worker 163*2d1272b8SAndroid Build Coastguard Worker unsigned int _num_output_glyphs; 164*2d1272b8SAndroid Build Coastguard Worker 165*2d1272b8SAndroid Build Coastguard Worker bool all_axes_pinned; 166*2d1272b8SAndroid Build Coastguard Worker bool pinned_at_default; 167*2d1272b8SAndroid Build Coastguard Worker bool has_seac; 168*2d1272b8SAndroid Build Coastguard Worker 169*2d1272b8SAndroid Build Coastguard Worker // whether to insert a catch-all FeatureVariationRecord 170*2d1272b8SAndroid Build Coastguard Worker bool gsub_insert_catch_all_feature_variation_rec; 171*2d1272b8SAndroid Build Coastguard Worker bool gpos_insert_catch_all_feature_variation_rec; 172*2d1272b8SAndroid Build Coastguard Worker 173*2d1272b8SAndroid Build Coastguard Worker // whether GDEF ItemVariationStore is retained 174*2d1272b8SAndroid Build Coastguard Worker mutable bool has_gdef_varstore; 175*2d1272b8SAndroid Build Coastguard Worker 176*2d1272b8SAndroid Build Coastguard Worker #define HB_SUBSET_PLAN_MEMBER(Type, Name) Type Name; 177*2d1272b8SAndroid Build Coastguard Worker #include "hb-subset-plan-member-list.hh" 178*2d1272b8SAndroid Build Coastguard Worker #undef HB_SUBSET_PLAN_MEMBER 179*2d1272b8SAndroid Build Coastguard Worker 180*2d1272b8SAndroid Build Coastguard Worker //recalculated head/maxp table info after instancing 181*2d1272b8SAndroid Build Coastguard Worker mutable head_maxp_info_t head_maxp_info; 182*2d1272b8SAndroid Build Coastguard Worker 183*2d1272b8SAndroid Build Coastguard Worker const hb_subset_accelerator_t* accelerator; 184*2d1272b8SAndroid Build Coastguard Worker hb_subset_accelerator_t* inprogress_accelerator; 185*2d1272b8SAndroid Build Coastguard Worker 186*2d1272b8SAndroid Build Coastguard Worker public: 187*2d1272b8SAndroid Build Coastguard Worker 188*2d1272b8SAndroid Build Coastguard Worker template<typename T> 189*2d1272b8SAndroid Build Coastguard Worker struct source_table_loader 190*2d1272b8SAndroid Build Coastguard Worker { operator ()hb_subset_plan_t::source_table_loader191*2d1272b8SAndroid Build Coastguard Worker hb_blob_ptr_t<T> operator () (hb_subset_plan_t *plan) 192*2d1272b8SAndroid Build Coastguard Worker { 193*2d1272b8SAndroid Build Coastguard Worker hb_lock_t lock (plan->accelerator ? &plan->accelerator->sanitized_table_cache_lock : nullptr); 194*2d1272b8SAndroid Build Coastguard Worker 195*2d1272b8SAndroid Build Coastguard Worker auto *cache = plan->accelerator ? &plan->accelerator->sanitized_table_cache : &plan->sanitized_table_cache; 196*2d1272b8SAndroid Build Coastguard Worker if (cache 197*2d1272b8SAndroid Build Coastguard Worker && !cache->in_error () 198*2d1272b8SAndroid Build Coastguard Worker && cache->has (+T::tableTag)) { 199*2d1272b8SAndroid Build Coastguard Worker return hb_blob_reference (cache->get (+T::tableTag).get ()); 200*2d1272b8SAndroid Build Coastguard Worker } 201*2d1272b8SAndroid Build Coastguard Worker 202*2d1272b8SAndroid Build Coastguard Worker hb::unique_ptr<hb_blob_t> table_blob {hb_sanitize_context_t ().reference_table<T> (plan->source)}; 203*2d1272b8SAndroid Build Coastguard Worker hb_blob_t* ret = hb_blob_reference (table_blob.get ()); 204*2d1272b8SAndroid Build Coastguard Worker 205*2d1272b8SAndroid Build Coastguard Worker if (likely (cache)) 206*2d1272b8SAndroid Build Coastguard Worker cache->set (+T::tableTag, std::move (table_blob)); 207*2d1272b8SAndroid Build Coastguard Worker 208*2d1272b8SAndroid Build Coastguard Worker return ret; 209*2d1272b8SAndroid Build Coastguard Worker } 210*2d1272b8SAndroid Build Coastguard Worker }; 211*2d1272b8SAndroid Build Coastguard Worker 212*2d1272b8SAndroid Build Coastguard Worker template<typename T> source_tablehb_subset_plan_t213*2d1272b8SAndroid Build Coastguard Worker auto source_table() HB_AUTO_RETURN (source_table_loader<T> {} (this)) 214*2d1272b8SAndroid Build Coastguard Worker 215*2d1272b8SAndroid Build Coastguard Worker bool in_error () const { return !successful; } 216*2d1272b8SAndroid Build Coastguard Worker check_successhb_subset_plan_t217*2d1272b8SAndroid Build Coastguard Worker bool check_success(bool success) 218*2d1272b8SAndroid Build Coastguard Worker { 219*2d1272b8SAndroid Build Coastguard Worker successful = (successful && success); 220*2d1272b8SAndroid Build Coastguard Worker return successful; 221*2d1272b8SAndroid Build Coastguard Worker } 222*2d1272b8SAndroid Build Coastguard Worker 223*2d1272b8SAndroid Build Coastguard Worker /* 224*2d1272b8SAndroid Build Coastguard Worker * The set of input glyph ids which will be retained in the subset. 225*2d1272b8SAndroid Build Coastguard Worker * Does NOT include ids kept due to retain_gids. You probably want to use 226*2d1272b8SAndroid Build Coastguard Worker * glyph_map/reverse_glyph_map. 227*2d1272b8SAndroid Build Coastguard Worker */ 228*2d1272b8SAndroid Build Coastguard Worker inline const hb_set_t * glyphsethb_subset_plan_t229*2d1272b8SAndroid Build Coastguard Worker glyphset () const 230*2d1272b8SAndroid Build Coastguard Worker { 231*2d1272b8SAndroid Build Coastguard Worker return &_glyphset; 232*2d1272b8SAndroid Build Coastguard Worker } 233*2d1272b8SAndroid Build Coastguard Worker 234*2d1272b8SAndroid Build Coastguard Worker /* 235*2d1272b8SAndroid Build Coastguard Worker * The set of input glyph ids which will be retained in the subset. 236*2d1272b8SAndroid Build Coastguard Worker */ 237*2d1272b8SAndroid Build Coastguard Worker inline const hb_set_t * glyphset_gsubhb_subset_plan_t238*2d1272b8SAndroid Build Coastguard Worker glyphset_gsub () const 239*2d1272b8SAndroid Build Coastguard Worker { 240*2d1272b8SAndroid Build Coastguard Worker return &_glyphset_gsub; 241*2d1272b8SAndroid Build Coastguard Worker } 242*2d1272b8SAndroid Build Coastguard Worker 243*2d1272b8SAndroid Build Coastguard Worker /* 244*2d1272b8SAndroid Build Coastguard Worker * The total number of output glyphs in the final subset. 245*2d1272b8SAndroid Build Coastguard Worker */ 246*2d1272b8SAndroid Build Coastguard Worker inline unsigned int num_output_glyphshb_subset_plan_t247*2d1272b8SAndroid Build Coastguard Worker num_output_glyphs () const 248*2d1272b8SAndroid Build Coastguard Worker { 249*2d1272b8SAndroid Build Coastguard Worker return _num_output_glyphs; 250*2d1272b8SAndroid Build Coastguard Worker } 251*2d1272b8SAndroid Build Coastguard Worker new_gid_for_codepointhb_subset_plan_t252*2d1272b8SAndroid Build Coastguard Worker inline bool new_gid_for_codepoint (hb_codepoint_t codepoint, 253*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t *new_gid) const 254*2d1272b8SAndroid Build Coastguard Worker { 255*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t old_gid = codepoint_to_glyph->get (codepoint); 256*2d1272b8SAndroid Build Coastguard Worker if (old_gid == HB_MAP_VALUE_INVALID) 257*2d1272b8SAndroid Build Coastguard Worker return false; 258*2d1272b8SAndroid Build Coastguard Worker 259*2d1272b8SAndroid Build Coastguard Worker return new_gid_for_old_gid (old_gid, new_gid); 260*2d1272b8SAndroid Build Coastguard Worker } 261*2d1272b8SAndroid Build Coastguard Worker new_gid_for_old_gidhb_subset_plan_t262*2d1272b8SAndroid Build Coastguard Worker inline bool new_gid_for_old_gid (hb_codepoint_t old_gid, 263*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t *new_gid) const 264*2d1272b8SAndroid Build Coastguard Worker { 265*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t gid = glyph_map->get (old_gid); 266*2d1272b8SAndroid Build Coastguard Worker if (gid == HB_MAP_VALUE_INVALID) 267*2d1272b8SAndroid Build Coastguard Worker return false; 268*2d1272b8SAndroid Build Coastguard Worker 269*2d1272b8SAndroid Build Coastguard Worker *new_gid = gid; 270*2d1272b8SAndroid Build Coastguard Worker return true; 271*2d1272b8SAndroid Build Coastguard Worker } 272*2d1272b8SAndroid Build Coastguard Worker old_gid_for_new_gidhb_subset_plan_t273*2d1272b8SAndroid Build Coastguard Worker inline bool old_gid_for_new_gid (hb_codepoint_t new_gid, 274*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t *old_gid) const 275*2d1272b8SAndroid Build Coastguard Worker { 276*2d1272b8SAndroid Build Coastguard Worker hb_codepoint_t gid = reverse_glyph_map->get (new_gid); 277*2d1272b8SAndroid Build Coastguard Worker if (gid == HB_MAP_VALUE_INVALID) 278*2d1272b8SAndroid Build Coastguard Worker return false; 279*2d1272b8SAndroid Build Coastguard Worker 280*2d1272b8SAndroid Build Coastguard Worker *old_gid = gid; 281*2d1272b8SAndroid Build Coastguard Worker return true; 282*2d1272b8SAndroid Build Coastguard Worker } 283*2d1272b8SAndroid Build Coastguard Worker 284*2d1272b8SAndroid Build Coastguard Worker inline bool add_tablehb_subset_plan_t285*2d1272b8SAndroid Build Coastguard Worker add_table (hb_tag_t tag, 286*2d1272b8SAndroid Build Coastguard Worker hb_blob_t *contents) 287*2d1272b8SAndroid Build Coastguard Worker { 288*2d1272b8SAndroid Build Coastguard Worker if (HB_DEBUG_SUBSET) 289*2d1272b8SAndroid Build Coastguard Worker { 290*2d1272b8SAndroid Build Coastguard Worker hb_blob_t *source_blob = source->reference_table (tag); 291*2d1272b8SAndroid Build Coastguard Worker DEBUG_MSG(SUBSET, nullptr, "add table %c%c%c%c, dest %u bytes, source %u bytes", 292*2d1272b8SAndroid Build Coastguard Worker HB_UNTAG(tag), 293*2d1272b8SAndroid Build Coastguard Worker hb_blob_get_length (contents), 294*2d1272b8SAndroid Build Coastguard Worker hb_blob_get_length (source_blob)); 295*2d1272b8SAndroid Build Coastguard Worker hb_blob_destroy (source_blob); 296*2d1272b8SAndroid Build Coastguard Worker } 297*2d1272b8SAndroid Build Coastguard Worker return hb_face_builder_add_table (dest, tag, contents); 298*2d1272b8SAndroid Build Coastguard Worker } 299*2d1272b8SAndroid Build Coastguard Worker }; 300*2d1272b8SAndroid Build Coastguard Worker 301*2d1272b8SAndroid Build Coastguard Worker 302*2d1272b8SAndroid Build Coastguard Worker #endif /* HB_SUBSET_PLAN_HH */ 303