Implement support for expanding crop rects in image filters
NOTE: this patch set is based on https://codereview.chromium.org/189913021/, and needs that patch to land first. Until now, crop rects in Skia have only been able to reduce the size of the destination bounds, but not expand them. SVG semantics require the latter as well. The heart of the change is in applyCropRect(), which now assigns each edge, instead of doing an intersection with the crop rect. In order to support this (and still work well with tiled drawing) we need to clip the resulting crop rect to the clipping region of the filters. This uses the Context struct previously landed from https://codereview.chromium.org/189913021/. Many of the pixel loops are not yet ready to handle a destination rect larger than the source rect. So we provide a convenience version of applyCropRect() which creates an offscreen and pads it out with transparent black. Once the pixel loops and shaders have been fixed to support larger destination bounds, they should be switched back to the non-drawing version of applyCropRect(). BUG=skia: R=bsalomon@google.com, reed@google.com Review URL: https://codereview.chromium.org/198003008 git-svn-id: http://skia.googlecode.com/svn/trunk@13805 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
8687608c45
commit
0ef0501baf
170
gm/imagefilterscropexpand.cpp
Normal file
170
gm/imagefilterscropexpand.cpp
Normal file
@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "gm.h"
|
||||
#include "SkCanvas.h"
|
||||
#include "SkColorFilter.h"
|
||||
#include "SkColorPriv.h"
|
||||
#include "SkShader.h"
|
||||
|
||||
#include "SkBitmapSource.h"
|
||||
#include "SkBlurImageFilter.h"
|
||||
#include "SkColorMatrixFilter.h"
|
||||
#include "SkDisplacementMapEffect.h"
|
||||
#include "SkDropShadowImageFilter.h"
|
||||
#include "SkGradientShader.h"
|
||||
#include "SkMorphologyImageFilter.h"
|
||||
#include "SkColorFilterImageFilter.h"
|
||||
#include "SkMergeImageFilter.h"
|
||||
#include "SkOffsetImageFilter.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class ImageFiltersCropExpandGM : public skiagm::GM {
|
||||
public:
|
||||
ImageFiltersCropExpandGM () {}
|
||||
|
||||
protected:
|
||||
|
||||
virtual SkString onShortName() {
|
||||
return SkString("imagefilterscropexpand");
|
||||
}
|
||||
|
||||
virtual SkISize onISize() { return SkISize::Make(570, 650); }
|
||||
|
||||
void make_checkerboard(SkBitmap* bitmap) {
|
||||
bitmap->allocN32Pixels(64, 64);
|
||||
SkCanvas canvas(*bitmap);
|
||||
canvas.clear(0xFFFF0000);
|
||||
SkPaint darkPaint;
|
||||
darkPaint.setColor(0xFF404040);
|
||||
SkPaint lightPaint;
|
||||
lightPaint.setColor(0xFFA0A0A0);
|
||||
for (int y = 8; y < 48; y += 16) {
|
||||
for (int x = 8; x < 48; x += 16) {
|
||||
canvas.save();
|
||||
canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
|
||||
canvas.drawRect(SkRect::MakeXYWH(0, 0, 8, 8), darkPaint);
|
||||
canvas.drawRect(SkRect::MakeXYWH(8, 0, 8, 8), lightPaint);
|
||||
canvas.drawRect(SkRect::MakeXYWH(0, 8, 8, 8), lightPaint);
|
||||
canvas.drawRect(SkRect::MakeXYWH(8, 8, 8, 8), darkPaint);
|
||||
canvas.restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void make_gradient_circle(int width, int height, SkBitmap* bitmap) {
|
||||
SkScalar x = SkIntToScalar(width / 2);
|
||||
SkScalar y = SkIntToScalar(height / 2);
|
||||
SkScalar radius = SkMinScalar(x, y) * 0.8f;
|
||||
bitmap->allocN32Pixels(width, height);
|
||||
SkCanvas canvas(*bitmap);
|
||||
canvas.clear(0x00000000);
|
||||
SkColor colors[2];
|
||||
colors[0] = SK_ColorWHITE;
|
||||
colors[1] = SK_ColorBLACK;
|
||||
SkAutoTUnref<SkShader> shader(
|
||||
SkGradientShader::CreateRadial(SkPoint::Make(x, y), radius, colors, NULL, 2,
|
||||
SkShader::kClamp_TileMode)
|
||||
);
|
||||
SkPaint paint;
|
||||
paint.setShader(shader);
|
||||
canvas.drawCircle(x, y, radius, paint);
|
||||
}
|
||||
|
||||
static void draw(SkCanvas* canvas, const SkBitmap& bitmap, const SkRect& rect, SkImageFilter* filter) {
|
||||
SkPaint paint;
|
||||
paint.setImageFilter(filter)->unref();
|
||||
canvas->saveLayer(&rect, &paint);
|
||||
canvas->drawBitmap(bitmap, 0, 0);
|
||||
canvas->restore();
|
||||
|
||||
SkPaint strokePaint;
|
||||
strokePaint.setColor(0xFFFF0000);
|
||||
strokePaint.setStyle(SkPaint::kStroke_Style);
|
||||
canvas->drawRect(rect, strokePaint);
|
||||
|
||||
canvas->translate(SkIntToScalar(80), 0);
|
||||
}
|
||||
|
||||
virtual void onDraw(SkCanvas* canvas) {
|
||||
SkAutoTUnref<SkColorFilter> cf(
|
||||
SkColorFilter::CreateModeFilter(SK_ColorBLUE, SkXfermode::kSrcIn_Mode));
|
||||
SkImageFilter::CropRect crop_rect(
|
||||
SkRect::Make(SkIRect::MakeXYWH(10, 10, 44, 44)),
|
||||
SkImageFilter::CropRect::kHasAll_CropEdge);
|
||||
|
||||
SkBitmap gradient_circle, checkerboard;
|
||||
make_gradient_circle(64, 64, &gradient_circle);
|
||||
make_checkerboard(&checkerboard);
|
||||
|
||||
SkAutoTUnref<SkImageFilter> gradient_circle_source(
|
||||
SkBitmapSource::Create(gradient_circle));
|
||||
SkAutoTUnref<SkImageFilter> noop_cropped(
|
||||
SkOffsetImageFilter::Create(0, 0, NULL, &crop_rect));
|
||||
SkScalar sk255 = SkIntToScalar(255);
|
||||
SkScalar matrix[20] = { 1, 0, 0, 0, 0,
|
||||
0, 1, 0, 0, sk255,
|
||||
0, 0, 1, 0, 0,
|
||||
0, 0, 0, 0, sk255 };
|
||||
SkAutoTUnref<SkColorFilter> cf_alpha_trans(SkColorMatrixFilter::Create(matrix));
|
||||
|
||||
SkRect r = SkRect::MakeWH(SkIntToScalar(64), SkIntToScalar(64));
|
||||
SkScalar MARGIN = SkIntToScalar(12);
|
||||
|
||||
SkIRect bounds;
|
||||
r.roundOut(&bounds);
|
||||
|
||||
SkPaint paint;
|
||||
canvas->translate(MARGIN, MARGIN);
|
||||
for (int outset = -15; outset <= 20; outset += 5) {
|
||||
canvas->save();
|
||||
SkRect rect = crop_rect.rect();
|
||||
rect.outset(SkIntToScalar(outset),
|
||||
SkIntToScalar(outset));
|
||||
SkImageFilter::CropRect big_rect(rect, SkImageFilter::CropRect::kHasAll_CropEdge);
|
||||
|
||||
draw(canvas, checkerboard, rect, SkColorFilterImageFilter::Create(
|
||||
cf_alpha_trans, noop_cropped.get(), &big_rect));
|
||||
|
||||
draw(canvas, checkerboard, rect, SkBlurImageFilter::Create(
|
||||
8.0f, 8.0f, noop_cropped.get(), &big_rect));
|
||||
|
||||
draw(canvas, checkerboard, rect, SkDilateImageFilter::Create(
|
||||
2, 2, noop_cropped.get(), &big_rect));
|
||||
|
||||
draw(canvas, checkerboard, rect, SkErodeImageFilter::Create(
|
||||
2, 2, noop_cropped.get(), &big_rect));
|
||||
|
||||
draw(canvas, checkerboard, rect, SkDropShadowImageFilter::Create(
|
||||
SkIntToScalar(10), SkIntToScalar(10), SkIntToScalar(3), SkIntToScalar(3),
|
||||
SK_ColorBLUE, noop_cropped.get(), &big_rect));
|
||||
|
||||
draw(canvas, checkerboard, rect, SkDisplacementMapEffect::Create(
|
||||
SkDisplacementMapEffect::kR_ChannelSelectorType,
|
||||
SkDisplacementMapEffect::kR_ChannelSelectorType,
|
||||
SkIntToScalar(12),
|
||||
gradient_circle_source.get(),
|
||||
noop_cropped.get(),
|
||||
&big_rect));
|
||||
|
||||
draw(canvas, checkerboard, rect, SkOffsetImageFilter::Create(
|
||||
SkIntToScalar(-8), SkIntToScalar(16), noop_cropped.get(), &big_rect));
|
||||
|
||||
canvas->restore();
|
||||
canvas->translate(0, SkIntToScalar(80));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
typedef GM INHERITED;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static skiagm::GM* MyFactory(void*) { return new ImageFiltersCropExpandGM; }
|
||||
static skiagm::GMRegistry reg(MyFactory);
|
@ -39,9 +39,7 @@ public:
|
||||
}
|
||||
|
||||
SkIRect bounds;
|
||||
source.getBounds(&bounds);
|
||||
|
||||
if (!this->applyCropRect(&bounds, ctx.ctm())) {
|
||||
if (!this->applyCropRect(ctx, proxy, source, &srcOffset, &bounds, &source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -101,6 +101,7 @@
|
||||
'../gm/imagefiltersbase.cpp',
|
||||
'../gm/imagefiltersclipped.cpp',
|
||||
'../gm/imagefilterscropped.cpp',
|
||||
'../gm/imagefilterscropexpand.cpp',
|
||||
'../gm/imagefiltersgraph.cpp',
|
||||
'../gm/imagefiltersscaled.cpp',
|
||||
'../gm/internal_links.cpp',
|
||||
|
@ -223,10 +223,25 @@ protected:
|
||||
// no inputs.
|
||||
virtual bool onFilterBounds(const SkIRect&, const SkMatrix&, SkIRect*) const;
|
||||
|
||||
// Applies "matrix" to the crop rect, and sets "rect" to the intersection of
|
||||
// "rect" and the transformed crop rect. If there is no overlap, returns
|
||||
// false and leaves "rect" unchanged.
|
||||
bool applyCropRect(SkIRect* rect, const SkMatrix& matrix) const;
|
||||
/** Computes source bounds as the src bitmap bounds offset by srcOffset.
|
||||
* Apply the transformed crop rect to the bounds if any of the
|
||||
* corresponding edge flags are set. Intersects the result against the
|
||||
* context's clipBounds, and returns the result in "bounds". If there is
|
||||
* no intersection, returns false and leaves "bounds" unchanged.
|
||||
*/
|
||||
bool applyCropRect(const Context&, const SkBitmap& src, const SkIPoint& srcOffset,
|
||||
SkIRect* bounds) const;
|
||||
|
||||
/** Same as the above call, except that if the resulting crop rect is not
|
||||
* entirely contained by the source bitmap's bounds, it creates a new
|
||||
* bitmap in "result" and pads the edges with transparent black. In that
|
||||
* case, the srcOffset is modified to be the same as the bounds, since no
|
||||
* further adjustment is needed by the caller. This version should only
|
||||
* be used by filters which are not capable of processing a smaller
|
||||
* source bitmap into a larger destination.
|
||||
*/
|
||||
bool applyCropRect(const Context&, Proxy* proxy, const SkBitmap& src, SkIPoint* srcOffset,
|
||||
SkIRect* bounds, SkBitmap* result) const;
|
||||
|
||||
/**
|
||||
* Returns true if the filter can be expressed a single-pass
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include "SkImageFilter.h"
|
||||
|
||||
#include "SkBitmap.h"
|
||||
#include "SkDevice.h"
|
||||
#include "SkReadBuffer.h"
|
||||
#include "SkWriteBuffer.h"
|
||||
#include "SkRect.h"
|
||||
@ -155,9 +156,7 @@ bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Cont
|
||||
}
|
||||
GrTexture* srcTexture = input.getTexture();
|
||||
SkIRect bounds;
|
||||
src.getBounds(&bounds);
|
||||
bounds.offset(srcOffset);
|
||||
if (!this->applyCropRect(&bounds, ctx.ctm())) {
|
||||
if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) {
|
||||
return false;
|
||||
}
|
||||
SkRect srcRect = SkRect::Make(bounds);
|
||||
@ -196,18 +195,60 @@ bool SkImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Cont
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SkImageFilter::applyCropRect(SkIRect* rect, const SkMatrix& matrix) const {
|
||||
bool SkImageFilter::applyCropRect(const Context& ctx, const SkBitmap& src,
|
||||
const SkIPoint& srcOffset, SkIRect* bounds) const {
|
||||
SkIRect srcBounds;
|
||||
src.getBounds(&srcBounds);
|
||||
srcBounds.offset(srcOffset);
|
||||
SkRect cropRect;
|
||||
matrix.mapRect(&cropRect, fCropRect.rect());
|
||||
ctx.ctm().mapRect(&cropRect, fCropRect.rect());
|
||||
SkIRect cropRectI;
|
||||
cropRect.roundOut(&cropRectI);
|
||||
uint32_t flags = fCropRect.flags();
|
||||
// If the original crop rect edges were unset, max out the new crop edges
|
||||
if (!(flags & CropRect::kHasLeft_CropEdge)) cropRectI.fLeft = SK_MinS32;
|
||||
if (!(flags & CropRect::kHasTop_CropEdge)) cropRectI.fTop = SK_MinS32;
|
||||
if (!(flags & CropRect::kHasRight_CropEdge)) cropRectI.fRight = SK_MaxS32;
|
||||
if (!(flags & CropRect::kHasBottom_CropEdge)) cropRectI.fBottom = SK_MaxS32;
|
||||
return rect->intersect(cropRectI);
|
||||
if (flags & CropRect::kHasLeft_CropEdge) srcBounds.fLeft = cropRectI.fLeft;
|
||||
if (flags & CropRect::kHasTop_CropEdge) srcBounds.fTop = cropRectI.fTop;
|
||||
if (flags & CropRect::kHasRight_CropEdge) srcBounds.fRight = cropRectI.fRight;
|
||||
if (flags & CropRect::kHasBottom_CropEdge) srcBounds.fBottom = cropRectI.fBottom;
|
||||
if (!srcBounds.intersect(ctx.clipBounds())) {
|
||||
return false;
|
||||
}
|
||||
*bounds = srcBounds;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SkImageFilter::applyCropRect(const Context& ctx, Proxy* proxy, const SkBitmap& src,
|
||||
SkIPoint* srcOffset, SkIRect* bounds, SkBitmap* dst) const {
|
||||
SkIRect srcBounds;
|
||||
src.getBounds(&srcBounds);
|
||||
srcBounds.offset(*srcOffset);
|
||||
SkRect cropRect;
|
||||
ctx.ctm().mapRect(&cropRect, fCropRect.rect());
|
||||
SkIRect cropRectI;
|
||||
cropRect.roundOut(&cropRectI);
|
||||
uint32_t flags = fCropRect.flags();
|
||||
*bounds = srcBounds;
|
||||
if (flags & CropRect::kHasLeft_CropEdge) bounds->fLeft = cropRectI.fLeft;
|
||||
if (flags & CropRect::kHasTop_CropEdge) bounds->fTop = cropRectI.fTop;
|
||||
if (flags & CropRect::kHasRight_CropEdge) bounds->fRight = cropRectI.fRight;
|
||||
if (flags & CropRect::kHasBottom_CropEdge) bounds->fBottom = cropRectI.fBottom;
|
||||
if (!bounds->intersect(ctx.clipBounds())) {
|
||||
return false;
|
||||
}
|
||||
if (srcBounds.contains(*bounds)) {
|
||||
*dst = src;
|
||||
return true;
|
||||
} else {
|
||||
SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds->width(), bounds->height()));
|
||||
if (!device) {
|
||||
return false;
|
||||
}
|
||||
SkCanvas canvas(device);
|
||||
canvas.clear(0x00000000);
|
||||
canvas.drawBitmap(src, srcOffset->x() - bounds->x(), srcOffset->y() - bounds->y());
|
||||
*srcOffset = SkIPoint::Make(bounds->x(), bounds->y());
|
||||
*dst = device->accessBitmap(false);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool SkImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
|
||||
|
@ -146,15 +146,13 @@ bool SkBlurImageFilter::onFilterImage(Proxy* proxy,
|
||||
return false;
|
||||
}
|
||||
|
||||
SkAutoLockPixels alp(src);
|
||||
if (!src.getPixels()) {
|
||||
SkIRect srcBounds, dstBounds;
|
||||
if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &srcBounds, &src)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkIRect srcBounds, dstBounds;
|
||||
src.getBounds(&srcBounds);
|
||||
srcBounds.offset(srcOffset);
|
||||
if (!this->applyCropRect(&srcBounds, ctx.ctm())) {
|
||||
SkAutoLockPixels alp(src);
|
||||
if (!src.getPixels()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -258,13 +256,11 @@ bool SkBlurImageFilter::filterImageGPU(Proxy* proxy, const SkBitmap& src, const
|
||||
if (getInput(0) && !getInput(0)->getInputResultGPU(proxy, src, ctx, &input, &srcOffset)) {
|
||||
return false;
|
||||
}
|
||||
GrTexture* source = input.getTexture();
|
||||
SkIRect rect;
|
||||
src.getBounds(&rect);
|
||||
rect.offset(srcOffset);
|
||||
if (!this->applyCropRect(&rect, ctx.ctm())) {
|
||||
if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &rect, &input)) {
|
||||
return false;
|
||||
}
|
||||
GrTexture* source = input.getTexture();
|
||||
SkVector sigma, localSigma = SkVector::Make(fSigma.width(), fSigma.height());
|
||||
ctx.ctm().mapVectors(&sigma, &localSigma, 1);
|
||||
offset->fX = rect.fLeft;
|
||||
|
@ -109,9 +109,7 @@ bool SkColorFilterImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& sourc
|
||||
}
|
||||
|
||||
SkIRect bounds;
|
||||
src.getBounds(&bounds);
|
||||
bounds.offset(srcOffset);
|
||||
if (!this->applyCropRect(&bounds, ctx.ctm())) {
|
||||
if (!this->applyCropRect(ctx, src, srcOffset, &bounds)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -209,26 +209,23 @@ bool SkDisplacementMapEffect::onFilterImage(Proxy* proxy,
|
||||
(color.colorType() != kPMColor_SkColorType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkAutoLockPixels alp_displacement(displ), alp_color(color);
|
||||
if (!displ.getPixels() || !color.getPixels()) {
|
||||
return false;
|
||||
}
|
||||
SkIRect bounds;
|
||||
color.getBounds(&bounds);
|
||||
bounds.offset(colorOffset);
|
||||
if (!this->applyCropRect(&bounds, ctx.ctm())) {
|
||||
// Since computeDisplacement does bounds checking on color pixel access, we don't need to pad
|
||||
// the color bitmap to bounds here.
|
||||
if (!this->applyCropRect(ctx, color, colorOffset, &bounds)) {
|
||||
return false;
|
||||
}
|
||||
SkIRect displBounds;
|
||||
displ.getBounds(&displBounds);
|
||||
displBounds.offset(displOffset);
|
||||
if (!this->applyCropRect(&displBounds, ctx.ctm())) {
|
||||
if (!this->applyCropRect(ctx, proxy, displ, &displOffset, &displBounds, &displ)) {
|
||||
return false;
|
||||
}
|
||||
if (!bounds.intersect(displBounds)) {
|
||||
return false;
|
||||
}
|
||||
SkAutoLockPixels alp_displacement(displ), alp_color(color);
|
||||
if (!displ.getPixels() || !color.getPixels()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dst->setConfig(color.config(), bounds.width(), bounds.height());
|
||||
if (!dst->allocPixels()) {
|
||||
@ -254,14 +251,18 @@ void SkDisplacementMapEffect::computeFastBounds(const SkRect& src, SkRect* dst)
|
||||
} else {
|
||||
*dst = src;
|
||||
}
|
||||
dst->outset(fScale * SK_ScalarHalf, fScale * SK_ScalarHalf);
|
||||
}
|
||||
|
||||
bool SkDisplacementMapEffect::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
|
||||
SkIRect* dst) const {
|
||||
if (getColorInput()) {
|
||||
return getColorInput()->filterBounds(src, ctm, dst);
|
||||
SkIRect bounds = src;
|
||||
if (getColorInput() && !getColorInput()->filterBounds(src, ctm, &bounds)) {
|
||||
return false;
|
||||
}
|
||||
*dst = src;
|
||||
bounds.outset(SkScalarCeilToInt(fScale * SK_ScalarHalf),
|
||||
SkScalarCeilToInt(fScale * SK_ScalarHalf));
|
||||
*dst = bounds;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -356,7 +357,6 @@ bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src,
|
||||
&colorOffset)) {
|
||||
return false;
|
||||
}
|
||||
GrTexture* color = colorBM.getTexture();
|
||||
SkBitmap displacementBM = src;
|
||||
SkIPoint displacementOffset = SkIPoint::Make(0, 0);
|
||||
if (getDisplacementInput() &&
|
||||
@ -364,6 +364,21 @@ bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src,
|
||||
&displacementOffset)) {
|
||||
return false;
|
||||
}
|
||||
SkIRect bounds;
|
||||
// Since GrDisplacementMapEffect does bounds checking on color pixel access, we don't need to
|
||||
// pad the color bitmap to bounds here.
|
||||
if (!this->applyCropRect(ctx, colorBM, colorOffset, &bounds)) {
|
||||
return false;
|
||||
}
|
||||
SkIRect displBounds;
|
||||
if (!this->applyCropRect(ctx, proxy, displacementBM,
|
||||
&displacementOffset, &displBounds, &displacementBM)) {
|
||||
return false;
|
||||
}
|
||||
if (!bounds.intersect(displBounds)) {
|
||||
return false;
|
||||
}
|
||||
GrTexture* color = colorBM.getTexture();
|
||||
GrTexture* displacement = displacementBM.getTexture();
|
||||
GrContext* context = color->getContext();
|
||||
|
||||
@ -380,21 +395,6 @@ bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src,
|
||||
|
||||
SkVector scale = SkVector::Make(fScale, fScale);
|
||||
ctx.ctm().mapVectors(&scale, 1);
|
||||
SkIRect bounds;
|
||||
colorBM.getBounds(&bounds);
|
||||
bounds.offset(colorOffset);
|
||||
if (!this->applyCropRect(&bounds, ctx.ctm())) {
|
||||
return false;
|
||||
}
|
||||
SkIRect displBounds;
|
||||
displacementBM.getBounds(&displBounds);
|
||||
displBounds.offset(displacementOffset);
|
||||
if (!this->applyCropRect(&displBounds, ctx.ctm())) {
|
||||
return false;
|
||||
}
|
||||
if (!bounds.intersect(displBounds)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GrPaint paint;
|
||||
SkMatrix offsetMatrix = GrEffect::MakeDivByTextureWHMatrix(displacement);
|
||||
|
@ -66,9 +66,7 @@ bool SkDropShadowImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source
|
||||
return false;
|
||||
|
||||
SkIRect bounds;
|
||||
src.getBounds(&bounds);
|
||||
bounds.offset(srcOffset);
|
||||
if (!this->applyCropRect(&bounds, ctx.ctm())) {
|
||||
if (!this->applyCropRect(ctx, src, srcOffset, &bounds)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -90,7 +88,8 @@ bool SkDropShadowImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source
|
||||
paint.setXfermodeMode(SkXfermode::kSrcOver_Mode);
|
||||
SkVector offsetVec, localOffsetVec = SkVector::Make(fDx, fDy);
|
||||
ctx.ctm().mapVectors(&offsetVec, &localOffsetVec, 1);
|
||||
canvas.translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop));
|
||||
canvas.translate(SkIntToScalar(srcOffset.fX - bounds.fLeft),
|
||||
SkIntToScalar(srcOffset.fY - bounds.fTop));
|
||||
canvas.drawBitmap(src, offsetVec.fX, offsetVec.fY, &paint);
|
||||
canvas.drawBitmap(src, 0, 0);
|
||||
*result = device->accessBitmap(false);
|
||||
|
@ -946,15 +946,8 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy,
|
||||
if (src.colorType() != kPMColor_SkColorType) {
|
||||
return false;
|
||||
}
|
||||
SkAutoLockPixels alp(src);
|
||||
if (!src.getPixels()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkIRect bounds;
|
||||
src.getBounds(&bounds);
|
||||
bounds.offset(srcOffset);
|
||||
if (!this->applyCropRect(&bounds, ctx.ctm())) {
|
||||
if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -962,6 +955,11 @@ bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy,
|
||||
return false;
|
||||
}
|
||||
|
||||
SkAutoLockPixels alp(src);
|
||||
if (!src.getPixels()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dst->setConfig(src.config(), bounds.width(), bounds.height());
|
||||
if (!dst->allocPixels()) {
|
||||
return false;
|
||||
@ -1039,15 +1037,9 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy,
|
||||
if (src.colorType() != kPMColor_SkColorType) {
|
||||
return false;
|
||||
}
|
||||
SkAutoLockPixels alp(src);
|
||||
if (!src.getPixels()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SkIRect bounds;
|
||||
src.getBounds(&bounds);
|
||||
bounds.offset(srcOffset);
|
||||
if (!this->applyCropRect(&bounds, ctx.ctm())) {
|
||||
if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1055,6 +1047,11 @@ bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy,
|
||||
return false;
|
||||
}
|
||||
|
||||
SkAutoLockPixels alp(src);
|
||||
if (!src.getPixels()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dst->setConfig(src.config(), bounds.width(), bounds.height());
|
||||
dst->allocPixels();
|
||||
if (!dst->getPixels()) {
|
||||
|
@ -265,9 +265,7 @@ bool SkMatrixConvolutionImageFilter::onFilterImage(Proxy* proxy,
|
||||
}
|
||||
|
||||
SkIRect bounds;
|
||||
src.getBounds(&bounds);
|
||||
bounds.offset(srcOffset);
|
||||
if (!this->applyCropRect(&bounds, ctx.ctm())) {
|
||||
if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -73,8 +73,7 @@ bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
|
||||
}
|
||||
|
||||
SkIRect bounds;
|
||||
src.getBounds(&bounds);
|
||||
if (!this->applyCropRect(&bounds, ctx.ctm())) {
|
||||
if (!this->applyCropRect(ctx, src, SkIPoint::Make(0, 0), &bounds)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -154,9 +154,7 @@ bool SkMorphologyImageFilter::filterImageGeneric(SkMorphologyImageFilter::Proc p
|
||||
}
|
||||
|
||||
SkIRect bounds;
|
||||
src.getBounds(&bounds);
|
||||
bounds.offset(srcOffset);
|
||||
if (!this->applyCropRect(&bounds, ctx.ctm())) {
|
||||
if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -547,9 +545,7 @@ bool SkMorphologyImageFilter::filterImageGPUGeneric(bool dilate,
|
||||
return false;
|
||||
}
|
||||
SkIRect bounds;
|
||||
input.getBounds(&bounds);
|
||||
bounds.offset(srcOffset);
|
||||
if (!this->applyCropRect(&bounds, ctx.ctm())) {
|
||||
if (!this->applyCropRect(ctx, proxy, input, &srcOffset, &bounds, &input)) {
|
||||
return false;
|
||||
}
|
||||
SkVector radius = SkVector::Make(SkIntToScalar(this->radius().width()),
|
||||
|
@ -42,10 +42,7 @@ bool SkOffsetImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source,
|
||||
}
|
||||
|
||||
SkIRect bounds;
|
||||
src.getBounds(&bounds);
|
||||
bounds.offset(srcOffset);
|
||||
|
||||
if (!applyCropRect(&bounds, ctx.ctm())) {
|
||||
if (!this->applyCropRect(ctx, src, srcOffset, &bounds)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -56,8 +56,7 @@ bool SkRectShaderImageFilter::onFilterImage(Proxy* proxy,
|
||||
SkBitmap* result,
|
||||
SkIPoint* offset) const {
|
||||
SkIRect bounds;
|
||||
source.getBounds(&bounds);
|
||||
if (!this->applyCropRect(&bounds, ctx.ctm())) {
|
||||
if (!this->applyCropRect(ctx, source, SkIPoint::Make(0, 0), &bounds)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -62,14 +62,13 @@ bool SkXfermodeImageFilter::onFilterImage(Proxy* proxy,
|
||||
}
|
||||
|
||||
SkIRect bounds, foregroundBounds;
|
||||
background.getBounds(&bounds);
|
||||
bounds.offset(backgroundOffset);
|
||||
foreground.getBounds(&foregroundBounds);
|
||||
foregroundBounds.offset(foregroundOffset);
|
||||
bounds.join(foregroundBounds);
|
||||
if (!applyCropRect(&bounds, ctx.ctm())) {
|
||||
if (!applyCropRect(ctx, foreground, foregroundOffset, &foregroundBounds)) {
|
||||
return false;
|
||||
}
|
||||
if (!applyCropRect(ctx, background, backgroundOffset, &bounds)) {
|
||||
return false;
|
||||
}
|
||||
bounds.join(foregroundBounds);
|
||||
|
||||
SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
|
||||
if (NULL == device.get()) {
|
||||
|
Loading…
Reference in New Issue
Block a user