summaryrefslogtreecommitdiff
path: root/pdf
diff options
context:
space:
mode:
authorcommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-12-03 21:08:46 +0000
committercommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-12-03 21:08:46 +0000
commit93b766d11ba984e9eec946374fe214d7fc55e41b (patch)
tree01fd0264c99debdae6000e68cb022662a6183de8 /pdf
parent264d90fca00ebdb782a0c131d8185480e5d8fde6 (diff)
downloadsrc-93b766d11ba984e9eec946374fe214d7fc55e41b.tar.gz
[PDF] Fixes the cases where SkPDFDevice::finishContentEntry is called with empty content.
There are some cases (like drawing a completely transparent image) where the code tries to finish a content entry with no content and an xfermode other than clear. This makes those cases work correctly. This is likely what was happening in chromium:316546, but it wasn't clear what the core problem was. desk_techcrunch.skp tripped a debug only assert that exposed the core issue. BUG=skia:1868,chromium:316546 R=reed@google.com, bungeman@google.com Author: vandebo@chromium.org Review URL: https://codereview.chromium.org/92453002 git-svn-id: http://skia.googlecode.com/svn/trunk/src@12473 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'pdf')
-rw-r--r--pdf/SkPDFDevice.cpp56
1 files changed, 41 insertions, 15 deletions
diff --git a/pdf/SkPDFDevice.cpp b/pdf/SkPDFDevice.cpp
index bdabc53f..cdfec330 100644
--- a/pdf/SkPDFDevice.cpp
+++ b/pdf/SkPDFDevice.cpp
@@ -1875,11 +1875,12 @@ ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* clipStack,
return entry;
}
-void SkPDFDevice::finishContentEntry(const SkXfermode::Mode xfermode,
+void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode,
SkPDFFormXObject* dst,
SkPath* shape) {
if (xfermode != SkXfermode::kClear_Mode &&
xfermode != SkXfermode::kSrc_Mode &&
+ xfermode != SkXfermode::kDstOver_Mode &&
xfermode != SkXfermode::kSrcIn_Mode &&
xfermode != SkXfermode::kDstIn_Mode &&
xfermode != SkXfermode::kSrcOut_Mode &&
@@ -1890,6 +1891,18 @@ void SkPDFDevice::finishContentEntry(const SkXfermode::Mode xfermode,
SkASSERT(!dst);
return;
}
+ if (xfermode == SkXfermode::kDstOver_Mode) {
+ SkASSERT(!dst);
+ ContentEntry* firstContentEntry = getContentEntries()->get();
+ if (firstContentEntry->fContent.getOffset() == 0) {
+ // For DstOver, an empty content entry was inserted before the rest
+ // of the content entries. If nothing was drawn, it needs to be
+ // removed.
+ SkAutoTDelete<ContentEntry>* contentEntries = getContentEntries();
+ contentEntries->reset(firstContentEntry->fNext.detach());
+ }
+ return;
+ }
if (!dst) {
SkASSERT(xfermode == SkXfermode::kSrc_Mode ||
xfermode == SkXfermode::kSrcOut_Mode);
@@ -1904,17 +1917,32 @@ void SkPDFDevice::finishContentEntry(const SkXfermode::Mode xfermode,
SkClipStack clipStack = contentEntries->fState.fClipStack;
SkRegion clipRegion = contentEntries->fState.fClipRegion;
+ SkMatrix identity;
+ identity.reset();
+ SkPaint stockPaint;
+
SkAutoTUnref<SkPDFFormXObject> srcFormXObject;
if (isContentEmpty()) {
- SkASSERT(xfermode == SkXfermode::kClear_Mode);
+ // If nothing was drawn and there's no shape, then the draw was a
+ // no-op, but dst needs to be restored for that to be true.
+ // If there is shape, then an empty source with Src, SrcIn, SrcOut,
+ // DstIn, DstAtop or Modulate reduces to Clear and DstOut or SrcAtop
+ // reduces to Dst.
+ if (shape == NULL || xfermode == SkXfermode::kDstOut_Mode ||
+ xfermode == SkXfermode::kSrcATop_Mode) {
+ ScopedContentEntry content(this, &clipStack, clipRegion, identity,
+ stockPaint);
+ SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst),
+ &content.entry()->fContent);
+ return;
+ } else {
+ xfermode = SkXfermode::kClear_Mode;
+ }
} else {
SkASSERT(!fContentEntries->fNext.get());
srcFormXObject.reset(createFormXObjectFromDevice());
}
- SkMatrix identity;
- identity.reset();
-
// TODO(vandebo) srcFormXObject may contain alpha, but here we want it
// without alpha.
if (xfermode == SkXfermode::kSrcATop_Mode) {
@@ -1946,16 +1974,7 @@ void SkPDFDevice::finishContentEntry(const SkXfermode::Mode xfermode,
clipRegion, SkXfermode::kSrcOver_Mode, true);
}
- SkPaint stockPaint;
-
- if (xfermode == SkXfermode::kSrcATop_Mode) {
- ScopedContentEntry content(this, &clipStack, clipRegion, identity,
- stockPaint);
- if (content.entry()) {
- SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst),
- &content.entry()->fContent);
- }
- } else if (xfermode == SkXfermode::kClear_Mode || !srcFormXObject.get()) {
+ if (xfermode == SkXfermode::kClear_Mode) {
return;
} else if (xfermode == SkXfermode::kSrc_Mode ||
xfermode == SkXfermode::kDstATop_Mode) {
@@ -1969,6 +1988,13 @@ void SkPDFDevice::finishContentEntry(const SkXfermode::Mode xfermode,
if (xfermode == SkXfermode::kSrc_Mode) {
return;
}
+ } else if (xfermode == SkXfermode::kSrcATop_Mode) {
+ ScopedContentEntry content(this, &clipStack, clipRegion, identity,
+ stockPaint);
+ if (content.entry()) {
+ SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst),
+ &content.entry()->fContent);
+ }
}
SkASSERT(xfermode == SkXfermode::kSrcIn_Mode ||