SkPdfNativeTokenizer.h revision 598cf5d3cfc428108cf21ab45d73a995d7e5c2a8
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 "SkPdfConfig.h"
12
13#include "SkTDArray.h"
14#include "SkTDict.h"
15#include <math.h>
16#include <string.h>
17
18class SkPdfDictionary;
19class SkPdfImageDictionary;
20
21// White Spaces
22#define kNUL_PdfWhiteSpace '\x00'
23#define kHT_PdfWhiteSpace  '\x09'
24#define kLF_PdfWhiteSpace  '\x0A'
25#define kFF_PdfWhiteSpace  '\x0C'
26#define kCR_PdfWhiteSpace  '\x0D'
27#define kSP_PdfWhiteSpace  '\x20'
28
29// PdfDelimiters
30#define kOpenedRoundBracket_PdfDelimiter        '('
31#define kClosedRoundBracket_PdfDelimiter        ')'
32#define kOpenedInequityBracket_PdfDelimiter     '<'
33#define kClosedInequityBracket_PdfDelimiter     '>'
34#define kOpenedSquareBracket_PdfDelimiter       '['
35#define kClosedSquareBracket_PdfDelimiter       ']'
36#define kOpenedCurlyBracket_PdfDelimiter        '{'
37#define kClosedCurlyBracket_PdfDelimiter        '}'
38#define kNamed_PdfDelimiter                     '/'
39#define kComment_PdfDelimiter                   '%'
40
41#define kEscape_PdfSpecial                      '\\'
42#define kBackspace_PdfSpecial                   '\x08'
43
44// TODO(edisonn): what is the faster way for compiler/machine type to evaluate this expressions?
45// we should evaluate all options. might be even different from one machine to another
46// 1) expand expression, let compiler optimize it
47// 2) binary search
48// 3) linear search in array
49// 4) vector (e.f. T type[256] .. return type[ch] ...
50// 5) manually build the expression with least number of operators, e.g. for consecutive
51// chars, we can use an binary equal ignoring last bit
52#define isPdfWhiteSpace(ch) (((ch)==kNUL_PdfWhiteSpace)||((ch)==kHT_PdfWhiteSpace)||((ch)==kLF_PdfWhiteSpace)||((ch)==kFF_PdfWhiteSpace)||((ch)==kCR_PdfWhiteSpace)||((ch)==kSP_PdfWhiteSpace))
53
54#define isPdfEOL(ch) (((ch)==kLF_PdfWhiteSpace)||((ch)==kCR_PdfWhiteSpace))
55
56
57#define isPdfDelimiter(ch) (((ch)==kOpenedRoundBracket_PdfDelimiter)||\
58                            ((ch)==kClosedRoundBracket_PdfDelimiter)||\
59                            ((ch)==kOpenedInequityBracket_PdfDelimiter)||\
60                            ((ch)==kClosedInequityBracket_PdfDelimiter)||\
61                            ((ch)==kOpenedSquareBracket_PdfDelimiter)||\
62                            ((ch)==kClosedSquareBracket_PdfDelimiter)||\
63                            ((ch)==kOpenedCurlyBracket_PdfDelimiter)||\
64                            ((ch)==kClosedCurlyBracket_PdfDelimiter)||\
65                            ((ch)==kNamed_PdfDelimiter)||\
66                            ((ch)==kComment_PdfDelimiter))
67
68#define isPdfWhiteSpaceOrPdfDelimiter(ch) (isPdfWhiteSpace(ch)||isPdfDelimiter(ch))
69
70#define isPdfDigit(ch) ((ch)>='0'&&(ch)<='9')
71#define isPdfNumeric(ch) (isPdfDigit(ch)||(ch)=='+'||(ch)=='-'||(ch)=='.')
72
73const unsigned char* skipPdfWhiteSpaces(const unsigned char* buffer, const unsigned char* end);
74const unsigned char* endOfPdfToken(const unsigned char* start, const unsigned char* end);
75
76// TODO(edisonn): typedef read and integer tyepes? make less readable...
77//typedef double SkPdfReal;
78//typedef int64_t SkPdfInteger;
79
80// an allocator only allocates memory, and it deletes it all when the allocator is destroyed
81// this would allow us not to do any garbage collection while we parse or draw a pdf, and defere it
82// while the user is looking at the image
83
84class SkPdfNativeObject;
85
86class SkPdfAllocator {
87#define BUFFER_SIZE 1024
88    SkTDArray<SkPdfNativeObject*> fHistory;
89    SkTDArray<void*> fHandles;
90    SkPdfNativeObject* fCurrent;
91    int fCurrentUsed;
92
93    SkPdfNativeObject* allocBlock();
94    size_t fSizeInBytes;
95
96public:
97    SkPdfAllocator() {
98        fSizeInBytes = sizeof(*this);
99        fCurrent = allocBlock();
100        fCurrentUsed = 0;
101    }
102
103    ~SkPdfAllocator();
104
105    SkPdfNativeObject* allocObject();
106
107    // TODO(edisonn): free this memory in destructor, track the usage?
108    void* alloc(size_t bytes) {
109        void* data = malloc(bytes);
110        fHandles.push(data);
111        fSizeInBytes += bytes;
112        return data;
113    }
114
115    size_t bytesUsed() const {
116        return fSizeInBytes;
117    }
118};
119
120class SkPdfNativeDoc;
121const unsigned char* nextObject(const unsigned char* start, const unsigned char* end, SkPdfNativeObject* token, SkPdfAllocator* allocator, SkPdfNativeDoc* doc);
122
123enum SkPdfTokenType {
124    kKeyword_TokenType,
125    kObject_TokenType,
126};
127
128struct PdfToken {
129    const char*      fKeyword;
130    size_t           fKeywordLength;
131    SkPdfNativeObject*     fObject;
132    SkPdfTokenType   fType;
133
134    PdfToken() : fKeyword(NULL), fKeywordLength(0), fObject(NULL) {}
135};
136
137class SkPdfNativeTokenizer {
138public:
139    SkPdfNativeTokenizer(SkPdfNativeObject* objWithStream, SkPdfAllocator* allocator, SkPdfNativeDoc* doc);
140    SkPdfNativeTokenizer(const unsigned char* buffer, int len, SkPdfAllocator* allocator, SkPdfNativeDoc* doc);
141
142    virtual ~SkPdfNativeTokenizer();
143
144    bool readToken(PdfToken* token);
145    bool readTokenCore(PdfToken* token);
146    void PutBack(PdfToken token);
147    SkPdfImageDictionary* readInlineImage();
148
149private:
150    SkPdfNativeDoc* fDoc;
151    SkPdfAllocator* fAllocator;
152
153    const unsigned char* fUncompressedStreamStart;
154    const unsigned char* fUncompressedStream;
155    const unsigned char* fUncompressedStreamEnd;
156
157    bool fEmpty;
158    bool fHasPutBack;
159    PdfToken fPutBack;
160};
161
162#endif  // SkPdfNativeTokenizer_DEFINED
163