w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

hb-subset.cc
Go to the documentation of this file.
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, Rod Sheeter, Behdad Esfahbod
25  */
26 
27 #include "hb.hh"
28 #include "hb-open-type.hh"
29 
30 #include "hb-subset.hh"
31 
32 #include "hb-open-file.hh"
33 #include "hb-ot-cmap-table.hh"
34 #include "hb-ot-glyf-table.hh"
35 #include "hb-ot-hdmx-table.hh"
36 #include "hb-ot-head-table.hh"
37 #include "hb-ot-hhea-table.hh"
38 #include "hb-ot-hmtx-table.hh"
39 #include "hb-ot-maxp-table.hh"
42 #include "hb-ot-os2-table.hh"
43 #include "hb-ot-post-table.hh"
44 #include "hb-ot-cff1-table.hh"
45 #include "hb-ot-cff2-table.hh"
46 #include "hb-ot-vorg-table.hh"
47 #include "hb-ot-name-table.hh"
51 #include "hb-ot-var-gvar-table.hh"
52 #include "hb-ot-var-hvar-table.hh"
53 
54 
55 static unsigned
57 {
58  unsigned src_glyphs = plan->source->get_num_glyphs ();
59  unsigned dst_glyphs = plan->glyphset ()->get_population ();
60 
61  if (unlikely (!src_glyphs))
62  return 512 + table_len;
63 
64  return 512 + (unsigned) (table_len * sqrt ((double) dst_glyphs / src_glyphs));
65 }
66 
67 template<typename TableType>
68 static bool
70 {
71  bool result = false;
72  hb_blob_t *source_blob = hb_sanitize_context_t ().reference_table<TableType> (plan->source);
73  const TableType *table = source_blob->as<TableType> ();
74 
75  hb_tag_t tag = TableType::tableTag;
76  if (source_blob->data)
77  {
79  /* TODO Not all tables are glyph-related. 'name' table size for example should not be
80  * affected by number of glyphs. Accommodate that. */
81  unsigned buf_size = _plan_estimate_subset_table_size (plan, source_blob->length);
82  DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c initial estimated table size: %u bytes.", HB_UNTAG (tag), buf_size);
83  if (unlikely (!buf.alloc (buf_size)))
84  {
85  DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to allocate %u bytes.", HB_UNTAG (tag), buf_size);
86  hb_blob_destroy (source_blob);
87  return false;
88  }
89  retry:
90  hb_serialize_context_t serializer ((void *) buf, buf_size);
91  serializer.start_serialize<TableType> ();
92  hb_subset_context_t c (source_blob, plan, &serializer, tag);
93  bool needed = table->subset (&c);
94  if (serializer.ran_out_of_room)
95  {
96  buf_size += (buf_size >> 1) + 32;
97  DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c ran out of room; reallocating to %u bytes.", HB_UNTAG (tag), buf_size);
98  if (unlikely (!buf.alloc (buf_size)))
99  {
100  DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c failed to reallocate %u bytes.", HB_UNTAG (tag), buf_size);
101  hb_blob_destroy (source_blob);
102  return false;
103  }
104  goto retry;
105  }
106  serializer.end_serialize ();
107 
108  result = !serializer.in_error ();
109 
110  if (result)
111  {
112  if (needed)
113  {
114  hb_blob_t *dest_blob = serializer.copy_blob ();
115  DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c final subset table size: %u bytes.", HB_UNTAG (tag), dest_blob->length);
116  result = c.plan->add_table (tag, dest_blob);
117  hb_blob_destroy (dest_blob);
118  }
119  else
120  {
121  DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset table subsetted to empty.", HB_UNTAG (tag));
122  }
123  }
124  }
125  else
126  DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset sanitize failed on source table.", HB_UNTAG (tag));
127 
128  hb_blob_destroy (source_blob);
129  DEBUG_MSG (SUBSET, nullptr, "OT::%c%c%c%c::subset %s", HB_UNTAG (tag), result ? "success" : "FAILED!");
130  return result;
131 }
132 
133 static bool
135 {
136  hb_tag_t table_tags[32];
137  unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
138  while ((hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables))
139  {
140  for (unsigned i = 0; i < num_tables; ++i)
141  if (table_tags[i] == tag)
142  return true;
143  offset += num_tables;
144  }
145  return false;
146 }
147 
148 static bool
150 {
151  if (plan->drop_tables->has (tag))
152  return true;
153 
154  switch (tag)
155  {
156  case HB_TAG ('c','v','a','r'): /* hint table, fallthrough */
157  case HB_TAG ('c','v','t',' '): /* hint table, fallthrough */
158  case HB_TAG ('f','p','g','m'): /* hint table, fallthrough */
159  case HB_TAG ('p','r','e','p'): /* hint table, fallthrough */
160  case HB_TAG ('h','d','m','x'): /* hint table, fallthrough */
161  case HB_TAG ('V','D','M','X'): /* hint table, fallthrough */
162  return plan->drop_hints;
163 
164 #ifdef HB_NO_SUBSET_LAYOUT
165  // Drop Layout Tables if requested.
166  case HB_OT_TAG_GDEF:
167  case HB_OT_TAG_GPOS:
168  case HB_OT_TAG_GSUB:
169  case HB_TAG ('m','o','r','x'):
170  case HB_TAG ('m','o','r','t'):
171  case HB_TAG ('k','e','r','x'):
172  case HB_TAG ('k','e','r','n'):
173  return true;
174 #endif
175 
176  default:
177  return false;
178  }
179 }
180 
181 static bool
183 {
184  DEBUG_MSG (SUBSET, nullptr, "subset %c%c%c%c", HB_UNTAG (tag));
185  switch (tag)
186  {
187  case HB_OT_TAG_glyf: return _subset<const OT::glyf> (plan);
188  case HB_OT_TAG_hdmx: return _subset<const OT::hdmx> (plan);
189  case HB_OT_TAG_name: return _subset<const OT::name> (plan);
190  case HB_OT_TAG_head:
192  return true; /* skip head, handled by glyf */
193  return _subset<const OT::head> (plan);
194  case HB_OT_TAG_hhea: return true; /* skip hhea, handled by hmtx */
195  case HB_OT_TAG_hmtx: return _subset<const OT::hmtx> (plan);
196  case HB_OT_TAG_vhea: return true; /* skip vhea, handled by vmtx */
197  case HB_OT_TAG_vmtx: return _subset<const OT::vmtx> (plan);
198  case HB_OT_TAG_maxp: return _subset<const OT::maxp> (plan);
199  case HB_OT_TAG_sbix: return _subset<const OT::sbix> (plan);
200  case HB_OT_TAG_loca: return true; /* skip loca, handled by glyf */
201  case HB_OT_TAG_cmap: return _subset<const OT::cmap> (plan);
202  case HB_OT_TAG_OS2 : return _subset<const OT::OS2 > (plan);
203  case HB_OT_TAG_post: return _subset<const OT::post> (plan);
204  case HB_OT_TAG_COLR: return _subset<const OT::COLR> (plan);
205  case HB_OT_TAG_CBLC: return _subset<const OT::CBLC> (plan);
206  case HB_OT_TAG_CBDT: return true; /* skip CBDT, handled by CBLC */
207 
208 #ifndef HB_NO_SUBSET_CFF
209  case HB_OT_TAG_cff1: return _subset<const OT::cff1> (plan);
210  case HB_OT_TAG_cff2: return _subset<const OT::cff2> (plan);
211  case HB_OT_TAG_VORG: return _subset<const OT::VORG> (plan);
212 #endif
213 
214 #ifndef HB_NO_SUBSET_LAYOUT
215  case HB_OT_TAG_GDEF: return _subset<const OT::GDEF> (plan);
216  case HB_OT_TAG_GSUB: return _subset<const OT::GSUB> (plan);
217  case HB_OT_TAG_GPOS: return _subset<const OT::GPOS> (plan);
218  case HB_OT_TAG_gvar: return _subset<const OT::gvar> (plan);
219  case HB_OT_TAG_HVAR: return _subset<const OT::HVAR> (plan);
220  case HB_OT_TAG_VVAR: return _subset<const OT::VVAR> (plan);
221 #endif
222 
223  default:
224  hb_blob_t *source_table = hb_face_reference_table (plan->source, tag);
225  bool result = plan->add_table (tag, source_table);
226  hb_blob_destroy (source_table);
227  return result;
228  }
229 }
230 
231 /**
232  * hb_subset:
233  * @source: font face data to be subset.
234  * @input: input to use for the subsetting.
235  *
236  * Subsets a font according to provided input.
237  **/
238 hb_face_t *
240 {
241  if (unlikely (!input || !source)) return hb_face_get_empty ();
242 
244  if (unlikely (plan->in_error ()))
245  return hb_face_get_empty ();
246 
247  hb_set_t tags_set;
248  bool success = true;
249  hb_tag_t table_tags[32];
250  unsigned offset = 0, num_tables = ARRAY_LENGTH (table_tags);
251  while ((hb_face_get_table_tags (source, offset, &num_tables, table_tags), num_tables))
252  {
253  for (unsigned i = 0; i < num_tables; ++i)
254  {
256  if (_should_drop_table (plan, tag) && !tags_set.has (tag)) continue;
257  tags_set.add (tag);
258  success = _subset_table (plan, tag);
259  if (unlikely (!success)) goto end;
260  }
261  offset += num_tables;
262  }
263 end:
264 
265  hb_face_t *result = success ? hb_face_reference (plan->dest) : hb_face_get_empty ();
266 
267  hb_subset_plan_destroy (plan);
268  return result;
269 }
#define ARRAY_LENGTH(__array)
Definition: cairoint.h:137
double sqrt()
#define c(n)
Definition: gpos-common.c:150
#define unlikely(x)
Definition: jbig2arith.cc:116
small capitals from c petite p scientific i
Definition: afcover.h:80
#define buf
#define buf_size
Definition: ctangleboot.c:104
static int offset
Definition: ppmtogif.c:642
void hb_blob_destroy(hb_blob_t *blob)
Definition: hb-blob.cc:226
#define HB_UNTAG(tag)
Definition: hb-common.h:163
#define HB_TAG(c1, c2, c3, c4)
Definition: hb-common.h:155
uint32_t hb_tag_t
Definition: hb-common.h:147
#define DEBUG_MSG(WHAT, OBJ,...)
Definition: hb-debug.hh:232
hb_face_t * hb_face_get_empty()
Definition: hb-face.cc:243
unsigned int hb_face_get_table_tags(const hb_face_t *face, unsigned int start_offset, unsigned int *table_count, hb_tag_t *table_tags)
Definition: hb-face.cc:540
hb_face_t * hb_face_reference(hb_face_t *face)
Definition: hb-face.cc:260
hb_blob_t * hb_face_reference_table(const hb_face_t *face, hb_tag_t tag)
Definition: hb-face.cc:387
#define HB_OT_TAG_cff1
#define HB_OT_TAG_cff2
#define HB_OT_TAG_cmap
#define HB_OT_TAG_CBDT
#define HB_OT_TAG_CBLC
#define HB_OT_TAG_COLR
#define HB_OT_TAG_sbix
#define HB_OT_TAG_glyf
#define HB_OT_TAG_loca
#define HB_OT_TAG_hdmx
#define HB_OT_TAG_head
#define HB_OT_TAG_hhea
#define HB_OT_TAG_vhea
#define HB_OT_TAG_hmtx
#define HB_OT_TAG_vmtx
#define HB_OT_TAG_GDEF
Definition: hb-ot-layout.h:42
#define HB_OT_TAG_GPOS
Definition: hb-ot-layout.h:44
#define HB_OT_TAG_GSUB
Definition: hb-ot-layout.h:43
static const hb_tag_t table_tags[2]
Definition: hb-ot-map.hh:40
#define HB_OT_TAG_maxp
#define HB_OT_TAG_name
#define HB_OT_TAG_OS2
#define HB_OT_TAG_post
#define HB_OT_TAG_gvar
#define HB_OT_TAG_VVAR
#define HB_OT_TAG_HVAR
#define HB_OT_TAG_VORG
hb_subset_plan_t * hb_subset_plan_create(hb_face_t *face, hb_subset_input_t *input)
void hb_subset_plan_destroy(hb_subset_plan_t *plan)
hb_face_t * hb_subset(hb_face_t *source, hb_subset_input_t *input)
Definition: hb-subset.cc:239
static unsigned _plan_estimate_subset_table_size(hb_subset_plan_t *plan, unsigned table_len)
Definition: hb-subset.cc:56
static bool _is_table_present(hb_face_t *source, hb_tag_t tag)
Definition: hb-subset.cc:134
static bool _should_drop_table(hb_subset_plan_t *plan, hb_tag_t tag)
Definition: hb-subset.cc:149
static bool _subset_table(hb_subset_plan_t *plan, hb_tag_t tag)
Definition: hb-subset.cc:182
static bool _subset(hb_subset_plan_t *plan)
Definition: hb-subset.cc:69
const Type * as() const
Definition: hb-blob.hh:59
unsigned int length
Definition: hb-blob.hh:65
const char * data
Definition: hb-blob.hh:64
unsigned int get_num_glyphs() const
Definition: hb-face.hh:94
hb_blob_t * reference_table(const hb_face_t *face, hb_tag_t tableTag=Type::tableTag)
Definition: hb-sanitize.hh:382
hb_blob_t * copy_blob() const
void add(hb_codepoint_t g)
Definition: hb-set.hh:284
bool has(hb_codepoint_t k) const
Definition: hb-set.hh:448
unsigned int get_population() const
Definition: hb-set.hh:776
hb_set_t * drop_tables
bool in_error() const
bool add_table(hb_tag_t tag, hb_blob_t *contents)
const hb_set_t * glyphset() const
hb_face_t * source
hb_face_t * dest
Definition: execute.c:108
Definition: sh.h:1345
Definition: table.h:30
Definition: xmlparse.c:179
#define end(cp)
Definition: zic.c:71