[PDF] Fix clipping in xfermode improvement.

In some cases, the wrong clip (src clip instead of initial clip) was used.
Switch almost exclusively to initial clip because it is safe and generates a smaller result.

BUG=chromium:328009
R=reed@google.com, bungeman@google.com

Author: vandebo@chromium.org

Review URL: https://codereview.chromium.org/116423004

git-svn-id: http://skia.googlecode.com/svn/trunk@12729 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2013-12-17 23:38:28 +00:00
parent b09bfcb7b1
commit 4e8f1e56b1
3 changed files with 33 additions and 21 deletions

View File

@ -72,3 +72,6 @@ xfermodeimagefilter
# Added by sugoi in https://codereview.chromium.org/101623007
displacement
# Added by vandebo while fixing Chromium bug 328009. Expanding xfermodes gm.
xfermodes

View File

@ -66,8 +66,10 @@ class XfermodesGM : public GM {
kQuarterClearInLayer_SrcType = 0x20,
//! A W/2xH/2 transparent image.
kSmallTransparentImage_SrcType = 0x40,
//! kRectangleImage_SrcType drawn directly with a mask.
kRectangleWithMask_SrcType = 0x80,
kAll_SrcType = 0x7F, //!< All the source types.
kAll_SrcType = 0xFF, //!< All the source types.
kBasic_SrcType = 0x03, //!< Just basic source types.
};
@ -112,6 +114,15 @@ class XfermodesGM : public GM {
canvas->drawRect(r, p);
break;
}
case kRectangleWithMask_SrcType: {
canvas->save(SkCanvas::kClip_SaveFlag);
restoreNeeded = true;
SkScalar w = SkIntToScalar(W);
SkScalar h = SkIntToScalar(H);
SkRect r = SkRect::MakeXYWH(x, y + h / 4, w, h * 23 / 60);
canvas->clipRect(r);
// Fall through.
}
case kRectangle_SrcType: {
SkScalar w = SkIntToScalar(W);
SkScalar h = SkIntToScalar(H);

View File

@ -1912,8 +1912,10 @@ void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode,
ContentEntry* contentEntries = getContentEntries()->get();
SkASSERT(dst);
SkASSERT(!contentEntries->fNext.get());
// We have to make a copy of these here because changing the current
// content into a form-xobject will destroy them.
// Changing the current content into a form-xobject will destroy the clip
// objects which is fine since the xobject will already be clipped. However
// if source has shape, we need to clip it too, so a copy of the clip is
// saved.
SkClipStack clipStack = contentEntries->fState.fClipStack;
SkRegion clipRegion = contentEntries->fState.fClipRegion;
@ -1930,7 +1932,8 @@ void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode,
// reduces to Dst.
if (shape == NULL || xfermode == SkXfermode::kDstOut_Mode ||
xfermode == SkXfermode::kSrcATop_Mode) {
ScopedContentEntry content(this, &clipStack, clipRegion, identity,
ScopedContentEntry content(this, &fExistingClipStack,
fExistingClipRegion, identity,
stockPaint);
SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst),
&content.entry()->fContent);
@ -1951,7 +1954,7 @@ void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode,
// the non-transparent parts of the device and the outlines (shape) of
// all images and devices drawn.
drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst,
&clipStack, clipRegion,
&fExistingClipStack, fExistingClipRegion,
SkXfermode::kSrcOver_Mode, true);
} else {
SkAutoTUnref<SkPDFFormXObject> dstMaskStorage;
@ -1970,16 +1973,17 @@ void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode,
dstMaskStorage.reset(createFormXObjectFromDevice());
dstMask = dstMaskStorage.get();
}
drawFormXObjectWithMask(addXObjectResource(dst), dstMask, &clipStack,
clipRegion, SkXfermode::kSrcOver_Mode, true);
drawFormXObjectWithMask(addXObjectResource(dst), dstMask,
&fExistingClipStack, fExistingClipRegion,
SkXfermode::kSrcOver_Mode, true);
}
if (xfermode == SkXfermode::kClear_Mode) {
return;
} else if (xfermode == SkXfermode::kSrc_Mode ||
xfermode == SkXfermode::kDstATop_Mode) {
ScopedContentEntry content(this, &clipStack, clipRegion, identity,
stockPaint);
ScopedContentEntry content(this, &fExistingClipStack,
fExistingClipRegion, identity, stockPaint);
if (content.entry()) {
SkPDFUtils::DrawFormXObject(
this->addXObjectResource(srcFormXObject.get()),
@ -1989,8 +1993,8 @@ void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode,
return;
}
} else if (xfermode == SkXfermode::kSrcATop_Mode) {
ScopedContentEntry content(this, &clipStack, clipRegion, identity,
stockPaint);
ScopedContentEntry content(this, &fExistingClipStack,
fExistingClipRegion, identity, stockPaint);
if (content.entry()) {
SkPDFUtils::DrawFormXObject(this->addXObjectResource(dst),
&content.entry()->fContent);
@ -2005,30 +2009,24 @@ void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode,
xfermode == SkXfermode::kDstATop_Mode ||
xfermode == SkXfermode::kModulate_Mode);
ScopedContentEntry inShapeContentEntry(this, &fExistingClipStack,
fExistingClipRegion, identity,
stockPaint);
if (!inShapeContentEntry.entry()) {
return;
}
if (xfermode == SkXfermode::kSrcIn_Mode ||
xfermode == SkXfermode::kSrcOut_Mode ||
xfermode == SkXfermode::kSrcATop_Mode) {
drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst,
&clipStack, clipRegion,
&fExistingClipStack, fExistingClipRegion,
SkXfermode::kSrcOver_Mode,
xfermode == SkXfermode::kSrcOut_Mode);
} else {
SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode;
if (xfermode == SkXfermode::kModulate_Mode) {
drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()),
dst, &clipStack, clipRegion,
dst, &fExistingClipStack,
fExistingClipRegion,
SkXfermode::kSrcOver_Mode, false);
mode = SkXfermode::kMultiply_Mode;
}
drawFormXObjectWithMask(addXObjectResource(dst), srcFormXObject.get(),
&clipStack, clipRegion, mode,
&fExistingClipStack, fExistingClipRegion, mode,
xfermode == SkXfermode::kDstOut_Mode);
}
}