diff options
Diffstat (limited to 'experimental')
24 files changed, 1595 insertions, 1249 deletions
diff --git a/experimental/PdfViewer/SkPdfBasics.h b/experimental/PdfViewer/SkPdfBasics.h index 894db10cd0..d20f34bdae 100644 --- a/experimental/PdfViewer/SkPdfBasics.h +++ b/experimental/PdfViewer/SkPdfBasics.h @@ -3,24 +3,22 @@ #include "SkCanvas.h" #include "SkPaint.h" +#include "SkPdfConfig.h" #include <iostream> #include <cstdio> +#include <map> #include <stack> -#define PDF_TRACE -//#define PDF_TRACE_DIFF_IN_PNG -//#define PDF_DEBUG_NO_CLIPING -//#define PDF_DEBUG_NO_PAGE_CLIPING -//#define PDF_DEBUG_3X - class SkPdfFont; class SkPdfDoc; class SkPdfObject; class SkPdfResourceDictionary; +class SkPodofoParsedPDF; + // TODO(edisonn): better class design. -struct PdfColorOperator { +struct SkPdfColorOperator { std::string fColorSpace; // TODO(edisonn): use SkString SkColor fColor; double fOpacity; // ca or CA @@ -31,7 +29,7 @@ struct PdfColorOperator { fColor = color; } // TODO(edisonn): double check the default values for all fields. - PdfColorOperator() : fColor(SK_ColorBLACK), fOpacity(1) {} + SkPdfColorOperator() : fColor(SK_ColorBLACK), fOpacity(1) {} void applyGraphicsState(SkPaint* paint) { paint->setColor(SkColorSetA(fColor, fOpacity * 255)); @@ -39,7 +37,7 @@ struct PdfColorOperator { }; // TODO(edisonn): better class design. -struct PdfGraphicsState { +struct SkPdfGraphicsState { SkMatrix fMatrix; SkMatrix fMatrixTm; SkMatrix fMatrixTlm; @@ -57,19 +55,19 @@ struct PdfGraphicsState { bool fHasClipPathToApply; SkPath fClipPath; - PdfColorOperator fStroking; - PdfColorOperator fNonStroking; + SkPdfColorOperator fStroking; + SkPdfColorOperator fNonStroking; double fLineWidth; double fTextLeading; double fWordSpace; double fCharSpace; - SkPdfResourceDictionary* fResources; + const SkPdfResourceDictionary* fResources; SkBitmap fSMask; - PdfGraphicsState() { + SkPdfGraphicsState() { fCurPosX = 0.0; fCurPosY = 0.0; fCurFontSize = 0.0; @@ -104,26 +102,30 @@ struct PdfGraphicsState { }; // TODO(edisonn): better class design. -struct PdfInlineImage { +// TODO(edisonn): could we remove it? +// TODO(edisonn): rename to SkPdfInlineImage +struct SkPdfInlineImage { std::map<std::string, std::string> fKeyValuePairs; std::string fImageData; }; // TODO(edisonn): better class design. +// TODO(edisonn): rename to SkPdfContext struct PdfContext { std::stack<SkPdfObject*> fObjectStack; - std::stack<PdfGraphicsState> fStateStack; - PdfGraphicsState fGraphicsState; - SkPdfDoc* fPdfDoc; + std::stack<SkPdfGraphicsState> fStateStack; + SkPdfGraphicsState fGraphicsState; + const SkPodofoParsedPDF* fPdfDoc; SkMatrix fOriginalMatrix; - PdfInlineImage fInlineImage; + SkPdfInlineImage fInlineImage; - PdfContext(SkPdfDoc* doc) : fPdfDoc(doc) {} + PdfContext(const SkPodofoParsedPDF* doc) : fPdfDoc(doc) {} }; -// TODO(edisonn): temporary code, to report how much of the PDF we actually think we rendered. +// TODO(edisonn): temporary code, to report how much of the PDF we actually think we rendered. +// TODO(edisonn): rename to SkPdfResult enum PdfResult { kOK_PdfResult, kPartial_PdfResult, diff --git a/experimental/PdfViewer/SkPdfConfig.h b/experimental/PdfViewer/SkPdfConfig.h new file mode 100644 index 0000000000..1092de17e2 --- /dev/null +++ b/experimental/PdfViewer/SkPdfConfig.h @@ -0,0 +1,19 @@ +#ifndef __DEFINED__SkPdfConfig +#define __DEFINED__SkPdfConfig + +//#define PDF_TRACE +//#define PDF_TRACE_DIFF_IN_PNG +//#define PDF_DEBUG_NO_CLIPING +//#define PDF_DEBUG_NO_PAGE_CLIPING +//#define PDF_DEBUG_3X + +// TODO(edisonn): move in trace util. +#ifdef PDF_TRACE +void SkTraceMatrix(const SkMatrix& matrix, const char* sz); +void SkTraceRect(const SkRect& rect, const char* sz); +#else +#define SkTraceMatrix(a,b) +#define SkTraceRect(a,b) +#endif + +#endif // __DEFINED__SkPdfConfig diff --git a/experimental/PdfViewer/SkPdfFont.cpp b/experimental/PdfViewer/SkPdfFont.cpp index e0cbd2cc1b..733ae8705a 100644 --- a/experimental/PdfViewer/SkPdfFont.cpp +++ b/experimental/PdfViewer/SkPdfFont.cpp @@ -3,6 +3,7 @@ #include "SkStream.h" #include "SkTypeface.h" +#include "SkPdfPodofoTokenizer.h" std::map<std::string, SkPdfStandardFontEntry>& getStandardFonts() { static std::map<std::string, SkPdfStandardFontEntry> gPdfStandardFonts; @@ -164,21 +165,17 @@ SkPdfFont* SkPdfFont::fontFromFontDescriptor(SkPdfFontDescriptorDictionary* fd, } } - if (!pdfStream || !pdfStream->podofo()->GetStream()) { - // TODO(edisonn): report warning to be used in testing. - return NULL; - } - char* uncompressedStream = NULL; - pdf_long uncompressedStreamLength = 0; + long uncompressedStreamLength = 0; - // TODO(edisonn): get rid of try/catch exceptions! We should not throw on user data! - try { - pdfStream->podofo()->GetStream()->GetFilteredCopy(&uncompressedStream, &uncompressedStreamLength); - } catch (PdfError& e) { - // TODO(edisonn): report warning to be used in testing. + // TODO(edisonn): report warning to be used in testing. + if (!pdfStream || + !pdfStream->GetFilteredCopy(&uncompressedStream, &uncompressedStreamLength) || + !uncompressedStream || + !uncompressedStreamLength) { return NULL; } + SkMemoryStream* skStream = new SkMemoryStream(uncompressedStream, uncompressedStreamLength); SkTypeface* face = SkTypeface::CreateFromStream(skStream); @@ -199,12 +196,11 @@ SkPdfFont* fontFromName(SkPdfObject* obj, const char* fontName) { } // TODO(edisonn): perf - make a map - for (int i = 0 ; i < obj->doc()->GetObjects().GetSize(); i++) { - PdfVecObjects& objects = (PdfVecObjects&)obj->doc()->GetObjects(); - const PdfObject* podofoFont = objects[i]; + for (int i = 0 ; i < obj->doc()->objects(); i++) { + const SkPdfObject* podofoFont = obj->doc()->object(i); SkPdfFontDescriptorDictionary* fd = NULL; - if (mapFontDescriptorDictionary(*obj->doc(), *podofoFont, &fd)) { + if (obj->doc()->mapper()->mapFontDescriptorDictionary(podofoFont, &fd)) { if (fd->has_FontName() && fd->FontName() == fontName) { SkPdfFont* font = SkPdfFont::fontFromFontDescriptor(fd, false); if (font) { @@ -289,8 +285,8 @@ SkPdfMultiMasterFont* SkPdfFont::fontFromMultiMasterFontDictionary(SkPdfMultiMas static int skstoi(const SkPdfString* str) { int ret = 0; - for (int i = 0 ; i < str->podofo()->GetString().GetLength(); i++) { - ret = (ret << 8) + ((unsigned char*)str->podofo()->GetString().GetString())[i]; + for (int i = 0 ; i < str->len(); i++) { + ret = (ret << 8) + ((unsigned char*)str->c_str())[i]; } return ret; } @@ -300,7 +296,7 @@ SkPdfToUnicode::SkPdfToUnicode(const SkPdfStream* stream) { fCMapEncodingFlag = NULL; if (stream) { - SkPdfTokenizer tokenizer(stream); + SkPdfPodofoTokenizer* tokenizer = stream->doc()->tokenizerOfStream(stream); PdfToken token; fCMapEncoding = new unsigned short[256 * 256]; @@ -316,15 +312,15 @@ SkPdfToUnicode::SkPdfToUnicode(const SkPdfStream* stream) { //<0000> <005E> <0020> //<005F> <0061> [<00660066> <00660069> <00660066006C>] - while (tokenizer.readToken(&token)) { + while (tokenizer->readToken(&token)) { if (token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "begincodespacerange") == 0) { - while (tokenizer.readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endcodespacerange") == 0)) { -// tokenizer.PutBack(token); -// tokenizer.readToken(&token); + while (tokenizer->readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endcodespacerange") == 0)) { +// tokenizer->PutBack(token); +// tokenizer->readToken(&token); // TODO(edisonn): check token type! ignore/report errors. int start = skstoi(token.fObject->asString()); - tokenizer.readToken(&token); + tokenizer->readToken(&token); int end = skstoi(token.fObject->asString()); for (int i = start; i <= end; i++) { fCMapEncodingFlag[i] |= 1; @@ -333,11 +329,11 @@ SkPdfToUnicode::SkPdfToUnicode(const SkPdfStream* stream) { } if (token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "beginbfchar") == 0) { - while (tokenizer.readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endbfchar") == 0)) { -// tokenizer.PutBack(token); -// tokenizer.readToken(&token); + while (tokenizer->readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endbfchar") == 0)) { +// tokenizer->PutBack(token); +// tokenizer->readToken(&token); int from = skstoi(token.fObject->asString()); - tokenizer.readToken(&token); + tokenizer->readToken(&token); int to = skstoi(token.fObject->asString()); fCMapEncodingFlag[from] |= 2; @@ -346,19 +342,19 @@ SkPdfToUnicode::SkPdfToUnicode(const SkPdfStream* stream) { } if (token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "beginbfrange") == 0) { - while (tokenizer.readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endbfrange") == 0)) { -// tokenizer.PutBack(token); -// tokenizer.readToken(&token); + while (tokenizer->readToken(&token) && !(token.fType == kKeyword_TokenType && strcmp(token.fKeyword, "endbfrange") == 0)) { +// tokenizer->PutBack(token); +// tokenizer->readToken(&token); int start = skstoi(token.fObject->asString()); - tokenizer.readToken(&token); + tokenizer->readToken(&token); int end = skstoi(token.fObject->asString()); - tokenizer.readToken(&token); // [ or just an array directly? -// tokenizer.PutBack(token); + tokenizer->readToken(&token); // [ or just an array directly? +// tokenizer->PutBack(token); if (token.fType == kObject_TokenType && token.fObject->asString()) { -// tokenizer.readToken(&token); +// tokenizer->readToken(&token); int value = skstoi(token.fObject->asString()); for (int i = start; i <= end; i++) { @@ -370,7 +366,7 @@ SkPdfToUnicode::SkPdfToUnicode(const SkPdfStream* stream) { // read one string } else if (token.fType == kObject_TokenType && token.fObject->asArray()) { -// tokenizer.readToken(&token); +// tokenizer->readToken(&token); for (int i = 0; i < token.fObject->asArray()->size(); i++) { fCMapEncodingFlag[start + i] |= 2; fCMapEncoding[start + i] = skstoi((*token.fObject->asArray())[i]->asString()); diff --git a/experimental/PdfViewer/SkPdfFont.h b/experimental/PdfViewer/SkPdfFont.h index 90fe3b0f16..1e9d9ee82f 100644 --- a/experimental/PdfViewer/SkPdfFont.h +++ b/experimental/PdfViewer/SkPdfFont.h @@ -2,7 +2,7 @@ #define __DEFINED__SkPdfFont #include "SkPdfHeaders_autogen.h" -#include "SkPdfPodofoMapper_autogen.h" +#include "SkPdfMapper_autogen.h" #include <map> #include <string> @@ -36,9 +36,9 @@ struct SkUnencodedText { int len; public: - SkUnencodedText(const SkPdfObject* obj) { - text = (void*)obj->podofo()->GetString().GetString(); - len = obj->podofo()->GetString().GetLength(); + SkUnencodedText(const SkPdfString* obj) { + text = (void*)obj->c_str(); + len = obj->len(); } }; diff --git a/experimental/PdfViewer/SkPdfParser.cpp b/experimental/PdfViewer/SkPdfParser.cpp index e4c545f69e..030251250e 100644 --- a/experimental/PdfViewer/SkPdfParser.cpp +++ b/experimental/PdfViewer/SkPdfParser.cpp @@ -37,8 +37,17 @@ __SK_FORCE_IMAGE_DECODER_LINKING; // TODO(edisonn): put drawtext in #ifdefs, so comparations will ignore minor changes in text positioning and font // this way, we look more at other features and layout in diffs +// TODO(edisonn): move trace dump in the get functions, and mapper ones too so it ghappens automatically +/* +#ifdef PDF_TRACE + std::string str; + pdfContext->fGraphicsState.fResources->podofo()->ToString(str); + printf("Print Tf Resources: %s\n", str.c_str()); +#endif + */ + #include "SkPdfHeaders_autogen.h" -#include "SkPdfPodofoMapper_autogen.h" +#include "SkPdfMapper_autogen.h" #include "SkPdfParser.h" #include "SkPdfBasics.h" @@ -46,11 +55,6 @@ __SK_FORCE_IMAGE_DECODER_LINKING; #include "SkPdfFont.h" -bool skpdfmap(const PdfMemDocument& podofoDoc, const PdfObject& podofoObj, SkPdfObject** out) { - return mapObject(podofoDoc, podofoObj, out); -} - - /* * TODO(edisonn): * - all font types and all ppdf font features @@ -97,25 +101,7 @@ int GetColorSpaceComponents(const std::string& colorSpace) { } } -const PdfObject* resolveReferenceObject(const PdfMemDocument* pdfDoc, - const PdfObject* obj, - bool resolveOneElementArrays) { - while (obj && (obj->IsReference() || (resolveOneElementArrays && - obj->IsArray() && - obj->GetArray().GetSize() == 1))) { - if (obj->IsReference()) { - // We need to force the non const, the only update we will do is for recurssion checks. - PdfReference& ref = (PdfReference&)obj->GetReference(); - obj = pdfDoc->GetObjects().GetObject(ref); - } else { - obj = &obj->GetArray()[0]; - } - } - - return obj; -} - -static SkMatrix SkMatrixFromPdfMatrix(double array[6]) { +SkMatrix SkMatrixFromPdfMatrix(double array[6]) { SkMatrix matrix; matrix.setAll(SkDoubleToScalar(array[0]), SkDoubleToScalar(array[2]), @@ -135,17 +121,16 @@ SkMatrix SkMatrixFromPdfArray(SkPdfArray* pdfArray) { // TODO(edisonn): security issue, ret if size() != 6 for (int i = 0; i < 6; i++) { - const PdfObject* elem = resolveReferenceObject(pdfArray->doc(), (*pdfArray)[i]->podofo()); - if (elem == NULL || (!elem->IsReal() && !elem->IsNumber())) { + const SkPdfObject* elem = pdfArray->operator [](i); + if (elem == NULL || (!elem->asNumber() && !elem->asInteger())) { return SkMatrix::I(); // TODO(edisonn): report issue } - array[i] = elem->GetReal(); + array[i] = elem->asNumber() ? elem->asNumber()->value() : elem->asInteger()->value(); } return SkMatrixFromPdfMatrix(array); } -PdfContext* gPdfContext = NULL; SkBitmap* gDumpBitmap = NULL; SkCanvas* gDumpCanvas = NULL; char gLastKeyword[100] = ""; @@ -167,7 +152,7 @@ bool hasVisualEffect(const char* pdfOp) { } // TODO(edisonn): Pass PdfContext and SkCanvasd only with the define for instrumentation. -static bool readToken(SkPdfTokenizer* fTokenizer, PdfToken* token) { +static bool readToken(SkPdfPodofoTokenizer* fTokenizer, PdfToken* token) { bool ret = fTokenizer->readToken(token); gReadOp++; @@ -333,7 +318,7 @@ static SkTypeface* SkTypefaceFromPdfFont(PdfFont* font) { } PdfResult DrawText(PdfContext* pdfContext, - const SkPdfObject* str, + const SkPdfObject* _str, SkCanvas* canvas) { @@ -342,6 +327,13 @@ PdfResult DrawText(PdfContext* pdfContext, skfont = SkPdfFont::Default(); } + const SkPdfString* str = _str->asString(); + + if (str == NULL) { + // TODO(edisonn): report warning + return kIgnoreError_PdfResult; + } + SkUnencodedText binary(str); SkDecodedText decoded; @@ -400,260 +392,6 @@ PdfResult PdfOp_Q(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** loo PdfResult PdfOp_Tw(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper); PdfResult PdfOp_Tc(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper); -// TODO(edisonn): deal with synonyms (/BPC == /BitsPerComponent), here or in GetKey? -// Always pass long form in key, and have a map of long -> short key -bool LongFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - long* data) { - const PdfObject* value = resolveReferenceObject(pdfDoc, - dict.GetKey(PdfName(key))); - - if (value == NULL || !value->IsNumber()) { - return false; - } - if (data == NULL) { - return true; - } - - *data = value->GetNumber(); - return true; -} - -bool LongFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - long* data) { - if (LongFromDictionary(pdfDoc, dict, key, data)) return true; - if (abr == NULL || *abr == '\0') return false; - return LongFromDictionary(pdfDoc, dict, abr, data); -} - -bool DoubleFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - double* data) { - const PdfObject* value = resolveReferenceObject(pdfDoc, - dict.GetKey(PdfName(key))); - - if (value == NULL || (!value->IsReal() && !value->IsNumber())) { - return false; - } - if (data == NULL) { - return true; - } - - *data = value->GetReal(); - return true; -} - -bool DoubleFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - double* data) { - if (DoubleFromDictionary(pdfDoc, dict, key, data)) return true; - if (abr == NULL || *abr == '\0') return false; - return DoubleFromDictionary(pdfDoc, dict, abr, data); -} - - -bool BoolFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - bool* data) { - const PdfObject* value = resolveReferenceObject(pdfDoc, - dict.GetKey(PdfName(key))); - - if (value == NULL || !value->IsBool()) { - return false; - } - if (data == NULL) { - return true; - } - - *data = value->GetBool(); - return true; -} - -bool BoolFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - bool* data) { - if (BoolFromDictionary(pdfDoc, dict, key, data)) return true; - if (abr == NULL || *abr == '\0') return false; - return BoolFromDictionary(pdfDoc, dict, abr, data); -} - -bool NameFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - std::string* data) { - const PdfObject* value = resolveReferenceObject(pdfDoc, - dict.GetKey(PdfName(key)), - true); - if (value == NULL || !value->IsName()) { - return false; - } - if (data == NULL) { - return true; - } - - *data = value->GetName().GetName(); - return true; -} - -bool NameFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - std::string* data) { - if (NameFromDictionary(pdfDoc, dict, key, data)) return true; - if (abr == NULL || *abr == '\0') return false; - return NameFromDictionary(pdfDoc, dict, abr, data); -} - -bool StringFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - std::string* data) { - const PdfObject* value = resolveReferenceObject(pdfDoc, - dict.GetKey(PdfName(key)), - true); - if (value == NULL || (!value->IsString() && !value->IsHexString())) { - return false; - } - if (data == NULL) { - return true; - } - - *data = value->GetString().GetString(); - return true; -} - -bool StringFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - std::string* data) { - if (StringFromDictionary(pdfDoc, dict, key, data)) return true; - if (abr == NULL || *abr == '\0') return false; - return StringFromDictionary(pdfDoc, dict, abr, data); -} - -/* -bool ArrayFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - SkPdfArray** data) { - const PdfObject* value = resolveReferenceObject(pdfDoc, - dict.GetKey(PdfName(key)), - true); - if (value == NULL || !value->IsArray()) { - return false; - } - if (data == NULL) { - return true; - } - - return mapArray(*pdfDoc, *value, data); -} - - -bool ArrayFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkPdfArray** data) { - if (ArrayFromDictionary(pdfDoc, dict, key, data)) return true; - if (abr == NULL || *abr == '\0') return false; - return ArrayFromDictionary(pdfDoc, dict, abr, data); -} - - -bool DictionaryFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - SkPdfDictionary** data) { - const PdfObject* value = resolveReferenceObject(pdfDoc, - dict.GetKey(PdfName(key)), - true); - if (value == NULL || !value->IsDictionary()) { - return false; - } - if (data == NULL) { - return true; - } - - return mapDictionary(*pdfDoc, *value, data); -} - -bool DictionaryFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkPdfDictionary** data) { - if (DictionaryFromDictionary(pdfDoc, dict, key, data)) return true; - if (abr == NULL || *abr == '\0') return false; - return DictionaryFromDictionary(pdfDoc, dict, abr, data); -} - - -bool ObjectFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - SkPdfObject** data) { - const PdfObject* value = resolveReferenceObject(pdfDoc, - dict.GetKey(PdfName(key)), - true); - if (value == NULL) { - return false; - } - if (data == NULL) { - return true; - } - return mapObject(*pdfDoc, *value, data); -} - -bool ObjectFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkPdfObject** data) { - if (ObjectFromDictionary(pdfDoc, dict, key, data)) return true; - if (abr == NULL || *abr == '\0') return false; - return ObjectFromDictionary(pdfDoc, dict, abr, data); -} - -bool StreamFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - SkPdfStream** data) { - const PdfObject* value = resolveReferenceObject(pdfDoc, - dict.GetKey(PdfName(key)), - true); - if (value == NULL) { - return false; - } - if (data == NULL) { - return true; - } - return mapStream(*pdfDoc, *value, data); -} - -bool StreamFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkPdfStream** data) { - if (StreamFromDictionary(pdfDoc, dict, key, data)) return true; - if (abr == NULL || *abr == '\0') return false; - return StreamFromDictionary(pdfDoc, dict, abr, data); -} -*/ - // TODO(edisonn): perf!!! static SkColorTable* getGrayColortable() { @@ -781,7 +519,7 @@ bool transferImageStreamToARGB(unsigned char* uncompressedStream, pdf_long uncom // this functions returns the image, it does not look at the smask. SkBitmap getImageFromObject(PdfContext* pdfContext, const SkPdfImageDictionary* image, bool transparencyMask) { - if (image == NULL || !image->valid()) { + if (image == NULL) { // TODO(edisonn): report warning to be used in testing. return SkBitmap(); } @@ -820,16 +558,15 @@ SkBitmap getImageFromObject(PdfContext* pdfContext, const SkPdfImageDictionary* } */ - const PdfObject* obj = image->podofo(); - char* uncompressedStream = NULL; pdf_long uncompressedStreamLength = 0; PdfResult ret = kPartial_PdfResult; - // TODO(edisonn): get rid of try/catch exceptions! We should not throw on user data! - try { - obj->GetStream()->GetFilteredCopy(&uncompressedStream, &uncompressedStreamLength); - } catch (PdfError& e) { + SkPdfStream* stream = NULL; + image->doc()->mapper()->mapStream(image, &stream); + + if (!stream || !stream->GetFilteredCopy(&uncompressedStream, &uncompressedStreamLength) || + uncompressedStream == NULL || uncompressedStreamLength == 0) { // TODO(edisonn): report warning to be used in testing. return SkBitmap(); } @@ -853,20 +590,10 @@ SkBitmap getImageFromObject(PdfContext* pdfContext, const SkPdfImageDictionary* } SkBitmap getSmaskFromObject(PdfContext* pdfContext, const SkPdfImageDictionary* obj) { - const PdfObject* sMask = resolveReferenceObject(&pdfContext->fPdfDoc->podofo(), - obj->podofo()->GetDictionary().GetKey(PdfName("SMask"))); - -#ifdef PDF_TRACE - std::string str; - if (sMask) { - sMask->ToString(str); - printf("/SMask of /Subtype /Image: %s\n", str.c_str()); - } -#endif + const SkPdfImageDictionary* sMask = obj->SMask(); if (sMask) { - SkPdfImageDictionary skxobjmask(&pdfContext->fPdfDoc->podofo(), sMask); - return getImageFromObject(pdfContext, &skxobjmask, true); + return getImageFromObject(pdfContext, sMask, true); } // TODO(edisonn): implement GS SMask. Default to empty right now. @@ -874,7 +601,7 @@ SkBitmap getSmaskFromObject(PdfContext* pdfContext, const SkPdfImageDictionary* } PdfResult doXObject_Image(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfImageDictionary* skpdfimage) { - if (skpdfimage == NULL || !skpdfimage->valid()) { + if (skpdfimage == NULL) { return kIgnoreError_PdfResult; } @@ -902,103 +629,12 @@ PdfResult doXObject_Image(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfI return kPartial_PdfResult; } -bool SkMatrixFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - SkMatrix** matrix) { - const PdfObject* value = resolveReferenceObject(pdfDoc, - dict.GetKey(PdfName(key))); - - if (value == NULL || !value->IsArray()) { - return false; - } - - if (value->GetArray().GetSize() != 6) { - return false; - } - - double array[6]; - for (int i = 0; i < 6; i++) { - const PdfObject* elem = resolveReferenceObject(pdfDoc, &value->GetArray()[i]); - if (elem == NULL || (!elem->IsReal() && !elem->IsNumber())) { - return false; - } - array[i] = elem->GetReal(); - } - - *matrix = new SkMatrix(); - **matrix = SkMatrixFromPdfMatrix(array); - return true; -} - -bool SkMatrixFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkMatrix** data) { - if (SkMatrixFromDictionary(pdfDoc, dict, key, data)) return true; - if (abr == NULL || *abr == '\0') return false; - return SkMatrixFromDictionary(pdfDoc, dict, abr, data); - -} -bool SkRectFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - SkRect** rect) { - const PdfObject* value = resolveReferenceObject(pdfDoc, - dict.GetKey(PdfName(key))); - if (value == NULL || !value->IsArray()) { - return false; - } - - if (value->GetArray().GetSize() != 4) { - return false; - } - - double array[4]; - for (int i = 0; i < 4; i++) { - const PdfObject* elem = resolveReferenceObject(pdfDoc, &value->GetArray()[i]); - if (elem == NULL || (!elem->IsReal() && !elem->IsNumber())) { - return false; - } - array[i] = elem->GetReal(); - } - - *rect = new SkRect(); - **rect = SkRect::MakeLTRB(SkDoubleToScalar(array[0]), - SkDoubleToScalar(array[1]), - SkDoubleToScalar(array[2]), - SkDoubleToScalar(array[3])); - return true; -} - -bool SkRectFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkRect** data) { - if (SkRectFromDictionary(pdfDoc, dict, key, data)) return true; - if (abr == NULL || *abr == '\0') return false; - return SkRectFromDictionary(pdfDoc, dict, abr, data); - -} - - -SkPdfObject* get(const SkPdfObject* obj, const char* key, const char* abr = "") { - SkPdfObject* ret = NULL; - if (obj == NULL) return NULL; - const SkPdfDictionary* dict = obj->asDictionary(); - if (dict == NULL) return NULL; - if (!dict->podofo()->IsDictionary()) return NULL; - ObjectFromDictionary(dict->doc(), dict->podofo()->GetDictionary(), key, abr, &ret); - return ret; -} PdfResult doXObject_Form(PdfContext* pdfContext, SkCanvas* canvas, SkPdfType1FormDictionary* skobj) { - if (!skobj || !skobj->podofo() || !skobj->podofo()->HasStream() || skobj->podofo()->GetStream() == NULL || skobj->podofo()->GetStream()->GetLength() == 0) { - return kOK_PdfResult; + if (!skobj) { + return kIgnoreError_PdfResult; } PdfOp_q(pdfContext, canvas, NULL); @@ -1029,16 +665,21 @@ PdfResult doXObject_Form(PdfContext* pdfContext, SkCanvas* canvas, SkPdfType1For // TODO(edisonn): iterate smart on the stream even if it is compressed, tokenize it as we go. // For this PdfContentsTokenizer needs to be extended. - PdfResult ret = kPartial_PdfResult; - SkPdfTokenizer tokenizer(skobj); - PdfMainLooper looper(NULL, &tokenizer, pdfContext, canvas); - looper.loop(); + SkPdfStream* stream = NULL; + skobj->doc()->mapper()->mapStream(skobj, &stream); + + SkPdfPodofoTokenizer* tokenizer = skobj->doc()->tokenizerOfStream(stream); + if (tokenizer != NULL) { + PdfMainLooper looper(NULL, tokenizer, pdfContext, canvas); + looper.loop(); + delete tokenizer; + } // TODO(edisonn): should we restore the variable stack at the same state? // There could be operands left, that could be consumed by a parent tokenizer when we pop. canvas->restore(); PdfOp_Q(pdfContext, canvas, NULL); - return ret; + return kPartial_PdfResult; } PdfResult doXObject_PS(PdfContext* pdfContext, SkCanvas* canvas, const PdfObject& obj) { @@ -1046,8 +687,8 @@ PdfResult doXObject_PS(PdfContext* pdfContext, SkCanvas* canvas, const PdfObject } PdfResult doType3Char(PdfContext* pdfContext, SkCanvas* canvas, SkPdfObject* skobj, SkRect bBox, SkMatrix matrix, double textSize) { - if (!skobj || !skobj->podofo() || !skobj->podofo()->HasStream() || skobj->podofo()->GetStream() == NULL || skobj->podofo()->GetStream()->GetLength() == 0) { - return kOK_PdfResult; + if (!skobj) { + return kIgnoreError_PdfResult; } PdfOp_q(pdfContext, canvas, NULL); @@ -1073,52 +714,58 @@ PdfResult doType3Char(PdfContext* pdfContext, SkCanvas* canvas, SkPdfObject* sko // TODO(edisonn): iterate smart on the stream even if it is compressed, tokenize it as we go. // For this PdfContentsTokenizer needs to be extended. - PdfResult ret = kPartial_PdfResult; - SkPdfTokenizer tokenizer(skobj); - PdfMainLooper looper(NULL, &tokenizer, pdfContext, canvas); - looper.loop(); + SkPdfStream* stream = NULL; + skobj->doc()->mapper()->mapStream(skobj, &stream); + + SkPdfPodofoTokenizer* tokenizer = skobj->doc()->tokenizerOfStream(stream); + if (tokenizer != NULL) { + PdfMainLooper looper(NULL, tokenizer, pdfContext, canvas); + looper.loop(); + delete tokenizer; + } // TODO(edisonn): should we restore the variable stack at the same state? // There could be operands left, that could be consumed by a parent tokenizer when we pop. canvas->restore(); PdfOp_Q(pdfContext, canvas, NULL); - return ret; + + return kPartial_PdfResult; } // TODO(edisonn): faster, have the property on the SkPdfObject itself? -std::set<const PdfObject*> gInRendering; +std::set<const void*> gInRendering; class CheckRecursiveRendering { - const PdfObject& fObj; + const void* fUniqueData; public: - CheckRecursiveRendering(const PdfObject& obj) : fObj(obj) { - gInRendering.insert(&obj); + CheckRecursiveRendering(const SkPdfObject* obj) : fUniqueData(obj->data()) { + gInRendering.insert(obj); } ~CheckRecursiveRendering() { //SkASSERT(fObj.fInRendering); - gInRendering.erase(&fObj); + gInRendering.erase(fUniqueData); } - static bool IsInRendering(const PdfObject& obj) { - return gInRendering.find(&obj) != gInRendering.end(); + static bool IsInRendering(const SkPdfObject* obj) { + return gInRendering.find(obj->data()) != gInRendering.end(); } }; PdfResult doXObject(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfObject& obj) { - if (CheckRecursiveRendering::IsInRendering(*obj.podofo())) { + if (CheckRecursiveRendering::IsInRendering(&obj)) { // Oops, corrupt PDF! return kIgnoreError_PdfResult; } - CheckRecursiveRendering checkRecursion(*obj.podofo()); + CheckRecursiveRendering checkRecursion(&obj); // TODO(edisonn): check type SkPdfXObjectDictionary* skobj = NULL; - if (!mapXObjectDictionary(obj, &skobj)) return kIgnoreError_PdfResult; + if (!obj.doc()->mapper()->mapXObjectDictionary(&obj, &skobj)) return kIgnoreError_PdfResult; - if (!skobj || !skobj->valid()) return kIgnoreError_PdfResult; + if (!skobj) return kIgnoreError_PdfResult; PdfResult ret = kIgnoreError_PdfResult; switch (skobj->getType()) @@ -1178,7 +825,7 @@ PdfResult PdfOp_cm(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo printf("%f ", array[i]); } printf("\n"); - SkTraceMatrix(pdfContext->fGraphicsState.fMatrix); + SkTraceMatrix(pdfContext->fGraphicsState.fMatrix, "cm"); #endif return kOK_PdfResult; @@ -1213,18 +860,26 @@ PdfResult PdfOp_TD(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo double tx = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->fObjectStack.pop(); // TODO(edisonn): Create factory methods or constructors so podofo is hidden - PdfObject _ty(PdfVariant(-ty)); - pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc->podofo(), &_ty)); + SkPdfNumber* _ty = pdfContext->fPdfDoc->createNumber(-ty); + pdfContext->fObjectStack.push(_ty); PdfOp_TL(pdfContext, canvas, looper); - PdfObject vtx(PdfVariant(-(-tx))); // TODO(edisonn): Hmm, the compiler thinks I have here a function pointer if we use (tx), but not -(-tx) - pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc->podofo(), &vtx)); + SkPdfNumber* vtx = pdfContext->fPdfDoc->createNumber(tx); + pdfContext->fObjectStack.push(vtx); + + SkPdfNumber* vty = pdfContext->fPdfDoc->createNumber(ty); + pdfContext->fObjectStack.push(vty); + + PdfResult ret = PdfOp_Td(pdfContext, canvas, looper); - PdfObject vty(PdfVariant(-(-ty))); - pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc->podofo(), &vty)); + // TODO(edisonn): delete all the objects after rendering was complete, in this way pdf is rendered faster + // and the cleanup can happen while the user looks at the image + delete _ty; + delete vtx; + delete vty; - return PdfOp_Td(pdfContext, canvas, looper); + return ret; } PdfResult PdfOp_Tm(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) { @@ -1257,12 +912,18 @@ PdfResult PdfOp_Tm(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo //0 Tl Td //where Tl is the current leading parameter in the text state PdfResult PdfOp_T_star(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) { - PdfObject zero(PdfVariant(0.0)); - PdfObject tl(PdfVariant(-(-pdfContext->fGraphicsState.fTextLeading))); + SkPdfNumber* zero = pdfContext->fPdfDoc->createNumber(0.0); + SkPdfNumber* tl = pdfContext->fPdfDoc->createNumber(pdfContext->fGraphicsState.fTextLeading); + + pdfContext->fObjectStack.push(zero); + pdfContext->fObjectStack.push(tl); + + PdfResult ret = PdfOp_Td(pdfContext, canvas, looper); - pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc->podofo(), &zero)); - pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc->podofo(), &tl)); - return PdfOp_Td(pdfContext, canvas, looper); + delete zero; // TODO(edisonn): do not alocate and delete constants! + delete tl; + + return ret; } PdfResult PdfOp_m(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) { @@ -1525,25 +1186,12 @@ PdfResult PdfOp_Tf(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo #ifdef PDF_TRACE printf("font name: %s\n", fontName.c_str()); - std::string str; - pdfContext->fGraphicsState.fResources->podofo()->ToString(str); - printf("Print Tf Resources: %s\n", str.c_str()); - pdfContext->fGraphicsState.fResources->Font()->podofo()->ToString(str); - printf("Print Tf Resources/Font: %s\n", str.c_str()); #endif SkPdfFontDictionary* fd = NULL; if (pdfContext->fGraphicsState.fResources->Font()) { SkPdfObject* objFont = pdfContext->fGraphicsState.fResources->Font()->get(fontName.c_str()); - mapFontDictionary(*objFont, &fd); - -#ifdef PDF_TRACE - objFont->podofo()->ToString(str); - printf("Print Font loaded: %s\n", str.c_str()); - fd->podofo()->ToString(str); - printf("Print Font loaded and resolved and upgraded: %s\n", str.c_str()); -#endif - + objFont->doc()->mapper()->mapFontDictionary(objFont, &fd); } SkPdfFont* skfont = SkPdfFont::fontFromPdfDictionary(fd); @@ -1638,7 +1286,7 @@ PdfResult PdfOp_TJ(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo return kPartial_PdfResult; // TODO(edisonn): Implement fully DrawText before returing OK. } -PdfResult PdfOp_CS_cs(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperator* colorOperator) { +PdfResult PdfOp_CS_cs(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) { colorOperator->fColorSpace = pdfContext->fObjectStack.top()->asName()->value(); pdfContext->fObjectStack.pop(); return kOK_PdfResult; } @@ -1651,7 +1299,7 @@ PdfResult PdfOp_cs(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo return PdfOp_CS_cs(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStroking); } -PdfResult PdfOp_SC_sc(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperator* colorOperator) { +PdfResult PdfOp_SC_sc(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) { double c[4]; pdf_int64 v[4]; @@ -1668,9 +1316,9 @@ PdfResult PdfOp_SC_sc(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperator for (int i = n - 1; i >= 0 ; i--) { if (doubles) { - c[i] = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->fObjectStack.pop(); + c[i] = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->fObjectStack.pop(); } else { - v[i] = pdfContext->fObjectStack.top()->asInteger()->value(); pdfContext->fObjectStack.pop(); + v[i] = pdfContext->fObjectStack.top()->asInteger()->value(); pdfContext->fObjectStack.pop(); } } @@ -1689,7 +1337,7 @@ PdfResult PdfOp_sc(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo return PdfOp_SC_sc(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStroking); } -PdfResult PdfOp_SCN_scn(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperator* colorOperator) { +PdfResult PdfOp_SCN_scn(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) { PdfString name; if (pdfContext->fObjectStack.top()->asName()) { @@ -1710,7 +1358,7 @@ PdfResult PdfOp_scn(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** l return PdfOp_SCN_scn(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStroking); } -PdfResult PdfOp_G_g(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperator* colorOperator) { +PdfResult PdfOp_G_g(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) { double gray = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->fObjectStack.pop(); return kNYI_PdfResult; } @@ -1723,7 +1371,7 @@ PdfResult PdfOp_g(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** loo return PdfOp_G_g(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStroking); } -PdfResult PdfOp_RG_rg(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperator* colorOperator) { +PdfResult PdfOp_RG_rg(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) { double b = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->fObjectStack.pop(); double g = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->fObjectStack.pop(); double r = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->fObjectStack.pop(); @@ -1741,7 +1389,7 @@ PdfResult PdfOp_rg(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo return PdfOp_RG_rg(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStroking); } -PdfResult PdfOp_K_k(PdfContext* pdfContext, SkCanvas* canvas, PdfColorOperator* colorOperator) { +PdfResult PdfOp_K_k(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) { // TODO(edisonn): spec has some rules about overprint, implement them. double k = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->fObjectStack.pop(); double y = pdfContext->fObjectStack.top()->asNumber()->value(); pdfContext->fObjectStack.pop(); @@ -1896,13 +1544,8 @@ PdfResult PdfOp_gs(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** lo SkPdfObject* value = extGStateDictionary->get(name.c_str()); -#ifdef PDF_TRACE -// value->ToString(str); -// printf("gs object value: %s\n", str.c_str()); -#endif - SkPdfGraphicsStateDictionary* gs = NULL; - mapGraphicsStateDictionary(*value, &gs); + value->doc()->mapper()->mapGraphicsStateDictionary(value, &gs); // TODO(edisonn): now load all those properties in graphic state. if (gs == NULL) { @@ -2300,60 +1943,52 @@ void PdfCompatibilitySectionLooper::loop() { // references automatically. bool SkPdfViewer::load(const SkString inputFileName, SkPicture* out) { - try + std::cout << "Init: " << inputFileName.c_str() << std::endl; + + SkPodofoParsedPDF* doc = new SkPodofoParsedPDF(inputFileName.c_str()); + if (!doc->pages()) { - std::cout << "Init: " << inputFileName.c_str() << std::endl; + std::cout << "ERROR: Empty Document" << inputFileName.c_str() << std::endl; + return false; + } else { - SkPdfDoc doc(inputFileName.c_str()); - if (!doc.pages()) - { - std::cout << "ERROR: Empty Document" << inputFileName.c_str() << std::endl; - return false; - } else { + for (int pn = 0; pn < doc->pages(); ++pn) { + // TODO(edisonn): implement inheritance properties as per PDF spec + //SkRect rect = page->MediaBox(); + SkRect rect = doc->MediaBox(pn); - for (int pn = 0; pn < doc.pages(); ++pn) { - // TODO(edisonn): implement inheritance properties as per PDF spec - //SkRect rect = page->MediaBox(); - SkRect rect = doc.MediaBox(pn); - - #ifdef PDF_TRACE - printf("Page Width: %f, Page Height: %f\n", SkScalarToDouble(rect.width()), SkScalarToDouble(rect.height())); - #endif - - // TODO(edisonn): page->GetCropBox(), page->GetTrimBox() ... how to use? - - SkBitmap bitmap; - #ifdef PDF_DEBUG_3X - setup_bitmap(&bitmap, 3 * (int)SkScalarToDouble(rect.width()), 3 * (int)SkScalarToDouble(rect.height())); - #else - setup_bitmap(&bitmap, (int)SkScalarToDouble(rect.width()), (int)SkScalarToDouble(rect.height())); - #endif - SkAutoTUnref<SkDevice> device(SkNEW_ARGS(SkDevice, (bitmap))); - SkCanvas canvas(device); - - gDumpBitmap = &bitmap; - - doc.drawPage(pn, &canvas); - - SkString out; - if (doc.pages() > 1) { - out.appendf("%s-%i.png", inputFileName.c_str(), pn); - } else { - out = inputFileName; - // .pdf -> .png - out[out.size() - 2] = 'n'; - out[out.size() - 1] = 'g'; - } - SkImageEncoder::EncodeFile(out.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100); +#ifdef PDF_TRACE + printf("Page Width: %f, Page Height: %f\n", SkScalarToDouble(rect.width()), SkScalarToDouble(rect.height())); +#endif + + // TODO(edisonn): page->GetCropBox(), page->GetTrimBox() ... how to use? + + SkBitmap bitmap; +#ifdef PDF_DEBUG_3X + setup_bitmap(&bitmap, 3 * (int)SkScalarToDouble(rect.width()), 3 * (int)SkScalarToDouble(rect.height())); +#else + setup_bitmap(&bitmap, (int)SkScalarToDouble(rect.width()), (int)SkScalarToDouble(rect.height())); +#endif + SkAutoTUnref<SkDevice> device(SkNEW_ARGS(SkDevice, (bitmap))); + SkCanvas canvas(device); + + gDumpBitmap = &bitmap; + + gDumpCanvas = &canvas; + doc->drawPage(pn, &canvas); + + SkString out; + if (doc->pages() > 1) { + out.appendf("%s-%i.png", inputFileName.c_str(), pn); + } else { + out = inputFileName; + // .pdf -> .png + out[out.size() - 2] = 'n'; + out[out.size() - 1] = 'g'; } - return true; + SkImageEncoder::EncodeFile(out.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100); } - } - catch( PdfError & e ) - { - e.PrintErrorMsg(); - std::cout << "ERROR: PDF can't be parsed!" << inputFileName.c_str() << std::endl; - return false; + return true; } return true; diff --git a/experimental/PdfViewer/SkPdfParser.h b/experimental/PdfViewer/SkPdfParser.h index c156004f60..5841b12c3b 100644 --- a/experimental/PdfViewer/SkPdfParser.h +++ b/experimental/PdfViewer/SkPdfParser.h @@ -5,167 +5,30 @@ * found in the LICENSE file. */ -#include "podofo.h" #include "SkPdfHeaders_autogen.h" -#include "SkPdfPodofoMapper_autogen.h" +#include "SkPdfMapper_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 { - PdfMemDocument* fDoc; - PdfContentsTokenizer* fTokenizer; - - char* fUncompressedStream; - pdf_long fUncompressedStreamLength; - - bool fEmpty; - bool fHasPutBack; - PdfToken fPutBack; - -public: - SkPdfTokenizer(PdfMemDocument* doc = NULL, PdfContentsTokenizer* tokenizer = NULL) : fDoc(doc), fTokenizer(tokenizer), fUncompressedStream(NULL), fUncompressedStreamLength(0), fEmpty(false), fHasPutBack(false) {} - SkPdfTokenizer(const SkPdfObject* objWithStream) : fDoc(NULL), fTokenizer(NULL), fEmpty(false), fHasPutBack(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), fUncompressedStream(NULL), fUncompressedStreamLength(0), fEmpty(false), fHasPutBack(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); - mapObject(*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; - } -}; +#include "SkPdfBasics.h" +#include "SkPdfPodofoTokenizer.h" extern "C" PdfContext* gPdfContext; extern "C" SkBitmap* gDumpBitmap; extern "C" SkCanvas* gDumpCanvas; -// TODO(edisonn): move in trace util. -#ifdef PDF_TRACE -static void SkTraceMatrix(const SkMatrix& matrix, const char* sz = "") { - printf("SkMatrix %s ", sz); - for (int i = 0 ; i < 9 ; i++) { - printf("%f ", SkScalarToDouble(matrix.get(i))); - } - printf("\n"); -} - -static void SkTraceRect(const SkRect& rect, const char* sz = "") { - printf("SkRect %s ", sz); - printf("x = %f ", SkScalarToDouble(rect.x())); - printf("y = %f ", SkScalarToDouble(rect.y())); - printf("w = %f ", SkScalarToDouble(rect.width())); - printf("h = %f ", SkScalarToDouble(rect.height())); - printf("\n"); -} - -#else -#define SkTraceMatrix(a,b) -#define SkTraceRect(a,b) -#endif - // TODO(edisonn): Document PdfTokenLooper and subclasses. class PdfTokenLooper { protected: PdfTokenLooper* fParent; - SkPdfTokenizer* fTokenizer; + SkPdfPodofoTokenizer* fTokenizer; PdfContext* fPdfContext; SkCanvas* fCanvas; public: PdfTokenLooper(PdfTokenLooper* parent, - SkPdfTokenizer* tokenizer, + SkPdfPodofoTokenizer* tokenizer, PdfContext* pdfContext, SkCanvas* canvas) : fParent(parent), fTokenizer(tokenizer), fPdfContext(pdfContext), fCanvas(canvas) {} @@ -184,7 +47,7 @@ public: class PdfMainLooper : public PdfTokenLooper { public: PdfMainLooper(PdfTokenLooper* parent, - SkPdfTokenizer* tokenizer, + SkPdfPodofoTokenizer* tokenizer, PdfContext* pdfContext, SkCanvas* canvas) : PdfTokenLooper(parent, tokenizer, pdfContext, canvas) {} @@ -212,119 +75,6 @@ public: virtual void loop(); }; -class SkPdfDoc { - PdfMemDocument fDoc; -public: - - PdfMemDocument& podofo() {return fDoc;} - - SkPdfDoc(const char* path) : fDoc(path) {} - - int pages() { - return fDoc.GetPageCount(); - } - - double width(int n) { - PdfRect rect = fDoc.GetPage(n)->GetMediaBox(); - return rect.GetWidth() + rect.GetLeft(); - } - - double height(int n) { - PdfRect rect = fDoc.GetPage(n)->GetMediaBox(); - return rect.GetHeight() + rect.GetBottom(); - } - - // Can return NULL - SkPdfPageObjectDictionary* page(int n) { - SkPdfPageObjectDictionary* page = NULL; - mapPageObjectDictionary(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; - } - - void drawPage(int n, SkCanvas* canvas) { - SkPdfPageObjectDictionary* pg = page(n); - SkPdfTokenizer* tokenizer = tokenizerOfPage(n); - - PdfContext pdfContext(this); - pdfContext.fOriginalMatrix = SkMatrix::I(); - pdfContext.fGraphicsState.fResources = NULL; - mapResourceDictionary(*pg->Resources(), &pdfContext.fGraphicsState.fResources); - - gPdfContext = &pdfContext; - gDumpCanvas = canvas; - - // TODO(edisonn): get matrix stuff right. - // TODO(edisonn): add DPI/scale/zoom. - SkScalar z = SkIntToScalar(0); - SkRect rect = MediaBox(n); - SkScalar w = rect.width(); - SkScalar h = rect.height(); - - SkPoint pdfSpace[4] = {SkPoint::Make(z, z), SkPoint::Make(w, z), SkPoint::Make(w, h), SkPoint::Make(z, h)}; -// SkPoint skiaSpace[4] = {SkPoint::Make(z, h), SkPoint::Make(w, h), SkPoint::Make(w, z), SkPoint::Make(z, z)}; - - // TODO(edisonn): add flag for this app to create sourunding buffer zone - // TODO(edisonn): add flagg for no clipping. - // Use larger image to make sure we do not draw anything outside of page - // could be used in tests. - -#ifdef PDF_DEBUG_3X - SkPoint skiaSpace[4] = {SkPoint::Make(w+z, h+h), SkPoint::Make(w+w, h+h), SkPoint::Make(w+w, h+z), SkPoint::Make(w+z, h+z)}; -#else - SkPoint skiaSpace[4] = {SkPoint::Make(z, h), SkPoint::Make(w, h), SkPoint::Make(w, z), SkPoint::Make(z, z)}; -#endif - //SkPoint pdfSpace[2] = {SkPoint::Make(z, z), SkPoint::Make(w, h)}; - //SkPoint skiaSpace[2] = {SkPoint::Make(w, z), SkPoint::Make(z, h)}; - - //SkPoint pdfSpace[2] = {SkPoint::Make(z, z), SkPoint::Make(z, h)}; - //SkPoint skiaSpace[2] = {SkPoint::Make(z, h), SkPoint::Make(z, z)}; - - //SkPoint pdfSpace[3] = {SkPoint::Make(z, z), SkPoint::Make(z, h), SkPoint::Make(w, h)}; - //SkPoint skiaSpace[3] = {SkPoint::Make(z, h), SkPoint::Make(z, z), SkPoint::Make(w, 0)}; - - SkAssertResult(pdfContext.fOriginalMatrix.setPolyToPoly(pdfSpace, skiaSpace, 4)); - SkTraceMatrix(pdfContext.fOriginalMatrix, "Original matrix"); - - - pdfContext.fGraphicsState.fMatrix = pdfContext.fOriginalMatrix; - pdfContext.fGraphicsState.fMatrixTm = pdfContext.fGraphicsState.fMatrix; - pdfContext.fGraphicsState.fMatrixTlm = pdfContext.fGraphicsState.fMatrix; - - canvas->setMatrix(pdfContext.fOriginalMatrix); - -#ifndef PDF_DEBUG_NO_PAGE_CLIPING - canvas->clipRect(SkRect::MakeXYWH(z, z, w, h), SkRegion::kIntersect_Op, true); -#endif - -// erase with red before? -// SkPaint paint; -// paint.setColor(SK_ColorRED); -// canvas->drawRect(rect, paint); - - PdfMainLooper looper(NULL, tokenizer, &pdfContext, canvas); - looper.loop(); - - delete tokenizer; - - - canvas->flush(); - } - - SkPdfTokenizer* tokenizerOfPage(int n) { - PdfContentsTokenizer* t = new PdfContentsTokenizer(fDoc.GetPage(n)); - return new SkPdfTokenizer(&fDoc, t); - } -}; - // TODO(edisonn): move in another file class SkPdfViewer : public SkRefCnt { public: diff --git a/experimental/PdfViewer/SkPdfUtils.cpp b/experimental/PdfViewer/SkPdfUtils.cpp index 29e35482ac..507077f163 100644 --- a/experimental/PdfViewer/SkPdfUtils.cpp +++ b/experimental/PdfViewer/SkPdfUtils.cpp @@ -1,37 +1,2 @@ #include "SkPdfUtils.h" -bool ArrayFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkPdfArray* data) {return false;} - -bool FileSpecFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkPdfFileSpec* data) {return false;} - -bool StreamFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkPdfStream** data); - -bool TreeFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkPdfTree** data) {return false;} - -bool DateFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkPdfDate* data) {return false;} - -bool FunctionFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkPdfFunction* data) {return false;} diff --git a/experimental/PdfViewer/SkPdfUtils.h b/experimental/PdfViewer/SkPdfUtils.h index 858ab8e4e3..03aacf671a 100644 --- a/experimental/PdfViewer/SkPdfUtils.h +++ b/experimental/PdfViewer/SkPdfUtils.h @@ -1,124 +1,12 @@ #ifndef __DEFINED__SkPdfUtils #define __DEFINED__SkPdfUtils -#include "podofo.h" -using namespace PoDoFo; - #include "SkPdfBasics.h" -const PdfObject* resolveReferenceObject(const PdfMemDocument* pdfDoc, - const PdfObject* obj, - bool resolveOneElementArrays = false); - -bool LongFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - long* data); - -bool DoubleFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - double* data); - -bool BoolFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - bool* data); - -bool NameFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - std::string* data); - -bool StringFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - std::string* data); -/* -class SkPdfDictionary; -bool DictionaryFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkPdfDictionary** data); -*/ - -bool skpdfmap(const PdfMemDocument& podofoDoc, const PdfObject& podofoObj, SkPdfObject** out); - - -class SkPdfObject; -bool ObjectFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkPdfObject** data); - - -struct SkPdfFileSpec {}; class SkPdfArray; -class SkPdfStream; -struct SkPdfDate {}; -struct SkPdfTree {}; -struct SkPdfFunction {}; - -bool ArrayFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkPdfArray** data); - -bool SkMatrixFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkMatrix** data); - -bool FileSpecFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkPdfFileSpec* data); - - -bool StreamFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkPdfStream** data); - -bool TreeFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkPdfTree** data); - -bool DateFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkPdfDate* data); - -bool SkRectFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkRect** data); - -bool FunctionFromDictionary(const PdfMemDocument* pdfDoc, - const PdfDictionary& dict, - const char* key, - const char* abr, - SkPdfFunction* data); SkMatrix SkMatrixFromPdfArray(SkPdfArray* pdfArray); PdfResult doType3Char(PdfContext* pdfContext, SkCanvas* canvas, SkPdfObject* skobj, SkRect bBox, SkMatrix matrix, double textSize); -#include "SkPdfPodofoMapper_autogen.h" - #endif // __DEFINED__SkPdfUtils diff --git a/experimental/PdfViewer/autogen.sh b/experimental/PdfViewer/autogen.sh new file mode 100755 index 0000000000..a1dcf67a5b --- /dev/null +++ b/experimental/PdfViewer/autogen.sh @@ -0,0 +1,5 @@ +rm pdfparser/autogen/* +rm pdfparser/native/autogen/* +rm pdfparser/podofo/autogen/* +#python spec2def.py PdfReference-okular-1.txt autogen/pdfspec_autogen.py +#python generate_code.py 'pdfparser/' diff --git a/experimental/PdfViewer/autogen/__init__.py b/experimental/PdfViewer/autogen/__init__.py new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/experimental/PdfViewer/autogen/__init__.py diff --git a/experimental/PdfViewer/generate_code.py b/experimental/PdfViewer/generate_code.py index 69e06b633b..baefab39ba 100644 --- a/experimental/PdfViewer/generate_code.py +++ b/experimental/PdfViewer/generate_code.py @@ -6,25 +6,25 @@ import datatypes from autogen.pdfspec_autogen import * knowTypes = { -'(any)': ['SkPdfObject*', 'ObjectFromDictionary', datatypes.CppNull(), 'true'], -'(undefined)': ['SkPdfObject*', 'ObjectFromDictionary', datatypes.CppNull(), 'true'], -'(various)': ['SkPdfObject*', 'ObjectFromDictionary', datatypes.CppNull(), 'true'], -'array': ['SkPdfArray*', 'ArrayFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == ePdfDataType_Array'], -'boolean': ['bool', 'BoolFromDictionary', datatypes.PdfBoolean('false'), 'ret->podofo()->GetDataType() == ePdfDataType_Bool'], -'date': ['SkPdfDate', 'DateFromDictionary', datatypes.PdfDateNever(), 'ret->podofo()->GetDataType() == ePdfDataType_Array'], -'dictionary': ['SkPdfDictionary*', 'DictionaryFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == ePdfDataType_Dictionary'], -'function': ['SkPdfFunction', 'FunctionFromDictionary', datatypes.PdfFunctionNone(), 'ret->podofo()->GetDataType() == ePdfDataType_Reference'], -'integer': ['long', 'LongFromDictionary', datatypes.PdfInteger(0), 'ret->podofo()->GetDataType() == ePdfDataType_Number'], -'file_specification': ['SkPdfFileSpec', 'FileSpecFromDictionary', datatypes.FileSpecNone(), 'ret->podofo()->GetDataType() == ePdfDataType_Reference'], -'name': ['std::string', 'NameFromDictionary', datatypes.PdfString('""'), 'ret->podofo()->GetDataType() == ePdfDataType_Name'], -'tree': ['SkPdfTree*', 'TreeFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == ePdfDataType_Reference'], -'number': ['double', 'DoubleFromDictionary', datatypes.PdfNumber(0), 'ret->podofo()->GetDataType() == ePdfDataType_Real || ret->podofo()->GetDataType() == ePdfDataType_Number'], -'rectangle': ['SkRect*', 'SkRectFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == ePdfDataType_Array && ret->podofo()->GetArray().GetLength() == 4'], +'(any)': ['SkPdfObject*', 'SkPdfObjectFromDictionary', datatypes.CppNull(), 'true', 'use a mapper'], +'(undefined)': ['SkPdfObject*', 'SkPdfObjectFromDictionary', datatypes.CppNull(), 'true', 'use a mapper'], +'(various)': ['SkPdfObject*', 'SkPdfObjectFromDictionary', datatypes.CppNull(), 'true', 'use a mapper'], +'array': ['SkPdfArray*', 'ArrayFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Array'], +'boolean': ['bool', 'BoolFromDictionary', datatypes.PdfBoolean('false'), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Bool'], +'date': ['SkPdfDate', 'DateFromDictionary', datatypes.PdfDateNever(), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Array'], +'dictionary': ['SkPdfDictionary*', 'SkPdfDictionaryFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Dictionary', 'use a mapper'], +'function': ['SkPdfFunction', 'FunctionFromDictionary', datatypes.PdfFunctionNone(), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Reference'], +'integer': ['long', 'LongFromDictionary', datatypes.PdfInteger(0), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Number'], +'file_specification': ['SkPdfFileSpec', 'FileSpecFromDictionary', datatypes.FileSpecNone(), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Reference'], +'name': ['std::string', 'NameFromDictionary', datatypes.PdfString('""'), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Name'], +'tree': ['SkPdfTree*', 'TreeFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Reference'], +'number': ['double', 'DoubleFromDictionary', datatypes.PdfNumber(0), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Real || ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Number'], +'rectangle': ['SkRect*', 'SkRectFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Array && ret->podofo()->GetArray().GetLength() == 4'], 'stream': ['SkPdfStream*', 'StreamFromDictionary', datatypes.CppNull(), 'ret->podofo()->HasStream()'], -'string': ['std::string', 'StringFromDictionary', datatypes.PdfString('""'), 'ret->podofo()->GetDataType() == ePdfDataType_String || ret->podofo()->GetDataType() == ePdfDataType_HexString'], -'text': ['std::string', 'StringFromDictionary', datatypes.PdfString('""'), 'ret->podofo()->GetDataType() == ePdfDataType_String || ret->podofo()->GetDataType() == ePdfDataType_HexString'], -'text string': ['std::string', 'StringFromDictionary', datatypes.PdfString('""'), 'ret->podofo()->GetDataType() == ePdfDataType_String || ret->podofo()->GetDataType() == ePdfDataType_HexString'], -'matrix': ['SkMatrix*', 'SkMatrixFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == ePdfDataType_Array && ret->podofo()->GetArray().GetLength() == 4'], +'string': ['std::string', 'StringFromDictionary', datatypes.PdfString('""'), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_String || ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_HexString'], +'text': ['std::string', 'StringFromDictionary', datatypes.PdfString('""'), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_String || ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_HexString'], +'text string': ['std::string', 'StringFromDictionary', datatypes.PdfString('""'), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_String || ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_HexString'], +'matrix': ['SkMatrix*', 'SkMatrixFromDictionary', datatypes.CppNull(), 'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Array && ret->podofo()->GetArray().GetLength() == 4'], } @@ -101,8 +101,8 @@ class PdfClass: def __init__(self, name, base, comment): self.fFields = [] self.fIncludes = [] - self.fCCPublic = [] - self.fCCPrivate = [] + self.fCCPublicPodofo = [] + self.fCCPublicPodofoCpp = [] self.fName = name self.fBase = base self.fComment = comment @@ -140,14 +140,14 @@ class PdfClass: self.fIncludes.append(path) return self - def carbonCopyPublic(self, cc): - self.fCCPublic.append(cc) + def carbonCopyPublicPodofo(self, cc): + self.fCCPublicPodofo.append(cc) return self - def carbonCopyPrivate(self, cc): - self.fCCPrivate.append(cc) + def carbonCopyPublicPodofoCpp(self, cc): + self.fCCPublicPodofoCpp.append(cc) return self - + def done(self): return @@ -179,40 +179,42 @@ class PdfClassManager: fileEnums.write(' ' + cls.fEnumEnd + ',\n') - def writeAsNull(self, fileClass, cls, enumToCls): - fileClass.write(' virtual SkPdf' + cls.fName +'* as' + cls.fName + '() {return NULL;}\n') - fileClass.write(' virtual const SkPdf' + cls.fName +'* as' + cls.fName + '() const {return NULL;}\n') - fileClass.write('\n') + def writeAsNull(self, podofoFileClass, cls, enumToCls): + podofoFileClass.write(' virtual SkPdf' + cls.fName +'* as' + cls.fName + '() {return NULL;}\n') + podofoFileClass.write(' virtual const SkPdf' + cls.fName +'* as' + cls.fName + '() const {return NULL;}\n') + podofoFileClass.write('\n') cnt = 0 for sub in cls.fEnumSubclasses: - self.writeAsNull(fileClass, enumToCls[cls.fEnumSubclasses[cnt]], enumToCls) + self.writeAsNull(podofoFileClass, enumToCls[cls.fEnumSubclasses[cnt]], enumToCls) cnt = cnt + 1 - def writeAsFoo(self, fileClass, cls, enumToCls): + def writeAsFoo(self, podofoFileClass, cls, enumToCls): # TODO(edisonn): add a container, with sections, public, private, default, ... # the end code will be grouped # me - fileClass.write('public:\n') - fileClass.write(' virtual SkPdf' + cls.fName +'* as' + cls.fName + '() {return this;}\n') - fileClass.write(' virtual const SkPdf' + cls.fName +'* as' + cls.fName + '() const {return this;}\n') - fileClass.write('\n') + podofoFileClass.write('public:\n') + + podofoFileClass.write('public:\n') + podofoFileClass.write(' SkPdf' + cls.fName +'* as' + cls.fName + '() {return this;}\n') + podofoFileClass.write(' virtual const SkPdf' + cls.fName +'* as' + cls.fName + '() const {return this;}\n') + podofoFileClass.write('\n') if cls.fName == 'Object': cnt = 0 for sub in cls.fEnumSubclasses: - self.writeAsNull(fileClass, enumToCls[cls.fEnumSubclasses[cnt]], enumToCls) + self.writeAsNull(podofoFileClass, enumToCls[cls.fEnumSubclasses[cnt]], enumToCls) cnt = cnt + 1 if cls.fName != 'Object': - fileClass.write('private:\n') + podofoFileClass.write('private:\n') base = self.fClasses[cls.fBase] cnt = 0 for sub in base.fEnumSubclasses: if enumToCls[base.fEnumSubclasses[cnt]].fName != cls.fName: - self.writeAsNull(fileClass, enumToCls[base.fEnumSubclasses[cnt]], enumToCls) + self.writeAsNull(podofoFileClass, enumToCls[base.fEnumSubclasses[cnt]], enumToCls) cnt = cnt + 1 @@ -235,8 +237,8 @@ class PdfClassManager: return mustBe def write(self): - global fileHeaders - global fileHeadersCpp + global fileHeadersPodofo + global fileHeadersPodofoCpp global knowTypes # generate enum @@ -249,8 +251,8 @@ class PdfClassManager: cls.fEnum = 'k' + name + '_SkPdfObjectType' cls.fEnumEnd = 'k' + name + '__End_SkPdfObjectType' - fileHeaders.write('#include "SkPdf' + cls.fName + '_autogen.h"\n') - fileHeadersCpp.write('#include "SkPdf' + cls.fName + '_autogen.cpp"\n') + fileHeadersPodofo.write('#include "SkPdf' + cls.fName + '_autogen.h"\n') + fileHeadersPodofoCpp.write('#include "SkPdf' + cls.fName + '_autogen.cpp"\n') if cls.fBase != '': self.fClasses[cls.fBase].fEnumSubclasses.append(cls.fEnum) @@ -267,7 +269,7 @@ class PdfClassManager: # write imports # write enums - fileEnums = open('SkPdfEnums_autogen.h', 'w') + fileEnums = open(sys.argv[1] + 'autogen/SkPdfEnums_autogen.h', 'w') fileEnums.write('#ifndef __DEFINED__SkPdfEnums\n') fileEnums.write('#define __DEFINED__SkPdfEnums\n') fileEnums.write('\n') @@ -290,72 +292,93 @@ class PdfClassManager: cls = self.fClasses[name] enum = cls.fEnum - fileClass = open('SkPdf' + cls.fName + '_autogen.h', 'w') - fileClassCpp = open('SkPdf' + cls.fName + '_autogen.cpp', 'w') - fileClass.write('#ifndef __DEFINED__SkPdf' + cls.fName + '\n') - fileClass.write('#define __DEFINED__SkPdf' + cls.fName + '\n') - fileClass.write('\n') - - fileClassCpp.write('#include "SkPdf' + cls.fName + '_autogen.h"\n\n') - fileClass.write('#include "SkPdfUtils.h"\n') - fileClass.write('#include "SkPdfEnums_autogen.h"\n') - fileClass.write('#include "SkPdfArray_autogen.h"\n') + podofoFileClass = open(sys.argv[1] + 'podofo/autogen/SkPdf' + cls.fName + '_autogen.h', 'w') + podofoFileClassCpp = open(sys.argv[1] + 'podofo/autogen/SkPdf' + cls.fName + '_autogen.cpp', 'w') + + podofoFileClass.write('#ifndef __DEFINED__SkPdf' + cls.fName + '\n') + podofoFileClass.write('#define __DEFINED__SkPdf' + cls.fName + '\n') + podofoFileClass.write('\n') + + podofoFileClassCpp.write('#include "SkPdf' + cls.fName + '_autogen.h"\n\n') + podofoFileClassCpp.write('#include "podofo.h"\n') + podofoFileClassCpp.write('#include "SkPodofoUtils.h"\n') + podofoFileClassCpp.write('#include "SkPdfMapper_autogen.h"\n') + podofoFileClassCpp.write('\n') + + + if cls.fBase == '': + podofoFileClass.write('#include "stddef.h"\n') + podofoFileClass.write('#include <string>\n') + podofoFileClass.write('#include "SkPdfEnums_autogen.h"\n') + podofoFileClass.write('#include "SkPdfNYI.h"\n') + podofoFileClass.write('#include "SkPodofoUtils.h"\n') + if cls.fBase != '': - fileClass.write('#include "SkPdf' + cls.fBase + '_autogen.h"\n') - fileClass.write('\n') + podofoFileClass.write('#include "SkPdf' + cls.fBase + '_autogen.h"\n') + + if cls.fBase == '': + podofoFileClass.write('#include "SkPodofoParsedPDF.h"\n') + + podofoFileClass.write('\n') + + if cls.fBase == '': + podofoFileClass.write('namespace PoDoFo {\n') + podofoFileClass.write('class PdfMemDocument;\n') + podofoFileClass.write('class PdfObject;\n') + podofoFileClass.write('}\n') if cls.fComment != '': - fileClass.write('// ' + cls.fComment + '\n') + podofoFileClass.write('// ' + cls.fComment + '\n') if cls.fBase == '': - fileClass.write('class SkPdf' + cls.fName + ' {\n') + podofoFileClass.write('class SkPdf' + cls.fName + ' {\n') else: - fileClass.write('class SkPdf' + cls.fName + ' : public SkPdf' + cls.fBase + ' {\n') + podofoFileClass.write('class SkPdf' + cls.fName + ' : public SkPdf' + cls.fBase + ' {\n') - fileClass.write('public:\n') - fileClass.write(' virtual SkPdfObjectType getType() const { return ' + cls.fEnum + ';}\n') + podofoFileClass.write('public:\n') + podofoFileClass.write(' virtual SkPdfObjectType getType() const { return ' + cls.fEnum + ';}\n') if len(cls.fEnumSubclasses) == 0: - fileClass.write(' virtual SkPdfObjectType getTypeEnd() const { return (SkPdfObjectType)(' + cls.fEnum + ' + 1);}\n') + podofoFileClass.write(' virtual SkPdfObjectType getTypeEnd() const { return (SkPdfObjectType)(' + cls.fEnum + ' + 1);}\n') else: - fileClass.write(' virtual SkPdfObjectType getTypeEnd() const { return ' + cls.fEnumEnd + ';}\n') + podofoFileClass.write(' virtual SkPdfObjectType getTypeEnd() const { return ' + cls.fEnumEnd + ';}\n') - self.writeAsFoo(fileClass, cls, enumToCls) + self.writeAsFoo(podofoFileClass, cls, enumToCls) - fileClass.write('public:\n') - for cc in cls.fCCPublic: - fileClass.write(' ' + cc + '\n') - - fileClass.write('private:\n') - for cc in cls.fCCPrivate: - fileClass.write(' ' + cc + '\n') + podofoFileClass.write('public:\n') + + for cc in cls.fCCPublicPodofo: + podofoFileClass.write(' ' + cc + '\n') + + for cc in cls.fCCPublicPodofoCpp: + podofoFileClassCpp.write(cc + '\n\n') + if cls.fBase == '': - fileClass.write('protected:\n') - fileClass.write(' const PdfMemDocument* fPodofoDoc;\n') - fileClass.write(' const PdfObject* fPodofoObj;\n') - fileClass.write('\n') - fileClass.write('public:\n') - fileClass.write(' SkPdf' + cls.fName + '(const PdfMemDocument* podofoDoc = NULL, const PdfObject* podofoObj = NULL) : fPodofoDoc(podofoDoc), fPodofoObj(podofoObj) {}\n') - fileClass.write(' SkPdf' + cls.fName + '(const SkPdf' + cls.fName + '& from) : fPodofoDoc(from.fPodofoDoc), fPodofoObj(from.fPodofoObj) {}\n') - fileClass.write('\n') - fileClass.write(' const PdfMemDocument* doc() const { return fPodofoDoc;}\n') - fileClass.write(' const PdfObject* podofo() const { return fPodofoObj;}\n') + podofoFileClass.write('protected:\n') + podofoFileClass.write(' const PoDoFo::PdfMemDocument* fPodofoDoc;\n') + podofoFileClass.write(' const SkPodofoParsedPDF* fParsedDoc;\n') + podofoFileClass.write(' const PoDoFo::PdfObject* fPodofoObj;\n') + podofoFileClass.write('\n') + + podofoFileClass.write('public:\n') + + podofoFileClass.write(' SkPdf' + cls.fName + '(const SkPodofoParsedPDF* doc = NULL, const PoDoFo::PdfObject* podofoObj = NULL) : fPodofoDoc(doc->podofo()), fParsedDoc(doc), fPodofoObj(podofoObj) {}\n') + podofoFileClass.write('\n') + podofoFileClass.write(' const SkPodofoParsedPDF* doc() const { return fParsedDoc;}\n') + podofoFileClass.write(' const void* data() const {return fPodofoObj;}\n') + podofoFileClass.write(' const PoDoFo::PdfObject* podofo() const {return fPodofoObj;}\n') else: - fileClass.write('public:\n') - fileClass.write(' SkPdf' + cls.fName + '(const PdfMemDocument* podofoDoc = NULL, const PdfObject* podofoObj = NULL) : SkPdf' + cls.fBase + '(podofoDoc, podofoObj) {}\n') - fileClass.write('\n') - fileClass.write(' SkPdf' + cls.fName + '(const SkPdf' + cls.fName + '& from) : SkPdf' + cls.fBase + '(from.fPodofoDoc, from.fPodofoObj) {}\n') - fileClass.write('\n') - + podofoFileClass.write('public:\n') + podofoFileClass.write(' SkPdf' + cls.fName + '(const SkPodofoParsedPDF* doc = NULL, const PoDoFo::PdfObject* podofoObj = NULL) : SkPdf' + cls.fBase + '(doc, podofoObj) {}\n') + podofoFileClass.write('\n') + + # TODO(edisonn): add is valid ? #check required fieds, also, there should be an internal_valid() manually wrote for complex # situations # right now valid return true - fileClass.write(' virtual bool valid() const {return true;}\n') - fileClass.write('\n') - - fileClass.write(' SkPdf' + cls.fName + '& operator=(const SkPdf' + cls.fName + '& from) {this->fPodofoDoc = from.fPodofoDoc; this->fPodofoObj = from.fPodofoObj; return *this;}\n') - fileClass.write('\n') + #podofoFileClass.write(' virtual bool valid() const {return true;}\n') + #podofoFileClass.write('\n') for field in cls.fFields: prop = field.fProp @@ -363,98 +386,133 @@ class PdfClassManager: lines = prop.fComment.split('\n') if prop.fComment != '' and len(lines) > 0: - fileClass.write('/** ' + lines[0] + '\n') + podofoFileClass.write('/** ' + lines[0] + '\n') for line in lines[1:]: - fileClass.write(' * ' + line + '\n') - fileClass.write('**/\n') + podofoFileClass.write(' * ' + line + '\n') + podofoFileClass.write('**/\n') if prop.fCppName[0] == '[': - fileClass.write('/*\n') # comment code of the atributes that can have any name - fileClassCpp.write('/*\n') # comment code of the atributes that can have any name + podofoFileClass.write('/*\n') # comment code of the atributes that can have any name + podofoFileClassCpp.write('/*\n') # comment code of the atributes that can have any name - # TODO(edisonn): has_foo(); - fileClass.write(' bool has_' + prop.fCppName + '() const {\n') - fileClass.write(' return (ObjectFromDictionary(fPodofoDoc, fPodofoObj->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", NULL));\n') - fileClass.write(' }\n') - fileClass.write('\n') if len(prop.fTypes.split()) == 1: t = prop.fTypes.strip() - fileClass.write(' ' + knowTypes[t][0] + ' ' + prop.fCppName + '() const;\n') - fileClassCpp.write('' + knowTypes[t][0] + ' SkPdf' + cls.fName + '::' + prop.fCppName + '() const {\n') - fileClassCpp.write(' ' + knowTypes[t][0] + ' ret;\n') - fileClassCpp.write(' if (' + knowTypes[t][1] + '(fPodofoDoc, fPodofoObj->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return ret;\n') + + podofoFileClass.write(' ' + knowTypes[t][0] + ' ' + prop.fCppName + '() const;\n') + podofoFileClassCpp.write('' + knowTypes[t][0] + ' SkPdf' + cls.fName + '::' + prop.fCppName + '() const {\n') + podofoFileClassCpp.write(' ' + knowTypes[t][0] + ' ret;\n') + + #hack, find out if it is dict, they have an extra entry in the array + if len(knowTypes[t]) == 5: + podofoFileClassCpp.write(' if (fParsedDoc->mapper()->' + knowTypes[t][1] + '(podofo()->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return ret;\n') + else: + podofoFileClassCpp.write(' if (' + knowTypes[t][1] + '(fParsedDoc, podofo()->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return ret;\n') + if field.fRequired == False and prop.fDefault != '': - fileClassCpp.write(' return ' + prop.fDefault.toCpp() + ';\n'); + podofoFileClassCpp.write(' return ' + prop.fDefault.toCpp() + ';\n'); else: - fileClassCpp.write(' // TODO(edisonn): warn about missing required field, assert for known good pdfs\n') - fileClassCpp.write(' return ' + knowTypes[t][2].toCpp() + ';\n'); - fileClassCpp.write('}\n') - fileClassCpp.write('\n') + podofoFileClassCpp.write(' // TODO(edisonn): warn about missing required field, assert for known good pdfs\n') + podofoFileClassCpp.write(' return ' + knowTypes[t][2].toCpp() + ';\n'); + podofoFileClassCpp.write('}\n') + podofoFileClassCpp.write('\n') else: for type in prop.fTypes.split(): t = type.strip() - fileClass.write(' bool is' + prop.fCppName + 'A' + t.title() + '() const {\n') - fileClass.write(' SkPdfObject* ret = NULL;\n') - fileClass.write(' if (!ObjectFromDictionary(fPodofoDoc, fPodofoObj->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return false;\n') - fileClass.write(' return ' + knowTypes[t][3] + ';\n') - fileClass.write(' }\n') - fileClass.write('\n') - - fileClass.write(' ' + knowTypes[t][0] + ' get' + prop.fCppName + 'As' + t.title() + '() const;\n') - fileClassCpp.write('' + knowTypes[t][0] + ' SkPdf' + cls.fName + '::get' + prop.fCppName + 'As' + t.title() + '() const {\n') - fileClassCpp.write(' ' + knowTypes[t][0] + ' ret = ' + knowTypes[t][2].toCpp() + ';\n') - fileClassCpp.write(' if (' + knowTypes[t][1] + '(fPodofoDoc, fPodofoObj->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return ret;\n') - fileClassCpp.write(' // TODO(edisonn): warn about missing required field, assert for known good pdfs\n') - fileClassCpp.write(' return ' + knowTypes[t][2].toCpp() + ';\n') - fileClassCpp.write('}\n') - fileClassCpp.write('\n') + + podofoFileClass.write(' bool is' + prop.fCppName + 'A' + t.title() + '() const;\n') + + podofoFileClassCpp.write('bool SkPdf' + cls.fName + '::is' + prop.fCppName + 'A' + t.title() + '() const {\n') + podofoFileClassCpp.write(' SkPdfObject* ret = NULL;\n') + podofoFileClassCpp.write(' if (!fParsedDoc->mapper()->SkPdfObjectFromDictionary(podofo()->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return false;\n') + podofoFileClassCpp.write(' return ' + knowTypes[t][3] + ';\n') + podofoFileClassCpp.write('}\n') + podofoFileClassCpp.write('\n') + + podofoFileClass.write(' ' + knowTypes[t][0] + ' get' + prop.fCppName + 'As' + t.title() + '() const;\n') + podofoFileClassCpp.write('' + knowTypes[t][0] + ' SkPdf' + cls.fName + '::get' + prop.fCppName + 'As' + t.title() + '() const {\n') + podofoFileClassCpp.write(' ' + knowTypes[t][0] + ' ret = ' + knowTypes[t][2].toCpp() + ';\n') + + # hack + if len(knowTypes[t]) == 5: + podofoFileClassCpp.write(' if (fParsedDoc->mapper()->' + knowTypes[t][1] + '(podofo()->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return ret;\n') + else: + podofoFileClassCpp.write(' if (' + knowTypes[t][1] + '(fParsedDoc, podofo()->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &ret)) return ret;\n') + + podofoFileClassCpp.write(' // TODO(edisonn): warn about missing required field, assert for known good pdfs\n') + podofoFileClassCpp.write(' return ' + knowTypes[t][2].toCpp() + ';\n') + podofoFileClassCpp.write('}\n') + podofoFileClassCpp.write('\n') + podofoFileClass.write(' bool has_' + prop.fCppName + '() const;\n') + podofoFileClassCpp.write('bool SkPdf' + cls.fName + '::has_' + prop.fCppName + '() const {\n') + podofoFileClassCpp.write(' return (ObjectFromDictionary(fParsedDoc, podofo()->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", NULL));\n') + podofoFileClassCpp.write('}\n') + podofoFileClassCpp.write('\n') if prop.fCppName[0] == '[': - fileClass.write('*/\n') # comment code of the atributes that can have any name - fileClassCpp.write('*/\n') # comment code of the atributes that can have any name + podofoFileClass.write('*/\n') # comment code of the atributes that can have any name + podofoFileClassCpp.write('*/\n') # comment code of the atributes that can have any name - fileClass.write('};\n') - fileClass.write('\n') + podofoFileClass.write('};\n') + podofoFileClass.write('\n') - fileClass.write('#endif // __DEFINED__SkPdf' + cls.fName + '\n') - fileClass.close() - fileClassCpp.close() - - + podofoFileClass.write('#endif // __DEFINED__PODOFO_SkPdf' + cls.fName + '\n') + + podofoFileClass.close() + podofoFileClassCpp.close() # generate constructor when knowing the type # later, p2, generate constructor when not knowing the type - very similar with parsing? # generate parser # TODO(edisonn): fast recognition based on must attributes. - fileMapper = open('SkPdfPodofoMapper_autogen.h', 'w') - fileMapperCpp = open('SkPdfPodofoMapper_autogen.cpp', 'w') - fileMapper.write('#ifndef __DEFINED__SkPdfPodofoMapper\n') - fileMapper.write('#define __DEFINED__SkPdfPodofoMapper\n') - fileMapper.write('\n') - - fileMapper.write('#include "SkPdfHeaders_autogen.h"\n') - fileMapperCpp.write('#include "SkPdfPodofoMapper_autogen.h"\n') -# fileMapper.write('class PodofoMapper {\n') -# fileMapper.write('public:\n') + fileMapperPodofo = open(sys.argv[1] + 'podofo/autogen/SkPdfMapper_autogen.h', 'w') + fileMapperPodofoCpp = open(sys.argv[1] + 'podofo/autogen/SkPdfMapper_autogen.cpp', 'w') + + fileMapperPodofo.write('#ifndef __DEFINED__SkPdfMapper\n') + fileMapperPodofo.write('#define __DEFINED__SkPdfMapper\n') + fileMapperPodofo.write('\n') + + fileMapperPodofo.write('#include "SkPdfHeaders_autogen.h"\n') + + + fileMapperPodofo.write('namespace PoDoFo {\n') + fileMapperPodofo.write('class PdfDictionary;\n') + fileMapperPodofo.write('class PdfMemDocument;\n') + fileMapperPodofo.write('class PdfObject;\n') + fileMapperPodofo.write('}\n') + + fileMapperPodofoCpp.write('#include "SkPdfMapper_autogen.h"\n') + fileMapperPodofoCpp.write('#include "SkPdfUtils.h"\n') + fileMapperPodofoCpp.write('#include "podofo.h"\n') + fileMapperPodofoCpp.write('\n') + + fileMapperPodofo.write('class SkPdfMapper {\n') + + fileMapperPodofo.write(' const SkPodofoParsedPDF* fParsedDoc;\n') + fileMapperPodofo.write(' const PoDoFo::PdfMemDocument* fPodofoDoc;\n') + + fileMapperPodofo.write('public:\n') + + fileMapperPodofo.write(' SkPdfMapper(const SkPodofoParsedPDF* doc) : fParsedDoc(doc), fPodofoDoc(doc ? doc->podofo() : NULL) {}\n') + fileMapperPodofo.write('\n') + for name in self.fClassesNamesInOrder: cls = self.fClasses[name] + fileMapperPodofo.write(' bool map' + name + '(const SkPdfObject* in, SkPdf' + name + '** out) const;\n') - fileMapper.write('bool map' + name + '(const SkPdfObject& in, SkPdf' + name + '** out);\n') - - fileMapperCpp.write('bool map' + name + '(const SkPdfObject& in, SkPdf' + name + '** out) {\n') - fileMapperCpp.write(' return map' + name + '(*in.doc(), *in.podofo(), out);\n') - fileMapperCpp.write('}\n') - fileMapperCpp.write('\n') + fileMapperPodofoCpp.write('bool SkPdfMapper::map' + name + '(const SkPdfObject* in, SkPdf' + name + '** out) const {\n') + fileMapperPodofoCpp.write(' return map' + name + '((const PoDoFo::PdfObject*)in->data(), (SkPdf' + name + '**)out);\n') + fileMapperPodofoCpp.write('}\n') + fileMapperPodofoCpp.write('\n') - fileMapper.write('bool map' + name + '(const PdfMemDocument& podofoDoc, const PdfObject& podofoObj, SkPdf' + name + '** out);\n') - fileMapperCpp.write('bool map' + name + '(const PdfMemDocument& podofoDoc, const PdfObject& podofoObj, SkPdf' + name + '** out) {\n') - fileMapperCpp.write(' if (!is' + name + '(podofoDoc, podofoObj)) return false;\n') - fileMapperCpp.write('\n') + fileMapperPodofo.write(' bool map' + name + '(const PoDoFo::PdfObject* podofoObj, SkPdf' + name + '** out) const ;\n') + fileMapperPodofoCpp.write('bool SkPdfMapper::map' + name + '(const PoDoFo::PdfObject* podofoObj, SkPdf' + name + '** out) const {\n') + fileMapperPodofoCpp.write(' if (!is' + name + '(podofoObj)) return false;\n') + fileMapperPodofoCpp.write('\n') # stream must be last one hasStream = False @@ -462,36 +520,36 @@ class PdfClassManager: if cls.fName == 'Object' and enumToCls[sub].fName == 'Stream': hasStream = True else: - fileMapperCpp.write(' if (map' + enumToCls[sub].fName + '(podofoDoc, podofoObj, (SkPdf' + enumToCls[sub].fName + '**)out)) return true;\n') + fileMapperPodofoCpp.write(' if (map' + enumToCls[sub].fName + '(podofoObj, (SkPdf' + enumToCls[sub].fName + '**)out)) return true;\n') if hasStream: - fileMapperCpp.write(' if (mapStream(podofoDoc, podofoObj, (SkPdfStream**)out)) return true;\n') + fileMapperPodofoCpp.write(' if (mapStream(podofoObj, (SkPdfStream**)out)) return true;\n') - fileMapperCpp.write('\n') + fileMapperPodofoCpp.write('\n') - fileMapperCpp.write(' *out = new SkPdf' + name + '(&podofoDoc, &podofoObj);\n') - fileMapperCpp.write(' return true;\n') - fileMapperCpp.write('}\n') - fileMapperCpp.write('\n') + fileMapperPodofoCpp.write(' *out = new SkPdf' + name + '(fParsedDoc, podofoObj);\n') + fileMapperPodofoCpp.write(' return true;\n') + fileMapperPodofoCpp.write('}\n') + fileMapperPodofoCpp.write('\n') for name in self.fClassesNamesInOrder: cls = self.fClasses[name] - fileMapper.write('bool is' + name + '(const PdfMemDocument& podofoDoc, const PdfObject& podofoObj);\n') - fileMapperCpp.write('bool is' + name + '(const PdfMemDocument& podofoDoc, const PdfObject& podofoObj) {\n') + fileMapperPodofo.write(' bool is' + name + '(const PoDoFo::PdfObject* podofoObj) const ;\n') + fileMapperPodofoCpp.write('bool SkPdfMapper::is' + name + '(const PoDoFo::PdfObject* podofoObj) const {\n') if cls.fCheck != '': - fileMapperCpp.write(' return ' + cls.fCheck + ';\n') + fileMapperPodofoCpp.write(' return ' + cls.fCheck + ';\n') else: cntMust = 0 for field in cls.fFields: prop = field.fProp if prop.fHasMust: cntMust = cntMust + 1 - fileMapperCpp.write(' ' + knowTypes[prop.fTypes.strip()][0] + ' ' + prop.fCppName + ';\n') - fileMapperCpp.write(' if (!podofoObj.IsDictionary()) return false;\n') - fileMapperCpp.write(' if (!' + knowTypes[prop.fTypes.strip()][1] + '(&podofoDoc, podofoObj.GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &' + prop.fCppName + ')) return false;\n') + fileMapperPodofoCpp.write(' ' + knowTypes[prop.fTypes.strip()][0] + ' ' + prop.fCppName + ';\n') + fileMapperPodofoCpp.write(' if (!podofoObj->IsDictionary()) return false;\n') + fileMapperPodofoCpp.write(' if (!' + knowTypes[prop.fTypes.strip()][1] + '(fParsedDoc, podofoObj->GetDictionary(), \"' + prop.fName + '\", \"' + prop.fAbr + '\", &' + prop.fCppName + ')) return false;\n') eval = ''; # TODO(edisonn): this could get out of hand, and could have poor performance if continued on this path @@ -505,88 +563,105 @@ class PdfClassManager: eval = '(' + prop.fCppName + ' != ' + cnd.toCpp() + ')' else: eval = eval + ' && ' + '(' + prop.fCppName + ' != ' + cnd.toCpp() + ')' - fileMapperCpp.write(' if (' + eval + ') return false;\n') - fileMapperCpp.write('\n') + fileMapperPodofoCpp.write(' if (' + eval + ') return false;\n') + fileMapperPodofoCpp.write('\n') - fileMapperCpp.write(' return true;\n') + fileMapperPodofoCpp.write(' return true;\n') - fileMapperCpp.write('}\n') - fileMapperCpp.write('\n') + fileMapperPodofoCpp.write('}\n') + fileMapperPodofoCpp.write('\n') - fileMapper.write('bool ' + name + 'FromDictionary(const PdfMemDocument* pdfDoc, const PdfDictionary& dict, const char* key, SkPdf' + name + '** data);\n') - fileMapperCpp.write('bool ' + name + 'FromDictionary(const PdfMemDocument* pdfDoc, const PdfDictionary& dict, const char* key, SkPdf' + name + '** data) {\n') - fileMapperCpp.write(' const PdfObject* value = resolveReferenceObject(pdfDoc, dict.GetKey(PdfName(key)), true);\n') - fileMapperCpp.write(' if (value == NULL) { return false; }\n') - fileMapperCpp.write(' if (data == NULL) { return true; }\n') - fileMapperCpp.write(' return map' + name + '(*pdfDoc, *value, (SkPdf' + name + '**)data);\n') - fileMapperCpp.write('}\n') - fileMapperCpp.write('\n') - - fileMapper.write('bool ' + name + 'FromDictionary(const PdfMemDocument* pdfDoc, const PdfDictionary& dict, const char* key, const char* abr, SkPdf' + name + '** data);\n') - fileMapperCpp.write('bool ' + name + 'FromDictionary(const PdfMemDocument* pdfDoc, const PdfDictionary& dict, const char* key, const char* abr, SkPdf' + name + '** data) {\n') - fileMapperCpp.write(' if (' + name + 'FromDictionary(pdfDoc, dict, key, data)) return true;\n') - fileMapperCpp.write(' if (abr == NULL || *abr == \'\\0\') return false;\n') - fileMapperCpp.write(' return ' + name + 'FromDictionary(pdfDoc, dict, abr, data);\n') - fileMapperCpp.write('}\n') - fileMapperCpp.write('\n') + fileMapperPodofo.write(' bool SkPdf' + name + 'FromDictionary(const PoDoFo::PdfDictionary& dict, const char* key, SkPdf' + name + '** data) const ;\n') + fileMapperPodofoCpp.write('bool SkPdfMapper::SkPdf' + name + 'FromDictionary(const PoDoFo::PdfDictionary& dict, const char* key, SkPdf' + name + '** data) const {\n') + fileMapperPodofoCpp.write(' const PoDoFo::PdfObject* value = resolveReferenceObject(fParsedDoc, dict.GetKey(PoDoFo::PdfName(key)), true);\n') + fileMapperPodofoCpp.write(' if (value == NULL) { return false; }\n') + fileMapperPodofoCpp.write(' if (data == NULL) { return true; }\n') + fileMapperPodofoCpp.write(' return map' + name + '(value, (SkPdf' + name + '**)data);\n') + fileMapperPodofoCpp.write('}\n') + fileMapperPodofoCpp.write('\n') + + fileMapperPodofo.write(' bool SkPdf' + name + 'FromDictionary(const PoDoFo::PdfDictionary& dict, const char* key, const char* abr, SkPdf' + name + '** data) const ;\n') + fileMapperPodofoCpp.write('bool SkPdfMapper::SkPdf' + name + 'FromDictionary(const PoDoFo::PdfDictionary& dict, const char* key, const char* abr, SkPdf' + name + '** data) const {\n') + fileMapperPodofoCpp.write(' if (SkPdf' + name + 'FromDictionary(dict, key, data)) return true;\n') + fileMapperPodofoCpp.write(' if (abr == NULL || *abr == \'\\0\') return false;\n') + fileMapperPodofoCpp.write(' return SkPdf' + name + 'FromDictionary(dict, abr, data);\n') + fileMapperPodofoCpp.write('}\n') + fileMapperPodofoCpp.write('\n') - #fileMapper.write('};\n') - fileMapper.write('\n') + fileMapperPodofo.write('};\n') + fileMapperPodofo.write('\n') - fileMapper.write('#endif // __DEFINED__SkPdfPodofoMapper\n') - fileMapper.close() + fileMapperPodofo.write('#endif // __DEFINED__SkPdfMapper\n') + + fileMapperPodofo.close() + fileMapperPodofoCpp.close() return def generateCode(): - global fileHeaders - global fileHeadersCpp + global fileHeadersPodofo + global fileHeadersPodofoCpp global knowTypes - fileHeaders = open('SkPdfHeaders_autogen.h', 'w') - fileHeadersCpp = open('SkPdfHeaders_autogen.cpp', 'w') - fileHeaders.write('#ifndef __DEFINED__SkPdfHeaders\n') - fileHeaders.write('#define __DEFINED__SkPdfHeaders\n') - fileHeaders.write('\n') + fileHeadersPodofo = open(sys.argv[1] + 'podofo/autogen/SkPdfHeaders_autogen.h', 'w') + fileHeadersPodofoCpp = open(sys.argv[1] + 'podofo/autogen/SkPdfHeaders_autogen.cpp', 'w') - fileHeaders.write('#include "SkPdfEnums_autogen.h"\n') + fileHeadersPodofo.write('#ifndef __DEFINED__SkPdfHeaders\n') + fileHeadersPodofo.write('#define __DEFINED__SkPdfHeaders\n') + fileHeadersPodofo.write('\n') - fileHeadersCpp.write('#include "SkPdfHeaders_autogen.h"\n') + fileHeadersPodofoCpp.write('#include "SkPdfHeaders_autogen.h"\n') manager = PdfClassManager() manager.addClass('Object') - manager.addClass('Null').check('podofoObj.GetDataType() == ePdfDataType_Null') - manager.addClass('Boolean').check('podofoObj.GetDataType() == ePdfDataType_Bool')\ - .carbonCopyPublic('bool value() const {return fPodofoObj->GetBool();}') + # TODO(edisonn): perf, instead of virtual functions, store data in field and reurn it. + # maybe in constructor load it, or laizy load it + + manager.addClass('Null').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_Null') + manager.addClass('Boolean').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_Bool')\ + .carbonCopyPublicPodofo('bool value() const;')\ + .carbonCopyPublicPodofoCpp('bool SkPdfBoolean::value() const {return podofo()->GetBool();}') - manager.addClass('Integer').check('podofoObj.GetDataType() == ePdfDataType_Number || podofoObj.GetDataType() == ePdfDataType_Real')\ - .carbonCopyPublic('long value() const {return fPodofoObj->GetNumber();}') + manager.addClass('Integer').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_Number || podofoObj->GetDataType() == PoDoFo::ePdfDataType_Real')\ + .carbonCopyPublicPodofo('long value() const;')\ + .carbonCopyPublicPodofoCpp('long SkPdfInteger::value() const {return podofo()->GetNumber();}') - manager.addClass('Number', 'Integer').check('podofoObj.GetDataType() == ePdfDataType_Number || podofoObj.GetDataType() == ePdfDataType_Real')\ - .carbonCopyPublic('double value() const {return fPodofoObj->GetReal();}') + manager.addClass('Number', 'Integer').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_Number || podofoObj->GetDataType() == PoDoFo::ePdfDataType_Real')\ + .carbonCopyPublicPodofo('double value() const;')\ + .carbonCopyPublicPodofoCpp('double SkPdfNumber::value() const {return podofo()->GetReal();}')\ - manager.addClass('Name').check('podofoObj.GetDataType() == ePdfDataType_Name')\ - .carbonCopyPublic('const std::string& value() const {return fPodofoObj->GetName().GetName();}') + manager.addClass('Name').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_Name')\ + .carbonCopyPublicPodofo('const std::string& value() const;')\ + .carbonCopyPublicPodofoCpp('const std::string& SkPdfName::value() const {return podofo()->GetName().GetName();}') - manager.addClass('Reference').check('podofoObj.GetDataType() == ePdfDataType_Reference') + manager.addClass('Reference').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_Reference') - manager.addClass('Array').check('podofoObj.GetDataType() == ePdfDataType_Array')\ - .carbonCopyPublic('const int size() const {return fPodofoObj->GetArray().GetSize();}')\ - .carbonCopyPublic('SkPdfObject* operator[](int i) const { SkPdfObject* ret = NULL; skpdfmap(*fPodofoDoc, fPodofoObj->GetArray()[i], &ret); return ret; }')\ + manager.addClass('Array').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_Array')\ + .carbonCopyPublicPodofo('const int size() const;')\ + .carbonCopyPublicPodofoCpp('const int SkPdfArray::size() const {return podofo()->GetArray().GetSize();}')\ + .carbonCopyPublicPodofo('SkPdfObject* operator[](int i) const;')\ + .carbonCopyPublicPodofoCpp('SkPdfObject* SkPdfArray::operator[](int i) const { SkPdfObject* ret = NULL; fParsedDoc->mapper()->mapObject(&podofo()->GetArray()[i], &ret); return ret; }') - manager.addClass('String').check('podofoObj.GetDataType() == ePdfDataType_String || podofoObj.GetDataType() == ePdfDataType_HexString')\ - .carbonCopyPublic('const std::string& value() const {return fPodofoObj->GetString().GetStringUtf8();}') + manager.addClass('String').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_String || podofoObj->GetDataType() == PoDoFo::ePdfDataType_HexString')\ + .carbonCopyPublicPodofo('const std::string& value() const;')\ + .carbonCopyPublicPodofoCpp('const std::string& SkPdfString::value() const {return podofo()->GetString().GetStringUtf8();}')\ + .carbonCopyPublicPodofo('const char* c_str() const;')\ + .carbonCopyPublicPodofoCpp('const char* SkPdfString::c_str() const {return podofo()->GetString().GetString();}')\ + .carbonCopyPublicPodofo('size_t len() const;')\ + .carbonCopyPublicPodofoCpp('size_t SkPdfString::len() const {return podofo()->GetString().GetLength();}') - manager.addClass('HexString', 'String').check('podofoObj.GetDataType() == ePdfDataType_HexString')\ - .carbonCopyPublic('const std::string& value() const {return fPodofoObj->GetString().GetStringUtf8();}') + manager.addClass('HexString', 'String').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_HexString')\ - manager.addClass('Dictionary').check('podofoObj.GetDataType() == ePdfDataType_Dictionary')\ - .carbonCopyPublic('SkPdfObject* get(const char* dictionaryKeyName) const {return new SkPdfObject(fPodofoDoc, resolveReferenceObject(fPodofoDoc, fPodofoObj->GetDictionary().GetKey(PdfName(dictionaryKeyName))));}')\ - .carbonCopyPublic('SkPdfObject* get(const char* dictionaryKeyName) {return new SkPdfObject(fPodofoDoc, resolveReferenceObject(fPodofoDoc, fPodofoObj->GetDictionary().GetKey(PdfName(dictionaryKeyName))));}')\ - - manager.addClass('Stream') # attached to a dictionary in podofo + manager.addClass('Dictionary').check('podofoObj->GetDataType() == PoDoFo::ePdfDataType_Dictionary')\ + .carbonCopyPublicPodofo('SkPdfObject* get(const char* dictionaryKeyName) const;')\ + .carbonCopyPublicPodofoCpp('SkPdfObject* SkPdfDictionary::get(const char* dictionaryKeyName) const {SkPdfObject* ret = NULL; fParsedDoc->mapper()->mapObject(resolveReferenceObject(fParsedDoc, podofo()->GetDictionary().GetKey(PoDoFo::PdfName(dictionaryKeyName))), &ret); return ret;}')\ + + # attached to a dictionary in podofo + manager.addClass('Stream')\ + .carbonCopyPublicPodofo('bool GetFilteredCopy(char** buffer, long* len) const;')\ + .carbonCopyPublicPodofoCpp('bool SkPdfStream::GetFilteredCopy(char** buffer, long* len) const {try {PoDoFo::pdf_long podofoLen = 0; *buffer = NULL; *len = 0;podofo()->GetStream()->GetFilteredCopy(buffer, &podofoLen); *len = (long)podofoLen;} catch (PoDoFo::PdfError& e) { return false; } return true;}') # these classes are not explicitely backed by a table in the pdf spec @@ -619,12 +694,12 @@ def generateCode(): manager.write() - fileHeaders.write('#endif // __DEFINED__SkPdfHeaders\n') - fileHeaders.close() - fileHeadersCpp.close() - - return 1 + fileHeadersPodofo.write('#endif // __DEFINED__SkPdfHeaders\n') + + fileHeadersPodofo.close() + fileHeadersPodofoCpp.close() if '__main__' == __name__: + #print sys.argv sys.exit(generateCode()) diff --git a/experimental/PdfViewer/pdfparser/SkPdfNYI.cpp b/experimental/PdfViewer/pdfparser/SkPdfNYI.cpp new file mode 100644 index 0000000000..7868cc625a --- /dev/null +++ b/experimental/PdfViewer/pdfparser/SkPdfNYI.cpp @@ -0,0 +1,4 @@ + +#include "SkPdfNYI.h" + + diff --git a/experimental/PdfViewer/pdfparser/SkPdfNYI.h b/experimental/PdfViewer/pdfparser/SkPdfNYI.h new file mode 100644 index 0000000000..5f1ee82691 --- /dev/null +++ b/experimental/PdfViewer/pdfparser/SkPdfNYI.h @@ -0,0 +1,10 @@ +#ifndef EXPERIMENTAL_PDFVIEWER_PDFPARSER_SKPDFNYI_H_ +#define EXPERIMENTAL_PDFVIEWER_PDFPARSER_SKPDFNYI_H_ + +struct SkPdfFileSpec {}; +struct SkPdfDate {}; +struct SkPdfTree {}; +struct SkPdfFunction {}; + + +#endif // EXPERIMENTAL_PDFVIEWER_PDFPARSER_SKPDFNYI_H_ diff --git a/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp b/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp new file mode 100644 index 0000000000..f405d4aa34 --- /dev/null +++ b/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.cpp @@ -0,0 +1,12 @@ + +#include "SkNativeParsedPDF.h" + +SkNativeParsedPDF::SkNativeParsedPDF() { + // TODO(edisonn): Auto-generated constructor stub + +} + +SkNativeParsedPDF::~SkNativeParsedPDF() { + // TODO(edisonn): Auto-generated destructor stub +} + diff --git a/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.h b/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.h new file mode 100644 index 0000000000..38c72b089b --- /dev/null +++ b/experimental/PdfViewer/pdfparser/native/SkNativeParsedPDF.h @@ -0,0 +1,12 @@ +#ifndef EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKNATIVEPARSEDPDF_H_ +#define EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKNATIVEPARSEDPDF_H_ + +#include "base/macros.h" + +class SkNativeParsedPDF : public SkParsedPDF { +public: + SkNativeParsedPDF(); + virtual ~SkNativeParsedPDF(); +}; + +#endif // EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKNATIVEPARSEDPDF_H_ diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp new file mode 100644 index 0000000000..ea744ac1ef --- /dev/null +++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp @@ -0,0 +1,12 @@ + +#include "SkPdfNativeTokenizer.h" + +SkPdfNativeTokenizer::SkPdfNativeTokenizer() { + // TODO(edisonn): Auto-generated constructor stub + +} + +SkPdfNativeTokenizer::~SkPdfNativeTokenizer() { + // TODO(edisonn): Auto-generated destructor stub +} + diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.h b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.h new file mode 100644 index 0000000000..c8a2f46c73 --- /dev/null +++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.h @@ -0,0 +1,10 @@ +#ifndef EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKPDFNATIVETOKENIZER_H_ +#define EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKPDFNATIVETOKENIZER_H_ + +class SkPdfNativeTokenizer : public SkPdfPodofoTokenizer { +public: + SkPdfNativeTokenizer(); + virtual ~SkPdfNativeTokenizer(); +}; + +#endif // EXPERIMENTAL_PDFVIEWER_PDFPARSER_NATIVE_SKPDFNATIVETOKENIZER_H_ diff --git a/experimental/PdfViewer/pdfparser/podofo/SkPdfPodofoTokenizer.cpp b/experimental/PdfViewer/pdfparser/podofo/SkPdfPodofoTokenizer.cpp new file mode 100644 index 0000000000..373825301b --- /dev/null +++ b/experimental/PdfViewer/pdfparser/podofo/SkPdfPodofoTokenizer.cpp @@ -0,0 +1,102 @@ +#include "SkPdfPodofoTokenizer.h" + +#include "SkTypes.h" +#include "SkPdfStream_autogen.h" +#include "SkPdfMapper_autogen.h" + +#include "podofo.h" + +// maps to a null doc, if the code asks for it, we should err/crash. +SkPdfMapper gNullMapper(NULL); + +SkPdfPodofoTokenizer::SkPdfPodofoTokenizer(const SkPodofoParsedPDF* parser, PoDoFo::PdfContentsTokenizer* tokenizer) + : fMapper(parser->mapper()), fDoc(parser->podofo()), fTokenizer(tokenizer), fUncompressedStream(NULL), fUncompressedStreamLength(0), fEmpty(false), fHasPutBack(false) {} + +SkPdfPodofoTokenizer::SkPdfPodofoTokenizer(const SkPdfObject* objWithStream) : fMapper(&gNullMapper), fDoc(NULL), fTokenizer(NULL), fUncompressedStream(NULL), fUncompressedStreamLength(0), fEmpty(false), fHasPutBack(false) { + fUncompressedStream = NULL; + fUncompressedStreamLength = 0; + + fDoc = NULL; + + SkPdfStream* stream = NULL; + if (objWithStream && + objWithStream->doc()->mapper()->mapStream(objWithStream, &stream) && + stream->GetFilteredCopy(&fUncompressedStream, &fUncompressedStreamLength) && + fUncompressedStream != NULL && + fUncompressedStreamLength != 0) { + fTokenizer = new PoDoFo::PdfContentsTokenizer(fUncompressedStream, fUncompressedStreamLength); + fDoc = objWithStream->doc()->podofo(); + } else { + fEmpty = true; + } +} + +SkPdfPodofoTokenizer::SkPdfPodofoTokenizer(const char* buffer, int len) : fMapper(&gNullMapper), fDoc(NULL), fTokenizer(NULL), fUncompressedStream(NULL), fUncompressedStreamLength(0), fEmpty(false), fHasPutBack(false) { + try { + fTokenizer = new PoDoFo::PdfContentsTokenizer(buffer, len); + } catch (PoDoFo::PdfError& e) { + fEmpty = true; + } +} + +SkPdfPodofoTokenizer::~SkPdfPodofoTokenizer() { + free(fUncompressedStream); +} + +bool SkPdfPodofoTokenizer::readTokenCore(PdfToken* token) { + PoDoFo::PdfVariant var; + PoDoFo::EPdfContentsType type; + + token->fKeyword = NULL; + token->fObject = NULL; + + bool ret = fTokenizer->ReadNext(type, token->fKeyword, var); + + if (!ret) return ret; + + switch (type) { + case PoDoFo::ePdfContentsType_Keyword: + token->fType = kKeyword_TokenType; + break; + + case PoDoFo::ePdfContentsType_Variant: { + token->fType = kObject_TokenType; + PoDoFo::PdfObject* obj = new PoDoFo::PdfObject(var); + fMapper->mapObject(obj, &token->fObject); + } + break; + + case PoDoFo::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; +} + +void SkPdfPodofoTokenizer::PutBack(PdfToken token) { + SkASSERT(!fHasPutBack); + fHasPutBack = true; + fPutBack = token; +} + +bool SkPdfPodofoTokenizer::readToken(PdfToken* token) { + if (fHasPutBack) { + *token = fPutBack; + fHasPutBack = false; + return true; + } + + if (fEmpty) { + return false; + } + + return readTokenCore(token); +} diff --git a/experimental/PdfViewer/pdfparser/podofo/SkPdfPodofoTokenizer.h b/experimental/PdfViewer/pdfparser/podofo/SkPdfPodofoTokenizer.h new file mode 100644 index 0000000000..6e812c48da --- /dev/null +++ b/experimental/PdfViewer/pdfparser/podofo/SkPdfPodofoTokenizer.h @@ -0,0 +1,54 @@ +#ifndef EXPERIMENTAL_PDFVIEWER_PDFPARSER_PODOFO_SKPDFPODOFOTOKENIZER_H_ +#define EXPERIMENTAL_PDFVIEWER_PDFPARSER_PODOFO_SKPDFPODOFOTOKENIZER_H_ + +#include "stddef.h" + +class SkPdfObject; +class SkPdfMapper; +class SkPodofoParsedPDF; + +namespace PoDoFo { +class PdfMemDocument; +class PdfContentsTokenizer; +} + +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 SkPdfPodofoTokenizer { +public: + SkPdfPodofoTokenizer(const SkPodofoParsedPDF* parser, PoDoFo::PdfContentsTokenizer* tokenizer); + SkPdfPodofoTokenizer(const SkPdfObject* objWithStream); + SkPdfPodofoTokenizer(const char* buffer, int len); + + virtual ~SkPdfPodofoTokenizer(); + + bool readToken(PdfToken* token); + bool readTokenCore(PdfToken* token); + void PutBack(PdfToken token); + +private: + const SkPdfMapper* fMapper; + const PoDoFo::PdfMemDocument* fDoc; + PoDoFo::PdfContentsTokenizer* fTokenizer; + + char* fUncompressedStream; + long fUncompressedStreamLength; + + bool fEmpty; + bool fHasPutBack; + PdfToken fPutBack; +}; + +#endif // EXPERIMENTAL_PDFVIEWER_PDFPARSER_PODOFO_SKPDFPODOFOTOKENIZER_H_ diff --git a/experimental/PdfViewer/pdfparser/podofo/SkPodofoParsedPDF.cpp b/experimental/PdfViewer/pdfparser/podofo/SkPodofoParsedPDF.cpp new file mode 100644 index 0000000000..86d62315bc --- /dev/null +++ b/experimental/PdfViewer/pdfparser/podofo/SkPodofoParsedPDF.cpp @@ -0,0 +1,194 @@ +#include "SkPodofoParsedPDF.h" + +#include "SkPdfPodofoTokenizer.h" +#include "SkPdfHeaders_autogen.h" +#include "SkPdfMapper_autogen.h" +#include "SkPdfBasics.h" +#include "SkPdfParser.h" + +#include "podofo.h" + +SkPodofoParsedPDF::SkPodofoParsedPDF(const char* path) : fDoc(new PoDoFo::PdfMemDocument(path)) + , fMapper(new SkPdfMapper(this)) {} + +SkPodofoParsedPDF::~SkPodofoParsedPDF() { + delete fDoc; + delete fMapper; +} + +int SkPodofoParsedPDF::pages() const { + return fDoc->GetPageCount(); +} + +double SkPodofoParsedPDF::width(int page) const { + PoDoFo::PdfRect rect = fDoc->GetPage(page)->GetMediaBox(); + return rect.GetWidth() + rect.GetLeft(); +} + +double SkPodofoParsedPDF::height(int page) const { + PoDoFo::PdfRect rect = fDoc->GetPage(page)->GetMediaBox(); + return rect.GetHeight() + rect.GetBottom(); +} + +const SkPdfResourceDictionary* SkPodofoParsedPDF::pageResources(int page) const { + SkPdfPageObjectDictionary* pg = NULL; + SkPdfObject* obj = make(fDoc->GetPage(page)->GetObject()); + fMapper->mapPageObjectDictionary(obj, &pg); + return pg ? pg->Resources() : NULL; +} + +SkRect SkPodofoParsedPDF::MediaBox(int page) const { + PoDoFo::PdfRect rect = fDoc->GetPage(page)->GetMediaBox(); + SkRect skrect = SkRect::MakeLTRB(SkDoubleToScalar(rect.GetLeft()), + SkDoubleToScalar(rect.GetBottom()), + SkDoubleToScalar(rect.GetLeft() + rect.GetWidth()), + SkDoubleToScalar(rect.GetBottom() + rect.GetHeight())); + return skrect; +} + + +SkPdfPodofoTokenizer* SkPodofoParsedPDF::tokenizerOfPage(int page) const { + PoDoFo::PdfContentsTokenizer* t = new PoDoFo::PdfContentsTokenizer(fDoc->GetPage(page)); + return new SkPdfPodofoTokenizer(this, t); +} + +SkPdfPodofoTokenizer* SkPodofoParsedPDF::tokenizerOfStream(const SkPdfStream* stream) const { + if (stream == NULL) { + return NULL; + } + + char* buffer = NULL; + long len = 0; + stream->GetFilteredCopy(&buffer, &len); + return tokenizerOfBuffer(buffer, len); +} + +SkPdfPodofoTokenizer* SkPodofoParsedPDF::tokenizerOfBuffer(char* buffer, size_t len) const { + PoDoFo::PdfContentsTokenizer* t = new PoDoFo::PdfContentsTokenizer(buffer, len); + return new SkPdfPodofoTokenizer(this, t); +} + +size_t SkPodofoParsedPDF::objects() const { + return fDoc->GetObjects().GetSize(); +} + +const SkPdfObject* SkPodofoParsedPDF::object(int i) const { + PoDoFo::PdfVecObjects& objects = (PoDoFo::PdfVecObjects&)fDoc->GetObjects(); + return make(objects[i]); +} + +SkPdfObject* SkPodofoParsedPDF::make(PoDoFo::PdfObject* obj) const { + return new SkPdfObject(this, obj); +} + +const SkPdfObject* SkPodofoParsedPDF::make(const PoDoFo::PdfObject* obj) const { + return new SkPdfObject(this, obj); +} + +const SkPdfMapper* SkPodofoParsedPDF::mapper() const { + return fMapper; +} + +SkPdfNumber* SkPodofoParsedPDF::createNumber(double number) const { + return new SkPdfNumber(this, new PoDoFo::PdfObject(PoDoFo::PdfVariant(number))); +} + +SkPdfInteger* SkPodofoParsedPDF::createInteger(int value) const { + return new SkPdfInteger(this, new PoDoFo::PdfObject(PoDoFo::PdfVariant((PoDoFo::pdf_int64)value))); +} + +SkPdfString* SkPodofoParsedPDF::createString(char* sz, size_t len) const { + // TODO(edisonn): NYI + return NULL; +} + +PdfContext* gPdfContext = NULL; + +void SkPodofoParsedPDF::drawPage(int page, SkCanvas* canvas) const { + SkPdfPodofoTokenizer* tokenizer = tokenizerOfPage(page); + + PdfContext pdfContext(this); + pdfContext.fOriginalMatrix = SkMatrix::I(); + pdfContext.fGraphicsState.fResources = pageResources(page); + + gPdfContext = &pdfContext; + + // TODO(edisonn): get matrix stuff right. + // TODO(edisonn): add DPI/scale/zoom. + SkScalar z = SkIntToScalar(0); + SkRect rect = MediaBox(page); + SkScalar w = rect.width(); + SkScalar h = rect.height(); + + SkPoint pdfSpace[4] = {SkPoint::Make(z, z), SkPoint::Make(w, z), SkPoint::Make(w, h), SkPoint::Make(z, h)}; +// SkPoint skiaSpace[4] = {SkPoint::Make(z, h), SkPoint::Make(w, h), SkPoint::Make(w, z), SkPoint::Make(z, z)}; + + // TODO(edisonn): add flag for this app to create sourunding buffer zone + // TODO(edisonn): add flagg for no clipping. + // Use larger image to make sure we do not draw anything outside of page + // could be used in tests. + +#ifdef PDF_DEBUG_3X + SkPoint skiaSpace[4] = {SkPoint::Make(w+z, h+h), SkPoint::Make(w+w, h+h), SkPoint::Make(w+w, h+z), SkPoint::Make(w+z, h+z)}; +#else + SkPoint skiaSpace[4] = {SkPoint::Make(z, h), SkPoint::Make(w, h), SkPoint::Make(w, z), SkPoint::Make(z, z)}; +#endif + //SkPoint pdfSpace[2] = {SkPoint::Make(z, z), SkPoint::Make(w, h)}; + //SkPoint skiaSpace[2] = {SkPoint::Make(w, z), SkPoint::Make(z, h)}; + + //SkPoint pdfSpace[2] = {SkPoint::Make(z, z), SkPoint::Make(z, h)}; + //SkPoint skiaSpace[2] = {SkPoint::Make(z, h), SkPoint::Make(z, z)}; + + //SkPoint pdfSpace[3] = {SkPoint::Make(z, z), SkPoint::Make(z, h), SkPoint::Make(w, h)}; + //SkPoint skiaSpace[3] = {SkPoint::Make(z, h), SkPoint::Make(z, z), SkPoint::Make(w, 0)}; + + SkAssertResult(pdfContext.fOriginalMatrix.setPolyToPoly(pdfSpace, skiaSpace, 4)); + SkTraceMatrix(pdfContext.fOriginalMatrix, "Original matrix"); + + + pdfContext.fGraphicsState.fMatrix = pdfContext.fOriginalMatrix; + pdfContext.fGraphicsState.fMatrixTm = pdfContext.fGraphicsState.fMatrix; + pdfContext.fGraphicsState.fMatrixTlm = pdfContext.fGraphicsState.fMatrix; + + canvas->setMatrix(pdfContext.fOriginalMatrix); + +#ifndef PDF_DEBUG_NO_PAGE_CLIPING + canvas->clipRect(SkRect::MakeXYWH(z, z, w, h), SkRegion::kIntersect_Op, true); +#endif + +// erase with red before? +// SkPaint paint; +// paint.setColor(SK_ColorRED); +// canvas->drawRect(rect, paint); + + PdfMainLooper looper(NULL, tokenizer, &pdfContext, canvas); + looper.loop(); + + delete tokenizer; + + canvas->flush(); +} + +// TODO(edisonn): move in trace util. +#include "SkMatrix.h" +#include "SkRect.h" + +#ifdef PDF_TRACE +void SkTraceMatrix(const SkMatrix& matrix, const char* sz) { + printf("SkMatrix %s ", sz); + for (int i = 0 ; i < 9 ; i++) { + printf("%f ", SkScalarToDouble(matrix.get(i))); + } + printf("\n"); +} + +void SkTraceRect(const SkRect& rect, const char* sz) { + printf("SkRect %s ", sz); + printf("x = %f ", SkScalarToDouble(rect.x())); + printf("y = %f ", SkScalarToDouble(rect.y())); + printf("w = %f ", SkScalarToDouble(rect.width())); + printf("h = %f ", SkScalarToDouble(rect.height())); + printf("\n"); +} +#endif + diff --git a/experimental/PdfViewer/pdfparser/podofo/SkPodofoParsedPDF.h b/experimental/PdfViewer/pdfparser/podofo/SkPodofoParsedPDF.h new file mode 100644 index 0000000000..d694dedb5a --- /dev/null +++ b/experimental/PdfViewer/pdfparser/podofo/SkPodofoParsedPDF.h @@ -0,0 +1,59 @@ +#ifndef EXPERIMENTAL_PDFVIEWER_PDFPARSER_PODOFO_SKPODOFOPARSEDPDF_H_ +#define EXPERIMENTAL_PDFVIEWER_PDFPARSER_PODOFO_SKPODOFOPARSEDPDF_H_ + +#include "SkRect.h" + +class SkCanvas; + +class SkPdfInteger; +class SkPdfMapper; +class SkPdfNumber; +class SkPdfObject; +class SkPdfResourceDictionary; +class SkPdfStream; +class SkPdfString; + +class SkPdfPodofoTokenizer; + +namespace PoDoFo { +class PdfMemDocument; +class PdfObject; +} + +class SkPodofoParsedPDF { +public: + SkPodofoParsedPDF(const char* path); + virtual ~SkPodofoParsedPDF(); + + virtual int pages() const; + virtual double width(int page) const; + virtual double height(int page) const; + const SkPdfResourceDictionary* pageResources(int page) const; + virtual SkRect MediaBox(int n) const; + virtual SkPdfPodofoTokenizer* tokenizerOfPage(int n) const; + + virtual SkPdfPodofoTokenizer* tokenizerOfStream(const SkPdfStream* stream) const; + virtual SkPdfPodofoTokenizer* tokenizerOfBuffer(char* buffer, size_t len) const; + + virtual size_t objects() const; + virtual const SkPdfObject* object(int i) const; + + PoDoFo::PdfMemDocument* podofo() const {return fDoc;} + + const SkPdfMapper* mapper() const; + + SkPdfNumber* createNumber(double number) const; + SkPdfInteger* createInteger(int value) const; + SkPdfString* createString(char* sz, size_t len) const; + + void drawPage(int page, SkCanvas* canvas) const; + +private: + SkPdfObject* make(PoDoFo::PdfObject* obj) const; + const SkPdfObject* make(const PoDoFo::PdfObject* obj) const; + + PoDoFo::PdfMemDocument* fDoc; + SkPdfMapper* fMapper; +}; + +#endif // EXPERIMENTAL_PDFVIEWER_PDFPARSER_PODOFO_SKPODOFOPARSEDPDF_H_ diff --git a/experimental/PdfViewer/pdfparser/podofo/SkPodofoUtils.cpp b/experimental/PdfViewer/pdfparser/podofo/SkPodofoUtils.cpp new file mode 100644 index 0000000000..1743510d88 --- /dev/null +++ b/experimental/PdfViewer/pdfparser/podofo/SkPodofoUtils.cpp @@ -0,0 +1,416 @@ + +#include "SkPodofoUtils.h" +#include "SkMatrix.h" +#include "SkPdfHeaders_autogen.h" +#include "SkPdfMapper_autogen.h" + +#include "podofo.h" + +const PoDoFo::PdfObject* resolveReferenceObject(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfObject* obj, + bool resolveOneElementArrays) { + while (obj && (obj->IsReference() || (resolveOneElementArrays && + obj->IsArray() && + obj->GetArray().GetSize() == 1))) { + if (obj->IsReference()) { + // We need to force the non const, the only update we will do is for recurssion checks. + PoDoFo::PdfReference& ref = (PoDoFo::PdfReference&)obj->GetReference(); + obj = pdfDoc->podofo()->GetObjects().GetObject(ref); + } else { + obj = &obj->GetArray()[0]; + } + } + + return obj; +} + +// TODO(edisonn): deal with synonyms (/BPC == /BitsPerComponent), here or in GetKey? +// Always pass long form in key, and have a map of long -> short key +bool LongFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + long* data) { + const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc, + dict.GetKey(PoDoFo::PdfName(key))); + + if (value == NULL || !value->IsNumber()) { + return false; + } + if (data == NULL) { + return true; + } + + *data = value->GetNumber(); + return true; +} + +bool LongFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + long* data) { + if (LongFromDictionary(pdfDoc, dict, key, data)) return true; + if (abr == NULL || *abr == '\0') return false; + return LongFromDictionary(pdfDoc, dict, abr, data); +} + +bool DoubleFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + double* data) { + const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc, + dict.GetKey(PoDoFo::PdfName(key))); + + if (value == NULL || (!value->IsReal() && !value->IsNumber())) { + return false; + } + if (data == NULL) { + return true; + } + + *data = value->GetReal(); + return true; +} + +bool DoubleFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + double* data) { + if (DoubleFromDictionary(pdfDoc, dict, key, data)) return true; + if (abr == NULL || *abr == '\0') return false; + return DoubleFromDictionary(pdfDoc, dict, abr, data); +} + + +bool BoolFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + bool* data) { + const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc, + dict.GetKey(PoDoFo::PdfName(key))); + + if (value == NULL || !value->IsBool()) { + return false; + } + if (data == NULL) { + return true; + } + + *data = value->GetBool(); + return true; +} + +bool BoolFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + bool* data) { + if (BoolFromDictionary(pdfDoc, dict, key, data)) return true; + if (abr == NULL || *abr == '\0') return false; + return BoolFromDictionary(pdfDoc, dict, abr, data); +} + +bool NameFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + std::string* data) { + const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc, + dict.GetKey(PoDoFo::PdfName(key)), + true); + if (value == NULL || !value->IsName()) { + return false; + } + if (data == NULL) { + return true; + } + + *data = value->GetName().GetName(); + return true; +} + +bool NameFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + std::string* data) { + if (NameFromDictionary(pdfDoc, dict, key, data)) return true; + if (abr == NULL || *abr == '\0') return false; + return NameFromDictionary(pdfDoc, dict, abr, data); +} + +bool StringFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + std::string* data) { + const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc, + dict.GetKey(PoDoFo::PdfName(key)), + true); + if (value == NULL || (!value->IsString() && !value->IsHexString())) { + return false; + } + if (data == NULL) { + return true; + } + + *data = value->GetString().GetString(); + return true; +} + +bool StringFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + std::string* data) { + if (StringFromDictionary(pdfDoc, dict, key, data)) return true; + if (abr == NULL || *abr == '\0') return false; + return StringFromDictionary(pdfDoc, dict, abr, data); +} + + +bool SkMatrixFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + SkMatrix** matrix) { + const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc, + dict.GetKey(PoDoFo::PdfName(key))); + + if (value == NULL || !value->IsArray()) { + return false; + } + + if (value->GetArray().GetSize() != 6) { + return false; + } + + double array[6]; + for (int i = 0; i < 6; i++) { + const PoDoFo::PdfObject* elem = resolveReferenceObject(pdfDoc, &value->GetArray()[i]); + if (elem == NULL || (!elem->IsReal() && !elem->IsNumber())) { + return false; + } + array[i] = elem->GetReal(); + } + + *matrix = new SkMatrix(); + **matrix = SkMatrixFromPdfMatrix(array); + return true; +} + +bool SkMatrixFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkMatrix** data) { + if (SkMatrixFromDictionary(pdfDoc, dict, key, data)) return true; + if (abr == NULL || *abr == '\0') return false; + return SkMatrixFromDictionary(pdfDoc, dict, abr, data); + +} + +bool SkRectFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + SkRect** rect) { + const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc, + dict.GetKey(PoDoFo::PdfName(key))); + + if (value == NULL || !value->IsArray()) { + return false; + } + + if (value->GetArray().GetSize() != 4) { + return false; + } + + double array[4]; + for (int i = 0; i < 4; i++) { + const PoDoFo::PdfObject* elem = resolveReferenceObject(pdfDoc, &value->GetArray()[i]); + if (elem == NULL || (!elem->IsReal() && !elem->IsNumber())) { + return false; + } + array[i] = elem->GetReal(); + } + + *rect = new SkRect(); + **rect = SkRect::MakeLTRB(SkDoubleToScalar(array[0]), + SkDoubleToScalar(array[1]), + SkDoubleToScalar(array[2]), + SkDoubleToScalar(array[3])); + return true; +} + +bool SkRectFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkRect** data) { + if (SkRectFromDictionary(pdfDoc, dict, key, data)) return true; + if (abr == NULL || *abr == '\0') return false; + return SkRectFromDictionary(pdfDoc, dict, abr, data); + +} + + +SkPdfObject* get(const SkPdfObject* obj, const char* key, const char* abr = "") { + PoDoFo::PdfObject* podofoObj = NULL; + if (obj == NULL) return NULL; + const SkPdfDictionary* dict = obj->asDictionary(); + if (dict == NULL) return NULL; + if (!dict->podofo()->IsDictionary()) return NULL; + ObjectFromDictionary(dict->doc(), dict->podofo()->GetDictionary(), key, abr, &podofoObj); + SkPdfObject* ret = NULL; + obj->doc()->mapper()->mapObject(podofoObj, &ret); + return ret; +} + +bool ArrayFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkPdfArray* data) {return false;} + +bool FileSpecFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkPdfFileSpec* data) {return false;} + +bool StreamFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkPdfStream** data); + +bool TreeFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkPdfTree** data) {return false;} + +bool DateFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkPdfDate* data) {return false;} + +bool FunctionFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkPdfFunction* data) {return false;} + + + + +bool ArrayFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + SkPdfArray** data) { + const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc, + dict.GetKey(PoDoFo::PdfName(key)), + true); + if (value == NULL || !value->IsArray()) { + return false; + } + if (data == NULL) { + return true; + } + + return pdfDoc->mapper()->mapArray(value, data); +} + + +bool ArrayFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkPdfArray** data) { + if (ArrayFromDictionary(pdfDoc, dict, key, data)) return true; + if (abr == NULL || *abr == '\0') return false; + return ArrayFromDictionary(pdfDoc, dict, abr, data); +} + +/* +bool DictionaryFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + SkPoDoFo::PdfDictionary** data) { + const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc, + dict.GetKey(PoDoFo::PdfName(key)), + true); + if (value == NULL || !value->IsDictionary()) { + return false; + } + if (data == NULL) { + return true; + } + + return pdfDoc->mapper()->mapDictionary(value, data); +} + +bool DictionaryFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkPoDoFo::PdfDictionary** data) { + if (DictionaryFromDictionary(pdfDoc, dict, key, data)) return true; + if (abr == NULL || *abr == '\0') return false; + return DictionaryFromDictionary(pdfDoc, dict, abr, data); +} +*/ + +bool ObjectFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + PoDoFo::PdfObject** data) { + const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc, + dict.GetKey(PoDoFo::PdfName(key)), + true); + if (value == NULL) { + return false; + } + if (data == NULL) { + return true; + } + *data = (PoDoFo::PdfObject*)value; + return true; +} + +bool ObjectFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + PoDoFo::PdfObject** data) { + if (ObjectFromDictionary(pdfDoc, dict, key, data)) return true; + if (abr == NULL || *abr == '\0') return false; + return ObjectFromDictionary(pdfDoc, dict, abr, data); +} + +bool StreamFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + SkPdfStream** data) { + const PoDoFo::PdfObject* value = resolveReferenceObject(pdfDoc, + dict.GetKey(PoDoFo::PdfName(key)), + true); + if (value == NULL) { + return false; + } + if (data == NULL) { + return true; + } + return pdfDoc->mapper()->mapStream(value, data); +} + +bool StreamFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkPdfStream** data) { + if (StreamFromDictionary(pdfDoc, dict, key, data)) return true; + if (abr == NULL || *abr == '\0') return false; + return StreamFromDictionary(pdfDoc, dict, abr, data); +} + + diff --git a/experimental/PdfViewer/pdfparser/podofo/SkPodofoUtils.h b/experimental/PdfViewer/pdfparser/podofo/SkPodofoUtils.h new file mode 100644 index 0000000000..b180f80ffa --- /dev/null +++ b/experimental/PdfViewer/pdfparser/podofo/SkPodofoUtils.h @@ -0,0 +1,122 @@ +#ifndef EXPERIMENTAL_PDFVIEWER_PDFPARSER_PODOFO_SKPODOFOUTILS_H_ +#define EXPERIMENTAL_PDFVIEWER_PDFPARSER_PODOFO_SKPODOFOUTILS_H_ + +#include <string> +#include "SkPdfNYI.h" + +class SkMatrix; +class SkRect; + +namespace PoDoFo { +class PdfDictionary; +class PdfObject; +} + +class SkPodofoParsedPDF; + +const PoDoFo::PdfObject* resolveReferenceObject(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfObject* obj, + bool resolveOneElementArrays = false); + +bool LongFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + long* data); + +bool DoubleFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + double* data); + +bool BoolFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + bool* data); + +bool NameFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + std::string* data); + +bool StringFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + std::string* data); +/* +class SkPoDoFo::PdfDictionary; +bool DictionaryFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkPoDoFo::PdfDictionary** data); +*/ + +bool skpdfmap(const SkPodofoParsedPDF& podofoDoc, const PoDoFo::PdfObject& podofoObj, PoDoFo::PdfObject** out); + +bool ObjectFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + PoDoFo::PdfObject** data); + + +class SkPdfArray; +class SkPdfStream; + +bool ArrayFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkPdfArray** data); + +bool SkMatrixFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkMatrix** data); + +bool FileSpecFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkPdfFileSpec* data); + + +bool StreamFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkPdfStream** data); + +bool TreeFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkPdfTree** data); + +bool DateFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkPdfDate* data); + +bool SkRectFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkRect** data); + +bool FunctionFromDictionary(const SkPodofoParsedPDF* pdfDoc, + const PoDoFo::PdfDictionary& dict, + const char* key, + const char* abr, + SkPdfFunction* data); + +SkMatrix SkMatrixFromPdfMatrix(double array[6]); + +#endif // EXPERIMENTAL_PDFVIEWER_PDFPARSER_PODOFO_SKPODOFOUTILS_H_ diff --git a/experimental/PdfViewer/spec2def.py b/experimental/PdfViewer/spec2def.py index b53e25106e..8b77e728a6 100644 --- a/experimental/PdfViewer/spec2def.py +++ b/experimental/PdfViewer/spec2def.py @@ -292,7 +292,7 @@ def fix(val): return ret -def commitRow(): +def commitRow(fspecPy): global columnValues global emitedDitionaryName global table @@ -393,27 +393,27 @@ def commitRow(): comment = fix(tableToClassName[tableKey][1]) if len(tableToClassName[tableKey]) >= 3 and tableToClassName[tableKey][2] != '': - print(' pdfspec.addClass(\'' + emitedDitionaryName + '\', \'' + tableToClassName[tableKey][2] + '\', \'' + comment + '\')\\') + fspecPy.write(' pdfspec.addClass(\'' + emitedDitionaryName + '\', \'' + tableToClassName[tableKey][2] + '\', \'' + comment + '\')\\\n') else: - print(' pdfspec.addClass(\'' + emitedDitionaryName + '\', \'Dictionary\', \'' + comment + '\')\\') + fspecPy.write(' pdfspec.addClass(\'' + emitedDitionaryName + '\', \'Dictionary\', \'' + comment + '\')\\\n') if len(tableToClassName[tableKey]) >= 4 and columnValues[0] in tableToClassName[tableKey][3]: required = True if required: - print(' .required(\'NULL\')\\') + fspecPy.write(' .required(\'NULL\')\\\n') else: - print(' .optional()\\') + fspecPy.write(' .optional()\\\n') - print(' .field(\'' + columnValues[0] + '\')\\') - print(' .name(\'' + columnValues[0] + '\')\\') - print(' .type(\'' + columnValues[1] + '\')\\') - print(' .comment(\'' + columnValues[2] + '\')\\') + fspecPy.write(' .field(\'' + columnValues[0] + '\')\\\n') + fspecPy.write(' .name(\'' + columnValues[0] + '\')\\\n') + fspecPy.write(' .type(\'' + columnValues[1] + '\')\\\n') + fspecPy.write(' .comment(\'' + columnValues[2] + '\')\\\n') if len(tableToClassName[tableKey]) >= 4 and columnValues[0] in tableToClassName[tableKey][3]: - print(' .must(' + tableToClassName[tableKey][3][columnValues[0]] + ')\\') + fspecPy.write(' .must(' + tableToClassName[tableKey][3][columnValues[0]] + ')\\\n') - print(' .done().done()\\') + fspecPy.write(' .done().done()\\\n') columnValues = None @@ -429,7 +429,7 @@ def appendRow(second, third): if third.rstrip() != '': columnValues[2] = columnValues[2] + '\n' + third.rstrip() -def rebaseTable(line): +def rebaseTable(fspecPy, line): global knownTypes global columnWidth @@ -445,7 +445,7 @@ def rebaseTable(line): i = i + 1 if words[i].startswith('(Optional') or words[i].startswith('(Required'): - commitRow() + commitRow(fspecPy) columnWidth[0] = line.find(words[1]) @@ -458,24 +458,24 @@ def rebaseTable(line): return False -def stopTable(): +def stopTable(fspecPy): global tableHeaderFound global emitedDitionaryName if not inTable(): return - commitRow() + commitRow(fspecPy) tableHeaderFound = False emitedDitionaryName = '' - print(' .done()') - print + fspecPy.write(' .done()\n') + fspecPy.write('\n') def killTable(): return -def processLineCore(line): +def processLineCore(fspecPy, line): global lines global tableLine global tableRow @@ -483,7 +483,7 @@ def processLineCore(line): global columnValues global mustFollowTableHeader - global fnewspec + #global fnewspec lines = lines + 1 @@ -493,12 +493,12 @@ def processLineCore(line): words = line.split() if len(words) == 0: - stopTable() + stopTable(fspecPy) return False isTableHeader = re.search('^[\s]*(TABLE [0-9].[0-9][0-9]?)', striped) if isTableHeader: - stopTable() + stopTable(fspecPy) tableDescriptionFound(striped) mustFollowTableHeader = True return False @@ -535,7 +535,7 @@ def processLineCore(line): newRow(first, second, third) return True - if rebaseTable(striped): + if rebaseTable(fspecPy, striped): first = striped[0 : columnWidth[0]] second = striped[columnWidth[0] : columnWidth[0] + columnWidth[1]] third = striped[columnWidth[0] + columnWidth[1] :] @@ -549,15 +549,15 @@ def processLineCore(line): return True if len(first.split()) > 1: - stopTable() + stopTable(fspecPy) return False if first != '' and first[0] == ' ': - stopTable() + stopTable(fspecPy) return False if first != '' and second != '' and third == '': - stopTable() + stopTable(fspecPy) return False if first == '' and second != '' and second[0] != ' ': @@ -565,7 +565,7 @@ def processLineCore(line): appendRow(second, third) return True else: - stopTable() + stopTable(fspecPy) return False if first != '' and second != '' and third[0] != '(': @@ -573,61 +573,65 @@ def processLineCore(line): return False if first == '' and second != '' and second[0] == ' ': - stopTable() + stopTable(fspecPy) return False if first != '' and second != '' and third[0] == '(': - commitRow() + commitRow(fspecPy) newRow(first, second, third) return True return False return False -def processLine(line): - global fnewspec +def processLine(fspecPy, line): + #global fnewspec - inSpec = processLineCore(line) + inSpec = processLineCore(fspecPy, line) #just return, use the next lines if you wish to rewrite spec - #return + return if inSpec: #resize colum with types line = line[:columnWidth[0] + columnWidth[1]] + (' ' * (60 - columnWidth[1])) + line[columnWidth[0] + columnWidth[1]:] line = line[:columnWidth[0]] + (' ' * (40 - columnWidth[0])) + line[columnWidth[0]:] - fnewspec.write(line) + #fnewspec.write(line) def generateDef(): global lines - global fnewspec + #global fnewspec + + #fnewspec = open('PdfReference-okular-2.txt', 'w') - fnewspec = open('PdfReference-okular-2.txt', 'w') + # pdf spec in text format + fspecText = open(sys.argv[1], 'r') - print 'import datatypes' - print + # pdf spec in python directives + fspecPy = open(sys.argv[2], 'w') + + fspecPy.write('import datatypes\n') + fspecPy.write('\n') - print 'def buildPdfSpec(pdfspec):' + fspecPy.write('def buildPdfSpec(pdfspec):\n') - for line in sys.stdin: - processLine(line) + for line in fspecText: + processLine(fspecPy, line) # close last table if it was not closed already - stopTable() + stopTable(fspecPy) - print + fspecPy.write('\n') - print 'def addDictionaryTypesTo(knowTypes):' + fspecPy.write('def addDictionaryTypesTo(knowTypes):\n') for e in tableToClassName: - print(' knowTypes[\'' + tableToClassName[e][0] + '\'] = [\'SkPdf' + tableToClassName[e][0] + '*\', \'' + tableToClassName[e][0] + 'FromDictionary\', datatypes.CppNull(), \'ret->podofo()->GetDataType() == ePdfDataType_Dictionary\']') - print - print - + fspecPy.write(' knowTypes[\'' + tableToClassName[e][0] + '\'] = [\'SkPdf' + tableToClassName[e][0] + '*\', \'SkPdf' + tableToClassName[e][0] + 'FromDictionary\', datatypes.CppNull(), \'ret->podofo()->GetDataType() == PoDoFo::ePdfDataType_Dictionary\', \'A_DICTIONARY\']\n') + fspecPy.write('\n') #print lines - fnewspec.close() + #fnewspec.close() if '__main__' == __name__: sys.exit(generateDef())
\ No newline at end of file |