diff options
-rw-r--r-- | expectations/gm/ignored-tests.txt | 4 | ||||
-rw-r--r-- | gm/xfermodes.cpp | 21 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 56 |
3 files changed, 61 insertions, 20 deletions
diff --git a/expectations/gm/ignored-tests.txt b/expectations/gm/ignored-tests.txt index 8d89cbca52..bf0bf7404a 100644 --- a/expectations/gm/ignored-tests.txt +++ b/expectations/gm/ignored-tests.txt @@ -45,6 +45,7 @@ perlinnoise # Added by bsalomon in support of adding HQ filter to GPU device drawBitmap bleed + downsamplebitmap_image_high_mandrill_512.png filterbitmap_image_mandrill_512.png filterbitmap_image_mandrill_256.png @@ -65,3 +66,6 @@ filterbitmap_text_10.00pt # Added by jvanverth in https://codereview.chromium.org/99993002/ colortype_gpu + +# Added by vandebo in https://codereview.chromium.org/92453002/ +xfermodes diff --git a/gm/xfermodes.cpp b/gm/xfermodes.cpp index 02cdd61927..6e1de3eb67 100644 --- a/gm/xfermodes.cpp +++ b/gm/xfermodes.cpp @@ -12,7 +12,8 @@ namespace skiagm { -static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst) { +static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst, + SkBitmap* transparent) { src->setConfig(SkBitmap::kARGB_8888_Config, w, h); src->allocPixels(); src->eraseColor(SK_ColorTRANSPARENT); @@ -41,6 +42,10 @@ static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst) { r.set(ww/3, hh/3, ww*19/20, hh*19/20); c.drawRect(r, p); } + + transparent->setConfig(SkBitmap::kARGB_8888_Config, w, h); + transparent->allocPixels(); + transparent->eraseColor(SK_ColorTRANSPARENT); } static uint16_t gData[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF }; @@ -59,13 +64,15 @@ class XfermodesGM : public GM { kQuarterClear_SrcType = 0x10, //! kQuarterClear_SrcType in a layer. kQuarterClearInLayer_SrcType = 0x20, + //! A W/2xH/2 transparent image. + kSmallTransparentImage_SrcType = 0x40, - kAll_SrcType = 0x3F, //!< All the source types. + kAll_SrcType = 0x7F, //!< All the source types. kBasic_SrcType = 0x03, //!< Just basic source types. }; SkBitmap fBG; - SkBitmap fSrcB, fDstB; + SkBitmap fSrcB, fDstB, fTransparent; /* The srcType argument indicates what to draw for the source part. Skia * uses the implied shape of the drawing command and these modes @@ -81,6 +88,10 @@ class XfermodesGM : public GM { canvas->drawBitmapMatrix(fSrcB, m, &p); p.setXfermode(mode); switch (srcType) { + case kSmallTransparentImage_SrcType: + m.postScale(SK_ScalarHalf, SK_ScalarHalf, x, y); + canvas->drawBitmapMatrix(fTransparent, m, &p); + break; case kQuarterClearInLayer_SrcType: { SkRect bounds = SkRect::MakeXYWH(x, y, SkIntToScalar(W), SkIntToScalar(H)); @@ -132,7 +143,7 @@ class XfermodesGM : public GM { fBG.setConfig(SkBitmap::kARGB_4444_Config, 2, 2, 4, kOpaque_SkAlphaType); fBG.setPixels(gData); - make_bitmaps(W, H, &fSrcB, &fDstB); + make_bitmaps(W, H, &fSrcB, &fDstB, &fTransparent); } public: @@ -146,7 +157,7 @@ protected: } virtual SkISize onISize() { - return make_isize(1590, 640); + return make_isize(1990, 640); } virtual void onDraw(SkCanvas* canvas) { diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index bdabc53f0f..cdfec330f0 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/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 || |