OLD | NEW |
| (Empty) |
1 /* | |
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 | |
10 | |
11 #include <math.h> | |
12 #include <string.h> | |
13 | |
14 #include "SkPdfConfig.h" | |
15 #include "SkTDArray.h" | |
16 #include "SkTDict.h" | |
17 | |
18 // All these constants are defined by the PDF 1.4 Spec. | |
19 | |
20 class SkPdfDictionary; | |
21 class SkPdfImageDictionary; | |
22 class SkPdfNativeDoc; | |
23 class SkPdfNativeObject; | |
24 | |
25 | |
26 // White Spaces | |
27 #define kNUL_PdfWhiteSpace '\x00' | |
28 #define kHT_PdfWhiteSpace '\x09' | |
29 #define kLF_PdfWhiteSpace '\x0A' | |
30 #define kFF_PdfWhiteSpace '\x0C' | |
31 #define kCR_PdfWhiteSpace '\x0D' | |
32 #define kSP_PdfWhiteSpace '\x20' | |
33 | |
34 // PdfDelimiters | |
35 #define kOpenedRoundBracket_PdfDelimiter '(' | |
36 #define kClosedRoundBracket_PdfDelimiter ')' | |
37 #define kOpenedInequityBracket_PdfDelimiter '<' | |
38 #define kClosedInequityBracket_PdfDelimiter '>' | |
39 #define kOpenedSquareBracket_PdfDelimiter '[' | |
40 #define kClosedSquareBracket_PdfDelimiter ']' | |
41 #define kOpenedCurlyBracket_PdfDelimiter '{' | |
42 #define kClosedCurlyBracket_PdfDelimiter '}' | |
43 #define kNamed_PdfDelimiter '/' | |
44 #define kComment_PdfDelimiter '%' | |
45 | |
46 #define kEscape_PdfSpecial '\\' | |
47 #define kBackspace_PdfSpecial '\x08' | |
48 | |
49 // TODO(edisonn): what is the faster way for compiler/machine type to evaluate t
his expressions? | |
50 // we should evaluate all options. might be even different from one machine to a
nother | |
51 // 1) expand expression, let compiler optimize it | |
52 // 2) binary search | |
53 // 3) linear search in array | |
54 // 4) vector (e.f. T type[256] .. return type[ch] ... | |
55 // 5) manually build the expression with least number of operators, e.g. for con
secutive | |
56 // chars, we can use an binary equal ignoring last bit | |
57 #define isPdfWhiteSpace(ch) (((ch)==kNUL_PdfWhiteSpace)|| \ | |
58 ((ch)==kHT_PdfWhiteSpace)|| \ | |
59 ((ch)==kLF_PdfWhiteSpace)|| \ | |
60 ((ch)==kFF_PdfWhiteSpace)|| \ | |
61 ((ch)==kCR_PdfWhiteSpace)|| \ | |
62 ((ch)==kSP_PdfWhiteSpace)) | |
63 | |
64 #define isPdfEOL(ch) (((ch)==kLF_PdfWhiteSpace)||((ch)==kCR_PdfWhiteSpace)) | |
65 | |
66 | |
67 #define isPdfDelimiter(ch) (((ch)==kOpenedRoundBracket_PdfDelimiter)||\ | |
68 ((ch)==kClosedRoundBracket_PdfDelimiter)||\ | |
69 ((ch)==kOpenedInequityBracket_PdfDelimiter)||\ | |
70 ((ch)==kClosedInequityBracket_PdfDelimiter)||\ | |
71 ((ch)==kOpenedSquareBracket_PdfDelimiter)||\ | |
72 ((ch)==kClosedSquareBracket_PdfDelimiter)||\ | |
73 ((ch)==kOpenedCurlyBracket_PdfDelimiter)||\ | |
74 ((ch)==kClosedCurlyBracket_PdfDelimiter)||\ | |
75 ((ch)==kNamed_PdfDelimiter)||\ | |
76 ((ch)==kComment_PdfDelimiter)) | |
77 | |
78 #define isPdfWhiteSpaceOrPdfDelimiter(ch) (isPdfWhiteSpace(ch)||isPdfDelimiter(c
h)) | |
79 | |
80 #define isPdfDigit(ch) ((ch)>='0'&&(ch)<='9') | |
81 #define isPdfNumeric(ch) (isPdfDigit(ch)||(ch)=='+'||(ch)=='-'||(ch)=='.') | |
82 | |
83 const unsigned char* skipPdfWhiteSpaces(const unsigned char* buffer, const unsig
ned char* end); | |
84 const unsigned char* endOfPdfToken(const unsigned char* start, const unsigned ch
ar* end); | |
85 | |
86 #define BUFFER_SIZE 1024 | |
87 | |
88 /** \class SkPdfAllocator | |
89 * | |
90 * An allocator only allocates memory, and it deletes it all when the allocato
r is destroyed. | |
91 * This strategy would allow us not to do any garbage collection while we pars
e and/or render | |
92 * a pdf. | |
93 * | |
94 */ | |
95 class SkPdfAllocator { | |
96 public: | |
97 SkPdfAllocator() { | |
98 fSizeInBytes = sizeof(*this); | |
99 fCurrent = allocBlock(); | |
100 fCurrentUsed = 0; | |
101 } | |
102 | |
103 ~SkPdfAllocator(); | |
104 | |
105 // Allocates an object. It will be reset automatically when ~SkPdfAllocator(
) is called. | |
106 SkPdfNativeObject* allocObject(); | |
107 | |
108 // Allocates a buffer. It will be freed automatically when ~SkPdfAllocator()
is called. | |
109 void* alloc(size_t bytes) { | |
110 void* data = malloc(bytes); | |
111 fHandles.push(data); | |
112 fSizeInBytes += bytes; | |
113 return data; | |
114 } | |
115 | |
116 // Returns the number of bytes used in this allocator. | |
117 size_t bytesUsed() const { | |
118 return fSizeInBytes; | |
119 } | |
120 | |
121 private: | |
122 SkTDArray<SkPdfNativeObject*> fHistory; | |
123 SkTDArray<void*> fHandles; | |
124 SkPdfNativeObject* fCurrent; | |
125 int fCurrentUsed; | |
126 | |
127 SkPdfNativeObject* allocBlock(); | |
128 size_t fSizeInBytes; | |
129 }; | |
130 | |
131 // Type of a parsed token. | |
132 enum SkPdfTokenType { | |
133 kKeyword_TokenType, | |
134 kObject_TokenType, | |
135 }; | |
136 | |
137 | |
138 /** \struct PdfToken | |
139 * | |
140 * Stores the result of the parsing - a keyword or an object. | |
141 * | |
142 */ | |
143 struct PdfToken { | |
144 const char* fKeyword; | |
145 size_t fKeywordLength; | |
146 SkPdfNativeObject* fObject; | |
147 SkPdfTokenType fType; | |
148 | |
149 PdfToken() : fKeyword(NULL), fKeywordLength(0), fObject(NULL) {} | |
150 }; | |
151 | |
152 /** \class SkPdfNativeTokenizer | |
153 * | |
154 * Responsible to tokenize a stream in small tokens, eityh a keyword or an obj
ect. | |
155 * A renderer can feed on the tokens and render a pdf. | |
156 * | |
157 */ | |
158 class SkPdfNativeTokenizer { | |
159 public: | |
160 SkPdfNativeTokenizer(SkPdfNativeObject* objWithStream, | |
161 SkPdfAllocator* allocator, SkPdfNativeDoc* doc); | |
162 SkPdfNativeTokenizer(const unsigned char* buffer, int len, | |
163 SkPdfAllocator* allocator, SkPdfNativeDoc* doc); | |
164 | |
165 virtual ~SkPdfNativeTokenizer(); | |
166 | |
167 // Reads one token. Returns false if there are no more tokens. | |
168 // If writeDiff is true, and a token was read, create a PNG highlighting | |
169 // the difference caused by this command in /tmp/log_step_by_step. | |
170 // If PDF_TRACE_DIFF_IN_PNG is not defined, writeDiff does nothing. | |
171 bool readToken(PdfToken* token, bool writeDiff = false); | |
172 | |
173 // Put back a token to be read in the nextToken read. Only one token is allo
wed to be put | |
174 // back. Must not necesaarely be the last token read. | |
175 void PutBack(PdfToken token); | |
176 | |
177 // Reads the inline image that is present in the stream. At this point we ju
st consumed the ID | |
178 // token already. | |
179 SkPdfImageDictionary* readInlineImage(); | |
180 | |
181 private: | |
182 bool readTokenCore(PdfToken* token); | |
183 | |
184 SkPdfNativeDoc* fDoc; | |
185 SkPdfAllocator* fAllocator; | |
186 | |
187 const unsigned char* fUncompressedStreamStart; | |
188 const unsigned char* fUncompressedStream; | |
189 const unsigned char* fUncompressedStreamEnd; | |
190 | |
191 bool fEmpty; | |
192 bool fHasPutBack; | |
193 PdfToken fPutBack; | |
194 }; | |
195 | |
196 const unsigned char* nextObject(const unsigned char* start, const unsigned char*
end, | |
197 SkPdfNativeObject* token, | |
198 SkPdfAllocator* allocator, | |
199 SkPdfNativeDoc* doc); | |
200 | |
201 #endif // SkPdfNativeTokenizer_DEFINED | |
OLD | NEW |