blob: 56bf2639ed63d37a7d5f01710829bbe7cd2cc365 [file] [log] [blame]
edisonn@google.comcf2cfa12013-08-21 16:31:37 +00001/*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkPdfNativeTokenizer_DEFINED
9#define SkPdfNativeTokenizer_DEFINED
edisonn@google.com3aac1f92013-07-02 22:42:53 +000010
edisonn@google.com571c70b2013-07-10 17:09:50 +000011#include "SkTDArray.h"
12#include "SkTDict.h"
13#include <math.h>
14#include <string.h>
15
edisonn@google.com571c70b2013-07-10 17:09:50 +000016class SkPdfDictionary;
edisonn@google.com78b38b12013-07-15 18:20:58 +000017class SkPdfImageDictionary;
edisonn@google.com571c70b2013-07-10 17:09:50 +000018
19// White Spaces
20#define kNUL_PdfWhiteSpace '\x00'
21#define kHT_PdfWhiteSpace '\x09'
22#define kLF_PdfWhiteSpace '\x0A'
23#define kFF_PdfWhiteSpace '\x0C'
24#define kCR_PdfWhiteSpace '\x0D'
25#define kSP_PdfWhiteSpace '\x20'
26
27// PdfDelimiters
28#define kOpenedRoundBracket_PdfDelimiter '('
29#define kClosedRoundBracket_PdfDelimiter ')'
30#define kOpenedInequityBracket_PdfDelimiter '<'
31#define kClosedInequityBracket_PdfDelimiter '>'
32#define kOpenedSquareBracket_PdfDelimiter '['
33#define kClosedSquareBracket_PdfDelimiter ']'
34#define kOpenedCurlyBracket_PdfDelimiter '{'
35#define kClosedCurlyBracket_PdfDelimiter '}'
36#define kNamed_PdfDelimiter '/'
37#define kComment_PdfDelimiter '%'
38
39#define kEscape_PdfSpecial '\\'
40#define kBackspace_PdfSpecial '\x08'
41
42// TODO(edisonn): what is the faster way for compiler/machine type to evaluate this expressions?
43// we should evaluate all options. might be even different from one machine to another
44// 1) expand expression, let compiler optimize it
45// 2) binary search
46// 3) linear search in array
47// 4) vector (e.f. T type[256] .. return type[ch] ...
48// 5) manually build the expression with least number of operators, e.g. for consecutive
49// chars, we can use an binary equal ignoring last bit
50#define isPdfWhiteSpace(ch) (((ch)==kNUL_PdfWhiteSpace)||((ch)==kHT_PdfWhiteSpace)||((ch)==kLF_PdfWhiteSpace)||((ch)==kFF_PdfWhiteSpace)||((ch)==kCR_PdfWhiteSpace)||((ch)==kSP_PdfWhiteSpace))
51
52#define isPdfEOL(ch) (((ch)==kLF_PdfWhiteSpace)||((ch)==kCR_PdfWhiteSpace))
53
54
55#define isPdfDelimiter(ch) (((ch)==kOpenedRoundBracket_PdfDelimiter)||\
56 ((ch)==kClosedRoundBracket_PdfDelimiter)||\
57 ((ch)==kOpenedInequityBracket_PdfDelimiter)||\
58 ((ch)==kClosedInequityBracket_PdfDelimiter)||\
59 ((ch)==kOpenedSquareBracket_PdfDelimiter)||\
60 ((ch)==kClosedSquareBracket_PdfDelimiter)||\
61 ((ch)==kOpenedCurlyBracket_PdfDelimiter)||\
62 ((ch)==kClosedCurlyBracket_PdfDelimiter)||\
63 ((ch)==kNamed_PdfDelimiter)||\
64 ((ch)==kComment_PdfDelimiter))
65
66#define isPdfWhiteSpaceOrPdfDelimiter(ch) (isPdfWhiteSpace(ch)||isPdfDelimiter(ch))
67
68#define isPdfDigit(ch) ((ch)>='0'&&(ch)<='9')
edisonn@google.com4ef4bed2013-07-29 22:14:45 +000069#define isPdfNumeric(ch) (isPdfDigit(ch)||(ch)=='+'||(ch)=='-'||(ch)=='.')
edisonn@google.com571c70b2013-07-10 17:09:50 +000070
edisonn@google.com4ef4bed2013-07-29 22:14:45 +000071const unsigned char* skipPdfWhiteSpaces(int level, const unsigned char* buffer, const unsigned char* end);
72const unsigned char* endOfPdfToken(int level, const unsigned char* start, const unsigned char* end);
edisonn@google.com571c70b2013-07-10 17:09:50 +000073
74// TODO(edisonn): typedef read and integer tyepes? make less readable...
75//typedef double SkPdfReal;
76//typedef int64_t SkPdfInteger;
77
78// an allocator only allocates memory, and it deletes it all when the allocator is destroyed
79// this would allow us not to do any garbage collection while we parse or draw a pdf, and defere it
80// while the user is looking at the image
81
edisonn@google.com3aa35552013-08-14 18:26:20 +000082class SkPdfNativeObject;
edisonn@google.com571c70b2013-07-10 17:09:50 +000083
84class SkPdfAllocator {
85#define BUFFER_SIZE 1024
edisonn@google.com3aa35552013-08-14 18:26:20 +000086 SkTDArray<SkPdfNativeObject*> fHistory;
edisonn@google.com571c70b2013-07-10 17:09:50 +000087 SkTDArray<void*> fHandles;
edisonn@google.com3aa35552013-08-14 18:26:20 +000088 SkPdfNativeObject* fCurrent;
edisonn@google.com571c70b2013-07-10 17:09:50 +000089 int fCurrentUsed;
90
edisonn@google.com3aa35552013-08-14 18:26:20 +000091 SkPdfNativeObject* allocBlock();
edisonn@google.coma5aaa792013-07-11 12:27:21 +000092 size_t fSizeInBytes;
edisonn@google.com571c70b2013-07-10 17:09:50 +000093
edisonn@google.com3aac1f92013-07-02 22:42:53 +000094public:
edisonn@google.com571c70b2013-07-10 17:09:50 +000095 SkPdfAllocator() {
edisonn@google.coma5aaa792013-07-11 12:27:21 +000096 fSizeInBytes = sizeof(*this);
edisonn@google.com571c70b2013-07-10 17:09:50 +000097 fCurrent = allocBlock();
98 fCurrentUsed = 0;
99 }
100
101 ~SkPdfAllocator();
102
edisonn@google.com3aa35552013-08-14 18:26:20 +0000103 SkPdfNativeObject* allocObject();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000104
105 // TODO(edisonn): free this memory in destructor, track the usage?
106 void* alloc(size_t bytes) {
107 void* data = malloc(bytes);
108 fHandles.push(data);
edisonn@google.coma5aaa792013-07-11 12:27:21 +0000109 fSizeInBytes += bytes;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000110 return data;
111 }
edisonn@google.coma5aaa792013-07-11 12:27:21 +0000112
edisonn@google.com7b328fd2013-07-11 12:53:06 +0000113 size_t bytesUsed() const {
edisonn@google.coma5aaa792013-07-11 12:27:21 +0000114 return fSizeInBytes;
115 }
edisonn@google.com571c70b2013-07-10 17:09:50 +0000116};
117
edisonn@google.com3aa35552013-08-14 18:26:20 +0000118class SkPdfNativeDoc;
119const unsigned char* nextObject(int level, const unsigned char* start, const unsigned char* end, SkPdfNativeObject* token, SkPdfAllocator* allocator, SkPdfNativeDoc* doc);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000120
121enum SkPdfTokenType {
122 kKeyword_TokenType,
123 kObject_TokenType,
124};
125
126struct PdfToken {
127 const char* fKeyword;
128 size_t fKeywordLength;
edisonn@google.com3aa35552013-08-14 18:26:20 +0000129 SkPdfNativeObject* fObject;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000130 SkPdfTokenType fType;
131
132 PdfToken() : fKeyword(NULL), fKeywordLength(0), fObject(NULL) {}
133};
134
135class SkPdfNativeTokenizer {
136public:
edisonn@google.com33f11b62013-08-14 21:35:27 +0000137 SkPdfNativeTokenizer(SkPdfNativeObject* objWithStream, SkPdfAllocator* allocator, SkPdfNativeDoc* doc);
138 SkPdfNativeTokenizer(const unsigned char* buffer, int len, SkPdfAllocator* allocator, SkPdfNativeDoc* doc);
edisonn@google.com571c70b2013-07-10 17:09:50 +0000139
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000140 virtual ~SkPdfNativeTokenizer();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000141
142 bool readToken(PdfToken* token);
143 bool readTokenCore(PdfToken* token);
144 void PutBack(PdfToken token);
edisonn@google.com78b38b12013-07-15 18:20:58 +0000145 SkPdfImageDictionary* readInlineImage();
edisonn@google.com571c70b2013-07-10 17:09:50 +0000146
147private:
edisonn@google.com3aa35552013-08-14 18:26:20 +0000148 SkPdfNativeDoc* fDoc;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000149 SkPdfAllocator* fAllocator;
150
edisonn@google.com2ccc3af2013-07-23 17:43:18 +0000151 const unsigned char* fUncompressedStreamStart;
152 const unsigned char* fUncompressedStream;
153 const unsigned char* fUncompressedStreamEnd;
edisonn@google.com571c70b2013-07-10 17:09:50 +0000154
155 bool fEmpty;
156 bool fHasPutBack;
157 PdfToken fPutBack;
edisonn@google.com3aac1f92013-07-02 22:42:53 +0000158};
159
edisonn@google.comcf2cfa12013-08-21 16:31:37 +0000160#endif // SkPdfNativeTokenizer_DEFINED