1 //========================================================================
5 // Copyright 2009 Glyph & Cog, LLC
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
30 #include "goo/gtypes.h"
31 #include "FoFiIdentifier.h"
33 //------------------------------------------------------------------------
35 namespace { // do not pollute global namespace
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
{
71 static MemReader
*make(char *bufA
, int lenA
);
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
);
82 MemReader(char *bufA
, int lenA
);
88 MemReader
*MemReader::make(char *bufA
, int lenA
) {
89 return new MemReader(bufA
, lenA
);
92 MemReader::MemReader(char *bufA
, int lenA
) {
97 MemReader::~MemReader() {
100 int MemReader::getByte(int pos
) {
101 if (pos
< 0 || pos
>= len
) {
104 return buf
[pos
] & 0xff;
107 GBool
MemReader::getU16BE(int pos
, int *val
) {
108 if (pos
< 0 || pos
> len
- 2) {
111 *val
= ((buf
[pos
] & 0xff) << 8) +
116 GBool
MemReader::getU32BE(int pos
, Guint
*val
) {
117 if (pos
< 0 || pos
> len
- 4) {
120 *val
= ((buf
[pos
] & 0xff) << 24) +
121 ((buf
[pos
+1] & 0xff) << 16) +
122 ((buf
[pos
+2] & 0xff) << 8) +
127 GBool
MemReader::getU32LE(int pos
, Guint
*val
) {
128 if (pos
< 0 || pos
> len
- 4) {
131 *val
= (buf
[pos
] & 0xff) +
132 ((buf
[pos
+1] & 0xff) << 8) +
133 ((buf
[pos
+2] & 0xff) << 16) +
134 ((buf
[pos
+3] & 0xff) << 24);
138 GBool
MemReader::getUVarBE(int pos
, int size
, Guint
*val
) {
141 if (size
< 1 || size
> 4 || pos
< 0 || pos
> len
- size
) {
145 for (i
= 0; i
< size
; ++i
) {
146 *val
= (*val
<< 8) + (buf
[pos
+ i
] & 0xff);
151 GBool
MemReader::cmp(int pos
, const char *s
) {
155 if (pos
< 0 || len
< n
|| pos
> len
- n
) {
158 return !memcmp(buf
+ pos
, s
, n
);
161 //------------------------------------------------------------------------
163 class FileReader
: public Reader
{
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
);
177 FileReader(FILE *fA
);
178 GBool
fillBuf(int pos
, int len
);
185 FileReader
*FileReader::make(char *fileName
) {
188 if (!(fA
= fopen(fileName
, "rb"))) {
191 return new FileReader(fA
);
194 FileReader::FileReader(FILE *fA
) {
200 FileReader::~FileReader() {
204 int FileReader::getByte(int pos
) {
205 if (!fillBuf(pos
, 1)) {
208 return buf
[pos
- bufPos
] & 0xff;
211 GBool
FileReader::getU16BE(int pos
, int *val
) {
212 if (!fillBuf(pos
, 2)) {
215 *val
= ((buf
[pos
- bufPos
] & 0xff) << 8) +
216 (buf
[pos
- bufPos
+ 1] & 0xff);
220 GBool
FileReader::getU32BE(int pos
, Guint
*val
) {
221 if (!fillBuf(pos
, 4)) {
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);
231 GBool
FileReader::getU32LE(int pos
, Guint
*val
) {
232 if (!fillBuf(pos
, 4)) {
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);
242 GBool
FileReader::getUVarBE(int pos
, int size
, Guint
*val
) {
245 if (size
< 1 || size
> 4 || !fillBuf(pos
, size
)) {
249 for (i
= 0; i
< size
; ++i
) {
250 *val
= (*val
<< 8) + (buf
[pos
- bufPos
+ i
] & 0xff);
255 GBool
FileReader::cmp(int pos
, const char *s
) {
259 if (!fillBuf(pos
, n
)) {
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
)) {
270 if (pos
>= bufPos
&& pos
+ len
<= bufPos
+ bufLen
) {
273 if (fseek(f
, pos
, SEEK_SET
)) {
277 bufLen
= (int)fread(buf
, 1, sizeof(buf
), f
);
284 //------------------------------------------------------------------------
286 class StreamReader
: public Reader
{
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
);
300 StreamReader(int (*getCharA
)(void *data
), void *dataA
);
301 GBool
fillBuf(int pos
, int len
);
303 int (*getChar
)(void *data
);
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
) {
322 StreamReader::~StreamReader() {
325 int StreamReader::getByte(int pos
) {
326 if (!fillBuf(pos
, 1)) {
329 return buf
[pos
- bufPos
] & 0xff;
332 GBool
StreamReader::getU16BE(int pos
, int *val
) {
333 if (!fillBuf(pos
, 2)) {
336 *val
= ((buf
[pos
- bufPos
] & 0xff) << 8) +
337 (buf
[pos
- bufPos
+ 1] & 0xff);
341 GBool
StreamReader::getU32BE(int pos
, Guint
*val
) {
342 if (!fillBuf(pos
, 4)) {
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);
352 GBool
StreamReader::getU32LE(int pos
, Guint
*val
) {
353 if (!fillBuf(pos
, 4)) {
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);
363 GBool
StreamReader::getUVarBE(int pos
, int size
, Guint
*val
) {
366 if (size
< 1 || size
> 4 || !fillBuf(pos
, size
)) {
370 for (i
= 0; i
< size
; ++i
) {
371 *val
= (*val
<< 8) + (buf
[pos
- bufPos
+ i
] & 0xff);
376 GBool
StreamReader::cmp(int pos
, const char *s
) {
380 if (!fillBuf(pos
, n
)) {
383 return !memcmp(buf
- bufPos
+ pos
, s
, n
);
386 GBool
StreamReader::fillBuf(int pos
, int len
) {
389 if (pos
< 0 || len
< 0 || len
> (int)sizeof(buf
) ||
390 pos
> INT_MAX
- (int)sizeof(buf
)) {
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
);
407 // otherwise discard data from the
408 // stream until we get to the requested position
412 while (bufPos
< pos
) {
413 if ((c
= (*getChar
)(data
)) < 0) {
421 // read the rest of the requested data
422 while (bufPos
+ bufLen
< pos
+ len
) {
423 if ((c
= (*getChar
)(data
)) < 0) {
426 buf
[bufLen
++] = (char)c
;
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
) {
442 FoFiIdentifierType type
;
444 if (!(reader
= MemReader::make(file
, len
))) {
447 type
= identify(reader
);
452 FoFiIdentifierType
FoFiIdentifier::identifyFile(char *fileName
) {
454 FoFiIdentifierType type
;
456 if (!(reader
= FileReader::make(fileName
))) {
459 type
= identify(reader
);
464 FoFiIdentifierType
FoFiIdentifier::identifyStream(int (*getChar
)(void *data
),
466 StreamReader
*reader
;
467 FoFiIdentifierType type
;
469 if (!(reader
= StreamReader::make(getChar
, data
))) {
472 type
= identify(reader
);
477 static FoFiIdentifierType
identify(Reader
*reader
) {
481 if (reader
->cmp(0, "%!PS-AdobeFont-1") ||
482 reader
->cmp(0, "%!FontType1")) {
483 return fofiIdType1PFA
;
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
;
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
;
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
);
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
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
;
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
;
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
;
580 return fofiIdUnknown
;
583 //----- skip the name index
584 if (!reader
->getU16BE(pos
, &n
)) {
585 return fofiIdUnknown
;
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;
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
||
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
++);
630 } else if (b0
== 0x1d) {
632 } else if (b0
>= 0xf7 && b0
<= 0xfe) {
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) {
646 return fofiIdCFF8Bit
;