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