blob: 5dd183e3a0ef277451ae40b949771bd1735e6064 [file] [log] [blame]
Michiharu Ariza64c54122018-08-10 11:07:07 -07001/*
Michiharu Ariza0dfa5842018-11-12 08:47:07 -08002 * Copyright © 2018 Adobe Inc.
Michiharu Ariza64c54122018-08-10 11:07:07 -07003 *
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
Michiharu Arizafdbfa182018-08-16 00:13:09 -070027#ifndef HB_OT_CFF1_TABLE_HH
28#define HB_OT_CFF1_TABLE_HH
Michiharu Ariza64c54122018-08-10 11:07:07 -070029
Michiharu Ariza8af96902018-08-29 13:26:17 -070030#include "hb-ot-cff-common.hh"
Michiharu Arizafdbfa182018-08-16 00:13:09 -070031#include "hb-subset-cff1.hh"
Ebrahim Byagowi9fe0dc32020-02-26 17:40:44 +033032#include "hb-draw.hh"
Michiharu Ariza64c54122018-08-10 11:07:07 -070033
blueshade7ff874652019-11-19 16:18:33 -080034#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
Michiharu Ariza64c54122018-08-10 11:07:07 -070040namespace CFF {
41
42/*
43 * CFF -- Compact Font Format (CFF)
Ebrahim Byagowi8c652f72020-02-19 16:32:44 +033044 * https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5176.CFF.pdf
Michiharu Ariza64c54122018-08-10 11:07:07 -070045 */
Michiharu Arizae67bb3f2018-08-16 00:25:57 -070046#define HB_OT_TAG_cff1 HB_TAG('C','F','F',' ')
Michiharu Ariza64c54122018-08-10 11:07:07 -070047
Michiharu Ariza1666b892018-09-10 16:00:20 -070048#define CFF_UNDEF_SID CFF_UNDEF_CODE
Michiharu Arizaaca73c92018-09-06 17:28:15 -070049
50enum EncodingID { StandardEncoding = 0, ExpertEncoding = 1 };
51enum CharsetID { ISOAdobeCharset = 0, ExpertCharset = 1, ExpertSubsetCharset = 2 };
52
Michiharu Arizaf57d6bc2018-08-16 08:03:46 -070053typedef CFFIndex<HBUINT16> CFF1Index;
Michiharu Arizaaca73c92018-09-06 17:28:15 -070054template <typename Type> struct CFF1IndexOf : CFFIndexOf<HBUINT16, Type> {};
Michiharu Ariza64c54122018-08-10 11:07:07 -070055
Behdad Esfahbod825df6d2018-11-30 23:04:59 -050056typedef CFFIndex<HBUINT16> CFF1Index;
57typedef CFF1Index CFF1CharStrings;
Behdad Esfahbod825df6d2018-11-30 23:04:59 -050058typedef Subrs<HBUINT16> CFF1Subrs;
Michiharu Ariza64c54122018-08-10 11:07:07 -070059
Michiharu Arizafdbfa182018-08-16 00:13:09 -070060struct CFF1FDSelect : FDSelect {};
Michiharu Ariza64c54122018-08-10 11:07:07 -070061
62/* Encoding */
63struct Encoding0 {
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +033064 bool sanitize (hb_sanitize_context_t *c) const
Michiharu Ariza64c54122018-08-10 11:07:07 -070065 {
66 TRACE_SANITIZE (this);
Michiharu Ariza261a7422019-01-23 14:04:29 -080067 return_trace (codes.sanitize (c));
Michiharu Ariza64c54122018-08-10 11:07:07 -070068 }
69
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +033070 hb_codepoint_t get_code (hb_codepoint_t glyph) const
Michiharu Ariza64c54122018-08-10 11:07:07 -070071 {
Michiharu Ariza7fed7d82018-11-07 09:09:13 -080072 assert (glyph > 0);
73 glyph--;
Michiharu Ariza261a7422019-01-23 14:04:29 -080074 if (glyph < nCodes ())
Michiharu Ariza64c54122018-08-10 11:07:07 -070075 {
Michiharu Arizaaca73c92018-09-06 17:28:15 -070076 return (hb_codepoint_t)codes[glyph];
Michiharu Ariza64c54122018-08-10 11:07:07 -070077 }
78 else
Michiharu Arizaaca73c92018-09-06 17:28:15 -070079 return CFF_UNDEF_CODE;
Michiharu Ariza64c54122018-08-10 11:07:07 -070080 }
81
Michiharu Ariza261a7422019-01-23 14:04:29 -080082 HBUINT8 &nCodes () { return codes.len; }
83 HBUINT8 nCodes () const { return codes.len; }
Michiharu Ariza64c54122018-08-10 11:07:07 -070084
Michiharu Ariza261a7422019-01-23 14:04:29 -080085 ArrayOf<HBUINT8, HBUINT8> codes;
Michiharu Ariza64c54122018-08-10 11:07:07 -070086
Michiharu Ariza261a7422019-01-23 14:04:29 -080087 DEFINE_SIZE_ARRAY_SIZED (1, codes);
Michiharu Ariza64c54122018-08-10 11:07:07 -070088};
89
90struct Encoding1_Range {
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +033091 bool sanitize (hb_sanitize_context_t *c) const
Michiharu Ariza64c54122018-08-10 11:07:07 -070092 {
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 {
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330104 bool sanitize (hb_sanitize_context_t *c) const
Michiharu Ariza64c54122018-08-10 11:07:07 -0700105 {
106 TRACE_SANITIZE (this);
Michiharu Ariza261a7422019-01-23 14:04:29 -0800107 return_trace (ranges.sanitize (c));
Michiharu Ariza64c54122018-08-10 11:07:07 -0700108 }
109
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330110 hb_codepoint_t get_code (hb_codepoint_t glyph) const
Michiharu Ariza64c54122018-08-10 11:07:07 -0700111 {
Michiharu Ariza7fed7d82018-11-07 09:09:13 -0800112 assert (glyph > 0);
113 glyph--;
Michiharu Ariza261a7422019-01-23 14:04:29 -0800114 for (unsigned int i = 0; i < nRanges (); i++)
Michiharu Ariza64c54122018-08-10 11:07:07 -0700115 {
116 if (glyph <= ranges[i].nLeft)
117 {
Michiharu Ariza267fb9c2019-04-18 15:17:10 -0700118 hb_codepoint_t code = (hb_codepoint_t) ranges[i].first + glyph;
119 return (likely (code < 0x100) ? code: CFF_UNDEF_CODE);
Michiharu Ariza64c54122018-08-10 11:07:07 -0700120 }
121 glyph -= (ranges[i].nLeft + 1);
122 }
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700123 return CFF_UNDEF_CODE;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700124 }
125
Michiharu Ariza261a7422019-01-23 14:04:29 -0800126 HBUINT8 &nRanges () { return ranges.len; }
127 HBUINT8 nRanges () const { return ranges.len; }
Michiharu Ariza64c54122018-08-10 11:07:07 -0700128
Michiharu Ariza261a7422019-01-23 14:04:29 -0800129 ArrayOf<Encoding1_Range, HBUINT8> ranges;
130
131 DEFINE_SIZE_ARRAY_SIZED (1, ranges);
Michiharu Ariza64c54122018-08-10 11:07:07 -0700132};
133
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700134struct SuppEncoding {
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330135 bool sanitize (hb_sanitize_context_t *c) const
Michiharu Ariza64c54122018-08-10 11:07:07 -0700136 {
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
Michiharu Arizafdbfa182018-08-16 00:13:09 -0700147struct CFF1SuppEncData {
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330148 bool sanitize (hb_sanitize_context_t *c) const
Michiharu Ariza64c54122018-08-10 11:07:07 -0700149 {
150 TRACE_SANITIZE (this);
Michiharu Ariza261a7422019-01-23 14:04:29 -0800151 return_trace (supps.sanitize (c));
Michiharu Ariza64c54122018-08-10 11:07:07 -0700152 }
153
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330154 void get_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
Michiharu Ariza64c54122018-08-10 11:07:07 -0700155 {
Michiharu Ariza261a7422019-01-23 14:04:29 -0800156 for (unsigned int i = 0; i < nSups (); i++)
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700157 if (sid == supps[i].glyph)
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500158 codes.push (supps[i].code);
Michiharu Ariza64c54122018-08-10 11:07:07 -0700159 }
160
Michiharu Ariza261a7422019-01-23 14:04:29 -0800161 HBUINT8 &nSups () { return supps.len; }
162 HBUINT8 nSups () const { return supps.len; }
Michiharu Ariza64c54122018-08-10 11:07:07 -0700163
Michiharu Ariza261a7422019-01-23 14:04:29 -0800164 ArrayOf<SuppEncoding, HBUINT8> supps;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700165
Michiharu Ariza261a7422019-01-23 14:04:29 -0800166 DEFINE_SIZE_ARRAY_SIZED (1, supps);
Michiharu Ariza64c54122018-08-10 11:07:07 -0700167};
168
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430169struct Encoding
170{
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700171 /* serialize a fullset Encoding */
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330172 bool serialize (hb_serialize_context_t *c, const Encoding &src)
Michiharu Ariza64c54122018-08-10 11:07:07 -0700173 {
174 TRACE_SERIALIZE (this);
175 unsigned int size = src.get_size ();
176 Encoding *dest = c->allocate_size<Encoding> (size);
Ebrahim Byagowi2be859d2020-04-20 23:48:23 +0430177 if (unlikely (!dest)) return_trace (false);
Michiharu Ariza64c54122018-08-10 11:07:07 -0700178 memcpy (dest, &src, size);
179 return_trace (true);
180 }
181
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700182 /* serialize a subset Encoding */
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330183 bool serialize (hb_serialize_context_t *c,
184 uint8_t format,
185 unsigned int enc_count,
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800186 const hb_vector_t<code_pair_t>& code_ranges,
187 const hb_vector_t<code_pair_t>& supp_codes)
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700188 {
189 TRACE_SERIALIZE (this);
Behdad Esfahbodf0a18922021-07-28 17:36:22 -0600190 Encoding *dest = c->extend_min (this);
Ebrahim Byagowi2be859d2020-04-20 23:48:23 +0430191 if (unlikely (!dest)) return_trace (false);
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430192 dest->format = format | ((supp_codes.length > 0) ? 0x80 : 0);
193 switch (format) {
194 case 0:
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700195 {
196 Encoding0 *fmt0 = c->allocate_size<Encoding0> (Encoding0::min_size + HBUINT8::static_size * enc_count);
Ebrahim Byagowi2be859d2020-04-20 23:48:23 +0430197 if (unlikely (!fmt0)) return_trace (false);
Behdad Esfahbodb986c6a2019-03-29 20:17:46 -0700198 fmt0->nCodes () = enc_count;
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700199 unsigned int glyph = 0;
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500200 for (unsigned int i = 0; i < code_ranges.length; i++)
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700201 {
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500202 hb_codepoint_t code = code_ranges[i].code;
203 for (int left = (int)code_ranges[i].glyph; left >= 0; left--)
Behdad Esfahbodb986c6a2019-03-29 20:17:46 -0700204 fmt0->codes[glyph++] = code++;
Michiharu Ariza33358622018-12-11 12:20:20 -0800205 if (unlikely (!((glyph <= 0x100) && (code <= 0x100))))
206 return_trace (false);
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700207 }
208 }
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430209 break;
210
211 case 1:
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700212 {
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500213 Encoding1 *fmt1 = c->allocate_size<Encoding1> (Encoding1::min_size + Encoding1_Range::static_size * code_ranges.length);
Ebrahim Byagowi2be859d2020-04-20 23:48:23 +0430214 if (unlikely (!fmt1)) return_trace (false);
Behdad Esfahbodb986c6a2019-03-29 20:17:46 -0700215 fmt1->nRanges () = code_ranges.length;
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500216 for (unsigned int i = 0; i < code_ranges.length; i++)
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700217 {
Michiharu Ariza33358622018-12-11 12:20:20 -0800218 if (unlikely (!((code_ranges[i].code <= 0xFF) && (code_ranges[i].glyph <= 0xFF))))
219 return_trace (false);
Behdad Esfahbodb986c6a2019-03-29 20:17:46 -0700220 fmt1->ranges[i].first = code_ranges[i].code;
221 fmt1->ranges[i].nLeft = code_ranges[i].glyph;
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700222 }
223 }
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430224 break;
225
226 }
227
228 if (supp_codes.length)
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700229 {
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500230 CFF1SuppEncData *suppData = c->allocate_size<CFF1SuppEncData> (CFF1SuppEncData::min_size + SuppEncoding::static_size * supp_codes.length);
Ebrahim Byagowi2be859d2020-04-20 23:48:23 +0430231 if (unlikely (!suppData)) return_trace (false);
Behdad Esfahbodb986c6a2019-03-29 20:17:46 -0700232 suppData->nSups () = supp_codes.length;
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500233 for (unsigned int i = 0; i < supp_codes.length; i++)
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700234 {
Behdad Esfahbodb986c6a2019-03-29 20:17:46 -0700235 suppData->supps[i].code = supp_codes[i].code;
236 suppData->supps[i].glyph = supp_codes[i].glyph; /* actually SID */
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700237 }
238 }
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430239
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700240 return_trace (true);
241 }
242
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330243 unsigned int get_size () const
Michiharu Ariza64c54122018-08-10 11:07:07 -0700244 {
245 unsigned int size = min_size;
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430246 switch (table_format ())
247 {
248 case 0: size += u.format0.get_size (); break;
249 case 1: size += u.format1.get_size (); break;
250 }
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700251 if (has_supplement ())
Michiharu Ariza64c54122018-08-10 11:07:07 -0700252 size += suppEncData ().get_size ();
253 return size;
254 }
255
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330256 hb_codepoint_t get_code (hb_codepoint_t glyph) const
Michiharu Ariza64c54122018-08-10 11:07:07 -0700257 {
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430258 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 }
Michiharu Ariza64c54122018-08-10 11:07:07 -0700264 }
265
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430266 uint8_t table_format () const { return format & 0x7F; }
267 bool has_supplement () const { return format & 0x80; }
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700268
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330269 void get_supplement_codes (hb_codepoint_t sid, hb_vector_t<hb_codepoint_t> &codes) const
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700270 {
271 codes.resize (0);
272 if (has_supplement ())
273 suppEncData().get_codes (sid, codes);
274 }
275
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430276 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
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700291 protected:
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330292 const CFF1SuppEncData &suppEncData () const
Michiharu Ariza64c54122018-08-10 11:07:07 -0700293 {
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430294 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 }
Michiharu Ariza64c54122018-08-10 11:07:07 -0700300 }
301
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700302 public:
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430303 HBUINT8 format;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700304 union {
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430305 Encoding0 format0;
306 Encoding1 format1;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700307 } u;
Michiharu Arizafdbfa182018-08-16 00:13:09 -0700308 /* CFF1SuppEncData suppEncData; */
Michiharu Ariza64c54122018-08-10 11:07:07 -0700309
310 DEFINE_SIZE_MIN (1);
311};
312
313/* Charset */
314struct Charset0 {
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330315 bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
Michiharu Ariza64c54122018-08-10 11:07:07 -0700316 {
317 TRACE_SANITIZE (this);
318 return_trace (c->check_struct (this) && sids[num_glyphs - 1].sanitize (c));
319 }
320
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330321 hb_codepoint_t get_sid (hb_codepoint_t glyph) const
Michiharu Ariza64c54122018-08-10 11:07:07 -0700322 {
323 if (glyph == 0)
324 return 0;
325 else
326 return sids[glyph - 1];
327 }
328
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330329 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
Michiharu Ariza3787c072018-11-14 13:38:03 -0800330 {
331 if (sid == 0)
332 return 0;
333
334 for (unsigned int glyph = 1; glyph < num_glyphs; glyph++)
335 {
336 if (sids[glyph-1] == sid)
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500337 return glyph;
Michiharu Ariza3787c072018-11-14 13:38:03 -0800338 }
339 return 0;
340 }
341
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330342 unsigned int get_size (unsigned int num_glyphs) const
Michiharu Ariza64c54122018-08-10 11:07:07 -0700343 {
344 assert (num_glyphs > 0);
345 return HBUINT16::static_size * (num_glyphs - 1);
346 }
347
Behdad Esfahbod0e294c42019-09-06 16:54:27 -0400348 HBUINT16 sids[HB_VAR_ARRAY];
Michiharu Ariza64c54122018-08-10 11:07:07 -0700349
350 DEFINE_SIZE_ARRAY(0, sids);
351};
352
353template <typename TYPE>
354struct Charset_Range {
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330355 bool sanitize (hb_sanitize_context_t *c) const
Michiharu Ariza64c54122018-08-10 11:07:07 -0700356 {
357 TRACE_SANITIZE (this);
358 return_trace (c->check_struct (this));
359 }
360
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700361 HBUINT16 first;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700362 TYPE nLeft;
363
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700364 DEFINE_SIZE_STATIC (HBUINT16::static_size + TYPE::static_size);
Michiharu Ariza64c54122018-08-10 11:07:07 -0700365};
366
367template <typename TYPE>
368struct Charset1_2 {
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330369 bool sanitize (hb_sanitize_context_t *c, unsigned int num_glyphs) const
Michiharu Ariza64c54122018-08-10 11:07:07 -0700370 {
371 TRACE_SANITIZE (this);
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700372 if (unlikely (!c->check_struct (this)))
373 return_trace (false);
374 num_glyphs--;
375 for (unsigned int i = 0; num_glyphs > 0; i++)
376 {
377 if (unlikely (!ranges[i].sanitize (c) || (num_glyphs < ranges[i].nLeft + 1)))
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500378 return_trace (false);
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700379 num_glyphs -= (ranges[i].nLeft + 1);
380 }
381 return_trace (true);
Michiharu Ariza64c54122018-08-10 11:07:07 -0700382 }
383
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330384 hb_codepoint_t get_sid (hb_codepoint_t glyph) const
Michiharu Ariza64c54122018-08-10 11:07:07 -0700385 {
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700386 if (glyph == 0) return 0;
387 glyph--;
388 for (unsigned int i = 0;; i++)
Michiharu Ariza64c54122018-08-10 11:07:07 -0700389 {
390 if (glyph <= ranges[i].nLeft)
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500391 return (hb_codepoint_t)ranges[i].first + glyph;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700392 glyph -= (ranges[i].nLeft + 1);
393 }
Behdad Esfahbod592f39b2018-11-30 22:54:57 -0500394
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700395 return 0;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700396 }
397
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330398 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
Michiharu Ariza3787c072018-11-14 13:38:03 -0800399 {
400 if (sid == 0) return 0;
401 hb_codepoint_t glyph = 1;
402 for (unsigned int i = 0;; i++)
403 {
Michiharu Arizad3d2f322018-12-04 13:51:26 -0800404 if (glyph >= num_glyphs)
Ebrahim Byagowice114d62019-12-31 15:53:02 +0330405 return 0;
Michiharu Arizad3d2f322018-12-04 13:51:26 -0800406 if ((ranges[i].first <= sid) && (sid <= ranges[i].first + ranges[i].nLeft))
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500407 return glyph + (sid - ranges[i].first);
Michiharu Ariza3787c072018-11-14 13:38:03 -0800408 glyph += (ranges[i].nLeft + 1);
409 }
Behdad Esfahbod592f39b2018-11-30 22:54:57 -0500410
Michiharu Ariza3787c072018-11-14 13:38:03 -0800411 return 0;
412 }
413
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330414 unsigned int get_size (unsigned int num_glyphs) const
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700415 {
416 unsigned int size = HBUINT8::static_size;
417 int glyph = (int)num_glyphs;
Behdad Esfahbod592f39b2018-11-30 22:54:57 -0500418
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700419 assert (glyph > 0);
420 glyph--;
421 for (unsigned int i = 0; glyph > 0; i++)
422 {
423 glyph -= (ranges[i].nLeft + 1);
424 size += Charset_Range<TYPE>::static_size;
425 }
Michiharu Ariza64c54122018-08-10 11:07:07 -0700426
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700427 return size;
428 }
429
Behdad Esfahbod0e294c42019-09-06 16:54:27 -0400430 Charset_Range<TYPE> ranges[HB_VAR_ARRAY];
Michiharu Ariza64c54122018-08-10 11:07:07 -0700431
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700432 DEFINE_SIZE_ARRAY (0, ranges);
Michiharu Ariza64c54122018-08-10 11:07:07 -0700433};
434
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700435typedef Charset1_2<HBUINT8> Charset1;
436typedef Charset1_2<HBUINT16> Charset2;
437typedef Charset_Range<HBUINT8> Charset1_Range;
438typedef Charset_Range<HBUINT16> Charset2_Range;
439
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430440struct Charset
441{
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700442 /* serialize a fullset Charset */
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330443 bool serialize (hb_serialize_context_t *c, const Charset &src, unsigned int num_glyphs)
Michiharu Ariza64c54122018-08-10 11:07:07 -0700444 {
445 TRACE_SERIALIZE (this);
446 unsigned int size = src.get_size (num_glyphs);
447 Charset *dest = c->allocate_size<Charset> (size);
Ebrahim Byagowi2be859d2020-04-20 23:48:23 +0430448 if (unlikely (!dest)) return_trace (false);
Michiharu Ariza64c54122018-08-10 11:07:07 -0700449 memcpy (dest, &src, size);
450 return_trace (true);
451 }
452
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700453 /* serialize a subset Charset */
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330454 bool serialize (hb_serialize_context_t *c,
455 uint8_t format,
456 unsigned int num_glyphs,
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800457 const hb_vector_t<code_pair_t>& sid_ranges)
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700458 {
459 TRACE_SERIALIZE (this);
Behdad Esfahbodf0a18922021-07-28 17:36:22 -0600460 Charset *dest = c->extend_min (this);
Ebrahim Byagowi2be859d2020-04-20 23:48:23 +0430461 if (unlikely (!dest)) return_trace (false);
Behdad Esfahbodb986c6a2019-03-29 20:17:46 -0700462 dest->format = format;
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430463 switch (format)
464 {
465 case 0:
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700466 {
Michiharu Ariza16084812018-09-12 13:22:19 -0700467 Charset0 *fmt0 = c->allocate_size<Charset0> (Charset0::min_size + HBUINT16::static_size * (num_glyphs - 1));
Ebrahim Byagowi2be859d2020-04-20 23:48:23 +0430468 if (unlikely (!fmt0)) return_trace (false);
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700469 unsigned int glyph = 0;
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500470 for (unsigned int i = 0; i < sid_ranges.length; i++)
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700471 {
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500472 hb_codepoint_t sid = sid_ranges[i].code;
473 for (int left = (int)sid_ranges[i].glyph; left >= 0; left--)
Behdad Esfahbodb986c6a2019-03-29 20:17:46 -0700474 fmt0->sids[glyph++] = sid++;
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700475 }
476 }
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430477 break;
478
479 case 1:
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700480 {
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500481 Charset1 *fmt1 = c->allocate_size<Charset1> (Charset1::min_size + Charset1_Range::static_size * sid_ranges.length);
Ebrahim Byagowi2be859d2020-04-20 23:48:23 +0430482 if (unlikely (!fmt1)) return_trace (false);
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500483 for (unsigned int i = 0; i < sid_ranges.length; i++)
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700484 {
Ebrahim Byagowice114d62019-12-31 15:53:02 +0330485 if (unlikely (!(sid_ranges[i].glyph <= 0xFF)))
Michiharu Ariza33358622018-12-11 12:20:20 -0800486 return_trace (false);
Behdad Esfahbodb986c6a2019-03-29 20:17:46 -0700487 fmt1->ranges[i].first = sid_ranges[i].code;
488 fmt1->ranges[i].nLeft = sid_ranges[i].glyph;
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700489 }
490 }
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430491 break;
492
493 case 2:
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700494 {
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500495 Charset2 *fmt2 = c->allocate_size<Charset2> (Charset2::min_size + Charset2_Range::static_size * sid_ranges.length);
Ebrahim Byagowi2be859d2020-04-20 23:48:23 +0430496 if (unlikely (!fmt2)) return_trace (false);
Behdad Esfahbod474a1202018-12-21 18:46:51 -0500497 for (unsigned int i = 0; i < sid_ranges.length; i++)
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700498 {
Ebrahim Byagowice114d62019-12-31 15:53:02 +0330499 if (unlikely (!(sid_ranges[i].glyph <= 0xFFFF)))
Michiharu Ariza33358622018-12-11 12:20:20 -0800500 return_trace (false);
Behdad Esfahbodb986c6a2019-03-29 20:17:46 -0700501 fmt2->ranges[i].first = sid_ranges[i].code;
502 fmt2->ranges[i].nLeft = sid_ranges[i].glyph;
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700503 }
504 }
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430505 break;
506
507 }
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700508 return_trace (true);
509 }
510
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330511 unsigned int get_size (unsigned int num_glyphs) const
Michiharu Ariza64c54122018-08-10 11:07:07 -0700512 {
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430513 switch (format)
514 {
515 case 0: return min_size + u.format0.get_size (num_glyphs);
516 case 1: return min_size + u.format1.get_size (num_glyphs);
517 case 2: return min_size + u.format2.get_size (num_glyphs);
518 default:return 0;
519 }
Michiharu Ariza64c54122018-08-10 11:07:07 -0700520 }
521
blueshade759fe3792019-11-16 19:47:31 -0800522 hb_codepoint_t get_sid (hb_codepoint_t glyph, unsigned int num_glyphs) const
Michiharu Ariza64c54122018-08-10 11:07:07 -0700523 {
blueshade759fe3792019-11-16 19:47:31 -0800524 if (unlikely (glyph >= num_glyphs)) return 0;
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430525 switch (format)
526 {
527 case 0: return u.format0.get_sid (glyph);
528 case 1: return u.format1.get_sid (glyph);
529 case 2: return u.format2.get_sid (glyph);
530 default:return 0;
531 }
Michiharu Ariza64c54122018-08-10 11:07:07 -0700532 }
533
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330534 hb_codepoint_t get_glyph (hb_codepoint_t sid, unsigned int num_glyphs) const
Michiharu Ariza3787c072018-11-14 13:38:03 -0800535 {
Ebrahim Byagowi9b853f72019-06-09 11:49:25 +0430536 switch (format)
537 {
538 case 0: return u.format0.get_glyph (sid, num_glyphs);
539 case 1: return u.format1.get_glyph (sid, num_glyphs);
540 case 2: return u.format2.get_glyph (sid, num_glyphs);
541 default:return 0;
542 }
543 }
544
545 bool sanitize (hb_sanitize_context_t *c) const
546 {
547 TRACE_SANITIZE (this);
548 if (unlikely (!c->check_struct (this)))
549 return_trace (false);
550
551 switch (format)
552 {
553 case 0: return_trace (u.format0.sanitize (c, c->get_num_glyphs ()));
554 case 1: return_trace (u.format1.sanitize (c, c->get_num_glyphs ()));
555 case 2: return_trace (u.format2.sanitize (c, c->get_num_glyphs ()));
556 default:return_trace (false);
557 }
Michiharu Ariza3787c072018-11-14 13:38:03 -0800558 }
559
Michiharu Ariza64c54122018-08-10 11:07:07 -0700560 HBUINT8 format;
561 union {
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700562 Charset0 format0;
563 Charset1 format1;
564 Charset2 format2;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700565 } u;
566
567 DEFINE_SIZE_MIN (1);
568};
569
Michiharu Ariza1666b892018-09-10 16:00:20 -0700570struct CFF1StringIndex : CFF1Index
571{
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330572 bool serialize (hb_serialize_context_t *c, const CFF1StringIndex &strings,
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +0430573 const hb_inc_bimap_t &sidmap)
Michiharu Ariza1666b892018-09-10 16:00:20 -0700574 {
575 TRACE_SERIALIZE (this);
Michiharu Ariza09496692019-06-17 22:12:40 -0700576 if (unlikely ((strings.count == 0) || (sidmap.get_population () == 0)))
Michiharu Ariza1666b892018-09-10 16:00:20 -0700577 {
Behdad Esfahbod0ca7ad42019-05-20 11:39:07 -0400578 if (unlikely (!c->extend_min (this->count)))
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +0430579 return_trace (false);
Behdad Esfahbodb986c6a2019-03-29 20:17:46 -0700580 count = 0;
Michiharu Ariza1666b892018-09-10 16:00:20 -0700581 return_trace (true);
582 }
Behdad Esfahbod592f39b2018-11-30 22:54:57 -0500583
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800584 byte_str_array_t bytesArray;
Michiharu Ariza1666b892018-09-10 16:00:20 -0700585 bytesArray.init ();
Michiharu Ariza09496692019-06-17 22:12:40 -0700586 if (!bytesArray.resize (sidmap.get_population ()))
Michiharu Ariza1666b892018-09-10 16:00:20 -0700587 return_trace (false);
588 for (unsigned int i = 0; i < strings.count; i++)
589 {
Michiharu Arizaf3ee2bd2019-06-20 14:33:09 -0700590 hb_codepoint_t j = sidmap[i];
Michiharu Arizac8420102019-02-20 15:48:29 -0800591 if (j != HB_MAP_VALUE_INVALID)
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +0430592 bytesArray[j] = strings[i];
Michiharu Ariza1666b892018-09-10 16:00:20 -0700593 }
594
arizac05458e2020-03-02 16:51:19 -0800595 bool result = CFF1Index::serialize (c, bytesArray);
Michiharu Ariza1666b892018-09-10 16:00:20 -0700596 bytesArray.fini ();
597 return_trace (result);
598 }
Michiharu Ariza1666b892018-09-10 16:00:20 -0700599};
600
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800601struct cff1_top_dict_interp_env_t : num_interp_env_t
Michiharu Ariza1666b892018-09-10 16:00:20 -0700602{
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800603 cff1_top_dict_interp_env_t ()
604 : num_interp_env_t(), prev_offset(0), last_offset(0) {}
Michiharu Ariza1666b892018-09-10 16:00:20 -0700605
606 unsigned int prev_offset;
607 unsigned int last_offset;
608};
609
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800610struct name_dict_values_t
Michiharu Ariza1666b892018-09-10 16:00:20 -0700611{
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800612 enum name_dict_val_index_t
Michiharu Arizac6f75c32018-09-10 17:02:31 -0700613 {
614 version,
615 notice,
616 copyright,
617 fullName,
618 familyName,
619 weight,
620 postscript,
621 fontName,
622 baseFontName,
623 registry,
624 ordering,
625
626 ValCount
627 };
628
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330629 void init ()
Michiharu Ariza1666b892018-09-10 16:00:20 -0700630 {
Michiharu Arizac6f75c32018-09-10 17:02:31 -0700631 for (unsigned int i = 0; i < ValCount; i++)
Michiharu Ariza1666b892018-09-10 16:00:20 -0700632 values[i] = CFF_UNDEF_SID;
633 }
634
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330635 unsigned int& operator[] (unsigned int i)
Michiharu Arizac6f75c32018-09-10 17:02:31 -0700636 { assert (i < ValCount); return values[i]; }
Michiharu Ariza1666b892018-09-10 16:00:20 -0700637
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330638 unsigned int operator[] (unsigned int i) const
Michiharu Arizac6f75c32018-09-10 17:02:31 -0700639 { assert (i < ValCount); return values[i]; }
Michiharu Ariza1666b892018-09-10 16:00:20 -0700640
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800641 static enum name_dict_val_index_t name_op_to_index (op_code_t op)
Michiharu Ariza1666b892018-09-10 16:00:20 -0700642 {
643 switch (op) {
Michiharu Ariza4d809692018-12-07 20:49:39 -0800644 default: // can't happen - just make some compiler happy
Michiharu Ariza1666b892018-09-10 16:00:20 -0700645 case OpCode_version:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500646 return version;
Michiharu Ariza1666b892018-09-10 16:00:20 -0700647 case OpCode_Notice:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500648 return notice;
Michiharu Ariza1666b892018-09-10 16:00:20 -0700649 case OpCode_Copyright:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500650 return copyright;
Michiharu Ariza1666b892018-09-10 16:00:20 -0700651 case OpCode_FullName:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500652 return fullName;
Michiharu Ariza1666b892018-09-10 16:00:20 -0700653 case OpCode_FamilyName:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500654 return familyName;
Michiharu Ariza1666b892018-09-10 16:00:20 -0700655 case OpCode_Weight:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500656 return weight;
Michiharu Ariza1666b892018-09-10 16:00:20 -0700657 case OpCode_PostScript:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500658 return postscript;
Michiharu Ariza1666b892018-09-10 16:00:20 -0700659 case OpCode_FontName:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500660 return fontName;
Michiharu Ariza4d809692018-12-07 20:49:39 -0800661 case OpCode_BaseFontName:
662 return baseFontName;
663 }
Michiharu Ariza1666b892018-09-10 16:00:20 -0700664 }
665
Michiharu Arizac6f75c32018-09-10 17:02:31 -0700666 unsigned int values[ValCount];
Michiharu Ariza1666b892018-09-10 16:00:20 -0700667};
668
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800669struct cff1_top_dict_val_t : op_str_t
Michiharu Ariza1666b892018-09-10 16:00:20 -0700670{
671 unsigned int last_arg_offset;
672};
673
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800674struct cff1_top_dict_values_t : top_dict_values_t<cff1_top_dict_val_t>
Michiharu Ariza64c54122018-08-10 11:07:07 -0700675{
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330676 void init ()
Michiharu Ariza64c54122018-08-10 11:07:07 -0700677 {
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800678 top_dict_values_t<cff1_top_dict_val_t>::init ();
Michiharu Ariza64c54122018-08-10 11:07:07 -0700679
Michiharu Ariza1666b892018-09-10 16:00:20 -0700680 nameSIDs.init ();
681 ros_supplement = 0;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700682 cidCount = 8720;
683 EncodingOffset = 0;
684 CharsetOffset = 0;
685 FDSelectOffset = 0;
ariza0b290532020-03-04 22:31:21 -0800686 privateDictInfo.init ();
Michiharu Ariza64c54122018-08-10 11:07:07 -0700687 }
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800688 void fini () { top_dict_values_t<cff1_top_dict_val_t>::fini (); }
Michiharu Ariza64c54122018-08-10 11:07:07 -0700689
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330690 bool is_CID () const
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800691 { return nameSIDs[name_dict_values_t::registry] != CFF_UNDEF_SID; }
Michiharu Ariza64c54122018-08-10 11:07:07 -0700692
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800693 name_dict_values_t nameSIDs;
Michiharu Ariza1666b892018-09-10 16:00:20 -0700694 unsigned int ros_supplement_offset;
695 unsigned int ros_supplement;
696 unsigned int cidCount;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700697
Michiharu Ariza1666b892018-09-10 16:00:20 -0700698 unsigned int EncodingOffset;
699 unsigned int CharsetOffset;
700 unsigned int FDSelectOffset;
ariza0b290532020-03-04 22:31:21 -0800701 table_info_t privateDictInfo;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700702};
703
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800704struct cff1_top_dict_opset_t : top_dict_opset_t<cff1_top_dict_val_t>
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700705{
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800706 static void process_op (op_code_t op, cff1_top_dict_interp_env_t& env, cff1_top_dict_values_t& dictval)
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700707 {
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800708 cff1_top_dict_val_t val;
Michiharu Ariza1666b892018-09-10 16:00:20 -0700709 val.last_arg_offset = (env.last_offset-1) - dictval.opStart; /* offset to the last argument */
Michiharu Arizaaca73c92018-09-06 17:28:15 -0700710
Michiharu Ariza64c54122018-08-10 11:07:07 -0700711 switch (op) {
712 case OpCode_version:
713 case OpCode_Notice:
714 case OpCode_Copyright:
715 case OpCode_FullName:
Garret Riegerdeee24f2021-07-14 13:46:36 -0700716 case OpCode_FontName:
Michiharu Ariza64c54122018-08-10 11:07:07 -0700717 case OpCode_FamilyName:
718 case OpCode_Weight:
Michiharu Ariza1666b892018-09-10 16:00:20 -0700719 case OpCode_PostScript:
720 case OpCode_BaseFontName:
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800721 dictval.nameSIDs[name_dict_values_t::name_op_to_index (op)] = env.argStack.pop_uint ();
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500722 env.clear_args ();
723 break;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700724 case OpCode_isFixedPitch:
725 case OpCode_ItalicAngle:
726 case OpCode_UnderlinePosition:
727 case OpCode_UnderlineThickness:
728 case OpCode_PaintType:
729 case OpCode_CharstringType:
730 case OpCode_UniqueID:
731 case OpCode_StrokeWidth:
732 case OpCode_SyntheticBase:
Michiharu Ariza64c54122018-08-10 11:07:07 -0700733 case OpCode_CIDFontVersion:
734 case OpCode_CIDFontRevision:
735 case OpCode_CIDFontType:
736 case OpCode_UIDBase:
737 case OpCode_FontBBox:
738 case OpCode_XUID:
739 case OpCode_BaseFontBlend:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500740 env.clear_args ();
741 break;
Behdad Esfahbod592f39b2018-11-30 22:54:57 -0500742
Michiharu Ariza64c54122018-08-10 11:07:07 -0700743 case OpCode_CIDCount:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500744 dictval.cidCount = env.argStack.pop_uint ();
745 env.clear_args ();
746 break;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700747
748 case OpCode_ROS:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500749 dictval.ros_supplement = env.argStack.pop_uint ();
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800750 dictval.nameSIDs[name_dict_values_t::ordering] = env.argStack.pop_uint ();
751 dictval.nameSIDs[name_dict_values_t::registry] = env.argStack.pop_uint ();
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500752 env.clear_args ();
753 break;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700754
755 case OpCode_Encoding:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500756 dictval.EncodingOffset = env.argStack.pop_uint ();
757 env.clear_args ();
758 if (unlikely (dictval.EncodingOffset == 0)) return;
759 break;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700760
761 case OpCode_charset:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500762 dictval.CharsetOffset = env.argStack.pop_uint ();
763 env.clear_args ();
764 if (unlikely (dictval.CharsetOffset == 0)) return;
765 break;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700766
767 case OpCode_FDSelect:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500768 dictval.FDSelectOffset = env.argStack.pop_uint ();
769 env.clear_args ();
770 break;
Behdad Esfahbod592f39b2018-11-30 22:54:57 -0500771
Michiharu Ariza64c54122018-08-10 11:07:07 -0700772 case OpCode_Private:
ariza0b290532020-03-04 22:31:21 -0800773 dictval.privateDictInfo.offset = env.argStack.pop_uint ();
774 dictval.privateDictInfo.size = env.argStack.pop_uint ();
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500775 env.clear_args ();
776 break;
Behdad Esfahbod592f39b2018-11-30 22:54:57 -0500777
Michiharu Ariza64c54122018-08-10 11:07:07 -0700778 default:
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800779 env.last_offset = env.str_ref.offset;
780 top_dict_opset_t<cff1_top_dict_val_t>::process_op (op, env, dictval);
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500781 /* Record this operand below if stack is empty, otherwise done */
782 if (!env.argStack.is_empty ()) return;
783 break;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700784 }
785
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700786 if (unlikely (env.in_error ())) return;
787
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800788 dictval.add_op (op, env.str_ref, val);
Michiharu Ariza64c54122018-08-10 11:07:07 -0700789 }
790};
791
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800792struct cff1_font_dict_values_t : dict_values_t<op_str_t>
Michiharu Ariza64c54122018-08-10 11:07:07 -0700793{
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330794 void init ()
Michiharu Ariza64c54122018-08-10 11:07:07 -0700795 {
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800796 dict_values_t<op_str_t>::init ();
ariza0b290532020-03-04 22:31:21 -0800797 privateDictInfo.init ();
Michiharu Ariza1666b892018-09-10 16:00:20 -0700798 fontName = CFF_UNDEF_SID;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700799 }
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800800 void fini () { dict_values_t<op_str_t>::fini (); }
Michiharu Ariza64c54122018-08-10 11:07:07 -0700801
ariza0b290532020-03-04 22:31:21 -0800802 table_info_t privateDictInfo;
Michiharu Ariza1666b892018-09-10 16:00:20 -0700803 unsigned int fontName;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700804};
805
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800806struct cff1_font_dict_opset_t : dict_opset_t
Michiharu Ariza64c54122018-08-10 11:07:07 -0700807{
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800808 static void process_op (op_code_t op, num_interp_env_t& env, cff1_font_dict_values_t& dictval)
Michiharu Ariza64c54122018-08-10 11:07:07 -0700809 {
810 switch (op) {
811 case OpCode_FontName:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500812 dictval.fontName = env.argStack.pop_uint ();
813 env.clear_args ();
814 break;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700815 case OpCode_FontMatrix:
816 case OpCode_PaintType:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500817 env.clear_args ();
818 break;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700819 case OpCode_Private:
ariza0b290532020-03-04 22:31:21 -0800820 dictval.privateDictInfo.offset = env.argStack.pop_uint ();
821 dictval.privateDictInfo.size = env.argStack.pop_uint ();
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500822 env.clear_args ();
823 break;
Behdad Esfahbod592f39b2018-11-30 22:54:57 -0500824
Michiharu Ariza64c54122018-08-10 11:07:07 -0700825 default:
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800826 dict_opset_t::process_op (op, env);
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500827 if (!env.argStack.is_empty ()) return;
828 break;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700829 }
830
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700831 if (unlikely (env.in_error ())) return;
832
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800833 dictval.add_op (op, env.str_ref);
Michiharu Ariza64c54122018-08-10 11:07:07 -0700834 }
835};
836
837template <typename VAL>
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800838struct cff1_private_dict_values_base_t : dict_values_t<VAL>
Michiharu Ariza64c54122018-08-10 11:07:07 -0700839{
Ebrahim Byagowie4120082018-12-17 21:31:01 +0330840 void init ()
Michiharu Ariza64c54122018-08-10 11:07:07 -0700841 {
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800842 dict_values_t<VAL>::init ();
Michiharu Ariza64c54122018-08-10 11:07:07 -0700843 subrsOffset = 0;
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +0430844 localSubrs = &Null (CFF1Subrs);
Michiharu Ariza64c54122018-08-10 11:07:07 -0700845 }
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800846 void fini () { dict_values_t<VAL>::fini (); }
Michiharu Ariza64c54122018-08-10 11:07:07 -0700847
Michiharu Ariza64c54122018-08-10 11:07:07 -0700848 unsigned int subrsOffset;
Michiharu Arizafdbfa182018-08-16 00:13:09 -0700849 const CFF1Subrs *localSubrs;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700850};
851
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800852typedef cff1_private_dict_values_base_t<op_str_t> cff1_private_dict_values_subset_t;
853typedef cff1_private_dict_values_base_t<num_dict_val_t> cff1_private_dict_values_t;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700854
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800855struct cff1_private_dict_opset_t : dict_opset_t
Michiharu Ariza64c54122018-08-10 11:07:07 -0700856{
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800857 static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_t& dictval)
Michiharu Ariza64c54122018-08-10 11:07:07 -0700858 {
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800859 num_dict_val_t val;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700860 val.init ();
861
862 switch (op) {
863 case OpCode_BlueValues:
864 case OpCode_OtherBlues:
865 case OpCode_FamilyBlues:
866 case OpCode_FamilyOtherBlues:
867 case OpCode_StemSnapH:
868 case OpCode_StemSnapV:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500869 env.clear_args ();
870 break;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700871 case OpCode_StdHW:
872 case OpCode_StdVW:
873 case OpCode_BlueScale:
874 case OpCode_BlueShift:
875 case OpCode_BlueFuzz:
876 case OpCode_ForceBold:
877 case OpCode_LanguageGroup:
878 case OpCode_ExpansionFactor:
879 case OpCode_initialRandomSeed:
880 case OpCode_defaultWidthX:
881 case OpCode_nominalWidthX:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500882 val.single_val = env.argStack.pop_num ();
883 env.clear_args ();
884 break;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700885 case OpCode_Subrs:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500886 dictval.subrsOffset = env.argStack.pop_uint ();
887 env.clear_args ();
888 break;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700889
890 default:
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800891 dict_opset_t::process_op (op, env);
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500892 if (!env.argStack.is_empty ()) return;
893 break;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700894 }
895
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700896 if (unlikely (env.in_error ())) return;
897
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800898 dictval.add_op (op, env.str_ref, val);
Michiharu Ariza64c54122018-08-10 11:07:07 -0700899 }
900};
901
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800902struct cff1_private_dict_opset_subset : dict_opset_t
Michiharu Ariza64c54122018-08-10 11:07:07 -0700903{
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800904 static void process_op (op_code_t op, num_interp_env_t& env, cff1_private_dict_values_subset_t& dictval)
Michiharu Ariza64c54122018-08-10 11:07:07 -0700905 {
906 switch (op) {
907 case OpCode_BlueValues:
908 case OpCode_OtherBlues:
909 case OpCode_FamilyBlues:
910 case OpCode_FamilyOtherBlues:
911 case OpCode_StemSnapH:
912 case OpCode_StemSnapV:
913 case OpCode_StdHW:
914 case OpCode_StdVW:
915 case OpCode_BlueScale:
916 case OpCode_BlueShift:
917 case OpCode_BlueFuzz:
918 case OpCode_ForceBold:
919 case OpCode_LanguageGroup:
920 case OpCode_ExpansionFactor:
921 case OpCode_initialRandomSeed:
922 case OpCode_defaultWidthX:
923 case OpCode_nominalWidthX:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500924 env.clear_args ();
925 break;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700926
Michiharu Ariza64c54122018-08-10 11:07:07 -0700927 case OpCode_Subrs:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500928 dictval.subrsOffset = env.argStack.pop_uint ();
929 env.clear_args ();
930 break;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700931
932 default:
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800933 dict_opset_t::process_op (op, env);
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500934 if (!env.argStack.is_empty ()) return;
935 break;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700936 }
937
Michiharu Ariza7d99a6c2018-10-12 02:16:07 -0700938 if (unlikely (env.in_error ())) return;
939
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800940 dictval.add_op (op, env.str_ref);
Michiharu Ariza64c54122018-08-10 11:07:07 -0700941 }
942};
943
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -0800944typedef dict_interpreter_t<cff1_top_dict_opset_t, cff1_top_dict_values_t, cff1_top_dict_interp_env_t> cff1_top_dict_interpreter_t;
945typedef dict_interpreter_t<cff1_font_dict_opset_t, cff1_font_dict_values_t> cff1_font_dict_interpreter_t;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700946
Michiharu Arizafdbfa182018-08-16 00:13:09 -0700947typedef CFF1Index CFF1NameIndex;
948typedef CFF1IndexOf<TopDict> CFF1TopDictIndex;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700949
arizac05458e2020-03-02 16:51:19 -0800950struct cff1_font_dict_values_mod_t
951{
952 cff1_font_dict_values_mod_t() { init (); }
953
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +0430954 void init () { init ( &Null (cff1_font_dict_values_t), CFF_UNDEF_SID ); }
arizac05458e2020-03-02 16:51:19 -0800955
956 void init (const cff1_font_dict_values_t *base_,
957 unsigned int fontName_)
958 {
959 base = base_;
960 fontName = fontName_;
ariza0b290532020-03-04 22:31:21 -0800961 privateDictInfo.init ();
arizac05458e2020-03-02 16:51:19 -0800962 }
963
964 unsigned get_count () const { return base->get_count (); }
965
966 const op_str_t &operator [] (unsigned int i) const { return (*base)[i]; }
967
968 const cff1_font_dict_values_t *base;
ariza0b290532020-03-04 22:31:21 -0800969 table_info_t privateDictInfo;
arizac05458e2020-03-02 16:51:19 -0800970 unsigned int fontName;
971};
972
973struct CFF1FDArray : FDArray<HBUINT16>
974{
975 /* FDArray::serialize() requires this partial specialization to compile */
976 template <typename ITER, typename OP_SERIALIZER>
977 bool serialize (hb_serialize_context_t *c, ITER it, OP_SERIALIZER& opszr)
978 { return FDArray<HBUINT16>::serialize<cff1_font_dict_values_mod_t, cff1_font_dict_values_mod_t> (c, it, opszr); }
979};
980
Behdad Esfahbodd25a2f12018-12-23 20:19:52 -0500981} /* namespace CFF */
Michiharu Ariza64c54122018-08-10 11:07:07 -0700982
983namespace OT {
984
985using namespace CFF;
986
Michiharu Arizae67bb3f2018-08-16 00:25:57 -0700987struct cff1
Michiharu Ariza64c54122018-08-10 11:07:07 -0700988{
Behdad Esfahbodef006542019-01-22 12:08:57 +0100989 static constexpr hb_tag_t tableTag = HB_OT_TAG_cff1;
Michiharu Ariza64c54122018-08-10 11:07:07 -0700990
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +0330991 bool sanitize (hb_sanitize_context_t *c) const
Michiharu Ariza64c54122018-08-10 11:07:07 -0700992 {
993 TRACE_SANITIZE (this);
994 return_trace (c->check_struct (this) &&
Behdad Esfahbod825df6d2018-11-30 23:04:59 -0500995 likely (version.major == 1));
Michiharu Ariza64c54122018-08-10 11:07:07 -0700996 }
997
Michiharu Arizafcf17782018-08-31 16:28:47 -0700998 template <typename PRIVOPSET, typename PRIVDICTVAL>
Michiharu Ariza64c54122018-08-10 11:07:07 -0700999 struct accelerator_templ_t
1000 {
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301001 void init (hb_face_t *face)
Michiharu Ariza64c54122018-08-10 11:07:07 -07001002 {
Michiharu Ariza1666b892018-09-10 16:00:20 -07001003 topDict.init ();
Michiharu Ariza64c54122018-08-10 11:07:07 -07001004 fontDicts.init ();
1005 privateDicts.init ();
Behdad Esfahbod592f39b2018-11-30 22:54:57 -05001006
Michiharu Arizae67bb3f2018-08-16 00:25:57 -07001007 this->blob = sc.reference_table<cff1> (face);
Michiharu Ariza64c54122018-08-10 11:07:07 -07001008
1009 /* setup for run-time santization */
1010 sc.init (this->blob);
1011 sc.start_processing ();
Behdad Esfahbod592f39b2018-11-30 22:54:57 -05001012
Michiharu Arizae67bb3f2018-08-16 00:25:57 -07001013 const OT::cff1 *cff = this->blob->template as<OT::cff1> ();
Michiharu Ariza64c54122018-08-10 11:07:07 -07001014
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301015 if (cff == &Null (OT::cff1))
Michiharu Ariza64c54122018-08-10 11:07:07 -07001016 { fini (); return; }
1017
1018 nameIndex = &cff->nameIndex (cff);
Michiharu Arizafdbfa182018-08-16 00:13:09 -07001019 if ((nameIndex == &Null (CFF1NameIndex)) || !nameIndex->sanitize (&sc))
Michiharu Ariza64c54122018-08-10 11:07:07 -07001020 { fini (); return; }
1021
Michiharu Arizafdbfa182018-08-16 00:13:09 -07001022 topDictIndex = &StructAtOffset<CFF1TopDictIndex> (nameIndex, nameIndex->get_size ());
1023 if ((topDictIndex == &Null (CFF1TopDictIndex)) || !topDictIndex->sanitize (&sc) || (topDictIndex->count == 0))
Michiharu Ariza64c54122018-08-10 11:07:07 -07001024 { fini (); return; }
1025
1026 { /* parse top dict */
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -08001027 const byte_str_t topDictStr = (*topDictIndex)[0];
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001028 if (unlikely (!topDictStr.sanitize (&sc))) { fini (); return; }
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -08001029 cff1_top_dict_interpreter_t top_interp;
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001030 top_interp.env.init (topDictStr);
1031 topDict.init ();
1032 if (unlikely (!top_interp.interpret (topDict))) { fini (); return; }
Michiharu Ariza64c54122018-08-10 11:07:07 -07001033 }
Behdad Esfahbod592f39b2018-11-30 22:54:57 -05001034
Michiharu Ariza3787c072018-11-14 13:38:03 -08001035 if (is_predef_charset ())
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301036 charset = &Null (Charset);
Michiharu Ariza3787c072018-11-14 13:38:03 -08001037 else
1038 {
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001039 charset = &StructAtOffsetOrNull<Charset> (cff, topDict.CharsetOffset);
1040 if (unlikely ((charset == &Null (Charset)) || !charset->sanitize (&sc))) { fini (); return; }
Michiharu Ariza3787c072018-11-14 13:38:03 -08001041 }
1042
Michiharu Ariza64c54122018-08-10 11:07:07 -07001043 fdCount = 1;
1044 if (is_CID ())
1045 {
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001046 fdArray = &StructAtOffsetOrNull<CFF1FDArray> (cff, topDict.FDArrayOffset);
1047 fdSelect = &StructAtOffsetOrNull<CFF1FDSelect> (cff, topDict.FDSelectOffset);
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301048 if (unlikely ((fdArray == &Null (CFF1FDArray)) || !fdArray->sanitize (&sc) ||
1049 (fdSelect == &Null (CFF1FDSelect)) || !fdSelect->sanitize (&sc, fdArray->count)))
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001050 { fini (); return; }
Michiharu Ariza64c54122018-08-10 11:07:07 -07001051
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001052 fdCount = fdArray->count;
Michiharu Ariza64c54122018-08-10 11:07:07 -07001053 }
1054 else
1055 {
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301056 fdArray = &Null (CFF1FDArray);
1057 fdSelect = &Null (CFF1FDSelect);
Michiharu Ariza64c54122018-08-10 11:07:07 -07001058 }
1059
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301060 encoding = &Null (Encoding);
blueshade77b490422019-11-16 18:20:16 -08001061 if (is_CID ())
1062 {
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301063 if (unlikely (charset == &Null (Charset))) { fini (); return; }
blueshade77b490422019-11-16 18:20:16 -08001064 }
1065 else
1066 {
1067 if (!is_predef_encoding ())
1068 {
1069 encoding = &StructAtOffsetOrNull<Encoding> (cff, topDict.EncodingOffset);
1070 if (unlikely ((encoding == &Null (Encoding)) || !encoding->sanitize (&sc))) { fini (); return; }
1071 }
1072 }
1073
Michiharu Arizafdbfa182018-08-16 00:13:09 -07001074 stringIndex = &StructAtOffset<CFF1StringIndex> (topDictIndex, topDictIndex->get_size ());
1075 if ((stringIndex == &Null (CFF1StringIndex)) || !stringIndex->sanitize (&sc))
Michiharu Ariza64c54122018-08-10 11:07:07 -07001076 { fini (); return; }
1077
Michiharu Arizafdbfa182018-08-16 00:13:09 -07001078 globalSubrs = &StructAtOffset<CFF1Subrs> (stringIndex, stringIndex->get_size ());
Michiharu Ariza6dcfda92018-12-05 15:07:46 -08001079 if ((globalSubrs != &Null (CFF1Subrs)) && !globalSubrs->sanitize (&sc))
Michiharu Ariza64c54122018-08-10 11:07:07 -07001080 { fini (); return; }
1081
Michiharu Ariza1666b892018-09-10 16:00:20 -07001082 charStrings = &StructAtOffsetOrNull<CFF1CharStrings> (cff, topDict.charStringsOffset);
Michiharu Ariza64c54122018-08-10 11:07:07 -07001083
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301084 if ((charStrings == &Null (CFF1CharStrings)) || unlikely (!charStrings->sanitize (&sc)))
Michiharu Ariza64c54122018-08-10 11:07:07 -07001085 { fini (); return; }
1086
1087 num_glyphs = charStrings->count;
1088 if (num_glyphs != sc.get_num_glyphs ())
1089 { fini (); return; }
1090
Garret Riegerd307c242020-07-29 12:23:37 -07001091 if (unlikely (!privateDicts.resize (fdCount)))
1092 { fini (); return; }
Michiharu Ariza64c54122018-08-10 11:07:07 -07001093 for (unsigned int i = 0; i < fdCount; i++)
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001094 privateDicts[i].init ();
Michiharu Ariza64c54122018-08-10 11:07:07 -07001095
1096 // parse CID font dicts and gather private dicts
1097 if (is_CID ())
1098 {
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001099 for (unsigned int i = 0; i < fdCount; i++)
1100 {
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -08001101 byte_str_t fontDictStr = (*fdArray)[i];
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001102 if (unlikely (!fontDictStr.sanitize (&sc))) { fini (); return; }
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301103 cff1_font_dict_values_t *font;
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -08001104 cff1_font_dict_interpreter_t font_interp;
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001105 font_interp.env.init (fontDictStr);
1106 font = fontDicts.push ();
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301107 if (unlikely (font == &Crap (cff1_font_dict_values_t))) { fini (); return; }
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001108 font->init ();
1109 if (unlikely (!font_interp.interpret (*font))) { fini (); return; }
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301110 PRIVDICTVAL *priv = &privateDicts[i];
ariza0b290532020-03-04 22:31:21 -08001111 const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001112 if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -08001113 dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001114 priv_interp.env.init (privDictStr);
1115 priv->init ();
1116 if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
Michiharu Ariza64c54122018-08-10 11:07:07 -07001117
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -08001118 priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301119 if (priv->localSubrs != &Null (CFF1Subrs) &&
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001120 unlikely (!priv->localSubrs->sanitize (&sc)))
1121 { fini (); return; }
1122 }
Michiharu Ariza64c54122018-08-10 11:07:07 -07001123 }
1124 else /* non-CID */
1125 {
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301126 cff1_top_dict_values_t *font = &topDict;
1127 PRIVDICTVAL *priv = &privateDicts[0];
Behdad Esfahbod592f39b2018-11-30 22:54:57 -05001128
ariza0b290532020-03-04 22:31:21 -08001129 const byte_str_t privDictStr (StructAtOffset<UnsizedByteStr> (cff, font->privateDictInfo.offset), font->privateDictInfo.size);
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001130 if (unlikely (!privDictStr.sanitize (&sc))) { fini (); return; }
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -08001131 dict_interpreter_t<PRIVOPSET, PRIVDICTVAL> priv_interp;
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001132 priv_interp.env.init (privDictStr);
1133 priv->init ();
1134 if (unlikely (!priv_interp.interpret (*priv))) { fini (); return; }
Michiharu Ariza64c54122018-08-10 11:07:07 -07001135
Michiharu Ariza29f0b6b2018-12-22 07:47:04 -08001136 priv->localSubrs = &StructAtOffsetOrNull<CFF1Subrs> (&privDictStr, priv->subrsOffset);
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301137 if (priv->localSubrs != &Null (CFF1Subrs) &&
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001138 unlikely (!priv->localSubrs->sanitize (&sc)))
1139 { fini (); return; }
Michiharu Ariza64c54122018-08-10 11:07:07 -07001140 }
1141 }
1142
Ebrahim Byagowie4120082018-12-17 21:31:01 +03301143 void fini ()
Michiharu Ariza64c54122018-08-10 11:07:07 -07001144 {
1145 sc.end_processing ();
Michiharu Ariza1666b892018-09-10 16:00:20 -07001146 topDict.fini ();
Michiharu Ariza0b952e62018-12-04 10:22:35 -08001147 fontDicts.fini_deep ();
Michiharu Arizab51418f2018-10-08 15:05:36 -07001148 privateDicts.fini_deep ();
Michiharu Ariza64c54122018-08-10 11:07:07 -07001149 hb_blob_destroy (blob);
1150 blob = nullptr;
1151 }
1152
Ebrahim Byagowi2be859d2020-04-20 23:48:23 +04301153 bool is_valid () const { return blob; }
Ebrahim Byagowi05584132019-10-01 13:49:55 +03301154 bool is_CID () const { return topDict.is_CID (); }
Michiharu Ariza64c54122018-08-10 11:07:07 -07001155
Ebrahim Byagowie4120082018-12-17 21:31:01 +03301156 bool is_predef_charset () const { return topDict.CharsetOffset <= ExpertSubsetCharset; }
Michiharu Ariza3787c072018-11-14 13:38:03 -08001157
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301158 unsigned int std_code_to_glyph (hb_codepoint_t code) const
Michiharu Ariza3787c072018-11-14 13:38:03 -08001159 {
1160 hb_codepoint_t sid = lookup_standard_encoding_for_sid (code);
1161 if (unlikely (sid == CFF_UNDEF_SID))
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001162 return 0;
Behdad Esfahbod592f39b2018-11-30 22:54:57 -05001163
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301164 if (charset != &Null (Charset))
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001165 return charset->get_glyph (sid, num_glyphs);
Michiharu Ariza3787c072018-11-14 13:38:03 -08001166 else if ((topDict.CharsetOffset == ISOAdobeCharset)
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001167 && (code <= 228 /*zcaron*/)) return sid;
Michiharu Ariza3787c072018-11-14 13:38:03 -08001168 return 0;
1169 }
1170
Ebrahim Byagowie4120082018-12-17 21:31:01 +03301171 bool is_predef_encoding () const { return topDict.EncodingOffset <= ExpertEncoding; }
Michiharu Arizaaca73c92018-09-06 17:28:15 -07001172
Ebrahim Byagowi05584132019-10-01 13:49:55 +03301173 hb_codepoint_t glyph_to_code (hb_codepoint_t glyph) const
Michiharu Arizaaca73c92018-09-06 17:28:15 -07001174 {
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301175 if (encoding != &Null (Encoding))
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001176 return encoding->get_code (glyph);
Michiharu Arizaaca73c92018-09-06 17:28:15 -07001177 else
1178 {
Ebrahim Byagowi05584132019-10-01 13:49:55 +03301179 hb_codepoint_t sid = glyph_to_sid (glyph);
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001180 if (sid == 0) return 0;
Ebrahim Byagowi05584132019-10-01 13:49:55 +03301181 hb_codepoint_t code = 0;
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001182 switch (topDict.EncodingOffset)
1183 {
Ebrahim Byagowi05584132019-10-01 13:49:55 +03301184 case StandardEncoding:
1185 code = lookup_standard_encoding_for_code (sid);
1186 break;
1187 case ExpertEncoding:
1188 code = lookup_expert_encoding_for_code (sid);
1189 break;
1190 default:
1191 break;
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001192 }
1193 return code;
Michiharu Arizaaca73c92018-09-06 17:28:15 -07001194 }
1195 }
1196
Ebrahim Byagowib2ebaa92018-12-16 22:38:10 +03301197 hb_codepoint_t glyph_to_sid (hb_codepoint_t glyph) const
Michiharu Arizaaca73c92018-09-06 17:28:15 -07001198 {
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301199 if (charset != &Null (Charset))
blueshade759fe3792019-11-16 19:47:31 -08001200 return charset->get_sid (glyph, num_glyphs);
Michiharu Arizaaca73c92018-09-06 17:28:15 -07001201 else
1202 {
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001203 hb_codepoint_t sid = 0;
1204 switch (topDict.CharsetOffset)
1205 {
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301206 case ISOAdobeCharset:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001207 if (glyph <= 228 /*zcaron*/) sid = glyph;
1208 break;
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301209 case ExpertCharset:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001210 sid = lookup_expert_charset_for_sid (glyph);
1211 break;
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301212 case ExpertSubsetCharset:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001213 sid = lookup_expert_subset_charset_for_sid (glyph);
1214 break;
1215 default:
1216 break;
1217 }
1218 return sid;
Michiharu Arizaaca73c92018-09-06 17:28:15 -07001219 }
1220 }
1221
ariza22f7c612020-04-17 23:49:51 -07001222 hb_codepoint_t sid_to_glyph (hb_codepoint_t sid) const
1223 {
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301224 if (charset != &Null (Charset))
1225 return charset->get_glyph (sid, num_glyphs);
ariza22f7c612020-04-17 23:49:51 -07001226 else
1227 {
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301228 hb_codepoint_t glyph = 0;
1229 switch (topDict.CharsetOffset)
1230 {
1231 case ISOAdobeCharset:
1232 if (sid <= 228 /*zcaron*/) glyph = sid;
1233 break;
1234 case ExpertCharset:
1235 glyph = lookup_expert_charset_for_glyph (sid);
1236 break;
1237 case ExpertSubsetCharset:
1238 glyph = lookup_expert_subset_charset_for_glyph (sid);
1239 break;
1240 default:
1241 break;
1242 }
1243 return glyph;
ariza22f7c612020-04-17 23:49:51 -07001244 }
1245 }
1246
blueshade77b490422019-11-16 18:20:16 -08001247 protected:
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301248 hb_blob_t *blob;
blueshade77b490422019-11-16 18:20:16 -08001249 hb_sanitize_context_t sc;
Michiharu Ariza64c54122018-08-10 11:07:07 -07001250
blueshade77b490422019-11-16 18:20:16 -08001251 public:
1252 const Encoding *encoding;
1253 const Charset *charset;
1254 const CFF1NameIndex *nameIndex;
1255 const CFF1TopDictIndex *topDictIndex;
1256 const CFF1StringIndex *stringIndex;
1257 const CFF1Subrs *globalSubrs;
1258 const CFF1CharStrings *charStrings;
1259 const CFF1FDArray *fdArray;
1260 const CFF1FDSelect *fdSelect;
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301261 unsigned int fdCount;
blueshade77b490422019-11-16 18:20:16 -08001262
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301263 cff1_top_dict_values_t topDict;
1264 hb_vector_t<cff1_font_dict_values_t>
1265 fontDicts;
1266 hb_vector_t<PRIVDICTVAL> privateDicts;
blueshade77b490422019-11-16 18:20:16 -08001267
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301268 unsigned int num_glyphs;
Michiharu Ariza64c54122018-08-10 11:07:07 -07001269 };
1270
blueshade77b490422019-11-16 18:20:16 -08001271 struct accelerator_t : accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t>
1272 {
blueshade7ff874652019-11-19 16:18:33 -08001273 void init (hb_face_t *face)
1274 {
1275 SUPER::init (face);
1276
1277 if (!is_valid ()) return;
1278 if (is_CID ()) return;
1279
1280 /* fill glyph_names */
1281 for (hb_codepoint_t gid = 0; gid < num_glyphs; gid++)
1282 {
blueshade761707262019-11-19 17:09:12 -08001283 hb_codepoint_t sid = glyph_to_sid (gid);
blueshade7ff874652019-11-19 16:18:33 -08001284 gname_t gname;
1285 gname.sid = sid;
1286 if (sid < cff1_std_strings_length)
1287 gname.name = cff1_std_strings (sid);
1288 else
1289 {
1290 byte_str_t ustr = (*stringIndex)[sid - cff1_std_strings_length];
1291 gname.name = hb_bytes_t ((const char*)ustr.arrayZ, ustr.length);
1292 }
Ebrahim Byagowi2be859d2020-04-20 23:48:23 +04301293 if (unlikely (!gname.name.arrayZ)) { fini (); return; }
blueshade7ff874652019-11-19 16:18:33 -08001294 glyph_names.push (gname);
1295 }
1296 glyph_names.qsort ();
1297 }
1298
blueshade74c4e08a2019-11-19 16:50:28 -08001299 void fini ()
1300 {
1301 glyph_names.fini ();
Ebrahim Byagowice114d62019-12-31 15:53:02 +03301302
blueshade74c4e08a2019-11-19 16:50:28 -08001303 SUPER::fini ();
1304 }
1305
blueshade77b490422019-11-16 18:20:16 -08001306 bool get_glyph_name (hb_codepoint_t glyph,
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301307 char *buf, unsigned int buf_len) const
blueshade77b490422019-11-16 18:20:16 -08001308 {
1309 if (!buf) return true;
blueshade7e26df432019-11-16 19:12:34 -08001310 if (unlikely (!is_valid ())) return false;
blueshade76d9eb9c2019-11-17 02:20:22 -08001311 if (is_CID()) return false;
blueshade77b490422019-11-16 18:20:16 -08001312 hb_codepoint_t sid = glyph_to_sid (glyph);
blueshade77b490422019-11-16 18:20:16 -08001313 const char *str;
1314 size_t str_len;
blueshade7ff874652019-11-19 16:18:33 -08001315 if (sid < cff1_std_strings_length)
blueshade77b490422019-11-16 18:20:16 -08001316 {
blueshade7ff874652019-11-19 16:18:33 -08001317 hb_bytes_t byte_str = cff1_std_strings (sid);
1318 str = byte_str.arrayZ;
1319 str_len = byte_str.length;
blueshade77b490422019-11-16 18:20:16 -08001320 }
1321 else
1322 {
blueshade7ff874652019-11-19 16:18:33 -08001323 byte_str_t ubyte_str = (*stringIndex)[sid - cff1_std_strings_length];
1324 str = (const char *)ubyte_str.arrayZ;
1325 str_len = ubyte_str.length;
blueshade77b490422019-11-16 18:20:16 -08001326 }
1327 if (!str_len) return false;
1328 unsigned int len = hb_min (buf_len - 1, str_len);
1329 strncpy (buf, (const char*)str, len);
1330 buf[len] = '\0';
1331 return true;
1332 }
1333
blueshade7ff874652019-11-19 16:18:33 -08001334 bool get_glyph_from_name (const char *name, int len,
1335 hb_codepoint_t *glyph) const
1336 {
1337 if (len < 0) len = strlen (name);
1338 if (unlikely (!len)) return false;
Ebrahim Byagowice114d62019-12-31 15:53:02 +03301339
Ebrahim Byagowi2dda6dd2020-04-20 14:12:45 +04301340 gname_t key = { hb_bytes_t (name, len), 0 };
blueshade7ff874652019-11-19 16:18:33 -08001341 const gname_t *gname = glyph_names.bsearch (key);
Ebrahim Byagowi2be859d2020-04-20 23:48:23 +04301342 if (!gname) return false;
ariza22f7c612020-04-17 23:49:51 -07001343 hb_codepoint_t gid = sid_to_glyph (gname->sid);
blueshade7ff874652019-11-19 16:18:33 -08001344 if (!gid && gname->sid) return false;
1345 *glyph = gid;
1346 return true;
1347 }
1348
blueshade77b490422019-11-16 18:20:16 -08001349 HB_INTERNAL bool get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const;
1350 HB_INTERNAL bool get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const;
Ebrahim Byagowi755a77d2020-01-29 22:26:04 +03301351#ifdef HB_EXPERIMENTAL_API
Ebrahim Byagowi9fe0dc32020-02-26 17:40:44 +03301352 HB_INTERNAL bool get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const;
Ebrahim Byagowi755a77d2020-01-29 22:26:04 +03301353#endif
blueshade7ff874652019-11-19 16:18:33 -08001354
1355 private:
1356 struct gname_t
1357 {
1358 hb_bytes_t name;
1359 uint16_t sid;
1360
1361 static int cmp (const void *a_, const void *b_)
1362 {
1363 const gname_t *a = (const gname_t *)a_;
1364 const gname_t *b = (const gname_t *)b_;
1365 int minlen = hb_min (a->name.length, b->name.length);
1366 int ret = strncmp (a->name.arrayZ, b->name.arrayZ, minlen);
1367 if (ret) return ret;
1368 return a->name.length - b->name.length;
1369 }
1370
1371 int cmp (const gname_t &a) const { return cmp (&a, this); }
1372 };
Ebrahim Byagowice114d62019-12-31 15:53:02 +03301373
blueshade7ff874652019-11-19 16:18:33 -08001374 hb_sorted_vector_t<gname_t> glyph_names;
1375
1376 typedef accelerator_templ_t<cff1_private_dict_opset_t, cff1_private_dict_values_t> SUPER;
blueshade77b490422019-11-16 18:20:16 -08001377 };
1378
1379 struct accelerator_subset_t : accelerator_templ_t<cff1_private_dict_opset_subset, cff1_private_dict_values_subset_t> {};
1380
Ebrahim Byagowi25707e32020-02-05 00:27:28 +03301381 bool subset (hb_subset_context_t *c) const { return hb_subset_cff1 (c); }
Michiharu Ariza64c54122018-08-10 11:07:07 -07001382
Michiharu Arizaaca73c92018-09-06 17:28:15 -07001383 protected:
Michiharu Ariza3787c072018-11-14 13:38:03 -08001384 HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_code (hb_codepoint_t sid);
1385 HB_INTERNAL static hb_codepoint_t lookup_expert_encoding_for_code (hb_codepoint_t sid);
1386 HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_sid (hb_codepoint_t glyph);
1387 HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph);
ariza22f7c612020-04-17 23:49:51 -07001388 HB_INTERNAL static hb_codepoint_t lookup_expert_charset_for_glyph (hb_codepoint_t sid);
1389 HB_INTERNAL static hb_codepoint_t lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid);
Michiharu Ariza3787c072018-11-14 13:38:03 -08001390 HB_INTERNAL static hb_codepoint_t lookup_standard_encoding_for_sid (hb_codepoint_t code);
Michiharu Arizaaca73c92018-09-06 17:28:15 -07001391
Michiharu Ariza64c54122018-08-10 11:07:07 -07001392 public:
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001393 FixedVersion<HBUINT8> version; /* Version of CFF table. set to 0x0100u */
Behdad Esfahbodc539afb2021-03-31 13:28:25 -06001394 NNOffsetTo<CFF1NameIndex, HBUINT8> nameIndex; /* headerSize = Offset to Name INDEX. */
Behdad Esfahbod825df6d2018-11-30 23:04:59 -05001395 HBUINT8 offSize; /* offset size (unused?) */
Michiharu Ariza64c54122018-08-10 11:07:07 -07001396
1397 public:
1398 DEFINE_SIZE_STATIC (4);
1399};
1400
Michiharu Arizac0c85b82018-09-17 11:14:56 -07001401struct cff1_accelerator_t : cff1::accelerator_t {};
Michiharu Ariza64c54122018-08-10 11:07:07 -07001402} /* namespace OT */
1403
Michiharu Arizafdbfa182018-08-16 00:13:09 -07001404#endif /* HB_OT_CFF1_TABLE_HH */