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-cff-common.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_SUBSET_CFF_COMMON_HH
28 #define HB_SUBSET_CFF_COMMON_HH
29 
30 #include "hb.hh"
31 
32 #include "hb-subset-plan.hh"
34 
35 namespace CFF {
36 
37 /* Used for writing a temporary charstring */
38 struct str_encoder_t
39 {
41  : buff (buff_), error (false) {}
42 
43  void reset () { buff.resize (0); }
44 
45  void encode_byte (unsigned char b)
46  {
47  if (unlikely (buff.push (b) == &Crap (unsigned char)))
48  set_error ();
49  }
50 
51  void encode_int (int v)
52  {
53  if ((-1131 <= v) && (v <= 1131))
54  {
55  if ((-107 <= v) && (v <= 107))
56  encode_byte (v + 139);
57  else if (v > 0)
58  {
59  v -= 108;
61  encode_byte (v & 0xFF);
62  }
63  else
64  {
65  v = -v - 108;
67  encode_byte (v & 0xFF);
68  }
69  }
70  else
71  {
72  if (unlikely (v < -32768))
73  v = -32768;
74  else if (unlikely (v > 32767))
75  v = 32767;
77  encode_byte ((v >> 8) & 0xFF);
78  encode_byte (v & 0xFF);
79  }
80  }
81 
82  void encode_num (const number_t& n)
83  {
84  if (n.in_int_range ())
85  {
86  encode_int (n.to_int ());
87  }
88  else
89  {
90  int32_t v = n.to_fixed ();
92  encode_byte ((v >> 24) & 0xFF);
93  encode_byte ((v >> 16) & 0xFF);
94  encode_byte ((v >> 8) & 0xFF);
95  encode_byte (v & 0xFF);
96  }
97  }
98 
100  {
101  if (Is_OpCode_ESC (op))
102  {
105  }
106  else
107  encode_byte (op);
108  }
109 
110  void copy_str (const byte_str_t &str)
111  {
112  unsigned int offset = buff.length;
113  if (unlikely (!buff.resize (offset + str.length)))
114  {
115  set_error ();
116  return;
117  }
118  if (unlikely (buff.length < offset + str.length))
119  {
120  set_error ();
121  return;
122  }
123  memcpy (&buff[offset], &str[0], str.length);
124  }
125 
126  bool is_error () const { return error; }
127 
128  protected:
129  void set_error () { error = true; }
130 
131  str_buff_t &buff;
132  bool error;
133 };
134 
135 struct cff_sub_table_info_t {
137  : fd_array_link (0),
139  {
140  fd_select.init ();
141  }
142 
146 };
147 
148 template <typename OPSTR=op_str_t>
149 struct cff_top_dict_op_serializer_t : op_serializer_t
150 {
152  const OPSTR &opstr,
153  const cff_sub_table_info_t &info) const
154  {
155  TRACE_SERIALIZE (this);
156 
157  switch (opstr.op)
158  {
159  case OpCode_CharStrings:
160  return_trace (FontDict::serialize_link4_op(c, opstr.op, info.char_strings_link, whence_t::Absolute));
161 
162  case OpCode_FDArray:
163  return_trace (FontDict::serialize_link4_op(c, opstr.op, info.fd_array_link, whence_t::Absolute));
164 
165  case OpCode_FDSelect:
166  return_trace (FontDict::serialize_link4_op(c, opstr.op, info.fd_select.link, whence_t::Absolute));
167 
168  default:
169  return_trace (copy_opstr (c, opstr));
170  }
171  return_trace (true);
172  }
173 };
174 
175 struct cff_font_dict_op_serializer_t : op_serializer_t
176 {
178  const op_str_t &opstr,
179  const table_info_t &privateDictInfo) const
180  {
181  TRACE_SERIALIZE (this);
182 
183  if (opstr.op == OpCode_Private)
184  {
185  /* serialize the private dict size & offset as 2-byte & 4-byte integers */
186  return_trace (UnsizedByteStr::serialize_int2 (c, privateDictInfo.size) &&
187  Dict::serialize_link4_op (c, opstr.op, privateDictInfo.link, whence_t::Absolute));
188  }
189  else
190  {
191  HBUINT8 *d = c->allocate_size<HBUINT8> (opstr.str.length);
192  if (unlikely (!d)) return_trace (false);
193  memcpy (d, &opstr.str[0], opstr.str.length);
194  }
195  return_trace (true);
196  }
197 };
198 
199 struct cff_private_dict_op_serializer_t : op_serializer_t
200 {
201  cff_private_dict_op_serializer_t (bool desubroutinize_, bool drop_hints_)
202  : desubroutinize (desubroutinize_), drop_hints (drop_hints_) {}
203 
205  const op_str_t &opstr,
206  objidx_t subrs_link) const
207  {
208  TRACE_SERIALIZE (this);
209 
210  if (drop_hints && dict_opset_t::is_hint_op (opstr.op))
211  return true;
212  if (opstr.op == OpCode_Subrs)
213  {
214  if (desubroutinize || !subrs_link)
215  return_trace (true);
216  else
217  return_trace (FontDict::serialize_link2_op (c, opstr.op, subrs_link));
218  }
219  else
220  return_trace (copy_opstr (c, opstr));
221  }
222 
223  protected:
224  const bool desubroutinize;
225  const bool drop_hints;
226 };
227 
228 struct flatten_param_t
229 {
231  bool drop_hints;
232 };
233 
234 template <typename ACC, typename ENV, typename OPSET, op_code_t endchar_op=OpCode_Invalid>
235 struct subr_flattener_t
236 {
237  subr_flattener_t (const ACC &acc_,
238  const hb_subset_plan_t *plan_)
239  : acc (acc_), plan (plan_) {}
240 
241  bool flatten (str_buff_vec_t &flat_charstrings)
242  {
243  if (!flat_charstrings.resize (plan->num_output_glyphs ()))
244  return false;
245  for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
246  flat_charstrings[i].init ();
247  for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
248  {
250  if (!plan->old_gid_for_new_gid (i, &glyph))
251  {
252  /* add an endchar only charstring for a missing glyph if CFF1 */
253  if (endchar_op != OpCode_Invalid) flat_charstrings[i].push (endchar_op);
254  continue;
255  }
256  const byte_str_t str = (*acc.charStrings)[glyph];
257  unsigned int fd = acc.fdSelect->get_fd (glyph);
258  if (unlikely (fd >= acc.fdCount))
259  return false;
261  interp.env.init (str, acc, fd);
262  flatten_param_t param = { flat_charstrings[i], plan->drop_hints };
263  if (unlikely (!interp.interpret (param)))
264  return false;
265  }
266  return true;
267  }
268 
269  const ACC &acc;
270  const hb_subset_plan_t *plan;
271 };
272 
273 struct subr_closures_t
274 {
276  { local_closures.init (); }
277 
278  void init (unsigned int fd_count)
279  {
280  valid = true;
283  valid = false;
284  if (!local_closures.resize (fd_count))
285  valid = false;
286 
287  for (unsigned int i = 0; i < local_closures.length; i++)
288  {
290  if (local_closures[i] == hb_set_get_empty ())
291  valid = false;
292  }
293  }
294 
295  void fini ()
296  {
298  for (unsigned int i = 0; i < local_closures.length; i++)
300  local_closures.fini ();
301  }
302 
303  void reset ()
304  {
306  for (unsigned int i = 0; i < local_closures.length; i++)
308  }
309 
310  bool is_valid () const { return valid; }
311  bool valid;
314 };
315 
316 struct parsed_cs_op_t : op_str_t
317 {
318  void init (unsigned int subr_num_ = 0)
319  {
320  op_str_t::init ();
321  subr_num = subr_num_;
322  drop_flag = false;
323  keep_flag = false;
324  skip_flag = false;
325  }
326 
327  void fini () { op_str_t::fini (); }
328 
329  bool for_drop () const { return drop_flag; }
330  void set_drop () { if (!for_keep ()) drop_flag = true; }
331 
332  bool for_keep () const { return keep_flag; }
333  void set_keep () { keep_flag = true; }
334 
335  bool for_skip () const { return skip_flag; }
336  void set_skip () { skip_flag = true; }
337 
338  unsigned int subr_num;
339 
340  protected:
341  bool drop_flag : 1;
342  bool keep_flag : 1;
343  bool skip_flag : 1;
344 };
345 
346 struct parsed_cs_str_t : parsed_values_t<parsed_cs_op_t>
347 {
348  void init ()
349  {
350  SUPER::init ();
351  parsed = false;
352  hint_dropped = false;
353  has_prefix_ = false;
354  }
355 
356  void add_op (op_code_t op, const byte_str_ref_t& str_ref)
357  {
358  if (!is_parsed ())
359  SUPER::add_op (op, str_ref);
360  }
361 
362  void add_call_op (op_code_t op, const byte_str_ref_t& str_ref, unsigned int subr_num)
363  {
364  if (!is_parsed ())
365  {
366  unsigned int parsed_len = get_count ();
367  if (likely (parsed_len > 0))
368  values[parsed_len-1].set_skip ();
369 
371  val.init (subr_num);
372  SUPER::add_op (op, str_ref, val);
373  }
374  }
375 
377  {
378  has_prefix_ = true;
379  prefix_op_ = op;
380  prefix_num_ = num;
381  }
382 
383  bool at_end (unsigned int pos) const
384  {
385  return ((pos + 1 >= values.length) /* CFF2 */
386  || (values[pos + 1].op == OpCode_return));
387  }
388 
389  bool is_parsed () const { return parsed; }
390  void set_parsed () { parsed = true; }
391 
392  bool is_hint_dropped () const { return hint_dropped; }
393  void set_hint_dropped () { hint_dropped = true; }
394 
395  bool is_vsindex_dropped () const { return vsindex_dropped; }
397 
398  bool has_prefix () const { return has_prefix_; }
399  op_code_t prefix_op () const { return prefix_op_; }
400  const number_t &prefix_num () const { return prefix_num_; }
401 
402  protected:
403  bool parsed;
404  bool hint_dropped;
405  bool vsindex_dropped;
406  bool has_prefix_;
409 
410  private:
412 };
413 
414 struct parsed_cs_str_vec_t : hb_vector_t<parsed_cs_str_t>
415 {
416  void init (unsigned int len_ = 0)
417  {
418  SUPER::init ();
419  if (unlikely (!resize (len_)))
420  return;
421  for (unsigned int i = 0; i < length; i++)
422  (*this)[i].init ();
423  }
424  void fini () { SUPER::fini_deep (); }
425 
426  private:
428 };
429 
430 struct subr_subset_param_t
431 {
432  void init (parsed_cs_str_t *parsed_charstring_,
433  parsed_cs_str_vec_t *parsed_global_subrs_, parsed_cs_str_vec_t *parsed_local_subrs_,
434  hb_set_t *global_closure_, hb_set_t *local_closure_,
435  bool drop_hints_)
436  {
437  parsed_charstring = parsed_charstring_;
439  parsed_global_subrs = parsed_global_subrs_;
440  parsed_local_subrs = parsed_local_subrs_;
441  global_closure = global_closure_;
442  local_closure = local_closure_;
443  drop_hints = drop_hints_;
444  }
445 
447  {
448  switch (context.type)
449  {
450  case CSType_CharString:
451  return parsed_charstring;
452 
453  case CSType_LocalSubr:
454  if (likely (context.subr_num < parsed_local_subrs->length))
455  return &(*parsed_local_subrs)[context.subr_num];
456  break;
457 
458  case CSType_GlobalSubr:
459  if (likely (context.subr_num < parsed_global_subrs->length))
460  return &(*parsed_global_subrs)[context.subr_num];
461  break;
462  }
463  return nullptr;
464  }
465 
466  template <typename ENV>
467  void set_current_str (ENV &env, bool calling)
468  {
469  parsed_cs_str_t *parsed_str = get_parsed_str_for_context (env.context);
470  if (unlikely (!parsed_str))
471  {
472  env.set_error ();
473  return;
474  }
475  /* If the called subroutine is parsed partially but not completely yet,
476  * it must be because we are calling it recursively.
477  * Handle it as an error. */
478  if (unlikely (calling && !parsed_str->is_parsed () && (parsed_str->values.length > 0)))
479  env.set_error ();
480  else
481  current_parsed_str = parsed_str;
482  }
483 
485 
491  bool drop_hints;
492 };
493 
494 struct subr_remap_t : hb_inc_bimap_t
495 {
497  {
498  /* create a remapping of subroutine numbers from old to new.
499  * no optimization based on usage counts. fonttools doesn't appear doing that either.
500  */
501 
503  while (hb_set_next (closure, &old_num))
504  add (old_num);
505 
506  if (get_population () < 1240)
507  bias = 107;
508  else if (get_population () < 33900)
509  bias = 1131;
510  else
511  bias = 32768;
512  }
513 
514  int biased_num (unsigned int old_num) const
515  {
516  hb_codepoint_t new_num = get (old_num);
517  return (int)new_num - bias;
518  }
519 
520  protected:
521  int bias;
522 };
523 
524 struct subr_remaps_t
525 {
527  {
528  global_remap.init ();
529  local_remaps.init ();
530  }
531 
532  ~subr_remaps_t () { fini (); }
533 
534  void init (unsigned int fdCount)
535  {
536  if (unlikely (!local_remaps.resize (fdCount))) return;
537  for (unsigned int i = 0; i < fdCount; i++)
538  local_remaps[i].init ();
539  }
540 
541  bool in_error()
542  {
543  return local_remaps.in_error ();
544  }
545 
546  void create (subr_closures_t& closures)
547  {
548  global_remap.create (closures.global_closure);
549  for (unsigned int i = 0; i < local_remaps.length; i++)
550  local_remaps[i].create (closures.local_closures[i]);
551  }
552 
553  void fini ()
554  {
555  global_remap.fini ();
556  local_remaps.fini_deep ();
557  }
558 
561 };
562 
563 template <typename SUBSETTER, typename SUBRS, typename ACC, typename ENV, typename OPSET, op_code_t endchar_op=OpCode_Invalid>
564 struct subr_subsetter_t
565 {
566  subr_subsetter_t (ACC &acc_, const hb_subset_plan_t *plan_)
567  : acc (acc_), plan (plan_)
568  {
571  parsed_local_subrs.init ();
572  }
573 
575  {
576  closures.fini ();
577  remaps.fini ();
580  parsed_local_subrs.fini_deep ();
581  }
582 
583  /* Subroutine subsetting with --no-desubroutinize runs in phases:
584  *
585  * 1. execute charstrings/subroutines to determine subroutine closures
586  * 2. parse out all operators and numbers
587  * 3. mark hint operators and operands for removal if --no-hinting
588  * 4. re-encode all charstrings and subroutines with new subroutine numbers
589  *
590  * Phases #1 and #2 are done at the same time in collect_subrs ().
591  * Phase #3 walks charstrings/subroutines forward then backward (hence parsing required),
592  * because we can't tell if a number belongs to a hint op until we see the first moveto.
593  *
594  * Assumption: a callsubr/callgsubr operator must immediately follow a (biased) subroutine number
595  * within the same charstring/subroutine, e.g., not split across a charstring and a subroutine.
596  */
597  bool subset (void)
598  {
599  closures.init (acc.fdCount);
600  remaps.init (acc.fdCount);
601 
603  parsed_global_subrs.init (acc.globalSubrs->count);
604 
605  if (unlikely (remaps.in_error()
607  || parsed_global_subrs.in_error ())) {
608  return false;
609  }
610 
611  if (unlikely (!parsed_local_subrs.resize (acc.fdCount))) return false;
612 
613  for (unsigned int i = 0; i < acc.fdCount; i++)
614  {
615  parsed_local_subrs[i].init (acc.privateDicts[i].localSubrs->count);
616  if (unlikely (parsed_local_subrs[i].in_error ())) return false;
617  }
618  if (unlikely (!closures.valid))
619  return false;
620 
621  /* phase 1 & 2 */
622  for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
623  {
625  if (!plan->old_gid_for_new_gid (i, &glyph))
626  continue;
627  const byte_str_t str = (*acc.charStrings)[glyph];
628  unsigned int fd = acc.fdSelect->get_fd (glyph);
629  if (unlikely (fd >= acc.fdCount))
630  return false;
631 
633  interp.env.init (str, acc, fd);
634 
636  param.init (&parsed_charstrings[i],
639  plan->drop_hints);
640 
641  if (unlikely (!interp.interpret (param)))
642  return false;
643 
644  /* complete parsed string esp. copy CFF1 width or CFF2 vsindex to the parsed charstring for encoding */
645  SUBSETTER::complete_parsed_str (interp.env, param, parsed_charstrings[i]);
646  }
647 
648  if (plan->drop_hints)
649  {
650  /* mark hint ops and arguments for drop */
651  for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
652  {
654  if (!plan->old_gid_for_new_gid (i, &glyph))
655  continue;
656  unsigned int fd = acc.fdSelect->get_fd (glyph);
657  if (unlikely (fd >= acc.fdCount))
658  return false;
660  param.init (&parsed_charstrings[i],
663  plan->drop_hints);
664 
665  drop_hints_param_t drop;
667  {
668  parsed_charstrings[i].set_hint_dropped ();
669  if (drop.vsindex_dropped)
670  parsed_charstrings[i].set_vsindex_dropped ();
671  }
672  }
673 
674  /* after dropping hints recreate closures of actually used subrs */
675  closures.reset ();
676  for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
677  {
679  if (!plan->old_gid_for_new_gid (i, &glyph))
680  continue;
681  unsigned int fd = acc.fdSelect->get_fd (glyph);
682  if (unlikely (fd >= acc.fdCount))
683  return false;
685  param.init (&parsed_charstrings[i],
688  plan->drop_hints);
690  }
691  }
692 
694 
695  return true;
696  }
697 
698  bool encode_charstrings (str_buff_vec_t &buffArray) const
699  {
700  if (unlikely (!buffArray.resize (plan->num_output_glyphs ())))
701  return false;
702  for (unsigned int i = 0; i < plan->num_output_glyphs (); i++)
703  {
705  if (!plan->old_gid_for_new_gid (i, &glyph))
706  {
707  /* add an endchar only charstring for a missing glyph if CFF1 */
708  if (endchar_op != OpCode_Invalid) buffArray[i].push (endchar_op);
709  continue;
710  }
711  unsigned int fd = acc.fdSelect->get_fd (glyph);
712  if (unlikely (fd >= acc.fdCount))
713  return false;
714  if (unlikely (!encode_str (parsed_charstrings[i], fd, buffArray[i])))
715  return false;
716  }
717  return true;
718  }
719 
720  bool encode_subrs (const parsed_cs_str_vec_t &subrs, const subr_remap_t& remap, unsigned int fd, str_buff_vec_t &buffArray) const
721  {
722  unsigned int count = remap.get_population ();
723 
724  if (unlikely (!buffArray.resize (count)))
725  return false;
726  for (unsigned int old_num = 0; old_num < subrs.length; old_num++)
727  {
728  hb_codepoint_t new_num = remap[old_num];
729  if (new_num != CFF_UNDEF_CODE)
730  {
731  if (unlikely (!encode_str (subrs[old_num], fd, buffArray[new_num])))
732  return false;
733  }
734  }
735  return true;
736  }
737 
739  {
740  return encode_subrs (parsed_global_subrs, remaps.global_remap, 0, buffArray);
741  }
742 
743  bool encode_localsubrs (unsigned int fd, str_buff_vec_t &buffArray) const
744  {
745  return encode_subrs (parsed_local_subrs[fd], remaps.local_remaps[fd], fd, buffArray);
746  }
747 
748  protected:
749  struct drop_hints_param_t
750  {
752  : seen_moveto (false),
754  all_dropped (false),
756 
757  bool seen_moveto;
758  bool ends_in_hint;
759  bool all_dropped;
760  bool vsindex_dropped;
761  };
762 
764  parsed_cs_str_vec_t &subrs, unsigned int subr_num,
766  {
767  drop.ends_in_hint = false;
768  bool has_hint = drop_hints_in_str (subrs[subr_num], param, drop);
769 
770  /* if this subr ends with a stem hint (i.e., not a number; potential argument for moveto),
771  * then this entire subroutine must be a hint. drop its call. */
772  if (drop.ends_in_hint)
773  {
774  str.values[pos].set_drop ();
775  /* if this subr call is at the end of the parent subr, propagate the flag
776  * otherwise reset the flag */
777  if (!str.at_end (pos))
778  drop.ends_in_hint = false;
779  }
780  else if (drop.all_dropped)
781  {
782  str.values[pos].set_drop ();
783  }
784 
785  return has_hint;
786  }
787 
788  /* returns true if it sees a hint op before the first moveto */
790  {
791  bool seen_hint = false;
792 
793  for (unsigned int pos = 0; pos < str.values.length; pos++)
794  {
795  bool has_hint = false;
796  switch (str.values[pos].op)
797  {
798  case OpCode_callsubr:
799  has_hint = drop_hints_in_subr (str, pos,
800  *param.parsed_local_subrs, str.values[pos].subr_num,
801  param, drop);
802  break;
803 
804  case OpCode_callgsubr:
805  has_hint = drop_hints_in_subr (str, pos,
806  *param.parsed_global_subrs, str.values[pos].subr_num,
807  param, drop);
808  break;
809 
810  case OpCode_rmoveto:
811  case OpCode_hmoveto:
812  case OpCode_vmoveto:
813  drop.seen_moveto = true;
814  break;
815 
816  case OpCode_hintmask:
817  case OpCode_cntrmask:
818  if (drop.seen_moveto)
819  {
820  str.values[pos].set_drop ();
821  break;
822  }
824 
825  case OpCode_hstemhm:
826  case OpCode_vstemhm:
827  case OpCode_hstem:
828  case OpCode_vstem:
829  has_hint = true;
830  str.values[pos].set_drop ();
831  if (str.at_end (pos))
832  drop.ends_in_hint = true;
833  break;
834 
835  case OpCode_dotsection:
836  str.values[pos].set_drop ();
837  break;
838 
839  default:
840  /* NONE */
841  break;
842  }
843  if (has_hint)
844  {
845  for (int i = pos - 1; i >= 0; i--)
846  {
847  parsed_cs_op_t &csop = str.values[(unsigned)i];
848  if (csop.for_drop ())
849  break;
850  csop.set_drop ();
851  if (csop.op == OpCode_vsindexcs)
852  drop.vsindex_dropped = true;
853  }
854  seen_hint |= has_hint;
855  }
856  }
857 
858  /* Raise all_dropped flag if all operators except return are dropped from a subr.
859  * It may happen even after seeing the first moveto if a subr contains
860  * only (usually one) hintmask operator, then calls to this subr can be dropped.
861  */
862  drop.all_dropped = true;
863  for (unsigned int pos = 0; pos < str.values.length; pos++)
864  {
865  parsed_cs_op_t &csop = str.values[pos];
866  if (csop.op == OpCode_return)
867  break;
868  if (!csop.for_drop ())
869  {
870  drop.all_dropped = false;
871  break;
872  }
873  }
874 
875  return seen_hint;
876  }
877 
879  unsigned int subr_num, parsed_cs_str_vec_t &subrs,
880  hb_set_t *closure,
881  const subr_subset_param_t &param)
882  {
883  closure->add (subr_num);
884  collect_subr_refs_in_str (subrs[subr_num], param);
885  }
886 
888  {
889  for (unsigned int pos = 0; pos < str.values.length; pos++)
890  {
891  if (!str.values[pos].for_drop ())
892  {
893  switch (str.values[pos].op)
894  {
895  case OpCode_callsubr:
897  str.values[pos].subr_num, *param.parsed_local_subrs,
898  param.local_closure, param);
899  break;
900 
901  case OpCode_callgsubr:
903  str.values[pos].subr_num, *param.parsed_global_subrs,
904  param.global_closure, param);
905  break;
906 
907  default: break;
908  }
909  }
910  }
911  }
912 
913  bool encode_str (const parsed_cs_str_t &str, const unsigned int fd, str_buff_t &buff) const
914  {
915  buff.init ();
916  str_encoder_t encoder (buff);
917  encoder.reset ();
918  /* if a prefix (CFF1 width or CFF2 vsindex) has been removed along with hints,
919  * re-insert it at the beginning of charstreing */
920  if (str.has_prefix () && str.is_hint_dropped ())
921  {
922  encoder.encode_num (str.prefix_num ());
923  if (str.prefix_op () != OpCode_Invalid)
924  encoder.encode_op (str.prefix_op ());
925  }
926  for (unsigned int i = 0; i < str.get_count(); i++)
927  {
928  const parsed_cs_op_t &opstr = str.values[i];
929  if (!opstr.for_drop () && !opstr.for_skip ())
930  {
931  switch (opstr.op)
932  {
933  case OpCode_callsubr:
934  encoder.encode_int (remaps.local_remaps[fd].biased_num (opstr.subr_num));
935  encoder.encode_op (OpCode_callsubr);
936  break;
937 
938  case OpCode_callgsubr:
939  encoder.encode_int (remaps.global_remap.biased_num (opstr.subr_num));
940  encoder.encode_op (OpCode_callgsubr);
941  break;
942 
943  default:
944  encoder.copy_str (opstr.str);
945  break;
946  }
947  }
948  }
949  return !encoder.is_error ();
950  }
951 
952  protected:
953  const ACC &acc;
954  const hb_subset_plan_t *plan;
955 
957 
961 
963 
964  private:
965  typedef typename SUBRS::count_type subr_count_type;
966 };
967 
968 } /* namespace CFF */
969 
970 HB_INTERNAL bool
972  unsigned int fdCount,
973  const CFF::FDSelect &src, /* IN */
974  unsigned int &subset_fd_count /* OUT */,
975  unsigned int &subset_fdselect_size /* OUT */,
976  unsigned int &subset_fdselect_format /* OUT */,
977  hb_vector_t<CFF::code_pair_t> &fdselect_ranges /* OUT */,
978  hb_inc_bimap_t &fdmap /* OUT */);
979 
980 HB_INTERNAL bool
982  unsigned int num_glyphs,
983  const CFF::FDSelect &src,
984  unsigned int fd_count,
985  unsigned int fdselect_format,
986  unsigned int size,
987  const hb_vector_t<CFF::code_pair_t> &fdselect_ranges);
988 
989 #endif /* HB_SUBSET_CFF_COMMON_HH */
#define count(a)
Definition: aptex-macros.h:781
#define param(a, b)
#define n
Definition: t4ht.c:1290
#define b
Definition: jpegint.h:372
int v
Definition: dviconv.c:10
#define info
Definition: dviinfo.c:42
int in_error
Definition: errors.c:64
static char buff[2 *10240]
Definition: genind.c:46
#define c(n)
Definition: gpos-common.c:150
#define d(n)
Definition: gpos-common.c:151
#define memcpy(d, s, n)
Definition: gsftopk.c:64
#define likely(x)
Definition: jbig2arith.cc:115
#define unlikely(x)
Definition: jbig2arith.cc:116
small capitals from c petite p scientific i
Definition: afcover.h:80
#define false
Definition: ftrandom.c:52
signed int int32_t
Definition: stdint.h:77
int num
Definition: disdvi.c:621
char * closure
Definition: font.h:85
const int * pos
Definition: combiners.h:905
hb_serialize_context_t::objidx_t objidx_t
hb_vector_t< unsigned char > str_buff_t
op_code_t Unmake_OpCode_ESC(op_code_t op)
bool Is_OpCode_ESC(op_code_t op)
unsigned int op_code_t
primitive interp
Definition: obx.h:197
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld init[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1 beq endif SRC MASK if dst_r_bpp DST_R else add endif PF add sub src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head pixblock_size cache_preload_simple process_pixblock_tail pixinterleave dst_w_basereg irp beq endif process_pixblock_tail_head tst beq irp if pixblock_size chunk_size tst beq pixld_src SRC pixld MASK if DST_R else pixld DST_R endif if src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head if pixblock_size cache_preload_simple endif process_pixblock_tail pixinterleave dst_w_basereg irp if pixblock_size chunk_size tst beq if DST_W else pixst DST_W else mov ORIG_W endif add lsl if lsl endif if lsl endif lsl endif lsl endif lsl endif subs mov DST_W if regs_shortage str endif bge start_of_loop_label endm macro generate_composite_function
static int size
Definition: ppmlabel.c:24
static int offset
Definition: ppmtogif.c:642
#define OpCode_hintmask
#define OpCode_Invalid
#define OpCode_rmoveto
#define OpCode_shortint
#define OpCode_FDSelect
#define OpCode_return
#define OpCode_vmoveto
#define OpCode_CharStrings
#define OpCode_vstem
#define OpCode_callsubr
#define OpCode_hstemhm
#define OpCode_Private
#define OpCode_TwoBytePosInt0
#define OpCode_escape
#define OpCode_fixedcs
#define OpCode_dotsection
#define OpCode_cntrmask
#define OpCode_hmoveto
#define OpCode_vstemhm
#define OpCode_hstem
#define OpCode_vsindexcs
#define OpCode_Subrs
#define OpCode_callgsubr
#define OpCode_TwoByteNegInt0
#define OpCode_FDArray
uint32_t hb_codepoint_t
Definition: hb-common.h:106
#define TRACE_SERIALIZE(this)
Definition: hb-debug.hh:426
#define return_trace(RET)
Definition: hb-debug.hh:349
#define Crap(Type)
Definition: hb-null.hh:147
#define CFF_UNDEF_CODE
hb_set_t * hb_set_get_empty()
Definition: hb-set.cc:74
hb_set_t * hb_set_create()
Definition: hb-set.cc:52
void hb_set_destroy(hb_set_t *set)
Definition: hb-set.cc:106
hb_bool_t hb_set_next(const hb_set_t *set, hb_codepoint_t *codepoint)
Definition: hb-set.cc:491
void hb_set_clear(hb_set_t *set)
Definition: hb-set.cc:184
#define HB_SET_VALUE_INVALID
Definition: hb-set.h:42
bool hb_serialize_cff_fdselect(hb_serialize_context_t *c, unsigned int num_glyphs, const CFF::FDSelect &src, unsigned int fd_count, unsigned int fdselect_format, unsigned int size, const hb_vector_t< CFF::code_pair_t > &fdselect_ranges)
bool hb_plan_subset_cff_fdselect(const hb_subset_plan_t *plan, unsigned int fdCount, const CFF::FDSelect &src, unsigned int &subset_fd_count, unsigned int &subset_fdselect_size, unsigned int &subset_fdselect_format, hb_vector_t< CFF::code_pair_t > &fdselect_ranges, hb_inc_bimap_t &fdmap)
#define HB_FALLTHROUGH
Definition: hb.hh:328
#define HB_INTERNAL
Definition: hb.hh:265
#define str(s)
Definition: sh6.c:399
static bool serialize_link2_op(hb_serialize_context_t *c, op_code_t op, objidx_t link, whence_t whence=whence_t::Head)
static bool serialize_link4_op(hb_serialize_context_t *c, op_code_t op, objidx_t link, whence_t whence=whence_t::Head)
static bool serialize_int2(hb_serialize_context_t *c, V value)
bool serialize(hb_serialize_context_t *c, const op_str_t &opstr, const table_info_t &privateDictInfo) const
cff_private_dict_op_serializer_t(bool desubroutinize_, bool drop_hints_)
bool serialize(hb_serialize_context_t *c, const op_str_t &opstr, objidx_t subrs_link) const
bool serialize(hb_serialize_context_t *c, const OPSTR &opstr, const cff_sub_table_info_t &info) const
static bool is_hint_op(op_code_t op)
bool copy_opstr(hb_serialize_context_t *c, const op_str_t &opstr) const
void init(unsigned int subr_num_=0)
parsed_values_t< parsed_cs_op_t > SUPER
bool at_end(unsigned int pos) const
op_code_t prefix_op() const
void add_op(op_code_t op, const byte_str_ref_t &str_ref)
void set_prefix(const number_t &num, op_code_t op=0xFFFFu)
void add_call_op(op_code_t op, const byte_str_ref_t &str_ref, unsigned int subr_num)
const number_t & prefix_num() const
hb_vector_t< parsed_cs_str_t > SUPER
void init(unsigned int len_=0)
void add_op(op_code_t op, const byte_str_ref_t &str_ref=byte_str_ref_t())
str_encoder_t(str_buff_t &buff_)
void encode_byte(unsigned char b)
void copy_str(const byte_str_t &str)
void encode_num(const number_t &n)
void encode_op(op_code_t op)
hb_vector_t< hb_set_t * > local_closures
void init(unsigned int fd_count)
const hb_subset_plan_t * plan
subr_flattener_t(const ACC &acc_, const hb_subset_plan_t *plan_)
bool flatten(str_buff_vec_t &flat_charstrings)
int biased_num(unsigned int old_num) const
void create(hb_set_t *closure)
void create(subr_closures_t &closures)
hb_vector_t< subr_remap_t > local_remaps
void init(unsigned int fdCount)
parsed_cs_str_t * current_parsed_str
parsed_cs_str_t * get_parsed_str_for_context(call_context_t &context)
void init(parsed_cs_str_t *parsed_charstring_, parsed_cs_str_vec_t *parsed_global_subrs_, parsed_cs_str_vec_t *parsed_local_subrs_, hb_set_t *global_closure_, hb_set_t *local_closure_, bool drop_hints_)
parsed_cs_str_t * parsed_charstring
void set_current_str(ENV &env, bool calling)
parsed_cs_str_vec_t * parsed_global_subrs
parsed_cs_str_vec_t * parsed_local_subrs
void collect_subr_refs_in_subr(parsed_cs_str_t &str, unsigned int pos, unsigned int subr_num, parsed_cs_str_vec_t &subrs, hb_set_t *closure, const subr_subset_param_t &param)
bool encode_subrs(const parsed_cs_str_vec_t &subrs, const subr_remap_t &remap, unsigned int fd, str_buff_vec_t &buffArray) const
bool encode_globalsubrs(str_buff_vec_t &buffArray)
bool encode_charstrings(str_buff_vec_t &buffArray) const
subr_subsetter_t(ACC &acc_, const hb_subset_plan_t *plan_)
bool drop_hints_in_str(parsed_cs_str_t &str, const subr_subset_param_t &param, drop_hints_param_t &drop)
parsed_cs_str_vec_t parsed_global_subrs
hb_vector_t< parsed_cs_str_vec_t > parsed_local_subrs
bool encode_localsubrs(unsigned int fd, str_buff_vec_t &buffArray) const
parsed_cs_str_vec_t parsed_charstrings
bool encode_str(const parsed_cs_str_t &str, const unsigned int fd, str_buff_t &buff) const
void collect_subr_refs_in_str(parsed_cs_str_t &str, const subr_subset_param_t &param)
const hb_subset_plan_t * plan
SUBRS::count_type subr_count_type
bool drop_hints_in_subr(parsed_cs_str_t &str, unsigned int pos, parsed_cs_str_vec_t &subrs, unsigned int subr_num, const subr_subset_param_t &param, drop_hints_param_t &drop)
Definition: sh.h:1689
Definition: pbmfont.h:4
unsigned int length
Definition: hb-array.hh:259
void fini()
Definition: hb-bimap.hh:45
unsigned int get_population() const
Definition: hb-bimap.hh:87
hb_codepoint_t get(hb_codepoint_t lhs) const
Definition: hb-bimap.hh:67
void init()
Definition: hb-bimap.hh:99
hb_codepoint_t add(hb_codepoint_t lhs)
Definition: hb-bimap.hh:108
bool old_gid_for_new_gid(hb_codepoint_t new_gid, hb_codepoint_t *old_gid) const
unsigned int num_output_glyphs() const
bool resize(int size_)
Definition: hb-vector.hh:216
bool in_error() const
Definition: hb-vector.hh:179
unsigned int length
Definition: hb-vector.hh:60
Type * push()
Definition: hb-vector.hh:165
Definition: sh.h:1226
Definition: strexpr.c:21
int subrs
Definition: t1part.c:260
val
Definition: tex4ht.c:3227
op
Definition: tex4ht.c:3129
TT_Glyph glyph
Definition: ttf2pfb.c:162
#define nullptr
Definition: xetex.h:75