beta-0.89.2
[luatex.git] / source / texk / web2c / luatexdir / font / writecff.w
blob3f4a4e588798c6991330d7834fc9645196340ecc
1 % writecff.w
3 % Copyright 2006-2010 Taco Hoekwater <taco@@luatex.org>
5 % This file is part of LuaTeX.
7 % LuaTeX is free software; you can redistribute it and/or modify it under
8 % the terms of the GNU General Public License as published by the Free
9 % Software Foundation; either version 2 of the License, or (at your
10 % option) any later version.
12 % LuaTeX is distributed in the hope that it will be useful, but WITHOUT
13 % ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 % FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 % License for more details.
17 % You should have received a copy of the GNU General Public License along
18 % with LuaTeX; if not, see <http://www.gnu.org/licenses/>.
20 @ @c
23 #include "ptexlib.h"
24 #include "lua/luatex-api.h"
25 #include "font/writecff.h"
27 extern int cidset;
29 @ @c
30 #define get_offset(s,n) get_unsigned(s, (n))
31 #define get_card8(a) (card8)(a->stream[a->offset++])
32 #define get_card16(a) (card16)(get_unsigned(a,2))
34 #undef b0
35 #undef b1
36 #undef b2
37 #undef b3
39 #define WORK_BUFFER_SIZE 1024
41 static char work_buffer[WORK_BUFFER_SIZE];
43 static unsigned long get_unsigned(cff_font * cff, int n)
45 unsigned long v = 0;
46 while (n-- > 0)
47 v = v * 256 + get_card8(cff);
48 return v;
51 @ @c
53 const char *const cff_stdstr[CFF_STDSTR_MAX] = {
54 ".notdef", "space", "exclam", "quotedbl", "numbersign",
55 "dollar", "percent", "ampersand", "quoteright", "parenleft",
56 "parenright", "asterisk", "plus", "comma", "hyphen",
57 "period", "slash", "zero", "one", "two",
58 "three", "four", "five", "six", "seven",
59 "eight", "nine", "colon", "semicolon", "less",
60 "equal", "greater", "question", "at", "A",
61 "B", "C", "D", "E", "F",
62 "G", "H", "I", "J", "K",
63 "L", "M", "N", "O", "P",
64 "Q", "R", "S", "T", "U",
65 "V", "W", "X", "Y", "Z",
66 "bracketleft", "backslash", "bracketright", "asciicircum", "underscore",
67 "quoteleft", "a", "b", "c", "d",
68 "e", "f", "g", "h", "i",
69 "j", "k", "l", "m", "n",
70 "o", "p", "q", "r", "s",
71 "t", "u", "v", "w", "x",
72 "y", "z", "braceleft", "bar", "braceright",
73 "asciitilde", "exclamdown", "cent", "sterling", "fraction",
74 "yen", "florin", "section", "currency", "quotesingle",
75 "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi",
76 "fl", "endash", "dagger", "daggerdbl", "periodcentered",
77 "paragraph", "bullet", "quotesinglbase", "quotedblbase", "quotedblright",
78 "guillemotright", "ellipsis", "perthousand", "questiondown", "grave",
79 "acute", "circumflex", "tilde", "macron", "breve",
80 "dotaccent", "dieresis", "ring", "cedilla", "hungarumlaut",
81 "ogonek", "caron", "emdash", "AE", "ordfeminine",
82 "Lslash", "Oslash", "OE", "ordmasculine", "ae",
83 "dotlessi", "lslash", "oslash", "oe", "germandbls",
84 "onesuperior", "logicalnot", "mu", "trademark", "Eth",
85 "onehalf", "plusminus", "Thorn", "onequarter", "divide",
86 "brokenbar", "degree", "thorn", "threequarters", "twosuperior",
87 "registered", "minus", "eth", "multiply", "threesuperior",
88 "copyright", "Aacute", "Acircumflex", "Adieresis", "Agrave",
89 "Aring", "Atilde", "Ccedilla", "Eacute", "Ecircumflex",
90 "Edieresis", "Egrave", "Iacute", "Icircumflex", "Idieresis",
91 "Igrave", "Ntilde", "Oacute", "Ocircumflex", "Odieresis",
92 "Ograve", "Otilde", "Scaron", "Uacute", "Ucircumflex",
93 "Udieresis", "Ugrave", "Yacute", "Ydieresis", "Zcaron",
94 "aacute", "acircumflex", "adieresis", "agrave", "aring",
95 "atilde", "ccedilla", "eacute", "ecircumflex", "edieresis",
96 "egrave", "iacute", "icircumflex", "idieresis", "igrave",
97 "ntilde", "oacute", "ocircumflex", "odieresis", "ograve",
98 "otilde", "scaron", "uacute", "ucircumflex", "udieresis",
99 "ugrave", "yacute", "ydieresis", "zcaron", "exclamsmall",
100 "Hungarumlautsmall", "dollaroldstyle", "dollarsuperior", "ampersandsmall",
101 "Acutesmall",
102 "parenleftsuperior", "parenrightsuperior", "twodotenleader",
103 "onedotenleader", "zerooldstyle",
104 "oneoldstyle", "twooldstyle", "threeoldstyle", "fouroldstyle",
105 "fiveoldstyle",
106 "sixoldstyle", "sevenoldstyle", "eightoldstyle", "nineoldstyle",
107 "commasuperior",
108 "threequartersemdash", "periodsuperior", "questionsmall", "asuperior",
109 "bsuperior",
110 "centsuperior", "dsuperior", "esuperior", "isuperior", "lsuperior",
111 "msuperior", "nsuperior", "osuperior", "rsuperior", "ssuperior",
112 "tsuperior", "ff", "ffi", "ffl", "parenleftinferior",
113 "parenrightinferior", "Circumflexsmall", "hyphensuperior", "Gravesmall",
114 "Asmall",
115 "Bsmall", "Csmall", "Dsmall", "Esmall", "Fsmall",
116 "Gsmall", "Hsmall", "Ismall", "Jsmall", "Ksmall",
117 "Lsmall", "Msmall", "Nsmall", "Osmall", "Psmall",
118 "Qsmall", "Rsmall", "Ssmall", "Tsmall", "Usmall",
119 "Vsmall", "Wsmall", "Xsmall", "Ysmall", "Zsmall",
120 "colonmonetary", "onefitted", "rupiah", "Tildesmall", "exclamdownsmall",
121 "centoldstyle", "Lslashsmall", "Scaronsmall", "Zcaronsmall",
122 "Dieresissmall",
123 "Brevesmall", "Caronsmall", "Dotaccentsmall", "Macronsmall", "figuredash",
124 "hypheninferior", "Ogoneksmall", "Ringsmall", "Cedillasmall",
125 "questiondownsmall",
126 "oneeighth", "threeeighths", "fiveeighths", "seveneighths", "onethird",
127 "twothirds", "zerosuperior", "foursuperior", "fivesuperior", "sixsuperior",
128 "sevensuperior", "eightsuperior", "ninesuperior", "zeroinferior",
129 "oneinferior",
130 "twoinferior", "threeinferior", "fourinferior", "fiveinferior",
131 "sixinferior",
132 "seveninferior", "eightinferior", "nineinferior", "centinferior",
133 "dollarinferior",
134 "periodinferior", "commainferior", "Agravesmall", "Aacutesmall",
135 "Acircumflexsmall",
136 "Atildesmall", "Adieresissmall", "Aringsmall", "AEsmall", "Ccedillasmall",
137 "Egravesmall", "Eacutesmall", "Ecircumflexsmall", "Edieresissmall",
138 "Igravesmall",
139 "Iacutesmall", "Icircumflexsmall", "Idieresissmall", "Ethsmall",
140 "Ntildesmall",
141 "Ogravesmall", "Oacutesmall", "Ocircumflexsmall", "Otildesmall",
142 "Odieresissmall",
143 "OEsmall", "Oslashsmall", "Ugravesmall", "Uacutesmall", "Ucircumflexsmall",
144 "Udieresissmall", "Yacutesmall", "Thornsmall", "Ydieresissmall",
145 "001.000", "001.001", "001.002", "001.003",
146 "Black", "Bold", "Book", "Light", "Medium", "Regular", "Roman", "Semibold"
150 @ Only read header part but not body
152 cff_index *cff_get_index_header(cff_font * cff)
154 cff_index *idx;
155 card16 i, count;
157 idx = xcalloc(1, sizeof(cff_index));
159 idx->count = count = get_card16(cff);
160 if (count > 0) {
161 idx->offsize = get_card8(cff);
162 if (idx->offsize < 1 || idx->offsize > 4)
163 normal_error("cff","invalid offsize data");
165 idx->offset =
166 xmalloc((unsigned) (((unsigned) count + 1) * sizeof(l_offset)));
167 for (i = 0; i <count + 1 ; i++) {
168 (idx->offset)[i] = get_offset(cff, idx->offsize);
169 if (i == USHRT_MAX)
170 break;
173 if (idx->offset[0] != 1)
174 normal_error("cff","invalid index data");
176 idx->data = NULL;
177 } else {
178 idx->offsize = 0;
179 idx->offset = NULL;
180 idx->data = NULL;
183 return idx;
188 @ @c
189 cff_index *cff_get_index(cff_font * cff)
191 cff_index *idx;
192 card16 i, count;
193 size_t length;
195 idx = xcalloc(1, sizeof(cff_index));
197 idx->count = count = get_card16(cff);
198 if (count > 0) {
199 idx->offsize = get_card8(cff);
200 if (idx->offsize < 1 || idx->offsize > 4)
201 normal_error("cff","invalid offsize data");
203 idx->offset =
204 xmalloc((unsigned) (((unsigned) count + 1) * sizeof(l_offset)));
205 for (i = 0; i < count + 1; i++) {
206 idx->offset[i] = get_offset(cff, idx->offsize);
209 if (idx->offset[0] != 1)
210 normal_error("cff","invalid index offset data");
212 length = (size_t) (idx->offset[count] - idx->offset[0]);
214 idx->data = xmalloc((unsigned) length * sizeof(card8));
215 memcpy(idx->data, &cff->stream[cff->offset], length);
216 cff->offset += length;
218 } else {
219 idx->offsize = 0;
220 idx->offset = NULL;
221 idx->data = NULL;
223 return idx;
227 @ @c
228 long cff_pack_index(cff_index * idx, card8 * dest, long destlen)
230 long len = 0;
231 unsigned long datalen;
232 card16 i;
234 if (idx->count < 1) {
235 if (destlen < 2)
236 normal_error("cff","not enough space available");
237 memset(dest, 0, 2);
238 return 2;
241 len = cff_index_size(idx);
242 datalen = idx->offset[idx->count] - 1;
244 if (destlen < len)
245 normal_error("cff","not enough space available");
247 *(dest++) = (card8) ((idx->count >> 8) & 0xff);
248 *(dest++) = (card8) (idx->count & 0xff);
250 if (datalen < 0xffUL) {
251 idx->offsize = 1;
252 *(dest++) = 1;
253 for (i = 0; i <= idx->count; i++) {
254 *(dest++) = (card8) (idx->offset[i] & 0xff);
256 } else if (datalen < 0xffffUL) {
257 idx->offsize = 2;
258 *(dest++) = 2;
259 for (i = 0; i <= idx->count; i++) {
260 *(dest++) = (card8) ((idx->offset[i] >> 8) & 0xff);
261 *(dest++) = (card8) (idx->offset[i] & 0xff);
263 } else if (datalen < 0xffffffUL) {
264 idx->offsize = 3;
265 *(dest++) = 3;
266 for (i = 0; i <= idx->count; i++) {
267 *(dest++) = (card8) ((idx->offset[i] >> 16) & 0xff);
268 *(dest++) = (card8) ((idx->offset[i] >> 8) & 0xff);
269 *(dest++) = (card8) (idx->offset[i] & 0xff);
271 } else {
272 idx->offsize = 4;
273 *(dest++) = 4;
274 for (i = 0; i <= idx->count; i++) {
275 *(dest++) = (card8) ((idx->offset[i] >> 24) & 0xff);
276 *(dest++) = (card8) ((idx->offset[i] >> 16) & 0xff);
277 *(dest++) = (card8) ((idx->offset[i] >> 8) & 0xff);
278 *(dest++) = (card8) (idx->offset[i] & 0xff);
282 memmove(dest, idx->data, idx->offset[idx->count] - 1);
284 return len;
287 @ @c
288 long cff_index_size(cff_index * idx)
290 if (idx->count > 0) {
291 l_offset datalen;
293 datalen = idx->offset[idx->count] - 1;
294 if (datalen < 0xffUL) {
295 idx->offsize = 1;
296 } else if (datalen < 0xffffUL) {
297 idx->offsize = 2;
298 } else if (datalen < 0xffffffUL) {
299 idx->offsize = 3;
300 } else {
301 idx->offsize = 4;
303 return (3 + (idx->offsize) * (idx->count + 1) + (long) datalen);
304 } else {
305 return 2;
309 @ @c
310 cff_index *cff_new_index(card16 count)
312 cff_index *idx;
314 idx = xcalloc(1, sizeof(cff_index));
315 idx->count = count;
316 idx->offsize = 0;
318 if (count > 0) {
319 idx->offset = xcalloc((unsigned) (count + 1), sizeof(l_offset));
320 (idx->offset)[0] = 1;
321 } else {
322 idx->offset = NULL;
324 idx->data = NULL;
326 return idx;
330 @ @c
331 void cff_release_index(cff_index * idx)
333 if (idx) {
334 xfree(idx->data);
335 xfree(idx->offset);
336 xfree(idx);
340 @ @c
341 void cff_release_dict(cff_dict * dict)
343 if (dict) {
344 if (dict->entries) {
345 int i;
346 for (i = 0; i < dict->count; i++) {
347 xfree((dict->entries)[i].values);
349 xfree(dict->entries);
351 xfree(dict);
356 @ @c
357 void cff_release_encoding(cff_encoding * encoding)
359 if (encoding) {
360 switch (encoding->format & (~0x80)) {
361 case 0:
362 xfree(encoding->data.codes);
363 break;
364 case 1:
365 xfree(encoding->data.range1);
366 break;
367 default:
368 normal_error("cff","unknown encoding format");
370 if (encoding->format & 0x80)
371 xfree(encoding->supp);
372 xfree(encoding);
376 @ @c
377 void cff_release_charsets(cff_charsets * charset)
379 if (charset) {
380 switch (charset->format) {
381 case 0:
382 xfree(charset->data.glyphs);
383 break;
384 case 1:
385 xfree(charset->data.range1);
386 break;
387 case 2:
388 xfree(charset->data.range2);
389 break;
390 default:
391 break;
393 xfree(charset);
397 @ @c
398 void cff_release_fdselect(cff_fdselect * fdselect)
400 if (fdselect) {
401 if (fdselect->format == 0) {
402 xfree(fdselect->data.fds);
403 } else if (fdselect->format == 3) {
404 xfree(fdselect->data.ranges);
406 xfree(fdselect);
411 @ @c
412 void cff_close(cff_font * cff)
414 card16 i;
416 if (cff) {
417 xfree(cff->fontname);
418 if (cff->name)
419 cff_release_index(cff->name);
420 if (cff->topdict)
421 cff_release_dict(cff->topdict);
422 if (cff->string)
423 cff_release_index(cff->string);
424 if (cff->gsubr)
425 cff_release_index(cff->gsubr);
426 if (cff->encoding)
427 cff_release_encoding(cff->encoding);
428 if (cff->charsets)
429 cff_release_charsets(cff->charsets);
430 if (cff->fdselect)
431 cff_release_fdselect(cff->fdselect);
432 if (cff->cstrings)
433 cff_release_index(cff->cstrings);
434 if (cff->fdarray) {
435 for (i = 0; i < cff->num_fds; i++) {
436 if (cff->fdarray[i])
437 cff_release_dict(cff->fdarray[i]);
439 xfree(cff->fdarray);
441 if (cff->private) {
442 for (i = 0; i < cff->num_fds; i++) {
443 if (cff->private[i])
444 cff_release_dict(cff->private[i]);
446 xfree(cff->private);
448 if (cff->subrs) {
449 for (i = 0; i < cff->num_fds; i++) {
450 if (cff->subrs[i])
451 cff_release_index(cff->subrs[i]);
453 xfree(cff->subrs);
455 if (cff->_string)
456 cff_release_index(cff->_string);
457 xfree(cff);
460 return;
463 @ @c
464 char *cff_get_name(cff_font * cff)
466 char *fontname;
467 l_offset len;
468 cff_index *idx;
470 idx = cff->name;
471 len = idx->offset[cff->index + 1] - idx->offset[cff->index];
472 fontname = xmalloc((unsigned) (len + 1) * sizeof(char));
473 memcpy(fontname, idx->data + idx->offset[cff->index] - 1, len);
474 fontname[len] = '\0';
476 return fontname;
480 @ @c
481 long cff_set_name(cff_font * cff, char *name)
483 cff_index *idx;
485 if (strlen(name) > 127)
486 normal_error("cff","FontName string length too large");
488 if (cff->name)
489 cff_release_index(cff->name);
491 cff->name = idx = xcalloc(1, sizeof(cff_index));
492 idx->count = 1;
493 idx->offsize = 1;
494 idx->offset = xmalloc(2 * sizeof(l_offset));
495 (idx->offset)[0] = 1;
496 (idx->offset)[1] = strlen(name) + 1;
497 idx->data = xmalloc((unsigned) strlen(name) * sizeof(card8));
498 memmove(idx->data, name, strlen(name)); /* no trailing |'\0'| */
500 return (long) (5 + strlen(name));
503 long cff_put_header(cff_font * cff, card8 * dest, long destlen)
505 if (destlen < 4)
506 normal_error("cff","not enough space available");
508 *(dest++) = cff->header_major;
509 *(dest++) = cff->header_minor;
510 *(dest++) = 4; /* Additional data in between header and
511 * Name INDEX ignored.
513 /* We will set all offset (0) to four-byte integer. */
514 *(dest++) = 4;
515 cff->header_offsize = 4;
517 return 4;
520 @ @c
521 #define CFF_PARSE_OK 0
522 #define CFF_CFF_ERROR_PARSE_CFF_ERROR -1
523 #define CFF_CFF_ERROR_STACK_OVERFLOW -2
524 #define CFF_CFF_ERROR_STACK_UNDERFLOW -3
525 #define CFF_CFF_ERROR_STACK_RANGECHECK -4
527 #define DICT_ENTRY_MAX 16
529 cff_dict *cff_new_dict(void)
531 cff_dict *dict;
533 dict = xcalloc(1, sizeof(cff_dict));
534 dict->max = DICT_ENTRY_MAX;
535 dict->count = 0;
536 dict->entries = xcalloc((unsigned) dict->max, sizeof(cff_dict_entry));
537 return dict;
542 Operand stack:
543 only numbers are stored (as double)
545 Operand types:
547 number : double (integer or real)
548 boolean: stored as a number
549 SID : stored as a number
550 array : array of numbers
551 delta : array of numbers
554 #define CFF_DICT_STACK_LIMIT 64
555 static int stack_top = 0;
556 static double arg_stack[CFF_DICT_STACK_LIMIT];
559 CFF DICT encoding:
560 TODO: default values
563 #define CFF_LAST_DICT_OP1 22
564 #define CFF_LAST_DICT_OP2 39
565 #define CFF_LAST_DICT_OP (CFF_LAST_DICT_OP1 + CFF_LAST_DICT_OP2)
567 static struct {
568 const char *opname;
569 int argtype;
570 } dict_operator[CFF_LAST_DICT_OP] = {
572 "version", CFF_TYPE_SID}, {
573 "Notice", CFF_TYPE_SID}, {
574 "FullName", CFF_TYPE_SID}, {
575 "FamilyName", CFF_TYPE_SID}, {
576 "Weight", CFF_TYPE_SID}, {
577 "FontBBox", CFF_TYPE_ARRAY}, {
578 "BlueValues", CFF_TYPE_DELTA}, {
579 "OtherBlues", CFF_TYPE_DELTA}, {
580 "FamilyBlues", CFF_TYPE_DELTA}, {
581 "FamilyOtherBlues", CFF_TYPE_DELTA}, {
582 "StdHW", CFF_TYPE_NUMBER}, {
583 "StdVW", CFF_TYPE_NUMBER}, {
584 NULL, -1}, /* first byte of two-byte operator */
585 /* Top */
587 "UniqueID", CFF_TYPE_NUMBER}, {
588 "XUID", CFF_TYPE_ARRAY}, {
589 "charset", CFF_TYPE_OFFSET}, {
590 "Encoding", CFF_TYPE_OFFSET}, {
591 "CharStrings", CFF_TYPE_OFFSET}, {
592 "Private", CFF_TYPE_SZOFF}, /* two numbers (size and offset) */
593 /* Private */
595 "Subrs", CFF_TYPE_OFFSET}, {
596 "defaultWidthX", CFF_TYPE_NUMBER}, {
597 "nominalWidthX", CFF_TYPE_NUMBER},
598 /* Operator 2 */
600 "Copyright", CFF_TYPE_SID}, {
601 "IsFixedPitch", CFF_TYPE_BOOLEAN}, {
602 "ItalicAngle", CFF_TYPE_NUMBER}, {
603 "UnderlinePosition", CFF_TYPE_NUMBER}, {
604 "UnderlineThickness", CFF_TYPE_NUMBER}, {
605 "PaintType", CFF_TYPE_NUMBER}, {
606 "CharstringType", CFF_TYPE_NUMBER}, {
607 "FontMatrix", CFF_TYPE_ARRAY}, {
608 "StrokeWidth", CFF_TYPE_NUMBER}, {
609 "BlueScale", CFF_TYPE_NUMBER}, {
610 "BlueShift", CFF_TYPE_NUMBER}, {
611 "BlueFuzz", CFF_TYPE_NUMBER}, {
612 "StemSnapH", CFF_TYPE_DELTA}, {
613 "StemSnapV", CFF_TYPE_DELTA}, {
614 "ForceBold", CFF_TYPE_BOOLEAN}, {
615 NULL, -1}, {
616 NULL, -1}, {
617 "LanguageGroup", CFF_TYPE_NUMBER}, {
618 "ExpansionFactor", CFF_TYPE_NUMBER}, {
619 "InitialRandomSeed", CFF_TYPE_NUMBER}, {
620 "SyntheticBase", CFF_TYPE_NUMBER}, {
621 "PostScript", CFF_TYPE_SID}, {
622 "BaseFontName", CFF_TYPE_SID}, {
623 "BaseFontBlend", CFF_TYPE_DELTA}, /* MMaster ? */
625 NULL, -1}, {
626 NULL, -1}, {
627 NULL, -1}, {
628 NULL, -1}, {
629 NULL, -1}, {
630 NULL, -1},
631 /* CID-Keyed font */
633 "ROS", CFF_TYPE_ROS}, /* SID SID number */
635 "CIDFontVersion", CFF_TYPE_NUMBER}, {
636 "CIDFontRevision", CFF_TYPE_NUMBER}, {
637 "CIDFontType", CFF_TYPE_NUMBER}, {
638 "CIDCount", CFF_TYPE_NUMBER}, {
639 "UIDBase", CFF_TYPE_NUMBER}, {
640 "FDArray", CFF_TYPE_OFFSET}, {
641 "FDSelect", CFF_TYPE_OFFSET}, {
642 "FontName", CFF_TYPE_SID},};
644 @ Parse DICT data
646 static double get_integer(card8 ** data, card8 * endptr, int *status)
648 long result = 0;
649 card8 b0, b1, b2;
651 b0 = *(*data)++;
652 if (b0 == 28 && *data < endptr - 2) { /* shortint */
653 b1 = *(*data)++;
654 b2 = *(*data)++;
655 result = b1 * 256 + b2;
656 if (result > 0x7fffL)
657 result -= 0x10000L;
658 } else if (b0 == 29 && *data < endptr - 4) { /* longint */
659 int i;
660 result = *(*data)++;
661 if (result > 0x7f)
662 result -= 0x100;
663 for (i = 0; i < 3; i++) {
664 result = result * 256 + (**data);
665 *data += 1;
667 } else if (b0 >= 32 && b0 <= 246) { /* int (1) */
668 result = b0 - 139;
669 } else if (b0 >= 247 && b0 <= 250) { /* int (2) */
670 b1 = *(*data)++;
671 result = (b0 - 247) * 256 + b1 + 108;
672 } else if (b0 >= 251 && b0 <= 254) {
673 b1 = *(*data)++;
674 result = -(b0 - 251) * 256 - b1 - 108;
675 } else {
676 *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
679 return (double) result;
682 @ Simply uses strtod
684 static double get_real(card8 ** data, card8 * endptr, int *status)
686 double result = 0.0;
687 int nibble = 0, pos = 0;
688 int len = 0, fail = 0;
690 if (**data != 30 || *data >= endptr - 1) {
691 *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
692 return 0.0;
695 *data += 1; /* skip first byte (30) */
697 pos = 0;
698 while ((!fail) && len < WORK_BUFFER_SIZE - 2 && *data < endptr) {
699 /* get nibble */
700 if (pos % 2) {
701 nibble = **data & 0x0f;
702 *data += 1;
703 } else {
704 nibble = (**data >> 4) & 0x0f;
706 if (nibble >= 0x00 && nibble <= 0x09) {
707 work_buffer[len++] = (char) (nibble + '0');
708 } else if (nibble == 0x0a) { /* . */
709 work_buffer[len++] = '.';
710 } else if (nibble == 0x0b || nibble == 0x0c) { /* E, E- */
711 work_buffer[len++] = 'e';
712 if (nibble == 0x0c)
713 work_buffer[len++] = '-';
714 } else if (nibble == 0x0e) { /* `-' */
715 work_buffer[len++] = '-';
716 } else if (nibble == 0x0d) { /* skip */
717 /* do nothing */
718 } else if (nibble == 0x0f) { /* end */
719 work_buffer[len++] = '\0';
720 if (((pos % 2) == 0) && (**data != 0xff)) {
721 fail = 1;
723 break;
724 } else { /* invalid */
725 fail = 1;
727 pos++;
730 /* returned values */
731 if (fail || nibble != 0x0f) {
732 *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
733 } else {
734 char *s;
735 /* strtod sets errno for OVERFLOW and _maybe_ UNDERFLOW */
736 /* but not for an invalid conversion (as for example if we try to convert "foo" in a double )*/
737 /* At least in glib sets errno also for UNDERFLOW */
738 /* We don't save/restore the prev. errno */
739 errno=0;
740 result = strtod(work_buffer, &s);
741 if ( (result==0.0 && work_buffer==s) || errno ) {
742 /* conversion is not possible */
743 *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
746 return result;
749 @ operators
751 static void add_dict(cff_dict * dict,
752 card8 ** data, card8 * endptr, int *status)
754 int id, argtype, t;
756 id = **data;
757 if (id == 0x0c) {
758 *data += 1;
759 if (*data >= endptr ||
760 (id = **data + CFF_LAST_DICT_OP1) >= CFF_LAST_DICT_OP) {
761 *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
762 return;
764 } else if (id >= CFF_LAST_DICT_OP1) {
765 *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
766 return;
769 argtype = dict_operator[id].argtype;
770 if (dict_operator[id].opname == NULL || argtype < 0) {
771 *status = CFF_CFF_ERROR_PARSE_CFF_ERROR;
772 return;
775 if (dict->count >= dict->max) {
776 dict->max += DICT_ENTRY_MAX;
777 /* not zeroed! */
778 dict->entries =
779 xrealloc(dict->entries,
780 (unsigned) ((unsigned) dict->max *
781 sizeof(cff_dict_entry)));
784 (dict->entries)[dict->count].id = id;
785 (dict->entries)[dict->count].key = dict_operator[id].opname;
786 if (argtype == CFF_TYPE_NUMBER ||
787 argtype == CFF_TYPE_BOOLEAN ||
788 argtype == CFF_TYPE_SID || argtype == CFF_TYPE_OFFSET) {
789 /* check for underflow here, as exactly one operand is expected */
790 if (stack_top < 1) {
791 *status = CFF_CFF_ERROR_STACK_UNDERFLOW;
792 return;
794 stack_top--;
795 (dict->entries)[dict->count].count = 1;
796 (dict->entries)[dict->count].values = xcalloc(1, sizeof(double));
797 (dict->entries)[dict->count].values[0] = arg_stack[stack_top];
798 dict->count += 1;
799 } else {
800 /* just ignore operator if there were no operands provided;
801 don't treat this as underflow (e.g. StemSnapV in TemporaLGCUni-Italic.otf) */
802 if ((t = stack_top) > 0) {
803 (dict->entries)[dict->count].count = stack_top;
804 (dict->entries)[dict->count].values =
805 xmalloc((unsigned) ((unsigned) stack_top * sizeof(double)));
806 while (stack_top > 0) {
807 stack_top--;
808 (dict->entries)[dict->count].values[stack_top] =
809 arg_stack[stack_top];
811 if (t > 3 && strcmp(dict_operator[id].opname, "FontMatrix") == 0) {
812 /* reset FontMatrix to [0.001 * * 0.001 * *],
813 fix mantis bug \# 0000200 (acroread "feature") */
814 (dict->entries)[dict->count].values[0] = 0.001;
815 (dict->entries)[dict->count].values[3] = 0.001;
817 dict->count += 1;
821 *data += 1;
823 return;
827 @ All operands are treated as number or array of numbers.
828 Private: two numbers, size and offset
829 ROS : three numbers, SID, SID, and a number
832 cff_dict *cff_dict_unpack(card8 * data, card8 * endptr)
834 cff_dict *dict;
835 int status = CFF_PARSE_OK;
837 stack_top = 0;
839 dict = cff_new_dict();
840 while (data < endptr && status == CFF_PARSE_OK) {
841 if (*data < 22) { /* operator */
842 add_dict(dict, &data, endptr, &status);
843 } else if (*data == 30) { /* real - First byte of a sequence (variable) */
844 if (stack_top < CFF_DICT_STACK_LIMIT) {
845 arg_stack[stack_top] = get_real(&data, endptr, &status);
846 stack_top++;
847 } else {
848 status = CFF_CFF_ERROR_STACK_OVERFLOW;
850 } else if (*data == 255 || (*data >= 22 && *data <= 27)) { /* reserved */
851 data++;
852 } else { /* everything else are integer */
853 if (stack_top < CFF_DICT_STACK_LIMIT) {
854 arg_stack[stack_top] = get_integer(&data, endptr, &status);
855 stack_top++;
856 } else {
857 status = CFF_CFF_ERROR_STACK_OVERFLOW;
862 if (status != CFF_PARSE_OK) {
863 formatted_error("cff","parsing DICT failed (error=%d)", status);
864 } else if (stack_top != 0) {
865 normal_warning("cff","garbage in DICT data");
866 stack_top = 0;
869 return dict;
872 @ @c
873 int cff_dict_known(cff_dict * dict, const char *key)
875 int i;
877 for (i = 0; i < dict->count; i++) {
878 if (key && strcmp(key, (dict->entries)[i].key) == 0
879 && (dict->entries)[i].count > 0)
880 return 1;
883 return 0;
886 @ @c
887 double cff_dict_get(cff_dict * dict, const char *key, int idx)
889 double value = 0.0;
890 int i;
892 assert(key && dict);
894 for (i = 0; i < dict->count; i++) {
895 if (strcmp(key, (dict->entries)[i].key) == 0) {
896 if ((dict->entries)[i].count > idx)
897 value = (dict->entries)[i].values[idx];
898 else
899 normal_error("cff","invalid index number");
900 break;
904 if (i == dict->count)
905 formatted_error("cff","DICT entry '%s' not found", key);
907 return value;
910 @ @c
911 card8 cff_fdselect_lookup(cff_font * cff, card16 gid)
913 card8 fd = 0xff;
914 cff_fdselect *fdsel;
916 if (cff->fdselect == NULL)
917 normal_error("cff","FDSelect not available");
919 fdsel = cff->fdselect;
921 if (gid >= cff->num_glyphs)
922 normal_error("cff","invalid glyph index");
924 switch (fdsel->format) {
925 case 0:
926 fd = fdsel->data.fds[gid];
927 break;
928 case 3:
930 if (gid == 0) {
931 fd = (fdsel->data).ranges[0].fd;
932 } else {
933 card16 i;
934 for (i = 1; i < (fdsel->num_entries); i++) {
935 if (gid < (fdsel->data).ranges[i].first)
936 break;
938 fd = (fdsel->data).ranges[i - 1].fd;
941 break;
942 default:
943 normal_error("cff","invalid FDSelect format");
944 break;
947 if (fd >= cff->num_fds)
948 normal_error("cff","invalid Font DICT index");
950 return fd;
953 @ @c
954 long cff_read_subrs(cff_font * cff)
956 long len = 0;
957 long offset;
958 int i;
961 if ((cff->flag & FONTTYPE_CIDFONT) && cff->fdselect == NULL) {
962 cff_read_fdselect(cff);
965 if ((cff->flag & FONTTYPE_CIDFONT) && cff->fdarray == NULL) {
966 cff_read_fdarray(cff);
969 if (cff->private == NULL)
970 cff_read_private(cff);
972 if (cff->gsubr == NULL) {
973 cff->offset = cff->gsubr_offset;
974 cff->gsubr = cff_get_index(cff);
977 cff->subrs = xcalloc(cff->num_fds, sizeof(cff_index *));
978 if (cff->flag & FONTTYPE_CIDFONT) {
979 for (i = 0; i < cff->num_fds; i++) {
980 if (cff->private[i] == NULL ||
981 !cff_dict_known(cff->private[i], "Subrs")) {
982 (cff->subrs)[i] = NULL;
983 } else {
984 offset = (long) cff_dict_get(cff->fdarray[i], "Private", 1);
985 offset += (long) cff_dict_get(cff->private[i], "Subrs", 0);
986 cff->offset = (l_offset) offset;
987 (cff->subrs)[i] = cff_get_index(cff);
988 len += cff_index_size((cff->subrs)[i]);
991 } else {
992 if (cff->private[0] == NULL ||
993 !cff_dict_known(cff->private[0], "Subrs")) {
994 (cff->subrs)[0] = NULL;
995 } else {
996 offset = (long) cff_dict_get(cff->topdict, "Private", 1);
997 offset += (long) cff_dict_get(cff->private[0], "Subrs", 0);
998 cff->offset = (l_offset) offset;
999 (cff->subrs)[0] = cff_get_index(cff);
1000 len += cff_index_size((cff->subrs)[0]);
1004 return len;
1008 @ @c
1009 long cff_read_fdarray(cff_font * cff)
1011 long len = 0;
1012 cff_index *idx;
1013 long offset, size;
1014 card16 i;
1016 if (cff->topdict == NULL)
1017 normal_error("cff","top DICT not found");
1019 if (!(cff->flag & FONTTYPE_CIDFONT))
1020 return 0;
1022 /* must exist */
1023 offset = (long) cff_dict_get(cff->topdict, "FDArray", 0);
1024 cff->offset = (l_offset) offset;
1025 idx = cff_get_index(cff);
1026 cff->num_fds = (card8) idx->count;
1027 cff->fdarray = xmalloc((unsigned) (idx->count * sizeof(cff_dict *)));
1028 for (i = 0; i < idx->count; i++) {
1029 card8 *data = idx->data + (idx->offset)[i] - 1;
1030 size = (long) ((idx->offset)[i + 1] - (idx->offset)[i]);
1031 if (size > 0) {
1032 (cff->fdarray)[i] = cff_dict_unpack(data, data + size);
1033 } else {
1034 (cff->fdarray)[i] = NULL;
1037 len = cff_index_size(idx);
1038 cff_release_index(idx);
1040 return len;
1044 @ @c
1045 long cff_read_private(cff_font * cff)
1047 long len = 0;
1048 card8 *data;
1049 long offset, size;
1051 if (cff->flag & FONTTYPE_CIDFONT) {
1052 int i;
1054 if (cff->fdarray == NULL)
1055 cff_read_fdarray(cff);
1057 cff->private = xmalloc((unsigned) (cff->num_fds * sizeof(cff_dict *)));
1058 for (i = 0; i < cff->num_fds; i++) {
1059 if (cff->fdarray[i] != NULL &&
1060 cff_dict_known(cff->fdarray[i], "Private") &&
1061 (size = (long) cff_dict_get(cff->fdarray[i], "Private", 0))
1062 > 0) {
1063 offset = (long) cff_dict_get(cff->fdarray[i], "Private", 1);
1064 cff->offset = (l_offset) offset;
1065 data = xmalloc((unsigned) size * sizeof(card8));
1066 memcpy(data, &cff->stream[cff->offset], (size_t) size);
1067 cff->offset = (l_offset) size;
1068 (cff->private)[i] = cff_dict_unpack(data, data + size);
1069 xfree(data);
1070 len += size;
1071 } else {
1072 (cff->private)[i] = NULL;
1075 } else {
1076 cff->num_fds = 1;
1077 cff->private = xmalloc(sizeof(cff_dict *));
1078 if (cff_dict_known(cff->topdict, "Private") &&
1079 (size = (long) cff_dict_get(cff->topdict, "Private", 0)) > 0) {
1080 offset = (long) cff_dict_get(cff->topdict, "Private", 1);
1081 cff->offset = (l_offset) offset;
1082 data = xmalloc((unsigned) size * sizeof(card8));
1083 memcpy(data, &cff->stream[cff->offset], (size_t) size);
1084 cff->offset = (l_offset) size;
1085 cff->private[0] = cff_dict_unpack(data, data + size);
1086 xfree(data);
1087 len += size;
1088 } else {
1089 (cff->private)[0] = NULL;
1090 len = 0;
1094 return len;
1098 @ @c
1099 cff_font *read_cff(unsigned char *buf, long buflength, int n)
1101 cff_font *cff;
1102 cff_index *idx;
1103 long offset;
1106 cff = xcalloc(1, sizeof(cff_font));
1108 cff->stream = buf;
1109 cff->stream_size = (l_offset) buflength;
1110 cff->index = n;
1112 cff->header_major = get_card8(cff);
1113 cff->header_minor = get_card8(cff);
1114 cff->header_hdr_size = get_card8(cff);
1115 cff->header_offsize = get_card8(cff);
1116 if (cff->header_offsize < 1 || cff->header_offsize > 4) {
1117 normal_warning("cff","invalid offsize data");
1118 cff_close(cff);
1119 return NULL;
1121 if (cff->header_major > 1) {
1122 formatted_warning("cff","major version %u not supported", cff->header_major);
1123 cff_close(cff);
1124 return NULL;
1126 cff->offset = cff->header_hdr_size;
1128 /* Name INDEX */
1129 idx = cff_get_index(cff);
1130 if (n > idx->count - 1) {
1131 normal_warning("cff","invalid fontset index number");
1132 cff_close(cff);
1133 return NULL;
1136 cff->name = idx;
1138 cff->fontname = cff_get_name(cff);
1140 /* Top DICT INDEX */
1141 idx = cff_get_index(cff);
1142 if (n > idx->count - 1) {
1143 normal_warning("cff","top DICT not exist");
1144 cff_close(cff);
1145 return NULL;
1147 cff->topdict = cff_dict_unpack(idx->data + idx->offset[n] - 1,
1148 idx->data + idx->offset[n + 1] - 1);
1149 if (!cff->topdict) {
1150 normal_warning("cff","parsing top DICT data failed");
1151 cff_close(cff);
1152 return NULL;
1154 cff_release_index(idx);
1156 if (cff_dict_known(cff->topdict, "CharstringType") &&
1157 cff_dict_get(cff->topdict, "CharstringType", 0) != 2) {
1158 normal_warning("cff","only type 2 charstrings supported");
1159 cff_close(cff);
1160 return NULL;
1163 if (cff_dict_known(cff->topdict, "SyntheticBase")) {
1164 normal_warning("cff","synthetic font not supported");
1165 cff_close(cff);
1166 return NULL;
1169 /* String INDEX */
1170 cff->string = cff_get_index(cff);
1172 /* offset to GSubr */
1173 cff->gsubr_offset = cff->offset;
1175 /* Number of glyphs */
1176 offset = (long) cff_dict_get(cff->topdict, "CharStrings", 0);
1177 cff->offset = (l_offset) offset;
1178 cff->num_glyphs = get_card16(cff);
1180 /* Check for font type */
1181 if (cff_dict_known(cff->topdict, "ROS")) {
1182 cff->flag |= FONTTYPE_CIDFONT;
1183 } else {
1184 cff->flag |= FONTTYPE_FONT;
1187 /* Check for encoding */
1188 if (cff_dict_known(cff->topdict, "Encoding")) {
1189 offset = (long) cff_dict_get(cff->topdict, "Encoding", 0);
1190 if (offset == 0) { /* predefined */
1191 cff->flag |= ENCODING_STANDARD;
1192 } else if (offset == 1) {
1193 cff->flag |= ENCODING_EXPERT;
1195 } else {
1196 cff->flag |= ENCODING_STANDARD;
1199 cff->offset = cff->gsubr_offset; /* seek back to GSubr */
1201 return cff;
1204 @* write a cff for opentype.
1206 @ Pack DICT data
1208 static long pack_integer(card8 * dest, long destlen, long value)
1210 long len = 0;
1212 if (value >= -107 && value <= 107) {
1213 if (destlen < 1)
1214 normal_error("cff","buffer overflow");
1215 dest[0] = (card8) ((value + 139) & 0xff);
1216 len = 1;
1217 } else if (value >= 108 && value <= 1131) {
1218 if (destlen < 2)
1219 normal_error("cff","buffer overflow");
1220 value = (long) 0xf700u + value - 108;
1221 dest[0] = (card8) ((value >> 8) & 0xff);
1222 dest[1] = (card8) (value & 0xff);
1223 len = 2;
1224 } else if (value >= -1131 && value <= -108) {
1225 if (destlen < 2)
1226 normal_error("cff","buffer overflow");
1227 value = (long) 0xfb00u - value - 108;
1228 dest[0] = (card8) ((value >> 8) & 0xff);
1229 dest[1] = (card8) (value & 0xff);
1230 len = 2;
1231 } else if (value >= -32768 && value <= 32767) { /* shortint */
1232 if (destlen < 3)
1233 normal_error("cff","buffer overflow");
1234 dest[0] = 28;
1235 dest[1] = (card8) ((value >> 8) & 0xff);
1236 dest[2] = (card8) (value & 0xff);
1237 len = 3;
1238 } else { /* longint */
1239 if (destlen < 5)
1240 normal_error("cff","buffer overflow");
1241 dest[0] = 29;
1242 dest[1] = (card8) ((value >> 24) & 0xff);
1243 dest[2] = (card8) ((value >> 16) & 0xff);
1244 dest[3] = (card8) ((value >> 8) & 0xff);
1245 dest[4] = (card8) (value & 0xff);
1246 len = 5;
1248 return len;
1251 @ @c
1252 static long pack_real(card8 * dest, long destlen, double value)
1254 long e;
1255 int i = 0, pos = 2;
1256 int res;
1257 #define CFF_REAL_MAX_LEN 17
1259 if (destlen < 2)
1260 normal_error("cff","buffer overflow");
1262 dest[0] = 30;
1264 if (value == 0.0) {
1265 dest[1] = 0x0f;
1266 return 2;
1269 if (value < 0.0) {
1270 dest[1] = 0xe0;
1271 value *= -1.0;
1272 pos++;
1275 e = 0;
1276 if (value >= 10.0) {
1277 while (value >= 10.0) {
1278 value /= 10.0;
1279 e++;
1281 } else if (value < 1.0) {
1282 while (value < 1.0) {
1283 value *= 10.0;
1284 e--;
1288 res=sprintf(work_buffer, "%1.14g", value);
1289 if (res<0) normal_error("cff","invalid conversion");
1290 if (res>CFF_REAL_MAX_LEN) res=CFF_REAL_MAX_LEN;
1292 for (i = 0; i < res; i++) {
1293 unsigned char ch = 0;
1295 if (work_buffer[i] == '\0') {
1296 /* res should prevent this. */
1297 /* normal_error("cff","cannot happen"); */
1298 break;
1299 } else if (work_buffer[i] == '.') {
1300 ch = 0x0a;
1301 } else if (work_buffer[i] >= '0' && work_buffer[i] <= '9') {
1302 ch = (unsigned char) (work_buffer[i] - '0');
1303 } else {
1304 normal_error("cff","invalid character");
1307 if (destlen < pos / 2 + 1)
1308 normal_error("cff","buffer overflow");
1310 if (pos % 2) {
1311 dest[pos / 2] = (card8) (dest[pos / 2] + ch);
1312 } else {
1313 dest[pos / 2] = (card8) (ch << 4);
1315 pos++;
1318 if (e > 0) {
1319 if (pos % 2) {
1320 dest[pos / 2] = (card8) (dest[pos / 2] + 0x0b);
1321 } else {
1322 if (destlen < pos / 2 + 1)
1323 normal_error("cff","buffer overflow");
1324 dest[pos / 2] = (card8) (0xb0);
1326 pos++;
1327 } else if (e < 0) {
1328 if (pos % 2) {
1329 dest[pos / 2] = (card8) (dest[pos / 2] + 0x0c);
1330 } else {
1331 if (destlen < pos / 2 + 1)
1332 normal_error("cff","buffer overflow");
1333 dest[pos / 2] = (card8) (0xc0);
1335 e *= -1;
1336 pos++;
1339 if (e != 0) {
1340 sprintf(work_buffer, "%ld", e);
1341 for (i = 0; i < CFF_REAL_MAX_LEN; i++) {
1342 unsigned char ch = 0;
1343 if (work_buffer[i] == '\0') {
1344 break;
1345 } else if (work_buffer[i] == '.') {
1346 ch = 0x0a;
1347 } else if (work_buffer[i] >= '0' && work_buffer[i] <= '9') {
1348 ch = (unsigned char) (work_buffer[i] - '0');
1349 } else {
1350 normal_error("cff","invalid character");
1353 if (destlen < pos / 2 + 1)
1354 normal_error("cff","buffer overflow");
1356 if (pos % 2) {
1357 dest[pos / 2] = (card8) (dest[pos / 2] + ch);
1358 } else {
1359 dest[pos / 2] = (card8) (ch << 4);
1361 pos++;
1365 if (pos % 2) {
1366 dest[pos / 2] = (card8) (dest[pos / 2] + 0x0f);
1367 pos++;
1368 } else {
1369 if (destlen < pos / 2 + 1)
1370 normal_error("cff","buffer overflow");
1371 dest[pos / 2] = (card8) (0xff);
1372 pos += 2;
1375 return pos / 2;
1378 @ @c
1379 static long cff_dict_put_number(double value,
1380 card8 * dest, long destlen, int type)
1382 long len = 0;
1383 double nearint;
1385 nearint = floor(value + 0.5);
1386 /* set offset to longint */
1387 if (type == CFF_TYPE_OFFSET) {
1388 long lvalue;
1390 lvalue = (long) value;
1391 if (destlen < 5)
1392 normal_error("cff","buffer overflow");
1393 dest[0] = 29;
1394 dest[1] = (card8) ((lvalue >> 24) & 0xff);
1395 dest[2] = (card8) ((lvalue >> 16) & 0xff);
1396 dest[3] = (card8) ((lvalue >> 8) & 0xff);
1397 dest[4] = (card8) (lvalue & 0xff);
1398 len = 5;
1399 } else if (value > CFF_INT_MAX || value < CFF_INT_MIN || (fabs(value - nearint) > 1.0e-5)) { /* real */
1400 len = pack_real(dest, destlen, value);
1401 } else { /* integer */
1402 len = pack_integer(dest, destlen, (long) nearint);
1405 return len;
1408 @ @c
1409 static long put_dict_entry(cff_dict_entry * de, card8 * dest, long destlen)
1411 long len = 0;
1412 int i, type, id;
1414 if (de->count > 0) {
1415 id = de->id;
1416 if (dict_operator[id].argtype == CFF_TYPE_OFFSET ||
1417 dict_operator[id].argtype == CFF_TYPE_SZOFF) {
1418 type = CFF_TYPE_OFFSET;
1419 } else {
1420 type = CFF_TYPE_NUMBER;
1422 for (i = 0; i < de->count; i++) {
1423 len += cff_dict_put_number(de->values[i],
1424 dest + len, destlen - len, type);
1426 if (id >= 0 && id < CFF_LAST_DICT_OP1) {
1427 if (len + 1 > destlen)
1428 normal_error("cff","buffer overflow");
1429 dest[len++] = (card8) id;
1430 } else if (id >= 0 && id < CFF_LAST_DICT_OP) {
1431 if (len + 2 > destlen)
1432 normal_error("cff","buffer overflow");
1433 dest[len++] = 12;
1434 dest[len++] = (card8) (id - CFF_LAST_DICT_OP1);
1435 } else {
1436 normal_error("cff","invalid DICT operator ID");
1440 return len;
1443 @ @c
1444 long cff_dict_pack(cff_dict * dict, card8 * dest, long destlen)
1446 long len = 0;
1447 int i;
1449 for (i = 0; i < dict->count; i++) {
1450 if (!strcmp(dict->entries[i].key, "ROS")) {
1451 len += put_dict_entry(&dict->entries[i], dest, destlen);
1452 break;
1455 for (i = 0; i < dict->count; i++) {
1456 if (strcmp(dict->entries[i].key, "ROS")) {
1457 len += put_dict_entry(&dict->entries[i], dest + len, destlen - len);
1461 return len;
1465 @ @c
1466 void cff_dict_add(cff_dict * dict, const char *key, int count)
1468 int id, i;
1470 for (id = 0; id < CFF_LAST_DICT_OP; id++) {
1471 if (key && dict_operator[id].opname &&
1472 strcmp(dict_operator[id].opname, key) == 0)
1473 break;
1476 if (id == CFF_LAST_DICT_OP)
1477 normal_error("cff","unknown DICT operator");
1479 for (i = 0; i < dict->count; i++) {
1480 if ((dict->entries)[i].id == id) {
1481 if ((dict->entries)[i].count != count)
1482 normal_error("cff","inconsistent DICT argument number");
1483 return;
1487 if (dict->count + 1 >= dict->max) {
1488 dict->max += 8;
1489 dict->entries =
1490 xrealloc(dict->entries,
1491 (unsigned) ((unsigned) dict->max *
1492 sizeof(cff_dict_entry)));
1495 (dict->entries)[dict->count].id = id;
1496 (dict->entries)[dict->count].key = dict_operator[id].opname;
1497 (dict->entries)[dict->count].count = count;
1498 if (count > 0) {
1499 (dict->entries)[dict->count].values =
1500 xcalloc((unsigned) count, sizeof(double));
1501 } else {
1502 (dict->entries)[dict->count].values = NULL;
1504 dict->count += 1;
1506 return;
1510 @ @c
1511 void cff_dict_remove(cff_dict * dict, const char *key)
1513 int i;
1514 for (i = 0; i < dict->count; i++) {
1515 if (key && strcmp(key, (dict->entries)[i].key) == 0) {
1516 (dict->entries)[i].count = 0;
1517 xfree((dict->entries)[i].values);
1522 @ @c
1523 void cff_dict_set(cff_dict * dict, const char *key, int idx, double value)
1525 int i;
1527 assert(dict && key);
1529 for (i = 0; i < dict->count; i++) {
1530 if (strcmp(key, (dict->entries)[i].key) == 0) {
1531 if ((dict->entries)[i].count > idx)
1532 (dict->entries)[i].values[idx] = value;
1533 else
1534 normal_error("cff","invalid index number");
1535 break;
1539 if (i == dict->count)
1540 formatted_error("cff","DICT entry '%s' not found", key);
1544 @ Strings
1546 char *cff_get_string(cff_font * cff, s_SID id)
1548 char *result = NULL;
1549 size_t len;
1551 if (id < CFF_STDSTR_MAX) {
1552 len = strlen(cff_stdstr[id]);
1553 result = xmalloc((unsigned) (len + 1) * sizeof(char));
1554 memcpy(result, cff_stdstr[id], len);
1555 result[len] = '\0';
1556 } else if (cff && cff->string) {
1557 cff_index *strings = cff->string;
1558 id = (s_SID) (id - CFF_STDSTR_MAX);
1559 if (id < strings->count) {
1560 len = (strings->offset)[id + 1] - (strings->offset)[id];
1561 result = xmalloc((unsigned) (len + 1) * sizeof(char));
1562 memmove(result, strings->data + (strings->offset)[id] - 1, len);
1563 result[len] = '\0';
1567 return result;
1570 @ @c
1571 long cff_get_sid(cff_font * cff, const char *str)
1573 card16 i;
1575 if (!cff || !str)
1576 return -1;
1578 /* I search String INDEX first. */
1579 if (cff && cff->string) {
1580 cff_index *idx = cff->string;
1581 for (i = 0; i < idx->count; i++) {
1582 if (strlen(str) == (idx->offset)[i + 1] - (idx->offset)[i] &&
1583 !memcmp(str, (idx->data) + (idx->offset)[i] - 1, strlen(str)))
1584 return (i + CFF_STDSTR_MAX);
1588 for (i = 0; i < CFF_STDSTR_MAX; i++) {
1589 if (!strcmp(str, cff_stdstr[i]))
1590 return i;
1593 return -1;
1597 @ @c
1598 void cff_update_string(cff_font * cff)
1600 if (cff == NULL)
1601 normal_error("cff","CFF font not opened");
1603 if (cff->string)
1604 cff_release_index(cff->string);
1605 cff->string = cff->_string;
1606 cff->_string = NULL;
1610 @ @c
1611 s_SID cff_add_string(cff_font * cff, const char *str)
1613 card16 idx;
1614 cff_index *strings;
1615 l_offset offset, size;
1617 if (cff == NULL)
1618 normal_error("cff","CFF font not opened");
1620 if (cff->_string == NULL)
1621 cff->_string = cff_new_index(0);
1622 strings = cff->_string;
1624 for (idx = 0; idx < strings->count; idx++) {
1625 size = strings->offset[idx + 1] - strings->offset[idx];
1626 offset = strings->offset[idx];
1627 if (size == strlen(str) &&
1628 !memcmp(strings->data + offset - 1, str, strlen(str)))
1629 return (s_SID) (idx + CFF_STDSTR_MAX);
1632 for (idx = 0; idx < CFF_STDSTR_MAX; idx++) {
1633 if (cff_stdstr[idx] && !strcmp(cff_stdstr[idx], str))
1634 return idx;
1636 offset = (strings->count > 0) ? strings->offset[strings->count] : 1;
1637 strings->offset =
1638 xrealloc(strings->offset,
1639 (unsigned) (((unsigned) strings->count +
1640 2) * sizeof(l_offset)));
1641 if (strings->count == 0)
1642 strings->offset[0] = 1;
1643 idx = strings->count;
1644 strings->count = (card16) (strings->count + 1);
1645 strings->offset[strings->count] = offset + strlen(str);
1646 strings->data =
1647 xrealloc(strings->data,
1648 (unsigned) ((offset + strlen(str) - 1) * sizeof(card8)));
1649 memcpy(strings->data + offset - 1, str, strlen(str));
1651 return (s_SID) (idx + CFF_STDSTR_MAX);
1655 @ @c
1656 void cff_dict_update(cff_dict * dict, cff_font * cff)
1658 int i;
1660 for (i = 0; i < dict->count; i++) {
1661 if ((dict->entries)[i].count > 0) {
1662 char *str;
1663 int id;
1665 id = (dict->entries)[i].id;
1667 if (dict_operator[id].argtype == CFF_TYPE_SID) {
1668 str = cff_get_string(cff, (s_SID) (dict->entries)[i].values[0]);
1669 (dict->entries)[i].values[0] = cff_add_string(cff, str);
1670 xfree(str);
1671 } else if (dict_operator[id].argtype == CFF_TYPE_ROS) {
1672 str = cff_get_string(cff, (s_SID) (dict->entries)[i].values[0]);
1673 (dict->entries)[i].values[0] = cff_add_string(cff, str);
1674 xfree(str);
1675 str = cff_get_string(cff, (s_SID) (dict->entries)[i].values[1]);
1676 (dict->entries)[i].values[1] = cff_add_string(cff, str);
1677 xfree(str);
1684 @ charsets
1686 long cff_read_charsets(cff_font * cff)
1688 cff_charsets *charset;
1689 long offset, length;
1690 card16 count, i;
1692 if (cff->topdict == NULL)
1693 normal_error("cff","top DICT not available");
1695 if (!cff_dict_known(cff->topdict, "charset")) {
1696 cff->flag |= CHARSETS_ISOADOBE;
1697 cff->charsets = NULL;
1698 return 0;
1701 offset = (long) cff_dict_get(cff->topdict, "charset", 0);
1703 if (offset == 0) { /* predefined */
1704 cff->flag |= CHARSETS_ISOADOBE;
1705 cff->charsets = NULL;
1706 return 0;
1707 } else if (offset == 1) {
1708 cff->flag |= CHARSETS_EXPERT;
1709 cff->charsets = NULL;
1710 return 0;
1711 } else if (offset == 2) {
1712 cff->flag |= CHARSETS_EXPSUB;
1713 cff->charsets = NULL;
1714 return 0;
1717 cff->offset = (l_offset) offset;
1718 cff->charsets = charset = xcalloc(1, sizeof(cff_charsets));
1719 charset->format = get_card8(cff);
1720 charset->num_entries = 0;
1722 count = (card16) (cff->num_glyphs - 1);
1723 length = 1;
1725 /* Not sure. Not well documented. */
1726 switch (charset->format) {
1727 case 0:
1728 charset->num_entries = (card16) (cff->num_glyphs - 1); /* no .notdef */
1729 charset->data.glyphs =
1730 xmalloc((unsigned) (charset->num_entries * sizeof(s_SID)));
1731 length += (charset->num_entries) * 2;
1732 for (i = 0; i < (charset->num_entries); i++) {
1733 charset->data.glyphs[i] = get_card16(cff);
1735 count = 0;
1736 break;
1737 case 1:
1739 cff_range1 *ranges = NULL;
1740 while (count > 0 && charset->num_entries < cff->num_glyphs) {
1741 ranges =
1742 xrealloc(ranges,
1743 (unsigned) (((unsigned) charset->num_entries +
1744 1) * sizeof(cff_range1)));
1745 ranges[charset->num_entries].first = get_card16(cff);
1746 ranges[charset->num_entries].n_left = get_card8(cff);
1747 count = (card16) (count - ranges[charset->num_entries].n_left + 1); /* no-overrap */
1748 charset->num_entries++;
1749 charset->data.range1 = ranges;
1751 length += (charset->num_entries) * 3;
1753 break;
1754 case 2:
1756 cff_range2 *ranges = NULL;
1757 while (count > 0 && charset->num_entries < cff->num_glyphs) {
1758 ranges =
1759 xrealloc(ranges,
1760 (unsigned) (((unsigned) charset->num_entries +
1761 1) * sizeof(cff_range2)));
1762 ranges[charset->num_entries].first = get_card16(cff);
1763 ranges[charset->num_entries].n_left = get_card16(cff);
1764 count = (card16) (count - (ranges[charset->num_entries].n_left + 1)); /* non-overrapping */
1765 charset->num_entries++;
1767 charset->data.range2 = ranges;
1768 length += (charset->num_entries) * 4;
1770 break;
1771 default:
1772 xfree(charset);
1773 normal_error("cff","unknown charset format");
1774 break;
1777 if (count > 0) {
1778 /* fprintf(stdout, "count=%d\n", count); */
1779 normal_warning("cff","charset data possibly broken (too many glyphs)");
1782 return length;
1785 @ @c
1786 long cff_pack_charsets(cff_font * cff, card8 * dest, long destlen)
1788 long len = 0;
1789 card16 i;
1790 cff_charsets *charset;
1792 if (cff->flag & HAVE_STANDARD_CHARSETS || cff->charsets == NULL)
1793 return 0;
1795 if (destlen < 1)
1796 normal_error("cff","buffer overflow");
1798 charset = cff->charsets;
1800 dest[len++] = charset->format;
1801 switch (charset->format) {
1802 case 0:
1803 if (destlen < len + (charset->num_entries) * 2)
1804 normal_error("cff","buffer overflow");
1805 for (i = 0; i < (charset->num_entries); i++) {
1806 s_SID sid = (charset->data).glyphs[i]; /* or CID */
1807 dest[len++] = (card8) ((sid >> 8) & 0xff);
1808 dest[len++] = (card8) (sid & 0xff);
1810 break;
1811 case 1:
1813 if (destlen < len + (charset->num_entries) * 3)
1814 normal_error("cff","buffer overflow");
1815 for (i = 0; i < (charset->num_entries); i++) {
1816 dest[len++] =
1817 (card8) (((charset->data).range1[i].first >> 8) & 0xff);
1818 dest[len++] = (card8) ((charset->data).range1[i].first & 0xff);
1819 dest[len++] = (card8) ((charset->data).range1[i].n_left);
1822 break;
1823 case 2:
1825 if (destlen < len + (charset->num_entries) * 4)
1826 normal_error("cff","buffer overflow");
1827 for (i = 0; i < (charset->num_entries); i++) {
1828 dest[len++] =
1829 (card8) (((charset->data).range2[i].first >> 8) & 0xff);
1830 dest[len++] = (card8) ((charset->data).range2[i].first & 0xff);
1831 dest[len++] =
1832 (card8) (((charset->data).range2[i].n_left >> 8) & 0xff);
1833 dest[len++] = (card8) ((charset->data).range2[i].n_left & 0xff);
1836 break;
1837 default:
1838 normal_error("cff","unknown charset format");
1839 break;
1842 return len;
1847 @* Type 2 Charstring support.
1849 Decode and encode Type 2 charstring
1851 All local/global subroutine calls in a given charstring is replace by the
1852 content of subroutine charstrings. We do this because some PostScript RIP
1853 may have problems with sparse subroutine array. Workaround for this is to
1854 re-order subroutine array so that no gap appears in the subroutine array,
1855 or put dummy charstrings that contains only `return' in the gap. However,
1856 re-ordering of subroutine is rather difficult for Type 2 charstrings due
1857 to the bias which depends on the total number of subroutines. Replacing
1858 callgsubr/callsubr calls with the content of the corresponding subroutine
1859 charstring may be more efficient than putting dummy subroutines in the
1860 case of subsetted font. Adobe distiller seems doing same thing.
1862 And also note that subroutine numbers within subroutines can depend on the
1863 content of operand stack as follows:
1865 \.{ ... l m callsubr << subr \#(m+bias): n add callsubr >> ...}
1867 I've not implemented the `random' operator which generates a pseudo-random
1868 number in the range (0, 1] and push them into argument stack.
1869 How pseudo-random sequences are generated is not documented in the Type 2
1870 charstring spec..
1874 #define CS_TYPE2_DEBUG_STR "Type2 Charstring Parser"
1875 #define CS_TYPE2_DEBUG 5
1877 /* decoder/encoder status codes */
1878 #define CS_BUFFER_CFF_ERROR -3
1879 #define CS_STACK_CFF_ERROR -2
1880 #define CS_PARSE_CFF_ERROR -1
1881 #define CS_PARSE_OK 0
1882 #define CS_PARSE_END 1
1883 #define CS_SUBR_RETURN 2
1884 #define CS_CHAR_END 3
1886 static int status = CS_PARSE_CFF_ERROR;
1888 #define DST_NEED(a,b) {if ((a) < (b)) { status = CS_BUFFER_CFF_ERROR ; return ; }}
1889 #define SRC_NEED(a,b) {if ((a) < (b)) { status = CS_PARSE_CFF_ERROR ; return ; }}
1890 #define NEED(a,b) {if ((a) < (b)) { status = CS_STACK_CFF_ERROR ; return ; }}
1892 /* hintmask and cntrmask need number of stem zones */
1893 static int num_stems = 0;
1894 static int phase = 0;
1896 /* subroutine nesting */
1897 static int cs2_nest = 0;
1899 /* advance width */
1900 static int have_width = 0;
1901 static double width = 0.0;
1904 Standard Encoding Accented Characters:
1905 Optional four arguments for endchar. See, CFF spec., p.35.
1906 This is obsolete feature and is no longer supported.
1908 #if 0
1909 /* adx ady bchar achar endchar */
1910 static double seac[4] = { 0.0, 0.0, 0.0, 0.0 };
1911 #endif
1913 @ Operand stack and Transient array
1915 static int cs2_stack_top = 0;
1916 static double cs2_arg_stack[CS_ARG_STACK_MAX];
1917 static double trn_array[CS_TRANS_ARRAY_MAX];
1919 @ Type 2 CharString encoding
1923 1-byte CharString operaotrs:
1924 |cs_escape| is first byte of two-byte operator
1927 /* RESERVED 0 */
1928 #define cs_hstem 1
1929 /* RESERVED 2 */
1930 #define cs_vstem 3
1931 #define cs_vmoveto 4
1932 #define cs_rlineto 5
1933 #define cs_hlineto 6
1934 #define cs_vlineto 7
1935 #define cs_rrcurveto 8
1936 /* |cs_closepath| 9 : TYPE1 */
1937 #define cs_callsubr 10
1938 #define cs_return 11
1939 #define cs_escape 12
1940 /* |cs_hsbw| 13 : TYPE1 */
1941 #define cs_endchar 14
1942 /* RESERVED 15 */
1943 /* RESERVED 16 */
1944 /* RESERVED 17 */
1945 #define cs_hstemhm 18
1946 #define cs_hintmask 19
1947 #define cs_cntrmask 20
1948 #define cs_rmoveto 21
1949 #define cs_hmoveto 22
1950 #define cs_vstemhm 23
1951 #define cs_rcurveline 24
1952 #define cs_rlinecurve 25
1953 #define cs_vvcurveto 26
1954 #define cs_hhcurveto 27
1955 /* SHORTINT 28 : first byte of shortint*/
1956 #define cs_callgsubr 29
1957 #define cs_vhcurveto 30
1958 #define cs_hvcurveto 31
1961 2-byte CharString operaotrs:
1962 "dotsection" is obsoleted in Type 2 charstring.
1965 #define cs_dotsection 0
1966 /* |cs_vstem3| 1 : TYPE1 */
1967 /* |cs_hstem3| 2 : TYPE1 */
1968 #define cs_and 3
1969 #define cs_or 4
1970 #define cs_not 5
1971 /* |cs_seac| 6 : TYPE1 */
1972 /* |cs_sbw| 7 : TYPE1 */
1973 /* RESERVED 8 */
1974 #define cs_abs 9
1975 #define cs_add 10
1976 #define cs_sub 11
1977 #define cs_div 12
1978 /* RESERVED 13 */
1979 #define cs_neg 14
1980 #define cs_eq 15
1981 /* |cs_callothersubr| 16 : TYPE1 */
1982 /* |cs_pop| 17 : TYPE1 */
1983 #define cs_drop 18
1984 /* RESERVED 19 */
1985 #define cs_put 20
1986 #define cs_get 21
1987 #define cs_ifelse 22
1988 #define cs_random 23
1989 #define cs_mul 24
1990 /* RESERVED 25 */
1991 #define cs_sqrt 26
1992 #define cs_dup 27
1993 #define cs_exch 28
1994 #define cs_index 29
1995 #define cs_roll 30
1996 /* |cs_setcurrentpoint| 31 : TYPE1 */
1997 /* RESERVED 32 */
1998 /* RESERVED 33 */
1999 #define cs_hflex 34
2000 #define cs_flex 35
2001 #define cs_hflex1 36
2002 #define cs_flex1 37
2005 |clear_stack()| put all operands sotred in operand stack to dest.
2007 static void clear_stack(card8 ** dest, card8 * limit)
2009 int i;
2011 for (i = 0; i < cs2_stack_top; i++) {
2012 double value;
2013 long ivalue;
2014 value = cs2_arg_stack[i];
2015 /* Nearest integer value */
2016 ivalue = (long) floor(value + 0.5);
2017 if (value >= 0x8000L || value <= (-0x8000L - 1)) {
2019 This number cannot be represented as a single operand.
2020 We must use `a b mul ...' or `a c div' to represent large values.
2022 normal_error("cff","argument value too large (this is bug)");
2023 } else if (fabs(value - (double) ivalue) > 3.0e-5) {
2024 /* 16.16-bit signed fixed value */
2025 DST_NEED(limit, *dest + 5);
2026 *(*dest)++ = 255;
2027 ivalue = (long) floor(value); /* mantissa */
2028 *(*dest)++ = (card8) ((ivalue >> 8) & 0xff);
2029 *(*dest)++ = (card8) (ivalue & 0xff);
2030 ivalue = (long) ((value - (double) ivalue) * 0x10000l); /* fraction */
2031 *(*dest)++ = (card8) ((ivalue >> 8) & 0xff);
2032 *(*dest)++ = (card8) (ivalue & 0xff);
2033 /* Everything else are integers. */
2034 } else if (ivalue >= -107 && ivalue <= 107) {
2035 DST_NEED(limit, *dest + 1);
2036 *(*dest)++ = (card8) (ivalue + 139);
2037 } else if (ivalue >= 108 && ivalue <= 1131) {
2038 DST_NEED(limit, *dest + 2);
2039 ivalue = (long) 0xf700u + ivalue - 108;
2040 *(*dest)++ = (card8) ((ivalue >> 8) & 0xff);
2041 *(*dest)++ = (card8) (ivalue & 0xff);
2042 } else if (ivalue >= -1131 && ivalue <= -108) {
2043 DST_NEED(limit, *dest + 2);
2044 ivalue = (long) 0xfb00u - ivalue - 108;
2045 *(*dest)++ = (card8) ((ivalue >> 8) & 0xff);
2046 *(*dest)++ = (card8) (ivalue & 0xff);
2047 } else if (ivalue >= -32768 && ivalue <= 32767) { /* shortint */
2048 DST_NEED(limit, *dest + 3);
2049 *(*dest)++ = 28;
2050 *(*dest)++ = (card8) ((ivalue >> 8) & 0xff);
2051 *(*dest)++ = (card8) ((ivalue) & 0xff);
2052 } else { /* Shouldn't come here */
2053 normal_error("cff","unexpected error");
2057 cs2_stack_top = 0; /* clear stack */
2059 return;
2063 Single byte operators:
2064 Path construction, Operator for finishing a path, Hint operators.
2066 phase:
2067 \item 0: inital state
2068 \item 1: hint declaration, first stack-clearing operator appeared
2069 \item 2: in path construction
2072 static void
2073 do_operator1(card8 ** dest, card8 * limit, card8 ** data, card8 * endptr)
2075 card8 op = **data;
2077 *data += 1;
2079 switch (op) {
2080 case cs_hstemhm:
2081 case cs_vstemhm:
2082 /* charstring may have hintmask if above operator have seen */
2083 case cs_hstem:
2084 case cs_vstem:
2085 if (phase == 0 && (cs2_stack_top % 2)) {
2086 have_width = 1;
2087 width = cs2_arg_stack[0];
2089 num_stems += cs2_stack_top / 2;
2090 clear_stack(dest, limit);
2091 DST_NEED(limit, *dest + 1);
2092 *(*dest)++ = op;
2093 phase = 1;
2094 break;
2095 case cs_hintmask:
2096 case cs_cntrmask:
2097 if (phase < 2) {
2098 if (phase == 0 && (cs2_stack_top % 2)) {
2099 have_width = 1;
2100 width = cs2_arg_stack[0];
2102 num_stems += cs2_stack_top / 2;
2104 clear_stack(dest, limit);
2105 DST_NEED(limit, *dest + 1);
2106 *(*dest)++ = op;
2107 if (num_stems > 0) {
2108 int masklen = (num_stems + 7) / 8;
2109 DST_NEED(limit, *dest + masklen);
2110 SRC_NEED(endptr, *data + masklen);
2111 memmove(*dest, *data, (size_t) masklen);
2112 *data += masklen;
2113 *dest += masklen;
2115 phase = 2;
2116 break;
2117 case cs_rmoveto:
2118 if (phase == 0 && (cs2_stack_top % 2)) {
2119 have_width = 1;
2120 width = cs2_arg_stack[0];
2122 clear_stack(dest, limit);
2123 DST_NEED(limit, *dest + 1);
2124 *(*dest)++ = op;
2125 phase = 2;
2126 break;
2127 case cs_hmoveto:
2128 case cs_vmoveto:
2129 if (phase == 0 && (cs2_stack_top % 2) == 0) {
2130 have_width = 1;
2131 width = cs2_arg_stack[0];
2133 clear_stack(dest, limit);
2134 DST_NEED(limit, *dest + 1);
2135 *(*dest)++ = op;
2136 phase = 2;
2137 break;
2138 case cs_endchar:
2139 if (cs2_stack_top == 1) {
2140 have_width = 1;
2141 width = cs2_arg_stack[0];
2142 clear_stack(dest, limit);
2143 } else if (cs2_stack_top == 4 || cs2_stack_top == 5) {
2144 normal_warning("cff","'seac' character deprecated in type 2 charstring");
2145 status = CS_PARSE_CFF_ERROR;
2146 return;
2147 } else if (cs2_stack_top > 0) {
2148 normal_warning("cff","operand stack not empty");
2150 DST_NEED(limit, *dest + 1);
2151 *(*dest)++ = op;
2152 status = CS_CHAR_END;
2153 break;
2154 /* above oprators are candidate for first stack-clearing operator */
2155 case cs_rlineto:
2156 case cs_hlineto:
2157 case cs_vlineto:
2158 case cs_rrcurveto:
2159 case cs_rcurveline:
2160 case cs_rlinecurve:
2161 case cs_vvcurveto:
2162 case cs_hhcurveto:
2163 case cs_vhcurveto:
2164 case cs_hvcurveto:
2165 if (phase < 2) {
2166 normal_warning("cff","broken type 2 charstring");
2167 status = CS_PARSE_CFF_ERROR;
2168 return;
2170 clear_stack(dest, limit);
2171 DST_NEED(limit, *dest + 1);
2172 *(*dest)++ = op;
2173 break;
2174 /* all operotors above are stack-clearing operator */
2175 /* no output */
2176 case cs_return:
2177 case cs_callgsubr:
2178 case cs_callsubr:
2179 normal_error("cff","unexpected call(g)subr/return");
2180 break;
2181 default:
2182 /* no-op ? */
2183 formatted_warning("cff","%s: unknown charstring operator: 0x%02x", CS_TYPE2_DEBUG_STR, op);
2184 status = CS_PARSE_CFF_ERROR;
2185 break;
2188 return;
2192 Double byte operators:
2193 Flex, arithmetic, conditional, and storage operators.
2195 Following operators are not supported:
2196 random: How random ?
2199 static void
2200 do_operator2(card8 ** dest, card8 * limit, card8 ** data, card8 * endptr)
2202 card8 op;
2204 *data += 1;
2206 SRC_NEED(endptr, *data + 1);
2208 op = **data;
2209 *data += 1;
2211 switch (op) {
2212 case cs_dotsection: /* deprecated */
2213 normal_warning("cff","Operator 'dotsection' deprecated in type 2 charstring");
2214 status = CS_PARSE_CFF_ERROR;
2215 return;
2216 break;
2217 case cs_hflex:
2218 case cs_flex:
2219 case cs_hflex1:
2220 case cs_flex1:
2221 if (phase < 2) {
2222 formatted_warning("cff","%s: broken type 2 charstring", CS_TYPE2_DEBUG_STR);
2223 status = CS_PARSE_CFF_ERROR;
2224 return;
2226 clear_stack(dest, limit);
2227 DST_NEED(limit, *dest + 2);
2228 *(*dest)++ = cs_escape;
2229 *(*dest)++ = op;
2230 break;
2231 /* all operator above are stack-clearing */
2232 /* no output */
2233 case cs_and:
2234 NEED(cs2_stack_top, 2);
2235 cs2_stack_top--;
2236 if (cs2_arg_stack[cs2_stack_top] && cs2_arg_stack[cs2_stack_top - 1]) {
2237 cs2_arg_stack[cs2_stack_top - 1] = 1.0;
2238 } else {
2239 cs2_arg_stack[cs2_stack_top - 1] = 0.0;
2241 break;
2242 case cs_or:
2243 NEED(cs2_stack_top, 2);
2244 cs2_stack_top--;
2245 if (cs2_arg_stack[cs2_stack_top] || cs2_arg_stack[cs2_stack_top - 1]) {
2246 cs2_arg_stack[cs2_stack_top - 1] = 1.0;
2247 } else {
2248 cs2_arg_stack[cs2_stack_top - 1] = 0.0;
2250 break;
2251 case cs_not:
2252 NEED(cs2_stack_top, 1);
2253 if (cs2_arg_stack[cs2_stack_top - 1]) {
2254 cs2_arg_stack[cs2_stack_top - 1] = 0.0;
2255 } else {
2256 cs2_arg_stack[cs2_stack_top - 1] = 1.0;
2258 break;
2259 case cs_abs:
2260 NEED(cs2_stack_top, 1);
2261 cs2_arg_stack[cs2_stack_top - 1] =
2262 fabs(cs2_arg_stack[cs2_stack_top - 1]);
2263 break;
2264 case cs_add:
2265 NEED(cs2_stack_top, 2);
2266 cs2_arg_stack[cs2_stack_top - 2] += cs2_arg_stack[cs2_stack_top - 1];
2267 cs2_stack_top--;
2268 break;
2269 case cs_sub:
2270 NEED(cs2_stack_top, 2);
2271 cs2_arg_stack[cs2_stack_top - 2] -= cs2_arg_stack[cs2_stack_top - 1];
2272 cs2_stack_top--;
2273 break;
2274 case cs_div: /* doesn't check overflow */
2275 NEED(cs2_stack_top, 2);
2276 cs2_arg_stack[cs2_stack_top - 2] /= cs2_arg_stack[cs2_stack_top - 1];
2277 cs2_stack_top--;
2278 break;
2279 case cs_neg:
2280 NEED(cs2_stack_top, 1);
2281 cs2_arg_stack[cs2_stack_top - 1] *= -1.0;
2282 break;
2283 case cs_eq:
2284 NEED(cs2_stack_top, 2);
2285 cs2_stack_top--;
2286 if (cs2_arg_stack[cs2_stack_top] == cs2_arg_stack[cs2_stack_top - 1]) {
2287 cs2_arg_stack[cs2_stack_top - 1] = 1.0;
2288 } else {
2289 cs2_arg_stack[cs2_stack_top - 1] = 0.0;
2291 break;
2292 case cs_drop:
2293 NEED(cs2_stack_top, 1);
2294 cs2_stack_top--;
2295 break;
2296 case cs_put:
2297 NEED(cs2_stack_top, 2);
2299 int idx = (int) cs2_arg_stack[--cs2_stack_top];
2300 NEED(CS_TRANS_ARRAY_MAX, idx);
2301 trn_array[idx] = cs2_arg_stack[--cs2_stack_top];
2303 break;
2304 case cs_get:
2305 NEED(cs2_stack_top, 1);
2307 int idx = (int) cs2_arg_stack[cs2_stack_top - 1];
2308 NEED(CS_TRANS_ARRAY_MAX, idx);
2309 cs2_arg_stack[cs2_stack_top - 1] = trn_array[idx];
2311 break;
2312 case cs_ifelse:
2313 NEED(cs2_stack_top, 4);
2314 cs2_stack_top -= 3;
2315 if (cs2_arg_stack[cs2_stack_top + 1] > cs2_arg_stack[cs2_stack_top + 2]) {
2316 cs2_arg_stack[cs2_stack_top - 1] = cs2_arg_stack[cs2_stack_top];
2318 break;
2319 case cs_mul:
2320 NEED(cs2_stack_top, 2);
2321 cs2_arg_stack[cs2_stack_top - 2] =
2322 cs2_arg_stack[cs2_stack_top - 2] * cs2_arg_stack[cs2_stack_top - 1];
2323 cs2_stack_top--;
2324 break;
2325 case cs_sqrt:
2326 NEED(cs2_stack_top, 1);
2327 cs2_arg_stack[cs2_stack_top - 1] =
2328 sqrt(cs2_arg_stack[cs2_stack_top - 1]);
2329 break;
2330 case cs_dup:
2331 NEED(cs2_stack_top, 1);
2332 NEED(CS_ARG_STACK_MAX, cs2_stack_top + 1);
2333 cs2_arg_stack[cs2_stack_top] = cs2_arg_stack[cs2_stack_top - 1];
2334 cs2_stack_top++;
2335 break;
2336 case cs_exch:
2337 NEED(cs2_stack_top, 2);
2339 double save = cs2_arg_stack[cs2_stack_top - 2];
2340 cs2_arg_stack[cs2_stack_top - 2] = cs2_arg_stack[cs2_stack_top - 1];
2341 cs2_arg_stack[cs2_stack_top - 1] = save;
2343 break;
2344 case cs_index:
2345 NEED(cs2_stack_top, 2); /* need two arguments at least */
2347 int idx = (int) cs2_arg_stack[cs2_stack_top - 1];
2348 if (idx < 0) {
2349 cs2_arg_stack[cs2_stack_top - 1] =
2350 cs2_arg_stack[cs2_stack_top - 2];
2351 } else {
2352 NEED(cs2_stack_top, idx + 2);
2353 cs2_arg_stack[cs2_stack_top - 1] =
2354 cs2_arg_stack[cs2_stack_top - idx - 2];
2357 break;
2358 case cs_roll:
2359 NEED(cs2_stack_top, 2);
2361 int N, J;
2362 J = (int) cs2_arg_stack[--cs2_stack_top];
2363 N = (int) cs2_arg_stack[--cs2_stack_top];
2364 NEED(cs2_stack_top, N);
2365 if (J > 0) {
2366 J = J % N;
2367 while (J-- > 0) {
2368 double save = cs2_arg_stack[cs2_stack_top - 1];
2369 int i = cs2_stack_top - 1;
2370 while (i > cs2_stack_top - N) {
2371 cs2_arg_stack[i] = cs2_arg_stack[i - 1];
2372 i--;
2374 cs2_arg_stack[i] = save;
2376 } else {
2377 J = (-J) % N;
2378 while (J-- > 0) {
2379 double save = cs2_arg_stack[cs2_stack_top - N];
2380 int i = cs2_stack_top - N;
2381 while (i < cs2_stack_top - 1) {
2382 cs2_arg_stack[i] = cs2_arg_stack[i + 1];
2383 i++;
2385 cs2_arg_stack[i] = save;
2389 break;
2390 case cs_random:
2391 formatted_warning("cff","%s: Charstring operator 'random' found.", CS_TYPE2_DEBUG_STR);
2392 NEED(CS_ARG_STACK_MAX, cs2_stack_top + 1);
2393 cs2_arg_stack[cs2_stack_top++] = 1.0;
2394 break;
2395 default:
2396 /* no-op ? */
2397 formatted_warning("cff","%s: unknown charstring operator: 0x0c%02x", CS_TYPE2_DEBUG_STR, op);
2398 status = CS_PARSE_CFF_ERROR;
2399 break;
2402 return;
2406 integer:
2407 exactly the same as the DICT encoding (except 29)
2409 static void cs2_get_integer(card8 ** data, card8 * endptr)
2411 long result = 0;
2412 card8 b0 = **data, b1, b2;
2414 *data += 1;
2416 if (b0 == 28) { /* shortint */
2417 SRC_NEED(endptr, *data + 2);
2418 b1 = **data;
2419 b2 = *(*data + 1);
2420 result = b1 * 256 + b2;
2421 if (result > 0x7fff)
2422 result -= 0x10000L;
2423 *data += 2;
2424 } else if (b0 >= 32 && b0 <= 246) { /* int (1) */
2425 result = b0 - 139;
2426 } else if (b0 >= 247 && b0 <= 250) { /* int (2) */
2427 SRC_NEED(endptr, *data + 1);
2428 b1 = **data;
2429 result = (b0 - 247) * 256 + b1 + 108;
2430 *data += 1;
2431 } else if (b0 >= 251 && b0 <= 254) {
2432 SRC_NEED(endptr, *data + 1);
2433 b1 = **data;
2434 result = -(b0 - 251) * 256 - b1 - 108;
2435 *data += 1;
2436 } else {
2437 status = CS_PARSE_CFF_ERROR;
2438 return;
2441 NEED(CS_ARG_STACK_MAX, cs2_stack_top + 1);
2442 cs2_arg_stack[cs2_stack_top++] = (double) result;
2444 return;
2448 Signed 16.16-bits fixed number for Type 2 charstring encoding
2450 static void get_fixed(card8 ** data, card8 * endptr)
2452 long ivalue;
2453 double rvalue;
2455 *data += 1;
2457 SRC_NEED(endptr, *data + 4);
2459 ivalue = *(*data) * 0x100 + *(*data + 1);
2460 rvalue = (double) ((ivalue > 0x7fffL) ? (ivalue - 0x10000L) : ivalue);
2461 ivalue = *(*data + 2) * 0x100 + *(*data + 3);
2462 rvalue += ((double) ivalue) / 0x10000L;
2464 NEED(CS_ARG_STACK_MAX, cs2_stack_top + 1);
2465 cs2_arg_stack[cs2_stack_top++] = rvalue;
2466 *data += 4;
2468 return;
2472 Subroutines:
2473 The bias for subroutine number is introduced in type 2 charstrings.
2475 subr: set to a pointer to the subroutine charstring.
2476 len: set to the length of subroutine charstring.
2477 |subr_idx|: CFF INDEX data that contains subroutines.
2478 id: biased subroutine number.
2481 static void get_subr(card8 ** subr, long *len, cff_index * subr_idx, long id)
2483 card16 count;
2485 if (subr_idx == NULL)
2486 formatted_error("cff","%s: subroutine called but no subroutine found",CS_TYPE2_DEBUG_STR);
2488 count = subr_idx->count;
2490 /* Adding bias number */
2491 if (count < 1240) {
2492 id += 107;
2493 } else if (count < 33900) {
2494 id += 1131;
2495 } else {
2496 id += 32768;
2499 if (id > count)
2500 formatted_error("cff","%s: invalid subroutine index: %ld (max=%u)", CS_TYPE2_DEBUG_STR, id, count);
2502 *len = (long) ((subr_idx->offset)[id + 1] - (subr_idx->offset)[id]);
2503 *subr = subr_idx->data + (subr_idx->offset)[id] - 1;
2505 return;
2509 @ NOTE:
2510 The Type 2 interpretation of a number encoded in five-bytes (those with
2511 an initial byte value of 255) differs from how it is interpreted in the
2512 Type 1 format.
2515 static void
2516 do_charstring(card8 ** dest, card8 * limit,
2517 card8 ** data, card8 * endptr,
2518 cff_index * gsubr_idx, cff_index * subr_idx)
2520 card8 b0 = 0, *subr;
2521 long len;
2523 if (cs2_nest > CS_SUBR_NEST_MAX)
2524 formatted_error("cff","%s: subroutine nested too deeply", CS_TYPE2_DEBUG_STR);
2526 cs2_nest++;
2528 while (*data < endptr && status == CS_PARSE_OK) {
2529 b0 = **data;
2530 if (b0 == 255) { /* 16-bit.16-bit fixed signed number */
2531 get_fixed(data, endptr);
2532 } else if (b0 == cs_return) {
2533 status = CS_SUBR_RETURN;
2534 } else if (b0 == cs_callgsubr) {
2535 if (cs2_stack_top < 1) {
2536 status = CS_STACK_CFF_ERROR;
2537 } else {
2538 cs2_stack_top--;
2539 get_subr(&subr, &len, gsubr_idx,
2540 (long) cs2_arg_stack[cs2_stack_top]);
2541 if (*dest + len > limit)
2542 formatted_error("cff","%s: possible buffer overflow", CS_TYPE2_DEBUG_STR);
2543 do_charstring(dest, limit, &subr, subr + len, gsubr_idx, subr_idx);
2544 *data += 1;
2546 } else if (b0 == cs_callsubr) {
2547 if (cs2_stack_top < 1) {
2548 status = CS_STACK_CFF_ERROR;
2549 } else {
2550 cs2_stack_top--;
2551 get_subr(&subr, &len, subr_idx,
2552 (long) cs2_arg_stack[cs2_stack_top]);
2553 if (limit < *dest + len)
2554 formatted_error("cff","%s: possible buffer overflow", CS_TYPE2_DEBUG_STR);
2555 do_charstring(dest, limit, &subr, subr + len, gsubr_idx, subr_idx);
2556 *data += 1;
2558 } else if (b0 == cs_escape) {
2559 do_operator2(dest, limit, data, endptr);
2560 } else if (b0 < 32 && b0 != 28) { /* 19, 20 need mask */
2561 do_operator1(dest, limit, data, endptr);
2562 } else if ((b0 <= 22 && b0 >= 27) || b0 == 31) { /* reserved */
2563 status = CS_PARSE_CFF_ERROR; /* not an error ? */
2564 } else { /* integer */
2565 cs2_get_integer(data, endptr);
2569 if (status == CS_SUBR_RETURN) {
2570 status = CS_PARSE_OK;
2571 } else if (status == CS_CHAR_END && *data < endptr) {
2572 formatted_warning("cff","%s: garbage after endchar", CS_TYPE2_DEBUG_STR);
2573 } else if (status < CS_PARSE_OK) { /* error */
2574 formatted_error("cff","%s: parsing charstring failed: (status=%d, stack=%d)", CS_TYPE2_DEBUG_STR, status, cs2_stack_top);
2577 cs2_nest--;
2579 return;
2582 @ @c
2583 static void cs_parse_init(void)
2585 status = CS_PARSE_OK;
2586 cs2_nest = 0;
2587 phase = 0;
2588 num_stems = 0;
2589 cs2_stack_top = 0;
2593 @ Not just copying...
2595 long
2596 cs_copy_charstring(card8 * dst, long dstlen,
2597 card8 * src, long srclen,
2598 cff_index * gsubr, cff_index * subr,
2599 double default_width, double nominal_width, cs_ginfo * ginfo)
2601 card8 *save = dst;
2603 cs_parse_init();
2605 width = 0.0;
2606 have_width = 0;
2608 /* expand call(g)subrs */
2609 do_charstring(&dst, dst + dstlen, &src, src + srclen, gsubr, subr);
2611 if (ginfo) {
2612 ginfo->flags = 0; /* not used */
2613 if (have_width) {
2614 ginfo->wx = nominal_width + width;
2615 } else {
2616 ginfo->wx = default_width;
2620 return (long) (dst - save);
2623 @* encodings.
2625 @ Encoding and Charset
2627 Encoding and Charset arrays always begin with GID = 1.
2630 long cff_read_encoding(cff_font * cff)
2632 cff_encoding *encoding;
2633 long offset, length;
2634 card8 i;
2636 if (cff->topdict == NULL) {
2637 normal_error("cff","top DICT data not found");
2640 if (!cff_dict_known(cff->topdict, "Encoding")) {
2641 cff->flag |= ENCODING_STANDARD;
2642 cff->encoding = NULL;
2643 return 0;
2646 offset = (long) cff_dict_get(cff->topdict, "Encoding", 0);
2647 if (offset == 0) { /* predefined */
2648 cff->flag |= ENCODING_STANDARD;
2649 cff->encoding = NULL;
2650 return 0;
2651 } else if (offset == 1) {
2652 cff->flag |= ENCODING_EXPERT;
2653 cff->encoding = NULL;
2654 return 0;
2657 cff->offset = (l_offset) offset;
2658 cff->encoding = encoding = xcalloc(1, sizeof(cff_encoding));
2659 encoding->format = get_card8(cff);
2660 length = 1;
2662 switch (encoding->format & (~0x80)) {
2663 case 0:
2664 encoding->num_entries = get_card8(cff);
2665 (encoding->data).codes = xmalloc(encoding->num_entries * sizeof(card8));
2666 for (i = 0; i < (encoding->num_entries); i++) {
2667 (encoding->data).codes[i] = get_card8(cff);
2669 length += encoding->num_entries + 1;
2670 break;
2671 case 1:
2673 cff_range1 *ranges;
2674 encoding->num_entries = get_card8(cff);
2675 encoding->data.range1 = ranges
2676 = xcalloc(encoding->num_entries, sizeof(cff_range1));
2677 for (i = 0; i < (encoding->num_entries); i++) {
2678 ranges[i].first = get_card8(cff);
2679 ranges[i].n_left = get_card8(cff);
2681 length += (encoding->num_entries) * 2 + 1;
2683 break;
2684 default:
2685 xfree(encoding);
2686 normal_error("cff","unknown encoding format");
2687 break;
2690 /* Supplementary data */
2691 if ((encoding->format) & 0x80) {
2692 cff_map *map;
2693 encoding->num_supps = get_card8(cff);
2694 encoding->supp = map = xcalloc(encoding->num_supps, sizeof(cff_map));
2695 for (i = 0; i < (encoding->num_supps); i++) {
2696 map[i].code = get_card8(cff);
2697 map[i].glyph = get_card16(cff); /* SID */
2699 length += (encoding->num_supps) * 3 + 1;
2700 } else {
2701 encoding->num_supps = 0;
2702 encoding->supp = NULL;
2705 return length;
2708 @ @c
2709 long cff_pack_encoding(cff_font * cff, card8 * dest, long destlen)
2711 long len = 0;
2712 cff_encoding *encoding;
2713 card16 i;
2715 if (cff->flag & HAVE_STANDARD_ENCODING || cff->encoding == NULL)
2716 return 0;
2718 if (destlen < 2)
2719 normal_error("cff","buffer overflow");
2721 encoding = cff->encoding;
2723 dest[len++] = encoding->format;
2724 dest[len++] = encoding->num_entries;
2725 switch (encoding->format & (~0x80)) {
2726 case 0:
2727 if (destlen < len + encoding->num_entries)
2728 normal_error("cff","buffer overflow");
2729 for (i = 0; i < (encoding->num_entries); i++) {
2730 dest[len++] = (encoding->data).codes[i];
2732 break;
2733 case 1:
2735 if (destlen < len + (encoding->num_entries) * 2)
2736 normal_error("cff","buffer overflow");
2737 for (i = 0; i < (encoding->num_entries); i++) {
2738 dest[len++] = (card8) ((encoding->data).range1[i].first & 0xff);
2739 dest[len++] = (card8) ((encoding->data).range1[i].n_left);
2742 break;
2743 default:
2744 normal_error("cff","unknown encoding format");
2745 break;
2748 if ((encoding->format) & 0x80) {
2749 if (destlen < len + (encoding->num_supps) * 3 + 1)
2750 normal_error("cff","buffer overflow");
2751 dest[len++] = encoding->num_supps;
2752 for (i = 0; i < (encoding->num_supps); i++) {
2753 dest[len++] = (card8) ((encoding->supp)[i].code);
2754 dest[len++] = (card8) (((encoding->supp)[i].glyph >> 8) & 0xff);
2755 dest[len++] = (card8) ((encoding->supp)[i].glyph & 0xff);
2759 return len;
2762 @ CID-Keyed font specific
2764 long cff_read_fdselect(cff_font * cff)
2766 cff_fdselect *fdsel;
2767 long offset, length;
2768 card16 i;
2770 if (cff->topdict == NULL)
2771 normal_error("cff","top DICT not available");
2773 if (!(cff->flag & FONTTYPE_CIDFONT))
2774 return 0;
2776 offset = (long) cff_dict_get(cff->topdict, "FDSelect", 0);
2777 cff->offset = (l_offset) offset;
2778 cff->fdselect = fdsel = xcalloc(1, sizeof(cff_fdselect));
2779 fdsel->format = get_card8(cff);
2781 length = 1;
2783 switch (fdsel->format) {
2784 case 0:
2785 fdsel->num_entries = cff->num_glyphs;
2786 (fdsel->data).fds = xmalloc(fdsel->num_entries * sizeof(card8));
2787 for (i = 0; i < (fdsel->num_entries); i++) {
2788 (fdsel->data).fds[i] = get_card8(cff);
2790 length += fdsel->num_entries;
2791 break;
2792 case 3:
2794 cff_range3 *ranges;
2795 fdsel->num_entries = get_card16(cff);
2796 fdsel->data.ranges = ranges =
2797 xcalloc(fdsel->num_entries, sizeof(cff_range3));
2798 for (i = 0; i < (fdsel->num_entries); i++) {
2799 ranges[i].first = get_card16(cff);
2800 ranges[i].fd = get_card8(cff);
2802 if (ranges[0].first != 0)
2803 normal_error("cff","range not starting with 0");
2804 if (cff->num_glyphs != get_card16(cff))
2805 normal_error("cff","sentinel value mismatched with number of glyphs");
2806 length += (fdsel->num_entries) * 3 + 4;
2808 break;
2809 default:
2810 xfree(fdsel);
2811 normal_error("cff","unknown FDSelect format");
2812 break;
2815 return length;
2819 @ @c
2820 long cff_pack_fdselect(cff_font * cff, card8 * dest, long destlen)
2822 cff_fdselect *fdsel;
2823 long len = 0;
2824 card16 i;
2826 if (cff->fdselect == NULL)
2827 return 0;
2829 if (destlen < 1)
2830 normal_error("cff","buffer overflow");
2832 fdsel = cff->fdselect;
2834 dest[len++] = fdsel->format;
2835 switch (fdsel->format) {
2836 case 0:
2837 if (fdsel->num_entries != cff->num_glyphs)
2838 normal_error("cff","invalid data");
2839 if (destlen < len + fdsel->num_entries)
2840 normal_error("cff","buffer overflow");
2841 for (i = 0; i < fdsel->num_entries; i++) {
2842 dest[len++] = (fdsel->data).fds[i];
2844 break;
2845 case 3:
2847 if (destlen < len + 2)
2848 normal_error("cff","buffer overflow");
2849 len += 2;
2850 for (i = 0; i < (fdsel->num_entries); i++) {
2851 if (destlen < len + 3)
2852 normal_error("cff","buffer overflow");
2853 dest[len++] =
2854 (card8) (((fdsel->data).ranges[i].first >> 8) & 0xff);
2855 dest[len++] = (card8) ((fdsel->data).ranges[i].first & 0xff);
2856 dest[len++] = (card8) ((fdsel->data).ranges[i].fd);
2858 if (destlen < len + 2)
2859 normal_error("cff","buffer overflow");
2860 dest[len++] = (card8) ((cff->num_glyphs >> 8) & 0xff);
2861 dest[len++] = (card8) (cff->num_glyphs & 0xff);
2862 dest[1] = (card8) (((len / 3 - 1) >> 8) & 0xff);
2863 dest[2] = (card8) ((len / 3 - 1) & 0xff);
2865 break;
2866 default:
2867 normal_error("cff","unknown FDSelect format");
2868 break;
2871 return len;
2876 @ Create an instance of embeddable font.
2879 static void write_fontfile(PDF pdf, cff_font * cffont, char *fullname)
2881 cff_index *topdict, *fdarray, *private;
2882 unsigned char *dest;
2883 long destlen = 0, i, size;
2884 long offset, topdict_offset, fdarray_offset;
2886 /* DICT sizes (offset set to long int) */
2887 topdict = cff_new_index(1);
2888 fdarray = cff_new_index(cffont->num_fds);
2889 private = cff_new_index(cffont->num_fds);
2891 cff_dict_remove(cffont->topdict, "UniqueID");
2892 cff_dict_remove(cffont->topdict, "XUID");
2893 cff_dict_remove(cffont->topdict, "Private"); /* some bad font may have */
2894 cff_dict_remove(cffont->topdict, "Encoding"); /* some bad font may have */
2896 topdict->offset[1] = (l_offset) cff_dict_pack(cffont->topdict,
2897 (card8 *) work_buffer,
2898 WORK_BUFFER_SIZE) + 1;
2899 for (i = 0; i < cffont->num_fds; i++) {
2900 size = 0;
2901 if (cffont->private && cffont->private[i]) {
2902 size = cff_dict_pack(cffont->private[i],
2903 (card8 *) work_buffer, WORK_BUFFER_SIZE);
2904 if (size < 1) { /* Private had contained only Subr */
2905 cff_dict_remove(cffont->fdarray[i], "Private");
2908 (private->offset)[i + 1] =
2909 (unsigned long) ((private->offset)[i] + (unsigned) size);
2910 (fdarray->offset)[i + 1] =
2911 (unsigned long) ((fdarray->offset)[i] + (unsigned)
2912 cff_dict_pack(cffont->fdarray[i],
2913 (card8 *) work_buffer,
2914 WORK_BUFFER_SIZE));
2917 destlen = 4; /* header size */
2918 destlen += cff_set_name(cffont, fullname);
2919 destlen += cff_index_size(topdict);
2920 destlen += cff_index_size(cffont->string);
2921 destlen += cff_index_size(cffont->gsubr);
2922 destlen += (cffont->charsets->num_entries) * 2 + 1; /* charset format 0 */
2923 destlen += (cffont->fdselect->num_entries) * 3 + 5; /* fdselect format 3 */
2924 destlen += cff_index_size(cffont->cstrings);
2925 destlen += cff_index_size(fdarray);
2926 destlen = (long) (destlen + (long) private->offset[private->count] - 1); /* Private is not INDEX */
2928 dest = xcalloc((unsigned) destlen, sizeof(card8));
2930 offset = 0;
2931 /* Header */
2932 offset += cff_put_header(cffont, dest + offset, destlen - offset);
2933 /* Name */
2934 offset += cff_pack_index(cffont->name, dest + offset, destlen - offset);
2935 /* Top DICT */
2936 topdict_offset = offset;
2937 offset += cff_index_size(topdict);
2938 /* Strings */
2939 offset += cff_pack_index(cffont->string, dest + offset, destlen - offset);
2940 /* Global Subrs */
2941 offset += cff_pack_index(cffont->gsubr, dest + offset, destlen - offset);
2943 /* charset */
2944 cff_dict_set(cffont->topdict, "charset", 0, (double) offset);
2945 offset += cff_pack_charsets(cffont, dest + offset, destlen - offset);
2947 /* FDSelect */
2948 cff_dict_set(cffont->topdict, "FDSelect", 0, (double) offset);
2949 offset += cff_pack_fdselect(cffont, dest + offset, destlen - offset);
2951 /* CharStrings */
2952 cff_dict_set(cffont->topdict, "CharStrings", 0, (double) offset);
2953 offset += cff_pack_index(cffont->cstrings,
2954 dest + offset, cff_index_size(cffont->cstrings));
2955 cff_release_index(cffont->cstrings);
2956 cffont->cstrings = NULL; /* Charstrings cosumes huge memory */
2958 /* FDArray and Private */
2959 cff_dict_set(cffont->topdict, "FDArray", 0, (double) offset);
2960 fdarray_offset = offset;
2961 offset += cff_index_size(fdarray);
2963 fdarray->data =
2964 xcalloc((unsigned) (fdarray->offset[fdarray->count] - 1),
2965 sizeof(card8));
2966 for (i = 0; i < cffont->num_fds; i++) {
2967 size = (long) (private->offset[i + 1] - private->offset[i]);
2968 if (cffont->private[i] && size > 0) {
2969 cff_dict_pack(cffont->private[i], dest + offset, size);
2970 cff_dict_set(cffont->fdarray[i], "Private", 0, (double) size);
2971 cff_dict_set(cffont->fdarray[i], "Private", 1, (double) offset);
2973 cff_dict_pack(cffont->fdarray[i],
2974 fdarray->data + (fdarray->offset)[i] - 1,
2975 (long) (fdarray->offset[fdarray->count] - 1));
2976 offset += size;
2979 cff_pack_index(fdarray, dest + fdarray_offset, cff_index_size(fdarray));
2980 cff_release_index(fdarray);
2981 cff_release_index(private);
2983 /* Finally Top DICT */
2984 topdict->data =
2985 xcalloc((unsigned) (topdict->offset[topdict->count] - 1),
2986 sizeof(card8));
2987 cff_dict_pack(cffont->topdict, topdict->data,
2988 (long) (topdict->offset[topdict->count] - 1));
2989 cff_pack_index(topdict, dest + topdict_offset, cff_index_size(topdict));
2990 cff_release_index(topdict);
2992 for (i = 0; i < offset; i++)
2993 strbuf_putchar(pdf->fb, dest[i]);
2995 xfree(dest);
2996 return;
3000 @ this block is used a few times
3002 #define DO_COPY_CHARSTRING() \
3003 if ((avl_find(fd->gl_tree,glyph) != NULL)) { \
3004 size = (long)(cs_idx->offset[code+1] - cs_idx->offset[code]); \
3005 if (size > CS_STR_LEN_MAX) { \
3006 formatted_error("cff","charstring too long: gid=%u, %ld bytes", code, size); \
3008 if (charstring_len + CS_STR_LEN_MAX >= max_len) { \
3009 max_len = (long)(charstring_len + 2 * CS_STR_LEN_MAX); \
3010 charstrings->data = xrealloc(charstrings->data, (unsigned)((unsigned)max_len*sizeof(card8))); \
3012 (charstrings->offset)[gid] = (unsigned)(charstring_len + 1); \
3013 cffont->offset= (l_offset)((unsigned)offset + (cs_idx->offset)[code] - 1); \
3014 memcpy(data,&cffont->stream[cffont->offset],(size_t)size); \
3015 charstring_len += cs_copy_charstring(charstrings->data + charstring_len, \
3016 max_len - charstring_len, \
3017 data, size, \
3018 cffont->gsubr, (cffont->subrs)[0], \
3019 default_width, nominal_width, NULL); \
3020 gid++; \
3023 @ @c
3024 void write_cff(PDF pdf, cff_font * cffont, fd_entry * fd)
3026 cff_index *charstrings, *cs_idx;
3028 long charstring_len, max_len;
3029 long size, offset = 0;
3031 card8 *data;
3032 card16 num_glyphs, cs_count1, code, gid, last_cid;
3034 double nominal_width, default_width;
3036 char *fullname;
3038 glw_entry *glyph, *found;
3039 struct avl_traverser t;
3041 fullname = xcalloc((unsigned) (8 + strlen(fd->fontname)), 1);
3042 sprintf(fullname, "%s+%s", fd->subset_tag, fd->fontname);
3044 /* finish parsing the CFF */
3045 cff_read_private(cffont);
3046 cff_read_subrs(cffont);
3049 Widths
3051 if (cffont->private[0] &&
3052 cff_dict_known(cffont->private[0], "defaultWidthX")) {
3053 default_width =
3054 (double) cff_dict_get(cffont->private[0], "defaultWidthX", 0);
3055 } else {
3056 default_width = CFF_DEFAULTWIDTHX_DEFAULT;
3058 if (cffont->private[0] &&
3059 cff_dict_known(cffont->private[0], "nominalWidthX")) {
3060 nominal_width =
3061 (double) cff_dict_get(cffont->private[0], "nominalWidthX", 0);
3062 } else {
3063 nominal_width = CFF_NOMINALWIDTHX_DEFAULT;
3066 num_glyphs = 0;
3067 last_cid = 0;
3068 glyph = xtalloc(1, glw_entry);
3070 /* insert notdef */
3071 glyph->id = 0;
3072 if (avl_find(fd->gl_tree, glyph) == NULL) {
3073 avl_insert(fd->gl_tree, glyph);
3074 glyph = xtalloc(1, glw_entry);
3077 avl_t_init(&t, fd->gl_tree);
3078 for (found = (glw_entry *) avl_t_first(&t, fd->gl_tree);
3079 found != NULL; found = (glw_entry *) avl_t_next(&t)) {
3080 if (found->id > last_cid)
3081 last_cid = (card16) found->id;
3082 num_glyphs++;
3086 cff_fdselect *fdselect;
3088 fdselect = xcalloc(1, sizeof(cff_fdselect));
3089 fdselect->format = 3;
3090 fdselect->num_entries = 1;
3091 fdselect->data.ranges = xcalloc(1, sizeof(cff_range3));
3092 fdselect->data.ranges[0].first = 0;
3093 fdselect->data.ranges[0].fd = 0;
3094 cffont->fdselect = fdselect;
3098 cff_charsets *charset;
3100 charset = xcalloc(1, sizeof(cff_charsets));
3101 charset->format = 0;
3102 charset->num_entries = (card16) (num_glyphs - 1);
3103 charset->data.glyphs = xcalloc(num_glyphs, sizeof(s_SID));
3105 gid = 0;
3107 avl_t_init(&t, fd->gl_tree);
3108 for (found = (glw_entry *) avl_t_first(&t, fd->gl_tree);
3109 found != NULL; found = (glw_entry *) avl_t_next(&t)) {
3110 if (found->id != 0) {
3111 charset->data.glyphs[gid] = (s_SID) found->id;
3112 gid++;
3115 cffont->charsets = charset;
3118 cff_dict_add(cffont->topdict, "CIDCount", 1);
3119 cff_dict_set(cffont->topdict, "CIDCount", 0, last_cid + 1);
3121 cffont->fdarray = xcalloc(1, sizeof(cff_dict *));
3122 cffont->fdarray[0] = cff_new_dict();
3123 cff_dict_add(cffont->fdarray[0], "FontName", 1);
3124 cff_dict_set(cffont->fdarray[0], "FontName", 0, (double) cff_add_string(cffont, fullname)); /* FIXME: Skip XXXXXX+ */
3125 cff_dict_add(cffont->fdarray[0], "Private", 2);
3126 cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0);
3127 cff_dict_set(cffont->fdarray[0], "Private", 0, 0.0);
3128 /* FDArray - index offset, not known yet */
3129 cff_dict_add(cffont->topdict, "FDArray", 1);
3130 cff_dict_set(cffont->topdict, "FDArray", 0, 0.0);
3131 /* FDSelect - offset, not known yet */
3132 cff_dict_add(cffont->topdict, "FDSelect", 1);
3133 cff_dict_set(cffont->topdict, "FDSelect", 0, 0.0);
3135 cff_dict_remove(cffont->topdict, "UniqueID");
3136 cff_dict_remove(cffont->topdict, "XUID");
3137 cff_dict_remove(cffont->topdict, "Private");
3138 cff_dict_remove(cffont->topdict, "Encoding");
3140 cffont->offset = (l_offset) cff_dict_get(cffont->topdict, "CharStrings", 0);
3141 cs_idx = cff_get_index_header(cffont);
3143 offset = (long) cffont->offset;
3144 cs_count1 = cs_idx->count;
3145 if (cs_count1 < 2) {
3146 normal_error("cff","no valid charstring data found");
3149 /* build the new charstrings entry */
3150 charstrings = cff_new_index((card16) (cs_count1==USHRT_MAX?cs_count1: cs_count1 + 1));
3151 max_len = 2 * CS_STR_LEN_MAX;
3152 charstrings->data = xcalloc((unsigned) max_len, sizeof(card8));
3153 charstring_len = 0;
3155 gid = 0;
3156 data = xcalloc(CS_STR_LEN_MAX, sizeof(card8));
3159 int i;
3160 for (i = 0; i < cs_count1; i++) {
3161 code = (card16) i;
3162 glyph->id = code;
3163 DO_COPY_CHARSTRING();
3167 /* CIDSet: a table of bits indexed by cid, bytes with high order bit first,
3168 each (set) bit is a (present) CID. */
3169 if (1) {
3170 int cid;
3171 cidset = pdf_create_obj(pdf, obj_type_others, 0);
3172 if (cidset != 0) {
3173 size_t l = (last_cid/8)+1;
3174 char *stream = xmalloc(l);
3175 memset(stream, 0, l);
3176 for (cid = 1; cid <= (long) last_cid; cid++) {
3177 glyph->id = cid;
3178 if (avl_find(fd->gl_tree,glyph) != NULL) {
3179 stream[(cid / 8)] |= (1 << (7 - (cid % 8)));
3182 pdf_begin_obj(pdf, cidset, OBJSTM_NEVER);
3183 pdf_begin_dict(pdf);
3184 pdf_dict_add_streaminfo(pdf);
3185 pdf_end_dict(pdf);
3186 pdf_begin_stream(pdf);
3187 pdf_out_block(pdf, stream, l);
3188 pdf_end_stream(pdf);
3189 pdf_end_obj(pdf);
3193 /* this happens if the internal metrics do not agree with the actual disk font */
3194 if (gid < num_glyphs) {
3195 formatted_warning("cff","embedded subset is smaller than expected: %d instead of %d glyphs", gid, num_glyphs);
3196 num_glyphs = gid;
3199 xfree(data);
3200 cff_release_index(cs_idx);
3202 (charstrings->offset)[num_glyphs] = (l_offset) (charstring_len + 1);
3203 charstrings->count = num_glyphs;
3204 cffont->num_glyphs = num_glyphs;
3205 cffont->cstrings = charstrings;
3208 We don't use subroutines at all.
3210 if (cffont->gsubr)
3211 cff_release_index(cffont->gsubr);
3212 cffont->gsubr = cff_new_index(0);
3214 if (cffont->subrs && cffont->subrs[0])
3215 cff_release_index(cffont->subrs[0]);
3216 cffont->subrs[0] = NULL;
3218 if (cffont->private && (cffont->private)[0]) {
3219 cff_dict_remove((cffont->private)[0], "Subrs"); /* no Subrs */
3222 cff_add_string(cffont, "Adobe");
3223 cff_add_string(cffont, "Identity");
3225 cff_dict_update(cffont->topdict, cffont);
3226 cff_dict_update(cffont->private[0], cffont);
3227 cff_update_string(cffont);
3229 /* CFF code need to be rewrote... */
3230 cff_dict_add(cffont->topdict, "ROS", 3);
3231 cff_dict_set(cffont->topdict, "ROS", 0,
3232 (double) cff_get_sid(cffont, "Adobe"));
3233 cff_dict_set(cffont->topdict, "ROS", 1,
3234 (double) cff_get_sid(cffont, "Identity"));
3235 cff_dict_set(cffont->topdict, "ROS", 2, 0.0);
3237 write_fontfile(pdf, cffont, fullname);
3238 xfree(fullname);
3239 cff_close(cffont);
3243 @ @c
3244 #undef ERROR /* for mingw */
3245 #define ERROR(a) { perror(a); return 0; }
3247 @ Input : SID or CID (16-bit unsigned int)
3248 Output: glyph index
3251 card16 cff_charsets_lookup(cff_font * cff, card16 cid)
3253 card16 gid = 0;
3254 cff_charsets *charset;
3255 card16 i;
3257 if (cff->flag & (CHARSETS_ISOADOBE | CHARSETS_EXPERT | CHARSETS_EXPSUB)) {
3258 ERROR("Predefined CFF charsets not supported yet");
3259 } else if (cff->charsets == NULL) {
3260 normal_error("cff","charsets data not available");
3263 if (cid == 0) {
3264 return 0; /* GID 0 (.notdef) */
3267 charset = cff->charsets;
3269 gid = 0;
3270 switch (charset->format) {
3271 case 0:
3272 for (i = 0; i < charset->num_entries; i++) {
3273 if (cid == charset->data.glyphs[i]) {
3274 gid = (card16) (i + 1);
3275 return gid;
3278 break;
3279 case 1:
3280 for (i = 0; i < charset->num_entries; i++) {
3281 if (cid >= charset->data.range1[i].first &&
3282 cid <=
3283 charset->data.range1[i].first +
3284 charset->data.range1[i].n_left) {
3285 gid = (card16) (gid + cid - charset->data.range1[i].first + 1);
3286 return gid;
3288 gid = (card16) (gid + charset->data.range1[i].n_left + 1);
3290 break;
3291 case 2:
3292 for (i = 0; i < charset->num_entries; i++) {
3293 if (cid >= charset->data.range2[i].first &&
3294 cid <=
3295 charset->data.range2[i].first +
3296 charset->data.range2[i].n_left) {
3297 gid = (card16) (gid + cid - charset->data.range2[i].first + 1);
3298 return gid;
3300 gid = (card16) (gid + charset->data.range2[i].n_left + 1);
3302 break;
3303 default:
3304 normal_error("cff","unknown charset format");
3307 return 0; /* not found */
3311 @ @c
3312 #define is_cidfont(a) ((a)->flag & FONTTYPE_CIDFONT)
3313 #define CID_MAX 65535
3314 void write_cid_cff(PDF pdf, cff_font * cffont, fd_entry * fd)
3316 cff_index *charstrings, *cs_idx;
3318 long charstring_len, max_len;
3319 long size, offset = 0;
3321 card8 *data;
3322 card16 num_glyphs, cs_count1, gid, last_cid;
3325 int fdsel, prev_fd, cid_count, cid;
3326 char *fullname;
3328 glw_entry *glyph;
3330 unsigned char *CIDToGIDMap = NULL;
3332 cff_fdselect *fdselect = NULL;
3333 cff_charsets *charset = NULL;
3336 if (!is_cidfont(cffont)) {
3337 perror("Not a CIDfont.");
3338 return;
3341 fullname = xcalloc((unsigned) (8 + strlen(fd->fontname)), 1);
3342 sprintf(fullname, "%s+%s", fd->subset_tag, fd->fontname);
3344 /* finish parsing the CFF */
3346 if (cff_dict_known(cffont->topdict, "CIDCount")) {
3347 cid_count = (card16) cff_dict_get(cffont->topdict, "CIDCount", 0);
3348 } else {
3349 cid_count = CFF_CIDCOUNT_DEFAULT;
3351 cff_read_charsets(cffont);
3352 CIDToGIDMap = xmalloc((unsigned)
3353 ((2 * (unsigned) cid_count) * sizeof(unsigned char)));
3354 memset(CIDToGIDMap, 0, (size_t) (2 * cid_count));
3357 glyph = xtalloc(1, glw_entry);
3358 /* insert notdef */
3359 glyph->id = 0;
3360 if (avl_find(fd->gl_tree, glyph) == NULL) {
3361 avl_insert(fd->gl_tree, glyph);
3362 glyph = xtalloc(1, glw_entry);
3365 last_cid = 0;
3366 num_glyphs = 0;
3367 for (cid = 0; cid <= CID_MAX; cid++) {
3368 glyph->id = (unsigned) cid;
3369 if (avl_find(fd->gl_tree, glyph) != NULL) {
3370 gid = (card16) cff_charsets_lookup(cffont, (card16) cid);
3371 CIDToGIDMap[2 * cid] = (unsigned char) ((gid >> 8) & 0xff);
3372 CIDToGIDMap[2 * cid + 1] = (unsigned char) (gid & 0xff);
3373 last_cid = (card16) cid;
3374 num_glyphs++;
3377 if (last_cid >= cffont->num_glyphs) {
3378 formatted_error("cff font","bad glyph index %i",last_cid);
3381 /* CIDSet: a table of bits indexed by cid, bytes with high order bit first,
3382 each (set) bit is a (present) CID. */
3383 if (1) {
3384 cidset = pdf_create_obj(pdf, obj_type_others, 0);
3385 if (cidset != 0) {
3386 size_t l = (last_cid / 8) + 1;
3387 char *stream = xmalloc(l);
3388 memset(stream, 0, l);
3389 for (cid = 1; cid <= (long) last_cid; cid++) {
3390 if (CIDToGIDMap[2 * cid] || CIDToGIDMap[2 * cid + 1]) {
3391 stream[(cid / 8)] |= (1 << (7 - (cid % 8)));
3394 pdf_begin_obj(pdf, cidset, OBJSTM_NEVER);
3395 pdf_begin_dict(pdf);
3396 pdf_dict_add_streaminfo(pdf);
3397 pdf_end_dict(pdf);
3398 pdf_begin_stream(pdf);
3399 pdf_out_block(pdf, stream, l);
3400 pdf_end_stream(pdf);
3401 pdf_end_obj(pdf);
3402 xfree(stream);
3407 cff_read_fdselect(cffont);
3408 cff_read_fdarray(cffont);
3409 cff_read_private(cffont);
3411 cff_read_subrs(cffont);
3414 cffont->offset = (l_offset) cff_dict_get(cffont->topdict, "CharStrings", 0);
3415 cs_idx = cff_get_index_header(cffont);
3417 offset = (long) cffont->offset;
3418 cs_count1 = cs_idx->count;
3419 if (cs_count1 < 2) {
3420 normal_error("cff","no valid charstring data found");
3423 charset = xcalloc(1, sizeof(cff_charsets));
3424 charset->format = 0;
3425 charset->num_entries = 0;
3426 charset->data.glyphs = xcalloc(num_glyphs, sizeof(s_SID));
3428 fdselect = xcalloc(1, sizeof(cff_fdselect));
3429 fdselect->format = 3;
3430 fdselect->num_entries = 0;
3431 fdselect->data.ranges = xcalloc(num_glyphs, sizeof(cff_range3));
3433 charstrings = cff_new_index((card16) (cs_count1==USHRT_MAX?cs_count1: cs_count1 + 1));
3434 max_len = 2 * CS_STR_LEN_MAX;
3435 charstrings->data = xcalloc((unsigned) max_len, sizeof(card8));
3436 charstring_len = 0;
3438 prev_fd = -1;
3439 gid = 0;
3440 data = xcalloc(CS_STR_LEN_MAX, sizeof(card8));
3441 for (cid = 0; cid <= last_cid; cid++) {
3442 unsigned short gid_org;
3444 glyph->id = (unsigned) cid;
3445 if (avl_find(fd->gl_tree, glyph) == NULL)
3446 continue;
3448 gid_org =
3449 (short unsigned) ((CIDToGIDMap[2 * cid] << 8) |
3450 (CIDToGIDMap[2 * cid + 1]));
3451 size = (long) (cs_idx->offset[gid_org + 1] - cs_idx->offset[gid_org]);
3452 if (size > CS_STR_LEN_MAX) {
3453 formatted_error("cff","charstring too long: gid=%u, %ld bytes", cid, size);
3455 if (charstring_len + CS_STR_LEN_MAX >= max_len) {
3456 max_len = charstring_len + 2 * CS_STR_LEN_MAX;
3457 charstrings->data =
3458 xrealloc(charstrings->data,
3459 (unsigned) ((unsigned) max_len * sizeof(card8)));
3461 (charstrings->offset)[gid] = (l_offset) (charstring_len + 1);
3462 cffont->offset =
3463 (l_offset) ((unsigned) offset + (cs_idx->offset)[gid_org] - 1);
3464 memcpy(data, &cffont->stream[cffont->offset], (size_t) size);
3465 fdsel = cff_fdselect_lookup(cffont, gid_org);
3466 charstring_len += cs_copy_charstring(charstrings->data + charstring_len,
3467 max_len - charstring_len,
3468 data, size,
3469 cffont->gsubr,
3470 (cffont->subrs)[fdsel], 0, 0,
3471 NULL);
3473 if (cid > 0 && gid_org > 0) {
3474 charset->data.glyphs[charset->num_entries] = (s_SID) cid;
3475 charset->num_entries++;
3477 if (fdsel != prev_fd) {
3478 fdselect->data.ranges[fdselect->num_entries].first = gid;
3479 fdselect->data.ranges[fdselect->num_entries].fd = (card8) fdsel;
3480 fdselect->num_entries++;
3481 prev_fd = fdsel;
3483 gid++;
3486 if (gid != num_glyphs)
3487 formatted_error("cff","unexpected error: %i != %i", gid, num_glyphs);
3488 xfree(data);
3489 cff_release_index(cs_idx);
3491 xfree(CIDToGIDMap);
3493 (charstrings->offset)[num_glyphs] = (l_offset) (charstring_len + 1);
3494 charstrings->count = num_glyphs;
3495 cffont->num_glyphs = num_glyphs;
3496 cffont->cstrings = charstrings;
3498 cff_release_charsets(cffont->charsets);
3499 cffont->charsets = charset;
3500 cff_release_fdselect(cffont->fdselect);
3501 cffont->fdselect = fdselect;
3504 * We don't use subroutines at all.
3506 if (cffont->gsubr)
3507 cff_release_index(cffont->gsubr);
3508 cffont->gsubr = cff_new_index(0);
3510 for (fdsel = 0; fdsel < cffont->num_fds; fdsel++) {
3511 if (cffont->subrs && cffont->subrs[fdsel]) {
3512 cff_release_index(cffont->subrs[fdsel]);
3513 cffont->subrs[fdsel] = NULL;
3515 if (cffont->private && (cffont->private)[fdsel]) {
3516 cff_dict_remove((cffont->private)[fdsel], "Subrs"); /* no Subrs */
3520 write_fontfile(pdf, cffont, fullname);
3521 xfree(fullname);
3522 cff_close(cffont);
3526 @ here is a sneaky trick: fontforge knows how to convert Type1 to CFF, so
3527 I have defined a utility function in luafflib.c that does exactly that.
3528 If it works out ok, I will clean up this code.
3531 void writetype1w(PDF pdf, fd_entry * fd)
3533 cff_font *cff;
3534 int i;
3535 FILE *fp;
3536 ff_entry *ff;
3537 unsigned char *tfm_buffer = NULL;
3538 int tfm_size = 0;
3540 ff = check_ff_exist(fd->fm->ff_name, 0);
3542 fp = fopen(ff->ff_path, "rb");
3543 cur_file_name = ff->ff_path;
3545 if (!fp) {
3546 fprintf(stderr, "Type1: Could not open Type1 font: %s", cur_file_name);
3547 uexit(1);
3549 fclose(fp);
3551 if (is_subsetted(fd->fm)) {
3552 report_start_file(filetype_subset,cur_file_name);
3553 } else {
3554 report_start_file(filetype_font,cur_file_name);
3556 (void) ff_createcff(ff->ff_path, &tfm_buffer, &tfm_size);
3558 if (tfm_size > 0) {
3559 cff = read_cff(tfm_buffer, tfm_size, 0);
3560 if (cff != NULL) {
3561 write_cff(pdf, cff, fd);
3562 } else {
3563 for (i = 0; i < tfm_size; i++)
3564 strbuf_putchar(pdf->fb, tfm_buffer[i]);
3566 fd->ff_found = 1;
3567 } else {
3568 fprintf(stderr, "Type1: Could not understand Type1 font: %s",
3569 cur_file_name);
3570 uexit(1);
3572 if (is_subsetted(fd->fm)) {
3573 report_stop_file(filetype_subset);
3574 } else {
3575 report_stop_file(filetype_font);
3577 cur_file_name = NULL;