/TeXmacs-1.0.7.11-src/src/Plugins/Pdf/dvipdfmx/t1_load.c
C | 1211 lines | 1001 code | 111 blank | 99 comment | 288 complexity | 6ae5f36bbf1f857e06cfbc8d434f1b08 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, MPL-2.0-no-copyleft-exception
1/* $Header: /home/cvsroot/dvipdfmx/src/t1_load.c,v 1.13 2009/04/08 03:10:58 chofchof Exp $
2
3 This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
4
5 Copyright (C) 2002 by Jin-Hwan Cho and Shunsaku Hirata,
6 the dvipdfmx project team <dvipdfmx@project.ktug.or.kr>
7
8 Copyright (C) 1998, 1999 by Mark A. Wicks <mwicks@kettering.edu>
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
23*/
24
25#if HAVE_CONFIG_H
26#include "config.h"
27#endif
28
29#include <string.h>
30#include <math.h>
31
32#include "system.h"
33#include "mfileio.h"
34#include "mem.h"
35#include "error.h"
36#include "numbers.h"
37
38#include "pdfobj.h"
39#include "pdffont.h"
40
41#include "pdfencoding.h"
42#include "unicode.h"
43
44#include "dpxutil.h"
45
46#include "pst_obj.h"
47#include "pst.h"
48
49#include "cff_limits.h"
50#include "cff_types.h"
51#include "cff_dict.h"
52#include "cff.h"
53
54#include "t1_load.h"
55
56/* Migrated from t1crypt */
57#define T1_EEKEY 55665u
58#define T1_CHARKEY 4330u
59
60#if 0
61/* We no longer need encryption. */
62static unsigned short r = T1_EEKEY, c1 = 52845, c2 = 22719;
63
64static unsigned char t1_encrypt (unsigned char plain)
65{
66 unsigned char cipher;
67 cipher = (plain ^ (r >> 8));
68 r = (cipher + r) * c1 + c2;
69 return cipher;
70}
71
72static void t1_crypt_init (unsigned short key)
73{
74 r = key;
75}
76#endif /* 0 */
77
78static void
79t1_decrypt (unsigned short key,
80 unsigned char *dst, const unsigned char *src,
81 long skip, long len)
82{
83 len -= skip;
84 while (skip--)
85 key = (key + *src++) * 52845u + 22719u;
86 while (len--) {
87 unsigned char c = *src++;
88 *dst++ = (c ^ (key >> 8));
89 key = (key + c) * 52845u + 22719u;
90 }
91}
92/* T1CRYPT */
93
94#define MATCH_NAME(t,n) ((t) && PST_NAMETYPE((t)) && !strncmp(pst_data_ptr((t)),(n),strlen((n))))
95#define MATCH_OP(t,n) ((t) && PST_UNKNOWNTYPE((t)) && !strncmp(pst_data_ptr((t)),(n),strlen((n))))
96
97#define RELEASE_TOK(t) if ((t) != NULL) {\
98 pst_release_obj((t));\
99 (t) = NULL;\
100}
101
102static char *
103get_next_key (unsigned char **start, unsigned char *end)
104{
105 char *key = NULL;
106 pst_obj *tok;
107
108 while (*start < end &&
109 (tok = pst_get_token(start, end)) != NULL) {
110 if (PST_NAMETYPE(tok)) {
111 key = (char *) pst_getSV(tok);
112 RELEASE_TOK(tok);
113 break;
114 }
115 RELEASE_TOK(tok);
116 }
117
118 return key;
119}
120
121static int
122seek_operator (unsigned char **start, unsigned char *end, const char *op)
123{
124 pst_obj *tok = NULL;
125
126 while (*start < end &&
127 (tok = pst_get_token(start, end)) != NULL) {
128 if (MATCH_OP(tok, op)) {
129 break;
130 }
131 RELEASE_TOK(tok);
132 }
133
134 if (tok == NULL)
135 return -1;
136 RELEASE_TOK(tok);
137
138 return 0;
139}
140
141
142static int
143parse_svalue (unsigned char **start, unsigned char *end, char **value)
144{
145 pst_obj *tok;
146
147 tok = pst_get_token(start, end);
148 if (tok == NULL)
149 return -1;
150 else if (PST_NAMETYPE(tok) || PST_STRINGTYPE(tok))
151 *value = (char *) pst_getSV(tok);
152 else {
153 RELEASE_TOK(tok);
154 return -1;
155 }
156 RELEASE_TOK(tok);
157
158 return 1;
159}
160
161static int
162parse_bvalue (unsigned char **start, unsigned char *end, double *value)
163{
164 pst_obj *tok;
165
166 tok = pst_get_token(start, end);
167 if (tok == NULL)
168 return -1;
169 else if (PST_BOOLEANTYPE(tok))
170 *value = (double) pst_getIV(tok);
171 else {
172 RELEASE_TOK(tok);
173 return -1;
174 }
175 RELEASE_TOK(tok);
176
177 return 1;
178}
179
180static int
181parse_nvalue (unsigned char **start, unsigned char *end, double *value, int max)
182{
183 int argn = 0;
184 pst_obj *tok;
185
186 tok = pst_get_token(start, end);
187 if (tok == NULL)
188 return -1;
189 /*
190 * All array elements must be numeric token. (ATM compatible)
191 */
192 if (PST_NUMBERTYPE(tok) && max > 0) {
193 value[0] = (double) pst_getRV(tok);
194 argn = 1;
195 } else if (PST_MARKTYPE(tok)) {
196 /* It does not distinguish '[' and '{'... */
197 RELEASE_TOK(tok);
198 while (*start < end &&
199 (tok = pst_get_token(start, end)) != NULL &&
200 PST_NUMBERTYPE(tok) && argn < max) {
201 value[argn++] = (double) pst_getRV(tok);
202 RELEASE_TOK(tok);
203 }
204 if (tok == NULL)
205 return -1;
206 if (!MATCH_OP(tok, "]") && !MATCH_OP(tok, "}")) {
207 argn = -1;
208 }
209 }
210 RELEASE_TOK(tok);
211
212 return argn;
213}
214
215static const char *const StandardEncoding[256] = {
216 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
217 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
218 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
219 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
220 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
221 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
222 ".notdef", ".notdef", "space", "exclam", "quotedbl",
223 "numbersign", "dollar", "percent", "ampersand", "quoteright",
224 "parenleft", "parenright", "asterisk", "plus", "comma",
225 "hyphen", "period", "slash", "zero", "one",
226 "two", "three", "four", "five", "six",
227 "seven", "eight", "nine", "colon", "semicolon",
228 "less", "equal", "greater", "question", "at",
229 "A", "B", "C", "D", "E",
230 "F", "G", "H", "I", "J",
231 "K", "L", "M", "N", "O",
232 "P", "Q", "R", "S", "T",
233 "U", "V", "W", "X", "Y",
234 "Z", "bracketleft", "backslash", "bracketright", "asciicircum",
235 "underscore", "quoteleft", "a", "b", "c",
236 "d", "e", "f", "g", "h",
237 "i", "j", "k", "l", "m",
238 "n", "o", "p", "q", "r",
239 "s", "t", "u", "v", "w",
240 "x", "y", "z", "braceleft", "bar",
241 "braceright", "asciitilde", ".notdef", ".notdef", ".notdef",
242 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
243 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
244 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
245 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
246 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
247 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
248 ".notdef", "exclamdown", "cent", "sterling", "fraction",
249 "yen", "florin", "section", "currency", "quotesingle",
250 "quotedblleft", "guillemotleft", "guilsinglleft", "guilsinglright", "fi",
251 "fl", ".notdef", "endash", "dagger", "daggerdbl",
252 "periodcentered", ".notdef", "paragraph", "bullet", "quotesinglbase",
253 "quotedblbase", "quotedblright", "guillemotright", "ellipsis", "perthousand",
254 ".notdef", "questiondown", ".notdef", "grave", "acute",
255 "circumflex", "tilde", "macron", "breve", "dotaccent",
256 "dieresis", ".notdef", "ring", "cedilla", ".notdef",
257 "hungarumlaut", "ogonek", "caron", "emdash", ".notdef",
258 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
259 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
260 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
261 "AE", ".notdef", "ordfeminine", ".notdef", ".notdef",
262 ".notdef", ".notdef", "Lslash", "Oslash", "OE",
263 "ordmasculine", ".notdef", ".notdef", ".notdef", ".notdef",
264 ".notdef", "ae", ".notdef", ".notdef", ".notdef",
265 "dotlessi", ".notdef", ".notdef", "lslash", "oslash",
266 "oe", "germandbls", ".notdef", ".notdef", ".notdef",
267 ".notdef"
268};
269
270static const char *const ISOLatin1Encoding[256] = {
271 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
272 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
273 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
274 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
275 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
276 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
277 ".notdef", ".notdef", "space", "exclam", "quotedbl",
278 "numbersign", "dollar", "percent", "ampersand", "quotesingle",
279 "parenleft", "parenright", "asterisk", "plus", "comma",
280 "hyphen", "period", "slash", "zero", "one",
281 "two", "three", "four", "five", "six",
282 "seven", "eight", "nine", "colon", "semicolon",
283 "less", "equal", "greater", "question", "at",
284 "A", "B", "C", "D", "E",
285 "F", "G", "H", "I", "J",
286 "K", "L", "M", "N", "O",
287 "P", "Q", "R", "S", "T",
288 "U", "V", "W", "X", "Y",
289 "Z", "bracketleft", "backslash", "bracketright", "asciicircum",
290 "underscore", "grave", "a", "b", "c",
291 "d", "e", "f", "g", "h",
292 "i", "j", "k", "l", "m",
293 "n", "o", "p", "q", "r",
294 "s", "t", "u", "v", "w",
295 "x", "y", "z", "braceleft", "bar",
296 "braceright", "asciitilde", ".notdef", ".notdef", ".notdef",
297 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
298 ".notdef", ".notdef", ".notdef", ".notdef", ".notdef",
299 ".notdef", ".notdef", ".notdef", ".notdef", "dotlessi",
300 "quoteleft", "quoteright", "circumflex", "tilde", "macron",
301 "breve", "dotaccent", "dieresis", ".notdef", "ring",
302 "cedilla", ".notdef", "hungarumlaut", "ogonek", "caron",
303 "space", "exclamdown", "cent", "sterling", "currency",
304 "yen", "brokenbar", "section", "dieresis", "copyright",
305 "ordfeminine", "guillemotleft", "logicalnot", "hyphen",
306 "registered",
307 "macron", "degree", "plusminus", "twosuperior", "threesuperior",
308 "acute", "mu", "paragraph", "periodcentered", "cedilla",
309 "onesuperior", "ordmasculine", "guillemotright", "onequarter",
310 "onehalf",
311 "threequarters", "questiondown", "Agrave", "Aacute", "Acircumflex",
312 "Atilde", "Adieresis", "Aring", "AE", "Ccedilla",
313 "Egrave", "Eacute", "Ecircumflex", "Edieresis", "Igrave",
314 "Iacute", "Icircumflex", "Idieresis", "Eth", "Ntilde",
315 "Ograve", "Oacute", "Ocircumflex", "Otilde", "Odieresis",
316 "multiply", "Oslash", "Ugrave", "Uacute", "Ucircumflex",
317 "Udieresis", "Yacute", "Thorn", "germandbls", "agrave",
318 "aacute", "acircumflex", "atilde", "adieresis", "aring",
319 "ae", "ccedilla", "egrave", "eacute", "ecircumflex",
320 "edieresis", "igrave", "iacute", "icircumflex", "idieresis",
321 "eth", "ntilde", "ograve", "oacute", "ocircumflex",
322 "otilde", "odieresis", "divide", "oslash", "ugrave",
323 "uacute", "ucircumflex", "udieresis", "yacute", "thorn",
324 "ydieresis"
325};
326
327static int
328parse_encoding (char **enc_vec, unsigned char **start, unsigned char *end, int mode)
329{
330 pst_obj *tok;
331 int code;
332
333 /*
334 * StandardEncoding def
335 * or
336 * ISOLatin1Encoding def
337 * or
338 * 0 1 255 {1 index exch /.notdef put } for
339 * dup int name put
340 * ...
341 * [readonly] def
342 */
343 tok = pst_get_token(start, end);
344 if (MATCH_OP(tok, "StandardEncoding")) {
345 RELEASE_TOK(tok);
346 if (enc_vec) {
347 for (code = 0; code < 256; code++) {
348 if (StandardEncoding[code] &&
349 strcmp(StandardEncoding[code], ".notdef") != 0) {
350 enc_vec[code] = NEW(strlen(StandardEncoding[code])+1, char);
351 strcpy(enc_vec[code], StandardEncoding[code]);
352 } else {
353 enc_vec[code] = NULL;
354 }
355 }
356 }
357 } else if (MATCH_OP(tok, "ISOLatin1Encoding")) {
358 RELEASE_TOK(tok);
359 if (enc_vec) {
360 for (code = 0; code < 256; code++) {
361 if (ISOLatin1Encoding[code] &&
362 strcmp(ISOLatin1Encoding[code], ".notdef") != 0) {
363 enc_vec[code] = NEW(strlen(ISOLatin1Encoding[code])+1, char);
364 strcpy(enc_vec[code], ISOLatin1Encoding[code]);
365 } else {
366 enc_vec[code] = NULL;
367 }
368 }
369 }
370 } else if (MATCH_OP(tok, "ExpertEncoding")) {
371 RELEASE_TOK(tok);
372 if (enc_vec) {
373 WARN("ExpertEncoding not supported.");
374 RELEASE_TOK(tok);
375 return -1;
376 }
377 /*
378 * Not supported yet.
379 */
380 } else {
381 RELEASE_TOK(tok);
382 seek_operator(start, end, "array");
383 /*
384 * Pick all seaquences that matches "dup n /Name put" until
385 * occurrence of "def" or "readonly".
386 */
387 while (*start < end &&
388 (tok = pst_get_token(start, end)) != NULL) {
389 if (MATCH_OP(tok, "def") || MATCH_OP(tok, "readonly")) {
390 RELEASE_TOK(tok);
391 break;
392 } else if (!MATCH_OP(tok, "dup")) {
393 RELEASE_TOK(tok);
394 continue;
395 }
396 RELEASE_TOK(tok);
397
398 tok = pst_get_token(start, end);
399 if (!tok || !PST_INTEGERTYPE(tok) ||
400 (code = pst_getIV(tok)) > 255 || code < 0) {
401 RELEASE_TOK(tok);
402 continue;
403 }
404 RELEASE_TOK(tok);
405
406 tok = pst_get_token(start, end);
407 if (!tok || !PST_NAMETYPE(tok)) {
408 RELEASE_TOK(tok);
409 continue;
410 }
411 if (enc_vec) {
412 if (enc_vec[code])
413 RELEASE(enc_vec[code]);
414 enc_vec[code] = (char *) pst_getSV(tok);
415 }
416 RELEASE_TOK(tok);
417
418 tok = pst_get_token(start, end);
419 if (!MATCH_OP(tok, "put")) {
420 if (enc_vec[code]) {
421 RELEASE(enc_vec[code]);
422 enc_vec[code] = NULL;
423 }
424 RELEASE_TOK(tok);
425 continue;
426 }
427 RELEASE_TOK(tok);
428 }
429 }
430
431 return 0;
432}
433
434#ifndef CS_STR_LEN_MAX
435#define CS_STR_LEN_MAX 65536UL
436#endif
437#ifndef CFF_GLYPH_MAX
438#define CFF_GLYPH_MAX CFF_SID_MAX
439#endif
440
441static int
442parse_subrs (cff_font *font,
443 unsigned char **start, unsigned char *end, int lenIV, int mode)
444{
445 cff_index *subrs;
446 pst_obj *tok;
447 long i, count, offset, max_size;
448 long *offsets, *lengths;
449 card8 *data;
450
451 tok = pst_get_token(start, end);
452 if (!PST_INTEGERTYPE(tok) || pst_getIV(tok) < 0) {
453 WARN("Parsing Subrs failed.");
454 RELEASE_TOK(tok);
455 return -1;
456 }
457
458 count = pst_getIV(tok);
459 RELEASE_TOK(tok);
460
461 if (count == 0) {
462 font->subrs[0] = NULL;
463 return 0;
464 }
465
466 tok = pst_get_token(start, end);
467 if (!MATCH_OP(tok, "array")) {
468 RELEASE_TOK(tok);
469 return -1;
470 }
471 RELEASE_TOK(tok);
472
473 if (mode != 1) {
474 max_size = CS_STR_LEN_MAX;
475 data = NEW(max_size, card8);
476 offsets = NEW(count, long);
477 lengths = NEW(count, long);
478 memset(offsets, 0, sizeof(long)*count);
479 memset(lengths, 0, sizeof(long)*count);
480 } else {
481 max_size = 0;
482 data = NULL;
483 offsets = NULL;
484 lengths = NULL;
485 }
486
487 offset = 0;
488 /* dup subr# n-bytes RD n-binary-bytes NP */
489 for (i = 0; i < count;) {
490 long idx, len;
491
492 tok = pst_get_token(start, end);
493 if (!tok) {
494 if (data) RELEASE(data);
495 if (offsets) RELEASE(offsets);
496 if (lengths) RELEASE(lengths);
497 return -1;
498 } else if (MATCH_OP(tok, "ND") ||
499 MATCH_OP(tok, "|-") || MATCH_OP(tok, "def")) {
500 RELEASE_TOK(tok);
501 break;
502 } else if (!MATCH_OP(tok, "dup")) {
503 RELEASE_TOK(tok);
504 continue;
505 }
506 RELEASE_TOK(tok);
507
508 /* Found "dup" */
509 tok = pst_get_token(start, end);
510 if (!PST_INTEGERTYPE(tok) || pst_getIV(tok) < 0 ||
511 pst_getIV(tok) >= count) {
512 RELEASE_TOK(tok);
513 if (data) RELEASE(data);
514 if (offsets) RELEASE(offsets);
515 if (lengths) RELEASE(lengths);
516 return -1;
517 }
518 idx = pst_getIV(tok);
519 RELEASE_TOK(tok);
520
521 tok = pst_get_token(start, end);
522 if (!PST_INTEGERTYPE(tok) || pst_getIV(tok) < 0 ||
523 pst_getIV(tok) > CS_STR_LEN_MAX) {
524 RELEASE_TOK(tok);
525 return -1;
526 }
527 len = pst_getIV(tok);
528 RELEASE_TOK(tok);
529
530 tok = pst_get_token(start, end);
531 if (!MATCH_OP(tok, "RD") && !MATCH_OP(tok, "-|") &&
532 seek_operator(start, end, "readstring") < 0) {
533 RELEASE_TOK(tok);
534 if (data) RELEASE(data);
535 if (offsets) RELEASE(offsets);
536 if (lengths) RELEASE(lengths);
537 return -1;
538 }
539 RELEASE_TOK(tok);
540
541 *start += 1;
542 if (*start + len >= end) {
543 if (data) RELEASE(data);
544 if (offsets) RELEASE(offsets);
545 if (lengths) RELEASE(lengths);
546 return -1;
547 }
548 if (mode != 1) {
549 if (offset + len >= max_size) {
550 max_size += CS_STR_LEN_MAX;
551 data = RENEW(data, max_size, card8);
552 }
553 if (lenIV >= 0) {
554 t1_decrypt(T1_CHARKEY, data+offset, *start, lenIV, len);
555 offsets[idx] = offset;
556 offset += (lengths[idx] = len - lenIV);
557 } else if (len > 0) {
558 offsets[idx] = offset;
559 lengths[idx] = len;
560 memcpy(&data[offset], *start, len);
561 offset += len;
562 }
563 }
564 *start += len;
565 i++;
566 }
567
568 if (mode != 1) {
569 if (font->subrs[0] == NULL) {
570 subrs = font->subrs[0] = cff_new_index(count);
571 subrs->data = NEW(offset, card8);
572 offset = 0;
573 for (i = 0; i < count; i++) {
574 subrs->offset[i] = offset + 1;
575 if (lengths[i] > 0) {
576 memcpy(subrs->data + offset, data + offsets[i], lengths[i]);
577 offset += lengths[i];
578 }
579 }
580 subrs->offset[count] = offset + 1;
581 } else {
582 /* Adobe's OPO_____.PFB and OPBO____.PFB have two /Subrs dicts,
583 * and also have /CharStrings not followed by dicts.
584 * Simply ignores those data. By ChoF on 2009/04/08. */
585 WARN("Already found /Subrs; ignores the other /Subrs dicts.");
586 }
587 RELEASE(data);
588 RELEASE(offsets);
589 RELEASE(lengths);
590 }
591
592 return 0;
593}
594
595static int
596parse_charstrings (cff_font *font,
597 unsigned char **start, unsigned char *end, int lenIV, int mode)
598{
599 cff_index *charstrings;
600 cff_charsets *charset;
601 pst_obj *tok;
602 long i, count, have_notdef;
603 long max_size, offset;
604
605 /* /CharStrings n dict dup begin
606 * /GlyphName n-bytes RD -n-binary-bytes- ND
607 * ...
608 * end
609 * - stack - ... /CharStrings dict
610 */
611 tok = pst_get_token(start, end);
612 if (!PST_INTEGERTYPE(tok) ||
613 pst_getIV(tok) < 0 || pst_getIV(tok) > CFF_GLYPH_MAX) {
614 unsigned char *s = pst_getSV(tok);
615 WARN("Ignores non dict \"/CharStrings %s ...\"", s);
616 RELEASE(s);
617 RELEASE_TOK(tok);
618 return 0;
619 }
620 count = pst_getIV(tok);
621 RELEASE_TOK(tok);
622
623 if (mode != 1) {
624 charstrings = cff_new_index(count);
625 max_size = CS_STR_LEN_MAX;
626 charstrings->data = NEW(max_size, card8);
627 } else {
628 charstrings = NULL;
629 max_size = 0;
630 }
631 font->cstrings = charstrings;
632
633 charset = font->charsets = NEW(1, cff_charsets);
634 charset->format = 0;
635 charset->num_entries = count-1;
636 charset->data.glyphs = NEW(count-1, s_SID);
637 memset(charset->data.glyphs, 0, sizeof(s_SID)*(count-1));
638
639 offset = 0;
640 have_notdef = 0; /* .notdef must be at gid = 0 in CFF */
641
642 seek_operator(start, end, "begin");
643 for (i = 0; i < count; i++) {
644 char *glyph_name;
645 long len, gid, j;
646
647 /* BUG-20061126 (by ChoF):
648 * Some fonts (e.g., belleek/blsy.pfb) does not have the correct number
649 * of glyphs. Modify the codes even to work with these broken fonts.
650 */
651 tok = pst_get_token(start, end);
652 glyph_name = (char *)pst_getSV(tok);
653
654 if (PST_NAMETYPE(tok)) {
655 RELEASE_TOK(tok);
656 if (!glyph_name) {
657 return -1;
658 } else if (!strcmp(glyph_name, ".notdef")) {
659 gid = 0;
660 have_notdef = 1;
661 } else if (have_notdef) {
662 gid = i;
663 } else if (i == count - 1) {
664 WARN("No .notdef glyph???");
665 return -1;
666 } else {
667 gid = i+1;
668 }
669 } else if (PST_UNKNOWNTYPE(tok) && !strcmp(glyph_name, "end")) {
670 RELEASE_TOK(tok);
671 break;
672 } else {
673 RELEASE_TOK(tok);
674 return -1;
675 }
676
677 if (gid > 0)
678 charset->data.glyphs[gid-1] = cff_add_string(font, glyph_name, 0);
679 /*
680 * We don't care about duplicate strings here since
681 * later a subset font of this font will be generated.
682 */
683
684 RELEASE(glyph_name);
685
686 tok = pst_get_token(start, end);
687 if (!PST_INTEGERTYPE(tok) ||
688 pst_getIV(tok) < 0 || pst_getIV(tok) > CS_STR_LEN_MAX) {
689 RELEASE_TOK(tok);
690 return -1;
691 }
692 len = pst_getIV(tok);
693 RELEASE_TOK(tok);
694
695 tok = pst_get_token(start, end);
696 if (!MATCH_OP(tok, "RD") &&
697 !MATCH_OP(tok, "-|") &&
698 seek_operator(start, end, "readstring") < 0) {
699 RELEASE_TOK(tok);
700 return -1;
701 }
702 RELEASE_TOK(tok);
703
704 if (*start + len + 1 >= end) {
705 return -1;
706 }
707 if (mode != 1) {
708 if (offset + len >= max_size) {
709 max_size += MAX(len, CS_STR_LEN_MAX);
710 charstrings->data = RENEW(charstrings->data, max_size, card8);
711 }
712 if (gid == 0) {
713 if (lenIV >= 0) {
714 memmove(charstrings->data + len - lenIV, charstrings->data, offset);
715 for (j = 1; j <= i; j++) {
716 charstrings->offset[j] += len - lenIV;
717 }
718 } else {
719 memmove(charstrings->data + len, charstrings->data, offset);
720 for (j = 1; j <= i; j++) {
721 charstrings->offset[j] += len;
722 }
723 }
724 }
725 }
726
727 *start += 1;
728 if (mode != 1) {
729 if (lenIV >= 0) {
730 long offs = gid ? offset : 0;
731 charstrings->offset[gid] = offs + 1; /* start at 1 */
732 t1_decrypt(T1_CHARKEY, charstrings->data+offs, *start, lenIV, len);
733 offset += len - lenIV;
734 } else {
735 if (gid == 0) {
736 charstrings->offset[gid] = 1;
737 memcpy(&charstrings->data[0], *start, len);
738 } else {
739 charstrings->offset[gid] = offset + 1;
740 memcpy(&charstrings->data[offset], *start, len);
741 }
742 offset += len;
743 }
744 }
745 *start += len;
746
747 tok = pst_get_token(start, end);
748 if (!MATCH_OP(tok, "ND") && !MATCH_OP(tok, "|-")) {
749 RELEASE_TOK(tok);
750 return -1;
751 }
752 RELEASE_TOK(tok);
753 }
754 if (mode != 1)
755 charstrings->offset[count] = offset + 1;
756 font->num_glyphs = count;
757
758 return 0;
759}
760
761#define CHECK_ARGN_EQ(n) if (argn != (n)) {\
762 WARN("%d values expected but only %d read.", (n), argn);\
763 RELEASE(key);\
764 return -1;\
765}
766#define CHECK_ARGN_GE(n) if (argn < (n)) {\
767 WARN("%d values expected but only %d read.", (n), argn);\
768 RELEASE(key);\
769 return -1;\
770}
771
772#define MAX_ARGS 127
773static int
774parse_part2 (cff_font *font, unsigned char **start, unsigned char *end, int mode)
775{
776 char *key;
777 double argv[MAX_ARGS];
778 int argn, lenIV = 4;
779
780 while (*start < end &&
781 (key = get_next_key(start, end)) != NULL) {
782 if (!strcmp(key, "Subrs")) {
783 /* levIV must appear before Subrs */
784 if (parse_subrs(font, start, end, lenIV, mode) < 0) {
785 RELEASE(key);
786 return -1;
787 }
788 } else if (!strcmp(key, "CharStrings")) {
789 if (parse_charstrings(font, start, end, lenIV, mode) < 0) {
790 RELEASE(key);
791 return -1;
792 }
793 } else if (!strcmp(key, "lenIV")) {
794 argn = parse_nvalue(start, end, argv, 1);
795 CHECK_ARGN_EQ(1);
796 lenIV = (int) argv[0];
797 } else if (!strcmp(key, "BlueValues") ||
798 !strcmp(key, "OtherBlues") ||
799 !strcmp(key, "FamilyBlues") ||
800 !strcmp(key, "FamilyOtherBlues") ||
801 !strcmp(key, "StemSnapH") ||
802 !strcmp(key, "StemSnapV")) {
803 /*
804 * Operand values are delta in CFF font dictionary encoding.
805 */
806 argn = parse_nvalue(start, end, argv, MAX_ARGS);
807 CHECK_ARGN_GE(0);
808 cff_dict_add(font->private[0], key, argn);
809 while (argn-- > 0) {
810 cff_dict_set(font->private[0], key, argn,
811 (argn == 0) ? argv[argn] : argv[argn] - argv[argn-1]);
812 }
813 } else if (!strcmp(key, "StdHW") ||
814 !strcmp(key, "StdVW") ||
815 !strcmp(key, "BlueScale") ||
816 !strcmp(key, "BlueShift") ||
817 !strcmp(key, "BlueFuzz") ||
818 !strcmp(key, "LanguageGroup") ||
819 !strcmp(key, "ExpansionFactor")) {
820 /*
821 * Value of StdHW and StdVW is described as an array in the
822 * Type 1 Font Specification but is a number in CFF format.
823 */
824 argn = parse_nvalue(start, end, argv, 1);
825 CHECK_ARGN_EQ(1);
826 cff_dict_add(font->private[0], key, 1);
827 cff_dict_set(font->private[0], key, 0, argv[0]);
828 } else if (!strcmp(key, "ForceBold")) {
829 argn = parse_bvalue(start, end, &(argv[0]));
830 CHECK_ARGN_EQ(1);
831 if (argv[0] != 0) {
832 cff_dict_add(font->private[0], key, 1);
833 cff_dict_set(font->private[0], key, 0, 1);
834 }
835 }
836 /*
837 * MinFeature, RndStemUp, UniqueID, Password ignored.
838 */
839 RELEASE(key);
840 }
841
842 return 0;
843}
844
845#ifndef TYPE1_NAME_LEN_MAX
846#define TYPE1_NAME_LEN_MAX 127
847#endif
848
849static long
850parse_part1 (cff_font *font, char **enc_vec,
851 unsigned char **start, unsigned char *end, int mode)
852{
853 char *key, *strval;
854 double argv[MAX_ARGS];
855 int argn; /* Macro CHECK_ARGN_XX assume 'argn' is used. */
856
857 /*
858 * We skip PostScript code inserted before the beginning of
859 * font dictionary so that parser will not be confused with
860 * it. See LMRoman10-Regular (lmr10.pfb) for example.
861 */
862 if (seek_operator(start, end, "begin") < 0)
863 return -1;
864
865 while (*start < end &&
866 (key = get_next_key(start, end)) != NULL) {
867 if (!strcmp(key, "Encoding")) {
868 if (parse_encoding(enc_vec, start, end, mode) < 0) {
869 RELEASE(key);
870 return -1;
871 }
872 } else if (!strcmp(key, "FontName")) {
873 argn = parse_svalue(start, end, &strval);
874 CHECK_ARGN_EQ(1);
875 if (strlen(strval) > TYPE1_NAME_LEN_MAX) {
876 WARN("FontName too long: %s (%d bytes)", strval, strlen(strval));
877 strval[TYPE1_NAME_LEN_MAX] = '\0';
878 }
879 cff_set_name(font, strval);
880 RELEASE(strval);
881 } else if (!strcmp(key, "FontType")) {
882 argn = parse_nvalue(start, end, argv, 1);
883 CHECK_ARGN_EQ(1);
884 if (argv[0] != 1.0) {
885 WARN("FontType %d not supported.", (int) argv[0]);
886 RELEASE(key);
887 return -1;
888 }
889#if 0
890 /* DISABLED:
891 *
892 * Subsetted font shouldn't have UniqueID.
893 */
894 } else if (!strcmp(key, "UniqueID")) {
895 argn = parse_nvalue(start, end, argv, 1);
896 CHECK_ARGN_EQ(1);
897 cff_dict_add(font->topdict, key, 1);
898 cff_dict_set(font->topdict, key, 0, argv[0]);
899#endif
900 } else if (!strcmp(key, "ItalicAngle") ||
901 !strcmp(key, "StrokeWidth") ||
902 !strcmp(key, "PaintType")) {
903 argn = parse_nvalue(start, end, argv, 1);
904 CHECK_ARGN_EQ(1);
905 if (argv[0] != 0.0) {
906#if 0
907 /*
908 * Positive value in Bitstream CharterBT-Italic ???
909 */
910 if (!strcmp(key, "ItalicAngle") && argv[0] > 0) {
911 WARN("Positive ItalicAngle value: %g", argv[0]);
912 argv[0] *= -1;
913 }
914#endif
915 cff_dict_add(font->topdict, key, 1);
916 cff_dict_set(font->topdict, key, 0, argv[0]);
917 }
918 } else if (!strcmp(key, "UnderLinePosition") ||
919 !strcmp(key, "UnderLineThickness")) {
920 argn = parse_nvalue(start, end, argv, 1);
921 CHECK_ARGN_EQ(1);
922 cff_dict_add(font->topdict, key, 1);
923 cff_dict_set(font->topdict, key, 0, argv[0]);
924 } else if (!strcmp(key, "FontBBox")) {
925 argn = parse_nvalue(start, end, argv, 4);
926 CHECK_ARGN_EQ(4);
927 cff_dict_add(font->topdict, key, 4);
928 while (argn-- > 0) {
929 cff_dict_set(font->topdict, key, argn, argv[argn]);
930 }
931 } else if (!strcmp(key, "FontMatrix")) {
932 argn = parse_nvalue(start, end, argv, 6);
933 CHECK_ARGN_EQ(6);
934 if (argv[0] != 0.001 || argv[1] != 0.0 || argv[2] != 0.0 ||
935 argv[3] != 0.001 || argv[4] != 0.0 || argv[5] != 0.0) {
936 cff_dict_add(font->topdict, key, 6);
937 while (argn-- > 0) {
938 cff_dict_set(font->topdict, key, argn, argv[argn]);
939 }
940 }
941 } else if (!strcmp(key, "version") || !strcmp(key, "Notice") ||
942 !strcmp(key, "FullName") || !strcmp(key, "FamilyName") ||
943 !strcmp(key, "Weight") || !strcmp(key, "Copyright")) {
944 /*
945 * FontInfo
946 */
947 argn = parse_svalue(start, end, &strval);
948 CHECK_ARGN_EQ(1);
949 {
950 s_SID sid;
951
952 cff_dict_add(font->topdict, key, 1);
953 if ((sid = cff_get_sid(font, strval)) == CFF_STRING_NOTDEF)
954 sid = cff_add_string(font, strval, 0); /* FIXME */
955 /*
956 * We don't care about duplicate strings here since
957 * later a subset font of this font will be generated.
958 */
959 cff_dict_set(font->topdict, key, 0, sid);
960 }
961 RELEASE(strval);
962 } else if (!strcmp(key, "IsFixedPitch")) {
963 argn = parse_bvalue(start, end, &(argv[0]));
964 CHECK_ARGN_EQ(1);
965 if (argv[0] != 0.0) {
966 cff_dict_add(font->private[0], key, 1);
967 cff_dict_set(font->private[0], key, 0, 1);
968 }
969 }
970 RELEASE(key);
971 }
972
973 return 0;
974}
975
976int
977is_pfb (FILE *fp)
978{
979 char sig[15];
980 int i, ch;
981
982 rewind(fp);
983 if ((ch = fgetc(fp)) != 128 ||
984 (ch = fgetc (fp)) < 0 || ch > 3) {
985 return 0;
986 }
987 for (i = 0; i < 4; i++) {
988 if ((ch = fgetc(fp)) < 0) {
989 return 0;
990 }
991 }
992 for (i = 0; i < 14; i++) {
993 if ((ch = fgetc(fp)) < 0) {
994 return 0;
995 }
996 sig[i] = (char) ch;
997 }
998 if (!memcmp(sig, "%!PS-AdobeFont", 14) ||
999 !memcmp(sig, "%!FontType1", 11)) {
1000 return 1;
1001 } else if (!memcmp(sig, "%!PS", 4)) {
1002 sig[14] = '\0';
1003 WARN("Ambiguous PostScript resource type: %s", sig);
1004 return 1;
1005 } else {
1006 WARN("Not a PFB font file?");
1007 return 0;
1008 }
1009
1010 return 0;
1011}
1012
1013
1014#define PFB_SEG_TYPE_ASCII 1
1015#define PFB_SEG_TYPE_BINARY 2
1016
1017static unsigned char *
1018get_pfb_segment (FILE *fp, int expected_type, long *length)
1019{
1020 unsigned char *buffer;
1021 long bytesread;
1022
1023 buffer = NULL; bytesread = 0;
1024 for (;;) {
1025 int ch;
1026
1027 ch = fgetc(fp);
1028 if (ch < 0) {
1029 break;
1030 } else if (ch != 128) {
1031 ERROR("Not a pfb file?");
1032 }
1033 ch = fgetc(fp);
1034 if (ch < 0 || ch != expected_type) {
1035 seek_relative(fp, -2);
1036 break;
1037 }
1038 {
1039 long slen, rlen;
1040 int i;
1041
1042 slen = 0;
1043 for (i = 0; i < 4; i++) {
1044 if ((ch = fgetc(fp)) < 0) {
1045 if (buffer)
1046 RELEASE(buffer);
1047 return NULL;
1048 }
1049 slen = slen + (ch << (8*i));
1050 }
1051 buffer = RENEW(buffer, bytesread + slen, unsigned char);
1052 while (slen > 0) {
1053 rlen = fread(buffer + bytesread, sizeof(unsigned char), slen, fp);
1054 if (rlen < 0) {
1055 if (buffer)
1056 RELEASE(buffer);
1057 return NULL;
1058 }
1059 slen -= rlen;
1060 bytesread += rlen;
1061 }
1062 }
1063 }
1064 if (bytesread == 0) {
1065 ERROR("PFB segment length zero?");
1066 }
1067
1068 buffer = RENEW(buffer, bytesread+1, unsigned char);
1069 buffer[bytesread] = 0;
1070
1071 if (length)
1072 *length = bytesread;
1073 return buffer;
1074}
1075
1076char *
1077t1_get_standard_glyph (int code)
1078{
1079 if (!StandardEncoding[code])
1080 return NULL;
1081
1082 return (char *) StandardEncoding[code];
1083}
1084
1085int
1086t1_get_fontname (FILE *fp, char *fontname)
1087{
1088 unsigned char *buffer, *start, *end;
1089 long length;
1090 char *key;
1091 int fn_found = 0;
1092
1093 rewind(fp);
1094 buffer = get_pfb_segment(fp, PFB_SEG_TYPE_ASCII, &length);
1095 if (buffer == NULL || length == 0)
1096 ERROR("Reading PFB (ASCII part) file failed.");
1097 start = buffer;
1098 end = buffer + length;
1099
1100 if (seek_operator(&start, end, "begin") < 0) {
1101 RELEASE(buffer);
1102 return -1;
1103 }
1104
1105 while (!fn_found && start < end &&
1106 (key = get_next_key(&start, end)) != NULL) {
1107 if (!strcmp(key, "FontName")) {
1108 char *strval;
1109 if (parse_svalue(&start, end, &strval) == 1) {
1110 if (strlen(strval) > TYPE1_NAME_LEN_MAX) {
1111 WARN("FontName \"%s\" too long. (%d bytes)", strval, strlen(strval));
1112 strval[TYPE1_NAME_LEN_MAX] = '\0';
1113 }
1114 strcpy(fontname, strval);
1115 RELEASE(strval);
1116 fn_found = 1;
1117 }
1118 }
1119 RELEASE(key);
1120 }
1121 RELEASE(buffer);
1122
1123 return 0;
1124}
1125
1126static void
1127init_cff_font (cff_font *cff)
1128{
1129 cff->stream = NULL;
1130 cff->filter = 0;
1131 cff->fontname = NULL;
1132 cff->index = 0;
1133 cff->flag = FONTTYPE_FONT;
1134
1135 cff->header.major = 1;
1136 cff->header.minor = 0;
1137 cff->header.hdr_size = 4;
1138 cff->header.offsize = 4;
1139 cff->name = cff_new_index(1);
1140 cff->topdict = cff_new_dict();
1141 cff->string = NULL;
1142 cff->gsubr = cff_new_index(0); /* No Global Subr */
1143 cff->encoding = NULL;
1144 cff->charsets = NULL;
1145 cff->fdselect = NULL;
1146 cff->cstrings = NULL;
1147 cff->fdarray = NULL;
1148 cff->private = NEW(1, cff_dict *);
1149 cff->private[0] = cff_new_dict();
1150 cff->subrs = NEW(1, cff_index *);
1151 cff->subrs[0] = NULL;
1152
1153 cff->offset = 0;
1154 cff->gsubr_offset = 0;
1155 cff->num_glyphs = 0;
1156 cff->num_fds = 1;
1157 cff->_string = cff_new_index(0);
1158}
1159
1160cff_font *
1161t1_load_font (char **enc_vec, int mode, FILE *fp)
1162{
1163 long length;
1164 cff_font *cff;
1165 unsigned char *buffer, *start, *end;
1166
1167 rewind(fp);
1168 /* ASCII section */
1169 buffer = get_pfb_segment(fp, PFB_SEG_TYPE_ASCII, &length);
1170 if (buffer == NULL || length == 0) {
1171 ERROR("Reading PFB (ASCII part) file failed.");
1172 return NULL;
1173 }
1174
1175 cff = NEW(1, cff_font);
1176 init_cff_font(cff);
1177
1178 start = buffer; end = buffer + length;
1179 if (parse_part1(cff, enc_vec, &start, end, mode) < 0) {
1180 cff_close(cff);
1181 RELEASE(buffer);
1182 ERROR("Reading PFB (ASCII part) file failed.");
1183 return NULL;
1184 }
1185 RELEASE(buffer);
1186
1187 /* Binary section */
1188 buffer = get_pfb_segment(fp, PFB_SEG_TYPE_BINARY, &length);
1189 if (buffer == NULL || length == 0) {
1190 cff_close(cff);
1191 RELEASE(buffer);
1192 ERROR("Reading PFB (BINARY part) file failed.");
1193 return NULL;
1194 } else {
1195 t1_decrypt(T1_EEKEY, buffer, buffer, 0, length);
1196 }
1197 start = buffer + 4; end = buffer + length;
1198 if (parse_part2(cff, &start, end, mode) < 0) {
1199 cff_close(cff);
1200 RELEASE(buffer);
1201 ERROR("Reading PFB (BINARY part) file failed.");
1202 return NULL;
1203 }
1204 RELEASE(buffer);
1205
1206 cff_update_string(cff);
1207
1208 /* Remaining section ignored. */
1209
1210 return cff;
1211}