Fills out most of the simple implementations.
Improves 22 gms in gbr-8888.
Bug: skia:
Change-Id: I881ade140993568263de75be51aed240d2de8cc6
Reviewed-on: https://skia-review.googlesource.com/13126
Commit-Queue: Matt Sarett <msarett@google.com>
Reviewed-by: Mike Klein <mtklein@chromium.org>
}
private:
+ // For makeColorSpace().
friend class ArithmeticImageFilterImpl;
+ friend class SkAlphaThresholdFilterImpl;
+ friend class SkBlurImageFilterImpl;
+ friend class SkColorFilterImageFilter;
friend class SkColorSpaceXformer;
+ friend class SkComposeImageFilter;
+ friend class SkDisplacementMapEffect;
+ friend class SkDropShadowImageFilter;
+ friend class SkImageSource;
+ friend class SkMagnifierImageFilter;
+ friend class SkMatrixConvolutionImageFilter;
+ friend class SkMergeImageFilter;
+ friend class SkMorphologyImageFilter;
+ friend class SkOffsetImageFilter;
+ friend class SkTileImageFilter;
+ friend class SkXfermodeImageFilter_Base;
+
friend class SkGraphics;
static void PurgeCache();
void flatten(SkWriteBuffer&) const override;
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
+ sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
bool onIsColorFilterNode(SkColorFilter**) const override;
bool onCanHandleComplexCTM() const override { return true; }
bool affectsTransparentBlack() const override;
}
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
+ sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
SkIRect onFilterBounds(const SkIRect&, const SkMatrix&, MapDirection) const override;
bool onCanHandleComplexCTM() const override { return true; }
virtual SkIRect onFilterBounds(const SkIRect& src, const SkMatrix&,
MapDirection) const override;
+ sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix&, MapDirection) const override;
SK_TO_STRING_OVERRIDE()
void flatten(SkWriteBuffer&) const override;
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
+ sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
SkIRect onFilterNodeBounds(const SkIRect& src, const SkMatrix&, MapDirection) const override;
private:
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
+ sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
private:
explicit SkImageSource(sk_sp<SkImage>);
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
+ sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
private:
SkRect fSrcRect;
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
+ sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix&, MapDirection) const override;
bool affectsTransparentBlack() const override;
void flatten(SkWriteBuffer&) const override;
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
+ sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
bool onCanHandleComplexCTM() const override { return true; }
private:
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source,
const Context&,
SkIPoint* offset) const override;
+ sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
void flatten(SkWriteBuffer&) const override;
SkISize radius() const { return fRadius; }
void flatten(SkWriteBuffer&) const override;
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
+ sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
SkIRect onFilterNodeBounds(const SkIRect&, const SkMatrix&, MapDirection) const override;
private:
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
+ sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
private:
SkTileImageFilter(const SkRect& srcRect, const SkRect& dstRect, sk_sp<SkImageFilter> input)
void flatten(SkWriteBuffer&) const override;
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
+ sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
SkIRect onFilterNodeBounds(const SkIRect& src, const SkMatrix&, MapDirection) const override;
private:
dst, &source->props());
}
+sk_sp<SkImageFilter> SkBlurImageFilterImpl::onMakeColorSpace(SkColorSpaceXformer* xformer)
+const {
+ SkASSERT(1 == this->countInputs());
+ if (!this->getInput(0)) {
+ return sk_ref_sp(const_cast<SkBlurImageFilterImpl*>(this));
+ }
+
+ sk_sp<SkImageFilter> input = this->getInput(0)->makeColorSpace(xformer);
+ return SkImageFilter::MakeBlur(fSigma.width(), fSigma.height(), std::move(input),
+ this->getCropRectIfSet());
+}
SkRect SkBlurImageFilterImpl::computeFastBounds(const SkRect& src) const {
SkRect bounds = this->getInput(0) ? this->getInput(0)->computeFastBounds(src) : src;
return xformed;
}
+// As far as I know, SkModeColorFilter is the only color filter that holds a color.
+sk_sp<SkColorFilter> SkColorSpaceXformer::apply(const SkColorFilter* colorFilter) {
+ SkColor color;
+ SkBlendMode mode;
+ if (colorFilter->asColorMode(&color, &mode)) {
+ return SkColorFilter::MakeModeFilter(this->apply(color), mode);
+ }
+
+ return sk_ref_sp(const_cast<SkColorFilter*>(colorFilter));
+}
+
void SkColorSpaceXformer::apply(SkColor* xformed, const SkColor* srgb, int n) {
SkAssertResult(fFromSRGB->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, xformed,
SkColorSpaceXform::kBGRA_8888_ColorFormat, srgb,
}
}
- // As far as I know, SkModeColorFilter is the only color filter that holds a color.
if (auto cf = src.getColorFilter()) {
- SkColor color;
- SkBlendMode mode;
- if (cf->asColorMode(&color, &mode)) {
- get_dst()->setColorFilter(SkColorFilter::MakeModeFilter(this->apply(color), mode));
+ auto replacement = this->apply(cf);
+ if (replacement.get() != cf) {
+ get_dst()->setColorFilter(std::move(replacement));
}
}
sk_sp<SkImage> apply(const SkImage* src);
sk_sp<SkImage> apply(const SkBitmap& bitmap);
+ sk_sp<SkColorFilter> apply(const SkColorFilter* shader);
const SkPaint* apply(const SkPaint* src);
const SkPaint& apply(const SkPaint& src);
void apply(SkColor dst[], const SkColor src[], int n);
+ SkColor apply(SkColor srgb);
private:
- SkColor apply(SkColor srgb);
sk_sp<SkShader> apply(const SkShader* shader);
SkColorSpaceXformer() {}
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
+ sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
+
#if SK_SUPPORT_GPU
- sk_sp<GrTextureProxy> createMaskTexture(GrContext*,
+ sk_sp<GrTextureProxy> createMaskTexture(GrContext*,
const SkMatrix&,
const SkIRect& bounds) const;
#endif
dst);
}
+sk_sp<SkImageFilter> SkAlphaThresholdFilterImpl::onMakeColorSpace(SkColorSpaceXformer* xformer)
+const {
+ SkASSERT(1 == this->countInputs());
+ if (!this->getInput(0)) {
+ return sk_ref_sp(const_cast<SkAlphaThresholdFilterImpl*>(this));
+ }
+
+ sk_sp<SkImageFilter> input = this->getInput(0)->makeColorSpace(xformer);
+ return SkAlphaThresholdFilter::Make(fRegion, fInnerThreshold, fOuterThreshold,
+ std::move(input), this->getCropRectIfSet());
+}
+
#ifndef SK_IGNORE_TO_STRING
void SkAlphaThresholdFilterImpl::toString(SkString* str) const {
str->appendf("SkAlphaThresholdImageFilter: (");
#include "SkCanvas.h"
#include "SkColorFilter.h"
+#include "SkColorSpaceXformer.h"
#include "SkReadBuffer.h"
#include "SkSpecialImage.h"
#include "SkSpecialSurface.h"
return surf->makeImageSnapshot();
}
+sk_sp<SkImageFilter> SkColorFilterImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer)
+const {
+ SkASSERT(1 == this->countInputs());
+
+ sk_sp<SkImageFilter> input =
+ this->getInput(0) ? this->getInput(0)->makeColorSpace(xformer) : nullptr;
+ sk_sp<SkColorFilter> colorFilter = xformer->apply(fColorFilter.get());
+
+ return SkColorFilterImageFilter::Make(std::move(colorFilter), std::move(input),
+ this->getCropRectIfSet());
+}
+
bool SkColorFilterImageFilter::onIsColorFilterNode(SkColorFilter** filter) const {
SkASSERT(1 == this->countInputs());
if (!this->cropRectIsSet()) {
return outer;
}
+sk_sp<SkImageFilter> SkComposeImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
+ SkASSERT(2 == this->countInputs() && this->getInput(0) && this->getInput(1));
+
+ return SkComposeImageFilter::Make(this->getInput(0)->makeColorSpace(xformer),
+ this->getInput(1)->makeColorSpace(xformer));
+}
+
SkIRect SkComposeImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
MapDirection direction) const {
SkImageFilter* outer = this->getInput(0);
dst);
}
+sk_sp<SkImageFilter> SkDisplacementMapEffect::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
+ SkASSERT(2 == this->countInputs());
+ if (!this->getInput(1)) {
+ return sk_ref_sp(const_cast<SkDisplacementMapEffect*>(this));
+ }
+
+ // Intentionally avoid xforming the displacement filter. The values will be used as
+ // offsets, not as colors.
+ sk_sp<SkImageFilter> displacement = sk_ref_sp(const_cast<SkImageFilter*>(this->getInput(0)));
+ sk_sp<SkImageFilter> color =
+ this->getInput(1) ? this->getInput(1)->makeColorSpace(xformer) : nullptr;
+
+ return SkDisplacementMapEffect::Make(fXChannelSelector, fYChannelSelector, fScale,
+ std::move(displacement), std::move(color),
+ this->getCropRectIfSet());
+}
+
SkRect SkDisplacementMapEffect::computeFastBounds(const SkRect& src) const {
SkRect bounds = this->getColorInput() ? this->getColorInput()->computeFastBounds(src) : src;
bounds.outset(SkScalarAbs(fScale) * SK_ScalarHalf, SkScalarAbs(fScale) * SK_ScalarHalf);
#include "SkBlurImageFilter.h"
#include "SkCanvas.h"
+#include "SkColorSpaceXformer.h"
#include "SkReadBuffer.h"
#include "SkSpecialImage.h"
#include "SkSpecialSurface.h"
return surf->makeImageSnapshot();
}
+sk_sp<SkImageFilter> SkDropShadowImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
+ SkASSERT(1 == this->countInputs());
+
+ sk_sp<SkImageFilter> input =
+ this->getInput(0) ? this->getInput(0)->makeColorSpace(xformer) : nullptr;
+
+ return SkDropShadowImageFilter::Make(fDx, fDy, fSigmaX, fSigmaY, xformer->apply(fColor),
+ fShadowMode, std::move(input));
+}
+
SkRect SkDropShadowImageFilter::computeFastBounds(const SkRect& src) const {
SkRect bounds = this->getInput(0) ? this->getInput(0)->computeFastBounds(src) : src;
SkRect shadowBounds = bounds;
#include "SkImageSource.h"
#include "SkCanvas.h"
+#include "SkColorSpaceXformer.h"
#include "SkImage.h"
#include "SkReadBuffer.h"
#include "SkSpecialImage.h"
return surf->makeImageSnapshot();
}
+sk_sp<SkImageFilter> SkImageSource::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
+ SkASSERT(0 == this->countInputs());
+
+ return SkImageSource::Make(xformer->apply(fImage.get()), fSrcRect, fDstRect, fFilterQuality);
+}
+
SkRect SkImageSource::computeFastBounds(const SkRect& src) const {
return fDstRect;
}
dst);
}
+sk_sp<SkImageFilter> SkMagnifierImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
+ SkASSERT(1 == this->countInputs());
+ if (!this->getInput(0)) {
+ return sk_ref_sp(const_cast<SkMagnifierImageFilter*>(this));
+ }
+
+ sk_sp<SkImageFilter> input = this->getInput(0)->makeColorSpace(xformer);
+ return SkMagnifierImageFilter::Make(fSrcRect, fInset, std::move(input),
+ this->getCropRectIfSet());
+}
+
#ifndef SK_IGNORE_TO_STRING
void SkMagnifierImageFilter::toString(SkString* str) const {
str->appendf("SkMagnifierImageFilter: (");
dst);
}
+sk_sp<SkImageFilter> SkMatrixConvolutionImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer)
+const {
+ SkASSERT(1 == this->countInputs());
+ if (!this->getInput(0)) {
+ return sk_ref_sp(const_cast<SkMatrixConvolutionImageFilter*>(this));
+ }
+
+ sk_sp<SkImageFilter> input = this->getInput(0)->makeColorSpace(xformer);
+ return SkMatrixConvolutionImageFilter::Make(fKernelSize, fKernel, fGain, fBias, fKernelOffset,
+ fTileMode, fConvolveAlpha, std::move(input),
+ this->getCropRectIfSet());
+}
+
SkIRect SkMatrixConvolutionImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm,
MapDirection direction) const {
SkIRect dst = src;
return surf->makeImageSnapshot();
}
+sk_sp<SkImageFilter> SkMergeImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
+ SkSTArray<5, sk_sp<SkImageFilter>> inputs(this->countInputs());
+ SkSTArray<5, SkBlendMode> modes(this->countInputs());
+ for (int i = 0; i < this->countInputs(); i++) {
+ inputs.push_back(this->getInput(i) ? this->getInput(i)->makeColorSpace(xformer) : nullptr);
+ modes.push_back((SkBlendMode) fModes[i]);
+ }
+
+ return SkMergeImageFilter::MakeN(inputs.begin(), this->countInputs(), modes.begin(),
+ this->getCropRectIfSet());
+}
+
sk_sp<SkFlattenable> SkMergeImageFilter::CreateProc(SkReadBuffer& buffer) {
Common common;
if (!common.unflatten(buffer, -1)) {
return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()),
dst, &source->props());
}
+
+sk_sp<SkImageFilter> SkMorphologyImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
+ SkASSERT(1 == this->countInputs());
+ if (!this->getInput(0)) {
+ return sk_ref_sp(const_cast<SkMorphologyImageFilter*>(this));
+ }
+
+ sk_sp<SkImageFilter> input = this->getInput(0)->makeColorSpace(xformer);
+ return (SkMorphologyImageFilter::kDilate_Op == this->op())
+ ? SkDilateImageFilter::Make(fRadius.width(), fRadius.height(), std::move(input),
+ this->getCropRectIfSet())
+ : SkErodeImageFilter::Make(fRadius.width(), fRadius.height(), std::move(input),
+ this->getCropRectIfSet());
+}
}
}
+sk_sp<SkImageFilter> SkOffsetImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
+ SkASSERT(1 == this->countInputs());
+ if (!this->getInput(0)) {
+ return sk_ref_sp(const_cast<SkOffsetImageFilter*>(this));
+ }
+
+ sk_sp<SkImageFilter> input = this->getInput(0)->makeColorSpace(xformer);
+ return SkOffsetImageFilter::Make(fOffset.fX, fOffset.fY, std::move(input),
+ this->getCropRectIfSet());
+}
+
SkRect SkOffsetImageFilter::computeFastBounds(const SkRect& src) const {
SkRect bounds = this->getInput(0) ? this->getInput(0)->computeFastBounds(src) : src;
bounds.offset(fOffset.fX, fOffset.fY);
return surf->makeImageSnapshot();
}
+sk_sp<SkImageFilter> SkTileImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
+ SkASSERT(1 == this->countInputs());
+ if (!this->getInput(0)) {
+ return sk_ref_sp(const_cast<SkTileImageFilter*>(this));
+ }
+
+ sk_sp<SkImageFilter> input = this->getInput(0)->makeColorSpace(xformer);
+ return SkTileImageFilter::Make(fSrcRect, fDstRect, std::move(input));
+}
+
SkIRect SkTileImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm,
MapDirection direction) const {
SkRect rect = kReverse_MapDirection == direction ? fSrcRect : fDstRect;
protected:
sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
SkIPoint* offset) const override;
+ sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
#if SK_SUPPORT_GPU
sk_sp<SkSpecialImage> filterImageGPU(SkSpecialImage* source,
return surf->makeImageSnapshot();
}
+sk_sp<SkImageFilter> SkXfermodeImageFilter_Base::onMakeColorSpace(SkColorSpaceXformer* xformer)
+const {
+ SkASSERT(2 == this->countInputs());
+ if (!this->getInput(0) && !this->getInput(1)) {
+ return sk_ref_sp(const_cast<SkXfermodeImageFilter_Base*>(this));
+ }
+
+ sk_sp<SkImageFilter> background =
+ this->getInput(0) ? this->getInput(0)->makeColorSpace(xformer) : nullptr;
+ sk_sp<SkImageFilter> foreground =
+ this->getInput(1) ? this->getInput(1)->makeColorSpace(xformer) : nullptr;
+
+ return SkXfermodeImageFilter::Make(fMode, std::move(background), std::move(foreground),
+ this->getCropRectIfSet());
+}
+
void SkXfermodeImageFilter_Base::drawForeground(SkCanvas* canvas, SkSpecialImage* img,
const SkIRect& fgBounds) const {
SkPaint paint;