beta-0.89.2
[luatex.git] / source / libs / poppler / poppler-src / fofi / FoFiIdentifier.cc
blobbe28e2568ebb5bb253458b1113ddbb3dee8a654a
1 //========================================================================
2 //
3 // FoFiIdentifier.cc
4 //
5 // Copyright 2009 Glyph & Cog, LLC
6 //
7 //========================================================================
9 //========================================================================
11 // Modified under the Poppler project - http://poppler.freedesktop.org
13 // All changes made under the Poppler project to this file are licensed
14 // under GPL version 2 or later
16 // Copyright (C) 2013 Christoph Duelli <duelli@melosgmbh.de>
18 // To see a description of the changes please see the Changelog file that
19 // came with your tarball or type make ChangeLog if you are building from git
21 //========================================================================
23 #ifdef USE_GCC_PRAGMAS
24 #pragma implementation
25 #endif
27 #include <stdio.h>
28 #include <string.h>
29 #include <limits.h>
30 #include "goo/gtypes.h"
31 #include "FoFiIdentifier.h"
33 //------------------------------------------------------------------------
35 namespace { // do not pollute global namespace
37 class Reader {
38 public:
40 virtual ~Reader() {}
42 // Read one byte. Returns -1 if past EOF.
43 virtual int getByte(int pos) = 0;
45 // Read a big-endian unsigned 16-bit integer. Fills in *val and
46 // returns true if successful.
47 virtual GBool getU16BE(int pos, int *val) = 0;
49 // Read a big-endian unsigned 32-bit integer. Fills in *val and
50 // returns true if successful.
51 virtual GBool getU32BE(int pos, Guint *val) = 0;
53 // Read a little-endian unsigned 32-bit integer. Fills in *val and
54 // returns true if successful.
55 virtual GBool getU32LE(int pos, Guint *val) = 0;
57 // Read a big-endian unsigned <size>-byte integer, where 1 <= size
58 // <= 4. Fills in *val and returns true if successful.
59 virtual GBool getUVarBE(int pos, int size, Guint *val) = 0;
61 // Compare against a string. Returns true if equal.
62 virtual GBool cmp(int pos, const char *s) = 0;
66 //------------------------------------------------------------------------
68 class MemReader: public Reader {
69 public:
71 static MemReader *make(char *bufA, int lenA);
72 virtual ~MemReader();
73 virtual int getByte(int pos);
74 virtual GBool getU16BE(int pos, int *val);
75 virtual GBool getU32BE(int pos, Guint *val);
76 virtual GBool getU32LE(int pos, Guint *val);
77 virtual GBool getUVarBE(int pos, int size, Guint *val);
78 virtual GBool cmp(int pos, const char *s);
80 private:
82 MemReader(char *bufA, int lenA);
84 char *buf;
85 int len;
88 MemReader *MemReader::make(char *bufA, int lenA) {
89 return new MemReader(bufA, lenA);
92 MemReader::MemReader(char *bufA, int lenA) {
93 buf = bufA;
94 len = lenA;
97 MemReader::~MemReader() {
100 int MemReader::getByte(int pos) {
101 if (pos < 0 || pos >= len) {
102 return -1;
104 return buf[pos] & 0xff;
107 GBool MemReader::getU16BE(int pos, int *val) {
108 if (pos < 0 || pos > len - 2) {
109 return gFalse;
111 *val = ((buf[pos] & 0xff) << 8) +
112 (buf[pos+1] & 0xff);
113 return gTrue;
116 GBool MemReader::getU32BE(int pos, Guint *val) {
117 if (pos < 0 || pos > len - 4) {
118 return gFalse;
120 *val = ((buf[pos] & 0xff) << 24) +
121 ((buf[pos+1] & 0xff) << 16) +
122 ((buf[pos+2] & 0xff) << 8) +
123 (buf[pos+3] & 0xff);
124 return gTrue;
127 GBool MemReader::getU32LE(int pos, Guint *val) {
128 if (pos < 0 || pos > len - 4) {
129 return gFalse;
131 *val = (buf[pos] & 0xff) +
132 ((buf[pos+1] & 0xff) << 8) +
133 ((buf[pos+2] & 0xff) << 16) +
134 ((buf[pos+3] & 0xff) << 24);
135 return gTrue;
138 GBool MemReader::getUVarBE(int pos, int size, Guint *val) {
139 int i;
141 if (size < 1 || size > 4 || pos < 0 || pos > len - size) {
142 return gFalse;
144 *val = 0;
145 for (i = 0; i < size; ++i) {
146 *val = (*val << 8) + (buf[pos + i] & 0xff);
148 return gTrue;
151 GBool MemReader::cmp(int pos, const char *s) {
152 int n;
154 n = (int)strlen(s);
155 if (pos < 0 || len < n || pos > len - n) {
156 return gFalse;
158 return !memcmp(buf + pos, s, n);
161 //------------------------------------------------------------------------
163 class FileReader: public Reader {
164 public:
166 static FileReader *make(char *fileName);
167 virtual ~FileReader();
168 virtual int getByte(int pos);
169 virtual GBool getU16BE(int pos, int *val);
170 virtual GBool getU32BE(int pos, Guint *val);
171 virtual GBool getU32LE(int pos, Guint *val);
172 virtual GBool getUVarBE(int pos, int size, Guint *val);
173 virtual GBool cmp(int pos, const char *s);
175 private:
177 FileReader(FILE *fA);
178 GBool fillBuf(int pos, int len);
180 FILE *f;
181 char buf[1024];
182 int bufPos, bufLen;
185 FileReader *FileReader::make(char *fileName) {
186 FILE *fA;
188 if (!(fA = fopen(fileName, "rb"))) {
189 return NULL;
191 return new FileReader(fA);
194 FileReader::FileReader(FILE *fA) {
195 f = fA;
196 bufPos = 0;
197 bufLen = 0;
200 FileReader::~FileReader() {
201 fclose(f);
204 int FileReader::getByte(int pos) {
205 if (!fillBuf(pos, 1)) {
206 return -1;
208 return buf[pos - bufPos] & 0xff;
211 GBool FileReader::getU16BE(int pos, int *val) {
212 if (!fillBuf(pos, 2)) {
213 return gFalse;
215 *val = ((buf[pos - bufPos] & 0xff) << 8) +
216 (buf[pos - bufPos + 1] & 0xff);
217 return gTrue;
220 GBool FileReader::getU32BE(int pos, Guint *val) {
221 if (!fillBuf(pos, 4)) {
222 return gFalse;
224 *val = ((buf[pos - bufPos] & 0xff) << 24) +
225 ((buf[pos - bufPos + 1] & 0xff) << 16) +
226 ((buf[pos - bufPos + 2] & 0xff) << 8) +
227 (buf[pos - bufPos + 3] & 0xff);
228 return gTrue;
231 GBool FileReader::getU32LE(int pos, Guint *val) {
232 if (!fillBuf(pos, 4)) {
233 return gFalse;
235 *val = (buf[pos - bufPos] & 0xff) +
236 ((buf[pos - bufPos + 1] & 0xff) << 8) +
237 ((buf[pos - bufPos + 2] & 0xff) << 16) +
238 ((buf[pos - bufPos + 3] & 0xff) << 24);
239 return gTrue;
242 GBool FileReader::getUVarBE(int pos, int size, Guint *val) {
243 int i;
245 if (size < 1 || size > 4 || !fillBuf(pos, size)) {
246 return gFalse;
248 *val = 0;
249 for (i = 0; i < size; ++i) {
250 *val = (*val << 8) + (buf[pos - bufPos + i] & 0xff);
252 return gTrue;
255 GBool FileReader::cmp(int pos, const char *s) {
256 int n;
258 n = (int)strlen(s);
259 if (!fillBuf(pos, n)) {
260 return gFalse;
262 return !memcmp(buf - bufPos + pos, s, n);
265 GBool FileReader::fillBuf(int pos, int len) {
266 if (pos < 0 || len < 0 || len > (int)sizeof(buf) ||
267 pos > INT_MAX - (int)sizeof(buf)) {
268 return gFalse;
270 if (pos >= bufPos && pos + len <= bufPos + bufLen) {
271 return gTrue;
273 if (fseek(f, pos, SEEK_SET)) {
274 return gFalse;
276 bufPos = pos;
277 bufLen = (int)fread(buf, 1, sizeof(buf), f);
278 if (bufLen < len) {
279 return gFalse;
281 return gTrue;
284 //------------------------------------------------------------------------
286 class StreamReader: public Reader {
287 public:
289 static StreamReader *make(int (*getCharA)(void *data), void *dataA);
290 virtual ~StreamReader();
291 virtual int getByte(int pos);
292 virtual GBool getU16BE(int pos, int *val);
293 virtual GBool getU32BE(int pos, Guint *val);
294 virtual GBool getU32LE(int pos, Guint *val);
295 virtual GBool getUVarBE(int pos, int size, Guint *val);
296 virtual GBool cmp(int pos, const char *s);
298 private:
300 StreamReader(int (*getCharA)(void *data), void *dataA);
301 GBool fillBuf(int pos, int len);
303 int (*getChar)(void *data);
304 void *data;
305 int streamPos;
306 char buf[1024];
307 int bufPos, bufLen;
310 StreamReader *StreamReader::make(int (*getCharA)(void *data), void *dataA) {
311 return new StreamReader(getCharA, dataA);
314 StreamReader::StreamReader(int (*getCharA)(void *data), void *dataA) {
315 getChar = getCharA;
316 data = dataA;
317 streamPos = 0;
318 bufPos = 0;
319 bufLen = 0;
322 StreamReader::~StreamReader() {
325 int StreamReader::getByte(int pos) {
326 if (!fillBuf(pos, 1)) {
327 return -1;
329 return buf[pos - bufPos] & 0xff;
332 GBool StreamReader::getU16BE(int pos, int *val) {
333 if (!fillBuf(pos, 2)) {
334 return gFalse;
336 *val = ((buf[pos - bufPos] & 0xff) << 8) +
337 (buf[pos - bufPos + 1] & 0xff);
338 return gTrue;
341 GBool StreamReader::getU32BE(int pos, Guint *val) {
342 if (!fillBuf(pos, 4)) {
343 return gFalse;
345 *val = ((buf[pos - bufPos] & 0xff) << 24) +
346 ((buf[pos - bufPos + 1] & 0xff) << 16) +
347 ((buf[pos - bufPos + 2] & 0xff) << 8) +
348 (buf[pos - bufPos + 3] & 0xff);
349 return gTrue;
352 GBool StreamReader::getU32LE(int pos, Guint *val) {
353 if (!fillBuf(pos, 4)) {
354 return gFalse;
356 *val = (buf[pos - bufPos] & 0xff) +
357 ((buf[pos - bufPos + 1] & 0xff) << 8) +
358 ((buf[pos - bufPos + 2] & 0xff) << 16) +
359 ((buf[pos - bufPos + 3] & 0xff) << 24);
360 return gTrue;
363 GBool StreamReader::getUVarBE(int pos, int size, Guint *val) {
364 int i;
366 if (size < 1 || size > 4 || !fillBuf(pos, size)) {
367 return gFalse;
369 *val = 0;
370 for (i = 0; i < size; ++i) {
371 *val = (*val << 8) + (buf[pos - bufPos + i] & 0xff);
373 return gTrue;
376 GBool StreamReader::cmp(int pos, const char *s) {
377 int n;
379 n = (int)strlen(s);
380 if (!fillBuf(pos, n)) {
381 return gFalse;
383 return !memcmp(buf - bufPos + pos, s, n);
386 GBool StreamReader::fillBuf(int pos, int len) {
387 int c;
389 if (pos < 0 || len < 0 || len > (int)sizeof(buf) ||
390 pos > INT_MAX - (int)sizeof(buf)) {
391 return gFalse;
393 if (pos < bufPos) {
394 return gFalse;
397 // if requested region will not fit in the current buffer...
398 if (pos + len > bufPos + (int)sizeof(buf)) {
400 // if the start of the requested data is already in the buffer, move
401 // it to the start of the buffer
402 if (pos < bufPos + bufLen) {
403 bufLen -= pos - bufPos;
404 memmove(buf, buf + (pos - bufPos), bufLen);
405 bufPos = pos;
407 // otherwise discard data from the
408 // stream until we get to the requested position
409 } else {
410 bufPos += bufLen;
411 bufLen = 0;
412 while (bufPos < pos) {
413 if ((c = (*getChar)(data)) < 0) {
414 return gFalse;
416 ++bufPos;
421 // read the rest of the requested data
422 while (bufPos + bufLen < pos + len) {
423 if ((c = (*getChar)(data)) < 0) {
424 return gFalse;
426 buf[bufLen++] = (char)c;
429 return gTrue;
434 //------------------------------------------------------------------------
436 static FoFiIdentifierType identify(Reader *reader);
437 static FoFiIdentifierType identifyOpenType(Reader *reader);
438 static FoFiIdentifierType identifyCFF(Reader *reader, int start);
440 FoFiIdentifierType FoFiIdentifier::identifyMem(char *file, int len) {
441 MemReader *reader;
442 FoFiIdentifierType type;
444 if (!(reader = MemReader::make(file, len))) {
445 return fofiIdError;
447 type = identify(reader);
448 delete reader;
449 return type;
452 FoFiIdentifierType FoFiIdentifier::identifyFile(char *fileName) {
453 FileReader *reader;
454 FoFiIdentifierType type;
456 if (!(reader = FileReader::make(fileName))) {
457 return fofiIdError;
459 type = identify(reader);
460 delete reader;
461 return type;
464 FoFiIdentifierType FoFiIdentifier::identifyStream(int (*getChar)(void *data),
465 void *data) {
466 StreamReader *reader;
467 FoFiIdentifierType type;
469 if (!(reader = StreamReader::make(getChar, data))) {
470 return fofiIdError;
472 type = identify(reader);
473 delete reader;
474 return type;
477 static FoFiIdentifierType identify(Reader *reader) {
478 Guint n;
480 //----- PFA
481 if (reader->cmp(0, "%!PS-AdobeFont-1") ||
482 reader->cmp(0, "%!FontType1")) {
483 return fofiIdType1PFA;
486 //----- PFB
487 if (reader->getByte(0) == 0x80 &&
488 reader->getByte(1) == 0x01 &&
489 reader->getU32LE(2, &n)) {
490 if ((n >= 16 && reader->cmp(6, "%!PS-AdobeFont-1")) ||
491 (n >= 11 && reader->cmp(6, "%!FontType1"))) {
492 return fofiIdType1PFB;
496 //----- TrueType
497 if ((reader->getByte(0) == 0x00 &&
498 reader->getByte(1) == 0x01 &&
499 reader->getByte(2) == 0x00 &&
500 reader->getByte(3) == 0x00) ||
501 (reader->getByte(0) == 0x74 && // 'true'
502 reader->getByte(1) == 0x72 &&
503 reader->getByte(2) == 0x75 &&
504 reader->getByte(3) == 0x65)) {
505 return fofiIdTrueType;
507 if (reader->getByte(0) == 0x74 && // 'ttcf'
508 reader->getByte(1) == 0x74 &&
509 reader->getByte(2) == 0x63 &&
510 reader->getByte(3) == 0x66) {
511 return fofiIdTrueTypeCollection;
514 //----- OpenType
515 if (reader->getByte(0) == 0x4f && // 'OTTO
516 reader->getByte(1) == 0x54 &&
517 reader->getByte(2) == 0x54 &&
518 reader->getByte(3) == 0x4f) {
519 return identifyOpenType(reader);
522 //----- CFF
523 if (reader->getByte(0) == 0x01 &&
524 reader->getByte(1) == 0x00) {
525 return identifyCFF(reader, 0);
527 // some tools embed CFF fonts with an extra whitespace char at the
528 // beginning
529 if (reader->getByte(1) == 0x01 &&
530 reader->getByte(2) == 0x00) {
531 return identifyCFF(reader, 1);
534 return fofiIdUnknown;
537 static FoFiIdentifierType identifyOpenType(Reader *reader) {
538 FoFiIdentifierType type;
539 Guint offset;
540 int nTables, i;
542 if (!reader->getU16BE(4, &nTables)) {
543 return fofiIdUnknown;
545 for (i = 0; i < nTables; ++i) {
546 if (reader->cmp(12 + i*16, "CFF ")) {
547 if (reader->getU32BE(12 + i*16 + 8, &offset) &&
548 offset < (Guint)INT_MAX) {
549 type = identifyCFF(reader, (int)offset);
550 if (type == fofiIdCFF8Bit) {
551 type = fofiIdOpenTypeCFF8Bit;
552 } else if (type == fofiIdCFFCID) {
553 type = fofiIdOpenTypeCFFCID;
555 return type;
557 return fofiIdUnknown;
560 return fofiIdUnknown;
563 static FoFiIdentifierType identifyCFF(Reader *reader, int start) {
564 Guint offset0, offset1;
565 int hdrSize, offSize0, offSize1, pos, endPos, b0, n, i;
567 //----- read the header
568 if (reader->getByte(start) != 0x01 ||
569 reader->getByte(start + 1) != 0x00) {
570 return fofiIdUnknown;
572 if ((hdrSize = reader->getByte(start + 2)) < 0) {
573 return fofiIdUnknown;
575 if ((offSize0 = reader->getByte(start + 3)) < 1 || offSize0 > 4) {
576 return fofiIdUnknown;
578 pos = start + hdrSize;
579 if (pos < 0) {
580 return fofiIdUnknown;
583 //----- skip the name index
584 if (!reader->getU16BE(pos, &n)) {
585 return fofiIdUnknown;
587 if (n == 0) {
588 pos += 2;
589 } else {
590 if ((offSize1 = reader->getByte(pos + 2)) < 1 || offSize1 > 4) {
591 return fofiIdUnknown;
593 if (!reader->getUVarBE(pos + 3 + n * offSize1, offSize1, &offset1) ||
594 offset1 > (Guint)INT_MAX) {
595 return fofiIdUnknown;
597 pos += 3 + (n + 1) * offSize1 + (int)offset1 - 1;
599 if (pos < 0) {
600 return fofiIdUnknown;
603 //----- parse the top dict index
604 if (!reader->getU16BE(pos, &n) || n < 1) {
605 return fofiIdUnknown;
607 if ((offSize1 = reader->getByte(pos + 2)) < 1 || offSize1 > 4) {
608 return fofiIdUnknown;
610 if (!reader->getUVarBE(pos + 3, offSize1, &offset0) ||
611 offset0 > (Guint)INT_MAX ||
612 !reader->getUVarBE(pos + 3 + offSize1, offSize1, &offset1) ||
613 offset1 > (Guint)INT_MAX ||
614 offset0 > offset1) {
615 return fofiIdUnknown;
617 pos = pos + 3 + (n + 1) * offSize1 + (int)offset0 - 1;
618 endPos = pos + 3 + (n + 1) * offSize1 + (int)offset1 - 1;
619 if (pos < 0 || endPos < 0 || pos > endPos) {
620 return fofiIdUnknown;
623 //----- parse the top dict, look for ROS as first entry
624 // for a CID font, the top dict starts with:
625 // <int> <int> <int> ROS
626 for (i = 0; i < 3; ++i) {
627 b0 = reader->getByte(pos++);
628 if (b0 == 0x1c) {
629 pos += 2;
630 } else if (b0 == 0x1d) {
631 pos += 4;
632 } else if (b0 >= 0xf7 && b0 <= 0xfe) {
633 pos += 1;
634 } else if (b0 < 0x20 || b0 > 0xf6) {
635 return fofiIdCFF8Bit;
637 if (pos >= endPos || pos < 0) {
638 return fofiIdCFF8Bit;
641 if (pos + 1 < endPos &&
642 reader->getByte(pos) == 12 &&
643 reader->getByte(pos + 1) == 30) {
644 return fofiIdCFFCID;
645 } else {
646 return fofiIdCFF8Bit;