1 /* This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
2
3 Copyright (C) 2002-2014 by Jin-Hwan Cho and Shunsaku Hirata,
4 the dvipdfmx project team.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <stdio.h>
26 #include <string.h>
27
28 #include "system.h"
29 #include "mem.h"
30 #include "error.h"
31 #include "mfileio.h"
32
33 #include "cff_limits.h"
34 #include "cff_types.h"
35 #include "cff_stdstr.h"
36 #include "cff_dict.h"
37
38 #include "cff.h"
39
40 #define CFF_DEBUG 5
41 #define CFF_DEBUG_STR "CFF"
42
get_unsigned(FILE * stream,int n)43 static unsigned long get_unsigned (FILE *stream, int n)
44 {
45 unsigned long v = 0;
46
47 while (n-- > 0)
48 v = v*0x100u + get_unsigned_byte(stream);
49
50 return v;
51 }
52
53 #define get_offset(s, n) get_unsigned((s), (n))
54
55 /*
56 * Read Header, Name INDEX, Top DICT INDEX, and String INDEX.
57 */
cff_open(FILE * stream,long offset,int n)58 cff_font *cff_open(FILE *stream, long offset, int n)
59 {
60 cff_font *cff;
61 cff_index *idx;
62
63 cff = NEW(1, cff_font);
64
65 cff->fontname = NULL;
66 cff->index = n;
67 cff->stream = stream;
68 cff->offset = offset;
69 cff->filter = 0; /* not used */
70 cff->flag = 0;
71
72 cff->name = NULL;
73 cff->topdict = NULL;
74 cff->gsubr = NULL;
75 cff->encoding = NULL;
76 cff->charsets = NULL;
77 cff->fdselect = NULL;
78 cff->cstrings = NULL;
79 cff->fdarray = NULL;
80 cff->private = NULL;
81 cff->subrs = NULL;
82
83 cff->num_glyphs = 0;
84 cff->num_fds = 0;
85 cff->string = NULL;
86 cff->_string = NULL;
87
88 cff_seek_set(cff, 0);
89 cff->header.major = get_unsigned_byte(cff->stream);
90 cff->header.minor = get_unsigned_byte(cff->stream);
91 cff->header.hdr_size = get_unsigned_byte(cff->stream);
92 cff->header.offsize = get_unsigned_byte(cff->stream);
93 if (cff->header.offsize < 1 ||
94 cff->header.offsize > 4)
95 ERROR("invalid offsize data");
96
97 if (cff->header.major > 1 ||
98 cff->header.minor > 0) {
99 WARN("%s: CFF version %u.%u not supported.",
100 CFF_DEBUG_STR, cff->header.major, cff->header.minor);
101 cff_close(cff);
102 return NULL;
103 }
104
105 cff_seek_set(cff, (cff->header).hdr_size);
106
107 /* Name INDEX */
108 idx = cff_get_index(cff);
109 if (n > idx->count - 1) {
110 WARN("%s: Invalid CFF fontset index number.", CFF_DEBUG_STR);
111 cff_close(cff);
112 return NULL;
113 }
114
115 cff->name = idx;
116
117 cff->fontname = cff_get_name(cff);
118
119 /* Top DICT INDEX */
120 idx = cff_get_index(cff);
121 if (n > idx->count - 1)
122 ERROR("CFF Top DICT not exist...");
123 cff->topdict = cff_dict_unpack(idx->data + idx->offset[n] - 1,
124 idx->data + idx->offset[n + 1] - 1);
125 if (!cff->topdict)
126 ERROR("Parsing CFF Top DICT data failed...");
127 cff_release_index(idx);
128
129 if (cff_dict_known(cff->topdict, "CharstringType") &&
130 cff_dict_get(cff->topdict, "CharstringType", 0) != 2) {
131 WARN("Only Type 2 Charstrings supported...");
132 cff_close(cff);
133 return NULL;
134 }
135
136 if (cff_dict_known(cff->topdict, "SyntheticBase")) {
137 WARN("CFF Synthetic font not supported.");
138 cff_close(cff);
139 return NULL;
140 }
141
142 /* String INDEX */
143 cff->string = cff_get_index(cff);
144
145 /* offset to GSubr */
146 cff->gsubr_offset = tell_position(cff->stream) - offset;
147
148 /* Number of glyphs */
149 offset = (long) cff_dict_get(cff->topdict, "CharStrings", 0);
150 cff_seek_set(cff, offset);
151 cff->num_glyphs = get_unsigned_pair(cff->stream);
152
153 /* Check for font type */
154 if (cff_dict_known(cff->topdict, "ROS")) {
155 cff->flag |= FONTTYPE_CIDFONT;
156 } else {
157 cff->flag |= FONTTYPE_FONT;
158 }
159
160 /* Check for encoding */
161 if (cff_dict_known(cff->topdict, "Encoding")) {
162 offset = (long) cff_dict_get(cff->topdict, "Encoding", 0);
163 if (offset == 0) { /* predefined */
164 cff->flag |= ENCODING_STANDARD;
165 } else if (offset == 1) {
166 cff->flag |= ENCODING_EXPERT;
167 }
168 } else {
169 cff->flag |= ENCODING_STANDARD;
170 }
171
172 /* Check for charset */
173 if (cff_dict_known(cff->topdict, "charset")) {
174 offset = (long) cff_dict_get(cff->topdict, "charset", 0);
175 if (offset == 0) { /* predefined */
176 cff->flag |= CHARSETS_ISOADOBE;
177 } else if (offset == 1) {
178 cff->flag |= CHARSETS_EXPERT;
179 } else if (offset == 2) {
180 cff->flag |= CHARSETS_EXPSUB;
181 }
182 } else {
183 cff->flag |= CHARSETS_ISOADOBE;
184 }
185
186 cff_seek_set(cff, cff->gsubr_offset); /* seek back to GSubr */
187
188 return cff;
189 }
190
191 void
cff_close(cff_font * cff)192 cff_close (cff_font *cff)
193 {
194 card16 i;
195
196 if (cff) {
197 if (cff->fontname) RELEASE(cff->fontname);
198 if (cff->name) cff_release_index(cff->name);
199 if (cff->topdict) cff_release_dict(cff->topdict);
200 if (cff->string) cff_release_index(cff->string);
201 if (cff->gsubr) cff_release_index(cff->gsubr);
202 if (cff->encoding) cff_release_encoding(cff->encoding);
203 if (cff->charsets) cff_release_charsets(cff->charsets);
204 if (cff->fdselect) cff_release_fdselect(cff->fdselect);
205 if (cff->cstrings) cff_release_index(cff->cstrings);
206 if (cff->fdarray) {
207 for (i=0;i<cff->num_fds;i++) {
208 if (cff->fdarray[i]) cff_release_dict(cff->fdarray[i]);
209 }
210 RELEASE(cff->fdarray);
211 }
212 if (cff->private) {
213 for (i=0;i<cff->num_fds;i++) {
214 if (cff->private[i]) cff_release_dict(cff->private[i]);
215 }
216 RELEASE(cff->private);
217 }
218 if (cff->subrs) {
219 for (i=0;i<cff->num_fds;i++) {
220 if (cff->subrs[i]) cff_release_index(cff->subrs[i]);
221 }
222 RELEASE(cff->subrs);
223 }
224 if (cff->_string)
225 cff_release_index(cff->_string);
226
227 RELEASE(cff);
228 }
229
230 return;
231 }
232
233 char *
cff_get_name(cff_font * cff)234 cff_get_name (cff_font *cff)
235 {
236 char *fontname;
237 l_offset len;
238 cff_index *idx;
239
240 idx = cff->name;
241 len = idx->offset[cff->index + 1] - idx->offset[cff->index];
242 fontname = NEW(len + 1, char);
243 memcpy(fontname, idx->data + idx->offset[cff->index] - 1, len);
244 fontname[len] = '\0';
245
246 return fontname;
247 }
248
249 long
cff_set_name(cff_font * cff,char * name)250 cff_set_name (cff_font *cff, char *name)
251 {
252 cff_index *idx;
253
254 if (strlen(name) > 127)
255 ERROR("FontName string length too large...");
256
257 if (cff->name)
258 cff_release_index(cff->name);
259
260 cff->name = idx = NEW(1, cff_index);
261 idx->count = 1;
262 idx->offsize = 1;
263 idx->offset = NEW(2, l_offset);
264 (idx->offset)[0] = 1;
265 (idx->offset)[1] = strlen(name) + 1;
266 idx->data = NEW(strlen(name), card8);
267 memmove(idx->data, name, strlen(name)); /* no trailing '\0' */
268
269 return 5 + strlen(name);
270 }
271
272 long
cff_put_header(cff_font * cff,card8 * dest,long destlen)273 cff_put_header (cff_font *cff, card8 *dest, long destlen)
274 {
275 if (destlen < 4)
276 ERROR("Not enough space available...");
277
278 *(dest++) = cff->header.major;
279 *(dest++) = cff->header.minor;
280 *(dest++) = 4; /* Additional data in between header and
281 * Name INDEX ignored.
282 */
283 /* We will set all offset (0) to four-byte integer. */
284 *(dest++) = 4;
285 cff->header.offsize = 4;
286
287 return 4;
288 }
289
290 /* Only read header part but not body */
291 cff_index *
cff_get_index_header(cff_font * cff)292 cff_get_index_header (cff_font *cff)
293 {
294 cff_index *idx;
295 card16 i, count;
296
297 idx = NEW(1, cff_index);
298
299 idx->count = count = get_unsigned_pair(cff->stream);
300 if (count > 0) {
301 idx->offsize = get_unsigned_byte(cff->stream);
302 if (idx->offsize < 1 || idx->offsize > 4)
303 ERROR("invalid offsize data");
304
305 idx->offset = NEW(count+1, l_offset);
306 for (i=0;i<count;i++) {
307 (idx->offset)[i] = get_offset(cff->stream, idx->offsize);
308 }
309 if (count == 0xFFFF)
310 cff_seek(cff, cff_tell(cff) + idx->offsize);
311 else
312 (idx->offset)[i] = get_offset(cff->stream, idx->offsize);
313
314 if (idx->offset[0] != 1)
315 ERROR("cff_get_index(): invalid index data");
316
317 idx->data = NULL;
318 } else {
319 idx->offsize = 0;
320 idx->offset = NULL;
321 idx->data = NULL;
322 }
323
324 return idx;
325 }
326
327 cff_index *
cff_get_index(cff_font * cff)328 cff_get_index (cff_font *cff)
329 {
330 cff_index *idx;
331 card16 i, count;
332 long length, nb_read, offset;
333
334 idx = NEW(1, cff_index);
335
336 idx->count = count = get_unsigned_pair(cff->stream);
337 if (count > 0) {
338 idx->offsize = get_unsigned_byte(cff->stream);
339 if (idx->offsize < 1 || idx->offsize > 4)
340 ERROR("invalid offsize data");
341
342 idx->offset = NEW(count + 1, l_offset);
343 for (i = 0 ; i < count + 1; i++) {
344 idx->offset[i] = get_offset(cff->stream, idx->offsize);
345 }
346
347 if (idx->offset[0] != 1)
348 ERROR("Invalid CFF Index offset data");
349
350 length = idx->offset[count] - idx->offset[0];
351
352 idx->data = NEW(length, card8);
353 offset = 0;
354 while (length > 0) {
355 nb_read = cff_read_data(idx->data + offset, length, cff);
356 offset += nb_read;
357 length -= nb_read;
358 }
359 } else {
360 idx->offsize = 0;
361 idx->offset = NULL;
362 idx->data = NULL;
363 }
364
365 return idx;
366 }
367
368 long
cff_pack_index(cff_index * idx,card8 * dest,long destlen)369 cff_pack_index (cff_index *idx, card8 *dest, long destlen)
370 {
371 long len = 0;
372 long datalen;
373 card16 i;
374
375 if (idx->count < 1) {
376 if (destlen < 2)
377 ERROR("Not enough space available...");
378 memset(dest, 0, 2);
379 return 2;
380 }
381
382 len = cff_index_size(idx);
383 datalen = idx->offset[idx->count] - 1;
384
385 if (destlen < len)
386 ERROR("Not enough space available...");
387
388 *(dest++) = (idx->count >> 8) & 0xff;
389 *(dest++) = idx->count & 0xff;
390
391 if (datalen < 0xffUL) {
392 idx->offsize = 1;
393 *(dest++) = 1;
394 for (i = 0; i <= idx->count; i++) {
395 *(dest++) = (card8) (idx->offset[i] & 0xff);
396 }
397 } else if (datalen < 0xffffUL) {
398 idx->offsize = 2;
399 *(dest++) = 2;
400 for (i = 0; i <= idx->count; i++) {
401 *(dest++) = (card8) ((idx->offset[i] >> 8) & 0xff);
402 *(dest++) = (card8) ( idx->offset[i] & 0xff);
403 }
404 } else if (datalen < 0xffffffUL) {
405 idx->offsize = 3;
406 *(dest++) = 3;
407 for (i = 0; i <= idx->count; i++) {
408 *(dest++) = (card8)((idx->offset[i] >> 16) & 0xff);
409 *(dest++) = (card8)((idx->offset[i] >> 8) & 0xff);
410 *(dest++) = (card8)(idx->offset[i] & 0xff);
411 }
412 } else {
413 idx->offsize = 4;
414 *(dest++) = 4;
415 for (i = 0; i <= idx->count; i++) {
416 *(dest++) = (card8)((idx->offset[i] >> 24) & 0xff);
417 *(dest++) = (card8)((idx->offset[i] >> 16) & 0xff);
418 *(dest++) = (card8)((idx->offset[i] >> 8) & 0xff);
419 *(dest++) = (card8)(idx->offset[i] & 0xff);
420 }
421 }
422
423 memmove(dest, idx->data, idx->offset[idx->count] - 1);
424
425 return len;
426 }
427
428 long
cff_index_size(cff_index * idx)429 cff_index_size (cff_index *idx)
430 {
431 if (idx->count > 0) {
432 l_offset datalen;
433
434 datalen = idx->offset[idx->count] - 1;
435 if (datalen < 0xffUL) {
436 idx->offsize = 1;
437 } else if (datalen < 0xffffUL) {
438 idx->offsize = 2;
439 } else if (datalen < 0xffffffUL) {
440 idx->offsize = 3;
441 } else {
442 idx->offsize = 4;
443 }
444 return (3 + (idx->offsize)*(idx->count + 1) + datalen);
445 } else {
446 return 2;
447 }
448 }
449
450
cff_new_index(card16 count)451 cff_index *cff_new_index (card16 count)
452 {
453 cff_index *idx;
454
455 idx = NEW(1, cff_index);
456 idx->count = count;
457 idx->offsize = 0;
458
459 if (count > 0) {
460 idx->offset = NEW(count + 1, l_offset);
461 (idx->offset)[0] = 1;
462 } else {
463 idx->offset = NULL;
464 }
465 idx->data = NULL;
466
467 return idx;
468 }
469
cff_release_index(cff_index * idx)470 void cff_release_index (cff_index *idx)
471 {
472 if (idx) {
473 if (idx->data) {
474 RELEASE(idx->data);
475 }
476 if (idx->offset) {
477 RELEASE(idx->offset);
478 }
479 RELEASE(idx);
480 }
481 }
482
483 /* Strings */
cff_get_string(cff_font * cff,s_SID id)484 char *cff_get_string (cff_font *cff, s_SID id)
485 {
486 char *result = NULL;
487 long len;
488
489 if (id < CFF_STDSTR_MAX) {
490 len = strlen(cff_stdstr[id]);
491 result = NEW(len+1, char);
492 memcpy(result, cff_stdstr[id], len);
493 result[len] = '\0';
494 } else if (cff && cff->string) {
495 cff_index *strings = cff->string;
496 id -= CFF_STDSTR_MAX;
497 if (id < strings->count) {
498 len = (strings->offset)[id+1] - (strings->offset)[id];
499 result = NEW(len + 1, char);
500 memmove(result, strings->data + (strings->offset)[id] - 1, len);
501 result[len] = '\0';
502 }
503 }
504
505 return result;
506 }
507
cff_get_sid(cff_font * cff,const char * str)508 long cff_get_sid (cff_font *cff, const char *str)
509 {
510 card16 i;
511
512 if (!cff || !str)
513 return -1;
514
515 /* I search String INDEX first. */
516 if (cff && cff->string) {
517 cff_index *idx = cff->string;
518 for (i = 0; i < idx->count; i++) {
519 if (strlen(str) == (idx->offset)[i+1] - (idx->offset)[i] &&
520 !memcmp(str, (idx->data)+(idx->offset)[i]-1, strlen(str)))
521 return (i + CFF_STDSTR_MAX);
522 }
523 }
524
525 for (i = 0; i < CFF_STDSTR_MAX; i++) {
526 if (!strcmp(str, cff_stdstr[i]))
527 return i;
528 }
529
530 return -1;
531 }
532
cff_get_seac_sid(cff_font * cff,const char * str)533 long cff_get_seac_sid (cff_font *cff, const char *str)
534 {
535 card16 i;
536
537 if (!cff || !str)
538 return -1;
539
540 for (i = 0; i < CFF_STDSTR_MAX; i++) {
541 if (!strcmp(str, cff_stdstr[i]))
542 return i;
543 }
544
545 return -1;
546 }
547
cff_match_string(cff_font * cff,const char * str,s_SID sid)548 int cff_match_string (cff_font *cff, const char *str, s_SID sid)
549 {
550 card16 i;
551
552 if (sid < CFF_STDSTR_MAX) {
553 return ((!strcmp(str, cff_stdstr[sid])) ? 1 : 0);
554 } else {
555 i = sid - CFF_STDSTR_MAX;
556 if (cff == NULL || cff->string == NULL || i >= cff->string->count)
557 ERROR("Invalid SID");
558 if (strlen(str) == (cff->string->offset)[i+1] - (cff->string->offset)[i])
559 return (!memcmp(str,
560 (cff->string->data)+(cff->string->offset)[i]-1,
561 strlen(str))) ? 1 : 0;
562 }
563
564 return 0;
565 }
566
cff_update_string(cff_font * cff)567 void cff_update_string (cff_font *cff)
568 {
569 if (cff == NULL)
570 ERROR("CFF font not opened.");
571
572 if (cff->string)
573 cff_release_index(cff->string);
574 cff->string = cff->_string;
575 cff->_string = NULL;
576 }
577
cff_add_string(cff_font * cff,const char * str,int unique)578 s_SID cff_add_string (cff_font *cff, const char *str, int unique)
579 /* Setting unique == 1 eliminates redundant or predefined strings. */
580 {
581 card16 idx;
582 cff_index *strings;
583 l_offset offset, size;
584 long len = strlen(str);
585
586 if (cff == NULL)
587 ERROR("CFF font not opened.");
588
589 if (cff->_string == NULL)
590 cff->_string = cff_new_index(0);
591 strings = cff->_string;
592
593 if (unique) {
594 /* TODO: do binary search to speed things up */
595 for (idx = 0; idx < CFF_STDSTR_MAX; idx++) {
596 if (cff_stdstr[idx] && !strcmp(cff_stdstr[idx], str))
597 return idx;
598 }
599 for (idx = 0; idx < strings->count; idx++) {
600 size = strings->offset[idx+1] - strings->offset[idx];
601 offset = strings->offset[idx];
602 if (size == len && !memcmp(strings->data+offset-1, str, len))
603 return (idx + CFF_STDSTR_MAX);
604 }
605 }
606
607 offset = (strings->count > 0) ? strings->offset[strings->count] : 1;
608 strings->offset = RENEW(strings->offset, strings->count+2, l_offset);
609 if (strings->count == 0)
610 strings->offset[0] = 1;
611 idx = strings->count;
612 strings->count += 1;
613 strings->offset[strings->count] = offset + len;
614 strings->data = RENEW(strings->data, offset+len-1, card8);
615 memcpy(strings->data+offset-1, str, len);
616
617 return (idx + CFF_STDSTR_MAX);
618 }
619
620 /*
621 * Encoding and Charset
622 *
623 * Encoding and Charset arrays always begin with GID = 1.
624 */
cff_read_encoding(cff_font * cff)625 long cff_read_encoding (cff_font *cff)
626 {
627 cff_encoding *encoding;
628 long offset, length;
629 card8 i;
630
631 if (cff->topdict == NULL) {
632 ERROR("Top DICT data not found");
633 }
634
635 if (!cff_dict_known(cff->topdict, "Encoding")) {
636 cff->flag |= ENCODING_STANDARD;
637 cff->encoding = NULL;
638 return 0;
639 }
640
641 offset = (long) cff_dict_get(cff->topdict, "Encoding", 0);
642 if (offset == 0) { /* predefined */
643 cff->flag |= ENCODING_STANDARD;
644 cff->encoding = NULL;
645 return 0;
646 } else if (offset == 1) {
647 cff->flag |= ENCODING_EXPERT;
648 cff->encoding = NULL;
649 return 0;
650 }
651
652 cff_seek_set(cff, offset);
653 cff->encoding = encoding = NEW(1, cff_encoding);
654 encoding->format = get_unsigned_byte(cff->stream);
655 length = 1;
656
657 switch (encoding->format & (~0x80)) {
658 case 0:
659 encoding->num_entries = get_unsigned_byte(cff->stream);
660 (encoding->data).codes = NEW(encoding->num_entries, card8);
661 for (i=0;i<(encoding->num_entries);i++) {
662 (encoding->data).codes[i] = get_unsigned_byte(cff->stream);
663 }
664 length += encoding->num_entries + 1;
665 break;
666 case 1:
667 {
668 cff_range1 *ranges;
669 encoding->num_entries = get_unsigned_byte(cff->stream);
670 encoding->data.range1 = ranges
671 = NEW(encoding->num_entries, cff_range1);
672 for (i=0;i<(encoding->num_entries);i++) {
673 ranges[i].first = get_unsigned_byte(cff->stream);
674 ranges[i].n_left = get_unsigned_byte(cff->stream);
675 }
676 length += (encoding->num_entries) * 2 + 1;
677 }
678 break;
679 default:
680 RELEASE(encoding);
681 ERROR("Unknown Encoding format");
682 break;
683 }
684
685 /* Supplementary data */
686 if ((encoding->format) & 0x80) {
687 cff_map *map;
688 encoding->num_supps = get_unsigned_byte(cff->stream);
689 encoding->supp = map = NEW(encoding->num_supps, cff_map);
690 for (i=0;i<(encoding->num_supps);i++) {
691 map[i].code = get_unsigned_byte(cff->stream);
692 map[i].glyph = get_unsigned_pair(cff->stream); /* SID */
693 }
694 length += (encoding->num_supps) * 3 + 1;
695 } else {
696 encoding->num_supps = 0;
697 encoding->supp = NULL;
698 }
699
700 return length;
701 }
702
cff_pack_encoding(cff_font * cff,card8 * dest,long destlen)703 long cff_pack_encoding (cff_font *cff, card8 *dest, long destlen)
704 {
705 long len = 0;
706 cff_encoding *encoding;
707 card16 i;
708
709 if (cff->flag & HAVE_STANDARD_ENCODING || cff->encoding == NULL)
710 return 0;
711
712 if (destlen < 2)
713 ERROR("in cff_pack_encoding(): Buffer overflow");
714
715 encoding = cff->encoding;
716
717 dest[len++] = encoding->format;
718 dest[len++] = encoding->num_entries;
719 switch (encoding->format & (~0x80)) {
720 case 0:
721 if (destlen < len + encoding->num_entries)
722 ERROR("in cff_pack_encoding(): Buffer overflow");
723 for (i=0;i<(encoding->num_entries);i++) {
724 dest[len++] = (encoding->data).codes[i];
725 }
726 break;
727 case 1:
728 {
729 if (destlen < len + (encoding->num_entries)*2)
730 ERROR("in cff_pack_encoding(): Buffer overflow");
731 for (i=0;i<(encoding->num_entries);i++) {
732 dest[len++] = (encoding->data).range1[i].first & 0xff;
733 dest[len++] = (encoding->data).range1[i].n_left;
734 }
735 }
736 break;
737 default:
738 ERROR("Unknown Encoding format");
739 break;
740 }
741
742 if ((encoding->format) & 0x80) {
743 if (destlen < len + (encoding->num_supps)*3 + 1)
744 ERROR("in cff_pack_encoding(): Buffer overflow");
745 dest[len++] = encoding->num_supps;
746 for (i=0;i<(encoding->num_supps);i++) {
747 dest[len++] = (encoding->supp)[i].code;
748 dest[len++] = ((encoding->supp)[i].glyph >> 8) & 0xff;
749 dest[len++] = (encoding->supp)[i].glyph & 0xff;
750 }
751 }
752
753 return len;
754 }
755
756 /* input: code, output: glyph index */
cff_encoding_lookup(cff_font * cff,card8 code)757 card16 cff_encoding_lookup (cff_font *cff, card8 code)
758 {
759 card16 gid = 0;
760 cff_encoding *encoding;
761 card16 i;
762
763 if (cff->flag & (ENCODING_STANDARD|ENCODING_EXPERT)) {
764 ERROR("Predefined CFF encoding not supported yet");
765 } else if (cff->encoding == NULL) {
766 ERROR("Encoding data not available");
767 }
768
769 encoding = cff->encoding;
770
771 gid = 0;
772 switch (encoding->format & (~0x80)) {
773 case 0:
774 for (i = 0; i < encoding->num_entries; i++) {
775 if (code == (encoding->data).codes[i]) {
776 gid = i + 1;
777 break;
778 }
779 }
780 break;
781 case 1:
782 for (i = 0; i < encoding->num_entries; i++) {
783 if (code >= (encoding->data).range1[i].first &&
784 code <= (encoding->data).range1[i].first + (encoding->data).range1[i].n_left) {
785 gid += code - (encoding->data).range1[i].first + 1;
786 break;
787 }
788 gid += (encoding->data).range1[i].n_left + 1;
789 }
790 if (i == encoding->num_entries)
791 gid = 0;
792 break;
793 default:
794 ERROR("Unknown Encoding format.");
795 }
796
797 /* Supplementary data */
798 if (gid == 0 && ((encoding->format) & 0x80)) {
799 cff_map *map;
800 if (!encoding->supp)
801 ERROR("No CFF supplementary encoding data read.");
802 map = encoding->supp;
803 for (i=0;i<(encoding->num_supps);i++) {
804 if (code == map[i].code) {
805 gid = cff_charsets_lookup(cff, map[i].glyph);
806 break;
807 }
808 }
809 }
810
811 return gid;
812 }
813
cff_release_encoding(cff_encoding * encoding)814 void cff_release_encoding (cff_encoding *encoding)
815 {
816 if (encoding) {
817 switch (encoding->format & (~0x80)) {
818 case 0:
819 if (encoding->data.codes)
820 RELEASE(encoding->data.codes);
821 break;
822 case 1:
823 if (encoding->data.range1)
824 RELEASE(encoding->data.range1);
825 break;
826 default:
827 ERROR("Unknown Encoding format.");
828 }
829 if (encoding->format & 0x80) {
830 if (encoding->supp)
831 RELEASE(encoding->supp);
832 }
833 RELEASE(encoding);
834 }
835 }
836
cff_read_charsets(cff_font * cff)837 long cff_read_charsets (cff_font *cff)
838 {
839 cff_charsets *charset;
840 long offset, length;
841 card16 count, i;
842
843 if (cff->topdict == NULL)
844 ERROR("Top DICT not available");
845
846 if (!cff_dict_known(cff->topdict, "charset")) {
847 cff->flag |= CHARSETS_ISOADOBE;
848 cff->charsets = NULL;
849 return 0;
850 }
851
852 offset = (long) cff_dict_get(cff->topdict, "charset", 0);
853
854 if (offset == 0) { /* predefined */
855 cff->flag |= CHARSETS_ISOADOBE;
856 cff->charsets = NULL;
857 return 0;
858 } else if (offset == 1) {
859 cff->flag |= CHARSETS_EXPERT;
860 cff->charsets = NULL;
861 return 0;
862 } else if (offset == 2) {
863 cff->flag |= CHARSETS_EXPSUB;
864 cff->charsets = NULL;
865 return 0;
866 }
867
868 cff_seek_set(cff, offset);
869 cff->charsets = charset = NEW(1, cff_charsets);
870 charset->format = get_unsigned_byte(cff->stream);
871 charset->num_entries = 0;
872
873 count = cff->num_glyphs - 1;
874 length = 1;
875
876 /* Not sure. Not well documented. */
877 switch (charset->format) {
878 case 0:
879 charset->num_entries = cff->num_glyphs - 1; /* no .notdef */
880 charset->data.glyphs = NEW(charset->num_entries, s_SID);
881 length += (charset->num_entries) * 2;
882 for (i=0;i<(charset->num_entries);i++) {
883 charset->data.glyphs[i] = get_unsigned_pair(cff->stream);
884 }
885 count = 0;
886 break;
887 case 1:
888 {
889 cff_range1 *ranges = NULL;
890 while (count > 0 && charset->num_entries < cff->num_glyphs) {
891 ranges = RENEW(ranges, charset->num_entries + 1, cff_range1);
892 ranges[charset->num_entries].first = get_unsigned_pair(cff->stream);
893 ranges[charset->num_entries].n_left = get_unsigned_byte(cff->stream);
894 count -= ranges[charset->num_entries].n_left + 1; /* no-overrap */
895 charset->num_entries += 1;
896 charset->data.range1 = ranges;
897 }
898 length += (charset->num_entries) * 3;
899 }
900 break;
901 case 2:
902 {
903 cff_range2 *ranges = NULL;
904 while (count > 0 && charset->num_entries < cff->num_glyphs) {
905 ranges = RENEW(ranges, charset->num_entries + 1, cff_range2);
906 ranges[charset->num_entries].first = get_unsigned_pair(cff->stream);
907 ranges[charset->num_entries].n_left = get_unsigned_pair(cff->stream);
908 count -= ranges[charset->num_entries].n_left + 1; /* non-overrapping */
909 charset->num_entries += 1;
910 }
911 charset->data.range2 = ranges;
912 length += (charset->num_entries) * 4;
913 }
914 break;
915 default:
916 RELEASE(charset);
917 ERROR("Unknown Charset format");
918 break;
919 }
920
921 if (count > 0)
922 ERROR("Charset data possibly broken");
923
924 return length;
925 }
926
cff_pack_charsets(cff_font * cff,card8 * dest,long destlen)927 long cff_pack_charsets (cff_font *cff, card8 *dest, long destlen)
928 {
929 long len = 0;
930 card16 i;
931 cff_charsets *charset;
932
933 if (cff->flag & HAVE_STANDARD_CHARSETS || cff->charsets == NULL)
934 return 0;
935
936 if (destlen < 1)
937 ERROR("in cff_pack_charsets(): Buffer overflow");
938
939 charset = cff->charsets;
940
941 dest[len++] = charset->format;
942 switch (charset->format) {
943 case 0:
944 if (destlen < len + (charset->num_entries)*2)
945 ERROR("in cff_pack_charsets(): Buffer overflow");
946 for (i=0;i<(charset->num_entries);i++) {
947 s_SID sid = (charset->data).glyphs[i]; /* or CID */
948 dest[len++] = (sid >> 8) & 0xff;
949 dest[len++] = sid & 0xff;
950 }
951 break;
952 case 1:
953 {
954 if (destlen < len + (charset->num_entries)*3)
955 ERROR("in cff_pack_charsets(): Buffer overflow");
956 for (i=0;i<(charset->num_entries);i++) {
957 dest[len++] = ((charset->data).range1[i].first >> 8) & 0xff;
958 dest[len++] = (charset->data).range1[i].first & 0xff;
959 dest[len++] = (charset->data).range1[i].n_left;
960 }
961 }
962 break;
963 case 2:
964 {
965 if (destlen < len + (charset->num_entries)*4)
966 ERROR("in cff_pack_charsets(): Buffer overflow");
967 for (i=0;i<(charset->num_entries);i++) {
968 dest[len++] = ((charset->data).range2[i].first >> 8) & 0xff;
969 dest[len++] = (charset->data).range2[i].first & 0xff;
970 dest[len++] = ((charset->data).range2[i].n_left >> 8) & 0xff;
971 dest[len++] = (charset->data).range2[i].n_left & 0xff;
972 }
973 }
974 break;
975 default:
976 ERROR("Unknown Charset format");
977 break;
978 }
979
980 return len;
981 }
982
cff_get_glyphname(cff_font * cff,card16 gid)983 char* cff_get_glyphname (cff_font *cff, card16 gid)
984 {
985 s_SID sid;
986
987 sid = cff_charsets_lookup_inverse(cff, gid);
988 return cff_get_string(cff, sid);
989 }
990
cff_glyph_lookup(cff_font * cff,const char * glyph)991 card16 cff_glyph_lookup (cff_font *cff, const char *glyph)
992 {
993 card16 gid;
994 cff_charsets *charset;
995 card16 i, n;
996
997 if (cff->flag & (CHARSETS_ISOADOBE|CHARSETS_EXPERT|CHARSETS_EXPSUB)) {
998 ERROR("Predefined CFF charsets not supported yet");
999 } else if (cff->charsets == NULL) {
1000 ERROR("Charsets data not available");
1001 }
1002
1003 /* .notdef always have glyph index 0 */
1004 if (!glyph || !strcmp(glyph, ".notdef")) {
1005 return 0;
1006 }
1007
1008 charset = cff->charsets;
1009
1010 gid = 0;
1011 switch (charset->format) {
1012 case 0:
1013 for (i = 0; i < charset->num_entries; i++) {
1014 gid++;
1015 if (cff_match_string(cff, glyph, charset->data.glyphs[i])) {
1016 return gid;
1017 }
1018 }
1019 break;
1020 case 1:
1021 for (i = 0; i < charset->num_entries; i++) {
1022 for (n = 0;
1023 n <= charset->data.range1[i].n_left; n++) {
1024 gid++;
1025 if (cff_match_string(cff, glyph,
1026 (s_SID)(charset->data.range1[i].first + n))) {
1027 return gid;
1028 }
1029 }
1030 }
1031 break;
1032 case 2:
1033 for (i = 0; i <charset->num_entries; i++) {
1034 for (n = 0;
1035 n <= charset->data.range2[i].n_left; n++) {
1036 gid++;
1037 if (cff_match_string(cff, glyph,
1038 (s_SID)(charset->data.range2[i].first + n))) {
1039 return gid;
1040 }
1041 }
1042 }
1043 break;
1044 default:
1045 ERROR("Unknown Charset format");
1046 }
1047
1048 return 0; /* not found, returns .notdef */
1049 }
1050
1051 /* Input : SID or CID (16-bit unsigned int)
1052 * Output: glyph index
1053 */
1054 card16
cff_charsets_lookup(cff_font * cff,card16 cid)1055 cff_charsets_lookup (cff_font *cff, card16 cid)
1056 {
1057 if (cff->flag & (CHARSETS_ISOADOBE|CHARSETS_EXPERT|CHARSETS_EXPSUB)) {
1058 ERROR("Predefined CFF charsets not supported yet");
1059 } else if (cff->charsets == NULL) {
1060 ERROR("Charsets data not available");
1061 }
1062
1063 return cff_charsets_lookup_gid(cff->charsets, cid);
1064 }
1065
cff_charsets_lookup_gid(cff_charsets * charset,card16 cid)1066 card16 cff_charsets_lookup_gid (cff_charsets *charset, card16 cid)
1067 {
1068 card16 gid = 0;
1069 card16 i;
1070
1071 if (cid == 0) {
1072 return 0; /* GID 0 (.notdef) */
1073 }
1074
1075 switch (charset->format) {
1076 case 0:
1077 for (i = 0; i <charset->num_entries; i++) {
1078 if (cid == charset->data.glyphs[i]) {
1079 gid = i + 1;
1080 return gid;
1081 }
1082 }
1083 break;
1084 case 1:
1085 for (i = 0; i < charset->num_entries; i++) {
1086 if (cid >= charset->data.range1[i].first &&
1087 cid <= charset->data.range1[i].first + charset->data.range1[i].n_left) {
1088 gid += cid - charset->data.range1[i].first + 1;
1089 return gid;
1090 }
1091 gid += charset->data.range1[i].n_left + 1;
1092 }
1093 break;
1094 case 2:
1095 for (i = 0; i < charset->num_entries; i++) {
1096 if (cid >= charset->data.range2[i].first &&
1097 cid <= charset->data.range2[i].first + charset->data.range2[i].n_left) {
1098 gid += cid - charset->data.range2[i].first + 1;
1099 return gid;
1100 }
1101 gid += charset->data.range2[i].n_left + 1;
1102 }
1103 break;
1104 default:
1105 ERROR("Unknown Charset format");
1106 }
1107
1108 return 0; /* not found */
1109 }
1110
1111 /* Input : GID
1112 * Output: SID/CID (card16)
1113 */
1114 card16
cff_charsets_lookup_inverse(cff_font * cff,card16 gid)1115 cff_charsets_lookup_inverse (cff_font *cff, card16 gid)
1116 {
1117 if (cff->flag & (CHARSETS_ISOADOBE|CHARSETS_EXPERT|CHARSETS_EXPSUB)) {
1118 ERROR("Predefined CFF charsets not supported yet");
1119 } else if (cff->charsets == NULL) {
1120 ERROR("Charsets data not available");
1121 }
1122
1123 if (gid == 0) {
1124 return 0; /* .notdef */
1125 }
1126
1127 return cff_charsets_lookup_cid(cff->charsets, gid);
1128 }
1129
1130 card16
cff_charsets_lookup_cid(cff_charsets * charset,card16 gid)1131 cff_charsets_lookup_cid(cff_charsets *charset, card16 gid)
1132 {
1133 card16 sid = 0;
1134 card16 i;
1135
1136 switch (charset->format) {
1137 case 0:
1138 if (gid - 1 >= charset->num_entries)
1139 ERROR("Invalid GID.");
1140 sid = charset->data.glyphs[gid - 1];
1141 break;
1142 case 1:
1143 for (i = 0; i < charset->num_entries; i++) {
1144 if (gid <= charset->data.range1[i].n_left + 1) {
1145 sid = gid + charset->data.range1[i].first - 1;
1146 break;
1147 }
1148 gid -= charset->data.range1[i].n_left + 1;
1149 }
1150 if (i == charset->num_entries)
1151 ERROR("Invalid GID");
1152 break;
1153 case 2:
1154 for (i = 0; i < charset->num_entries; i++) {
1155 if (gid <= charset->data.range2[i].n_left + 1) {
1156 sid = gid + charset->data.range2[i].first - 1;
1157 break;
1158 }
1159 gid -= charset->data.range2[i].n_left + 1;
1160 }
1161 if (i == charset->num_entries)
1162 ERROR("Invalid GID");
1163 break;
1164 default:
1165 ERROR("Unknown Charset format");
1166 }
1167
1168 return sid;
1169 }
1170
1171 void
cff_release_charsets(cff_charsets * charset)1172 cff_release_charsets (cff_charsets *charset)
1173 {
1174 if (charset) {
1175 switch (charset->format) {
1176 case 0:
1177 if (charset->data.glyphs)
1178 RELEASE(charset->data.glyphs);
1179 break;
1180 case 1:
1181 if (charset->data.range1)
1182 RELEASE(charset->data.range1);
1183 break;
1184 case 2:
1185 if (charset->data.range2)
1186 RELEASE(charset->data.range2);
1187 break;
1188 default:
1189 break;
1190 }
1191 RELEASE(charset);
1192 }
1193 }
1194
1195 /* CID-Keyed font specific */
cff_read_fdselect(cff_font * cff)1196 long cff_read_fdselect (cff_font *cff)
1197 {
1198 cff_fdselect *fdsel;
1199 long offset, length;
1200 card16 i;
1201
1202 if (cff->topdict == NULL)
1203 ERROR("Top DICT not available");
1204
1205 if (!(cff->flag & FONTTYPE_CIDFONT))
1206 return 0;
1207
1208 offset = (long) cff_dict_get(cff->topdict, "FDSelect", 0);
1209 cff_seek_set(cff, offset);
1210 cff->fdselect = fdsel = NEW(1, cff_fdselect);
1211 fdsel->format = get_unsigned_byte(cff->stream);
1212
1213 length = 1;
1214
1215 switch (fdsel->format) {
1216 case 0:
1217 fdsel->num_entries = cff->num_glyphs;
1218 (fdsel->data).fds = NEW(fdsel->num_entries, card8);
1219 for (i=0;i<(fdsel->num_entries);i++) {
1220 (fdsel->data).fds[i] = get_unsigned_byte(cff->stream);
1221 }
1222 length += fdsel->num_entries;
1223 break;
1224 case 3:
1225 {
1226 cff_range3 *ranges;
1227 fdsel->num_entries = get_unsigned_pair(cff->stream);
1228 fdsel->data.ranges = ranges = NEW(fdsel->num_entries, cff_range3);
1229 for (i=0;i<(fdsel->num_entries);i++) {
1230 ranges[i].first = get_unsigned_pair(cff->stream);
1231 ranges[i].fd = get_unsigned_byte(cff->stream);
1232 }
1233 if (ranges[0].first != 0)
1234 ERROR("Range not starting with 0.");
1235 if (cff->num_glyphs != get_unsigned_pair(cff->stream))
1236 ERROR("Sentinel value mismatched with number of glyphs.");
1237 length += (fdsel->num_entries) * 3 + 4;
1238 }
1239 break;
1240 default:
1241 RELEASE(fdsel);
1242 ERROR("Unknown FDSelect format.");
1243 break;
1244 }
1245
1246 return length;
1247 }
1248
cff_pack_fdselect(cff_font * cff,card8 * dest,long destlen)1249 long cff_pack_fdselect (cff_font *cff, card8 *dest, long destlen)
1250 {
1251 cff_fdselect *fdsel;
1252 long len = 0;
1253 card16 i;
1254
1255 if (cff->fdselect == NULL)
1256 return 0;
1257
1258 if (destlen < 1)
1259 ERROR("in cff_pack_fdselect(): Buffur overflow");
1260
1261 fdsel = cff->fdselect;
1262
1263 dest[len++] = fdsel->format;
1264 switch (fdsel->format) {
1265 case 0:
1266 if (fdsel->num_entries != cff->num_glyphs)
1267 ERROR("in cff_pack_fdselect(): Invalid data");
1268 if (destlen < len + fdsel->num_entries)
1269 ERROR("in cff_pack_fdselect(): Buffer overflow");
1270 for (i=0;i<fdsel->num_entries;i++) {
1271 dest[len++] = (fdsel->data).fds[i];
1272 }
1273 break;
1274 case 3:
1275 {
1276 if (destlen < len + 2)
1277 ERROR("in cff_pack_fdselect(): Buffer overflow");
1278 len += 2;
1279 for (i=0;i<(fdsel->num_entries);i++) {
1280 if (destlen < len + 3)
1281 ERROR("in cff_pack_fdselect(): Buffer overflow");
1282 dest[len++] = ((fdsel->data).ranges[i].first >> 8) & 0xff;
1283 dest[len++] = (fdsel->data).ranges[i].first & 0xff;
1284 dest[len++] = (fdsel->data).ranges[i].fd;
1285 }
1286 if (destlen < len + 2)
1287 ERROR("in cff_pack_fdselect(): Buffer overflow");
1288 dest[len++] = (cff->num_glyphs >> 8) & 0xff;
1289 dest[len++] = cff->num_glyphs & 0xff;
1290 dest[1] = ((len/3 - 1) >> 8) & 0xff;
1291 dest[2] = (len/3 - 1) & 0xff;
1292 }
1293 break;
1294 default:
1295 ERROR("Unknown FDSelect format.");
1296 break;
1297 }
1298
1299 return len;
1300 }
1301
cff_release_fdselect(cff_fdselect * fdselect)1302 void cff_release_fdselect (cff_fdselect *fdselect)
1303 {
1304 if (fdselect) {
1305 if (fdselect->format == 0) {
1306 if (fdselect->data.fds) RELEASE(fdselect->data.fds);
1307 } else if (fdselect->format == 3) {
1308 if (fdselect->data.ranges) RELEASE(fdselect->data.ranges);
1309 }
1310 RELEASE(fdselect);
1311 }
1312 }
1313
cff_fdselect_lookup(cff_font * cff,card16 gid)1314 card8 cff_fdselect_lookup (cff_font *cff, card16 gid)
1315 {
1316 card8 fd = 0xff;
1317 cff_fdselect *fdsel;
1318
1319 if (cff->fdselect == NULL)
1320 ERROR("in cff_fdselect_lookup(): FDSelect not available");
1321
1322 fdsel = cff->fdselect;
1323
1324 if (gid >= cff->num_glyphs)
1325 ERROR("in cff_fdselect_lookup(): Invalid glyph index");
1326
1327 switch (fdsel->format) {
1328 case 0:
1329 fd = fdsel->data.fds[gid];
1330 break;
1331 case 3:
1332 {
1333 if (gid == 0) {
1334 fd = (fdsel->data).ranges[0].fd;
1335 } else {
1336 card16 i;
1337 for (i=1;i<(fdsel->num_entries);i++) {
1338 if (gid < (fdsel->data).ranges[i].first)
1339 break;
1340 }
1341 fd = (fdsel->data).ranges[i-1].fd;
1342 }
1343 }
1344 break;
1345 default:
1346 ERROR("in cff_fdselect_lookup(): Invalid FDSelect format");
1347 break;
1348 }
1349
1350 if (fd >= cff->num_fds)
1351 ERROR("in cff_fdselect_lookup(): Invalid Font DICT index");
1352
1353 return fd;
1354 }
1355
cff_read_subrs(cff_font * cff)1356 long cff_read_subrs (cff_font *cff)
1357 {
1358 long len = 0;
1359 long offset;
1360 int i;
1361
1362 if ((cff->flag & FONTTYPE_CIDFONT) && cff->fdarray == NULL) {
1363 cff_read_fdarray(cff);
1364 }
1365
1366 if (cff->private == NULL)
1367 cff_read_private(cff);
1368
1369 if (cff->gsubr == NULL) {
1370 cff_seek_set(cff, cff->gsubr_offset);
1371 cff->gsubr = cff_get_index(cff);
1372 }
1373
1374 cff->subrs = NEW(cff->num_fds, cff_index *);
1375 if (cff->flag & FONTTYPE_CIDFONT) {
1376 for (i=0;i<cff->num_fds;i++) {
1377 if (cff->private[i] == NULL ||
1378 !cff_dict_known(cff->private[i], "Subrs")) {
1379 (cff->subrs)[i] = NULL;
1380 } else {
1381 offset = (long) cff_dict_get(cff->fdarray[i], "Private", 1);
1382 offset += (long) cff_dict_get(cff->private[i], "Subrs", 0);
1383 cff_seek_set(cff, offset);
1384 (cff->subrs)[i] = cff_get_index(cff);
1385 len += cff_index_size((cff->subrs)[i]);
1386 }
1387 }
1388 } else {
1389 if (cff->private[0] == NULL ||
1390 !cff_dict_known(cff->private[0], "Subrs")) {
1391 (cff->subrs)[0] = NULL;
1392 } else {
1393 offset = (long) cff_dict_get(cff->topdict, "Private", 1);
1394 offset += (long) cff_dict_get(cff->private[0], "Subrs", 0);
1395 cff_seek_set(cff, offset);
1396 (cff->subrs)[0] = cff_get_index(cff);
1397 len += cff_index_size((cff->subrs)[0]);
1398 }
1399 }
1400
1401 return len;
1402 }
1403
cff_read_fdarray(cff_font * cff)1404 long cff_read_fdarray (cff_font *cff)
1405 {
1406 long len = 0;
1407 cff_index *idx;
1408 long offset, size;
1409 card16 i;
1410
1411 if (cff->topdict == NULL)
1412 ERROR("in cff_read_fdarray(): Top DICT not found");
1413
1414 if (!(cff->flag & FONTTYPE_CIDFONT))
1415 return 0;
1416
1417 /* must exist */
1418 offset = (long) cff_dict_get(cff->topdict, "FDArray", 0);
1419 cff_seek_set(cff, offset);
1420 idx = cff_get_index(cff);
1421 cff->num_fds = (card8)idx->count;
1422 cff->fdarray = NEW(idx->count, cff_dict *);
1423 for (i=0;i<idx->count;i++) {
1424 card8 *data = idx->data + (idx->offset)[i] - 1;
1425 size = (idx->offset)[i+1] - (idx->offset)[i];
1426 if (size > 0) {
1427 (cff->fdarray)[i] = cff_dict_unpack(data, data+size);
1428 } else {
1429 (cff->fdarray)[i] = NULL;
1430 }
1431 }
1432 len = cff_index_size(idx);
1433 cff_release_index(idx);
1434
1435 return len;
1436 }
1437
cff_read_private(cff_font * cff)1438 long cff_read_private (cff_font *cff)
1439 {
1440 long len = 0;
1441 card8 *data;
1442 long offset, size;
1443
1444 if (cff->flag & FONTTYPE_CIDFONT) {
1445 int i;
1446
1447 if (cff->fdarray == NULL)
1448 cff_read_fdarray(cff);
1449
1450 cff->private = NEW(cff->num_fds, cff_dict *);
1451 for (i=0;i<cff->num_fds;i++) {
1452 if (cff->fdarray[i] != NULL &&
1453 cff_dict_known(cff->fdarray[i], "Private") &&
1454 (size = (long) cff_dict_get(cff->fdarray[i], "Private", 0))
1455 > 0) {
1456 offset = (long) cff_dict_get(cff->fdarray[i], "Private", 1);
1457 cff_seek_set(cff, offset);
1458 data = NEW(size, card8);
1459 if (cff_read_data(data, size, cff) != size)
1460 ERROR("reading file failed");
1461 (cff->private)[i] = cff_dict_unpack(data, data+size);
1462 RELEASE(data);
1463 len += size;
1464 } else {
1465 (cff->private)[i] = NULL;
1466 }
1467 }
1468 } else {
1469 cff->num_fds = 1;
1470 cff->private = NEW(1, cff_dict *);
1471 if (cff_dict_known(cff->topdict, "Private") &&
1472 (size = (long) cff_dict_get(cff->topdict, "Private", 0)) > 0) {
1473 offset = (long) cff_dict_get(cff->topdict, "Private", 1);
1474 cff_seek_set(cff, offset);
1475 data = NEW(size, card8);
1476 if (cff_read_data(data, size, cff) != size)
1477 ERROR("reading file failed");
1478 cff->private[0] = cff_dict_unpack(data, data+size);
1479 RELEASE(data);
1480 len += size;
1481 } else {
1482 (cff->private)[0] = NULL;
1483 len = 0;
1484 }
1485 }
1486
1487 return len;
1488 }
1489