QtBase  v6.3.1
hb-ot-cff2-table.hh
Go to the documentation of this file.
1 /*
2  * Copyright © 2018 Adobe 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  * Adobe Author(s): Michiharu Ariza
25  */
26 
27 #ifndef HB_OT_CFF2_TABLE_HH
28 #define HB_OT_CFF2_TABLE_HH
29 
30 #include "hb-ot-cff-common.hh"
31 #include "hb-subset-cff2.hh"
32 #include "hb-draw.hh"
33 
34 namespace CFF {
35 
36 /*
37  * CFF2 -- Compact Font Format (CFF) Version 2
38  * https://docs.microsoft.com/en-us/typography/opentype/spec/cff2
39  */
40 #define HB_OT_TAG_cff2 HB_TAG('C','F','F','2')
41 
43 template <typename Type> struct CFF2IndexOf : CFFIndexOf<HBUINT32, Type> {};
44 
47 
50 
52 {
53  bool serialize (hb_serialize_context_t *c, const CFF2FDSelect &src, unsigned int num_glyphs)
54  {
55  TRACE_SERIALIZE (this);
56  unsigned int size = src.get_size (num_glyphs);
57  CFF2FDSelect *dest = c->allocate_size<CFF2FDSelect> (size);
58  if (unlikely (!dest)) return_trace (false);
59  memcpy (dest, &src, size);
60  return_trace (true);
61  }
62 
63  unsigned int get_size (unsigned int num_glyphs) const
64  {
65  switch (format)
66  {
67  case 0: return format.static_size + u.format0.get_size (num_glyphs);
68  case 3: return format.static_size + u.format3.get_size ();
69  case 4: return format.static_size + u.format4.get_size ();
70  default:return 0;
71  }
72  }
73 
75  {
76  if (this == &Null (CFF2FDSelect))
77  return 0;
78 
79  switch (format)
80  {
81  case 0: return u.format0.get_fd (glyph);
82  case 3: return u.format3.get_fd (glyph);
83  case 4: return u.format4.get_fd (glyph);
84  default:return 0;
85  }
86  }
87 
88  bool sanitize (hb_sanitize_context_t *c, unsigned int fdcount) const
89  {
90  TRACE_SANITIZE (this);
91  if (unlikely (!c->check_struct (this)))
92  return_trace (false);
93 
94  switch (format)
95  {
96  case 0: return_trace (u.format0.sanitize (c, fdcount));
97  case 3: return_trace (u.format3.sanitize (c, fdcount));
98  case 4: return_trace (u.format4.sanitize (c, fdcount));
99  default:return_trace (false);
100  }
101  }
102 
104  union {
108  } u;
109  public:
111 };
112 
114 {
116  {
117  TRACE_SANITIZE (this);
118  return_trace (likely (c->check_struct (this)) && c->check_range (&varStore, size) && varStore.sanitize (c));
119  }
120 
122  {
123  TRACE_SERIALIZE (this);
124  unsigned int size_ = varStore->get_size ();
125  CFF2VariationStore *dest = c->allocate_size<CFF2VariationStore> (size_);
126  if (unlikely (!dest)) return_trace (false);
127  memcpy (dest, varStore, size_);
128  return_trace (true);
129  }
130 
131  unsigned int get_size () const { return HBUINT16::static_size + size; }
132 
135 
136  DEFINE_SIZE_MIN (2 + VariationStore::min_size);
137 };
138 
140 {
141  void init ()
142  {
144  vstoreOffset = 0;
145  FDSelectOffset = 0;
146  }
148 
149  unsigned int vstoreOffset;
150  unsigned int FDSelectOffset;
151 };
152 
154 {
156  {
157  switch (op) {
158  case OpCode_FontMatrix:
159  {
160  dict_val_t val;
161  val.init ();
162  dictval.add_op (op, env.str_ref);
163  env.clear_args ();
164  }
165  break;
166 
167  case OpCode_vstore:
168  dictval.vstoreOffset = env.argStack.pop_uint ();
169  env.clear_args ();
170  break;
171  case OpCode_FDSelect:
172  dictval.FDSelectOffset = env.argStack.pop_uint ();
173  env.clear_args ();
174  break;
175 
176  default:
177  SUPER::process_op (op, env, dictval);
178  /* Record this operand below if stack is empty, otherwise done */
179  if (!env.argStack.is_empty ()) return;
180  }
181 
182  if (unlikely (env.in_error ())) return;
183 
184  dictval.add_op (op, env.str_ref);
185  }
186 
188 };
189 
191 {
192  void init ()
193  {
196  }
198 
200 };
201 
203 {
205  {
206  switch (op) {
207  case OpCode_Private:
208  dictval.privateDictInfo.offset = env.argStack.pop_uint ();
209  dictval.privateDictInfo.size = env.argStack.pop_uint ();
210  env.clear_args ();
211  break;
212 
213  default:
214  SUPER::process_op (op, env);
215  if (!env.argStack.is_empty ())
216  return;
217  }
218 
219  if (unlikely (env.in_error ())) return;
220 
221  dictval.add_op (op, env.str_ref);
222  }
223 
224  private:
225  typedef dict_opset_t SUPER;
226 };
227 
228 template <typename VAL>
230 {
231  void init ()
232  {
234  subrsOffset = 0;
236  ivs = 0;
237  }
239 
240  unsigned int subrsOffset;
242  unsigned int ivs;
243 };
244 
247 
249 {
250  void init (const byte_str_t &str)
251  {
253  ivs = 0;
254  seen_vsindex = false;
255  }
256 
258  {
259  if (likely (!seen_vsindex))
260  {
261  set_ivs (argStack.pop_uint ());
262  }
263  seen_vsindex = true;
264  }
265 
266  unsigned int get_ivs () const { return ivs; }
267  void set_ivs (unsigned int ivs_) { ivs = ivs_; }
268 
269  protected:
270  unsigned int ivs;
272 };
273 
275 {
277  {
279  val.init ();
280 
281  switch (op) {
282  case OpCode_StdHW:
283  case OpCode_StdVW:
284  case OpCode_BlueScale:
285  case OpCode_BlueShift:
286  case OpCode_BlueFuzz:
289  val.single_val = env.argStack.pop_num ();
290  env.clear_args ();
291  break;
292  case OpCode_BlueValues:
293  case OpCode_OtherBlues:
294  case OpCode_FamilyBlues:
296  case OpCode_StemSnapH:
297  case OpCode_StemSnapV:
298  env.clear_args ();
299  break;
300  case OpCode_Subrs:
301  dictval.subrsOffset = env.argStack.pop_uint ();
302  env.clear_args ();
303  break;
304  case OpCode_vsindexdict:
305  env.process_vsindex ();
306  dictval.ivs = env.get_ivs ();
307  env.clear_args ();
308  break;
309  case OpCode_blenddict:
310  break;
311 
312  default:
314  if (!env.argStack.is_empty ()) return;
315  break;
316  }
317 
318  if (unlikely (env.in_error ())) return;
319 
320  dictval.add_op (op, env.str_ref, val);
321  }
322 };
323 
325 {
327  {
328  switch (op) {
329  case OpCode_BlueValues:
330  case OpCode_OtherBlues:
331  case OpCode_FamilyBlues:
333  case OpCode_StdHW:
334  case OpCode_StdVW:
335  case OpCode_BlueScale:
336  case OpCode_BlueShift:
337  case OpCode_BlueFuzz:
338  case OpCode_StemSnapH:
339  case OpCode_StemSnapV:
342  env.clear_args ();
343  break;
344 
345  case OpCode_blenddict:
346  env.clear_args ();
347  return;
348 
349  case OpCode_Subrs:
350  dictval.subrsOffset = env.argStack.pop_uint ();
351  env.clear_args ();
352  break;
353 
354  default:
355  SUPER::process_op (op, env);
356  if (!env.argStack.is_empty ()) return;
357  break;
358  }
359 
360  if (unlikely (env.in_error ())) return;
361 
362  dictval.add_op (op, env.str_ref);
363  }
364 
365  private:
366  typedef dict_opset_t SUPER;
367 };
368 
371 
372 struct CFF2FDArray : FDArray<HBUINT32>
373 {
374  /* FDArray::serialize does not compile without this partial specialization */
375  template <typename ITER, typename OP_SERIALIZER>
376  bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr)
378 };
379 
380 } /* namespace CFF */
381 
382 namespace OT {
383 
384 using namespace CFF;
385 
386 struct cff2
387 {
388  static constexpr hb_tag_t tableTag = HB_OT_TAG_cff2;
389 
391  {
392  TRACE_SANITIZE (this);
393  return_trace (c->check_struct (this) &&
394  likely (version.major == 2));
395  }
396 
397  template <typename PRIVOPSET, typename PRIVDICTVAL>
399  {
401  {
402  topDict.init ();
403  fontDicts.init ();
404  privateDicts.init ();
405 
406  this->blob = sc.reference_table<cff2> (face);
407 
408  /* setup for run-time santization */
409  sc.init (this->blob);
410  sc.start_processing ();
411 
412  const OT::cff2 *cff2 = this->blob->template as<OT::cff2> ();
413 
414  if (cff2 == &Null (OT::cff2))
415  goto fail;
416 
417  { /* parse top dict */
418  byte_str_t topDictStr (cff2 + cff2->topDict, cff2->topDictSize);
419  if (unlikely (!topDictStr.sanitize (&sc))) goto fail;
420  cff2_top_dict_interpreter_t top_interp;
421  top_interp.env.init (topDictStr);
422  topDict.init ();
423  if (unlikely (!top_interp.interpret (topDict))) goto fail;
424  }
425 
426  globalSubrs = &StructAtOffset<CFF2Subrs> (cff2, cff2->topDict + cff2->topDictSize);
427  varStore = &StructAtOffsetOrNull<CFF2VariationStore> (cff2, topDict.vstoreOffset);
428  charStrings = &StructAtOffsetOrNull<CFF2CharStrings> (cff2, topDict.charStringsOffset);
429  fdArray = &StructAtOffsetOrNull<CFF2FDArray> (cff2, topDict.FDArrayOffset);
430  fdSelect = &StructAtOffsetOrNull<CFF2FDSelect> (cff2, topDict.FDSelectOffset);
431 
432  if (((varStore != &Null (CFF2VariationStore)) && unlikely (!varStore->sanitize (&sc))) ||
433  (charStrings == &Null (CFF2CharStrings)) || unlikely (!charStrings->sanitize (&sc)) ||
434  (globalSubrs == &Null (CFF2Subrs)) || unlikely (!globalSubrs->sanitize (&sc)) ||
435  (fdArray == &Null (CFF2FDArray)) || unlikely (!fdArray->sanitize (&sc)) ||
436  (((fdSelect != &Null (CFF2FDSelect)) && unlikely (!fdSelect->sanitize (&sc, fdArray->count)))))
437  goto fail;
438 
439  num_glyphs = charStrings->count;
440  if (num_glyphs != sc.get_num_glyphs ())
441  goto fail;
442 
443  fdCount = fdArray->count;
444  if (!privateDicts.resize (fdCount))
445  goto fail;
446 
447  /* parse font dicts and gather private dicts */
448  for (unsigned int i = 0; i < fdCount; i++)
449  {
450  const byte_str_t fontDictStr = (*fdArray)[i];
451  if (unlikely (!fontDictStr.sanitize (&sc))) goto fail;
453  cff2_font_dict_interpreter_t font_interp;
454  font_interp.env.init (fontDictStr);
455  font = fontDicts.push ();
456  if (unlikely (font == &Crap (cff2_font_dict_values_t))) goto fail;
457  font->init ();
458  if (unlikely (!font_interp.interpret (*font))) goto fail;
459 
460  const byte_str_t privDictStr (StructAtOffsetOrNull<UnsizedByteStr> (cff2, font->privateDictInfo.offset), font->privateDictInfo.size);
461  if (unlikely (!privDictStr.sanitize (&sc))) goto fail;
463  priv_interp.env.init(privDictStr);
464  privateDicts[i].init ();
465  if (unlikely (!priv_interp.interpret (privateDicts[i]))) goto fail;
466 
467  privateDicts[i].localSubrs = &StructAtOffsetOrNull<CFF2Subrs> (&privDictStr[0], privateDicts[i].subrsOffset);
468  if (privateDicts[i].localSubrs != &Null (CFF2Subrs) &&
469  unlikely (!privateDicts[i].localSubrs->sanitize (&sc)))
470  goto fail;
471  }
472 
473 
474  return;
475 
476  fail:
477  _fini ();
478  }
479  ~accelerator_templ_t () { _fini (); }
480  void _fini ()
481  {
482  sc.end_processing ();
483  topDict.fini ();
484  fontDicts.fini ();
485  privateDicts.fini ();
486  hb_blob_destroy (blob);
487  blob = nullptr;
488  }
489 
490  bool is_valid () const { return blob; }
491 
492  protected:
493  hb_blob_t *blob = nullptr;
495 
496  public:
498  const CFF2Subrs *globalSubrs = nullptr;
499  const CFF2VariationStore *varStore = nullptr;
500  const CFF2CharStrings *charStrings = nullptr;
501  const CFF2FDArray *fdArray = nullptr;
502  const CFF2FDSelect *fdSelect = nullptr;
503  unsigned int fdCount = 0;
504 
507 
508  unsigned int num_glyphs = 0;
509  };
510 
511  struct accelerator_t : accelerator_templ_t<cff2_private_dict_opset_t, cff2_private_dict_values_t>
512  {
514 
515  HB_INTERNAL bool get_extents (hb_font_t *font,
516  hb_codepoint_t glyph,
517  hb_glyph_extents_t *extents) const;
518  HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const;
519  };
520 
522 
523  bool subset (hb_subset_context_t *c) const { return hb_subset_cff2 (c); }
524 
525  public:
526  FixedVersion<HBUINT8> version; /* Version of CFF2 table. set to 0x0200u */
527  NNOffsetTo<TopDict, HBUINT8> topDict; /* headerSize = Offset to Top DICT. */
528  HBUINT16 topDictSize; /* Top DICT size */
529 
530  public:
532 };
533 
536 };
537 
538 } /* namespace OT */
539 
540 #endif /* HB_OT_CFF2_TABLE_HH */
small capitals from c petite p scientific i
[1]
Definition: afcover.h:80
QString str
[2]
void hb_blob_destroy(hb_blob_t *blob)
Definition: hb-blob.cc:262
#define OpCode_BlueShift
#define OpCode_BlueValues
#define OpCode_FontMatrix
#define OpCode_StemSnapH
#define OpCode_BlueFuzz
#define OpCode_StemSnapV
#define OpCode_vsindexdict
#define OpCode_ExpansionFactor
#define OpCode_FDSelect
#define OpCode_StdVW
#define OpCode_vstore
#define OpCode_LanguageGroup
#define OpCode_Private
#define OpCode_FamilyOtherBlues
#define OpCode_blenddict
#define OpCode_StdHW
#define OpCode_FamilyBlues
#define OpCode_BlueScale
#define OpCode_Subrs
#define OpCode_OtherBlues
#define TRACE_SERIALIZE(this)
Definition: hb-debug.hh:426
#define TRACE_SANITIZE(this)
Definition: hb-debug.hh:414
#define return_trace(RET)
Definition: hb-debug.hh:349
#define Crap(Type)
Definition: hb-null.hh:159
#define HB_OT_TAG_cff2
bool hb_subset_cff2(hb_subset_context_t *c)
#define likely(expr)
Definition: hb.hh:250
#define unlikely(expr)
Definition: hb.hh:251
#define HB_INTERNAL
Definition: hb.hh:274
FDSelect3_4_Range< HBUINT32, HBUINT16 > FDSelect4_Range
CFF2Index CFF2CharStrings
cff2_private_dict_values_base_t< op_str_t > cff2_private_dict_values_subset_t
dict_interpreter_t< cff2_top_dict_opset_t, cff2_top_dict_values_t > cff2_top_dict_interpreter_t
CFFIndex< HBUINT32 > CFF2Index
dict_interpreter_t< cff2_font_dict_opset_t, cff2_font_dict_values_t > cff2_font_dict_interpreter_t
unsigned int op_code_t
FDSelect3_4< HBUINT32, HBUINT16 > FDSelect4
cff2_private_dict_values_base_t< num_dict_val_t > cff2_private_dict_values_t
Subrs< HBUINT32 > CFF2Subrs
set set set set set set set macro pixldst1 op
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum face
GLenum src
GLint GLsizei GLsizei GLenum format
const GLubyte * c
Definition: qopenglext.h:12701
GLuint GLfloat * val
Definition: qopenglext.h:1513
uint32_t hb_codepoint_t
Definition: hb-common.h:106
uint32_t hb_tag_t
Definition: hb-common.h:157
QStringList::Iterator it
bool serialize(hb_serialize_context_t *c, ITER it, OP_SERIALIZER &opszr)
bool sanitize(hb_sanitize_context_t *c, unsigned int fdcount) const
union CFF::CFF2FDSelect::@148 u
hb_codepoint_t get_fd(hb_codepoint_t glyph) const
unsigned int get_size(unsigned int num_glyphs) const
bool serialize(hb_serialize_context_t *c, const CFF2FDSelect &src, unsigned int num_glyphs)
unsigned int get_size() const
bool sanitize(hb_sanitize_context_t *c) const
DEFINE_SIZE_MIN(2+VariationStore::min_size)
bool serialize(hb_serialize_context_t *c, const CFF2VariationStore *varStore)
static void process_op(op_code_t op, num_interp_env_t &env, cff2_font_dict_values_t &dictval)
void init(const byte_str_t &str)
void set_ivs(unsigned int ivs_)
static void process_op(op_code_t op, cff2_priv_dict_interp_env_t &env, cff2_private_dict_values_subset_t &dictval)
static void process_op(op_code_t op, cff2_priv_dict_interp_env_t &env, cff2_private_dict_values_t &dictval)
static void process_op(op_code_t op, num_interp_env_t &env, cff2_top_dict_values_t &dictval)
static void process_op(op_code_t op, interp_env_t< number_t > &env)
void init(const byte_str_t &str_)
arg_stack_t< ARG > argStack
void add_op(op_code_t op, const byte_str_ref_t &str_ref=byte_str_ref_t())
static void process_op(op_code_t op, interp_env_t< number_t > &env, top_dict_values_t< VAL > &dictval)
Definition: hb-null.hh:93
bool sanitize(hb_sanitize_context_t *c) const
accelerator_t(hb_face_t *face)
hb_vector_t< cff2_font_dict_values_t > fontDicts
hb_vector_t< PRIVDICTVAL > privateDicts
cff2_top_dict_values_t topDict
cff2_accelerator_t(hb_face_t *face)
bool sanitize(hb_sanitize_context_t *c) const
HBUINT16 topDictSize
bool subset(hb_subset_context_t *c) const
DEFINE_SIZE_STATIC(5)
static constexpr hb_tag_t tableTag
NNOffsetTo< TopDict, HBUINT8 > topDict
accelerator_templ_t< cff2_private_dict_opset_subset_t, cff2_private_dict_values_subset_t > accelerator_subset_t
FixedVersion< HBUINT8 > version
bool sanitize(hb_sanitize_context_t *c) const
Definition: hb-array.hh:282