blob: ad425d8e02cfdeb96486e5a94596125dbd0bd3aa [file] [log] [blame]
#ifndef EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKPDFNATIVETOKENIZER_H_
#define EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKPDFNATIVETOKENIZER_H_
#include "SkTDArray.h"
#include "SkTDict.h"
#include <math.h>
#include <string.h>
class SkPdfMapper;
class SkPdfDictionary;
class SkPdfImageDictionary;
// White Spaces
#define kNUL_PdfWhiteSpace '\x00'
#define kHT_PdfWhiteSpace '\x09'
#define kLF_PdfWhiteSpace '\x0A'
#define kFF_PdfWhiteSpace '\x0C'
#define kCR_PdfWhiteSpace '\x0D'
#define kSP_PdfWhiteSpace '\x20'
// PdfDelimiters
#define kOpenedRoundBracket_PdfDelimiter '('
#define kClosedRoundBracket_PdfDelimiter ')'
#define kOpenedInequityBracket_PdfDelimiter '<'
#define kClosedInequityBracket_PdfDelimiter '>'
#define kOpenedSquareBracket_PdfDelimiter '['
#define kClosedSquareBracket_PdfDelimiter ']'
#define kOpenedCurlyBracket_PdfDelimiter '{'
#define kClosedCurlyBracket_PdfDelimiter '}'
#define kNamed_PdfDelimiter '/'
#define kComment_PdfDelimiter '%'
#define kEscape_PdfSpecial '\\'
#define kBackspace_PdfSpecial '\x08'
// TODO(edisonn): what is the faster way for compiler/machine type to evaluate this expressions?
// we should evaluate all options. might be even different from one machine to another
// 1) expand expression, let compiler optimize it
// 2) binary search
// 3) linear search in array
// 4) vector (e.f. T type[256] .. return type[ch] ...
// 5) manually build the expression with least number of operators, e.g. for consecutive
// chars, we can use an binary equal ignoring last bit
#define isPdfWhiteSpace(ch) (((ch)==kNUL_PdfWhiteSpace)||((ch)==kHT_PdfWhiteSpace)||((ch)==kLF_PdfWhiteSpace)||((ch)==kFF_PdfWhiteSpace)||((ch)==kCR_PdfWhiteSpace)||((ch)==kSP_PdfWhiteSpace))
#define isPdfEOL(ch) (((ch)==kLF_PdfWhiteSpace)||((ch)==kCR_PdfWhiteSpace))
#define isPdfDelimiter(ch) (((ch)==kOpenedRoundBracket_PdfDelimiter)||\
((ch)==kClosedRoundBracket_PdfDelimiter)||\
((ch)==kOpenedInequityBracket_PdfDelimiter)||\
((ch)==kClosedInequityBracket_PdfDelimiter)||\
((ch)==kOpenedSquareBracket_PdfDelimiter)||\
((ch)==kClosedSquareBracket_PdfDelimiter)||\
((ch)==kOpenedCurlyBracket_PdfDelimiter)||\
((ch)==kClosedCurlyBracket_PdfDelimiter)||\
((ch)==kNamed_PdfDelimiter)||\
((ch)==kComment_PdfDelimiter))
#define isPdfWhiteSpaceOrPdfDelimiter(ch) (isPdfWhiteSpace(ch)||isPdfDelimiter(ch))
#define isPdfDigit(ch) ((ch)>='0'&&(ch)<='9')
#define isPdfNumeric(ch) (isPdfDigit(ch)||(ch)=='+'||(ch)=='-')
unsigned char* skipPdfWhiteSpaces(unsigned char* buffer, size_t len);
unsigned char* endOfPdfToken(unsigned char* start, size_t len);
unsigned char* skipPdfComment(unsigned char* start, size_t len);
// TODO(edisonn): typedef read and integer tyepes? make less readable...
//typedef double SkPdfReal;
//typedef int64_t SkPdfInteger;
// an allocator only allocates memory, and it deletes it all when the allocator is destroyed
// this would allow us not to do any garbage collection while we parse or draw a pdf, and defere it
// while the user is looking at the image
class SkPdfObject;
class SkPdfAllocator {
#define BUFFER_SIZE 1024
SkTDArray<SkPdfObject*> fHistory;
SkTDArray<void*> fHandles;
SkPdfObject* fCurrent;
int fCurrentUsed;
SkPdfObject* allocBlock();
size_t fSizeInBytes;
public:
SkPdfAllocator() {
fSizeInBytes = sizeof(*this);
fCurrent = allocBlock();
fCurrentUsed = 0;
}
~SkPdfAllocator();
SkPdfObject* allocObject();
// TODO(edisonn): free this memory in destructor, track the usage?
void* alloc(size_t bytes) {
void* data = malloc(bytes);
fHandles.push(data);
fSizeInBytes += bytes;
return data;
}
size_t bytesUsed() const {
return fSizeInBytes;
}
};
class SkNativeParsedPDF;
unsigned char* nextObject(unsigned char* start, unsigned char* end, SkPdfObject* token, SkPdfAllocator* allocator, SkNativeParsedPDF* doc);
enum SkPdfTokenType {
kKeyword_TokenType,
kObject_TokenType,
};
struct PdfToken {
const char* fKeyword;
size_t fKeywordLength;
SkPdfObject* fObject;
SkPdfTokenType fType;
PdfToken() : fKeyword(NULL), fKeywordLength(0), fObject(NULL) {}
};
class SkPdfNativeTokenizer {
public:
SkPdfNativeTokenizer(SkPdfObject* objWithStream, const SkPdfMapper* mapper, SkPdfAllocator* allocator, SkNativeParsedPDF* doc);
SkPdfNativeTokenizer(unsigned char* buffer, int len, const SkPdfMapper* mapper, SkPdfAllocator* allocator, SkNativeParsedPDF* doc);
virtual ~SkPdfNativeTokenizer();
bool readToken(PdfToken* token);
bool readTokenCore(PdfToken* token);
void PutBack(PdfToken token);
SkPdfImageDictionary* readInlineImage();
private:
SkNativeParsedPDF* fDoc;
const SkPdfMapper* fMapper;
SkPdfAllocator* fAllocator;
unsigned char* fUncompressedStreamStart;
unsigned char* fUncompressedStream;
unsigned char* fUncompressedStreamEnd;
bool fEmpty;
bool fHasPutBack;
PdfToken fPutBack;
};
#endif // EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKPDFNATIVETOKENIZER_H_