Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: third_party/ots/src/cff.cc

Issue 775893002: Updating OTS repo from https://github.com/khaledhosny/ots.git (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Updating with 4800 warning fix Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/ots/src/cff.h ('k') | third_party/ots/src/cff_type2_charstring.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "cff.h"
6
7 #include <cstring>
8 #include <utility>
9 #include <vector>
10
11 #include "maxp.h"
12 #include "cff_type2_charstring.h"
13
14 // CFF - PostScript font program (Compact Font Format) table
15 // http://www.microsoft.com/typography/otspec/cff.htm
16 // http://www.microsoft.com/typography/otspec/cffspec.htm
17
18 #define TABLE_NAME "CFF"
19
20 namespace {
21
22 enum DICT_OPERAND_TYPE {
23 DICT_OPERAND_INTEGER,
24 DICT_OPERAND_REAL,
25 DICT_OPERATOR,
26 };
27
28 enum DICT_DATA_TYPE {
29 DICT_DATA_TOPLEVEL,
30 DICT_DATA_FDARRAY,
31 };
32
33 enum FONT_FORMAT {
34 FORMAT_UNKNOWN,
35 FORMAT_CID_KEYED,
36 FORMAT_OTHER, // Including synthetic fonts
37 };
38
39 // see Appendix. A
40 const size_t kNStdString = 390;
41
42 bool ReadOffset(ots::Buffer *table, uint8_t off_size, uint32_t *offset) {
43 if (off_size > 4) {
44 return OTS_FAILURE();
45 }
46
47 uint32_t tmp32 = 0;
48 for (unsigned i = 0; i < off_size; ++i) {
49 uint8_t tmp8 = 0;
50 if (!table->ReadU8(&tmp8)) {
51 return OTS_FAILURE();
52 }
53 tmp32 <<= 8;
54 tmp32 += tmp8;
55 }
56 *offset = tmp32;
57 return true;
58 }
59
60 bool ParseIndex(ots::Buffer *table, ots::CFFIndex *index) {
61 index->off_size = 0;
62 index->offsets.clear();
63
64 if (!table->ReadU16(&(index->count))) {
65 return OTS_FAILURE();
66 }
67 if (index->count == 0) {
68 // An empty INDEX.
69 index->offset_to_next = table->offset();
70 return true;
71 }
72
73 if (!table->ReadU8(&(index->off_size))) {
74 return OTS_FAILURE();
75 }
76 if ((index->off_size == 0) ||
77 (index->off_size > 4)) {
78 return OTS_FAILURE();
79 }
80
81 const size_t array_size = (index->count + 1) * index->off_size;
82 // less than ((64k + 1) * 4), thus does not overflow.
83 const size_t object_data_offset = table->offset() + array_size;
84 // does not overflow too, since offset() <= 1GB.
85
86 if (object_data_offset >= table->length()) {
87 return OTS_FAILURE();
88 }
89
90 for (unsigned i = 0; i <= index->count; ++i) { // '<=' is not a typo.
91 uint32_t rel_offset = 0;
92 if (!ReadOffset(table, index->off_size, &rel_offset)) {
93 return OTS_FAILURE();
94 }
95 if (rel_offset < 1) {
96 return OTS_FAILURE();
97 }
98 if (i == 0 && rel_offset != 1) {
99 return OTS_FAILURE();
100 }
101
102 if (rel_offset > table->length()) {
103 return OTS_FAILURE();
104 }
105
106 // does not underflow.
107 if (object_data_offset > table->length() - (rel_offset - 1)) {
108 return OTS_FAILURE();
109 }
110
111 index->offsets.push_back(
112 object_data_offset + (rel_offset - 1)); // less than length(), 1GB.
113 }
114
115 for (unsigned i = 1; i < index->offsets.size(); ++i) {
116 // We allow consecutive identical offsets here for zero-length strings.
117 // See http://crbug.com/69341 for more details.
118 if (index->offsets[i] < index->offsets[i - 1]) {
119 return OTS_FAILURE();
120 }
121 }
122
123 index->offset_to_next = index->offsets.back();
124 return true;
125 }
126
127 bool ParseNameData(
128 ots::Buffer *table, const ots::CFFIndex &index, std::string* out_name) {
129 uint8_t name[256] = {0};
130 if (index.offsets.size() == 0) { // just in case.
131 return OTS_FAILURE();
132 }
133 for (unsigned i = 1; i < index.offsets.size(); ++i) {
134 const size_t length = index.offsets[i] - index.offsets[i - 1];
135 // font names should be no longer than 127 characters.
136 if (length > 127) {
137 return OTS_FAILURE();
138 }
139
140 table->set_offset(index.offsets[i - 1]);
141 if (!table->Read(name, length)) {
142 return OTS_FAILURE();
143 }
144
145 for (size_t j = 0; j < length; ++j) {
146 // setting the first byte to NUL is allowed.
147 if (j == 0 && name[j] == 0) continue;
148 // non-ASCII characters are not recommended (except the first character).
149 if (name[j] < 33 || name[j] > 126) {
150 return OTS_FAILURE();
151 }
152 // [, ], ... are not allowed.
153 if (std::strchr("[](){}<>/% ", name[j])) {
154 return OTS_FAILURE();
155 }
156 }
157 }
158
159 *out_name = reinterpret_cast<char *>(name);
160 return true;
161 }
162
163 bool CheckOffset(const std::pair<uint32_t, DICT_OPERAND_TYPE>& operand,
164 size_t table_length) {
165 if (operand.second != DICT_OPERAND_INTEGER) {
166 return OTS_FAILURE();
167 }
168 if (operand.first >= table_length) {
169 return OTS_FAILURE();
170 }
171 return true;
172 }
173
174 bool CheckSid(const std::pair<uint32_t, DICT_OPERAND_TYPE>& operand,
175 size_t sid_max) {
176 if (operand.second != DICT_OPERAND_INTEGER) {
177 return OTS_FAILURE();
178 }
179 if (operand.first > sid_max) {
180 return OTS_FAILURE();
181 }
182 return true;
183 }
184
185 bool ParseDictDataBcd(
186 ots::Buffer *table,
187 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) {
188 bool read_decimal_point = false;
189 bool read_e = false;
190
191 uint8_t nibble = 0;
192 size_t count = 0;
193 while (true) {
194 if (!table->ReadU8(&nibble)) {
195 return OTS_FAILURE();
196 }
197 if ((nibble & 0xf0) == 0xf0) {
198 if ((nibble & 0xf) == 0xf) {
199 // TODO(yusukes): would be better to store actual double value,
200 // rather than the dummy integer.
201 operands->push_back(std::make_pair(static_cast<uint32_t>(0),
202 DICT_OPERAND_REAL));
203 return true;
204 }
205 return OTS_FAILURE();
206 }
207 if ((nibble & 0x0f) == 0x0f) {
208 operands->push_back(std::make_pair(static_cast<uint32_t>(0),
209 DICT_OPERAND_REAL));
210 return true;
211 }
212
213 // check number format
214 uint8_t nibbles[2];
215 nibbles[0] = (nibble & 0xf0) >> 8;
216 nibbles[1] = (nibble & 0x0f);
217 for (unsigned i = 0; i < 2; ++i) {
218 if (nibbles[i] == 0xd) { // reserved number
219 return OTS_FAILURE();
220 }
221 if ((nibbles[i] == 0xe) && // minus
222 ((count > 0) || (i > 0))) {
223 return OTS_FAILURE(); // minus sign should be the first character.
224 }
225 if (nibbles[i] == 0xa) { // decimal point
226 if (!read_decimal_point) {
227 read_decimal_point = true;
228 } else {
229 return OTS_FAILURE(); // two or more points.
230 }
231 }
232 if ((nibbles[i] == 0xb) || // E+
233 (nibbles[i] == 0xc)) { // E-
234 if (!read_e) {
235 read_e = true;
236 } else {
237 return OTS_FAILURE(); // two or more E's.
238 }
239 }
240 }
241 ++count;
242 }
243 }
244
245 bool ParseDictDataEscapedOperator(
246 ots::Buffer *table,
247 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) {
248 uint8_t op = 0;
249 if (!table->ReadU8(&op)) {
250 return OTS_FAILURE();
251 }
252
253 if ((op <= 14) ||
254 (op >= 17 && op <= 23) ||
255 (op >= 30 && op <= 38)) {
256 operands->push_back(std::make_pair((12U << 8) + op, DICT_OPERATOR));
257 return true;
258 }
259
260 // reserved area.
261 return OTS_FAILURE();
262 }
263
264 bool ParseDictDataNumber(
265 ots::Buffer *table, uint8_t b0,
266 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) {
267 uint8_t b1 = 0;
268 uint8_t b2 = 0;
269 uint8_t b3 = 0;
270 uint8_t b4 = 0;
271
272 switch (b0) {
273 case 28: // shortint
274 if (!table->ReadU8(&b1) ||
275 !table->ReadU8(&b2)) {
276 return OTS_FAILURE();
277 }
278 operands->push_back(std::make_pair(
279 static_cast<uint32_t>((b1 << 8) + b2), DICT_OPERAND_INTEGER));
280 return true;
281
282 case 29: // longint
283 if (!table->ReadU8(&b1) ||
284 !table->ReadU8(&b2) ||
285 !table->ReadU8(&b3) ||
286 !table->ReadU8(&b4)) {
287 return OTS_FAILURE();
288 }
289 operands->push_back(std::make_pair(
290 static_cast<uint32_t>((b1 << 24) + (b2 << 16) + (b3 << 8) + b4),
291 DICT_OPERAND_INTEGER));
292 return true;
293
294 case 30: // binary coded decimal
295 return ParseDictDataBcd(table, operands);
296
297 default:
298 break;
299 }
300
301 uint32_t result;
302 if (b0 >=32 && b0 <=246) {
303 result = b0 - 139;
304 } else if (b0 >=247 && b0 <= 250) {
305 if (!table->ReadU8(&b1)) {
306 return OTS_FAILURE();
307 }
308 result = (b0 - 247) * 256 + b1 + 108;
309 } else if (b0 >= 251 && b0 <= 254) {
310 if (!table->ReadU8(&b1)) {
311 return OTS_FAILURE();
312 }
313 result = -(b0 - 251) * 256 + b1 - 108;
314 } else {
315 return OTS_FAILURE();
316 }
317
318 operands->push_back(std::make_pair(result, DICT_OPERAND_INTEGER));
319 return true;
320 }
321
322 bool ParseDictDataReadNext(
323 ots::Buffer *table,
324 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) {
325 uint8_t op = 0;
326 if (!table->ReadU8(&op)) {
327 return OTS_FAILURE();
328 }
329 if (op <= 21) {
330 if (op == 12) {
331 return ParseDictDataEscapedOperator(table, operands);
332 }
333 operands->push_back(std::make_pair(
334 static_cast<uint32_t>(op), DICT_OPERATOR));
335 return true;
336 } else if (op <= 27 || op == 31 || op == 255) {
337 // reserved area.
338 return OTS_FAILURE();
339 }
340
341 return ParseDictDataNumber(table, op, operands);
342 }
343
344 bool ParsePrivateDictData(
345 const uint8_t *data,
346 size_t table_length, size_t offset, size_t dict_length,
347 DICT_DATA_TYPE type, ots::OpenTypeCFF *out_cff) {
348 ots::Buffer table(data + offset, dict_length);
349 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > operands;
350
351 // Since a Private DICT for FDArray might not have a Local Subr (e.g. Hiragino
352 // Kaku Gothic Std W8), we create an empty Local Subr here to match the size
353 // of FDArray the size of |local_subrs_per_font|.
354 if (type == DICT_DATA_FDARRAY) {
355 out_cff->local_subrs_per_font.push_back(new ots::CFFIndex);
356 }
357
358 while (table.offset() < dict_length) {
359 if (!ParseDictDataReadNext(&table, &operands)) {
360 return OTS_FAILURE();
361 }
362 if (operands.empty()) {
363 return OTS_FAILURE();
364 }
365 if (operands.size() > 48) {
366 // An operator may be preceded by up to a maximum of 48 operands.
367 return OTS_FAILURE();
368 }
369 if (operands.back().second != DICT_OPERATOR) {
370 continue;
371 }
372
373 // got operator
374 const uint32_t op = operands.back().first;
375 operands.pop_back();
376
377 switch (op) {
378 // array
379 case 6: // BlueValues
380 case 7: // OtherBlues
381 case 8: // FamilyBlues
382 case 9: // FamilyOtherBlues
383 case (12U << 8) + 12: // StemSnapH (delta)
384 case (12U << 8) + 13: // StemSnapV (delta)
385 if (operands.empty()) {
386 return OTS_FAILURE();
387 }
388 break;
389
390 // number
391 case 10: // StdHW
392 case 11: // StdVW
393 case 20: // defaultWidthX
394 case 21: // nominalWidthX
395 case (12U << 8) + 9: // BlueScale
396 case (12U << 8) + 10: // BlueShift
397 case (12U << 8) + 11: // BlueFuzz
398 case (12U << 8) + 17: // LanguageGroup
399 case (12U << 8) + 18: // ExpansionFactor
400 case (12U << 8) + 19: // initialRandomSeed
401 if (operands.size() != 1) {
402 return OTS_FAILURE();
403 }
404 break;
405
406 // Local Subrs INDEX, offset(self)
407 case 19: {
408 if (operands.size() != 1) {
409 return OTS_FAILURE();
410 }
411 if (operands.back().second != DICT_OPERAND_INTEGER) {
412 return OTS_FAILURE();
413 }
414 if (operands.back().first >= 1024 * 1024 * 1024) {
415 return OTS_FAILURE();
416 }
417 if (operands.back().first + offset >= table_length) {
418 return OTS_FAILURE();
419 }
420 // parse "16. Local Subrs INDEX"
421 ots::Buffer cff_table(data, table_length);
422 cff_table.set_offset(operands.back().first + offset);
423 ots::CFFIndex *local_subrs_index = NULL;
424 if (type == DICT_DATA_FDARRAY) {
425 if (out_cff->local_subrs_per_font.empty()) {
426 return OTS_FAILURE(); // not reached.
427 }
428 local_subrs_index = out_cff->local_subrs_per_font.back();
429 } else { // type == DICT_DATA_TOPLEVEL
430 if (out_cff->local_subrs) {
431 return OTS_FAILURE(); // two or more local_subrs?
432 }
433 local_subrs_index = new ots::CFFIndex;
434 out_cff->local_subrs = local_subrs_index;
435 }
436 if (!ParseIndex(&cff_table, local_subrs_index)) {
437 return OTS_FAILURE();
438 }
439 break;
440 }
441
442 // boolean
443 case (12U << 8) + 14: // ForceBold
444 if (operands.size() != 1) {
445 return OTS_FAILURE();
446 }
447 if (operands.back().second != DICT_OPERAND_INTEGER) {
448 return OTS_FAILURE();
449 }
450 if (operands.back().first >= 2) {
451 return OTS_FAILURE();
452 }
453 break;
454
455 default:
456 return OTS_FAILURE();
457 }
458 operands.clear();
459 }
460
461 return true;
462 }
463
464 bool ParseDictData(const uint8_t *data, size_t table_length,
465 const ots::CFFIndex &index, uint16_t glyphs,
466 size_t sid_max, DICT_DATA_TYPE type,
467 ots::OpenTypeCFF *out_cff) {
468 for (unsigned i = 1; i < index.offsets.size(); ++i) {
469 if (type == DICT_DATA_TOPLEVEL) {
470 out_cff->char_strings_array.push_back(new ots::CFFIndex);
471 }
472 size_t dict_length = index.offsets[i] - index.offsets[i - 1];
473 ots::Buffer table(data + index.offsets[i - 1], dict_length);
474
475 std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > operands;
476
477 FONT_FORMAT font_format = FORMAT_UNKNOWN;
478 bool have_ros = false;
479 uint16_t charstring_glyphs = 0;
480 size_t charset_offset = 0;
481
482 while (table.offset() < dict_length) {
483 if (!ParseDictDataReadNext(&table, &operands)) {
484 return OTS_FAILURE();
485 }
486 if (operands.empty()) {
487 return OTS_FAILURE();
488 }
489 if (operands.size() > 48) {
490 // An operator may be preceded by up to a maximum of 48 operands.
491 return OTS_FAILURE();
492 }
493 if (operands.back().second != DICT_OPERATOR) continue;
494
495 // got operator
496 const uint32_t op = operands.back().first;
497 operands.pop_back();
498
499 switch (op) {
500 // SID
501 case 0: // version
502 case 1: // Notice
503 case 2: // Copyright
504 case 3: // FullName
505 case 4: // FamilyName
506 case (12U << 8) + 0: // Copyright
507 case (12U << 8) + 21: // PostScript
508 case (12U << 8) + 22: // BaseFontName
509 case (12U << 8) + 38: // FontName
510 if (operands.size() != 1) {
511 return OTS_FAILURE();
512 }
513 if (!CheckSid(operands.back(), sid_max)) {
514 return OTS_FAILURE();
515 }
516 break;
517
518 // array
519 case 5: // FontBBox
520 case 14: // XUID
521 case (12U << 8) + 7: // FontMatrix
522 case (12U << 8) + 23: // BaseFontBlend (delta)
523 if (operands.empty()) {
524 return OTS_FAILURE();
525 }
526 break;
527
528 // number
529 case 13: // UniqueID
530 case (12U << 8) + 2: // ItalicAngle
531 case (12U << 8) + 3: // UnderlinePosition
532 case (12U << 8) + 4: // UnderlineThickness
533 case (12U << 8) + 5: // PaintType
534 case (12U << 8) + 8: // StrokeWidth
535 case (12U << 8) + 20: // SyntheticBase
536 if (operands.size() != 1) {
537 return OTS_FAILURE();
538 }
539 break;
540 case (12U << 8) + 31: // CIDFontVersion
541 case (12U << 8) + 32: // CIDFontRevision
542 case (12U << 8) + 33: // CIDFontType
543 case (12U << 8) + 34: // CIDCount
544 case (12U << 8) + 35: // UIDBase
545 if (operands.size() != 1) {
546 return OTS_FAILURE();
547 }
548 if (font_format != FORMAT_CID_KEYED) {
549 return OTS_FAILURE();
550 }
551 break;
552 case (12U << 8) + 6: // CharstringType
553 if (operands.size() != 1) {
554 return OTS_FAILURE();
555 }
556 if(operands.back().second != DICT_OPERAND_INTEGER) {
557 return OTS_FAILURE();
558 }
559 if (operands.back().first != 2) {
560 // We only support the "Type 2 Charstring Format."
561 // TODO(yusukes): Support Type 1 format? Is that still in use?
562 return OTS_FAILURE();
563 }
564 break;
565
566 // boolean
567 case (12U << 8) + 1: // isFixedPitch
568 if (operands.size() != 1) {
569 return OTS_FAILURE();
570 }
571 if (operands.back().second != DICT_OPERAND_INTEGER) {
572 return OTS_FAILURE();
573 }
574 if (operands.back().first >= 2) {
575 return OTS_FAILURE();
576 }
577 break;
578
579 // offset(0)
580 case 15: // charset
581 if (operands.size() != 1) {
582 return OTS_FAILURE();
583 }
584 if (operands.back().first <= 2) {
585 // predefined charset, ISOAdobe, Expert or ExpertSubset, is used.
586 break;
587 }
588 if (!CheckOffset(operands.back(), table_length)) {
589 return OTS_FAILURE();
590 }
591 if (charset_offset) {
592 return OTS_FAILURE(); // multiple charset tables?
593 }
594 charset_offset = operands.back().first;
595 break;
596
597 case 16: { // Encoding
598 if (operands.size() != 1) {
599 return OTS_FAILURE();
600 }
601 if (operands.back().first <= 1) {
602 break; // predefined encoding, "Standard" or "Expert", is used.
603 }
604 if (!CheckOffset(operands.back(), table_length)) {
605 return OTS_FAILURE();
606 }
607
608 // parse sub dictionary INDEX.
609 ots::Buffer cff_table(data, table_length);
610 cff_table.set_offset(operands.back().first);
611 uint8_t format = 0;
612 if (!cff_table.ReadU8(&format)) {
613 return OTS_FAILURE();
614 }
615 if (format & 0x80) {
616 // supplemental encoding is not supported at the moment.
617 return OTS_FAILURE();
618 }
619 // TODO(yusukes): support & parse supplemental encoding tables.
620 break;
621 }
622
623 case 17: { // CharStrings
624 if (type != DICT_DATA_TOPLEVEL) {
625 return OTS_FAILURE();
626 }
627 if (operands.size() != 1) {
628 return OTS_FAILURE();
629 }
630 if (!CheckOffset(operands.back(), table_length)) {
631 return OTS_FAILURE();
632 }
633 // parse "14. CharStrings INDEX"
634 ots::Buffer cff_table(data, table_length);
635 cff_table.set_offset(operands.back().first);
636 ots::CFFIndex *charstring_index = out_cff->char_strings_array.back();
637 if (!ParseIndex(&cff_table, charstring_index)) {
638 return OTS_FAILURE();
639 }
640 if (charstring_index->count < 2) {
641 return OTS_FAILURE();
642 }
643 if (charstring_glyphs) {
644 return OTS_FAILURE(); // multiple charstring tables?
645 }
646 charstring_glyphs = charstring_index->count;
647 if (charstring_glyphs != glyphs) {
648 return OTS_FAILURE(); // CFF and maxp have different number of glyp hs?
649 }
650 break;
651 }
652
653 case (12U << 8) + 36: { // FDArray
654 if (type != DICT_DATA_TOPLEVEL) {
655 return OTS_FAILURE();
656 }
657 if (operands.size() != 1) {
658 return OTS_FAILURE();
659 }
660 if (!CheckOffset(operands.back(), table_length)) {
661 return OTS_FAILURE();
662 }
663
664 // parse sub dictionary INDEX.
665 ots::Buffer cff_table(data, table_length);
666 cff_table.set_offset(operands.back().first);
667 ots::CFFIndex sub_dict_index;
668 if (!ParseIndex(&cff_table, &sub_dict_index)) {
669 return OTS_FAILURE();
670 }
671 if (!ParseDictData(data, table_length,
672 sub_dict_index,
673 glyphs, sid_max, DICT_DATA_FDARRAY,
674 out_cff)) {
675 return OTS_FAILURE();
676 }
677 if (out_cff->font_dict_length != 0) {
678 return OTS_FAILURE(); // two or more FDArray found.
679 }
680 out_cff->font_dict_length = sub_dict_index.count;
681 break;
682 }
683
684 case (12U << 8) + 37: { // FDSelect
685 if (type != DICT_DATA_TOPLEVEL) {
686 return OTS_FAILURE();
687 }
688 if (operands.size() != 1) {
689 return OTS_FAILURE();
690 }
691 if (!CheckOffset(operands.back(), table_length)) {
692 return OTS_FAILURE();
693 }
694
695 // parse FDSelect data structure
696 ots::Buffer cff_table(data, table_length);
697 cff_table.set_offset(operands.back().first);
698 uint8_t format = 0;
699 if (!cff_table.ReadU8(&format)) {
700 return OTS_FAILURE();
701 }
702 if (format == 0) {
703 for (uint16_t j = 0; j < glyphs; ++j) {
704 uint8_t fd_index = 0;
705 if (!cff_table.ReadU8(&fd_index)) {
706 return OTS_FAILURE();
707 }
708 (out_cff->fd_select)[j] = fd_index;
709 }
710 } else if (format == 3) {
711 uint16_t n_ranges = 0;
712 if (!cff_table.ReadU16(&n_ranges)) {
713 return OTS_FAILURE();
714 }
715 if (n_ranges == 0) {
716 return OTS_FAILURE();
717 }
718
719 uint16_t last_gid = 0;
720 uint8_t fd_index = 0;
721 for (unsigned j = 0; j < n_ranges; ++j) {
722 uint16_t first = 0; // GID
723 if (!cff_table.ReadU16(&first)) {
724 return OTS_FAILURE();
725 }
726
727 // Sanity checks.
728 if ((j == 0) && (first != 0)) {
729 return OTS_FAILURE();
730 }
731 if ((j != 0) && (last_gid >= first)) {
732 return OTS_FAILURE(); // not increasing order.
733 }
734
735 // Copy the mapping to |out_cff->fd_select|.
736 if (j != 0) {
737 for (uint16_t k = last_gid; k < first; ++k) {
738 if (!out_cff->fd_select.insert(
739 std::make_pair(k, fd_index)).second) {
740 return OTS_FAILURE();
741 }
742 }
743 }
744
745 if (!cff_table.ReadU8(&fd_index)) {
746 return OTS_FAILURE();
747 }
748 last_gid = first;
749 // TODO(yusukes): check GID?
750 }
751 uint16_t sentinel = 0;
752 if (!cff_table.ReadU16(&sentinel)) {
753 return OTS_FAILURE();
754 }
755 if (last_gid >= sentinel) {
756 return OTS_FAILURE();
757 }
758 for (uint16_t k = last_gid; k < sentinel; ++k) {
759 if (!out_cff->fd_select.insert(
760 std::make_pair(k, fd_index)).second) {
761 return OTS_FAILURE();
762 }
763 }
764 } else {
765 // unknown format
766 return OTS_FAILURE();
767 }
768 break;
769 }
770
771 // Private DICT (2 * number)
772 case 18: {
773 if (operands.size() != 2) {
774 return OTS_FAILURE();
775 }
776 if (operands.back().second != DICT_OPERAND_INTEGER) {
777 return OTS_FAILURE();
778 }
779 const uint32_t private_offset = operands.back().first;
780 operands.pop_back();
781 if (operands.back().second != DICT_OPERAND_INTEGER) {
782 return OTS_FAILURE();
783 }
784 const uint32_t private_length = operands.back().first;
785 if (private_offset > table_length) {
786 return OTS_FAILURE();
787 }
788 if (private_length >= table_length) {
789 return OTS_FAILURE();
790 }
791 if (private_length + private_offset > table_length) {
792 return OTS_FAILURE();
793 }
794 // parse "15. Private DICT Data"
795 if (!ParsePrivateDictData(data, table_length,
796 private_offset, private_length,
797 type, out_cff)) {
798 return OTS_FAILURE();
799 }
800 break;
801 }
802
803 // ROS
804 case (12U << 8) + 30:
805 if (font_format != FORMAT_UNKNOWN) {
806 return OTS_FAILURE();
807 }
808 font_format = FORMAT_CID_KEYED;
809 if (operands.size() != 3) {
810 return OTS_FAILURE();
811 }
812 // check SIDs
813 operands.pop_back(); // ignore the first number.
814 if (!CheckSid(operands.back(), sid_max)) {
815 return OTS_FAILURE();
816 }
817 operands.pop_back();
818 if (!CheckSid(operands.back(), sid_max)) {
819 return OTS_FAILURE();
820 }
821 if (have_ros) {
822 return OTS_FAILURE(); // multiple ROS tables?
823 }
824 have_ros = true;
825 break;
826
827 default:
828 return OTS_FAILURE();
829 }
830 operands.clear();
831
832 if (font_format == FORMAT_UNKNOWN) {
833 font_format = FORMAT_OTHER;
834 }
835 }
836
837 // parse "13. Charsets"
838 if (charset_offset) {
839 ots::Buffer cff_table(data, table_length);
840 cff_table.set_offset(charset_offset);
841 uint8_t format = 0;
842 if (!cff_table.ReadU8(&format)) {
843 return OTS_FAILURE();
844 }
845 switch (format) {
846 case 0:
847 for (uint16_t j = 1 /* .notdef is omitted */; j < glyphs; ++j) {
848 uint16_t sid = 0;
849 if (!cff_table.ReadU16(&sid)) {
850 return OTS_FAILURE();
851 }
852 if (!have_ros && (sid > sid_max)) {
853 return OTS_FAILURE();
854 }
855 // TODO(yusukes): check CIDs when have_ros is true.
856 }
857 break;
858
859 case 1:
860 case 2: {
861 uint32_t total = 1; // .notdef is omitted.
862 while (total < glyphs) {
863 uint16_t sid = 0;
864 if (!cff_table.ReadU16(&sid)) {
865 return OTS_FAILURE();
866 }
867 if (!have_ros && (sid > sid_max)) {
868 return OTS_FAILURE();
869 }
870 // TODO(yusukes): check CIDs when have_ros is true.
871
872 if (format == 1) {
873 uint8_t left = 0;
874 if (!cff_table.ReadU8(&left)) {
875 return OTS_FAILURE();
876 }
877 total += (left + 1);
878 } else {
879 uint16_t left = 0;
880 if (!cff_table.ReadU16(&left)) {
881 return OTS_FAILURE();
882 }
883 total += (left + 1);
884 }
885 }
886 break;
887 }
888
889 default:
890 return OTS_FAILURE();
891 }
892 }
893 }
894 return true;
895 }
896
897 } // namespace
898
899 namespace ots {
900
901 bool ots_cff_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
902 Buffer table(data, length);
903
904 file->cff = new OpenTypeCFF;
905 file->cff->data = data;
906 file->cff->length = length;
907 file->cff->font_dict_length = 0;
908 file->cff->local_subrs = NULL;
909
910 // parse "6. Header" in the Adobe Compact Font Format Specification
911 uint8_t major = 0;
912 uint8_t minor = 0;
913 uint8_t hdr_size = 0;
914 uint8_t off_size = 0;
915 if (!table.ReadU8(&major)) {
916 return OTS_FAILURE();
917 }
918 if (!table.ReadU8(&minor)) {
919 return OTS_FAILURE();
920 }
921 if (!table.ReadU8(&hdr_size)) {
922 return OTS_FAILURE();
923 }
924 if (!table.ReadU8(&off_size)) {
925 return OTS_FAILURE();
926 }
927 if ((off_size == 0) || (off_size > 4)) {
928 return OTS_FAILURE();
929 }
930
931 if ((major != 1) ||
932 (minor != 0) ||
933 (hdr_size != 4)) {
934 return OTS_FAILURE();
935 }
936 if (hdr_size >= length) {
937 return OTS_FAILURE();
938 }
939
940 // parse "7. Name INDEX"
941 table.set_offset(hdr_size);
942 CFFIndex name_index;
943 if (!ParseIndex(&table, &name_index)) {
944 return OTS_FAILURE();
945 }
946 if (!ParseNameData(&table, name_index, &(file->cff->name))) {
947 return OTS_FAILURE();
948 }
949
950 // parse "8. Top DICT INDEX"
951 table.set_offset(name_index.offset_to_next);
952 CFFIndex top_dict_index;
953 if (!ParseIndex(&table, &top_dict_index)) {
954 return OTS_FAILURE();
955 }
956 if (name_index.count != top_dict_index.count) {
957 return OTS_FAILURE();
958 }
959
960 // parse "10. String INDEX"
961 table.set_offset(top_dict_index.offset_to_next);
962 CFFIndex string_index;
963 if (!ParseIndex(&table, &string_index)) {
964 return OTS_FAILURE();
965 }
966 if (string_index.count >= 65000 - kNStdString) {
967 return OTS_FAILURE();
968 }
969
970 const uint16_t num_glyphs = file->maxp->num_glyphs;
971 const size_t sid_max = string_index.count + kNStdString;
972 // string_index.count == 0 is allowed.
973
974 // parse "9. Top DICT Data"
975 if (!ParseDictData(data, length, top_dict_index,
976 num_glyphs, sid_max,
977 DICT_DATA_TOPLEVEL, file->cff)) {
978 return OTS_FAILURE();
979 }
980
981 // parse "16. Global Subrs INDEX"
982 table.set_offset(string_index.offset_to_next);
983 CFFIndex global_subrs_index;
984 if (!ParseIndex(&table, &global_subrs_index)) {
985 return OTS_FAILURE();
986 }
987
988 // Check if all fd_index in FDSelect are valid.
989 std::map<uint16_t, uint8_t>::const_iterator iter;
990 std::map<uint16_t, uint8_t>::const_iterator end = file->cff->fd_select.end();
991 for (iter = file->cff->fd_select.begin(); iter != end; ++iter) {
992 if (iter->second >= file->cff->font_dict_length) {
993 return OTS_FAILURE();
994 }
995 }
996
997 // Check if all charstrings (font hinting code for each glyph) are valid.
998 for (size_t i = 0; i < file->cff->char_strings_array.size(); ++i) {
999 if (!ValidateType2CharStringIndex(file,
1000 *(file->cff->char_strings_array.at(i)),
1001 global_subrs_index,
1002 file->cff->fd_select,
1003 file->cff->local_subrs_per_font,
1004 file->cff->local_subrs,
1005 &table)) {
1006 return OTS_FAILURE_MSG("Failed validating charstring set %d", (int) i);
1007 }
1008 }
1009
1010 return true;
1011 }
1012
1013 bool ots_cff_should_serialise(OpenTypeFile *file) {
1014 return file->cff != NULL;
1015 }
1016
1017 bool ots_cff_serialise(OTSStream *out, OpenTypeFile *file) {
1018 // TODO(yusukes): would be better to transcode the data,
1019 // rather than simple memcpy.
1020 if (!out->Write(file->cff->data, file->cff->length)) {
1021 return OTS_FAILURE();
1022 }
1023 return true;
1024 }
1025
1026 void ots_cff_free(OpenTypeFile *file) {
1027 if (file->cff) {
1028 for (size_t i = 0; i < file->cff->char_strings_array.size(); ++i) {
1029 delete (file->cff->char_strings_array)[i];
1030 }
1031 for (size_t i = 0; i < file->cff->local_subrs_per_font.size(); ++i) {
1032 delete (file->cff->local_subrs_per_font)[i];
1033 }
1034 delete file->cff->local_subrs;
1035 delete file->cff;
1036 }
1037 }
1038
1039 } // namespace ots
1040
1041 #undef TABLE_NAME
OLDNEW
« no previous file with comments | « third_party/ots/src/cff.h ('k') | third_party/ots/src/cff_type2_charstring.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698