diff options
author | Mike Reed <reed@google.com> | 2016-10-03 21:34:16 +0000 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2016-10-03 21:34:36 +0000 |
commit | 2cbcd12281ee807214df094964c584c78932e10b (patch) | |
tree | 456f2c92158b18a8b010cc6e5bb594b73fbb998e /src | |
parent | 418374c0d27280f3a1161601ae5fab28a76a0d3c (diff) |
Revert "Revert "Revert "replace SkXfermode obj with SkBlendMode enum in paints"""
This reverts commit I86875511a13497112827cbaed1dbd7639e9e3d10.
legacy (100K) skp failure
Original change's description:
> Revert "Revert "replace SkXfermode obj with SkBlendMode enum in paints""
>
> This reverts commit ce02e7175872abde3721df9e5d3ec0ab8384cd8e.
>
> BUG=skia:
>
> GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2878
>
> Change-Id: I86875511a13497112827cbaed1dbd7639e9e3d10
> Reviewed-on: https://skia-review.googlesource.com/2878
> Reviewed-by: Matt Sarett <msarett@google.com>
> Commit-Queue: Mike Reed <reed@google.com>
>
TBR=msarett@google.com,reed@google.com,reviews@skia.org
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
Change-Id: Ife6f0cf3a22b3e8cf885a188f7f44e1ff62e06a5
Reviewed-on: https://skia-review.googlesource.com/2881
Reviewed-by: Mike Reed <reed@google.com>
Commit-Queue: Mike Reed <reed@google.com>
Diffstat (limited to 'src')
59 files changed, 488 insertions, 492 deletions
diff --git a/src/c/sk_paint.cpp b/src/c/sk_paint.cpp index 126170ca4c..f82cd815c1 100644 --- a/src/c/sk_paint.cpp +++ b/src/c/sk_paint.cpp @@ -5,7 +5,6 @@ * found in the LICENSE file. */ -#include "SkBlendMode.h" #include "SkMaskFilter.h" #include "SkPaint.h" #include "SkShader.h" @@ -133,41 +132,41 @@ void sk_paint_set_stroke_join(sk_paint_t* cpaint, sk_stroke_join_t cjoin) { void sk_paint_set_xfermode_mode(sk_paint_t* paint, sk_xfermode_mode_t mode) { SkASSERT(paint); - SkBlendMode skmode; + SkXfermode::Mode skmode; switch (mode) { #define MAP(X, Y) case (X): skmode = (Y); break - MAP( CLEAR_SK_XFERMODE_MODE, SkBlendMode::kClear ); - MAP( SRC_SK_XFERMODE_MODE, SkBlendMode::kSrc ); - MAP( DST_SK_XFERMODE_MODE, SkBlendMode::kDst ); - MAP( SRCOVER_SK_XFERMODE_MODE, SkBlendMode::kSrcOver ); - MAP( DSTOVER_SK_XFERMODE_MODE, SkBlendMode::kDstOver ); - MAP( SRCIN_SK_XFERMODE_MODE, SkBlendMode::kSrcIn ); - MAP( DSTIN_SK_XFERMODE_MODE, SkBlendMode::kDstIn ); - MAP( SRCOUT_SK_XFERMODE_MODE, SkBlendMode::kSrcOut ); - MAP( DSTOUT_SK_XFERMODE_MODE, SkBlendMode::kDstOut ); - MAP( SRCATOP_SK_XFERMODE_MODE, SkBlendMode::kSrcATop ); - MAP( DSTATOP_SK_XFERMODE_MODE, SkBlendMode::kDstATop ); - MAP( XOR_SK_XFERMODE_MODE, SkBlendMode::kXor ); - MAP( PLUS_SK_XFERMODE_MODE, SkBlendMode::kPlus ); - MAP( MODULATE_SK_XFERMODE_MODE, SkBlendMode::kModulate ); - MAP( SCREEN_SK_XFERMODE_MODE, SkBlendMode::kScreen ); - MAP( OVERLAY_SK_XFERMODE_MODE, SkBlendMode::kOverlay ); - MAP( DARKEN_SK_XFERMODE_MODE, SkBlendMode::kDarken ); - MAP( LIGHTEN_SK_XFERMODE_MODE, SkBlendMode::kLighten ); - MAP( COLORDODGE_SK_XFERMODE_MODE, SkBlendMode::kColorDodge ); - MAP( COLORBURN_SK_XFERMODE_MODE, SkBlendMode::kColorBurn ); - MAP( HARDLIGHT_SK_XFERMODE_MODE, SkBlendMode::kHardLight ); - MAP( SOFTLIGHT_SK_XFERMODE_MODE, SkBlendMode::kSoftLight ); - MAP( DIFFERENCE_SK_XFERMODE_MODE, SkBlendMode::kDifference ); - MAP( EXCLUSION_SK_XFERMODE_MODE, SkBlendMode::kExclusion ); - MAP( MULTIPLY_SK_XFERMODE_MODE, SkBlendMode::kMultiply ); - MAP( HUE_SK_XFERMODE_MODE, SkBlendMode::kHue ); - MAP( SATURATION_SK_XFERMODE_MODE, SkBlendMode::kSaturation ); - MAP( COLOR_SK_XFERMODE_MODE, SkBlendMode::kColor ); - MAP( LUMINOSITY_SK_XFERMODE_MODE, SkBlendMode::kLuminosity ); + MAP( CLEAR_SK_XFERMODE_MODE, SkXfermode::kClear_Mode ); + MAP( SRC_SK_XFERMODE_MODE, SkXfermode::kSrc_Mode ); + MAP( DST_SK_XFERMODE_MODE, SkXfermode::kDst_Mode ); + MAP( SRCOVER_SK_XFERMODE_MODE, SkXfermode::kSrcOver_Mode ); + MAP( DSTOVER_SK_XFERMODE_MODE, SkXfermode::kDstOver_Mode ); + MAP( SRCIN_SK_XFERMODE_MODE, SkXfermode::kSrcIn_Mode ); + MAP( DSTIN_SK_XFERMODE_MODE, SkXfermode::kDstIn_Mode ); + MAP( SRCOUT_SK_XFERMODE_MODE, SkXfermode::kSrcOut_Mode ); + MAP( DSTOUT_SK_XFERMODE_MODE, SkXfermode::kDstOut_Mode ); + MAP( SRCATOP_SK_XFERMODE_MODE, SkXfermode::kSrcATop_Mode ); + MAP( DSTATOP_SK_XFERMODE_MODE, SkXfermode::kDstATop_Mode ); + MAP( XOR_SK_XFERMODE_MODE, SkXfermode::kXor_Mode ); + MAP( PLUS_SK_XFERMODE_MODE, SkXfermode::kPlus_Mode ); + MAP( MODULATE_SK_XFERMODE_MODE, SkXfermode::kModulate_Mode ); + MAP( SCREEN_SK_XFERMODE_MODE, SkXfermode::kScreen_Mode ); + MAP( OVERLAY_SK_XFERMODE_MODE, SkXfermode::kOverlay_Mode ); + MAP( DARKEN_SK_XFERMODE_MODE, SkXfermode::kDarken_Mode ); + MAP( LIGHTEN_SK_XFERMODE_MODE, SkXfermode::kLighten_Mode ); + MAP( COLORDODGE_SK_XFERMODE_MODE, SkXfermode::kColorDodge_Mode ); + MAP( COLORBURN_SK_XFERMODE_MODE, SkXfermode::kColorBurn_Mode ); + MAP( HARDLIGHT_SK_XFERMODE_MODE, SkXfermode::kHardLight_Mode ); + MAP( SOFTLIGHT_SK_XFERMODE_MODE, SkXfermode::kSoftLight_Mode ); + MAP( DIFFERENCE_SK_XFERMODE_MODE, SkXfermode::kDifference_Mode ); + MAP( EXCLUSION_SK_XFERMODE_MODE, SkXfermode::kExclusion_Mode ); + MAP( MULTIPLY_SK_XFERMODE_MODE, SkXfermode::kMultiply_Mode ); + MAP( HUE_SK_XFERMODE_MODE, SkXfermode::kHue_Mode ); + MAP( SATURATION_SK_XFERMODE_MODE, SkXfermode::kSaturation_Mode ); + MAP( COLOR_SK_XFERMODE_MODE, SkXfermode::kColor_Mode ); + MAP( LUMINOSITY_SK_XFERMODE_MODE, SkXfermode::kLuminosity_Mode ); #undef MAP default: return; } - AsPaint(paint)->setBlendMode(skmode); + AsPaint(paint)->setXfermodeMode(skmode); } diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp index 26d253cf38..440de68345 100644 --- a/src/core/SkBitmapDevice.cpp +++ b/src/core/SkBitmapDevice.cpp @@ -446,7 +446,7 @@ bool SkBitmapDevice::onShouldDisableLCD(const SkPaint& paint) const { paint.getPathEffect() || paint.isFakeBoldText() || paint.getStyle() != SkPaint::kFill_Style || - !paint.isSrcOver()) + !SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode)) { return true; } diff --git a/src/core/SkBlendModePriv.h b/src/core/SkBlendModePriv.h deleted file mode 100644 index b5d9e751e6..0000000000 --- a/src/core/SkBlendModePriv.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2016 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkBlendModePriv_DEFINED -#define SkBlendModePriv_DEFINED - -#include "SkBlendMode.h" - -bool SkBlendMode_SupportsCoverageAsAlpha(SkBlendMode); - -#if SK_SUPPORT_GPU -sk_sp<GrXPFactory> SkBlendMode_AsXPFactory(SkBlendMode); -#endif - -#endif diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp index ce689d7e84..db9fcda93b 100644 --- a/src/core/SkBlitter.cpp +++ b/src/core/SkBlitter.cpp @@ -810,7 +810,7 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device, SkShader* shader = origPaint.getShader(); SkColorFilter* cf = origPaint.getColorFilter(); - SkBlendMode mode = origPaint.getBlendMode(); + SkXfermode* mode = origPaint.getXfermode(); sk_sp<Sk3DShader> shader3D; SkTCopyOnFirstWrite<SkPaint> paint(origPaint); @@ -823,12 +823,12 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device, shader = shader3D.get(); } - if (mode != SkBlendMode::kSrcOver) { + if (mode) { bool deviceIsOpaque = kRGB_565_SkColorType == device.colorType(); switch (SkInterpretXfermode(*paint, deviceIsOpaque)) { case kSrcOver_SkXfermodeInterpretation: - mode = SkBlendMode::kSrcOver; - paint.writable()->setBlendMode(mode); + mode = nullptr; + paint.writable()->setXfermode(nullptr); break; case kSkipDrawing_SkXfermodeInterpretation:{ return allocator->createT<SkNullBlitter>(); @@ -843,13 +843,13 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device, * color/shader/colorfilter, and just pretend we're SRC + color==0. This * will fall into our optimizations for SRC mode. */ - if (mode == SkBlendMode::kClear) { + if (SkXfermode::IsMode(mode, SkXfermode::kClear_Mode)) { SkPaint* p = paint.writable(); p->setShader(nullptr); shader = nullptr; p->setColorFilter(nullptr); cf = nullptr; - p->setBlendMode(mode = SkBlendMode::kSrc); + mode = p->setXfermodeMode(SkXfermode::kSrc_Mode); p->setColor(0); } @@ -858,7 +858,7 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device, } if (nullptr == shader) { - if (mode != SkBlendMode::kSrcOver) { + if (mode) { // xfermodes (and filters) require shaders for our current blitters paint.writable()->setShader(SkShader::MakeColorShader(paint->getColor())); paint.writable()->setAlpha(0xFF); @@ -909,7 +909,7 @@ SkBlitter* SkBlitter::Choose(const SkPixmap& device, case kAlpha_8_SkColorType: if (drawCoverage) { SkASSERT(nullptr == shader); - SkASSERT(paint->isSrcOver()); + SkASSERT(nullptr == paint->getXfermode()); blitter = allocator->createT<SkA8_Coverage_Blitter>(device, *paint); } else if (shader) { blitter = allocator->createT<SkA8_Shader_Blitter>(device, *paint, shaderContext); diff --git a/src/core/SkBlitter_A8.cpp b/src/core/SkBlitter_A8.cpp index cb7d718f54..66976143c8 100644 --- a/src/core/SkBlitter_A8.cpp +++ b/src/core/SkBlitter_A8.cpp @@ -230,8 +230,10 @@ SkA8_Shader_Blitter::SkA8_Shader_Blitter(const SkPixmap& device, const SkPaint& SkShader::Context* shaderContext) : INHERITED(device, paint, shaderContext) { - fXfermode = SkXfermode::Peek(paint.getBlendMode()); - SkASSERT(!fXfermode || fShaderContext); + if ((fXfermode = paint.getXfermode()) != nullptr) { + fXfermode->ref(); + SkASSERT(fShaderContext); + } int width = device.width(); fBuffer = (SkPMColor*)sk_malloc_throw(sizeof(SkPMColor) * (width + (SkAlign4(width) >> 2))); @@ -239,6 +241,7 @@ SkA8_Shader_Blitter::SkA8_Shader_Blitter(const SkPixmap& device, const SkPaint& } SkA8_Shader_Blitter::~SkA8_Shader_Blitter() { + if (fXfermode) SkSafeUnref(fXfermode); sk_free(fBuffer); } @@ -352,7 +355,7 @@ void SkA8_Shader_Blitter::blitMask(const SkMask& mask, const SkIRect& clip) { SkA8_Coverage_Blitter::SkA8_Coverage_Blitter(const SkPixmap& device, const SkPaint& paint) : SkRasterBlitter(device) { SkASSERT(nullptr == paint.getShader()); - SkASSERT(paint.isSrcOver()); + SkASSERT(nullptr == paint.getXfermode()); SkASSERT(nullptr == paint.getColorFilter()); } diff --git a/src/core/SkBlitter_ARGB32.cpp b/src/core/SkBlitter_ARGB32.cpp index ea0554d66e..aada0586a4 100644 --- a/src/core/SkBlitter_ARGB32.cpp +++ b/src/core/SkBlitter_ARGB32.cpp @@ -339,7 +339,8 @@ SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkPixmap& device, { fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor))); - fXfermode = SkXfermode::Peek(paint.getBlendMode()); + fXfermode = paint.getXfermode(); + SkSafeRef(fXfermode); int flags = 0; if (!(shaderContext->getFlags() & SkShader::kOpaqueAlpha_Flag)) { @@ -369,6 +370,7 @@ SkARGB32_Shader_Blitter::SkARGB32_Shader_Blitter(const SkPixmap& device, } SkARGB32_Shader_Blitter::~SkARGB32_Shader_Blitter() { + SkSafeUnref(fXfermode); sk_free(fBuffer); } diff --git a/src/core/SkBlitter_PM4f.cpp b/src/core/SkBlitter_PM4f.cpp index d63e924e2c..455a97b95d 100644 --- a/src/core/SkBlitter_PM4f.cpp +++ b/src/core/SkBlitter_PM4f.cpp @@ -325,7 +325,7 @@ static bool is_opaque(const SkPaint& paint, const SkShader::Context* shaderConte struct State4f { State4f(const SkImageInfo& info, const SkPaint& paint, const SkShader::Context* shaderContext) { - fXfer = SkXfermode::Peek(paint.getBlendMode()); + fXfer = paint.getXfermode(); if (shaderContext) { fBuffer.reset(info.width()); } else { @@ -410,7 +410,7 @@ template <typename State> SkBlitter* create(const SkPixmap& device, const SkPain SkShader::Context::BlitState bstate; sk_bzero(&bstate, sizeof(bstate)); bstate.fCtx = shaderContext; - bstate.fXfer = SkXfermode::Peek(paint.getBlendMode()); + bstate.fXfer = paint.getXfermode(); (void)shaderContext->chooseBlitProcs(device.info(), &bstate); return allocator->createT<SkState_Shader_Blitter<State>>(device, paint, bstate); diff --git a/src/core/SkBlitter_RGB16.cpp b/src/core/SkBlitter_RGB16.cpp index 7860b7cb6c..066ec616de 100644 --- a/src/core/SkBlitter_RGB16.cpp +++ b/src/core/SkBlitter_RGB16.cpp @@ -160,7 +160,7 @@ SkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkPixmap& device, const SkPai : INHERITED(device, paint) { SkASSERT(paint.getShader() == nullptr); SkASSERT(paint.getColorFilter() == nullptr); - SkASSERT(paint.isSrcOver()); + SkASSERT(paint.getXfermode() == nullptr); SkASSERT(paint.getColor() == SK_ColorBLACK); } @@ -683,7 +683,7 @@ SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkPixmap& device, SkShader::Context* shaderContext) : INHERITED(device, paint, shaderContext) { - SkASSERT(paint.isSrcOver()); + SkASSERT(paint.getXfermode() == nullptr); fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor)); @@ -809,8 +809,9 @@ SkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter( SkShader::Context* shaderContext) : INHERITED(device, paint, shaderContext) { - fXfermode = SkXfermode::Peek(paint.getBlendMode()); + fXfermode = paint.getXfermode(); SkASSERT(fXfermode); + fXfermode->ref(); int width = device.width(); fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor)); @@ -818,6 +819,7 @@ SkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter( } SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() { + fXfermode->unref(); sk_free(fBuffer); } @@ -895,14 +897,14 @@ SkBlitter* SkBlitter_ChooseD565(const SkPixmap& device, const SkPaint& paint, SkBlitter* blitter; SkShader* shader = paint.getShader(); - bool is_srcover = paint.isSrcOver(); + SkXfermode* mode = paint.getXfermode(); // we require a shader if there is an xfermode, handled by our caller - SkASSERT(is_srcover || shader); + SkASSERT(nullptr == mode || shader); if (shader) { SkASSERT(shaderContext != nullptr); - if (!is_srcover) { + if (mode) { blitter = allocator->createT<SkRGB16_Shader_Xfermode_Blitter>(device, paint, shaderContext); } else { diff --git a/src/core/SkBlitter_Sprite.cpp b/src/core/SkBlitter_Sprite.cpp index cef4cfaa2f..950f18791f 100644 --- a/src/core/SkBlitter_Sprite.cpp +++ b/src/core/SkBlitter_Sprite.cpp @@ -68,11 +68,14 @@ public: if (0xFF != paint.getAlpha()) { return false; } - SkBlendMode mode = paint.getBlendMode(); - if (SkBlendMode::kSrc == mode) { + SkXfermode::Mode mode; + if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) { + return false; + } + if (SkXfermode::kSrc_Mode == mode) { return true; } - if (SkBlendMode::kSrcOver == mode && src.isOpaque()) { + if (SkXfermode::kSrcOver_Mode == mode && src.isOpaque()) { return true; } @@ -82,7 +85,7 @@ public: return false; } - return SkBlendMode::kSrcOver == mode; + return SkXfermode::kSrcOver_Mode == mode; } SkSpriteBlitter_Src_SrcOver(const SkPixmap& src) @@ -91,11 +94,14 @@ public: void setup(const SkPixmap& dst, int left, int top, const SkPaint& paint) override { SkASSERT(Supports(dst, fSource, paint)); this->INHERITED::setup(dst, left, top, paint); - SkBlendMode mode = paint.getBlendMode(); + SkXfermode::Mode mode; + if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) { + SkFAIL("Should never happen."); + } - SkASSERT(mode == SkBlendMode::kSrcOver || mode == SkBlendMode::kSrc); + SkASSERT(mode == SkXfermode::kSrcOver_Mode || mode == SkXfermode::kSrc_Mode); - if (mode == SkBlendMode::kSrcOver && !fSource.isOpaque()) { + if (mode == SkXfermode::kSrcOver_Mode && !fSource.isOpaque()) { fUseMemcpy = false; } } diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index cf3b5309c4..7db8601846 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -484,7 +484,7 @@ public: */ SkPaint tmp; tmp.setImageFilter(fPaint->getImageFilter()); - tmp.setBlendMode(fPaint->getBlendMode()); + tmp.setXfermode(sk_ref_sp(fPaint->getXfermode())); SkRect storage; if (rawBounds) { // Make rawBounds include all paint outsets except for those due to image filters. @@ -558,7 +558,7 @@ bool AutoDrawLooper::doNext(SkDrawFilter::Type drawType) { if (fTempLayerForImageFilter) { paint->setImageFilter(nullptr); - paint->setBlendMode(SkBlendMode::kSrcOver); + paint->setXfermode(nullptr); } if (fLooperContext && !fLooperContext->next(fCanvas, paint)) { @@ -2634,7 +2634,7 @@ void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint, // nothing to draw if (text == nullptr || byteLength == 0 || draw.fRC->isEmpty() || - (paint.getAlpha() == 0 && paint.isSrcOver())) { + (paint.getAlpha() == 0 && paint.getXfermode() == nullptr)) { return; } @@ -2938,21 +2938,26 @@ void SkCanvas::onDrawAnnotation(const SkRect& rect, const char key[], SkData* va // methods, rather than actually drawing themselves. ////////////////////////////////////////////////////////////////////////////// -void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, SkBlendMode mode) { +void SkCanvas::drawARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b, + SkXfermode::Mode mode) { TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawARGB()"); SkPaint paint; paint.setARGB(a, r, g, b); - paint.setBlendMode(mode); + if (SkXfermode::kSrcOver_Mode != mode) { + paint.setXfermodeMode(mode); + } this->drawPaint(paint); } -void SkCanvas::drawColor(SkColor c, SkBlendMode mode) { +void SkCanvas::drawColor(SkColor c, SkXfermode::Mode mode) { TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawColor()"); SkPaint paint; paint.setColor(c); - paint.setBlendMode(mode); + if (SkXfermode::kSrcOver_Mode != mode) { + paint.setXfermodeMode(mode); + } this->drawPaint(paint); } diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp index 2a88781e48..53c8e5f0e8 100644 --- a/src/core/SkDraw.cpp +++ b/src/core/SkDraw.cpp @@ -7,7 +7,6 @@ #define __STDC_LIMIT_MACROS #include "SkDraw.h" -#include "SkBlendModePriv.h" #include "SkBlitter.h" #include "SkCanvas.h" #include "SkColorPriv.h" @@ -164,27 +163,31 @@ static BitmapXferProc ChooseBitmapXferProc(const SkPixmap& dst, const SkPaint& p return nullptr; } - SkBlendMode mode = paint.getBlendMode(); + SkXfermode::Mode mode; + if (!SkXfermode::AsMode(paint.getXfermode(), &mode)) { + return nullptr; + } + SkColor color = paint.getColor(); // collaps modes based on color... - if (SkBlendMode::kSrcOver == mode) { + if (SkXfermode::kSrcOver_Mode == mode) { unsigned alpha = SkColorGetA(color); if (0 == alpha) { - mode = SkBlendMode::kDst; + mode = SkXfermode::kDst_Mode; } else if (0xFF == alpha) { - mode = SkBlendMode::kSrc; + mode = SkXfermode::kSrc_Mode; } } switch (mode) { - case SkBlendMode::kClear: + case SkXfermode::kClear_Mode: // SkDebugf("--- D_Clear_BitmapXferProc\n"); return D_Clear_BitmapXferProc; // ignore data - case SkBlendMode::kDst: + case SkXfermode::kDst_Mode: // SkDebugf("--- D_Dst_BitmapXferProc\n"); return D_Dst_BitmapXferProc; // ignore data - case SkBlendMode::kSrc: { + case SkXfermode::kSrc_Mode: { /* should I worry about dithering for the lower depths? */ @@ -1140,7 +1143,7 @@ void SkDraw::drawPath(const SkPath& origSrcPath, const SkPaint& origPaint, if (SkDrawTreatAsHairline(origPaint, *matrix, &coverage)) { if (SK_Scalar1 == coverage) { paint.writable()->setStrokeWidth(0); - } else if (SkBlendMode_SupportsCoverageAsAlpha(origPaint.getBlendMode())) { + } else if (SkXfermode::SupportsCoverageAsAlpha(origPaint.getXfermode())) { U8CPU newAlpha; #if 0 newAlpha = SkToU8(SkScalarRoundToInt(coverage * diff --git a/src/core/SkGpuBlurUtils.cpp b/src/core/SkGpuBlurUtils.cpp index ec3b0a9909..5b29884c25 100644 --- a/src/core/SkGpuBlurUtils.cpp +++ b/src/core/SkGpuBlurUtils.cpp @@ -80,7 +80,7 @@ static void convolve_gaussian_1d(GrDrawContext* drawContext, sk_sp<GrFragmentProcessor> conv(GrConvolutionEffect::MakeGaussian( texture, direction, radius, sigma, useBounds, bounds)); paint.addColorFragmentProcessor(std::move(conv)); - paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); SkMatrix localMatrix = SkMatrix::MakeTrans(-SkIntToScalar(srcOffset.x()), -SkIntToScalar(srcOffset.y())); drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), @@ -110,7 +110,7 @@ static void convolve_gaussian_2d(GrDrawContext* drawContext, srcBounds ? GrTextureDomain::kDecal_Mode : GrTextureDomain::kIgnore_Mode, true, sigmaX, sigmaY)); paint.addColorFragmentProcessor(std::move(conv)); - paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); drawContext->fillRectWithLocalMatrix(clip, paint, SkMatrix::I(), SkRect::Make(dstRect), localMatrix); } @@ -285,7 +285,7 @@ sk_sp<GrDrawContext> GaussianBlur(GrContext* context, GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode); paint.addColorTextureProcessor(srcTexture.get(), nullptr, matrix, params); } - paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); shrink_irect_by_2(&dstRect, i < scaleFactorX, i < scaleFactorY); dstDrawContext->fillRectToRect(clip, paint, SkMatrix::I(), @@ -361,7 +361,7 @@ sk_sp<GrDrawContext> GaussianBlur(GrContext* context, GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBilerp_FilterMode); sk_sp<GrTexture> tex(srcDrawContext->asTexture()); paint.addColorTextureProcessor(tex.get(), nullptr, matrix, params); - paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); SkIRect dstRect(srcRect); scale_irect(&dstRect, scaleFactorX, scaleFactorY); diff --git a/src/core/SkImageFilter.cpp b/src/core/SkImageFilter.cpp index 68183cc444..63095bc65d 100644 --- a/src/core/SkImageFilter.cpp +++ b/src/core/SkImageFilter.cpp @@ -281,7 +281,7 @@ sk_sp<SkSpecialImage> SkImageFilter::DrawWithFP(GrContext* context, const OutputProperties& outputProperties) { GrPaint paint; paint.addColorFragmentProcessor(std::move(fp)); - paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); sk_sp<SkColorSpace> colorSpace = sk_ref_sp(outputProperties.colorSpace()); GrPixelConfig config = GrRenderableConfigForColorSpace(colorSpace.get()); diff --git a/src/core/SkMatrixImageFilter.cpp b/src/core/SkMatrixImageFilter.cpp index 0a33280414..12efc64683 100644 --- a/src/core/SkMatrixImageFilter.cpp +++ b/src/core/SkMatrixImageFilter.cpp @@ -85,7 +85,7 @@ sk_sp<SkSpecialImage> SkMatrixImageFilter::onFilterImage(SkSpecialImage* source, SkPaint paint; paint.setAntiAlias(true); - paint.setBlendMode(SkBlendMode::kSrc); + paint.setXfermodeMode(SkXfermode::kSrc_Mode); paint.setFilterQuality(fFilterQuality); input->draw(canvas, srcRect.x(), srcRect.y(), &paint); diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp index 1c5065e8c9..9d76a169b3 100644 --- a/src/core/SkPaint.cpp +++ b/src/core/SkPaint.cpp @@ -52,7 +52,6 @@ SkPaint::SkPaint() { fColor = SK_ColorBLACK; fWidth = 0; fMiterLimit = SkPaintDefaults_MiterLimit; - fBlendMode = (unsigned)SkBlendMode::kSrcOver; // Zero all bitfields, then set some non-zero defaults. fBitfieldsUInt = 0; @@ -70,6 +69,7 @@ SkPaint::SkPaint(const SkPaint& src) : COPY(fTypeface) , COPY(fPathEffect) , COPY(fShader) + , COPY(fXfermode) , COPY(fMaskFilter) , COPY(fColorFilter) , COPY(fRasterizer) @@ -81,7 +81,6 @@ SkPaint::SkPaint(const SkPaint& src) , COPY(fColor) , COPY(fWidth) , COPY(fMiterLimit) - , COPY(fBlendMode) , COPY(fBitfields) #undef COPY {} @@ -91,6 +90,7 @@ SkPaint::SkPaint(SkPaint&& src) { MOVE(fTypeface); MOVE(fPathEffect); MOVE(fShader); + MOVE(fXfermode); MOVE(fMaskFilter); MOVE(fColorFilter); MOVE(fRasterizer); @@ -102,7 +102,6 @@ SkPaint::SkPaint(SkPaint&& src) { MOVE(fColor); MOVE(fWidth); MOVE(fMiterLimit); - MOVE(fBlendMode); MOVE(fBitfields); #undef MOVE } @@ -118,6 +117,7 @@ SkPaint& SkPaint::operator=(const SkPaint& src) { ASSIGN(fTypeface); ASSIGN(fPathEffect); ASSIGN(fShader); + ASSIGN(fXfermode); ASSIGN(fMaskFilter); ASSIGN(fColorFilter); ASSIGN(fRasterizer); @@ -129,7 +129,6 @@ SkPaint& SkPaint::operator=(const SkPaint& src) { ASSIGN(fColor); ASSIGN(fWidth); ASSIGN(fMiterLimit); - ASSIGN(fBlendMode); ASSIGN(fBitfields); #undef ASSIGN @@ -145,6 +144,7 @@ SkPaint& SkPaint::operator=(SkPaint&& src) { MOVE(fTypeface); MOVE(fPathEffect); MOVE(fShader); + MOVE(fXfermode); MOVE(fMaskFilter); MOVE(fColorFilter); MOVE(fRasterizer); @@ -156,7 +156,6 @@ SkPaint& SkPaint::operator=(SkPaint&& src) { MOVE(fColor); MOVE(fWidth); MOVE(fMiterLimit); - MOVE(fBlendMode); MOVE(fBitfields); #undef MOVE @@ -168,6 +167,7 @@ bool operator==(const SkPaint& a, const SkPaint& b) { return EQUAL(fTypeface) && EQUAL(fPathEffect) && EQUAL(fShader) + && EQUAL(fXfermode) && EQUAL(fMaskFilter) && EQUAL(fColorFilter) && EQUAL(fRasterizer) @@ -179,7 +179,6 @@ bool operator==(const SkPaint& a, const SkPaint& b) { && EQUAL(fColor) && EQUAL(fWidth) && EQUAL(fMiterLimit) - && EQUAL(fBlendMode) && EQUAL(fBitfieldsUInt) ; #undef EQUAL @@ -361,6 +360,7 @@ MOVE_FIELD(Rasterizer) MOVE_FIELD(ImageFilter) MOVE_FIELD(Shader) MOVE_FIELD(ColorFilter) +MOVE_FIELD(Xfermode) MOVE_FIELD(PathEffect) MOVE_FIELD(MaskFilter) MOVE_FIELD(DrawLooper) @@ -386,10 +386,7 @@ SET_PTR(Shader) SET_PTR(ColorFilter) #endif #ifdef SK_SUPPORT_LEGACY_XFERMODE_PTR -SkXfermode* SkPaint::setXfermode(SkXfermode* xfer) { - this->setBlendMode(xfer ? xfer->blend() : SkBlendMode::kSrcOver); - return this->getXfermode(); -} +SET_PTR(Xfermode) #endif #ifdef SK_SUPPORT_LEGACY_PATHEFFECT_PTR SET_PTR(PathEffect) @@ -406,18 +403,10 @@ SkDrawLooper* SkPaint::setLooper(SkDrawLooper* looper) { } #endif -#ifdef SK_SUPPORT_LEGACY_XFERMODE_OBJECT -void SkPaint::setXfermode(sk_sp<SkXfermode> mode) { - this->setBlendMode(mode ? mode->blend() : SkBlendMode::kSrcOver); -} -SkXfermode* SkPaint::getXfermode() const { - return SkXfermode::Peek((SkBlendMode)fBlendMode); -} SkXfermode* SkPaint::setXfermodeMode(SkXfermode::Mode mode) { - this->setBlendMode((SkBlendMode)mode); - return SkXfermode::Peek((SkBlendMode)mode); + fXfermode = SkXfermode::Make(mode); + return fXfermode.get(); // can/should we change this API to be void, like the other setters? } -#endif /////////////////////////////////////////////////////////////////////////////// @@ -1915,6 +1904,7 @@ void SkPaint::flatten(SkWriteBuffer& buffer) const { } if (asint(this->getPathEffect()) | asint(this->getShader()) | + asint(this->getXfermode()) | asint(this->getMaskFilter()) | asint(this->getColorFilter()) | asint(this->getRasterizer()) | @@ -1933,8 +1923,7 @@ void SkPaint::flatten(SkWriteBuffer& buffer) const { buffer.writeUInt(pack_paint_flags(this->getFlags(), this->getHinting(), this->getTextAlign(), this->getFilterQuality(), flatFlags)); buffer.writeUInt(pack_4(this->getStrokeCap(), this->getStrokeJoin(), - (this->getStyle() << 4) | this->getTextEncoding(), - fBlendMode)); + this->getStyle(), this->getTextEncoding())); // now we're done with ptr and the (pre)reserved space. If we need to write // additional fields, use the buffer directly @@ -1944,6 +1933,7 @@ void SkPaint::flatten(SkWriteBuffer& buffer) const { if (flatFlags & kHasEffects_FlatFlag) { buffer.writeFlattenable(this->getPathEffect()); buffer.writeFlattenable(this->getShader()); + buffer.writeFlattenable(this->getXfermode()); buffer.writeFlattenable(this->getMaskFilter()); buffer.writeFlattenable(this->getColorFilter()); buffer.writeFlattenable(this->getRasterizer()); @@ -1965,14 +1955,8 @@ void SkPaint::unflatten(SkReadBuffer& buffer) { uint32_t tmp = buffer.readUInt(); this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF)); this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF)); - if (buffer.isVersionLT(SkReadBuffer::kXfermodeToBlendMode_Version)) { - this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF)); - this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF)); - } else { - this->setStyle(static_cast<Style>((tmp >> 12) & 0xF)); - this->setTextEncoding(static_cast<TextEncoding>((tmp >> 8) & 0xF)); - this->setBlendMode((SkBlendMode)(tmp & 0xFF)); - } + this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF)); + this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF)); if (flatFlags & kHasTypeface_FlatFlag) { this->setTypeface(buffer.readTypeface()); @@ -1983,16 +1967,7 @@ void SkPaint::unflatten(SkReadBuffer& buffer) { if (flatFlags & kHasEffects_FlatFlag) { this->setPathEffect(buffer.readPathEffect()); this->setShader(buffer.readShader()); - if (buffer.isVersionLT(SkReadBuffer::kXfermodeToBlendMode_Version)) { - sk_sp<SkXfermode> xfer = buffer.readXfermode(); - if (xfer) { - SkXfermode::Mode mode; - if (!xfer->asMode(&mode)) { - mode = SkXfermode::kSrcOver_Mode; - } - this->setBlendMode((SkBlendMode)mode); - } - } + this->setXfermode(buffer.readXfermode()); this->setMaskFilter(buffer.readMaskFilter()); this->setColorFilter(buffer.readColorFilter()); this->setRasterizer(buffer.readRasterizer()); @@ -2011,6 +1986,7 @@ void SkPaint::unflatten(SkReadBuffer& buffer) { } else { this->setPathEffect(nullptr); this->setShader(nullptr); + this->setXfermode(nullptr); this->setMaskFilter(nullptr); this->setColorFilter(nullptr); this->setRasterizer(nullptr); @@ -2140,8 +2116,11 @@ void SkPaint::toString(SkString* str) const { str->append("</dd>"); } - if (!this->isSrcOver()) { - str->appendf("<dt>Xfermode:</dt><dd>%d</dd>", fBlendMode); + SkXfermode* xfer = this->getXfermode(); + if (xfer) { + str->append("<dt>Xfermode:</dt><dd>"); + xfer->toString(str); + str->append("</dd>"); } SkMaskFilter* maskFilter = this->getMaskFilter(); @@ -2384,20 +2363,23 @@ bool SkPaint::nothingToDraw() const { if (fDrawLooper) { return false; } - switch ((SkBlendMode)fBlendMode) { - case SkBlendMode::kSrcOver: - case SkBlendMode::kSrcATop: - case SkBlendMode::kDstOut: - case SkBlendMode::kDstOver: - case SkBlendMode::kPlus: - if (0 == this->getAlpha()) { - return !affects_alpha(fColorFilter.get()) && !affects_alpha(fImageFilter.get()); - } - break; - case SkBlendMode::kDst: - return true; - default: - break; + SkXfermode::Mode mode; + if (SkXfermode::AsMode(fXfermode.get(), &mode)) { + switch (mode) { + case SkXfermode::kSrcOver_Mode: + case SkXfermode::kSrcATop_Mode: + case SkXfermode::kDstOut_Mode: + case SkXfermode::kDstOver_Mode: + case SkXfermode::kPlus_Mode: + if (0 == this->getAlpha()) { + return !affects_alpha(fColorFilter.get()) && !affects_alpha(fImageFilter.get()); + } + break; + case SkXfermode::kDst_Mode: + return true; + default: + break; + } } return false; } @@ -2405,7 +2387,7 @@ bool SkPaint::nothingToDraw() const { uint32_t SkPaint::getHash() const { // We're going to hash 10 pointers and 7 32-bit values, finishing up with fBitfields, // so fBitfields should be 10 pointers and 6 32-bit values from the start. - static_assert(offsetof(SkPaint, fBitfields) == 8 * sizeof(void*) + 7 * sizeof(uint32_t), + static_assert(offsetof(SkPaint, fBitfields) == 9 * sizeof(void*) + 6 * sizeof(uint32_t), "SkPaint_notPackedTightly"); return SkOpts::hash(reinterpret_cast<const uint32_t*>(this), offsetof(SkPaint, fBitfields) + sizeof(fBitfields)); diff --git a/src/core/SkPaintPriv.cpp b/src/core/SkPaintPriv.cpp index cbe2558c2a..6725cb49be 100644 --- a/src/core/SkPaintPriv.cpp +++ b/src/core/SkPaintPriv.cpp @@ -41,7 +41,7 @@ bool SkPaintPriv::Overwrites(const SkPaint* paint, ShaderOverrideOpacity overrid } } - return SkXfermode::IsOpaque(paint->getBlendMode(), opacityType); + return SkXfermode::IsOpaque(paint->getXfermode(), opacityType); } bool SkPaintPriv::Overwrites(const SkBitmap& bitmap, const SkPaint* paint) { diff --git a/src/core/SkPixmap.cpp b/src/core/SkPixmap.cpp index 108c87757b..77498396b0 100644 --- a/src/core/SkPixmap.cpp +++ b/src/core/SkPixmap.cpp @@ -267,7 +267,7 @@ bool SkPixmap::scalePixels(const SkPixmap& dst, SkFilterQuality quality) const { SkPaint paint; paint.setFilterQuality(quality); - paint.setBlendMode(SkBlendMode::kSrc); + paint.setXfermodeMode(SkXfermode::kSrc_Mode); surface->getCanvas()->drawBitmapRect(bitmap, SkRect::MakeIWH(dst.width(), dst.height()), &paint); return true; diff --git a/src/core/SkRasterPipelineBlitter.cpp b/src/core/SkRasterPipelineBlitter.cpp index 91d60bee3a..1e8dcf59e0 100644 --- a/src/core/SkRasterPipelineBlitter.cpp +++ b/src/core/SkRasterPipelineBlitter.cpp @@ -82,8 +82,8 @@ SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst, } SkRasterPipeline shader, colorFilter, xfermode; - if (!append_effect_stages(paint.getColorFilter(), &colorFilter) || - !append_effect_stages(SkXfermode::Peek(paint.getBlendMode()), &xfermode )) { + if (!append_effect_stages(paint.getColorFilter(), &colorFilter) || + !append_effect_stages(paint.getXfermode(), &xfermode )) { return nullptr; } @@ -104,7 +104,7 @@ SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst, if (!paint.getShader()) { blitter->fShader.append(SkRasterPipeline::constant_color, &blitter->fPaintColor); } - if (paint.isSrcOver()) { + if (!paint.getXfermode()) { blitter->fXfermode.append(SkRasterPipeline::srcover); } diff --git a/src/core/SkReadBuffer.h b/src/core/SkReadBuffer.h index 4ac7973198..3e6742fde0 100644 --- a/src/core/SkReadBuffer.h +++ b/src/core/SkReadBuffer.h @@ -69,7 +69,6 @@ public: kLightingShaderWritesInvNormRotation = 45, kBlurMaskFilterWritesOccluder = 47, kGradientShaderFloatColor_Version = 49, - kXfermodeToBlendMode_Version = 50, }; /** diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp index dca19df100..ca9c1b6f78 100644 --- a/src/core/SkRecordDraw.cpp +++ b/src/core/SkRecordDraw.cpp @@ -341,27 +341,34 @@ private: return true; } - // Unusual blendmodes require us to process a saved layer + // Unusual Xfermodes require us to process a saved layer // even with operations outisde the clip. // For example, DstIn is used by masking layers. // https://code.google.com/p/skia/issues/detail?id=1291 // https://crbug.com/401593 - switch (paint->getBlendMode()) { - // For each of the following transfer modes, if the source - // alpha is zero (our transparent black), the resulting - // blended alpha is not necessarily equal to the original - // destination alpha. - case SkBlendMode::kClear: - case SkBlendMode::kSrc: - case SkBlendMode::kSrcIn: - case SkBlendMode::kDstIn: - case SkBlendMode::kSrcOut: - case SkBlendMode::kDstATop: - case SkBlendMode::kModulate: - return true; - break; - default: - break; + SkXfermode* xfermode = paint->getXfermode(); + SkXfermode::Mode mode; + // SrcOver is ok, and is also the common case with a nullptr xfermode. + // So we should make that the fast path and bypass the mode extraction + // and test. + if (xfermode && xfermode->asMode(&mode)) { + switch (mode) { + // For each of the following transfer modes, if the source + // alpha is zero (our transparent black), the resulting + // blended alpha is not necessarily equal to the original + // destination alpha. + case SkXfermode::kClear_Mode: + case SkXfermode::kSrc_Mode: + case SkXfermode::kSrcIn_Mode: + case SkXfermode::kDstIn_Mode: + case SkXfermode::kSrcOut_Mode: + case SkXfermode::kDstATop_Mode: + case SkXfermode::kModulate_Mode: + return true; + break; + default: + break; + } } } return false; diff --git a/src/core/SkRecordOpts.cpp b/src/core/SkRecordOpts.cpp index a7feec1fb3..d46a6573b5 100644 --- a/src/core/SkRecordOpts.cpp +++ b/src/core/SkRecordOpts.cpp @@ -98,7 +98,7 @@ static bool fold_opacity_layer_color_to_paint(const SkPaint* layerPaint, // looper drawing unmodulated filter layer twice and then modulating the result produces // different image to drawing modulated filter layer twice. // TODO: most likely the looper and only some xfer modes are the hard constraints - if (!paint->isSrcOver() || paint->getLooper()) { + if (paint->getXfermode() || paint->getLooper()) { return false; } @@ -129,9 +129,9 @@ static bool fold_opacity_layer_color_to_paint(const SkPaint* layerPaint, } // The layer paint can not have any effects. - if (layerPaint->getPathEffect() || + if (layerPaint->getPathEffect() || layerPaint->getShader() || - !layerPaint->isSrcOver() || + layerPaint->getXfermode() || layerPaint->getMaskFilter() || layerPaint->getColorFilter() || layerPaint->getRasterizer() || @@ -174,12 +174,16 @@ void SkRecordNoopSaveRestores(SkRecord* record) { } static bool effectively_srcover(const SkPaint* paint) { - if (!paint || paint->isSrcOver()) { + if (!paint) { + return true; + } + SkXfermode* mode = paint->getXfermode(); + if (SkXfermode::IsMode(mode, SkXfermode::kSrcOver_Mode)) { return true; } // src-mode with opaque and no effects (which might change opaqueness) is ok too. return !paint->getShader() && !paint->getColorFilter() && !paint->getImageFilter() && - 0xFF == paint->getAlpha() && paint->getBlendMode() == SkBlendMode::kSrc; + 0xFF == paint->getAlpha() && SkXfermode::IsMode(mode, SkXfermode::kSrc_Mode); } // For some SaveLayer-[drawing command]-Restore patterns, merge the SaveLayer's alpha into the diff --git a/src/core/SkSpriteBlitter4f.cpp b/src/core/SkSpriteBlitter4f.cpp index 38ec7394d7..a13edd9806 100644 --- a/src/core/SkSpriteBlitter4f.cpp +++ b/src/core/SkSpriteBlitter4f.cpp @@ -13,7 +13,7 @@ class Sprite_4f : public SkSpriteBlitter { public: Sprite_4f(const SkPixmap& src, const SkPaint& paint) : INHERITED(src) { - fXfer = SkXfermode::Peek(paint.getBlendMode()); + fXfer = paint.getXfermode(); fLoader = SkLoadSpanProc_Choose(src.info()); fFilter = SkFilterSpanProc_Choose(paint); fBuffer.reset(src.width()); diff --git a/src/core/SkSpriteBlitter_ARGB32.cpp b/src/core/SkSpriteBlitter_ARGB32.cpp index 1a76b1b2fe..93885996ea 100644 --- a/src/core/SkSpriteBlitter_ARGB32.cpp +++ b/src/core/SkSpriteBlitter_ARGB32.cpp @@ -63,7 +63,8 @@ public: fColorFilter = paint.getColorFilter(); SkSafeRef(fColorFilter); - fXfermode = SkXfermode::Peek(paint.getBlendMode()); + fXfermode = paint.getXfermode(); + SkSafeRef(fXfermode); fBufferSize = 0; fBuffer = nullptr; @@ -82,6 +83,7 @@ public: virtual ~Sprite_D32_XferFilter() { delete[] fBuffer; + SkSafeUnref(fXfermode); SkSafeUnref(fColorFilter); } @@ -261,7 +263,7 @@ SkSpriteBlitter* SkSpriteBlitter::ChooseL32(const SkPixmap& source, const SkPain } U8CPU alpha = paint.getAlpha(); - bool isSrcOver = paint.isSrcOver(); + SkXfermode* xfermode = paint.getXfermode(); SkColorFilter* filter = paint.getColorFilter(); SkSpriteBlitter* blitter = nullptr; @@ -270,7 +272,7 @@ SkSpriteBlitter* SkSpriteBlitter::ChooseL32(const SkPixmap& source, const SkPain if (alpha != 0xFF) { return nullptr; // we only have opaque sprites } - if (!isSrcOver || filter) { + if (xfermode || filter) { blitter = allocator->createT<Sprite_D32_S4444_XferFilter>(source, paint); } else if (source.isOpaque()) { blitter = allocator->createT<Sprite_D32_S4444_Opaque>(source); @@ -279,7 +281,7 @@ SkSpriteBlitter* SkSpriteBlitter::ChooseL32(const SkPixmap& source, const SkPain } break; case kN32_SkColorType: - if (!isSrcOver || filter) { + if (xfermode || filter) { if (255 == alpha) { // this can handle xfermode or filter, but not alpha blitter = allocator->createT<Sprite_D32_S32A_XferFilter>(source, paint); diff --git a/src/core/SkSpriteBlitter_RGB16.cpp b/src/core/SkSpriteBlitter_RGB16.cpp index 9df7dab48c..6c5a7cb130 100644 --- a/src/core/SkSpriteBlitter_RGB16.cpp +++ b/src/core/SkSpriteBlitter_RGB16.cpp @@ -307,7 +307,7 @@ SkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkPixmap& source, const SkPain if (paint.getMaskFilter() != nullptr) { // may add cases for this return nullptr; } - if (!paint.isSrcOver()) { // may add cases for this + if (paint.getXfermode() != nullptr) { // may add cases for this return nullptr; } if (paint.getColorFilter() != nullptr) { // may add cases for this diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp index 226f2b8b43..2717fab7e9 100644 --- a/src/core/SkXfermode.cpp +++ b/src/core/SkXfermode.cpp @@ -1553,64 +1553,3 @@ bool SkProcCoeffXfermode::onAppendStages(SkRasterPipeline* p) const { } return false; } - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -bool SkBlendMode_SupportsCoverageAsAlpha(SkBlendMode mode) { - switch (mode) { - case SkBlendMode::kDst: - case SkBlendMode::kSrcOver: - case SkBlendMode::kDstOver: - case SkBlendMode::kDstOut: - case SkBlendMode::kSrcATop: - case SkBlendMode::kXor: - case SkBlendMode::kPlus: - return true; - default: - break; - } - return false; -} - -bool SkXfermode::IsOpaque(SkBlendMode mode, SrcColorOpacity opacityType) { - const ProcCoeff rec = gProcCoeffs[(int)mode]; - - switch (rec.fSC) { - case kDA_Coeff: - case kDC_Coeff: - case kIDA_Coeff: - case kIDC_Coeff: - return false; - default: - break; - } - - switch (rec.fDC) { - case kZero_Coeff: - return true; - case kISA_Coeff: - return kOpaque_SrcColorOpacity == opacityType; - case kSA_Coeff: - return kTransparentBlack_SrcColorOpacity == opacityType || - kTransparentAlpha_SrcColorOpacity == opacityType; - case kSC_Coeff: - return kTransparentBlack_SrcColorOpacity == opacityType; - default: - return false; - } - return false; -} - -#if SK_SUPPORT_GPU -sk_sp<GrXPFactory> SkBlendMode_AsXPFactory(SkBlendMode mode) { - const ProcCoeff rec = gProcCoeffs[(int)mode]; - if (CANNOT_USE_COEFF != rec.fSC) { - sk_sp<GrXPFactory> result(GrPorterDuffXPFactory::Make(mode)); - SkASSERT(result); - return result; - } - - SkASSERT(GrCustomXfermode::IsSupportedMode((SkXfermode::Mode)mode)); - return GrCustomXfermode::MakeXPFactory((SkXfermode::Mode)mode); -} -#endif diff --git a/src/core/SkXfermodeInterpretation.cpp b/src/core/SkXfermodeInterpretation.cpp index 3a1da368d7..1b2c8e32e6 100644 --- a/src/core/SkXfermodeInterpretation.cpp +++ b/src/core/SkXfermodeInterpretation.cpp @@ -9,31 +9,38 @@ #include "SkPaint.h" static bool just_solid_color(const SkPaint& p) { - return SK_AlphaOPAQUE == p.getAlpha() && !p.getColorFilter() && !p.getShader(); + return SK_AlphaOPAQUE == p.getAlpha() + && !p.getColorFilter() && !p.getShader(); } -SkXfermodeInterpretation SkInterpretXfermode(const SkPaint& paint, bool dstIsOpaque) { - switch (paint.getBlendMode()) { - case SkBlendMode::kSrcOver: +SkXfermodeInterpretation SkInterpretXfermode(const SkPaint& paint, + bool dstIsOpaque) { + const SkXfermode* xfer = paint.getXfermode(); + SkXfermode::Mode mode; + if (!SkXfermode::AsMode(xfer, &mode)) { + return kNormal_SkXfermodeInterpretation; + } + switch (mode) { + case SkXfermode::kSrcOver_Mode: return kSrcOver_SkXfermodeInterpretation; - case SkBlendMode::kSrc: + case SkXfermode::kSrc_Mode: if (just_solid_color(paint)) { return kSrcOver_SkXfermodeInterpretation; } return kNormal_SkXfermodeInterpretation; - case SkBlendMode::kDst: + case SkXfermode::kDst_Mode: return kSkipDrawing_SkXfermodeInterpretation; - case SkBlendMode::kDstOver: + case SkXfermode::kDstOver_Mode: if (dstIsOpaque) { return kSkipDrawing_SkXfermodeInterpretation; } return kNormal_SkXfermodeInterpretation; - case SkBlendMode::kSrcIn: + case SkXfermode::kSrcIn_Mode: if (dstIsOpaque && just_solid_color(paint)) { return kSrcOver_SkXfermodeInterpretation; } return kNormal_SkXfermodeInterpretation; - case SkBlendMode::kDstIn: + case SkXfermode::kDstIn_Mode: if (just_solid_color(paint)) { return kSkipDrawing_SkXfermodeInterpretation; } diff --git a/src/effects/SkAlphaThresholdFilter.cpp b/src/effects/SkAlphaThresholdFilter.cpp index bbae2e1552..515e05b323 100644 --- a/src/effects/SkAlphaThresholdFilter.cpp +++ b/src/effects/SkAlphaThresholdFilter.cpp @@ -107,7 +107,7 @@ sk_sp<GrTexture> SkAlphaThresholdFilterImpl::createMaskTexture(GrContext* contex } GrPaint grPaint; - grPaint.setPorterDuffXPFactory(SkBlendMode::kSrc); + grPaint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); SkRegion::Iterator iter(fRegion); drawContext->clear(nullptr, 0x0, true); diff --git a/src/effects/SkColorFilterImageFilter.cpp b/src/effects/SkColorFilterImageFilter.cpp index 507a80580f..d6b23d5038 100644 --- a/src/effects/SkColorFilterImageFilter.cpp +++ b/src/effects/SkColorFilterImageFilter.cpp @@ -89,7 +89,7 @@ sk_sp<SkSpecialImage> SkColorFilterImageFilter::onFilterImage(SkSpecialImage* so SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrc); + paint.setXfermodeMode(SkXfermode::kSrc_Mode); paint.setColorFilter(fColorFilter); // TODO: it may not be necessary to clear or drawPaint inside the input bounds diff --git a/src/effects/SkDisplacementMapEffect.cpp b/src/effects/SkDisplacementMapEffect.cpp index 6c779b74fd..4f6386d92e 100644 --- a/src/effects/SkDisplacementMapEffect.cpp +++ b/src/effects/SkDisplacementMapEffect.cpp @@ -343,7 +343,7 @@ sk_sp<SkSpecialImage> SkDisplacementMapEffect::onFilterImage(SkSpecialImage* sou offsetMatrix, colorTexture.get(), SkISize::Make(color->width(), color->height()))); - paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); SkMatrix matrix; matrix.setTranslate(-SkIntToScalar(colorBounds.x()), -SkIntToScalar(colorBounds.y())); diff --git a/src/effects/SkDropShadowImageFilter.cpp b/src/effects/SkDropShadowImageFilter.cpp index cc43db7f08..b4b8cac4f0 100644 --- a/src/effects/SkDropShadowImageFilter.cpp +++ b/src/effects/SkDropShadowImageFilter.cpp @@ -95,6 +95,7 @@ sk_sp<SkSpecialImage> SkDropShadowImageFilter::onFilterImage(SkSpecialImage* sou SkPaint paint; paint.setImageFilter(SkBlurImageFilter::Make(sigma.fX, sigma.fY, nullptr)); paint.setColorFilter(SkColorFilter::MakeModeFilter(fColor, SkXfermode::kSrcIn_Mode)); + paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); SkVector offsetVec = SkVector::Make(fDx, fDy); ctx.ctm().mapVectors(&offsetVec, 1); diff --git a/src/effects/SkImageSource.cpp b/src/effects/SkImageSource.cpp index f96a4a1676..f434de4aa0 100644 --- a/src/effects/SkImageSource.cpp +++ b/src/effects/SkImageSource.cpp @@ -108,7 +108,7 @@ sk_sp<SkSpecialImage> SkImageSource::onFilterImage(SkSpecialImage* source, const // Subtract off the integer component of the translation (will be applied in offset, below). dstRect.offset(-SkIntToScalar(dstIRect.fLeft), -SkIntToScalar(dstIRect.fTop)); - paint.setBlendMode(SkBlendMode::kSrc); + paint.setXfermodeMode(SkXfermode::kSrc_Mode); // FIXME: this probably shouldn't be necessary, but drawImageRect asserts // None filtering when it's translate-only paint.setFilterQuality( diff --git a/src/effects/SkLayerDrawLooper.cpp b/src/effects/SkLayerDrawLooper.cpp index 784228fa8b..d8f774437e 100644 --- a/src/effects/SkLayerDrawLooper.cpp +++ b/src/effects/SkLayerDrawLooper.cpp @@ -104,7 +104,7 @@ void SkLayerDrawLooper::LayerDrawLooperContext::ApplyInfo( dst->setColorFilter(sk_ref_sp(src.getColorFilter())); } if (bits & kXfermode_Bit) { - dst->setBlendMode(src.getBlendMode()); + dst->setXfermode(sk_ref_sp(src.getXfermode())); } // we don't override these diff --git a/src/effects/SkLightingImageFilter.cpp b/src/effects/SkLightingImageFilter.cpp index 057ef24e95..56275743d7 100644 --- a/src/effects/SkLightingImageFilter.cpp +++ b/src/effects/SkLightingImageFilter.cpp @@ -396,7 +396,7 @@ void SkLightingImageFilterInternal::drawRect(GrDrawContext* drawContext, sk_sp<GrFragmentProcessor> fp(this->makeFragmentProcessor(src, matrix, srcBounds, boundaryMode)); paint.addColorFragmentProcessor(std::move(fp)); - paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); drawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect); } diff --git a/src/effects/SkMergeImageFilter.cpp b/src/effects/SkMergeImageFilter.cpp index 9830669f04..cc7e336a3d 100755 --- a/src/effects/SkMergeImageFilter.cpp +++ b/src/effects/SkMergeImageFilter.cpp @@ -131,7 +131,7 @@ sk_sp<SkSpecialImage> SkMergeImageFilter::onFilterImage(SkSpecialImage* source, SkPaint paint; if (fModes) { - paint.setBlendMode((SkBlendMode)fModes[i]); + paint.setXfermodeMode((SkXfermode::Mode)fModes[i]); } inputs[i]->draw(canvas, diff --git a/src/effects/SkMorphologyImageFilter.cpp b/src/effects/SkMorphologyImageFilter.cpp index 2bd792860b..82e47c5081 100644 --- a/src/effects/SkMorphologyImageFilter.cpp +++ b/src/effects/SkMorphologyImageFilter.cpp @@ -401,7 +401,7 @@ static void apply_morphology_rect(GrDrawContext* drawContext, radius, morphType, bounds)); - paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); drawContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect), SkRect::Make(srcRect)); } @@ -418,7 +418,7 @@ static void apply_morphology_rect_no_bounds(GrDrawContext* drawContext, paint.setGammaCorrect(drawContext->isGammaCorrect()); paint.addColorFragmentProcessor(GrMorphologyEffect::Make(texture, direction, radius, morphType)); - paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); drawContext->fillRectToRect(clip, paint, SkMatrix::I(), SkRect::Make(dstRect), SkRect::Make(srcRect)); } diff --git a/src/effects/SkOffsetImageFilter.cpp b/src/effects/SkOffsetImageFilter.cpp index 2e8b0d916d..1c99154f16 100644 --- a/src/effects/SkOffsetImageFilter.cpp +++ b/src/effects/SkOffsetImageFilter.cpp @@ -61,7 +61,7 @@ sk_sp<SkSpecialImage> SkOffsetImageFilter::onFilterImage(SkSpecialImage* source, canvas->clear(0x0); SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrc); + paint.setXfermodeMode(SkXfermode::kSrc_Mode); canvas->translate(SkIntToScalar(srcOffset.fX - bounds.fLeft), SkIntToScalar(srcOffset.fY - bounds.fTop)); diff --git a/src/effects/SkTileImageFilter.cpp b/src/effects/SkTileImageFilter.cpp index a140db216b..46c4d9af67 100644 --- a/src/effects/SkTileImageFilter.cpp +++ b/src/effects/SkTileImageFilter.cpp @@ -87,7 +87,7 @@ sk_sp<SkSpecialImage> SkTileImageFilter::onFilterImage(SkSpecialImage* source, SkASSERT(canvas); SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrc); + paint.setXfermodeMode(SkXfermode::kSrc_Mode); input->draw(canvas, SkIntToScalar(inputOffset.x()), SkIntToScalar(inputOffset.y()), @@ -107,7 +107,7 @@ sk_sp<SkSpecialImage> SkTileImageFilter::onFilterImage(SkSpecialImage* source, SkASSERT(canvas); SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrc); + paint.setXfermodeMode(SkXfermode::kSrc_Mode); paint.setShader(subset->makeShader(SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode)); canvas->translate(-dstRect.fLeft, -dstRect.fTop); canvas->drawRect(dstRect, paint); diff --git a/src/effects/SkXfermodeImageFilter.cpp b/src/effects/SkXfermodeImageFilter.cpp index 2335a760fb..952ce977aa 100644 --- a/src/effects/SkXfermodeImageFilter.cpp +++ b/src/effects/SkXfermodeImageFilter.cpp @@ -27,7 +27,7 @@ class SkXfermodeImageFilter_Base : public SkImageFilter { public: - SkXfermodeImageFilter_Base(SkBlendMode mode, sk_sp<SkImageFilter> inputs[2], + SkXfermodeImageFilter_Base(sk_sp<SkXfermode> mode, sk_sp<SkImageFilter> inputs[2], const CropRect* cropRect); SK_TO_STRING_OVERRIDE() @@ -55,7 +55,7 @@ protected: #endif private: - SkBlendMode fMode; + sk_sp<SkXfermode> fMode; friend class SkXfermodeImageFilter; @@ -64,7 +64,7 @@ private: /////////////////////////////////////////////////////////////////////////////// -sk_sp<SkImageFilter> SkXfermodeImageFilter::Make(SkBlendMode mode, +sk_sp<SkImageFilter> SkXfermodeImageFilter::Make(sk_sp<SkXfermode> mode, sk_sp<SkImageFilter> background, sk_sp<SkImageFilter> foreground, const SkImageFilter::CropRect* cropRect) { @@ -72,36 +72,23 @@ sk_sp<SkImageFilter> SkXfermodeImageFilter::Make(SkBlendMode mode, return sk_sp<SkImageFilter>(new SkXfermodeImageFilter_Base(mode, inputs, cropRect)); } -#ifdef SK_SUPPORT_LEGACY_XFERMODE_OBJECT -sk_sp<SkImageFilter> SkXfermodeImageFilter::Make(sk_sp<SkXfermode> mode, - sk_sp<SkImageFilter> background, - sk_sp<SkImageFilter> foreground, - const SkImageFilter::CropRect* cropRect) { - return Make(mode ? mode->blend() : SkBlendMode::kSrcOver, - std::move(background), std::move(foreground), cropRect); -} -#endif - -SkXfermodeImageFilter_Base::SkXfermodeImageFilter_Base(SkBlendMode mode, - sk_sp<SkImageFilter> inputs[2], - const CropRect* cropRect) +SkXfermodeImageFilter_Base::SkXfermodeImageFilter_Base(sk_sp<SkXfermode> mode, + sk_sp<SkImageFilter> inputs[2], + const CropRect* cropRect) : INHERITED(inputs, 2, cropRect) - , fMode(mode) -{} + , fMode(std::move(mode)) { +} sk_sp<SkFlattenable> SkXfermodeImageFilter_Base::CreateProc(SkReadBuffer& buffer) { SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2); - uint32_t mode = buffer.read32(); - if (!buffer.validate(mode <= (unsigned)SkBlendMode::kLastMode)) { - return nullptr; - } - return SkXfermodeImageFilter::Make((SkBlendMode)mode, common.getInput(0), common.getInput(1), + sk_sp<SkXfermode> mode(buffer.readXfermode()); + return SkXfermodeImageFilter::Make(std::move(mode), common.getInput(0), common.getInput(1), &common.cropRect()); } void SkXfermodeImageFilter_Base::flatten(SkWriteBuffer& buffer) const { this->INHERITED::flatten(buffer); - buffer.write32((unsigned)fMode); + buffer.writeFlattenable(fMode.get()); } sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::onFilterImage(SkSpecialImage* source, @@ -160,7 +147,7 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::onFilterImage(SkSpecialImage* if (background) { SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrc); + paint.setXfermodeMode(SkXfermode::kSrc_Mode); background->draw(canvas, SkIntToScalar(backgroundOffset.fX), SkIntToScalar(backgroundOffset.fY), &paint); @@ -174,7 +161,7 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::onFilterImage(SkSpecialImage* void SkXfermodeImageFilter_Base::drawForeground(SkCanvas* canvas, SkSpecialImage* img, const SkIRect& fgBounds) const { SkPaint paint; - paint.setBlendMode(fMode); + paint.setXfermode(fMode); if (img) { img->draw(canvas, SkIntToScalar(fgBounds.fLeft), SkIntToScalar(fgBounds.fTop), &paint); } @@ -188,7 +175,11 @@ void SkXfermodeImageFilter_Base::drawForeground(SkCanvas* canvas, SkSpecialImage #ifndef SK_IGNORE_TO_STRING void SkXfermodeImageFilter_Base::toString(SkString* str) const { str->appendf("SkXfermodeImageFilter: ("); - str->appendf("blendmode: (%d)", fMode); + str->appendf("xfermode: ("); + if (fMode) { + fMode->toString(str); + } + str->append(")"); if (this->getInput(0)) { str->appendf("foreground: ("); this->getInput(0)->toString(str); @@ -275,7 +266,7 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::filterImageGPU( paint.addColorFragmentProcessor(std::move(bgFP)); } - paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); sk_sp<GrDrawContext> drawContext( context->makeDrawContext(SkBackingFit::kApprox, bounds.width(), bounds.height(), @@ -299,9 +290,8 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::filterImageGPU( sk_sp<GrFragmentProcessor> SkXfermodeImageFilter_Base::makeFGFrag(sk_sp<GrFragmentProcessor> bgFP) const { // A null fMode is interpreted to mean kSrcOver_Mode (to match raster). - SkXfermode* xfer = SkXfermode::Peek(fMode); - sk_sp<SkXfermode> srcover; - if (!xfer) { + SkAutoTUnref<SkXfermode> mode(SkSafeRef(fMode.get())); + if (!mode) { // It would be awesome to use SkXfermode::Create here but it knows better // than us and won't return a kSrcOver_Mode SkXfermode. That means we // have to get one the hard way. @@ -309,11 +299,9 @@ SkXfermodeImageFilter_Base::makeFGFrag(sk_sp<GrFragmentProcessor> bgFP) const { rec.fProc = SkXfermode::GetProc(SkXfermode::kSrcOver_Mode); SkXfermode::ModeAsCoeff(SkXfermode::kSrcOver_Mode, &rec.fSC, &rec.fDC); - srcover.reset(new SkProcCoeffXfermode(rec, SkXfermode::kSrcOver_Mode)); - xfer = srcover.get(); - + mode.reset(new SkProcCoeffXfermode(rec, SkXfermode::kSrcOver_Mode)); } - return xfer->makeFragmentProcessorForImageFilter(std::move(bgFP)); + return mode->makeFragmentProcessorForImageFilter(std::move(bgFP)); } #endif @@ -324,8 +312,7 @@ class SkArithmeticImageFilter : public SkXfermodeImageFilter_Base { public: SkArithmeticImageFilter(float k1, float k2, float k3, float k4, bool enforcePMColor, sk_sp<SkImageFilter> inputs[2], const CropRect* cropRect) - // need to pass a blendmode to our inherited constructor, but we ignore it - : SkXfermodeImageFilter_Base(SkBlendMode::kSrcOver, inputs, cropRect) + : SkXfermodeImageFilter_Base(nullptr, inputs, cropRect) , fK{ k1, k2, k3, k4 } , fEnforcePMColor(enforcePMColor) {} @@ -360,8 +347,8 @@ sk_sp<SkFlattenable> SkArithmeticImageFilter::CreateProc(SkReadBuffer& buffer) { SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2); // skip the mode (srcover) our parent-class wrote - SkDEBUGCODE(uint32_t mode =) buffer.read32(); - SkASSERT((unsigned)SkBlendMode::kSrcOver == mode); + sk_sp<SkXfermode> mode(buffer.readXfermode()); + SkASSERT(nullptr == mode); float k[4]; for (int i = 0; i < 4; ++i) { @@ -488,16 +475,16 @@ sk_sp<SkImageFilter> SkXfermodeImageFilter::MakeArithmetic(float k1, float k2, f int mode = -1; // illegal mode if (SkScalarNearlyZero(k1) && SkScalarNearlyEqual(k2, SK_Scalar1) && SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) { - mode = (int)SkBlendMode::kSrc; + mode = SkXfermode::kSrc_Mode; } else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) && SkScalarNearlyEqual(k3, SK_Scalar1) && SkScalarNearlyZero(k4)) { - mode = (int)SkBlendMode::kDst; + mode = SkXfermode::kDst_Mode; } else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) && SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) { - mode = (int)SkBlendMode::kClear; + mode = SkXfermode::kClear_Mode; } if (mode >= 0) { - return SkXfermodeImageFilter::Make((SkBlendMode)mode, + return SkXfermodeImageFilter::Make(SkXfermode::Make((SkXfermode::Mode)mode), std::move(background), std::move(foreground), crop); } diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 176d5da59b..6cec1da86b 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -356,7 +356,7 @@ bool GrContext::writeSurfacePixels(GrSurface* surface, } GrPaint paint; paint.addColorFragmentProcessor(std::move(fp)); - paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); paint.setAllowSRGBInputs(true); SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); drawContext->drawRect(GrNoClip(), paint, matrix, rect, nullptr); @@ -471,7 +471,7 @@ bool GrContext::readSurfacePixels(GrSurface* src, if (fp) { GrPaint paint; paint.addColorFragmentProcessor(std::move(fp)); - paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); paint.setAllowSRGBInputs(true); SkRect rect = SkRect::MakeWH(SkIntToScalar(width), SkIntToScalar(height)); tempDC->drawRect(GrNoClip(), paint, SkMatrix::I(), rect, nullptr); diff --git a/src/gpu/GrDrawContext.cpp b/src/gpu/GrDrawContext.cpp index 42d6795903..e9a9619da5 100644 --- a/src/gpu/GrDrawContext.cpp +++ b/src/gpu/GrDrawContext.cpp @@ -241,7 +241,7 @@ void GrDrawContext::internalClear(const GrFixedClip& clip, GrPaint paint; paint.setColor4f(GrColor4f::FromGrColor(color)); - paint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::Mode::kSrc_Mode)); + paint.setXPFactory(GrPorterDuffXPFactory::Make(SkXfermode::kSrc_Mode)); this->drawRect(clip, paint, SkMatrix::I(), clearRect); } else if (isFull) { diff --git a/src/gpu/GrSWMaskHelper.cpp b/src/gpu/GrSWMaskHelper.cpp index 747b7574be..a20eacb75c 100644 --- a/src/gpu/GrSWMaskHelper.cpp +++ b/src/gpu/GrSWMaskHelper.cpp @@ -21,15 +21,15 @@ /* * Convert a boolean operation into a transfer mode code */ -static SkBlendMode op_to_mode(SkRegion::Op op) { - - static const SkBlendMode modeMap[] = { - SkBlendMode::kDstOut, // kDifference_Op - SkBlendMode::kModulate, // kIntersect_Op - SkBlendMode::kSrcOver, // kUnion_Op - SkBlendMode::kXor, // kXOR_Op - SkBlendMode::kClear, // kReverseDifference_Op - SkBlendMode::kSrc, // kReplace_Op +static SkXfermode::Mode op_to_mode(SkRegion::Op op) { + + static const SkXfermode::Mode modeMap[] = { + SkXfermode::kDstOut_Mode, // kDifference_Op + SkXfermode::kModulate_Mode, // kIntersect_Op + SkXfermode::kSrcOver_Mode, // kUnion_Op + SkXfermode::kXor_Mode, // kXOR_Op + SkXfermode::kClear_Mode, // kReverseDifference_Op + SkXfermode::kSrc_Mode, // kReplace_Op }; return modeMap[op]; @@ -42,7 +42,7 @@ void GrSWMaskHelper::drawRect(const SkRect& rect, SkRegion::Op op, bool antiAlias, uint8_t alpha) { SkPaint paint; - paint.setBlendMode(op_to_mode(op)); + paint.setXfermode(SkXfermode::Make(op_to_mode(op))); paint.setAntiAlias(antiAlias); paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha)); @@ -65,7 +65,7 @@ void GrSWMaskHelper::drawShape(const GrShape& shape, SkRegion::Op op, bool antiA SkASSERT(0xFF == paint.getAlpha()); fDraw.drawPathCoverage(path, paint); } else { - paint.setBlendMode(op_to_mode(op)); + paint.setXfermodeMode(op_to_mode(op)); paint.setColor(SkColorSetARGB(alpha, alpha, alpha, alpha)); fDraw.drawPath(path, paint); } diff --git a/src/gpu/GrTextureParamsAdjuster.cpp b/src/gpu/GrTextureParamsAdjuster.cpp index f51cc54aba..3ca90f5adb 100644 --- a/src/gpu/GrTextureParamsAdjuster.cpp +++ b/src/gpu/GrTextureParamsAdjuster.cpp @@ -72,7 +72,7 @@ static GrTexture* copy_on_gpu(GrTexture* inputTexture, const SkIRect* subset, GrTextureParams params(SkShader::kClamp_TileMode, copyParams.fFilter); paint.addColorTextureProcessor(inputTexture, nullptr, SkMatrix::I(), params); } - paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); SkRect localRect; if (subset) { diff --git a/src/gpu/GrTextureToYUVPlanes.cpp b/src/gpu/GrTextureToYUVPlanes.cpp index 93a62d2643..5e7dafecf3 100644 --- a/src/gpu/GrTextureToYUVPlanes.cpp +++ b/src/gpu/GrTextureToYUVPlanes.cpp @@ -41,7 +41,7 @@ static bool convert_texture(GrTexture* src, GrDrawContext* dst, int dstW, int ds return false; } GrPaint paint; - paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); paint.addColorFragmentProcessor(std::move(fp)); dst->drawRect(GrNoClip(), paint, SkMatrix::I(), SkRect::MakeIWH(dstW, dstH)); return true; diff --git a/src/gpu/GrYUVProvider.cpp b/src/gpu/GrYUVProvider.cpp index db58e0afed..b187ec3888 100644 --- a/src/gpu/GrYUVProvider.cpp +++ b/src/gpu/GrYUVProvider.cpp @@ -142,7 +142,7 @@ sk_sp<GrTexture> GrYUVProvider::refAsTexture(GrContext* ctx, } } - paint.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); const SkRect r = SkRect::MakeIWH(yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fWidth, yuvInfo.fSizeInfo.fSizes[SkYUVSizeInfo::kY].fHeight); diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp index ee4e40a642..d4db461c57 100644 --- a/src/gpu/SkGr.cpp +++ b/src/gpu/SkGr.cpp @@ -20,7 +20,6 @@ #include "GrXferProcessor.h" #include "GrYUVProvider.h" -#include "SkBlendModePriv.h" #include "SkColorFilter.h" #include "SkConfig8888.h" #include "SkCanvas.h" @@ -681,8 +680,9 @@ static inline bool skpaint_to_grpaint_impl(GrContext* context, // When the xfermode is null on the SkPaint (meaning kSrcOver) we need the XPFactory field on // the GrPaint to also be null (also kSrcOver). SkASSERT(!grPaint->getXPFactory()); - if (!skPaint.isSrcOver()) { - grPaint->setXPFactory(SkBlendMode_AsXPFactory(skPaint.getBlendMode())); + SkXfermode* xfermode = skPaint.getXfermode(); + if (xfermode) { + grPaint->setXPFactory(xfermode->asXPFactory()); } #ifndef SK_IGNORE_GPU_DITHER diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp index 80a0314ac2..4eb7a11c76 100644 --- a/src/gpu/effects/GrConfigConversionEffect.cpp +++ b/src/gpu/effects/GrConfigConversionEffect.cpp @@ -229,19 +229,19 @@ void GrConfigConversionEffect::TestForPreservingPMConversions(GrContext* context tempDC->asTexture().get(), GrSwizzle::RGBA(), *pmToUPMRule, SkMatrix::I())); paint1.addColorFragmentProcessor(std::move(pmToUPM1)); - paint1.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint1.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); readDC->fillRectToRect(GrNoClip(), paint1, SkMatrix::I(), kDstRect, kSrcRect); readDC->asTexture()->readPixels(0, 0, kSize, kSize, kConfig, firstRead); paint2.addColorFragmentProcessor(std::move(upmToPM)); - paint2.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint2.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); tempDC->fillRectToRect(GrNoClip(), paint2, SkMatrix::I(), kDstRect, kSrcRect); paint3.addColorFragmentProcessor(std::move(pmToUPM2)); - paint3.setPorterDuffXPFactory(SkBlendMode::kSrc); + paint3.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); readDC->fillRectToRect(GrNoClip(), paint3, SkMatrix::I(), kDstRect, kSrcRect); diff --git a/src/gpu/text/GrTextUtils.cpp b/src/gpu/text/GrTextUtils.cpp index a5685f0381..56d4ec1c00 100644 --- a/src/gpu/text/GrTextUtils.cpp +++ b/src/gpu/text/GrTextUtils.cpp @@ -547,7 +547,8 @@ void GrTextUtils::DrawPosTextAsPath(GrContext* context, } bool GrTextUtils::ShouldDisableLCD(const SkPaint& paint) { - return paint.getMaskFilter() || + return !SkXfermode::AsMode(paint.getXfermode(), nullptr) || + paint.getMaskFilter() || paint.getRasterizer() || paint.getPathEffect() || paint.isFakeBoldText() || diff --git a/src/image/SkImage.cpp b/src/image/SkImage.cpp index 67779ba146..2870f31ef1 100644 --- a/src/image/SkImage.cpp +++ b/src/image/SkImage.cpp @@ -259,7 +259,7 @@ bool SkImage_Base::onReadPixels(const SkImageInfo& dstInfo, void* dstPixels, siz SkCanvas canvas(bm); SkPaint paint; - paint.setBlendMode(SkBlendMode::kSrc); + paint.setXfermodeMode(SkXfermode::kSrc_Mode); canvas.drawImage(this, -SkIntToScalar(srcX), -SkIntToScalar(srcY), &paint); return true; diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index 217dd3f2b6..f13b4bc1f6 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -47,11 +47,12 @@ // Utility functions -// If the paint will definitely draw opaquely, replace kSrc with -// kSrcOver. http://crbug.com/473572 +// If the paint will definitely draw opaquely, replace kSrc_Mode with +// kSrcOver_Mode. http://crbug.com/473572 static void replace_srcmode_on_opaque_paint(SkPaint* paint) { - if (kSrcOver_SkXfermodeInterpretation == SkInterpretXfermode(*paint, false)) { - paint->setBlendMode(SkBlendMode::kSrcOver); + if (kSrcOver_SkXfermodeInterpretation + == SkInterpretXfermode(*paint, false)) { + paint->setXfermode(nullptr); } } @@ -391,7 +392,7 @@ public: const SkPaint& paint, bool hasText = false) : fDevice(device), fContentEntry(nullptr), - fBlendMode(SkBlendMode::kSrcOver), + fXfermode(SkXfermode::kSrcOver_Mode), fDstFormXObject(nullptr) { init(draw.fClipStack, draw.fRC->bwRgn(), *draw.fMatrix, paint, hasText); } @@ -400,7 +401,7 @@ public: const SkPaint& paint, bool hasText = false) : fDevice(device), fContentEntry(nullptr), - fBlendMode(SkBlendMode::kSrcOver), + fXfermode(SkXfermode::kSrcOver_Mode), fDstFormXObject(nullptr) { init(clipStack, clipRegion, matrix, paint, hasText); } @@ -411,7 +412,7 @@ public: if (shape->isEmpty()) { shape = nullptr; } - fDevice->finishContentEntry(fBlendMode, std::move(fDstFormXObject), shape); + fDevice->finishContentEntry(fXfermode, std::move(fDstFormXObject), shape); } } @@ -419,16 +420,16 @@ public: /* Returns true when we explicitly need the shape of the drawing. */ bool needShape() { - switch (fBlendMode) { - case SkBlendMode::kClear: - case SkBlendMode::kSrc: - case SkBlendMode::kSrcIn: - case SkBlendMode::kSrcOut: - case SkBlendMode::kDstIn: - case SkBlendMode::kDstOut: - case SkBlendMode::kSrcATop: - case SkBlendMode::kDstATop: - case SkBlendMode::kModulate: + switch (fXfermode) { + case SkXfermode::kClear_Mode: + case SkXfermode::kSrc_Mode: + case SkXfermode::kSrcIn_Mode: + case SkXfermode::kSrcOut_Mode: + case SkXfermode::kDstIn_Mode: + case SkXfermode::kDstOut_Mode: + case SkXfermode::kSrcATop_Mode: + case SkXfermode::kDstATop_Mode: + case SkXfermode::kModulate_Mode: return true; default: return false; @@ -437,7 +438,7 @@ public: /* Returns true unless we only need the shape of the drawing. */ bool needSource() { - if (fBlendMode == SkBlendMode::kClear) { + if (fXfermode == SkXfermode::kClear_Mode) { return false; } return true; @@ -454,7 +455,7 @@ public: private: SkPDFDevice* fDevice; SkPDFDevice::ContentEntry* fContentEntry; - SkBlendMode fBlendMode; + SkXfermode::Mode fXfermode; sk_sp<SkPDFObject> fDstFormXObject; SkPath fShape; @@ -465,7 +466,9 @@ private: NOT_IMPLEMENTED(!matrix.hasPerspective(), false); return; } - fBlendMode = paint.getBlendMode(); + if (paint.getXfermode()) { + paint.getXfermode()->asMode(&fXfermode); + } fContentEntry = fDevice->setUpContentEntry(clipStack, clipRegion, matrix, paint, hasText, &fDstFormXObject); @@ -1704,7 +1707,7 @@ void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex, sk_sp<SkPDFObject> mask, const SkClipStack* clipStack, const SkRegion& clipRegion, - SkBlendMode mode, + SkXfermode::Mode mode, bool invertClip) { if (clipRegion.isEmpty() && !invertClip) { return; @@ -1717,7 +1720,7 @@ void SkPDFDevice::drawFormXObjectWithMask(int xObjectIndex, SkMatrix identity; identity.reset(); SkPaint paint; - paint.setBlendMode(mode); + paint.setXfermodeMode(mode); ScopedContentEntry content(this, clipStack, clipRegion, identity, paint); if (!content.entry()) { return; @@ -1762,24 +1765,27 @@ SkPDFDevice::ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* cli } } - SkBlendMode blendMode = paint.getBlendMode(); + SkXfermode::Mode xfermode = SkXfermode::kSrcOver_Mode; + if (paint.getXfermode()) { + paint.getXfermode()->asMode(&xfermode); + } // For the following modes, we want to handle source and destination // separately, so make an object of what's already there. - if (blendMode == SkBlendMode::kClear || - blendMode == SkBlendMode::kSrc || - blendMode == SkBlendMode::kSrcIn || - blendMode == SkBlendMode::kDstIn || - blendMode == SkBlendMode::kSrcOut || - blendMode == SkBlendMode::kDstOut || - blendMode == SkBlendMode::kSrcATop || - blendMode == SkBlendMode::kDstATop || - blendMode == SkBlendMode::kModulate) { + if (xfermode == SkXfermode::kClear_Mode || + xfermode == SkXfermode::kSrc_Mode || + xfermode == SkXfermode::kSrcIn_Mode || + xfermode == SkXfermode::kDstIn_Mode || + xfermode == SkXfermode::kSrcOut_Mode || + xfermode == SkXfermode::kDstOut_Mode || + xfermode == SkXfermode::kSrcATop_Mode || + xfermode == SkXfermode::kDstATop_Mode || + xfermode == SkXfermode::kModulate_Mode) { if (!isContentEmpty()) { *dst = this->makeFormXObjectFromDevice(); SkASSERT(isContentEmpty()); - } else if (blendMode != SkBlendMode::kSrc && - blendMode != SkBlendMode::kSrcOut) { + } else if (xfermode != SkXfermode::kSrc_Mode && + xfermode != SkXfermode::kSrcOut_Mode) { // Except for Src and SrcOut, if there isn't anything already there, // then we're done. return nullptr; @@ -1789,14 +1795,14 @@ SkPDFDevice::ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* cli // Xor, Plus. // Dst xfer mode doesn't draw source at all. - if (blendMode == SkBlendMode::kDst) { + if (xfermode == SkXfermode::kDst_Mode) { return nullptr; } SkPDFDevice::ContentEntry* entry; if (fContentEntries.back() && fContentEntries.back()->fContent.getOffset() == 0) { entry = fContentEntries.back(); - } else if (blendMode != SkBlendMode::kDstOver) { + } else if (xfermode != SkXfermode::kDstOver_Mode) { entry = fContentEntries.emplace_back(); } else { entry = fContentEntries.emplace_front(); @@ -1806,23 +1812,23 @@ SkPDFDevice::ContentEntry* SkPDFDevice::setUpContentEntry(const SkClipStack* cli return entry; } -void SkPDFDevice::finishContentEntry(SkBlendMode blendMode, +void SkPDFDevice::finishContentEntry(SkXfermode::Mode xfermode, sk_sp<SkPDFObject> dst, SkPath* shape) { - if (blendMode != SkBlendMode::kClear && - blendMode != SkBlendMode::kSrc && - blendMode != SkBlendMode::kDstOver && - blendMode != SkBlendMode::kSrcIn && - blendMode != SkBlendMode::kDstIn && - blendMode != SkBlendMode::kSrcOut && - blendMode != SkBlendMode::kDstOut && - blendMode != SkBlendMode::kSrcATop && - blendMode != SkBlendMode::kDstATop && - blendMode != SkBlendMode::kModulate) { + 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 && + xfermode != SkXfermode::kDstOut_Mode && + xfermode != SkXfermode::kSrcATop_Mode && + xfermode != SkXfermode::kDstATop_Mode && + xfermode != SkXfermode::kModulate_Mode) { SkASSERT(!dst); return; } - if (blendMode == SkBlendMode::kDstOver) { + if (xfermode == SkXfermode::kDstOver_Mode) { SkASSERT(!dst); if (fContentEntries.front()->fContent.getOffset() == 0) { // For DstOver, an empty content entry was inserted before the rest @@ -1833,8 +1839,8 @@ void SkPDFDevice::finishContentEntry(SkBlendMode blendMode, return; } if (!dst) { - SkASSERT(blendMode == SkBlendMode::kSrc || - blendMode == SkBlendMode::kSrcOut); + SkASSERT(xfermode == SkXfermode::kSrc_Mode || + xfermode == SkXfermode::kSrcOut_Mode); return; } @@ -1859,8 +1865,8 @@ void SkPDFDevice::finishContentEntry(SkBlendMode blendMode, // 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 == nullptr || blendMode == SkBlendMode::kDstOut || - blendMode == SkBlendMode::kSrcATop) { + if (shape == nullptr || xfermode == SkXfermode::kDstOut_Mode || + xfermode == SkXfermode::kSrcATop_Mode) { ScopedContentEntry content(this, &fExistingClipStack, fExistingClipRegion, identity, stockPaint); @@ -1869,7 +1875,7 @@ void SkPDFDevice::finishContentEntry(SkBlendMode blendMode, &content.entry()->fContent); return; } else { - blendMode = SkBlendMode::kClear; + xfermode = SkXfermode::kClear_Mode; } } else { SkASSERT(fContentEntries.count() == 1); @@ -1878,14 +1884,14 @@ void SkPDFDevice::finishContentEntry(SkBlendMode blendMode, // TODO(vandebo) srcFormXObject may contain alpha, but here we want it // without alpha. - if (blendMode == SkBlendMode::kSrcATop) { + if (xfermode == SkXfermode::kSrcATop_Mode) { // TODO(vandebo): In order to properly support SrcATop we have to track // the shape of what's been drawn at all times. It's the intersection of // the non-transparent parts of the device and the outlines (shape) of // all images and devices drawn. drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), dst, &fExistingClipStack, fExistingClipRegion, - SkBlendMode::kSrcOver, true); + SkXfermode::kSrcOver_Mode, true); } else { if (shape != nullptr) { // Draw shape into a form-xobject. @@ -1901,19 +1907,19 @@ void SkPDFDevice::finishContentEntry(SkBlendMode blendMode, drawFormXObjectWithMask(addXObjectResource(dst.get()), this->makeFormXObjectFromDevice(), &fExistingClipStack, fExistingClipRegion, - SkBlendMode::kSrcOver, true); + SkXfermode::kSrcOver_Mode, true); } else { drawFormXObjectWithMask(addXObjectResource(dst.get()), srcFormXObject, &fExistingClipStack, fExistingClipRegion, - SkBlendMode::kSrcOver, true); + SkXfermode::kSrcOver_Mode, true); } } - if (blendMode == SkBlendMode::kClear) { + if (xfermode == SkXfermode::kClear_Mode) { return; - } else if (blendMode == SkBlendMode::kSrc || - blendMode == SkBlendMode::kDstATop) { + } else if (xfermode == SkXfermode::kSrc_Mode || + xfermode == SkXfermode::kDstATop_Mode) { ScopedContentEntry content(this, &fExistingClipStack, fExistingClipRegion, identity, stockPaint); if (content.entry()) { @@ -1921,10 +1927,10 @@ void SkPDFDevice::finishContentEntry(SkBlendMode blendMode, this->addXObjectResource(srcFormXObject.get()), &content.entry()->fContent); } - if (blendMode == SkBlendMode::kSrc) { + if (xfermode == SkXfermode::kSrc_Mode) { return; } - } else if (blendMode == SkBlendMode::kSrcATop) { + } else if (xfermode == SkXfermode::kSrcATop_Mode) { ScopedContentEntry content(this, &fExistingClipStack, fExistingClipRegion, identity, stockPaint); if (content.entry()) { @@ -1933,36 +1939,36 @@ void SkPDFDevice::finishContentEntry(SkBlendMode blendMode, } } - SkASSERT(blendMode == SkBlendMode::kSrcIn || - blendMode == SkBlendMode::kDstIn || - blendMode == SkBlendMode::kSrcOut || - blendMode == SkBlendMode::kDstOut || - blendMode == SkBlendMode::kSrcATop || - blendMode == SkBlendMode::kDstATop || - blendMode == SkBlendMode::kModulate); + SkASSERT(xfermode == SkXfermode::kSrcIn_Mode || + xfermode == SkXfermode::kDstIn_Mode || + xfermode == SkXfermode::kSrcOut_Mode || + xfermode == SkXfermode::kDstOut_Mode || + xfermode == SkXfermode::kSrcATop_Mode || + xfermode == SkXfermode::kDstATop_Mode || + xfermode == SkXfermode::kModulate_Mode); - if (blendMode == SkBlendMode::kSrcIn || - blendMode == SkBlendMode::kSrcOut || - blendMode == SkBlendMode::kSrcATop) { + if (xfermode == SkXfermode::kSrcIn_Mode || + xfermode == SkXfermode::kSrcOut_Mode || + xfermode == SkXfermode::kSrcATop_Mode) { drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), std::move(dst), &fExistingClipStack, fExistingClipRegion, - SkBlendMode::kSrcOver, - blendMode == SkBlendMode::kSrcOut); + SkXfermode::kSrcOver_Mode, + xfermode == SkXfermode::kSrcOut_Mode); return; } else { - SkBlendMode mode = SkBlendMode::kSrcOver; + SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode; int resourceID = addXObjectResource(dst.get()); - if (blendMode == SkBlendMode::kModulate) { + if (xfermode == SkXfermode::kModulate_Mode) { drawFormXObjectWithMask(addXObjectResource(srcFormXObject.get()), std::move(dst), &fExistingClipStack, fExistingClipRegion, - SkBlendMode::kSrcOver, false); - mode = SkBlendMode::kMultiply; + SkXfermode::kSrcOver_Mode, false); + mode = SkXfermode::kMultiply_Mode; } drawFormXObjectWithMask(resourceID, std::move(srcFormXObject), &fExistingClipStack, fExistingClipRegion, mode, - blendMode == SkBlendMode::kDstOut); + xfermode == SkXfermode::kDstOut_Mode); return; } } diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h index 7d207e7cf9..be0a277ff5 100644 --- a/src/pdf/SkPDFDevice.h +++ b/src/pdf/SkPDFDevice.h @@ -246,7 +246,7 @@ private: sk_sp<SkPDFObject> mask, const SkClipStack* clipStack, const SkRegion& clipRegion, - SkBlendMode, + SkXfermode::Mode mode, bool invertClip); // If the paint or clip is such that we shouldn't draw anything, this @@ -259,7 +259,9 @@ private: const SkPaint& paint, bool hasText, sk_sp<SkPDFObject>* dst); - void finishContentEntry(SkBlendMode, sk_sp<SkPDFObject> dst, SkPath* shape); + void finishContentEntry(SkXfermode::Mode xfermode, + sk_sp<SkPDFObject> dst, + SkPath* shape); bool isContentEmpty(); void populateGraphicStateEntryFromPaint(const SkMatrix& matrix, diff --git a/src/pdf/SkPDFGraphicState.cpp b/src/pdf/SkPDFGraphicState.cpp index d60526c11a..a78c4c51b5 100644 --- a/src/pdf/SkPDFGraphicState.cpp +++ b/src/pdf/SkPDFGraphicState.cpp @@ -12,58 +12,58 @@ #include "SkPDFGraphicState.h" #include "SkPDFUtils.h" -static const char* as_blend_mode(SkBlendMode mode) { +static const char* as_blend_mode(SkXfermode::Mode mode) { switch (mode) { - case SkBlendMode::kSrcOver: + case SkXfermode::kSrcOver_Mode: return "Normal"; - case SkBlendMode::kMultiply: + case SkXfermode::kMultiply_Mode: return "Multiply"; - case SkBlendMode::kScreen: + case SkXfermode::kScreen_Mode: return "Screen"; - case SkBlendMode::kOverlay: + case SkXfermode::kOverlay_Mode: return "Overlay"; - case SkBlendMode::kDarken: + case SkXfermode::kDarken_Mode: return "Darken"; - case SkBlendMode::kLighten: + case SkXfermode::kLighten_Mode: return "Lighten"; - case SkBlendMode::kColorDodge: + case SkXfermode::kColorDodge_Mode: return "ColorDodge"; - case SkBlendMode::kColorBurn: + case SkXfermode::kColorBurn_Mode: return "ColorBurn"; - case SkBlendMode::kHardLight: + case SkXfermode::kHardLight_Mode: return "HardLight"; - case SkBlendMode::kSoftLight: + case SkXfermode::kSoftLight_Mode: return "SoftLight"; - case SkBlendMode::kDifference: + case SkXfermode::kDifference_Mode: return "Difference"; - case SkBlendMode::kExclusion: + case SkXfermode::kExclusion_Mode: return "Exclusion"; - case SkBlendMode::kHue: + case SkXfermode::kHue_Mode: return "Hue"; - case SkBlendMode::kSaturation: + case SkXfermode::kSaturation_Mode: return "Saturation"; - case SkBlendMode::kColor: + case SkXfermode::kColor_Mode: return "Color"; - case SkBlendMode::kLuminosity: + case SkXfermode::kLuminosity_Mode: return "Luminosity"; // These are handled in SkPDFDevice::setUpContentEntry. - case SkBlendMode::kClear: - case SkBlendMode::kSrc: - case SkBlendMode::kDst: - case SkBlendMode::kDstOver: - case SkBlendMode::kSrcIn: - case SkBlendMode::kDstIn: - case SkBlendMode::kSrcOut: - case SkBlendMode::kDstOut: - case SkBlendMode::kSrcATop: - case SkBlendMode::kDstATop: - case SkBlendMode::kModulate: + case SkXfermode::kClear_Mode: + case SkXfermode::kSrc_Mode: + case SkXfermode::kDst_Mode: + case SkXfermode::kDstOver_Mode: + case SkXfermode::kSrcIn_Mode: + case SkXfermode::kDstIn_Mode: + case SkXfermode::kSrcOut_Mode: + case SkXfermode::kDstOut_Mode: + case SkXfermode::kSrcATop_Mode: + case SkXfermode::kDstATop_Mode: + case SkXfermode::kModulate_Mode: return "Normal"; // TODO(vandebo): Figure out if we can support more of these modes. - case SkBlendMode::kXor: - case SkBlendMode::kPlus: + case SkXfermode::kXor_Mode: + case SkXfermode::kPlus_Mode: return nullptr; } return nullptr; @@ -71,28 +71,32 @@ static const char* as_blend_mode(SkBlendMode mode) { // If a SkXfermode is unsupported in PDF, this function returns // SrcOver, otherwise, it returns that Xfermode as a Mode. -static SkBlendMode mode_for_pdf(SkBlendMode mode) { +static SkXfermode::Mode mode_for_pdf(const SkXfermode* xfermode) { + SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode; + if (xfermode) { + xfermode->asMode(&mode); + } switch (mode) { - case SkBlendMode::kSrcOver: - case SkBlendMode::kMultiply: - case SkBlendMode::kScreen: - case SkBlendMode::kOverlay: - case SkBlendMode::kDarken: - case SkBlendMode::kLighten: - case SkBlendMode::kColorDodge: - case SkBlendMode::kColorBurn: - case SkBlendMode::kHardLight: - case SkBlendMode::kSoftLight: - case SkBlendMode::kDifference: - case SkBlendMode::kExclusion: - case SkBlendMode::kHue: - case SkBlendMode::kSaturation: - case SkBlendMode::kColor: - case SkBlendMode::kLuminosity: + case SkXfermode::kSrcOver_Mode: + case SkXfermode::kMultiply_Mode: + case SkXfermode::kScreen_Mode: + case SkXfermode::kOverlay_Mode: + case SkXfermode::kDarken_Mode: + case SkXfermode::kLighten_Mode: + case SkXfermode::kColorDodge_Mode: + case SkXfermode::kColorBurn_Mode: + case SkXfermode::kHardLight_Mode: + case SkXfermode::kSoftLight_Mode: + case SkXfermode::kDifference_Mode: + case SkXfermode::kExclusion_Mode: + case SkXfermode::kHue_Mode: + case SkXfermode::kSaturation_Mode: + case SkXfermode::kColor_Mode: + case SkXfermode::kLuminosity_Mode: // Mode is suppported and handled by pdf graphics state. return mode; default: - return SkBlendMode::kSrcOver; // Default mode. + return SkXfermode::kSrcOver_Mode; // Default mode. } } @@ -102,7 +106,7 @@ SkPDFGraphicState::SkPDFGraphicState(const SkPaint& p) , fAlpha(p.getAlpha()) , fStrokeCap(SkToU8(p.getStrokeCap())) , fStrokeJoin(SkToU8(p.getStrokeJoin())) - , fMode(SkToU8((unsigned)mode_for_pdf(p.getBlendMode()))) {} + , fMode(SkToU8(mode_for_pdf(p.getXfermode()))) {} // static SkPDFGraphicState* SkPDFGraphicState::GetGraphicStateForPaint( @@ -182,6 +186,7 @@ void SkPDFGraphicState::emitObject( SkPaint::Cap strokeCap = (SkPaint::Cap)fStrokeCap; SkPaint::Join strokeJoin = (SkPaint::Join)fStrokeJoin; + SkXfermode::Mode xferMode = (SkXfermode::Mode)fMode; static_assert(SkPaint::kButt_Cap == 0, "paint_cap_mismatch"); static_assert(SkPaint::kRound_Cap == 1, "paint_cap_mismatch"); @@ -200,6 +205,6 @@ void SkPDFGraphicState::emitObject( dict->insertScalar("LW", fStrokeWidth); dict->insertScalar("ML", fStrokeMiter); dict->insertBool("SA", true); // SA = Auto stroke adjustment. - dict->insertName("BM", as_blend_mode((SkBlendMode)fMode)); + dict->insertName("BM", as_blend_mode(xferMode)); dict->emitObject(stream, objNumMap); } diff --git a/src/pdf/SkPDFGraphicState.h b/src/pdf/SkPDFGraphicState.h index 8ee6728f56..0c2e4a0f49 100644 --- a/src/pdf/SkPDFGraphicState.h +++ b/src/pdf/SkPDFGraphicState.h @@ -70,7 +70,7 @@ private: const uint8_t fAlpha; const uint8_t fStrokeCap; // SkPaint::Cap const uint8_t fStrokeJoin; // SkPaint::Join - const uint8_t fMode; // SkBlendMode + const uint8_t fMode; // SkXfermode::Mode SkPDFGraphicState(const SkPaint&); diff --git a/src/pipe/SkPipeCanvas.cpp b/src/pipe/SkPipeCanvas.cpp index 3b636a23c0..a01237fbbb 100644 --- a/src/pipe/SkPipeCanvas.cpp +++ b/src/pipe/SkPipeCanvas.cpp @@ -81,6 +81,7 @@ static uint16_t compute_nondef(const SkPaint& paint, PaintUsage usage) { bits |= (paint.getMaskFilter() ? kMaskFilter_NonDef : 0); } + bits |= (paint.getXfermode() ? kXfermode_NonDef : 0); bits |= (paint.getColorFilter() ? kColorFilter_NonDef : 0); bits |= (paint.getImageFilter() ? kImageFilter_NonDef : 0); bits |= (paint.getDrawLooper() ? kDrawLooper_NonDef : 0); @@ -149,8 +150,15 @@ static void write_paint(SkWriteBuffer& writer, const SkPaint& paint, unsigned us writer.write32(packedFlags); unsigned nondef = compute_nondef(paint, (PaintUsage)usage); + SkXfermode::Mode mode; + if (SkXfermode::AsMode(paint.getXfermode(), &mode)) { + nondef &= ~kXfermode_NonDef; // don't need to store a pointer since we have an enum + } else { + SkASSERT(nondef & kXfermode_NonDef); + mode = (SkXfermode::Mode)0; + } const uint8_t pad = 0; - writer.write32((nondef << 16) | ((unsigned)paint.getBlendMode() << 8) | pad); + writer.write32((nondef << 16) | ((unsigned)mode << 8) | pad); CHECK_WRITE_SCALAR(writer, nondef, paint, TextSize); CHECK_WRITE_SCALAR(writer, nondef, paint, TextScaleX); @@ -171,6 +179,7 @@ static void write_paint(SkWriteBuffer& writer, const SkPaint& paint, unsigned us CHECK_WRITE_FLATTENABLE(writer, nondef, paint, PathEffect); CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Shader); + CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Xfermode); CHECK_WRITE_FLATTENABLE(writer, nondef, paint, MaskFilter); CHECK_WRITE_FLATTENABLE(writer, nondef, paint, ColorFilter); CHECK_WRITE_FLATTENABLE(writer, nondef, paint, Rasterizer); diff --git a/src/pipe/SkPipeFormat.h b/src/pipe/SkPipeFormat.h index 9a1d30c7be..8f5c8282e4 100644 --- a/src/pipe/SkPipeFormat.h +++ b/src/pipe/SkPipeFormat.h @@ -94,11 +94,12 @@ enum { kTypeface_NonDef = 1 << 6, kPathEffect_NonDef = 1 << 7, kShader_NonDef = 1 << 8, - kMaskFilter_NonDef = 1 << 9, - kColorFilter_NonDef = 1 << 10, - kRasterizer_NonDef = 1 << 11, - kImageFilter_NonDef = 1 << 12, - kDrawLooper_NonDef = 1 << 13, + kXfermode_NonDef = 1 << 9, + kMaskFilter_NonDef = 1 << 10, + kColorFilter_NonDef = 1 << 11, + kRasterizer_NonDef = 1 << 12, + kImageFilter_NonDef = 1 << 13, + kDrawLooper_NonDef = 1 << 14, }; enum { diff --git a/src/pipe/SkPipeReader.cpp b/src/pipe/SkPipeReader.cpp index 47d4072d06..8840da1c83 100644 --- a/src/pipe/SkPipeReader.cpp +++ b/src/pipe/SkPipeReader.cpp @@ -149,13 +149,13 @@ static SkMatrix read_sparse_matrix(SkReadBuffer& reader, SkMatrix::TypeMask tm) * pad zeros : 8 */ static SkPaint read_paint(SkReadBuffer& reader) { - SkPaint paint; - uint32_t packedFlags = reader.read32(); uint32_t extra = reader.read32(); unsigned nondef = extra >> 16; - paint.setBlendMode(SkBlendMode((extra >> 8) & 0xFF)); - SkASSERT((extra & 0xFF) == 0); // zero pad byte + SkXfermode::Mode mode = (SkXfermode::Mode)((extra >> 8) & 0xFF); + SkASSERT((extra & 0xFF) == 0); + + SkPaint paint; packedFlags >>= 2; // currently unused paint.setTextEncoding((SkPaint::TextEncoding)(packedFlags & 3)); packedFlags >>= 2; @@ -180,12 +180,17 @@ static SkPaint read_paint(SkReadBuffer& reader) { CHECK_SET_FLATTENABLE(Typeface); CHECK_SET_FLATTENABLE(PathEffect); CHECK_SET_FLATTENABLE(Shader); + CHECK_SET_FLATTENABLE(Xfermode); CHECK_SET_FLATTENABLE(MaskFilter); CHECK_SET_FLATTENABLE(ColorFilter); CHECK_SET_FLATTENABLE(Rasterizer); CHECK_SET_FLATTENABLE(ImageFilter); CHECK_SET_FLATTENABLE(DrawLooper); + if (!(nondef & kXfermode_NonDef)) { + paint.setXfermodeMode(mode); + } + return paint; } diff --git a/src/utils/SkDumpCanvas.cpp b/src/utils/SkDumpCanvas.cpp index 68bd13eccb..fcb24d28c4 100644 --- a/src/utils/SkDumpCanvas.cpp +++ b/src/utils/SkDumpCanvas.cpp @@ -209,8 +209,8 @@ SkCanvas::SaveLayerStrategy SkDumpCanvas::getSaveLayerStrategy(const SaveLayerRe if (paint->getAlpha() != 0xFF) { str.appendf(" alpha:0x%02X", paint->getAlpha()); } - if (!paint->isSrcOver()) { - str.appendf(" blendmode:%d", paint->getBlendMode()); + if (paint->getXfermode()) { + str.appendf(" xfermode:%p", paint->getXfermode()); } } this->dump(kSave_Verb, paint, str.c_str()); @@ -540,10 +540,8 @@ void SkFormatDumper::dump(SkDumpCanvas* canvas, SkDumpCanvas::Verb verb, if (p) { msg.appendf(" color:0x%08X flags:%X", p->getColor(), p->getFlags()); - if (!p->isSrcOver()) { - msg.appendf(" blendmode:%d", p->getBlendMode()); - } appendFlattenable(&msg, p->getShader(), "shader"); + appendFlattenable(&msg, p->getXfermode(), "xfermode"); appendFlattenable(&msg, p->getPathEffect(), "pathEffect"); appendFlattenable(&msg, p->getMaskFilter(), "maskFilter"); appendFlattenable(&msg, p->getPathEffect(), "pathEffect"); diff --git a/src/utils/SkLua.cpp b/src/utils/SkLua.cpp index ba311af61c..e80708c71c 100644 --- a/src/utils/SkLua.cpp +++ b/src/utils/SkLua.cpp @@ -28,6 +28,7 @@ #include "SkSurface.h" #include "SkTextBlob.h" #include "SkTypeface.h" +#include "SkXfermode.h" extern "C" { #include "lua.h" @@ -58,6 +59,7 @@ DEF_MTNAME(SkShader) DEF_MTNAME(SkSurface) DEF_MTNAME(SkTextBlob) DEF_MTNAME(SkTypeface) +DEF_MTNAME(SkXfermode) template <typename T> T* push_new(lua_State* L) { T* addr = (T*)lua_newuserdata(L, sizeof(T)); @@ -1071,9 +1073,26 @@ static int lpaint_getEffects(lua_State* L) { setfield_bool_if(L, "shader", !!paint->getShader()); setfield_bool_if(L, "colorFilter", !!paint->getColorFilter()); setfield_bool_if(L, "imageFilter", !!paint->getImageFilter()); + setfield_bool_if(L, "xfermode", !!paint->getXfermode()); return 1; } +static int lpaint_getXfermode(lua_State* L) { + const SkPaint* paint = get_obj<SkPaint>(L, 1); + SkXfermode* xfermode = paint->getXfermode(); + if (xfermode) { + push_ref(L, xfermode); + return 1; + } + return 0; +} + +static int lpaint_setXfermode(lua_State* L) { + SkPaint* paint = get_obj<SkPaint>(L, 1); + paint->setXfermode(sk_ref_sp(get_ref<SkXfermode>(L, 2))); + return 0; +} + static int lpaint_getColorFilter(lua_State* L) { const SkPaint* paint = get_obj<SkPaint>(L, 1); SkColorFilter* cf = paint->getColorFilter(); @@ -1198,6 +1217,8 @@ static const struct luaL_Reg gSkPaint_Methods[] = { { "setColorFilter", lpaint_setColorFilter }, { "getImageFilter", lpaint_getImageFilter }, { "setImageFilter", lpaint_setImageFilter }, + { "getXfermode", lpaint_getXfermode }, + { "setXfermode", lpaint_setXfermode }, { "getShader", lpaint_getShader }, { "setShader", lpaint_setShader }, { "getPathEffect", lpaint_getPathEffect }, @@ -1320,6 +1341,24 @@ static const struct luaL_Reg gSkPathEffect_Methods[] = { /////////////////////////////////////////////////////////////////////////////// +static int lpxfermode_getTypeName(lua_State* L) { + lua_pushstring(L, get_ref<SkXfermode>(L, 1)->getTypeName()); + return 1; +} + +static int lpxfermode_gc(lua_State* L) { + get_ref<SkXfermode>(L, 1)->unref(); + return 0; +} + +static const struct luaL_Reg gSkXfermode_Methods[] = { + { "getTypeName", lpxfermode_getTypeName }, + { "__gc", lpxfermode_gc }, + { nullptr, nullptr } +}; + +/////////////////////////////////////////////////////////////////////////////// + static int lpcolorfilter_gc(lua_State* L) { get_ref<SkColorFilter>(L, 1)->unref(); return 0; @@ -2139,6 +2178,7 @@ void SkLua::Load(lua_State* L) { REG_CLASS(L, SkSurface); REG_CLASS(L, SkTextBlob); REG_CLASS(L, SkTypeface); + REG_CLASS(L, SkXfermode); } extern "C" int luaopen_skia(lua_State* L); diff --git a/src/utils/SkRGBAToYUV.cpp b/src/utils/SkRGBAToYUV.cpp index 0528b144f0..63d9152362 100644 --- a/src/utils/SkRGBAToYUV.cpp +++ b/src/utils/SkRGBAToYUV.cpp @@ -45,7 +45,7 @@ bool SkRGBAToYUV(const SkImage* image, const SkISize sizes[3], void* const plane } SkPaint paint; paint.setFilterQuality(kLow_SkFilterQuality); - paint.setBlendMode(SkBlendMode::kSrc); + paint.setXfermodeMode(SkXfermode::kSrc_Mode); int rowStartIdx = 5 * i; const SkScalar* row = kYUVColorSpaceInvMatrices[colorSpace] + rowStartIdx; paint.setColorFilter( diff --git a/src/xps/SkXPSDevice.cpp b/src/xps/SkXPSDevice.cpp index 5db644c30a..7757cb8774 100644 --- a/src/xps/SkXPSDevice.cpp +++ b/src/xps/SkXPSDevice.cpp @@ -1220,7 +1220,7 @@ void SkXPSDevice::internalDrawRect(const SkDraw& d, const SkPaint& paint) { //Exit early if there is nothing to draw. if (d.fRC->isEmpty() || - (paint.getAlpha() == 0 && paint.isSrcOver())) { + (paint.getAlpha() == 0 && paint.getXfermode() == nullptr)) { return; } @@ -1536,7 +1536,7 @@ void SkXPSDevice::drawPath(const SkDraw& d, // nothing to draw if (d.fRC->isEmpty() || - (paint->getAlpha() == 0 && paint->isSrcOver())) { + (paint->getAlpha() == 0 && paint->getXfermode() == nullptr)) { return; } |