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