Implement a resize image filter. This is needed for the "filterRes" feature in SVG filter effects, which specifies the required size for intermediate processing buffers. In order to make this work, we need to render the primitive at the given resolution (doable at the callsite in Blink), and then to resize the result to the actual on-screen size. The latter is where this filter comes in.

It simply applies a scaling factor (and the current CTM) to its input, and draws its input bitmap at that size.

R=reed@google.com

Committed: https://code.google.com/p/skia/source/detail?r=13077
Reverted: https://code.google.com/p/skia/source/detail?r=13078

BUG=

Review URL: https://codereview.chromium.org/136863006

git-svn-id: http://skia.googlecode.com/svn/trunk@13082 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
senorblanco@chromium.org 2014-01-15 04:49:18 +00:00
parent 32678d9a45
commit a612d4c513
7 changed files with 234 additions and 0 deletions

96
gm/resizeimagefilter.cpp Normal file
View File

@ -0,0 +1,96 @@
/*
* Copyright 2013 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 "SkColor.h"
#include "SkResizeImageFilter.h"
namespace skiagm {
class ResizeGM : public GM {
public:
ResizeGM() {
this->setBGColor(0x00000000);
}
protected:
virtual SkString onShortName() {
return SkString("resizeimagefilter");
}
void draw(SkCanvas* canvas,
const SkRect& rect,
const SkSize& deviceSize,
SkPaint::FilterLevel filterLevel) {
SkRect dstRect;
canvas->getTotalMatrix().mapRect(&dstRect, rect);
canvas->save();
SkScalar deviceScaleX = SkScalarDiv(deviceSize.width(), dstRect.width());
SkScalar deviceScaleY = SkScalarDiv(deviceSize.height(), dstRect.height());
canvas->translate(rect.x(), rect.y());
canvas->scale(deviceScaleX, deviceScaleY);
canvas->translate(-rect.x(), -rect.y());
SkAutoTUnref<SkImageFilter> imageFilter(
new SkResizeImageFilter(SkScalarInvert(deviceScaleX),
SkScalarInvert(deviceScaleY),
filterLevel));
SkPaint filteredPaint;
filteredPaint.setImageFilter(imageFilter.get());
canvas->saveLayer(&rect, &filteredPaint);
SkPaint paint;
paint.setColor(0xFF00FF00);
SkRect ovalRect = rect;
ovalRect.inset(SkIntToScalar(4), SkIntToScalar(4));
canvas->drawOval(ovalRect, paint);
canvas->restore(); // for saveLayer
canvas->restore();
}
virtual SkISize onISize() {
return make_isize(420, 100);
}
virtual void onDraw(SkCanvas* canvas) {
canvas->clear(0x00000000);
SkRect srcRect = SkRect::MakeWH(96, 96);
SkSize deviceSize = SkSize::Make(16, 16);
draw(canvas,
srcRect,
deviceSize,
SkPaint::kNone_FilterLevel);
canvas->translate(srcRect.width() + SkIntToScalar(10), 0);
draw(canvas,
srcRect,
deviceSize,
SkPaint::kLow_FilterLevel);
canvas->translate(srcRect.width() + SkIntToScalar(10), 0);
draw(canvas,
srcRect,
deviceSize,
SkPaint::kMedium_FilterLevel);
canvas->translate(srcRect.width() + SkIntToScalar(10), 0);
draw(canvas,
srcRect,
deviceSize,
SkPaint::kHigh_FilterLevel);
}
private:
typedef GM INHERITED;
};
//////////////////////////////////////////////////////////////////////////////
static GM* MyFactory(void*) { return new ResizeGM; }
static GMRegistry reg(MyFactory);
}

View File

@ -52,6 +52,7 @@
'<(skia_src_path)/effects/SkPixelXorXfermode.cpp',
'<(skia_src_path)/effects/SkPorterDuff.cpp',
'<(skia_src_path)/effects/SkRectShaderImageFilter.cpp',
'<(skia_src_path)/effects/SkResizeImageFilter.cpp',
'<(skia_src_path)/effects/SkStippleMaskFilter.cpp',
'<(skia_src_path)/effects/SkTableColorFilter.cpp',
'<(skia_src_path)/effects/SkTableMaskFilter.cpp',

View File

@ -111,6 +111,7 @@
'../gm/polygons.cpp',
'../gm/quadpaths.cpp',
'../gm/rects.cpp',
'../gm/resizeimagefilter.cpp',
'../gm/rrect.cpp',
'../gm/rrects.cpp',
'../gm/roundrects.cpp',

View File

@ -0,0 +1,51 @@
/*
* Copyright 2013 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef SkResizeImageFilter_DEFINED
#define SkResizeImageFilter_DEFINED
#include "SkImageFilter.h"
#include "SkScalar.h"
#include "SkRect.h"
#include "SkPoint.h"
#include "SkPaint.h"
/*! \class SkResizeImageFilter
Resampling image filter. This filter draws its source image resampled using the given scale
values.
*/
class SK_API SkResizeImageFilter : public SkImageFilter {
public:
/** Construct a (scaling-only) resampling image filter.
* @param sx The x scale parameter to apply when resizing.
* @param sy The y scale parameter to apply when resizing.
* @param filterLevel The quality of filtering to apply when scaling.
* @param input The input image filter. If NULL, the src bitmap
* passed to filterImage() is used instead.
*/
SkResizeImageFilter(SkScalar sx, SkScalar sy, SkPaint::FilterLevel filterLevel,
SkImageFilter* input = NULL);
virtual ~SkResizeImageFilter();
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkResizeImageFilter)
protected:
SkResizeImageFilter(SkFlattenableReadBuffer& buffer);
virtual void flatten(SkFlattenableWriteBuffer&) const SK_OVERRIDE;
virtual bool onFilterImage(Proxy*, const SkBitmap& src, const SkMatrix&,
SkBitmap* result, SkIPoint* loc) SK_OVERRIDE;
private:
SkScalar fSx, fSy;
SkPaint::FilterLevel fFilterLevel;
typedef SkImageFilter INHERITED;
};
#endif

