Implement a resize image filter. This is needed for the "filterRes" feature in SVG...
authorsenorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 15 Jan 2014 04:49:18 +0000 (04:49 +0000)
committersenorblanco@chromium.org <senorblanco@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Wed, 15 Jan 2014 04:49:18 +0000 (04:49 +0000)
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

gm/resizeimagefilter.cpp [new file with mode: 0644]
gyp/effects.gypi
gyp/gmslides.gypi
include/effects/SkResizeImageFilter.h [new file with mode: 0644]
src/effects/SkResizeImageFilter.cpp [new file with mode: 0644]
src/ports/SkGlobalInitialization_chromium.cpp
src/ports/SkGlobalInitialization_default.cpp

diff --git a/gm/resizeimagefilter.cpp b/gm/resizeimagefilter.cpp
new file mode 100644 (file)
index 0000000..fa407c4
--- /dev/null
@@ -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);
+
+}
index 21e02e4..9315c26 100644 (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',
index 8e50eb0..8069419 100644 (file)
     '../gm/polygons.cpp',
     '../gm/quadpaths.cpp',
     '../gm/rects.cpp',
+    '../gm/resizeimagefilter.cpp',
     '../gm/rrect.cpp',
     '../gm/rrects.cpp',
     '../gm/roundrects.cpp',
diff --git a/include/effects/SkResizeImageFilter.h b/include/effects/SkResizeImageFilter.h
new file mode 100644 (file)
index 0000000..d638555
--- /dev/null
@@ -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
diff --git a/src/effects/SkResizeImageFilter.cpp b/src/effects/SkResizeImageFilter.cpp
new file mode 100644 (file)
index 0000000..4d70090
--- /dev/null
@@ -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;
+}
index d402c02..79ed46c 100644 (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)
index d402c02..79ed46c 100644 (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)