1
2#include "SkTestImageFilters.h"
3#include "SkCanvas.h"
4#include "SkDevice.h"
5#include "SkReadBuffer.h"
6#include "SkWriteBuffer.h"
7
8// Simple helper canvas that "takes ownership" of the provided device, so that
9// when this canvas goes out of scope, so will its device. Could be replaced
10// with the following:
11//
12//  SkCanvas canvas(device);
13//  SkAutoTUnref<SkBaseDevice> aur(device);
14//
15class OwnDeviceCanvas : public SkCanvas {
16public:
17    OwnDeviceCanvas(SkBaseDevice* device) : SkCanvas(device) {
18        SkSafeUnref(device);
19    }
20};
21
22///////////////////////////////////////////////////////////////////////////////
23
24bool SkDownSampleImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
25                                            const Context&,
26                                            SkBitmap* result, SkIPoint*) const {
27    SkScalar scale = fScale;
28    if (scale > SK_Scalar1 || scale <= 0) {
29        return false;
30    }
31
32    int dstW = SkScalarRoundToInt(src.width() * scale);
33    int dstH = SkScalarRoundToInt(src.height() * scale);
34    if (dstW < 1) {
35        dstW = 1;
36    }
37    if (dstH < 1) {
38        dstH = 1;
39    }
40
41    SkBitmap tmp;
42
43    // downsample
44    {
45        SkBaseDevice* dev = proxy->createDevice(dstW, dstH);
46        if (NULL == dev) {
47            return false;
48        }
49        OwnDeviceCanvas canvas(dev);
50        SkPaint paint;
51
52        paint.setFilterLevel(SkPaint::kLow_FilterLevel);
53        canvas.scale(scale, scale);
54        canvas.drawBitmap(src, 0, 0, &paint);
55        tmp = dev->accessBitmap(false);
56    }
57
58    // upscale
59    {
60        SkBaseDevice* dev = proxy->createDevice(src.width(), src.height());
61        if (NULL == dev) {
62            return false;
63        }
64        OwnDeviceCanvas canvas(dev);
65
66        SkRect r = SkRect::MakeWH(SkIntToScalar(src.width()),
67                                  SkIntToScalar(src.height()));
68        canvas.drawBitmapRect(tmp, NULL, r, NULL);
69        *result = dev->accessBitmap(false);
70    }
71    return true;
72}
73
74void SkDownSampleImageFilter::flatten(SkWriteBuffer& buffer) const {
75    this->INHERITED::flatten(buffer);
76
77    buffer.writeScalar(fScale);
78}
79
80SkDownSampleImageFilter::SkDownSampleImageFilter(SkReadBuffer& buffer)
81  : INHERITED(1, buffer) {
82    fScale = buffer.readScalar();
83    buffer.validate(SkScalarIsFinite(fScale));
84}
85