diff options
Diffstat (limited to 'experimental/PdfViewer/SkPdfParser.h')
-rw-r--r-- | experimental/PdfViewer/SkPdfParser.h | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/experimental/PdfViewer/SkPdfParser.h b/experimental/PdfViewer/SkPdfParser.h new file mode 100644 index 0000000000..7e2cd0ede1 --- /dev/null +++ b/experimental/PdfViewer/SkPdfParser.h @@ -0,0 +1,164 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "podofo.h" +#include "SkPdfHeaders_autogen.h" +#include "SkPdfPodofoMapper_autogen.h" + +#ifndef SkPdfParser_DEFINED +#define SkPdfParser_DEFINED + + +enum SkPdfTokenType { + kKeyword_TokenType, + kObject_TokenType, + kImageData_TokenType, // TODO(edisonn): inline images seem to work without it +}; + +struct PdfToken { + const char* fKeyword; + SkPdfObject* fObject; + SkPdfTokenType fType; + + PdfToken() : fKeyword(NULL), fObject(NULL) {} +}; + +class SkPdfTokenizer { + PdfContentsTokenizer* fTokenizer; + PdfMemDocument* fDoc; + + char* fUncompressedStream; + pdf_long fUncompressedStreamLength; + + bool fEmpty; + bool fHasPutBack; + PdfToken fPutBack; + +public: + SkPdfTokenizer(PdfMemDocument* doc = NULL, PdfContentsTokenizer* tokenizer = NULL) : fDoc(doc), fTokenizer(tokenizer), fEmpty(false), fUncompressedStream(NULL), fUncompressedStreamLength(0), fHasPutBack(false) {} + SkPdfTokenizer(const SkPdfObject* objWithStream) : fDoc(NULL), fTokenizer(NULL), fHasPutBack(false), fEmpty(false) { + fUncompressedStream = NULL; + fUncompressedStreamLength = 0; + + fDoc = NULL; + + + try { + objWithStream->podofo()->GetStream()->GetFilteredCopy(&fUncompressedStream, &fUncompressedStreamLength); + if (fUncompressedStream != NULL && fUncompressedStreamLength != 0) { + fTokenizer = new PdfContentsTokenizer(fUncompressedStream, fUncompressedStreamLength); + } else { + fEmpty = true; + } + } catch (PdfError& e) { + fEmpty = true; + } + + } + + SkPdfTokenizer(const char* buffer, int len) : fDoc(NULL), fTokenizer(NULL), fHasPutBack(false), fUncompressedStream(NULL), fUncompressedStreamLength(0), fEmpty(false) { + try { + fTokenizer = new PdfContentsTokenizer(buffer, len); + } catch (PdfError& e) { + fEmpty = true; + } + } + + ~SkPdfTokenizer() { + free(fUncompressedStream); + } + + void PutBack(PdfToken token) { + SkASSERT(!fHasPutBack); + fHasPutBack = true; + fPutBack = token; + } + + bool readToken(PdfToken* token) { + if (fHasPutBack) { + *token = fPutBack; + fHasPutBack = false; + return true; + } + + if (fEmpty) { + return false; + } + + PdfVariant var; + EPdfContentsType type; + + token->fKeyword = NULL; + token->fObject = NULL; + + bool ret = fTokenizer->ReadNext(type, token->fKeyword, var); + + if (!ret) return ret; + + switch (type) { + case ePdfContentsType_Keyword: + token->fType = kKeyword_TokenType; + break; + + case ePdfContentsType_Variant: { + token->fType = kObject_TokenType; + PdfObject* obj = new PdfObject(var); + PodofoMapper::map(*fDoc, *obj, &token->fObject); + } + break; + + case ePdfContentsType_ImageData: + token->fType = kImageData_TokenType; + // TODO(edisonn): inline images seem to work without it + break; + } +#ifdef PDF_TRACE + std::string str; + if (token->fObject) { + token->fObject->podofo()->ToString(str); + } + printf("%s %s\n", token->fType == kKeyword_TokenType ? "Keyword" : token->fType == kObject_TokenType ? "Object" : "ImageData", token->fKeyword ? token->fKeyword : str.c_str()); +#endif + return ret; + } +}; + +class SkPdfDoc { + PdfMemDocument fDoc; +public: + + PdfMemDocument& podofo() {return fDoc;} + + SkPdfDoc(const char* path) : fDoc(path) {} + + int pages() { + return fDoc.GetPageCount(); + } + + // Can return NULL + SkPdfPageObjectDictionary* page(int n) { + SkPdfPageObjectDictionary* page = NULL; + PodofoMapper::map(fDoc, *fDoc.GetPage(n)->GetObject(), &page); + return page; + } + + SkRect MediaBox(int n) { + PdfRect rect = fDoc.GetPage(n)->GetMediaBox(); + SkRect skrect = SkRect::MakeLTRB(SkDoubleToScalar(rect.GetLeft()), + SkDoubleToScalar(rect.GetBottom()), + SkDoubleToScalar(rect.GetLeft() + rect.GetWidth()), + SkDoubleToScalar(rect.GetBottom() + rect.GetHeight())); + return skrect; + } + + SkPdfTokenizer* tokenizerOfPage(int n) { + PdfContentsTokenizer* t = new PdfContentsTokenizer(fDoc.GetPage(n)); + return new SkPdfTokenizer(&fDoc, t); + } +}; + +#endif // SkPdfParser_DEFINED |