Revert "replace Arithmetic xfermode with imagefilter"
This reverts commit Ia3f3b721854c516f3b7f8c44f71f40a8a2eeb9b4. Reason for revert: need to guard the no-gpu codepath Original issue's description: > replace Arithmetic xfermode with imagefilter > > chrome pre-cl: https://codereview.chromium.org/2369023002/ > > BUG=skia: > > GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2595 > > Change-Id: Ia3f3b721854c516f3b7f8c44f71f40a8a2eeb9b4 > Reviewed-on: https://skia-review.googlesource.com/2595 > Commit-Queue: Mike Reed <reed@google.com> > Reviewed-by: Florin Malita <fmalita@chromium.org> > Reviewed-by: Robert Phillips <robertphillips@google.com> > TBR=robertphillips@google.com,fmalita@chromium.org,fmalita@google.com,reed@google.com NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true Change-Id: I761799b594a0379c6bf356e6abc73552c3d19480 Reviewed-on: https://skia-review.googlesource.com/2661 Reviewed-by: Florin Malita <fmalita@chromium.org> Commit-Queue: Florin Malita <fmalita@chromium.org>
This commit is contained in:
parent
29111a3e71
commit
10ff5bfa78
@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "Benchmark.h"
|
||||
#include "SkArithmeticMode.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkPaint.h"
|
||||
#include "SkRandom.h"
|
||||
@ -22,6 +23,12 @@ public:
|
||||
fName.printf("Xfermode_%s%s", SkXfermode::ModeName(mode), aa ? "_aa" : "");
|
||||
}
|
||||
|
||||
XfermodeBench(sk_sp<SkXfermode> xferMode, const char* name, bool aa) {
|
||||
fXfermode = xferMode;
|
||||
fAA = aa;
|
||||
fName.printf("Xfermode_%s%s", name, aa ? "_aa" : "");
|
||||
}
|
||||
|
||||
protected:
|
||||
const char* onGetName() override { return fName.c_str(); }
|
||||
|
||||
@ -128,4 +135,13 @@ BENCH(SkXfermode::kSaturation_Mode)
|
||||
BENCH(SkXfermode::kColor_Mode)
|
||||
BENCH(SkXfermode::kLuminosity_Mode)
|
||||
|
||||
DEF_BENCH( return new XfermodeBench(SkArithmeticMode::Make(0.2f, -0.3f, 1.5f, -0.7f, false), \
|
||||
"arithmetic", false); )
|
||||
DEF_BENCH( return new XfermodeBench(SkArithmeticMode::Make(0.2f, -0.3f, 1.5f, -0.7f, true), \
|
||||
"arithmetic_enforce_pm", false); )
|
||||
DEF_BENCH( return new XfermodeBench(SkArithmeticMode::Make(0.2f, -0.3f, 1.5f, -0.7f, false), \
|
||||
"arithmetic", true); )
|
||||
DEF_BENCH( return new XfermodeBench(SkArithmeticMode::Make(0.2f, -0.3f, 1.5f, -0.7f, true), \
|
||||
"arithmetic_enforce_pm", true); )
|
||||
|
||||
DEF_BENCH(return new XferCreateBench;)
|
||||
|
@ -39,11 +39,13 @@ enum Shape {
|
||||
kLast_Shape = kConcave_Shape
|
||||
};
|
||||
|
||||
namespace skiagm {
|
||||
|
||||
/**
|
||||
* Verifies AA works properly on all Xfermodes, including arithmetic, with both opaque and unknown
|
||||
* src colors.
|
||||
*/
|
||||
class AAXfermodesGM : public skiagm::GM {
|
||||
class AAXfermodesGM : public GM {
|
||||
public:
|
||||
AAXfermodesGM() {}
|
||||
|
||||
@ -118,9 +120,6 @@ protected:
|
||||
canvas->translate(0, kSubtitleSpacing + kShapeSpacing/2);
|
||||
|
||||
for (size_t m = 0; m <= SkXfermode::kLastCoeffMode; m++) {
|
||||
if (firstMode + m > SkXfermode::kLastMode) {
|
||||
break;
|
||||
}
|
||||
SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(firstMode + m);
|
||||
canvas->save();
|
||||
|
||||
@ -211,7 +210,7 @@ protected:
|
||||
if (maxSum > 255) {
|
||||
SkPaint dimPaint;
|
||||
dimPaint.setAntiAlias(false);
|
||||
dimPaint.setXfermodeMode(SkXfermode::kDstIn_Mode);
|
||||
dimPaint.setXfermode(SkXfermode::Make(SkXfermode::kDstIn_Mode));
|
||||
if (255 != paint->getAlpha()) {
|
||||
// Dim the src and dst colors.
|
||||
dimPaint.setARGB(255 * 255 / maxSum, 0, 0, 0);
|
||||
@ -228,10 +227,16 @@ protected:
|
||||
}
|
||||
|
||||
void drawShape(SkCanvas* canvas, Shape shape, const SkPaint& paint, SkXfermode::Mode mode) {
|
||||
SkASSERT(mode <= SkXfermode::kLastMode);
|
||||
SkPaint shapePaint(paint);
|
||||
shapePaint.setAntiAlias(kSquare_Shape != shape);
|
||||
shapePaint.setXfermodeMode(mode);
|
||||
|
||||
sk_sp<SkXfermode> xfermode;
|
||||
if (mode <= SkXfermode::kLastMode) {
|
||||
xfermode = SkXfermode::Make(mode);
|
||||
} else {
|
||||
xfermode = SkArithmeticMode::Make(+1.0f, +0.25f, -0.5f, +0.1f);
|
||||
}
|
||||
shapePaint.setXfermode(std::move(xfermode));
|
||||
|
||||
switch (shape) {
|
||||
case kSquare_Shape:
|
||||
@ -268,6 +273,12 @@ private:
|
||||
SkPath fOval;
|
||||
SkPath fConcave;
|
||||
|
||||
typedef skiagm::GM INHERITED;
|
||||
typedef GM INHERITED;
|
||||
};
|
||||
DEF_GM( return new AAXfermodesGM; )
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static GM* MyFactory(void*) { return new AAXfermodesGM; }
|
||||
static GMRegistry reg(MyFactory);
|
||||
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
#define WW 100
|
||||
#define HH 32
|
||||
|
||||
#ifdef SK_SUPPORT_LEGACY_ARITHMETICMODE
|
||||
static SkBitmap make_bm() {
|
||||
SkBitmap bm;
|
||||
bm.allocN32Pixels(WW, HH);
|
||||
@ -161,4 +160,3 @@ private:
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DEF_GM( return new ArithmodeGM; )
|
||||
#endif
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "gm.h"
|
||||
|
||||
#include "SkArithmeticMode.h"
|
||||
#include "SkBlurImageFilter.h"
|
||||
#include "SkColorFilter.h"
|
||||
#include "SkColorFilterImageFilter.h"
|
||||
@ -89,7 +90,7 @@ protected:
|
||||
|
||||
SkPaint paint;
|
||||
paint.setImageFilter(
|
||||
SkXfermodeImageFilter::MakeArithmetic(0, 1, 1, 0, true,
|
||||
SkXfermodeImageFilter::Make(SkArithmeticMode::Make(0, SK_Scalar1, SK_Scalar1, 0),
|
||||
std::move(matrixFilter),
|
||||
std::move(offsetFilter),
|
||||
nullptr));
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "gm.h"
|
||||
#include "sk_tool_utils.h"
|
||||
#include "SkArithmeticMode.h"
|
||||
#include "SkImage.h"
|
||||
#include "SkImageSource.h"
|
||||
#include "SkOffsetImageFilter.h"
|
||||
@ -96,7 +97,9 @@ protected:
|
||||
}
|
||||
}
|
||||
// Test arithmetic mode as image filter
|
||||
paint.setImageFilter(SkXfermodeImageFilter::MakeArithmetic(0, 1, 1, 0, true, background));
|
||||
paint.setImageFilter(SkXfermodeImageFilter::Make(
|
||||
SkArithmeticMode::Make(0, SK_Scalar1, SK_Scalar1, 0),
|
||||
background));
|
||||
DrawClippedBitmap(canvas, fBitmap, paint, x, y);
|
||||
x += fBitmap.width() + MARGIN;
|
||||
if (x + fBitmap.width() > WIDTH) {
|
||||
|
@ -11,6 +11,31 @@
|
||||
#include "SkXfermode.h"
|
||||
#include "SkPM4f.h"
|
||||
|
||||
#include "SkArithmeticMode.h"
|
||||
|
||||
#define kCustomShift 16
|
||||
#define kCustomMask (~0xFFFF)
|
||||
|
||||
enum CustomModes {
|
||||
kArithmetic_CustomMode = 1 << kCustomShift,
|
||||
};
|
||||
|
||||
static sk_sp<SkXfermode> make_custom(int customMode) {
|
||||
switch (customMode) {
|
||||
case kArithmetic_CustomMode: {
|
||||
const SkScalar k1 = 0.25;
|
||||
const SkScalar k2 = 0.75;
|
||||
const SkScalar k3 = 0.75;
|
||||
const SkScalar k4 = -0.25;
|
||||
return SkArithmeticMode::Make(k1, k2, k3, k4);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
SkASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
enum SrcType {
|
||||
//! A WxH image with a rectangle in the lower right.
|
||||
kRectangleImage_SrcType = 0x01,
|
||||
@ -73,6 +98,8 @@ const struct {
|
||||
{ SkXfermode::kSaturation_Mode, "Saturation", kBasic_SrcType },
|
||||
{ SkXfermode::kColor_Mode, "Color", kBasic_SrcType },
|
||||
{ SkXfermode::kLuminosity_Mode, "Luminosity", kBasic_SrcType },
|
||||
|
||||
{ SkXfermode::Mode(0xFFFF), "Arithmetic", kBasic_SrcType + kArithmetic_CustomMode },
|
||||
};
|
||||
|
||||
static void make_bitmaps(int w, int h, SkBitmap* src, SkBitmap* dst,
|
||||
@ -118,7 +145,7 @@ class XfermodesGM : public skiagm::GM {
|
||||
* uses the implied shape of the drawing command and these modes
|
||||
* demonstrate that.
|
||||
*/
|
||||
void draw_mode(SkCanvas* canvas, SkXfermode::Mode mode, SrcType srcType,
|
||||
void draw_mode(SkCanvas* canvas, sk_sp<SkXfermode> mode, SrcType srcType,
|
||||
SkScalar x, SkScalar y) {
|
||||
SkPaint p;
|
||||
SkMatrix m;
|
||||
@ -126,7 +153,7 @@ class XfermodesGM : public skiagm::GM {
|
||||
m.setTranslate(x, y);
|
||||
|
||||
canvas->drawBitmap(fSrcB, x, y, &p);
|
||||
p.setXfermodeMode(mode);
|
||||
p.setXfermode(std::move(mode));
|
||||
switch (srcType) {
|
||||
case kSmallTransparentImage_SrcType: {
|
||||
m.postScale(SK_ScalarHalf, SK_ScalarHalf, x, y);
|
||||
@ -214,7 +241,7 @@ protected:
|
||||
}
|
||||
|
||||
SkISize onISize() override {
|
||||
return SkISize::Make(1990, 570);
|
||||
return SkISize::Make(1990, 660);
|
||||
}
|
||||
|
||||
void onDraw(SkCanvas* canvas) override {
|
||||
@ -242,7 +269,14 @@ protected:
|
||||
if ((gModes[i].fSourceTypeMask & sourceType) == 0) {
|
||||
continue;
|
||||
}
|
||||
SkRect r{ x, y, x+w, y+h };
|
||||
sk_sp<SkXfermode> mode;
|
||||
if (gModes[i].fSourceTypeMask & kCustomMask) {
|
||||
mode = make_custom(gModes[i].fSourceTypeMask & kCustomMask);
|
||||
} else {
|
||||
mode = SkXfermode::Make(gModes[i].fMode);
|
||||
}
|
||||
SkRect r;
|
||||
r.set(x, y, x+w, y+h);
|
||||
|
||||
SkPaint p;
|
||||
p.setStyle(SkPaint::kFill_Style);
|
||||
@ -250,7 +284,7 @@ protected:
|
||||
canvas->drawRect(r, p);
|
||||
|
||||
canvas->saveLayer(&r, nullptr);
|
||||
draw_mode(canvas, gModes[i].fMode, static_cast<SrcType>(sourceType),
|
||||
draw_mode(canvas, std::move(mode), static_cast<SrcType>(sourceType),
|
||||
r.fLeft, r.fTop);
|
||||
canvas->restore();
|
||||
|
||||
|
@ -12,8 +12,6 @@
|
||||
#include "SkScalar.h"
|
||||
#include "SkXfermode.h"
|
||||
|
||||
#ifdef SK_SUPPORT_LEGACY_ARITHMETICMODE
|
||||
|
||||
class SK_API SkArithmeticMode {
|
||||
public:
|
||||
/**
|
||||
@ -40,5 +38,3 @@ private:
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -26,18 +26,6 @@ public:
|
||||
return Make(std::move(mode), std::move(background), nullptr, nullptr);
|
||||
}
|
||||
|
||||
static sk_sp<SkImageFilter> MakeArithmetic(float k1, float k2, float k3, float k4,
|
||||
bool enforcePMColor,
|
||||
sk_sp<SkImageFilter> background,
|
||||
sk_sp<SkImageFilter> foreground,
|
||||
const SkImageFilter::CropRect* cropRect);
|
||||
static sk_sp<SkImageFilter> MakeArithmetic(float k1, float k2, float k3, float k4,
|
||||
bool enforcePMColor,
|
||||
sk_sp<SkImageFilter> background) {
|
||||
return MakeArithmetic(k1, k2, k3, k4, enforcePMColor, std::move(background),
|
||||
nullptr, nullptr);
|
||||
}
|
||||
|
||||
#ifdef SK_SUPPORT_LEGACY_XFERMODE_PTR
|
||||
static SkImageFilter* Create(SkXfermode* mode, SkImageFilter* background,
|
||||
SkImageFilter* foreground = NULL,
|
||||
|
@ -5,7 +5,7 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkArithmeticModePriv.h"
|
||||
#include "SkArithmeticMode.h"
|
||||
#include "SkColorPriv.h"
|
||||
#include "SkNx.h"
|
||||
#include "SkRasterPipeline.h"
|
||||
|
@ -1,42 +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 SkArithmeticModePriv_DEFINED
|
||||
#define SkArithmeticModePriv_DEFINED
|
||||
|
||||
#include "SkArithmeticMode.h"
|
||||
|
||||
#ifndef SK_SUPPORT_LEGACY_ARITHMETICMODE
|
||||
|
||||
class SK_API SkArithmeticMode {
|
||||
public:
|
||||
/**
|
||||
* result = clamp[k1 * src * dst + k2 * src + k3 * dst + k4]
|
||||
*
|
||||
* k1=k2=k3=0, k4=1.0 results in returning opaque white
|
||||
* k1=k3=k4=0, k2=1.0 results in returning the src
|
||||
* k1=k2=k4=0, k3=1.0 results in returning the dst
|
||||
*/
|
||||
static sk_sp<SkXfermode> Make(SkScalar k1, SkScalar k2, SkScalar k3, SkScalar k4,
|
||||
bool enforcePMColor = true);
|
||||
#ifdef SK_SUPPORT_LEGACY_XFERMODE_PTR
|
||||
static SkXfermode* Create(SkScalar k1, SkScalar k2,
|
||||
SkScalar k3, SkScalar k4,
|
||||
bool enforcePMColor = true) {
|
||||
return Make(k1, k2, k3, k4, enforcePMColor).release();
|
||||
}
|
||||
#endif
|
||||
|
||||
SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP();
|
||||
|
||||
private:
|
||||
SkArithmeticMode(); // can't be instantiated
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -20,12 +20,11 @@
|
||||
#include "effects/GrConstColorProcessor.h"
|
||||
#include "effects/GrTextureDomain.h"
|
||||
#include "effects/GrSimpleTextureEffect.h"
|
||||
#include "SkArithmeticMode_gpu.h"
|
||||
#include "SkGr.h"
|
||||
#include "SkGrPriv.h"
|
||||
#endif
|
||||
|
||||
class SkXfermodeImageFilter_Base : public SkImageFilter {
|
||||
class SK_API SkXfermodeImageFilter_Base : public SkImageFilter {
|
||||
public:
|
||||
SkXfermodeImageFilter_Base(sk_sp<SkXfermode> mode, sk_sp<SkImageFilter> inputs[2],
|
||||
const CropRect* cropRect);
|
||||
@ -49,8 +48,6 @@ protected:
|
||||
|
||||
void flatten(SkWriteBuffer&) const override;
|
||||
|
||||
virtual void drawForeground(SkCanvas* canvas, SkSpecialImage*, const SkIRect&) const;
|
||||
virtual sk_sp<GrFragmentProcessor> makeFGFrag(sk_sp<GrFragmentProcessor> bgFP) const;
|
||||
|
||||
private:
|
||||
sk_sp<SkXfermode> fMode;
|
||||
@ -141,35 +138,33 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::onFilterImage(SkSpecialImage*
|
||||
SkASSERT(canvas);
|
||||
|
||||
canvas->clear(0x0); // can't count on background to fully clear the background
|
||||
|
||||
canvas->translate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
|
||||
|
||||
if (background) {
|
||||
SkPaint paint;
|
||||
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
|
||||
|
||||
if (background) {
|
||||
background->draw(canvas,
|
||||
SkIntToScalar(backgroundOffset.fX), SkIntToScalar(backgroundOffset.fY),
|
||||
&paint);
|
||||
}
|
||||
|
||||
this->drawForeground(canvas, foreground.get(), foregroundBounds);
|
||||
paint.setXfermode(fMode);
|
||||
|
||||
if (foreground) {
|
||||
foreground->draw(canvas,
|
||||
SkIntToScalar(foregroundOffset.fX), SkIntToScalar(foregroundOffset.fY),
|
||||
&paint);
|
||||
}
|
||||
|
||||
canvas->clipRect(SkRect::Make(foregroundBounds), SkCanvas::kDifference_Op);
|
||||
paint.setColor(SK_ColorTRANSPARENT);
|
||||
canvas->drawPaint(paint);
|
||||
|
||||
return surf->makeImageSnapshot();
|
||||
}
|
||||
|
||||
void SkXfermodeImageFilter_Base::drawForeground(SkCanvas* canvas, SkSpecialImage* img,
|
||||
const SkIRect& fgBounds) const {
|
||||
SkPaint paint;
|
||||
paint.setXfermode(fMode);
|
||||
if (img) {
|
||||
img->draw(canvas, SkIntToScalar(fgBounds.fLeft), SkIntToScalar(fgBounds.fTop), &paint);
|
||||
}
|
||||
|
||||
SkAutoCanvasRestore acr(canvas, true);
|
||||
canvas->clipRect(SkRect::Make(fgBounds), SkCanvas::kDifference_Op);
|
||||
paint.setColor(0);
|
||||
canvas->drawPaint(paint);
|
||||
}
|
||||
|
||||
#ifndef SK_IGNORE_TO_STRING
|
||||
void SkXfermodeImageFilter_Base::toString(SkString* str) const {
|
||||
str->appendf("SkXfermodeImageFilter: (");
|
||||
@ -254,7 +249,21 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::filterImageGPU(
|
||||
|
||||
paint.addColorFragmentProcessor(std::move(foregroundFP));
|
||||
|
||||
sk_sp<GrFragmentProcessor> xferFP = this->makeFGFrag(bgFP);
|
||||
// A null fMode is interpreted to mean kSrcOver_Mode (to match raster).
|
||||
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.
|
||||
struct ProcCoeff rec;
|
||||
rec.fProc = SkXfermode::GetProc(SkXfermode::kSrcOver_Mode);
|
||||
SkXfermode::ModeAsCoeff(SkXfermode::kSrcOver_Mode, &rec.fSC, &rec.fDC);
|
||||
|
||||
mode.reset(new SkProcCoeffXfermode(rec, SkXfermode::kSrcOver_Mode));
|
||||
}
|
||||
|
||||
sk_sp<GrFragmentProcessor> xferFP(
|
||||
mode->makeFragmentProcessorForImageFilter(std::move(bgFP)));
|
||||
|
||||
// A null 'xferFP' here means kSrc_Mode was used in which case we can just proceed
|
||||
if (xferFP) {
|
||||
@ -285,220 +294,13 @@ sk_sp<SkSpecialImage> SkXfermodeImageFilter_Base::filterImageGPU(
|
||||
sk_ref_sp(drawContext->getColorSpace()));
|
||||
}
|
||||
|
||||
sk_sp<GrFragmentProcessor>
|
||||
SkXfermodeImageFilter_Base::makeFGFrag(sk_sp<GrFragmentProcessor> bgFP) const {
|
||||
// A null fMode is interpreted to mean kSrcOver_Mode (to match raster).
|
||||
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.
|
||||
struct ProcCoeff rec;
|
||||
rec.fProc = SkXfermode::GetProc(SkXfermode::kSrcOver_Mode);
|
||||
SkXfermode::ModeAsCoeff(SkXfermode::kSrcOver_Mode, &rec.fSC, &rec.fDC);
|
||||
|
||||
mode.reset(new SkProcCoeffXfermode(rec, SkXfermode::kSrcOver_Mode));
|
||||
}
|
||||
return mode->makeFragmentProcessorForImageFilter(std::move(bgFP));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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)
|
||||
: SkXfermodeImageFilter_Base(nullptr, inputs, cropRect)
|
||||
, fK{ k1, k2, k3, k4 }
|
||||
, fEnforcePMColor(enforcePMColor)
|
||||
{}
|
||||
|
||||
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkArithmeticImageFilter)
|
||||
|
||||
protected:
|
||||
void flatten(SkWriteBuffer& buffer) const override {
|
||||
this->INHERITED::flatten(buffer);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
buffer.writeScalar(fK[i]);
|
||||
}
|
||||
buffer.writeBool(fEnforcePMColor);
|
||||
}
|
||||
void drawForeground(SkCanvas* canvas, SkSpecialImage*, const SkIRect&) const override;
|
||||
sk_sp<GrFragmentProcessor> makeFGFrag(sk_sp<GrFragmentProcessor> bgFP) const override;
|
||||
|
||||
private:
|
||||
const float fK[4];
|
||||
const bool fEnforcePMColor;
|
||||
|
||||
friend class SkXfermodeImageFilter;
|
||||
|
||||
typedef SkXfermodeImageFilter_Base INHERITED;
|
||||
};
|
||||
|
||||
sk_sp<SkFlattenable> SkArithmeticImageFilter::CreateProc(SkReadBuffer& buffer) {
|
||||
SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2);
|
||||
|
||||
// skip the mode (srcover) our parent-class wrote
|
||||
sk_sp<SkXfermode> mode(buffer.readXfermode());
|
||||
SkASSERT(nullptr == mode);
|
||||
|
||||
float k[4];
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
k[i] = buffer.readScalar();
|
||||
}
|
||||
const bool enforcePMColor = buffer.readBool();
|
||||
return SkXfermodeImageFilter::MakeArithmetic(k[0], k[1], k[2], k[3], enforcePMColor,
|
||||
common.getInput(0), common.getInput(1),
|
||||
&common.cropRect());
|
||||
}
|
||||
|
||||
#include "SkNx.h"
|
||||
|
||||
static Sk4f pin(float min, const Sk4f& val, float max) {
|
||||
return Sk4f::Max(min, Sk4f::Min(val, max));
|
||||
}
|
||||
|
||||
template<bool EnforcePMColor> void arith_span(const float k[], SkPMColor dst[],
|
||||
const SkPMColor src[], int count) {
|
||||
const Sk4f k1 = k[0] * (1/255.0f),
|
||||
k2 = k[1],
|
||||
k3 = k[2],
|
||||
k4 = k[3] * 255.0f + 0.5f;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
Sk4f s = SkNx_cast<float>(Sk4b::Load(src+i)),
|
||||
d = SkNx_cast<float>(Sk4b::Load(dst+i)),
|
||||
r = pin(0, k1*s*d + k2*s + k3*d + k4, 255);
|
||||
if (EnforcePMColor) {
|
||||
Sk4f a = SkNx_shuffle<3,3,3,3>(r);
|
||||
r = Sk4f::Min(a, r);
|
||||
}
|
||||
SkNx_cast<uint8_t>(r).store(dst+i);
|
||||
}
|
||||
}
|
||||
|
||||
// apply mode to src==transparent (0)
|
||||
template<bool EnforcePMColor> void arith_transparent(const float k[], SkPMColor dst[], int count) {
|
||||
const Sk4f k3 = k[2],
|
||||
k4 = k[3] * 255.0f + 0.5f;
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
Sk4f d = SkNx_cast<float>(Sk4b::Load(dst+i)),
|
||||
r = pin(0, k3*d + k4, 255);
|
||||
if (EnforcePMColor) {
|
||||
Sk4f a = SkNx_shuffle<3,3,3,3>(r);
|
||||
r = Sk4f::Min(a, r);
|
||||
}
|
||||
SkNx_cast<uint8_t>(r).store(dst+i);
|
||||
}
|
||||
}
|
||||
|
||||
static bool intersect(SkPixmap* dst, SkPixmap* src, SkIPoint srcOffset) {
|
||||
SkIRect dstR = SkIRect::MakeWH(dst->width(), dst->height());
|
||||
SkIRect srcR = SkIRect::MakeXYWH(srcOffset.x(), srcOffset.y(), src->width(), src->height());
|
||||
SkIRect sect;
|
||||
if (!sect.intersect(dstR, srcR)) {
|
||||
return false;
|
||||
}
|
||||
*dst = SkPixmap(dst->info().makeWH(sect.width(), sect.height()),
|
||||
dst->addr(sect.fLeft, sect.fTop),
|
||||
dst->rowBytes());
|
||||
*src = SkPixmap(src->info().makeWH(sect.width(), sect.height()),
|
||||
src->addr(SkTMax(0, -srcOffset.x()), SkTMax(0, -srcOffset.y())),
|
||||
src->rowBytes());
|
||||
return true;
|
||||
}
|
||||
|
||||
void SkArithmeticImageFilter::drawForeground(SkCanvas* canvas, SkSpecialImage* img,
|
||||
const SkIRect& fgBounds) const {
|
||||
SkPixmap dst;
|
||||
if (!canvas->peekPixels(&dst)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (img) {
|
||||
SkBitmap srcBM;
|
||||
SkPixmap src;
|
||||
if (!img->getROPixels(&srcBM)) {
|
||||
return;
|
||||
}
|
||||
srcBM.lockPixels();
|
||||
if (!srcBM.peekPixels(&src)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto proc = fEnforcePMColor ? arith_span<true> : arith_span<false>;
|
||||
const SkMatrix& ctm = canvas->getTotalMatrix();
|
||||
SkASSERT(ctm.getType() <= SkMatrix::kTranslate_Mask);
|
||||
SkIPoint offset {
|
||||
fgBounds.fLeft + SkScalarRoundToInt(ctm.getTranslateX()),
|
||||
fgBounds.fTop + SkScalarRoundToInt(ctm.getTranslateY()),
|
||||
};
|
||||
SkPixmap tmpDst = dst;
|
||||
if (intersect(&tmpDst, &src, offset)) {
|
||||
for (int y = 0; y < tmpDst.height(); ++y) {
|
||||
proc(fK, tmpDst.writable_addr32(0, y), src.addr32(0, y), tmpDst.width());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now apply the mode with transparent-color to the outside of the fg image
|
||||
SkRegion outside(SkIRect::MakeWH(dst.width(), dst.height()));
|
||||
outside.op(fgBounds, SkRegion::kDifference_Op);
|
||||
auto proc = fEnforcePMColor ? arith_transparent<true> : arith_transparent<false>;
|
||||
for (SkRegion::Iterator iter(outside); !iter.done(); iter.next()) {
|
||||
const SkIRect r = iter.rect();
|
||||
for (int y = r.fTop; y < r.fBottom; ++y) {
|
||||
proc(fK, dst.writable_addr32(r.fLeft, y), r.width());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sk_sp<GrFragmentProcessor>
|
||||
SkArithmeticImageFilter::makeFGFrag(sk_sp<GrFragmentProcessor> bgFP) const {
|
||||
return GrArithmeticFP::Make(fK[0], fK[1], fK[2], fK[3], fEnforcePMColor, std::move(bgFP));
|
||||
}
|
||||
|
||||
sk_sp<SkImageFilter> SkXfermodeImageFilter::MakeArithmetic(float k1, float k2, float k3, float k4,
|
||||
bool enforcePMColor,
|
||||
sk_sp<SkImageFilter> background,
|
||||
sk_sp<SkImageFilter> foreground,
|
||||
const SkImageFilter::CropRect* crop) {
|
||||
if (!SkScalarIsFinite(k1) || !SkScalarIsFinite(k2) ||
|
||||
!SkScalarIsFinite(k3) || !SkScalarIsFinite(k4)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// are we nearly some other "std" mode?
|
||||
int mode = -1; // illegal mode
|
||||
if (SkScalarNearlyZero(k1) && SkScalarNearlyEqual(k2, SK_Scalar1) &&
|
||||
SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) {
|
||||
mode = SkXfermode::kSrc_Mode;
|
||||
} else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) &&
|
||||
SkScalarNearlyEqual(k3, SK_Scalar1) && SkScalarNearlyZero(k4)) {
|
||||
mode = SkXfermode::kDst_Mode;
|
||||
} else if (SkScalarNearlyZero(k1) && SkScalarNearlyZero(k2) &&
|
||||
SkScalarNearlyZero(k3) && SkScalarNearlyZero(k4)) {
|
||||
mode = SkXfermode::kClear_Mode;
|
||||
}
|
||||
if (mode >= 0) {
|
||||
return SkXfermodeImageFilter::Make(SkXfermode::Make((SkXfermode::Mode)mode),
|
||||
std::move(background), std::move(foreground), crop);
|
||||
}
|
||||
|
||||
sk_sp<SkImageFilter> inputs[2] = { std::move(background), std::move(foreground) };
|
||||
return sk_sp<SkImageFilter>(new SkArithmeticImageFilter(k1, k2, k3, k4, enforcePMColor,
|
||||
inputs, crop));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermodeImageFilter)
|
||||
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkXfermodeImageFilter_Base)
|
||||
// manually register the legacy serialized name "SkXfermodeImageFilter"
|
||||
SkFlattenable::Register("SkXfermodeImageFilter", SkXfermodeImageFilter_Base::CreateProc,
|
||||
SkFlattenable::kSkImageFilter_Type);
|
||||
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkArithmeticImageFilter)
|
||||
SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include "Sk1DPathEffect.h"
|
||||
#include "Sk2DPathEffect.h"
|
||||
#include "SkAlphaThresholdFilter.h"
|
||||
#include "../../src/effects/SkArithmeticModePriv.h"
|
||||
#include "SkArithmeticMode.h"
|
||||
#include "SkArcToPathEffect.h"
|
||||
#include "SkBitmapSourceDeserializer.h"
|
||||
#include "SkBlurDrawLooper.h"
|
||||
|
Loading…
Reference in New Issue
Block a user