diff options
author | 2013-08-22 15:37:21 +0000 | |
---|---|---|
committer | 2013-08-22 15:37:21 +0000 | |
commit | f68aed33819cbc98a95edeadde1da9303eca7fb2 (patch) | |
tree | 7b08f5ae985b4393cd21bee249d0e6c61c87eed3 /experimental | |
parent | bd2f30132e1433b4dd1276e59a03fc70fd8209d7 (diff) |
pdfviewer: when q start, and an operator is called, it should not be able to see operands before q. nest/unnest are similar with pop/push - simulates a stack of stacks, in a single stack
Review URL: https://codereview.chromium.org/23033022
git-svn-id: http://skia.googlecode.com/svn/trunk@10873 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'experimental')
-rw-r--r-- | experimental/PdfViewer/SkPdfFont.h | 2 | ||||
-rw-r--r-- | experimental/PdfViewer/SkPdfGraphicsState.h | 47 | ||||
-rw-r--r-- | experimental/PdfViewer/SkPdfRenderer.cpp | 22 | ||||
-rw-r--r-- | experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp | 10 | ||||
-rw-r--r-- | experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.h | 2 |
5 files changed, 72 insertions, 11 deletions
diff --git a/experimental/PdfViewer/SkPdfFont.h b/experimental/PdfViewer/SkPdfFont.h index 09e01ac86e..51e032980c 100644 --- a/experimental/PdfViewer/SkPdfFont.h +++ b/experimental/PdfViewer/SkPdfFont.h @@ -211,7 +211,7 @@ public: }; inline unsigned int ToUnicode(unsigned int ch) const { - if (fToUnicode) { + if (fToUnicode && fToUnicode->fCMapEncoding) { return fToUnicode->fCMapEncoding[ch]; } else { return ch; diff --git a/experimental/PdfViewer/SkPdfGraphicsState.h b/experimental/PdfViewer/SkPdfGraphicsState.h index 0928f443e0..abda00fe3b 100644 --- a/experimental/PdfViewer/SkPdfGraphicsState.h +++ b/experimental/PdfViewer/SkPdfGraphicsState.h @@ -24,14 +24,18 @@ class SkPdfSoftMaskDictionary; class SkPdfNativeDoc; class SkPdfAllocator; -// TODO(edisonn): move this class in iclude/core? +// TODO(edisonn): move this class in include/core? // Ref objects can't be dealt unless we use a specific class initialization // The difference between SkTDStackNew and SkTDStack is that SkTDStackNew uses new/delete // to be a manage c++ stuff (like initializations) + +// Adobe limits it to 28, so 256 should be more than enough +#define MAX_NESTING 256 + #include "SkTypes.h" template <typename T> class SkTDStackNew : SkNoncopyable { public: - SkTDStackNew() : fCount(0), fTotalCount(0) { + SkTDStackNew() : fCount(0), fTotalCount(0), fLocalCount(0) { fInitialRec.fNext = NULL; fRec = &fInitialRec; @@ -47,9 +51,36 @@ public: } } - int count() const { return fTotalCount; } - int depth() const { return fTotalCount; } - bool empty() const { return fTotalCount == 0; } + int count() const { return fLocalCount; } + int depth() const { return fLocalCount; } + bool empty() const { return fLocalCount == 0; } + + bool nests() { + return fNestingLevel; + } + + void nest() { + // We are are past max nesting levels, we will still continue to work, but we might fail + // to properly ignore errors. Ideally it should only mean poor rendering in exceptional + // cases + if (fNestingLevel >= 0 && fNestingLevel < MAX_NESTING) { + fNestings[fNestingLevel] = fLocalCount; + fLocalCount = 0; + } + fNestingLevel++; + } + + void unnest() { + SkASSERT(fNestingLevel > 0); + fNestingLevel--; + if (fNestingLevel >= 0 && fNestingLevel < MAX_NESTING) { + // TODO(edisonn): warn if fLocal > 0 + while (fLocalCount > 0) { + pop(); + } + fLocalCount = fNestings[fNestingLevel]; + } + } T* push() { SkASSERT(fCount <= kSlotCount); @@ -60,6 +91,7 @@ public: fCount = 0; } ++fTotalCount; + ++fLocalCount; return &fRec->fSlots[fCount++]; } @@ -94,6 +126,7 @@ public: void pop() { SkASSERT(fCount > 0 && fRec); + --fLocalCount; --fTotalCount; if (--fCount == 0) { if (fRec != &fInitialRec) { @@ -121,7 +154,9 @@ private: }; Rec fInitialRec; Rec* fRec; - int fCount, fTotalCount; + int fCount, fTotalCount, fLocalCount; + int fNestings[MAX_NESTING]; + int fNestingLevel; }; // TODO(edisonn): better class design. diff --git a/experimental/PdfViewer/SkPdfRenderer.cpp b/experimental/PdfViewer/SkPdfRenderer.cpp index e7be1d85ea..21e428777b 100644 --- a/experimental/PdfViewer/SkPdfRenderer.cpp +++ b/experimental/PdfViewer/SkPdfRenderer.cpp @@ -1085,13 +1085,25 @@ SkPdfResult PdfOp_q(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** // it is not possible to see under the previous q? pdfContext->fStateStack.push(pdfContext->fGraphicsState); canvas->save(); + pdfContext->fObjectStack.nest(); return kOK_SkPdfResult; } SkPdfResult PdfOp_Q(SkPdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) { - pdfContext->fGraphicsState = pdfContext->fStateStack.top(); - pdfContext->fStateStack.pop(); - canvas->restore(); + if (pdfContext->fStateStack.count() > 0) { + pdfContext->fGraphicsState = pdfContext->fStateStack.top(); + pdfContext->fStateStack.pop(); + canvas->restore(); + + if (pdfContext->fObjectStack.nests() <= 0) { + return kIgnoreError_SkPdfResult; + } else { + pdfContext->fObjectStack.unnest(); + } + } else { + return kIgnoreError_SkPdfResult; + } + return kOK_SkPdfResult; } @@ -2775,6 +2787,10 @@ bool SkPdfRenderer::renderPage(int page, SkCanvas* canvas, const SkRect& dst) co SkScalar w = dst.width(); SkScalar h = dst.height(); + if (SkScalarTruncToInt(w) <= 0 || SkScalarTruncToInt(h) <= 0) { + return true; + } + SkScalar wp = fPdfDoc->MediaBox(page).width(); SkScalar hp = fPdfDoc->MediaBox(page).height(); diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp b/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp index c32d5ffede..ebc27ad060 100644 --- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp +++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp @@ -358,6 +358,7 @@ void SkPdfNativeDoc::addCrossSectionInfo(int id, int generation, int offset, boo fObjects[id].fOffset = offset; fObjects[id].fObj = NULL; fObjects[id].fResolvedReference = NULL; + fObjects[id].fIsReferenceResolved = false; } SkPdfNativeObject* SkPdfNativeDoc::readObject(int id/*, int expectedGeneration*/) { @@ -546,15 +547,22 @@ SkPdfNativeObject* SkPdfNativeDoc::resolveReference(SkPdfNativeObject* ref) { return NULL; } - if (fObjects[id].fResolvedReference != NULL) { + if (fObjects[id].fIsReferenceResolved) { #ifdef PDF_TRACE printf("\nresolve(%s) = %s\n", ref->toString(0).c_str(), fObjects[id].fResolvedReference->toString(0, ref->toString().size() + 13).c_str()); #endif + // TODO(edisonn): for known good documents, assert here THAT THE REFERENCE IS NOT null return fObjects[id].fResolvedReference; } + // TODO(edisonn): there are pdfs in the crashing suite that cause a stack overflow here unless we check for resolved reference on next line + // determine if the pdf is corrupted, or we have a bug here + + // avoids recursive calls + fObjects[id].fIsReferenceResolved = true; + if (fObjects[id].fObj == NULL) { fObjects[id].fObj = readObject(id); } diff --git a/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.h b/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.h index ae89e8f585..411343b56c 100644 --- a/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.h +++ b/experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.h @@ -36,6 +36,7 @@ private: SkPdfNativeObject* fObj; // TODO(edisonn): perf ... probably it does not make sense to cache the ref. test it! SkPdfNativeObject* fResolvedReference; + bool fIsReferenceResolved; }; public: @@ -91,6 +92,7 @@ private: obj->fObj = NULL; obj->fResolvedReference = NULL; obj->fOffset = -1; + obj->fIsReferenceResolved = false; } SkPdfNativeObject* readObject(int id/*, int generation*/); |