View File

@ -0,0 +1,81 @@
/*
* Copyright 2013 The Android Open Source Project
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkResizeImageFilter.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkDevice.h"
#include "SkColorPriv.h"
#include "SkFlattenableBuffers.h"
#include "SkMatrix.h"
#include "SkRect.h"
SkResizeImageFilter::SkResizeImageFilter(SkScalar sx, SkScalar sy, SkPaint::FilterLevel filterLevel,
SkImageFilter* input)
: INHERITED(input),
fSx(sx),
fSy(sy),
fFilterLevel(filterLevel) {
}
SkResizeImageFilter::SkResizeImageFilter(SkFlattenableReadBuffer& buffer)
: INHERITED(1, buffer) {
fSx = buffer.readScalar();
fSy = buffer.readScalar();
fFilterLevel = static_cast<SkPaint::FilterLevel>(buffer.readInt());
}
void SkResizeImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeScalar(fSx);
buffer.writeScalar(fSy);
buffer.writeInt(fFilterLevel);
}
SkResizeImageFilter::~SkResizeImageFilter() {
}
bool SkResizeImageFilter::onFilterImage(Proxy* proxy,
const SkBitmap& source,
const SkMatrix& matrix,
SkBitmap* result,
SkIPoint* offset) {
SkBitmap src = source;
SkIPoint srcOffset = SkIPoint::Make(0, 0);
if (getInput(0) && !getInput(0)->filterImage(proxy, source, matrix, &src, &srcOffset)) {
return false;
}
SkRect dstRect;
SkIRect srcBounds, dstBounds;
src.getBounds(&srcBounds);
srcBounds.offset(srcOffset);
SkRect srcRect = SkRect::Make(srcBounds);
SkMatrix dstMatrix;
dstMatrix.setScale(fSx, fSy);
dstMatrix.mapRect(&dstRect, srcRect);
dstRect.roundOut(&dstBounds);
SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(dstBounds.width(), dstBounds.height()));
if (NULL == device.get()) {
return false;
}
SkCanvas canvas(device.get());
canvas.translate(-SkIntToScalar(dstBounds.fLeft), -SkIntToScalar(dstBounds.fTop));
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
paint.setFilterLevel(fFilterLevel);
canvas.concat(dstMatrix);
canvas.drawBitmap(src, srcRect.left(), srcRect.top(), &paint);
*result = device.get()->accessBitmap(false);
offset->fX = dstBounds.fLeft;
offset->fY = dstBounds.fTop;
return true;
}

View File

@ -52,6 +52,7 @@
#include "SkPerlinNoiseShader.h"
#include "SkPixelXorXfermode.h"
#include "SkRectShaderImageFilter.h"
#include "SkResizeImageFilter.h"
#include "SkStippleMaskFilter.h"
#include "SkTableColorFilter.h"
#include "SkTestImageFilters.h"
@ -89,6 +90,7 @@ static void InitializeFlattenables(int*) {
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPerlinNoiseShader)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPixelXorXfermode)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRectShaderImageFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkResizeImageFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkStippleMaskFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSumPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTileImageFilter)

View File

@ -52,6 +52,7 @@
#include "SkPerlinNoiseShader.h"
#include "SkPixelXorXfermode.h"
#include "SkRectShaderImageFilter.h"
#include "SkResizeImageFilter.h"
#include "SkStippleMaskFilter.h"
#include "SkTableColorFilter.h"
#include "SkTestImageFilters.h"
@ -89,6 +90,7 @@ static void InitializeFlattenables(int*) {
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPerlinNoiseShader)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkPixelXorXfermode)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkRectShaderImageFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkResizeImageFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkStippleMaskFilter)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSumPathEffect)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkTileImageFilter)