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