| Index: experimental/PdfViewer/SkPdfParser.cpp
|
| ===================================================================
|
| --- experimental/PdfViewer/SkPdfParser.cpp (revision 9813)
|
| +++ experimental/PdfViewer/SkPdfParser.cpp (working copy)
|
| @@ -37,8 +37,17 @@
|
| // 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 @@
|
|
|
| #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 @@
|
| }
|
| }
|
|
|
| -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 @@
|
|
|
| // 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 @@
|
| }
|
|
|
| // 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 @@
|
| }
|
|
|
| PdfResult DrawText(PdfContext* pdfContext,
|
| - const SkPdfObject* str,
|
| + const SkPdfObject* _str,
|
| SkCanvas* canvas)
|
| {
|
|
|
| @@ -342,6 +327,13 @@
|
| 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_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 @@
|
| // 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 @@
|
| }
|
| */
|
|
|
| - 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,28 +590,18 @@
|
| }
|
|
|
| SkBitmap getSmaskFromObject(PdfContext* pdfContext, const SkPdfImageDictionary* obj) {
|
| - const PdfObject* sMask = resolveReferenceObject(&pdfContext->fPdfDoc->podofo(),
|
| - obj->podofo()->GetDictionary().GetKey(PdfName("SMask")));
|
| + const SkPdfImageDictionary* sMask = obj->SMask();
|
|
|
| -#ifdef PDF_TRACE
|
| - std::string str;
|
| if (sMask) {
|
| - sMask->ToString(str);
|
| - printf("/SMask of /Subtype /Image: %s\n", str.c_str());
|
| + return getImageFromObject(pdfContext, sMask, true);
|
| }
|
| -#endif
|
|
|
| - if (sMask) {
|
| - SkPdfImageDictionary skxobjmask(&pdfContext->fPdfDoc->podofo(), sMask);
|
| - return getImageFromObject(pdfContext, &skxobjmask, true);
|
| - }
|
| -
|
| // TODO(edisonn): implement GS SMask. Default to empty right now.
|
| return pdfContext->fGraphicsState.fSMask;
|
| }
|
|
|
| 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 @@
|
| 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 @@
|
| // 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 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 @@
|
| // 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 @@
|
| printf("%f ", array[i]);
|
| }
|
| printf("\n");
|
| - SkTraceMatrix(pdfContext->fGraphicsState.fMatrix);
|
| + SkTraceMatrix(pdfContext->fGraphicsState.fMatrix, "cm");
|
| #endif
|
|
|
| return kOK_PdfResult;
|
| @@ -1213,18 +860,26 @@
|
| 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);
|
|
|
| - PdfObject vty(PdfVariant(-(-ty)));
|
| - pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc->podofo(), &vty));
|
| + SkPdfNumber* vty = pdfContext->fPdfDoc->createNumber(ty);
|
| + pdfContext->fObjectStack.push(vty);
|
|
|
| - return PdfOp_Td(pdfContext, canvas, looper);
|
| + PdfResult ret = PdfOp_Td(pdfContext, canvas, looper);
|
| +
|
| + // 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 ret;
|
| }
|
|
|
| PdfResult PdfOp_Tm(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) {
|
| @@ -1257,12 +912,18 @@
|
| //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(new SkPdfNumber(&pdfContext->fPdfDoc->podofo(), &zero));
|
| - pdfContext->fObjectStack.push(new SkPdfNumber(&pdfContext->fPdfDoc->podofo(), &tl));
|
| - return PdfOp_Td(pdfContext, canvas, looper);
|
| + pdfContext->fObjectStack.push(zero);
|
| + pdfContext->fObjectStack.push(tl);
|
| +
|
| + PdfResult ret = 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 @@
|
|
|
| #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 @@
|
| 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 @@
|
| 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 @@
|
|
|
| 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 @@
|
| 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 @@
|
| 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 @@
|
| 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 @@
|
| 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 @@
|
|
|
| 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,61 +1943,53 @@
|
| // 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
|
|
|
| - #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?
|
|
|
| - // 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);
|
|
|
| - 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;
|
|
|
| - gDumpBitmap = &bitmap;
|
| + gDumpCanvas = &canvas;
|
| + doc->drawPage(pn, &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';
|
| - }
|
| - SkImageEncoder::EncodeFile(out.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
|
| + 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);
|
| }
|
| + return true;
|
| }
|
| - catch( PdfError & e )
|
| - {
|
| - e.PrintErrorMsg();
|
| - std::cout << "ERROR: PDF can't be parsed!" << inputFileName.c_str() << std::endl;
|
| - return false;
|
| - }
|
|
|
| return true;
|
| }
|
|
|