diff options
author | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-12-03 21:08:46 +0000 |
---|---|---|
committer | commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-12-03 21:08:46 +0000 |
commit | 93b766d11ba984e9eec946374fe214d7fc55e41b (patch) | |
tree | 01fd0264c99debdae6000e68cb022662a6183de8 /pdf | |
parent | 264d90fca00ebdb782a0c131d8185480e5d8fde6 (diff) | |
download | src-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.cpp | 56 |
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 || |