hb-subset-plan.hh (10179B)
1 /* 2 * Copyright © 2018 Google, Inc. 3 * 4 * This is part of HarfBuzz, a text shaping library. 5 * 6 * Permission is hereby granted, without written agreement and without 7 * license or royalty fees, to use, copy, modify, and distribute this 8 * software and its documentation for any purpose, provided that the 9 * above copyright notice and the following two paragraphs appear in 10 * all copies of this software. 11 * 12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 16 * DAMAGE. 17 * 18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 23 * 24 * Google Author(s): Garret Rieger, Roderick Sheeter 25 */ 26 27 #ifndef HB_SUBSET_PLAN_HH 28 #define HB_SUBSET_PLAN_HH 29 30 #include "hb.hh" 31 32 #include "hb-subset.h" 33 #include "hb-subset-input.hh" 34 #include "hb-subset-accelerator.hh" 35 36 #include "hb-map.hh" 37 #include "hb-bimap.hh" 38 #include "hb-set.hh" 39 40 namespace OT { 41 struct Feature; 42 } 43 44 struct os2_info_t { 45 hb_codepoint_t min_cmap_codepoint; 46 hb_codepoint_t max_cmap_codepoint; 47 }; 48 49 typedef struct os2_info_t os2_info_t; 50 51 struct head_maxp_info_t 52 { 53 head_maxp_info_t () 54 :xMin (0x7FFF), xMax (-0x7FFF), yMin (0x7FFF), yMax (-0x7FFF), 55 maxPoints (0), maxContours (0), 56 maxCompositePoints (0), 57 maxCompositeContours (0), 58 maxComponentElements (0), 59 maxComponentDepth (0), 60 allXMinIsLsb (true) {} 61 62 int xMin; 63 int xMax; 64 int yMin; 65 int yMax; 66 unsigned maxPoints; 67 unsigned maxContours; 68 unsigned maxCompositePoints; 69 unsigned maxCompositeContours; 70 unsigned maxComponentElements; 71 unsigned maxComponentDepth; 72 bool allXMinIsLsb; 73 }; 74 75 typedef struct head_maxp_info_t head_maxp_info_t; 76 77 struct contour_point_t 78 { 79 void init (float x_ = 0.f, float y_ = 0.f, bool is_end_point_ = false) 80 { flag = 0; x = x_; y = y_; is_end_point = is_end_point_; } 81 82 void transform (const float (&matrix)[4]) 83 { 84 float x_ = x * matrix[0] + y * matrix[2]; 85 y = x * matrix[1] + y * matrix[3]; 86 x = x_; 87 } 88 89 void add_delta (float delta_x, float delta_y) 90 { 91 x += delta_x; 92 y += delta_y; 93 } 94 95 HB_ALWAYS_INLINE 96 void translate (const contour_point_t &p) { x += p.x; y += p.y; } 97 98 float x; 99 float y; 100 uint8_t flag; 101 bool is_end_point; 102 }; 103 104 struct contour_point_vector_t : hb_vector_t<contour_point_t> 105 { 106 bool add_deltas (hb_array_t<const float> deltas_x, 107 hb_array_t<const float> deltas_y, 108 hb_array_t<const bool> indices) 109 { 110 if (indices.length != deltas_x.length || 111 indices.length != deltas_y.length) 112 return false; 113 114 for (unsigned i = 0; i < indices.length; i++) 115 { 116 if (!indices.arrayZ[i]) continue; 117 arrayZ[i].add_delta (deltas_x.arrayZ[i], deltas_y.arrayZ[i]); 118 } 119 return true; 120 } 121 }; 122 123 namespace OT { 124 struct cff1_subset_accelerator_t; 125 struct cff2_subset_accelerator_t; 126 } 127 128 struct hb_subset_plan_t 129 { 130 HB_INTERNAL hb_subset_plan_t (hb_face_t *, 131 const hb_subset_input_t *input); 132 133 HB_INTERNAL ~hb_subset_plan_t(); 134 135 hb_object_header_t header; 136 137 bool successful; 138 unsigned flags; 139 bool attach_accelerator_data = false; 140 bool force_long_loca = false; 141 142 // The glyph subset 143 hb_map_t *codepoint_to_glyph; // Needs to be heap-allocated 144 145 // Old -> New glyph id mapping 146 hb_map_t *glyph_map; // Needs to be heap-allocated 147 hb_map_t *reverse_glyph_map; // Needs to be heap-allocated 148 149 // Plan is only good for a specific source/dest so keep them with it 150 hb_face_t *source; 151 #ifndef HB_NO_SUBSET_CFF 152 // These have to be immediately after source: 153 hb_face_lazy_loader_t<OT::cff1_subset_accelerator_t, 1> cff1_accel; 154 hb_face_lazy_loader_t<OT::cff2_subset_accelerator_t, 2> cff2_accel; 155 #endif 156 157 hb_face_t *dest; 158 159 unsigned int _num_output_glyphs; 160 161 bool all_axes_pinned; 162 bool pinned_at_default; 163 bool has_seac; 164 165 // whether to insert a catch-all FeatureVariationRecord 166 bool gsub_insert_catch_all_feature_variation_rec; 167 bool gpos_insert_catch_all_feature_variation_rec; 168 169 // whether GDEF ItemVariationStore is retained 170 mutable bool has_gdef_varstore; 171 172 #define HB_SUBSET_PLAN_MEMBER(Type, Name) Type Name; 173 #include "hb-subset-plan-member-list.hh" 174 #undef HB_SUBSET_PLAN_MEMBER 175 176 //recalculated head/maxp table info after instancing 177 mutable head_maxp_info_t head_maxp_info; 178 179 os2_info_t os2_info; 180 181 const hb_subset_accelerator_t* accelerator; 182 hb_subset_accelerator_t* inprogress_accelerator; 183 184 public: 185 186 template<typename T> 187 struct source_table_loader 188 { 189 hb_blob_ptr_t<T> operator () (hb_subset_plan_t *plan) 190 { 191 hb_lock_t lock (plan->accelerator ? &plan->accelerator->sanitized_table_cache_lock : nullptr); 192 193 auto *cache = plan->accelerator ? &plan->accelerator->sanitized_table_cache : &plan->sanitized_table_cache; 194 if (cache 195 && !cache->in_error () 196 && cache->has (+T::tableTag)) { 197 return hb_blob_reference (cache->get (+T::tableTag).get ()); 198 } 199 200 hb::unique_ptr<hb_blob_t> table_blob {hb_sanitize_context_t ().reference_table<T> (plan->source)}; 201 hb_blob_t* ret = hb_blob_reference (table_blob.get ()); 202 203 if (likely (cache)) 204 cache->set (+T::tableTag, std::move (table_blob)); 205 206 return ret; 207 } 208 }; 209 210 template<typename T> 211 auto source_table() HB_AUTO_RETURN (source_table_loader<T> {} (this)) 212 213 bool in_error () const { return !successful; } 214 215 bool check_success(bool success) 216 { 217 successful = (successful && success); 218 return successful; 219 } 220 221 /* 222 * The set of input glyph ids which will be retained in the subset. 223 * Does NOT include ids kept due to retain_gids. You probably want to use 224 * glyph_map/reverse_glyph_map. 225 */ 226 inline const hb_set_t * 227 glyphset () const 228 { 229 return &_glyphset; 230 } 231 232 /* 233 * The set of input glyph ids which will be retained in the subset. 234 */ 235 inline const hb_set_t * 236 glyphset_gsub () const 237 { 238 return &_glyphset_gsub; 239 } 240 241 /* 242 * The total number of output glyphs in the final subset. 243 */ 244 inline unsigned int 245 num_output_glyphs () const 246 { 247 return _num_output_glyphs; 248 } 249 250 inline bool new_gid_for_codepoint (hb_codepoint_t codepoint, 251 hb_codepoint_t *new_gid) const 252 { 253 hb_codepoint_t old_gid = codepoint_to_glyph->get (codepoint); 254 if (old_gid == HB_MAP_VALUE_INVALID) 255 return false; 256 257 return new_gid_for_old_gid (old_gid, new_gid); 258 } 259 260 inline bool new_gid_for_old_gid (hb_codepoint_t old_gid, 261 hb_codepoint_t *new_gid) const 262 { 263 hb_codepoint_t gid = glyph_map->get (old_gid); 264 if (gid == HB_MAP_VALUE_INVALID) 265 return false; 266 267 *new_gid = gid; 268 return true; 269 } 270 271 inline bool old_gid_for_new_gid (hb_codepoint_t new_gid, 272 hb_codepoint_t *old_gid) const 273 { 274 hb_codepoint_t gid = reverse_glyph_map->get (new_gid); 275 if (gid == HB_MAP_VALUE_INVALID) 276 return false; 277 278 *old_gid = gid; 279 return true; 280 } 281 282 inline bool 283 add_table (hb_tag_t tag, 284 hb_blob_t *contents) 285 { 286 if (HB_DEBUG_SUBSET) 287 { 288 hb_blob_t *source_blob = source->reference_table (tag); 289 DEBUG_MSG(SUBSET, nullptr, "add table %c%c%c%c, dest %u bytes, source %u bytes", 290 HB_UNTAG(tag), 291 hb_blob_get_length (contents), 292 hb_blob_get_length (source_blob)); 293 hb_blob_destroy (source_blob); 294 } 295 return hb_face_builder_add_table (dest, tag, contents); 296 } 297 }; 298 299 // hb-subset-plan implementation is split into multiple files to keep 300 // compile times more reasonable: 301 // - hb-subset-plan.cc 302 // - hb-subset-plan-layout.cc 303 // - hb-subset-plan-var.cc 304 // 305 // The functions below are those needed to connect the split files 306 // above together. 307 HB_INTERNAL void 308 remap_indexes (const hb_set_t *indexes, 309 hb_map_t *mapping /* OUT */); 310 311 312 #ifndef HB_NO_VAR 313 template<typename ItemVarStore> 314 HB_INTERNAL void 315 remap_variation_indices (const ItemVarStore &var_store, 316 const hb_set_t &variation_indices, 317 const hb_vector_t<int>& normalized_coords, 318 bool calculate_delta, /* not pinned at default */ 319 bool no_variations, /* all axes pinned */ 320 hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> &variation_idx_delta_map /* OUT */); 321 322 323 template<typename DeltaSetIndexMap> 324 HB_INTERNAL void 325 remap_colrv1_delta_set_index_indices (const DeltaSetIndexMap &index_map, 326 const hb_set_t &delta_set_idxes, 327 hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> &variation_idx_delta_map, /* IN/OUT */ 328 hb_map_t &new_deltaset_idx_varidx_map /* OUT */); 329 330 331 HB_INTERNAL void 332 generate_varstore_inner_maps (const hb_set_t& varidx_set, 333 unsigned subtable_count, 334 hb_vector_t<hb_inc_bimap_t> &inner_maps /* OUT */); 335 336 HB_INTERNAL bool 337 normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan); 338 339 HB_INTERNAL void 340 update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan); 341 342 HB_INTERNAL bool 343 get_instance_glyphs_contour_points (hb_subset_plan_t *plan); 344 345 #ifndef HB_NO_BASE 346 HB_INTERNAL void 347 collect_base_variation_indices (hb_subset_plan_t* plan); 348 #endif 349 #endif 350 351 #ifndef HB_NO_SUBSET_LAYOUT 352 typedef hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> script_langsys_map; 353 354 HB_INTERNAL void 355 remap_used_mark_sets (hb_subset_plan_t *plan, 356 hb_map_t& used_mark_sets_map); 357 358 HB_INTERNAL void 359 layout_nameid_closure (hb_subset_plan_t* plan, 360 hb_set_t* drop_tables); 361 362 HB_INTERNAL void 363 layout_populate_gids_to_retain (hb_subset_plan_t* plan, 364 hb_set_t* drop_tables); 365 366 HB_INTERNAL void 367 collect_layout_variation_indices (hb_subset_plan_t* plan); 368 #endif 369 370 371 #endif /* HB_SUBSET_PLAN_HH */