source: trunk/poppler/mypoppler/fofi/FoFiIdentifier.cc @ 515

Last change on this file since 515 was 515, checked in by Silvan Scherrer, 9 years ago

updated poppler to 0.20.3

File size: 14.7 KB
Line 
1//========================================================================
2//
3// FoFiIdentifier.cc
4//
5// Copyright 2009 Glyph & Cog, LLC
6//
7//========================================================================
8
9#ifdef USE_GCC_PRAGMAS
10#pragma implementation
11#endif
12
13#include <stdio.h>
14#include <string.h>
15#include <limits.h>
16#include "goo/gtypes.h"
17#include "FoFiIdentifier.h"
18
19//------------------------------------------------------------------------
20
21class Reader {
22public:
23
24  virtual ~Reader() {}
25
26  // Read one byte.  Returns -1 if past EOF.
27  virtual int getByte(int pos) = 0;
28
29  // Read a big-endian unsigned 16-bit integer.  Fills in *val and
30  // returns true if successful.
31  virtual GBool getU16BE(int pos, int *val) = 0;
32
33  // Read a big-endian unsigned 32-bit integer.  Fills in *val and
34  // returns true if successful.
35  virtual GBool getU32BE(int pos, Guint *val) = 0;
36
37  // Read a little-endian unsigned 32-bit integer.  Fills in *val and
38  // returns true if successful.
39  virtual GBool getU32LE(int pos, Guint *val) = 0;
40
41  // Read a big-endian unsigned <size>-byte integer, where 1 <= size
42  // <= 4.  Fills in *val and returns true if successful.
43  virtual GBool getUVarBE(int pos, int size, Guint *val) = 0;
44
45  // Compare against a string.  Returns true if equal.
46  virtual GBool cmp(int pos, const char *s) = 0;
47
48};
49
50//------------------------------------------------------------------------
51
52class MemReader: public Reader {
53public:
54
55  static MemReader *make(char *bufA, int lenA);
56  virtual ~MemReader();
57  virtual int getByte(int pos);
58  virtual GBool getU16BE(int pos, int *val);
59  virtual GBool getU32BE(int pos, Guint *val);
60  virtual GBool getU32LE(int pos, Guint *val);
61  virtual GBool getUVarBE(int pos, int size, Guint *val);
62  virtual GBool cmp(int pos, const char *s);
63
64private:
65
66  MemReader(char *bufA, int lenA);
67
68  char *buf;
69  int len;
70};
71
72MemReader *MemReader::make(char *bufA, int lenA) {
73  return new MemReader(bufA, lenA);
74}
75
76MemReader::MemReader(char *bufA, int lenA) {
77  buf = bufA;
78  len = lenA;
79}
80
81MemReader::~MemReader() {
82}
83
84int MemReader::getByte(int pos) {
85  if (pos < 0 || pos >= len) {
86    return -1;
87  }
88  return buf[pos] & 0xff;
89}
90
91GBool MemReader::getU16BE(int pos, int *val) {
92  if (pos < 0 || pos > len - 2) {
93    return gFalse;
94  }
95  *val = ((buf[pos] & 0xff) << 8) +
96         (buf[pos+1] & 0xff);
97  return gTrue;
98}
99
100GBool MemReader::getU32BE(int pos, Guint *val) {
101  if (pos < 0 || pos > len - 4) {
102    return gFalse;
103  }
104  *val = ((buf[pos] & 0xff) << 24) +
105         ((buf[pos+1] & 0xff) << 16) +
106         ((buf[pos+2] & 0xff) << 8) +
107         (buf[pos+3] & 0xff);
108  return gTrue;
109}
110
111GBool MemReader::getU32LE(int pos, Guint *val) {
112  if (pos < 0 || pos > len - 4) {
113    return gFalse;
114  }
115  *val = (buf[pos] & 0xff) +
116         ((buf[pos+1] & 0xff) << 8) +
117         ((buf[pos+2] & 0xff) << 16) +
118         ((buf[pos+3] & 0xff) << 24);
119  return gTrue;
120}
121
122GBool MemReader::getUVarBE(int pos, int size, Guint *val) {
123  int i;
124
125  if (size < 1 || size > 4 || pos < 0 || pos > len - size) {
126    return gFalse;
127  }
128  *val = 0;
129  for (i = 0; i < size; ++i) {
130    *val = (*val << 8) + (buf[pos + i] & 0xff);
131  }
132  return gTrue;
133}
134
135GBool MemReader::cmp(int pos, const char *s) {
136  int n;
137
138  n = (int)strlen(s);
139  if (pos < 0 || len < n || pos > len - n) {
140    return gFalse;
141  }
142  return !memcmp(buf + pos, s, n);
143}
144
145//------------------------------------------------------------------------
146
147class FileReader: public Reader {
148public:
149
150  static FileReader *make(char *fileName);
151  virtual ~FileReader();
152  virtual int getByte(int pos);
153  virtual GBool getU16BE(int pos, int *val);
154  virtual GBool getU32BE(int pos, Guint *val);
155  virtual GBool getU32LE(int pos, Guint *val);
156  virtual GBool getUVarBE(int pos, int size, Guint *val);
157  virtual GBool cmp(int pos, const char *s);
158
159private:
160
161  FileReader(FILE *fA);
162  GBool fillBuf(int pos, int len);
163
164  FILE *f;
165  char buf[1024];
166  int bufPos, bufLen;
167};
168
169FileReader *FileReader::make(char *fileName) {
170  FILE *fA;
171
172  if (!(fA = fopen(fileName, "rb"))) {
173    return NULL;
174  }
175  return new FileReader(fA);
176}
177
178FileReader::FileReader(FILE *fA) {
179  f = fA;
180  bufPos = 0;
181  bufLen = 0;
182}
183
184FileReader::~FileReader() {
185  fclose(f);
186}
187
188int FileReader::getByte(int pos) {
189  if (!fillBuf(pos, 1)) {
190    return -1;
191  }
192  return buf[pos - bufPos] & 0xff;
193}
194
195GBool FileReader::getU16BE(int pos, int *val) {
196  if (!fillBuf(pos, 2)) {
197    return gFalse;
198  }
199  *val = ((buf[pos - bufPos] & 0xff) << 8) +
200         (buf[pos - bufPos + 1] & 0xff);
201  return gTrue;
202}
203
204GBool FileReader::getU32BE(int pos, Guint *val) {
205  if (!fillBuf(pos, 4)) {
206    return gFalse;
207  }
208  *val = ((buf[pos - bufPos] & 0xff) << 24) +
209         ((buf[pos - bufPos + 1] & 0xff) << 16) +
210         ((buf[pos - bufPos + 2] & 0xff) << 8) +
211         (buf[pos - bufPos + 3] & 0xff);
212  return gTrue;
213}
214
215GBool FileReader::getU32LE(int pos, Guint *val) {
216  if (!fillBuf(pos, 4)) {
217    return gFalse;
218  }
219  *val = (buf[pos - bufPos] & 0xff) +
220         ((buf[pos - bufPos + 1] & 0xff) << 8) +
221         ((buf[pos - bufPos + 2] & 0xff) << 16) +
222         ((buf[pos - bufPos + 3] & 0xff) << 24);
223  return gTrue;
224}
225
226GBool FileReader::getUVarBE(int pos, int size, Guint *val) {
227  int i;
228
229  if (size < 1 || size > 4 || !fillBuf(pos, size)) {
230    return gFalse;
231  }
232  *val = 0;
233  for (i = 0; i < size; ++i) {
234    *val = (*val << 8) + (buf[pos - bufPos + i] & 0xff);
235  }
236  return gTrue;
237}
238
239GBool FileReader::cmp(int pos, const char *s) {
240  int n;
241
242  n = (int)strlen(s);
243  if (!fillBuf(pos, n)) {
244    return gFalse;
245  }
246  return !memcmp(buf - bufPos + pos, s, n);
247}
248
249GBool FileReader::fillBuf(int pos, int len) {
250  if (pos < 0 || len < 0 || len > (int)sizeof(buf) ||
251      pos > INT_MAX - (int)sizeof(buf)) {
252    return gFalse;
253  }
254  if (pos >= bufPos && pos + len <= bufPos + bufLen) {
255    return gTrue;
256  }
257  if (fseek(f, pos, SEEK_SET)) {
258    return gFalse;
259  }
260  bufPos = pos;
261  bufLen = (int)fread(buf, 1, sizeof(buf), f);
262  if (bufLen < len) {
263    return gFalse;
264  }
265  return gTrue;
266}
267
268//------------------------------------------------------------------------
269
270class StreamReader: public Reader {
271public:
272
273  static StreamReader *make(int (*getCharA)(void *data), void *dataA);
274  virtual ~StreamReader();
275  virtual int getByte(int pos);
276  virtual GBool getU16BE(int pos, int *val);
277  virtual GBool getU32BE(int pos, Guint *val);
278  virtual GBool getU32LE(int pos, Guint *val);
279  virtual GBool getUVarBE(int pos, int size, Guint *val);
280  virtual GBool cmp(int pos, const char *s);
281
282private:
283
284  StreamReader(int (*getCharA)(void *data), void *dataA);
285  GBool fillBuf(int pos, int len);
286
287  int (*getChar)(void *data);
288  void *data;
289  int streamPos;
290  char buf[1024];
291  int bufPos, bufLen;
292};
293
294StreamReader *StreamReader::make(int (*getCharA)(void *data), void *dataA) {
295  return new StreamReader(getCharA, dataA);
296}
297
298StreamReader::StreamReader(int (*getCharA)(void *data), void *dataA) {
299  getChar = getCharA;
300  data = dataA;
301  streamPos = 0;
302  bufPos = 0;
303  bufLen = 0;
304}
305
306StreamReader::~StreamReader() {
307}
308
309int StreamReader::getByte(int pos) {
310  if (!fillBuf(pos, 1)) {
311    return -1;
312  }
313  return buf[pos - bufPos] & 0xff;
314}
315
316GBool StreamReader::getU16BE(int pos, int *val) {
317  if (!fillBuf(pos, 2)) {
318    return gFalse;
319  }
320  *val = ((buf[pos - bufPos] & 0xff) << 8) +
321         (buf[pos - bufPos + 1] & 0xff);
322  return gTrue;
323}
324
325GBool StreamReader::getU32BE(int pos, Guint *val) {
326  if (!fillBuf(pos, 4)) {
327    return gFalse;
328  }
329  *val = ((buf[pos - bufPos] & 0xff) << 24) +
330         ((buf[pos - bufPos + 1] & 0xff) << 16) +
331         ((buf[pos - bufPos + 2] & 0xff) << 8) +
332         (buf[pos - bufPos + 3] & 0xff);
333  return gTrue;
334}
335
336GBool StreamReader::getU32LE(int pos, Guint *val) {
337  if (!fillBuf(pos, 4)) {
338    return gFalse;
339  }
340  *val = (buf[pos - bufPos] & 0xff) +
341         ((buf[pos - bufPos + 1] & 0xff) << 8) +
342         ((buf[pos - bufPos + 2] & 0xff) << 16) +
343         ((buf[pos - bufPos + 3] & 0xff) << 24);
344  return gTrue;
345}
346
347GBool StreamReader::getUVarBE(int pos, int size, Guint *val) {
348  int i;
349
350  if (size < 1 || size > 4 || !fillBuf(pos, size)) {
351    return gFalse;
352  }
353  *val = 0;
354  for (i = 0; i < size; ++i) {
355    *val = (*val << 8) + (buf[pos - bufPos + i] & 0xff);
356  }
357  return gTrue;
358}
359
360GBool StreamReader::cmp(int pos, const char *s) {
361  int n;
362
363  n = (int)strlen(s);
364  if (!fillBuf(pos, n)) {
365    return gFalse;
366  }
367  return !memcmp(buf - bufPos + pos, s, n);
368}
369
370GBool StreamReader::fillBuf(int pos, int len) {
371  int c;
372
373  if (pos < 0 || len < 0 || len > (int)sizeof(buf) ||
374      pos > INT_MAX - (int)sizeof(buf)) {
375    return gFalse;
376  }
377  if (pos < bufPos) {
378    return gFalse;
379  }
380
381  // if requested region will not fit in the current buffer...
382  if (pos + len > bufPos + (int)sizeof(buf)) {
383
384    // if the start of the requested data is already in the buffer, move
385    // it to the start of the buffer
386    if (pos < bufPos + bufLen) {
387      bufLen -= pos - bufPos;
388      memmove(buf, buf + (pos - bufPos), bufLen);
389      bufPos = pos;
390
391    // otherwise discard data from the
392    // stream until we get to the requested position
393    } else {
394      bufPos += bufLen;
395      bufLen = 0;
396      while (bufPos < pos) {
397        if ((c = (*getChar)(data)) < 0) {
398          return gFalse;
399        }
400        ++bufPos;
401      }
402    }
403  }
404
405  // read the rest of the requested data
406  while (bufPos + bufLen < pos + len) {
407    if ((c = (*getChar)(data)) < 0) {
408      return gFalse;
409    }
410    buf[bufLen++] = (char)c;
411  }
412
413  return gTrue;
414}
415
416//------------------------------------------------------------------------
417
418static FoFiIdentifierType identify(Reader *reader);
419static FoFiIdentifierType identifyOpenType(Reader *reader);
420static FoFiIdentifierType identifyCFF(Reader *reader, int start);
421
422FoFiIdentifierType FoFiIdentifier::identifyMem(char *file, int len) {
423  MemReader *reader;
424  FoFiIdentifierType type;
425
426  if (!(reader = MemReader::make(file, len))) {
427    return fofiIdError;
428  }
429  type = identify(reader);
430  delete reader;
431  return type;
432}
433
434FoFiIdentifierType FoFiIdentifier::identifyFile(char *fileName) {
435  FileReader *reader;
436  FoFiIdentifierType type;
437
438  if (!(reader = FileReader::make(fileName))) {
439    return fofiIdError;
440  }
441  type = identify(reader);
442  delete reader;
443  return type;
444}
445
446FoFiIdentifierType FoFiIdentifier::identifyStream(int (*getChar)(void *data),
447                                                  void *data) {
448  StreamReader *reader;
449  FoFiIdentifierType type;
450
451  if (!(reader = StreamReader::make(getChar, data))) {
452    return fofiIdError;
453  }
454  type = identify(reader);
455  delete reader;
456  return type;
457}
458
459static FoFiIdentifierType identify(Reader *reader) {
460  Guint n;
461
462  //----- PFA
463  if (reader->cmp(0, "%!PS-AdobeFont-1") ||
464      reader->cmp(0, "%!FontType1")) {
465    return fofiIdType1PFA;
466  }
467
468  //----- PFB
469  if (reader->getByte(0) == 0x80 &&
470      reader->getByte(1) == 0x01 &&
471      reader->getU32LE(2, &n)) {
472    if ((n >= 16 && reader->cmp(6, "%!PS-AdobeFont-1")) ||
473        (n >= 11 && reader->cmp(6, "%!FontType1"))) {
474      return fofiIdType1PFB;
475    }
476  }
477
478  //----- TrueType
479  if ((reader->getByte(0) == 0x00 &&
480       reader->getByte(1) == 0x01 &&
481       reader->getByte(2) == 0x00 &&
482       reader->getByte(3) == 0x00) ||
483      (reader->getByte(0) == 0x74 &&    // 'true'
484       reader->getByte(1) == 0x72 &&
485       reader->getByte(2) == 0x75 &&
486       reader->getByte(3) == 0x65)) {
487    return fofiIdTrueType;
488  }
489  if (reader->getByte(0) == 0x74 &&     // 'ttcf'
490      reader->getByte(1) == 0x74 &&
491      reader->getByte(2) == 0x63 &&
492      reader->getByte(3) == 0x66) {
493    return fofiIdTrueTypeCollection;
494  }
495
496  //----- OpenType
497  if (reader->getByte(0) == 0x4f &&     // 'OTTO
498      reader->getByte(1) == 0x54 &&
499      reader->getByte(2) == 0x54 &&
500      reader->getByte(3) == 0x4f) {
501    return identifyOpenType(reader);
502  }
503
504  //----- CFF
505  if (reader->getByte(0) == 0x01 &&
506      reader->getByte(1) == 0x00) {
507    return identifyCFF(reader, 0);
508  }
509  // some tools embed CFF fonts with an extra whitespace char at the
510  // beginning
511  if (reader->getByte(1) == 0x01 &&
512      reader->getByte(2) == 0x00) {
513    return identifyCFF(reader, 1);
514  }
515
516  return fofiIdUnknown;
517}
518
519static FoFiIdentifierType identifyOpenType(Reader *reader) {
520  FoFiIdentifierType type;
521  Guint offset;
522  int nTables, i;
523
524  if (!reader->getU16BE(4, &nTables)) {
525    return fofiIdUnknown;
526  }
527  for (i = 0; i < nTables; ++i) {
528    if (reader->cmp(12 + i*16, "CFF ")) {
529      if (reader->getU32BE(12 + i*16 + 8, &offset) &&
530          offset < (Guint)INT_MAX) {
531        type = identifyCFF(reader, (int)offset);
532        if (type == fofiIdCFF8Bit) {
533          type = fofiIdOpenTypeCFF8Bit;
534        } else if (type == fofiIdCFFCID) {
535          type = fofiIdOpenTypeCFFCID;
536        }
537        return type;
538      }
539      return fofiIdUnknown;
540    }
541  }
542  return fofiIdUnknown;
543}
544
545static FoFiIdentifierType identifyCFF(Reader *reader, int start) {
546  Guint offset0, offset1;
547  int hdrSize, offSize0, offSize1, pos, endPos, b0, n, i;
548
549  //----- read the header
550  if (reader->getByte(start) != 0x01 ||
551      reader->getByte(start + 1) != 0x00) {
552    return fofiIdUnknown;
553  }
554  if ((hdrSize = reader->getByte(start + 2)) < 0) {
555    return fofiIdUnknown;
556  }
557  if ((offSize0 = reader->getByte(start + 3)) < 1 || offSize0 > 4) {
558    return fofiIdUnknown;
559  }
560  pos = start + hdrSize;
561  if (pos < 0) {
562    return fofiIdUnknown;
563  }
564
565  //----- skip the name index
566  if (!reader->getU16BE(pos, &n)) {
567    return fofiIdUnknown;
568  }
569  if (n == 0) {
570    pos += 2;
571  } else {
572    if ((offSize1 = reader->getByte(pos + 2)) < 1 || offSize1 > 4) {
573      return fofiIdUnknown;
574    }
575    if (!reader->getUVarBE(pos + 3 + n * offSize1, offSize1, &offset1) ||
576        offset1 > (Guint)INT_MAX) {
577      return fofiIdUnknown;
578    }
579    pos += 3 + (n + 1) * offSize1 + (int)offset1 - 1;
580  }
581  if (pos < 0) {
582    return fofiIdUnknown;
583  }
584
585  //----- parse the top dict index
586  if (!reader->getU16BE(pos, &n) || n < 1) {
587    return fofiIdUnknown;
588  }
589  if ((offSize1 = reader->getByte(pos + 2)) < 1 || offSize1 > 4) {
590    return fofiIdUnknown;
591  }
592  if (!reader->getUVarBE(pos + 3, offSize1, &offset0) ||
593      offset0 > (Guint)INT_MAX ||
594      !reader->getUVarBE(pos + 3 + offSize1, offSize1, &offset1) ||
595      offset1 > (Guint)INT_MAX ||
596      offset0 > offset1) {
597    return fofiIdUnknown;
598  }
599  pos = pos + 3 + (n + 1) * offSize1 + (int)offset0 - 1;
600  endPos = pos + 3 + (n + 1) * offSize1 + (int)offset1 - 1;
601  if (pos < 0 || endPos < 0 || pos > endPos) {
602    return fofiIdUnknown;
603  }
604 
605  //----- parse the top dict, look for ROS as first entry
606  // for a CID font, the top dict starts with:
607  //     <int> <int> <int> ROS
608  for (i = 0; i < 3; ++i) {
609    b0 = reader->getByte(pos++);
610    if (b0 == 0x1c) {
611      pos += 2;
612    } else if (b0 == 0x1d) {
613      pos += 4;
614    } else if (b0 >= 0xf7 && b0 <= 0xfe) {
615      pos += 1;
616    } else if (b0 < 0x20 || b0 > 0xf6) {
617      return fofiIdCFF8Bit;
618    }
619    if (pos >= endPos || pos < 0) {
620      return fofiIdCFF8Bit;
621    }
622  }
623  if (pos + 1 < endPos &&
624      reader->getByte(pos) == 12 &&
625      reader->getByte(pos + 1) == 30) {
626    return fofiIdCFFCID;
627  } else {
628    return fofiIdCFF8Bit;
629  }
630}
Note: See TracBrowser for help on using the repository browser.