imagefiltersgraph.cpp revision bbfe4541ef154696313374de2130b1ac90e28482
1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gm.h"
9
10#include "SkArithmeticMode.h"
11#include "SkBitmapSource.h"
12#include "SkBlurImageFilter.h"
13#include "SkColorFilter.h"
14#include "SkColorMatrixFilter.h"
15#include "SkColorFilterImageFilter.h"
16#include "SkFlattenableBuffers.h"
17#include "SkMergeImageFilter.h"
18#include "SkMorphologyImageFilter.h"
19#include "SkOnce.h"
20#include "SkXfermodeImageFilter.h"
21
22#include "SkTestImageFilters.h"
23
24///////////////////////////////////////////////////////////////////////////////
25
26namespace {
27// More closely models how Blink's OffsetFilter works as of 10/23/13. SkOffsetImageFilter doesn't
28// perform a draw and this one does.
29class SimpleOffsetFilter : public SkImageFilter {
30public:
31    SimpleOffsetFilter(SkScalar dx, SkScalar dy, SkImageFilter* input)
32    : SkImageFilter(input), fDX(dx), fDY(dy) {}
33
34    virtual bool onFilterImage(Proxy* proxy, const SkBitmap& src, const SkMatrix& ctm,
35                               SkBitmap* dst, SkIPoint* offset) SK_OVERRIDE {
36        SkBitmap source = src;
37        SkImageFilter* input = getInput(0);
38        SkIPoint srcOffset = SkIPoint::Make(0, 0);
39        if (NULL != input && !input->filterImage(proxy, src, ctm, &source, &srcOffset)) {
40            return false;
41        }
42
43        SkIRect bounds;
44        source.getBounds(&bounds);
45
46        if (!this->applyCropRect(&bounds, ctm)) {
47            return false;
48        }
49
50        SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
51        SkCanvas canvas(device);
52        SkPaint paint;
53        paint.setXfermodeMode(SkXfermode::kSrc_Mode);
54        canvas.drawBitmap(source, fDX - bounds.left(), fDY - bounds.top(), &paint);
55        *dst = device->accessBitmap(false);
56        offset->fX += bounds.left();
57        offset->fY += bounds.top();
58        return true;
59    }
60
61    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SimpleOffsetFilter);
62
63protected:
64    explicit SimpleOffsetFilter(SkFlattenableReadBuffer& buffer)
65    : SkImageFilter(buffer) {
66        fDX = buffer.readScalar();
67        fDY = buffer.readScalar();
68    }
69
70    virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
71        this->SkImageFilter::flatten(buffer);
72        buffer.writeScalar(fDX);
73        buffer.writeScalar(fDY);
74    }
75
76private:
77    SkScalar fDX, fDY;
78};
79}
80
81static void init_flattenable(int*) {
82    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SimpleOffsetFilter)
83}
84
85class ImageFiltersGraphGM : public skiagm::GM {
86public:
87    ImageFiltersGraphGM() : fInitialized(false) {
88        int dummy;
89        SK_DECLARE_STATIC_ONCE(once);
90        SkOnce(&once, init_flattenable, &dummy);
91    }
92
93protected:
94    virtual SkString onShortName() {
95        return SkString("imagefiltersgraph");
96    }
97
98    void make_bitmap() {
99        fBitmap.setConfig(SkBitmap::kARGB_8888_Config, 100, 100);
100        fBitmap.allocPixels();
101        SkBitmapDevice device(fBitmap);
102        SkCanvas canvas(&device);
103        canvas.clear(0x00000000);
104        SkPaint paint;
105        paint.setAntiAlias(true);
106        paint.setColor(0xFFFFFFFF);
107        paint.setTextSize(SkIntToScalar(96));
108        const char* str = "e";
109        canvas.drawText(str, strlen(str), SkIntToScalar(20), SkIntToScalar(70), paint);
110    }
111
112    virtual SkISize onISize() { return SkISize::Make(500, 150); }
113
114    virtual void onDraw(SkCanvas* canvas) {
115        if (!fInitialized) {
116            this->make_bitmap();
117            fInitialized = true;
118        }
119        canvas->clear(0x00000000);
120        {
121            SkAutoTUnref<SkImageFilter> bitmapSource(new SkBitmapSource(fBitmap));
122            SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED,
123                                                         SkXfermode::kSrcIn_Mode));
124            SkAutoTUnref<SkImageFilter> blur(new SkBlurImageFilter(4.0f, 4.0f, bitmapSource));
125            SkAutoTUnref<SkImageFilter> erode(new SkErodeImageFilter(4, 4, blur));
126            SkAutoTUnref<SkImageFilter> color(SkColorFilterImageFilter::Create(cf, erode));
127            SkAutoTUnref<SkImageFilter> merge(new SkMergeImageFilter(blur, color));
128
129            SkPaint paint;
130            paint.setImageFilter(merge);
131            canvas->drawPaint(paint);
132        }
133        {
134            SkAutoTUnref<SkImageFilter> morph(new SkDilateImageFilter(5, 5));
135
136            SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
137                                    0, SK_Scalar1, 0, 0, 0,
138                                    0, 0, SK_Scalar1, 0, 0,
139                                    0, 0, 0, SkFloatToScalar(0.5f), 0 };
140
141            SkAutoTUnref<SkColorFilter> matrixFilter(new SkColorMatrixFilter(matrix));
142            SkAutoTUnref<SkImageFilter> colorMorph(SkColorFilterImageFilter::Create(matrixFilter, morph));
143            SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
144            SkAutoTUnref<SkImageFilter> blendColor(new SkXfermodeImageFilter(mode, colorMorph));
145
146            SkPaint paint;
147            paint.setImageFilter(blendColor);
148            canvas->drawBitmap(fBitmap, 100, 0, &paint);
149        }
150        {
151            SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
152                                    0, SK_Scalar1, 0, 0, 0,
153                                    0, 0, SK_Scalar1, 0, 0,
154                                    0, 0, 0, SkFloatToScalar(0.5f), 0 };
155            SkColorMatrixFilter matrixCF(matrix);
156            SkAutoTUnref<SkImageFilter> matrixFilter(SkColorFilterImageFilter::Create(&matrixCF));
157            SimpleOffsetFilter offsetFilter(SkIntToScalar(10), SkIntToScalar(10), matrixFilter);
158
159            SkAutoTUnref<SkXfermode> arith(SkArithmeticMode::Create(0, SK_Scalar1, SK_Scalar1, 0));
160            SkXfermodeImageFilter arithFilter(arith, matrixFilter, &offsetFilter);
161
162            SkPaint paint;
163            paint.setImageFilter(&arithFilter);
164            canvas->drawSprite(fBitmap, 200, 0, &paint);
165        }
166    }
167
168private:
169    typedef GM INHERITED;
170    SkBitmap fBitmap;
171    bool fInitialized;
172};
173
174///////////////////////////////////////////////////////////////////////////////
175
176static skiagm::GM* MyFactory(void*) { return new ImageFiltersGraphGM; }
177static skiagm::GMRegistry reg(MyFactory);
178