aboutsummaryrefslogtreecommitdiffhomepage
path: root/experimental
diff options
context:
space:
mode:
authorGravatar edisonn@google.com <edisonn@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-08-22 15:37:21 +0000
committerGravatar edisonn@google.com <edisonn@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-08-22 15:37:21 +0000
commitf68aed33819cbc98a95edeadde1da9303eca7fb2 (patch)
tree7b08f5ae985b4393cd21bee249d0e6c61c87eed3 /experimental
parentbd2f30132e1433b4dd1276e59a03fc70fd8209d7 (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.h2
-rw-r--r--experimental/PdfViewer/SkPdfGraphicsState.h47
-rw-r--r--experimental/PdfViewer/SkPdfRenderer.cpp22
-rw-r--r--experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.cpp10
-rw-r--r--experimental/PdfViewer/pdfparser/native/SkPdfNativeDoc.h2
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*/);