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_CFF1_TABLE_HH
28#define HB_OT_CFF1_TABLE_HH
29
30#include "hb-ot-head-table.hh"
31#include "hb-ot-cff-common.hh"
32#include "hb-subset-cff1.hh"
33
34namespace CFF {
35
36/*
37 * CFF -- Compact Font Format (CFF)
38 * http://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf
39 */
40#define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ')
41
42#define CFF_UNDEF_SID CFF_UNDEF_CODE
43
44enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
45enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };
46
47typedef CFFIndex<HBUINT16> CFF1Index;
48template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type> {};
49
50typedef CFFIndex<HBUINT16> CFF1Index;
51typedef CFF1Index CFF1CharStrings;
52typedef FDArray<HBUINT16> CFF1FDArray;
53typedef Subrs<HBUINT16> CFF1Subrs;
54
55struct CFF1FDSelect : FDSelect {};
56
57/* Encoding */
58struct Encoding0 {
59 bool sanitize (hb_sanitize_context_t *c) const
60 {
61 TRACE_SANITIZE (this);
62 return_trace (c->check_struct (this) && codes[nCodes - 1].sanitize (c));
63 }
64
65 hb_codepoint_t get_code (hb_codepoint_t glyph) const
66 {
67 assert (glyph > 0);
68 glyph--;
69 if (glyph < nCodes)
70 {
71 return (hb_codepoint_t)codes[glyph];
72 }
73 else
74 return CFF_UNDEF_CODE;
75 }
76
77 unsigned int get_size () const
78 { return HBUINT8::static_size * (nCodes + 1); }
79
80 HBUINT8 nCodes;
81 HBUINT8 codes[VAR];
82
83 DEFINE_SIZE_ARRAY(1, codes);
84};
85
86struct Encoding1_Range {
87 bool sanitize (hb_sanitize_context_t *c) const
88 {
89 TRACE_SANITIZE (this);
90 return_trace (c->check_struct (this));
91 }
92
93 HBUINT8 first;
94 HBUINT8 nLeft;
95
96 DEFINE_SIZE_STATIC (2);
97};
98
99struct Encoding1 {
100 unsigned int get_size () const
101 { return HBUINT8::static_size + Encoding1_Range::static_size * nRanges; }
102
103 bool sanitize (hb_sanitize_context_t *c) const
104 {
105 TRACE_SANITIZE (this);
106 return_trace (c->check_struct (this) && ((nRanges == 0) || (ranges[nRanges - 1]).sanitize (c)));
107 }
108
109 hb_codepoint_t get_code (hb_codepoint_t glyph) const
110 {
111 assert (glyph > 0);
112 glyph--;
113 for (unsigned int i = 0; i < nRanges; i++)
114 {
115 if (glyph <= ranges[i].nLeft)
116 {
117 return (hb_codepoint_t)ranges[i].first + glyph;
118 }
119 glyph -= (ranges[i].nLeft + 1);
120 }
121 return CFF_UNDEF_CODE;
122 }
123
124 HBUINT8 nRanges;
125 Encoding1_Range ranges[VAR];
126
127 DEFINE_SIZE_ARRAY (1, ranges);
128};
129
130struct SuppEncoding {
131 bool sanitize (hb_sanitize_context_t *c) const
132 {
133 TRACE_SANITIZE (this);
134 return_trace (c->check_struct (this));
135 }
136
137 HBUINT8 code;
138 HBUINT16 glyph;
139
140 DEFINE_SIZE_STATIC (3);
141};
142
143struct CFF1SuppEncData {
144 bool sanitize (hb_sanitize_context_t *c) const
145 {
146 TRACE_SANITIZE (this);
147 return_trace (c->check_struct (this) && ((nSups == 0) || (supps[nSups - 1]).sanitize (c)));
148 }
149
150 void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
151 {
152 for (unsigned int i = 0; i < nSups; i++)
153 if (sid == supps[i].glyph)
154 codes.push (supps[i].code);
155 }
156
157 unsigned int get_size () const
158 { return HBUINT8::static_size + SuppEncoding::static_size * nSups; }
159
160 HBUINT8 nSups;
161 SuppEncoding supps[VAR];
162
163 DEFINE_SIZE_ARRAY (1, supps);
164};
165
166struct Encoding {
167 bool sanitize (hb_sanitize_context_t *c) const
168 {
169 TRACE_SANITIZE (this);
170
171 if (unlikely (!c->check_struct (this)))
172 return_trace (false);
173 unsigned int fmt = format & 0x7F;
174 if (unlikely (fmt > 1))
175 return_trace (false);
176 if (unlikely (!((fmt == 0)? u.format0.sanitize (c): u.format1.sanitize (c))))
177 return_trace (false);
178 return_trace (((format & 0x80) == 0) || suppEncData ().sanitize (c));
179 }
180
181 /* serialize a fullset Encoding */
182 bool serialize (hb_serialize_context_t *c, const Encoding &src)
183 {
184 TRACE_SERIALIZE (this);
185 unsigned int size = src.get_size ();
186 Encoding *dest = c->allocate_size<Encoding> (size);
187 if (unlikely (dest == nullptr)) return_trace (false);
188 memcpy (dest, &src, size);
189 return_trace (true);
190 }
191
192 /* serialize a subset Encoding */
193 bool serialize (hb_serialize_context_t *c,
194 uint8_t format,
195 unsigned int enc_count,
196 const hb_vector_t<code_pair_t>& code_ranges,
197 const hb_vector_t<code_pair_t>& supp_codes)
198 {
199 TRACE_SERIALIZE (this);
200 Encoding *dest = c->extend_min (*this);
201 if (unlikely (dest == nullptr)) return_trace (false);
202 dest->format.set (format | ((supp_codes.length > 0)? 0x80: 0));
203 if (format == 0)
204 {
205 Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
206 if (unlikely (fmt0 == nullptr)) return_trace (false);
207 fmt0->nCodes.set (enc_count);
208 unsigned int glyph = 0;
209 for (unsigned int i = 0; i < code_ranges.length; i++)
210 {
211 hb_codepoint_t code = code_ranges[i].code;
212 for (int left = (int)code_ranges[i].glyph; left >= 0; left--)
213 fmt0->codes[glyph++].set (code++);
214 if (unlikely (!((glyph <= 0x100) && (code <= 0x100))))
215 return_trace (false);
216 }
217 }
218 else
219 {
220 Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
221 if (unlikely (fmt1 == nullptr)) return_trace (false);
222 fmt1->nRanges.set (code_ranges.length);
223 for (unsigned int i = 0; i < code_ranges.length; i++)
224 {
225 if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF))))
226 return_trace (false);
227 fmt1->ranges[i].first.set (code_ranges[i].code);
228 fmt1->ranges[i].nLeft.set (code_ranges[i].glyph);
229 }
230 }
231 if (supp_codes.length > 0)
232 {
233 CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
234 if (unlikely (suppData == nullptr)) return_trace (false);
235 suppData->nSups.set (supp_codes.length);
236 for (unsigned int i = 0; i < supp_codes.length; i++)
237 {
238 suppData->supps[i].code.set (supp_codes[i].code);
239 suppData->supps[i].glyph.set (supp_codes[i].glyph); /* actually SID */
240 }
241 }
242 return_trace (true);
243 }
244
245 /* parallel to above: calculate the size of a subset Encoding */
246 static unsigned int calculate_serialized_size (uint8_t format,
247 unsigned int enc_count,
248 unsigned int supp_count)
249 {
250 unsigned int size = min_size;
251 if (format == 0)
252 size += Encoding0::min_size + HBUINT8::static_size * enc_count;
253 else
254 size += Encoding1::min_size + Encoding1_Range::static_size * enc_count;
255 if (supp_count > 0)
256 size += CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_count;
257 return size;
258 }
259
260 unsigned int get_size () const
261 {
262 unsigned int size = min_size;
263 if (table_format () == 0)
264 size += u.format0.get_size ();
265 else
266 size += u.format1.get_size ();
267 if (has_supplement ())
268 size += suppEncData ().get_size ();
269 return size;
270 }
271
272 hb_codepoint_t get_code (hb_codepoint_t glyph) const
273 {
274 if (table_format () == 0)
275 return u.format0.get_code (glyph);
276 else
277 return u.format1.get_code (glyph);
278 }
279
280 uint8_t table_format () const { return (format & 0x7F); }
281 bool has_supplement () const { return (format & 0x80) != 0; }
282
283 void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
284 {
285 codes.resize (0);
286 if (has_supplement ())
287 suppEncData().get_codes (sid, codes);
288 }
289
290 protected:
291 const CFF1SuppEncData &suppEncData () const
292 {
293 if ((format & 0x7F) == 0)
294 return StructAfter<CFF1SuppEncData> (u.format0.codes[u.format0.nCodes-1]);
295 else
296 return StructAfter<CFF1SuppEncData> (u.format1.ranges[u.format1.nRanges-1]);
297 }
298
299 public:
300 HBUINT8 format;
301
302 union {
303 Encoding0 format0;
304 Encoding1 format1;
305 } u;
306 /* CFF1SuppEncData suppEncData; */
307
308 DEFINE_SIZE_MIN (1);
309};
310
311/* Charset */
312struct Charset0 {
313 bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
314 {
315 TRACE_SANITIZE (this);
316 return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c));
317 }
318
319 hb_codepoint_t get_sid (hb_codepoint_t glyph) const
320 {
321 if (glyph == 0)
322 return 0;
323 else
324 return sids[glyph - 1];
325 }
326
327 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
328 {
329 if (sid == 0)
330 return 0;
331
332 for (unsigned int glyph = 1; glyph < num_glyphs; glyph++)
333 {
334 if (sids[glyph-1] == sid)
335 return glyph;
336 }
337 return 0;
338 }
339
340 unsigned int get_size (unsigned int num_glyphs) const
341 {
342 assert (num_glyphs > 0);
343 return HBUINT16::static_size * (num_glyphs - 1);
344 }
345
346 HBUINT16 sids[VAR];
347
348 DEFINE_SIZE_ARRAY(0, sids);
349};
350
351template <typename TYPE>
352struct Charset_Range {
353 bool sanitize (hb_sanitize_context_t *c) const
354 {
355 TRACE_SANITIZE (this);
356 return_trace (c->check_struct (this));
357 }
358
359 HBUINT16 first;
360 TYPE nLeft;
361
362 DEFINE_SIZE_STATIC (HBUINT16::static_size + TYPE::static_size);
363};
364
365template <typename TYPE>
366struct Charset1_2 {
367 bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
368 {
369 TRACE_SANITIZE (this);
370 if (unlikely (!c->check_struct (this)))
371 return_trace (false);
372 num_glyphs--;
373 for (unsigned int i = 0; num_glyphs > 0; i++)
374 {
375 if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1)))
376 return_trace (false);
377 num_glyphs -= (ranges[i].nLeft + 1);
378 }
379 return_trace (true);
380 }
381
382 hb_codepoint_t get_sid (hb_codepoint_t glyph) const
383 {
384 if (glyph == 0) return 0;
385 glyph--;
386 for (unsigned int i = 0;; i++)
387 {
388 if (glyph <= ranges[i].nLeft)
389 return (hb_codepoint_t)ranges[i].first + glyph;
390 glyph -= (ranges[i].nLeft + 1);
391 }
392
393 return 0;
394 }
395
396 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
397 {
398 if (sid == 0) return 0;
399 hb_codepoint_t glyph = 1;
400 for (unsigned int i = 0;; i++)
401 {
402 if (glyph >= num_glyphs)
403 return 0;
404 if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
405 return glyph + (sid - ranges[i].first);
406 glyph += (ranges[i].nLeft + 1);
407 }
408
409 return 0;
410 }
411
412 unsigned int get_size (unsigned int num_glyphs) const
413 {
414 unsigned int size = HBUINT8::static_size;
415 int glyph = (int)num_glyphs;
416
417 assert (glyph > 0);
418 glyph--;
419 for (unsigned int i = 0; glyph > 0; i++)
420 {
421 glyph -= (ranges[i].nLeft + 1);
422 size += Charset_Range<TYPE>::static_size;
423 }
424
425 return size;
426 }
427
428 Charset_Range<TYPE> ranges[VAR];
429
430 DEFINE_SIZE_ARRAY (0, ranges);
431};
432
433typedef Charset1_2<HBUINT8> Charset1;
434typedef Charset1_2<HBUINT16> Charset2;
435typedef Charset_Range<HBUINT8> Charset1_Range;
436typedef Charset_Range<HBUINT16> Charset2_Range;
437
438struct Charset {
439 bool sanitize (hb_sanitize_context_t *c) const
440 {
441 TRACE_SANITIZE (this);
442
443 if (unlikely (!c->check_struct (this)))
444 return_trace (false);
445 if (format == 0)
446 return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
447 else if (format == 1)
448 return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
449 else if (likely (format == 2))
450 return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
451 else
452 return_trace (false);
453 }
454
455 /* serialize a fullset Charset */
456 bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
457 {
458 TRACE_SERIALIZE (this);
459 unsigned int size = src.get_size (num_glyphs);
460 Charset *dest = c->allocate_size<Charset> (size);
461 if (unlikely (dest == nullptr)) return_trace (false);
462 memcpy (dest, &src, size);
463 return_trace (true);
464 }
465
466 /* serialize a subset Charset */
467 bool serialize (hb_serialize_context_t *c,
468 uint8_t format,
469 unsigned int num_glyphs,
470 const hb_vector_t<code_pair_t>& sid_ranges)
471 {
472 TRACE_SERIALIZE (this);
473 Charset *dest = c->extend_min (*this);
474 if (unlikely (dest == nullptr)) return_trace (false);
475 dest->format.set (format);
476 if (format == 0)
477 {
478 Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
479 if (unlikely (fmt0 == nullptr)) return_trace (false);
480 unsigned int glyph = 0;
481 for (unsigned int i = 0; i < sid_ranges.length; i++)
482 {
483 hb_codepoint_t sid = sid_ranges[i].code;
484 for (int left = (int)sid_ranges[i].glyph; left >= 0; left--)
485 fmt0->sids[glyph++].set (sid++);
486 }
487 }
488 else if (format == 1)
489 {
490 Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length);
491 if (unlikely (fmt1 == nullptr)) return_trace (false);
492 for (unsigned int i = 0; i < sid_ranges.length; i++)
493 {
494 if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
495 return_trace (false);
496 fmt1->ranges[i].first.set (sid_ranges[i].code);
497 fmt1->ranges[i].nLeft.set (sid_ranges[i].glyph);
498 }
499 }
500 else /* format 2 */
501 {
502 Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length);
503 if (unlikely (fmt2 == nullptr)) return_trace (false);
504 for (unsigned int i = 0; i < sid_ranges.length; i++)
505 {
506 if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
507 return_trace (false);
508 fmt2->ranges[i].first.set (sid_ranges[i].code);
509 fmt2->ranges[i].nLeft.set (sid_ranges[i].glyph);
510 }
511 }
512 return_trace (true);
513 }
514
515 /* parallel to above: calculate the size of a subset Charset */
516 static unsigned int calculate_serialized_size (
517 uint8_t format,
518 unsigned int count)
519 {
520 unsigned int size = min_size;
521 if (format == 0)
522 size += Charset0::min_size + HBUINT16::static_size * (count - 1);
523 else if (format == 1)
524 size += Charset1::min_size + Charset1_Range::static_size * count;
525 else
526 size += Charset2::min_size + Charset2_Range::static_size * count;
527
528 return size;
529 }
530
531 unsigned int get_size (unsigned int num_glyphs) const
532 {
533 unsigned int size = min_size;
534 if (format == 0)
535 size += u.format0.get_size (num_glyphs);
536 else if (format == 1)
537 size += u.format1.get_size (num_glyphs);
538 else
539 size += u.format2.get_size (num_glyphs);
540 return size;
541 }
542
543 hb_codepoint_t get_sid (hb_codepoint_t glyph) const
544 {
545 if (format == 0)
546 return u.format0.get_sid (glyph);
547 else if (format == 1)
548 return u.format1.get_sid (glyph);
549 else
550 return u.format2.get_sid (glyph);
551 }
552
553 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
554 {
555 if (format == 0)
556 return u.format0.get_glyph (sid, num_glyphs);
557 else if (format == 1)
558 return u.format1.get_glyph (sid, num_glyphs);
559 else
560 return u.format2.get_glyph (sid, num_glyphs);
561 }
562
563 HBUINT8 format;
564 union {
565 Charset0 format0;
566 Charset1 format1;
567 Charset2 format2;
568 } u;
569
570 DEFINE_SIZE_MIN (1);
571};
572
573struct CFF1StringIndex : CFF1Index
574{
575 bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
576 unsigned int offSize_, const remap_t &sidmap)
577 {
578 TRACE_SERIALIZE (this);
579 if (unlikely ((strings.count == 0) || (sidmap.get_count () == 0)))
580 {
581 if (!unlikely (c->extend_min (this->count)))
582 return_trace (false);
583 count.set (0);
584 return_trace (true);
585 }
586
587 byte_str_array_t bytesArray;
588 bytesArray.init ();
589 if (!bytesArray.resize (sidmap.get_count ()))
590 return_trace (false);
591 for (unsigned int i = 0; i < strings.count; i++)
592 {
593 hb_codepoint_t j = sidmap[i];
594 if (j != CFF_UNDEF_CODE)
595 bytesArray[j] = strings[i];
596 }
597
598 bool result = CFF1Index::serialize (c, offSize_, bytesArray);
599 bytesArray.fini ();
600 return_trace (result);
601 }
602
603 /* in parallel to above */
604 unsigned int calculate_serialized_size (unsigned int &offSize /*OUT*/, const remap_t &sidmap) const
605 {
606 offSize = 0;
607 if ((count == 0) || (sidmap.get_count () == 0))
608 return count.static_size;
609
610 unsigned int dataSize = 0;
611 for (unsigned int i = 0; i < count; i++)
612 if (sidmap[i] != CFF_UNDEF_CODE)
613 dataSize += length_at (i);
614
615 offSize = calcOffSize(dataSize);
616 return CFF1Index::calculate_serialized_size (offSize, sidmap.get_count (), dataSize);
617 }
618};
619
620struct cff1_top_dict_interp_env_t : num_interp_env_t
621{
622 cff1_top_dict_interp_env_t ()
623 : num_interp_env_t(), prev_offset(0), last_offset(0) {}
624
625 unsigned int prev_offset;
626 unsigned int last_offset;
627};
628
629struct name_dict_values_t
630{
631 enum name_dict_val_index_t
632 {
633 version,
634 notice,
635 copyright,
636 fullName,
637 familyName,
638 weight,
639 postscript,
640 fontName,
641 baseFontName,
642 registry,
643 ordering,
644
645 ValCount
646 };
647
648 void init ()
649 {
650 for (unsigned int i = 0; i < ValCount; i++)
651 values[i] = CFF_UNDEF_SID;
652 }
653
654 unsigned int& operator[] (unsigned int i)
655 { assert (i < ValCount); return values[i]; }
656
657 unsigned int operator[] (unsigned int i) const
658 { assert (i < ValCount); return values[i]; }
659
660 static enum name_dict_val_index_t name_op_to_index (op_code_t op)
661 {
662 switch (op) {
663 default: // can't happen - just make some compiler happy
664 case OpCode_version:
665 return version;
666 case OpCode_Notice:
667 return notice;
668 case OpCode_Copyright:
669 return copyright;
670 case OpCode_FullName:
671 return fullName;
672 case OpCode_FamilyName:
673 return familyName;
674 case OpCode_Weight:
675 return weight;
676 case OpCode_PostScript:
677 return postscript;
678 case OpCode_FontName:
679 return fontName;
680 case OpCode_BaseFontName:
681 return baseFontName;
682 }
683 }
684
685 unsigned int values[ValCount];
686};
687
688struct cff1_top_dict_val_t : op_str_t
689{
690 unsigned int last_arg_offset;
691};
692
693struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t>
694{
695 void init ()
696 {
697 top_dict_values_t<cff1_top_dict_val_t>::init ();
698
699 nameSIDs.init ();
700 ros_supplement = 0;
701 cidCount = 8720;
702 EncodingOffset = 0;
703 CharsetOffset = 0;
704 FDSelectOffset = 0;
705 privateDictInfo.init ();
706 }
707 void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); }
708
709 bool is_CID () const
710 { return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; }
711
712 name_dict_values_t nameSIDs;
713 unsigned int ros_supplement_offset;
714 unsigned int ros_supplement;
715 unsigned int cidCount;
716
717 unsigned int EncodingOffset;
718 unsigned int CharsetOffset;
719 unsigned int FDSelectOffset;
720 table_info_t privateDictInfo;
721};
722
723struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
724{
725 static void process_op (op_code_t op, cff1_top_dict_interp_env_t& env, cff1_top_dict_values_t& dictval)
726 {
727 cff1_top_dict_val_t val;
728 val.last_arg_offset = (env.last_offset-1) - dictval.opStart; /* offset to the last argument */
729
730 switch (op) {
731 case OpCode_version:
732 case OpCode_Notice:
733 case OpCode_Copyright:
734 case OpCode_FullName:
735 case OpCode_FamilyName:
736 case OpCode_Weight:
737 case OpCode_PostScript:
738 case OpCode_BaseFontName:
739 dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint ();
740 env.clear_args ();
741 break;
742 case OpCode_isFixedPitch:
743 case OpCode_ItalicAngle:
744 case OpCode_UnderlinePosition:
745 case OpCode_UnderlineThickness:
746 case OpCode_PaintType:
747 case OpCode_CharstringType:
748 case OpCode_UniqueID:
749 case OpCode_StrokeWidth:
750 case OpCode_SyntheticBase:
751 case OpCode_CIDFontVersion:
752 case OpCode_CIDFontRevision:
753 case OpCode_CIDFontType:
754 case OpCode_UIDBase:
755 case OpCode_FontBBox:
756 case OpCode_XUID:
757 case OpCode_BaseFontBlend:
758 env.clear_args ();
759 break;
760
761 case OpCode_CIDCount:
762 dictval.cidCount = env.argStack.pop_uint ();
763 env.clear_args ();
764 break;
765
766 case OpCode_ROS:
767 dictval.ros_supplement = env.argStack.pop_uint ();
768 dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint ();
769 dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint ();
770 env.clear_args ();
771 break;
772
773 case OpCode_Encoding:
774 dictval.EncodingOffset = env.argStack.pop_uint ();
775 env.clear_args ();
776 if (unlikely (dictval.EncodingOffset == 0)) return;
777 break;
778
779 case OpCode_charset:
780 dictval.CharsetOffset = env.argStack.pop_uint ();
781 env.clear_args ();
782 if (unlikely (dictval.CharsetOffset == 0)) return;
783 break;
784
785 case OpCode_FDSelect:
786 dictval.FDSelectOffset = env.argStack.pop_uint ();
787 env.clear_args ();
788 break;
789
790 case OpCode_Private:
791 dictval.privateDictInfo.offset = env.argStack.pop_uint ();
792 dictval.privateDictInfo.size = env.argStack.pop_uint ();
793 env.clear_args ();
794 break;
795
796 default:
797 env.last_offset = env.str_ref.offset;
798 top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval);
799 /* Record this operand below if stack is empty, otherwise done */
800 if (!env.argStack.is_empty ()) return;
801 break;
802 }
803
804 if (unlikely (env.in_error ())) return;
805
806 dictval.add_op (op, env.str_ref, val);
807 }
808};
809
810struct cff1_font_dict_values_t : dict_values_t<op_str_t>
811{
812 void init ()
813 {
814 dict_values_t<op_str_t>::init ();
815 privateDictInfo.init ();
816 fontName = CFF_UNDEF_SID;
817 }
818 void fini () { dict_values_t<op_str_t>::fini (); }
819
820 table_info_t privateDictInfo;
821 unsigned int fontName;
822};
823
824struct cff1_font_dict_opset_t : dict_opset_t
825{
826 static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval)
827 {
828 switch (op) {
829 case OpCode_FontName:
830 dictval.fontName = env.argStack.pop_uint ();
831 env.clear_args ();
832 break;
833 case OpCode_FontMatrix:
834 case OpCode_PaintType:
835 env.clear_args ();
836 break;
837 case OpCode_Private:
838 dictval.privateDictInfo.offset = env.argStack.pop_uint ();
839 dictval.privateDictInfo.size = env.argStack.pop_uint ();
840 env.clear_args ();
841 break;
842
843 default:
844 dict_opset_t::process_op (op, env);
845 if (!env.argStack.is_empty ()) return;
846 break;
847 }
848
849 if (unlikely (env.in_error ())) return;
850
851 dictval.add_op (op, env.str_ref);
852 }
853};
854
855template <typename VAL>
856struct cff1_private_dict_values_base_t : dict_values_t<VAL>
857{
858 void init ()
859 {
860 dict_values_t<VAL>::init ();
861 subrsOffset = 0;
862 localSubrs = &Null(CFF1Subrs);
863 }
864 void fini () { dict_values_t<VAL>::fini (); }
865
866 unsigned int calculate_serialized_size () const
867 {
868 unsigned int size = 0;
869 for (unsigned int i = 0; i < dict_values_t<VAL>::get_count; i++)
870 if (dict_values_t<VAL>::get_value (i).op == OpCode_Subrs)
871 size += OpCode_Size (OpCode_shortint) + 2 + OpCode_Size (OpCode_Subrs);
872 else
873 size += dict_values_t<VAL>::get_value (i).str.length;
874 return size;
875 }
876
877 unsigned int subrsOffset;
878 const CFF1Subrs *localSubrs;
879};
880
881typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t;
882typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t;
883
884struct cff1_private_dict_opset_t : dict_opset_t
885{
886 static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval)
887 {
888 num_dict_val_t val;
889 val.init ();
890
891 switch (op) {
892 case OpCode_BlueValues:
893 case OpCode_OtherBlues:
894 case OpCode_FamilyBlues:
895 case OpCode_FamilyOtherBlues:
896 case OpCode_StemSnapH:
897 case OpCode_StemSnapV:
898 env.clear_args ();
899 break;
900 case OpCode_StdHW:
901 case OpCode_StdVW:
902 case OpCode_BlueScale:
903 case OpCode_BlueShift:
904 case OpCode_BlueFuzz:
905 case OpCode_ForceBold:
906 case OpCode_LanguageGroup:
907 case OpCode_ExpansionFactor:
908 case OpCode_initialRandomSeed:
909 case OpCode_defaultWidthX:
910 case OpCode_nominalWidthX:
911 val.single_val = env.argStack.pop_num ();
912 env.clear_args ();
913 break;
914 case OpCode_Subrs:
915 dictval.subrsOffset = env.argStack.pop_uint ();
916 env.clear_args ();
917 break;
918
919 default:
920 dict_opset_t::process_op (op, env);
921 if (!env.argStack.is_empty ()) return;
922 break;
923 }
924
925 if (unlikely (env.in_error ())) return;
926
927 dictval.add_op (op, env.str_ref, val);
928 }
929};
930
931struct cff1_private_dict_opset_subset : dict_opset_t
932{
933 static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval)
934 {
935 switch (op) {
936 case OpCode_BlueValues:
937 case OpCode_OtherBlues:
938 case OpCode_FamilyBlues:
939 case OpCode_FamilyOtherBlues:
940 case OpCode_StemSnapH:
941 case OpCode_StemSnapV:
942 case OpCode_StdHW:
943 case OpCode_StdVW:
944 case OpCode_BlueScale:
945 case OpCode_BlueShift:
946 case OpCode_BlueFuzz:
947 case OpCode_ForceBold:
948 case OpCode_LanguageGroup:
949 case OpCode_ExpansionFactor:
950 case OpCode_initialRandomSeed:
951 case OpCode_defaultWidthX:
952 case OpCode_nominalWidthX:
953 env.clear_args ();
954 break;
955
956 case OpCode_Subrs:
957 dictval.subrsOffset = env.argStack.pop_uint ();
958 env.clear_args ();
959 break;
960
961 default:
962 dict_opset_t::process_op (op, env);
963 if (!env.argStack.is_empty ()) return;
964 break;
965 }
966
967 if (unlikely (env.in_error ())) return;
968
969 dictval.add_op (op, env.str_ref);
970 }
971};
972
973typedef dict_interpreter_t<cff1_top_dict_opset_t, cff1_top_dict_values_t, cff1_top_dict_interp_env_t> cff1_top_dict_interpreter_t;
974typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t;
975
976typedef CFF1Index CFF1NameIndex;
977typedef CFF1IndexOf<TopDict> CFF1TopDictIndex;
978
979} /* namespace CFF */
980
981namespace OT {
982
983using namespace CFF;
984
985struct cff1
986{
987 static constexpr hb_tag_t tableTag = HB_OT_TAG_cff1;
988
989 bool sanitize (hb_sanitize_context_t *c) const
990 {
991 TRACE_SANITIZE (this);
992 return_trace (c->check_struct (this) &&
993 likely (version.major == 1));
994 }
995
996 template <typename PRIVOPSET, typename PRIVDICTVAL>
997 struct accelerator_templ_t
998 {
999 void init (hb_face_t *face)
1000 {
1001 topDict.init ();
1002 fontDicts.init ();
1003 privateDicts.init ();
1004
1005 this->blob = sc.reference_table<cff1> (face);
1006
1007 /* setup for run-time santization */
1008 sc.init (this->blob);
1009 sc.start_processing ();
1010
1011 const OT::cff1 *cff = this->blob->template as<OT::cff1> ();
1012
1013 if (cff == &Null(OT::cff1))
1014 { fini (); return; }
1015
1016 nameIndex = &cff->nameIndex (cff);
1017 if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc))
1018 { fini (); return; }
1019
1020 topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ());
1021 if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0))
1022 { fini (); return; }
1023
1024 { /* parse top dict */
1025 const byte_str_t topDictStr = (*topDictIndex)[0];
1026 if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
1027 cff1_top_dict_interpreter_t top_interp;
1028 top_interp.env.init (topDictStr);
1029 topDict.init ();
1030 if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
1031 }
1032
1033 if (is_predef_charset ())
1034 charset = &Null(Charset);
1035 else
1036 {
1037 charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
1038 if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; }
1039 }
1040
1041 fdCount = 1;
1042 if (is_CID ())
1043 {
1044 fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset);
1045 fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
1046 if (unlikely ((fdArray == &Null(CFF1FDArray)) || !fdArray->sanitize (&sc) ||
1047 (fdSelect == &Null(CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
1048 { fini (); return; }
1049
1050 fdCount = fdArray->count;
1051 }
1052 else
1053 {
1054 fdArray = &Null(CFF1FDArray);
1055 fdSelect = &Null(CFF1FDSelect);
1056 }
1057
1058 stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ());
1059 if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc))
1060 { fini (); return; }
1061
1062 globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ());
1063 if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc))
1064 { fini (); return; }
1065
1066 charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);
1067
1068 if ((charStrings == &Null(CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
1069 { fini (); return; }
1070
1071 num_glyphs = charStrings->count;
1072 if (num_glyphs != sc.get_num_glyphs ())
1073 { fini (); return; }
1074
1075 privateDicts.resize (fdCount);
1076 for (unsigned int i = 0; i < fdCount; i++)
1077 privateDicts[i].init ();
1078
1079 // parse CID font dicts and gather private dicts
1080 if (is_CID ())
1081 {
1082 for (unsigned int i = 0; i < fdCount; i++)
1083 {
1084 byte_str_t fontDictStr = (*fdArray)[i];
1085 if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
1086 cff1_font_dict_values_t *font;
1087 cff1_font_dict_interpreter_t font_interp;
1088 font_interp.env.init (fontDictStr);
1089 font = fontDicts.push ();
1090 if (unlikely (font == &Crap(cff1_font_dict_values_t))) { fini (); return; }
1091 font->init ();
1092 if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
1093 PRIVDICTVAL *priv = &privateDicts[i];
1094 const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
1095 if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
1096 dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
1097 priv_interp.env.init (privDictStr);
1098 priv->init ();
1099 if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
1100
1101 priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
1102 if (priv->localSubrs != &Null(CFF1Subrs) &&
1103 unlikely (!priv->localSubrs->sanitize (&sc)))
1104 { fini (); return; }
1105 }
1106 }
1107 else /* non-CID */
1108 {
1109 cff1_top_dict_values_t *font = &topDict;
1110 PRIVDICTVAL *priv = &privateDicts[0];
1111
1112 const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
1113 if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
1114 dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
1115 priv_interp.env.init (privDictStr);
1116 priv->init ();
1117 if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
1118
1119 priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
1120 if (priv->localSubrs != &Null(CFF1Subrs) &&
1121 unlikely (!priv->localSubrs->sanitize (&sc)))
1122 { fini (); return; }
1123 }
1124 }
1125
1126 void fini ()
1127 {
1128 sc.end_processing ();
1129 topDict.fini ();
1130 fontDicts.fini_deep ();
1131 privateDicts.fini_deep ();
1132 hb_blob_destroy (blob);
1133 blob = nullptr;
1134 }
1135
1136 bool is_valid () const { return blob != nullptr; }
1137 bool is_CID () const { return topDict.is_CID (); }
1138
1139 bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
1140
1141 unsigned int std_code_to_glyph (hb_codepoint_t code) const
1142 {
1143 hb_codepoint_t sid = lookup_standard_encoding_for_sid (code);
1144 if (unlikely (sid == CFF_UNDEF_SID))
1145 return 0;
1146
1147 if (charset != &Null(Charset))
1148 return charset->get_glyph (sid, num_glyphs);
1149 else if ((topDict.CharsetOffset == ISOAdobeCharset)
1150 && (code <= 228 /*zcaron*/)) return sid;
1151 return 0;
1152 }
1153
1154 protected:
1155 hb_blob_t *blob;
1156 hb_sanitize_context_t sc;
1157
1158 public:
1159 const Charset *charset;
1160 const CFF1NameIndex *nameIndex;
1161 const CFF1TopDictIndex *topDictIndex;
1162 const CFF1StringIndex *stringIndex;
1163 const CFF1Subrs *globalSubrs;
1164 const CFF1CharStrings *charStrings;
1165 const CFF1FDArray *fdArray;
1166 const CFF1FDSelect *fdSelect;
1167 unsigned int fdCount;
1168
1169 cff1_top_dict_values_t topDict;
1170 hb_vector_t<cff1_font_dict_values_t> fontDicts;
1171 hb_vector_t<PRIVDICTVAL> privateDicts;
1172
1173 unsigned int num_glyphs;
1174 };
1175
1176 struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
1177 {
1178 HB_INTERNAL bool get_extents (hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
1179 HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
1180 };
1181
1182 struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t>
1183 {
1184 void init (hb_face_t *face)
1185 {
1186 SUPER::init (face);
1187 if (blob == nullptr) return;
1188
1189 const OT::cff1 *cff = this->blob->as<OT::cff1> ();
1190 encoding = &Null(Encoding);
1191 if (is_CID ())
1192 {
1193 if (unlikely (charset == &Null(Charset))) { fini (); return; }
1194 }
1195 else
1196 {
1197 if (!is_predef_encoding ())
1198 {
1199 encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
1200 if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; }
1201 }
1202 }
1203 }
1204
1205 bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
1206
1207 hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const
1208 {
1209 if (encoding != &Null(Encoding))
1210 return encoding->get_code (glyph);
1211 else
1212 {
1213 hb_codepoint_t sid = glyph_to_sid (glyph);
1214 if (sid == 0) return 0;
1215 hb_codepoint_t code = 0;
1216 switch (topDict.EncodingOffset)
1217 {
1218 case StandardEncoding:
1219 code = lookup_standard_encoding_for_code (sid);
1220 break;
1221 case ExpertEncoding:
1222 code = lookup_expert_encoding_for_code (sid);
1223 break;
1224 default:
1225 break;
1226 }
1227 return code;
1228 }
1229 }
1230
1231 hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
1232 {
1233 if (charset != &Null(Charset))
1234 return charset->get_sid (glyph);
1235 else
1236 {
1237 hb_codepoint_t sid = 0;
1238 switch (topDict.CharsetOffset)
1239 {
1240 case ISOAdobeCharset:
1241 if (glyph <= 228 /*zcaron*/) sid = glyph;
1242 break;
1243 case ExpertCharset:
1244 sid = lookup_expert_charset_for_sid (glyph);
1245 break;
1246 case ExpertSubsetCharset:
1247 sid = lookup_expert_subset_charset_for_sid (glyph);
1248 break;
1249 default:
1250 break;
1251 }
1252 return sid;
1253 }
1254 }
1255
1256 const Encoding *encoding;
1257
1258 private:
1259 typedef accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> SUPER;
1260 };
1261
1262 bool subset (hb_subset_plan_t *plan) const
1263 {
1264 hb_blob_t *cff_prime = nullptr;
1265
1266 bool success = true;
1267 if (hb_subset_cff1 (plan, &cff_prime)) {
1268 success = success && plan->add_table (HB_OT_TAG_cff1, cff_prime);
1269 hb_blob_t *head_blob = hb_sanitize_context_t().reference_table<head> (plan->source);
1270 success = success && head_blob && plan->add_table (HB_OT_TAG_head, head_blob);
1271 hb_blob_destroy (head_blob);
1272 } else {
1273 success = false;
1274 }
1275 hb_blob_destroy (cff_prime);
1276
1277 return success;
1278 }
1279
1280 protected:
1281 HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
1282 HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
1283 HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph);
1284 HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph);
1285 HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code);
1286
1287 public:
1288 FixedVersion<HBUINT8> version; /* Version of CFF table. set to 0x0100u */
1289 OffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
1290 HBUINT8 offSize; /* offset size (unused?) */
1291
1292 public:
1293 DEFINE_SIZE_STATIC (4);
1294};
1295
1296struct cff1_accelerator_t : cff1::accelerator_t {};
1297} /* namespace OT */
1298
1299#endif /* HB_OT_CFF1_TABLE_HH */
1300