comparison mupdf-source/thirdparty/harfbuzz/src/hb-ot-cff1-table.hh @ 2:b50eed0cc0ef upstream

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