Coverage Report

Created: 2025-07-07 10:01

/work/workdir/UnpackedTarball/harfbuzz/src/hb-subset-plan.hh
Line
Count
Source (jump to first uncovered line)
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
0
      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
0
  { flag = 0; x = x_; y = y_; is_end_point = is_end_point_; }
81
82
  void transform (const float (&matrix)[4])
83
0
  {
84
0
    float x_ = x * matrix[0] + y * matrix[2];
85
0
    y  = x * matrix[1] + y * matrix[3];
86
0
    x  = x_;
87
0
  }
88
89
  void add_delta (float delta_x, float delta_y)
90
0
  {
91
0
    x += delta_x;
92
0
    y += delta_y;
93
0
  }
94
95
  HB_ALWAYS_INLINE
96
0
  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
0
  {
110
0
    if (indices.length != deltas_x.length ||
111
0
        indices.length != deltas_y.length)
112
0
      return false;
113
0
114
0
    for (unsigned i = 0; i < indices.length; i++)
115
0
    {
116
0
      if (!indices.arrayZ[i]) continue;
117
0
      arrayZ[i].add_delta (deltas_x.arrayZ[i], deltas_y.arrayZ[i]);
118
0
    }
119
0
    return true;
120
0
  }
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
0
  bool in_error () const { return !successful; }
214
215
  bool check_success(bool success)
216
0
  {
217
0
    successful = (successful && success);
218
0
    return successful;
219
0
  }
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
0
  {
229
0
    return &_glyphset;
230
0
  }
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
0
  {
238
0
    return &_glyphset_gsub;
239
0
  }
240
241
  /*
242
   * The total number of output glyphs in the final subset.
243
   */
244
  inline unsigned int
245
  num_output_glyphs () const
246
0
  {
247
0
    return _num_output_glyphs;
248
0
  }
249
250
  inline bool new_gid_for_codepoint (hb_codepoint_t codepoint,
251
             hb_codepoint_t *new_gid) const
252
0
  {
253
0
    hb_codepoint_t old_gid = codepoint_to_glyph->get (codepoint);
254
0
    if (old_gid == HB_MAP_VALUE_INVALID)
255
0
      return false;
256
0
257
0
    return new_gid_for_old_gid (old_gid, new_gid);
258
0
  }
259
260
  inline bool new_gid_for_old_gid (hb_codepoint_t old_gid,
261
           hb_codepoint_t *new_gid) const
262
0
  {
263
0
    hb_codepoint_t gid = glyph_map->get (old_gid);
264
0
    if (gid == HB_MAP_VALUE_INVALID)
265
0
      return false;
266
0
267
0
    *new_gid = gid;
268
0
    return true;
269
0
  }
270
271
  inline bool old_gid_for_new_gid (hb_codepoint_t  new_gid,
272
           hb_codepoint_t *old_gid) const
273
0
  {
274
0
    hb_codepoint_t gid = reverse_glyph_map->get (new_gid);
275
0
    if (gid == HB_MAP_VALUE_INVALID)
276
0
      return false;
277
0
278
0
    *old_gid = gid;
279
0
    return true;
280
0
  }
281
282
  inline bool
283
  add_table (hb_tag_t tag,
284
       hb_blob_t *contents)
285
0
  {
286
0
    if (HB_DEBUG_SUBSET)
287
0
    {
288
0
      hb_blob_t *source_blob = source->reference_table (tag);
289
0
      DEBUG_MSG(SUBSET, nullptr, "add table %c%c%c%c, dest %u bytes, source %u bytes",
290
0
    HB_UNTAG(tag),
291
0
    hb_blob_get_length (contents),
292
0
    hb_blob_get_length (source_blob));
293
0
      hb_blob_destroy (source_blob);
294
0
    }
295
0
    return hb_face_builder_add_table (dest, tag, contents);
296
0
  }
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
//
304
// The functions below are those needed to connect the split files
305
// above together.
306
HB_INTERNAL void
307
remap_indexes (const hb_set_t *indexes,
308
               hb_map_t       *mapping /* OUT */);
309
310
311
#ifndef HB_NO_VAR
312
template<typename ItemVarStore>
313
HB_INTERNAL void
314
remap_variation_indices (const ItemVarStore &var_store,
315
                         const hb_set_t &variation_indices,
316
                         const hb_vector_t<int>& normalized_coords,
317
                         bool calculate_delta, /* not pinned at default */
318
                         bool no_variations, /* all axes pinned */
319
                         hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> &variation_idx_delta_map /* OUT */);
320
321
322
template<typename DeltaSetIndexMap>
323
HB_INTERNAL void
324
remap_colrv1_delta_set_index_indices (const DeltaSetIndexMap &index_map,
325
                                      const hb_set_t &delta_set_idxes,
326
                                      hb_hashmap_t<unsigned, hb_pair_t<unsigned, int>> &variation_idx_delta_map, /* IN/OUT */
327
                                      hb_map_t &new_deltaset_idx_varidx_map /* OUT */);
328
329
330
HB_INTERNAL void
331
generate_varstore_inner_maps (const hb_set_t& varidx_set,
332
                              unsigned subtable_count,
333
                              hb_vector_t<hb_inc_bimap_t> &inner_maps /* OUT */);
334
335
HB_INTERNAL void
336
normalize_axes_location (hb_face_t *face, hb_subset_plan_t *plan);
337
338
HB_INTERNAL void
339
update_instance_metrics_map_from_cff2 (hb_subset_plan_t *plan);
340
341
HB_INTERNAL bool
342
get_instance_glyphs_contour_points (hb_subset_plan_t *plan);
343
344
#ifndef HB_NO_BASE
345
HB_INTERNAL void
346
collect_base_variation_indices (hb_subset_plan_t* plan);
347
#endif
348
#endif
349
350
#ifndef HB_NO_SUBSET_LAYOUT
351
typedef hb_hashmap_t<unsigned, hb::unique_ptr<hb_set_t>> script_langsys_map;
352
353
HB_INTERNAL void
354
remap_used_mark_sets (hb_subset_plan_t *plan,
355
                      hb_map_t& used_mark_sets_map);
356
357
HB_INTERNAL void
358
layout_nameid_closure (hb_subset_plan_t* plan,
359
                       hb_set_t* drop_tables);
360
361
HB_INTERNAL void
362
layout_populate_gids_to_retain (hb_subset_plan_t* plan,
363
                                hb_set_t* drop_tables);
364
365
HB_INTERNAL void
366
collect_layout_variation_indices (hb_subset_plan_t* plan);
367
#endif
368
369
370
#endif /* HB_SUBSET_PLAN_HH */