2 * Copyright 2012 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
10 #include "SkArithmeticMode.h"
12 #include "SkBitmapSource.h"
13 #include "SkBlurImageFilter.h"
14 #include "SkColorFilter.h"
15 #include "SkColorFilterImageFilter.h"
16 #include "SkColorMatrixFilter.h"
17 #include "SkReadBuffer.h"
18 #include "SkWriteBuffer.h"
19 #include "SkMergeImageFilter.h"
20 #include "SkMorphologyImageFilter.h"
21 #include "SkTestImageFilters.h"
22 #include "SkXfermodeImageFilter.h"
24 // More closely models how Blink's OffsetFilter works as of 10/23/13. SkOffsetImageFilter doesn't
25 // perform a draw and this one does.
26 class SimpleOffsetFilter : public SkImageFilter {
28 static SkImageFilter* Create(SkScalar dx, SkScalar dy, SkImageFilter* input) {
29 return SkNEW_ARGS(SimpleOffsetFilter, (dx, dy, input));
32 virtual bool onFilterImage(Proxy* proxy, const SkBitmap& src, const Context& ctx,
33 SkBitmap* dst, SkIPoint* offset) const SK_OVERRIDE {
34 SkBitmap source = src;
35 SkImageFilter* input = getInput(0);
36 SkIPoint srcOffset = SkIPoint::Make(0, 0);
37 if (NULL != input && !input->filterImage(proxy, src, ctx, &source, &srcOffset)) {
42 if (!this->applyCropRect(ctx, proxy, source, &srcOffset, &bounds, &source)) {
46 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
47 SkCanvas canvas(device);
49 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
50 canvas.drawBitmap(source, fDX - bounds.left(), fDY - bounds.top(), &paint);
51 *dst = device->accessBitmap(false);
52 offset->fX += bounds.left();
53 offset->fY += bounds.top();
57 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SimpleOffsetFilter);
60 explicit SimpleOffsetFilter(SkReadBuffer& buffer)
61 : SkImageFilter(1, buffer) {
62 fDX = buffer.readScalar();
63 fDY = buffer.readScalar();
66 virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
67 this->SkImageFilter::flatten(buffer);
68 buffer.writeScalar(fDX);
69 buffer.writeScalar(fDY);
73 SimpleOffsetFilter(SkScalar dx, SkScalar dy, SkImageFilter* input)
74 : SkImageFilter(1, &input), fDX(dx), fDY(dy) {}
79 SkFlattenable::Registrar registrar("SimpleOffsetFilter",
80 SimpleOffsetFilter::CreateProc,
81 SimpleOffsetFilter::GetFlattenableType());
83 class ImageFiltersGraphGM : public skiagm::GM {
85 ImageFiltersGraphGM() {}
88 virtual uint32_t onGetFlags() const SK_OVERRIDE {
89 return kSkipTiled_Flag;
92 virtual SkString onShortName() {
93 return SkString("imagefiltersgraph");
97 fBitmap.allocN32Pixels(100, 100);
98 SkCanvas canvas(fBitmap);
99 canvas.clear(0x00000000);
101 paint.setAntiAlias(true);
102 sk_tool_utils::set_portable_typeface(&paint);
103 paint.setColor(0xFFFFFFFF);
104 paint.setTextSize(SkIntToScalar(96));
105 const char* str = "e";
106 canvas.drawText(str, strlen(str), SkIntToScalar(20), SkIntToScalar(70), paint);
109 void drawClippedBitmap(SkCanvas* canvas, const SkBitmap& bitmap, const SkPaint& paint) {
111 canvas->clipRect(SkRect::MakeXYWH(0, 0,
112 SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())));
113 canvas->drawBitmap(bitmap, 0, 0, &paint);
117 virtual SkISize onISize() { return SkISize::Make(500, 150); }
119 virtual void onOnceBeforeDraw() {
123 virtual void onDraw(SkCanvas* canvas) {
124 canvas->clear(0x00000000);
126 SkAutoTUnref<SkImageFilter> bitmapSource(SkBitmapSource::Create(fBitmap));
127 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED,
128 SkXfermode::kSrcIn_Mode));
129 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(4.0f, 4.0f, bitmapSource));
130 SkAutoTUnref<SkImageFilter> erode(SkErodeImageFilter::Create(4, 4, blur));
131 SkAutoTUnref<SkImageFilter> color(SkColorFilterImageFilter::Create(cf, erode));
132 SkAutoTUnref<SkImageFilter> merge(SkMergeImageFilter::Create(blur, color));
135 paint.setImageFilter(merge);
136 canvas->drawPaint(paint);
137 canvas->translate(SkIntToScalar(100), 0);
140 SkAutoTUnref<SkImageFilter> morph(SkDilateImageFilter::Create(5, 5));
142 SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
143 0, SK_Scalar1, 0, 0, 0,
144 0, 0, SK_Scalar1, 0, 0,
147 SkAutoTUnref<SkColorFilter> matrixFilter(SkColorMatrixFilter::Create(matrix));
148 SkAutoTUnref<SkImageFilter> colorMorph(SkColorFilterImageFilter::Create(matrixFilter, morph));
149 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
150 SkAutoTUnref<SkImageFilter> blendColor(SkXfermodeImageFilter::Create(mode, colorMorph));
153 paint.setImageFilter(blendColor);
154 drawClippedBitmap(canvas, fBitmap, paint);
155 canvas->translate(SkIntToScalar(100), 0);
158 SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
159 0, SK_Scalar1, 0, 0, 0,
160 0, 0, SK_Scalar1, 0, 0,
162 SkAutoTUnref<SkColorMatrixFilter> matrixCF(SkColorMatrixFilter::Create(matrix));
163 SkAutoTUnref<SkImageFilter> matrixFilter(SkColorFilterImageFilter::Create(matrixCF));
164 SkAutoTUnref<SkImageFilter> offsetFilter(
165 SimpleOffsetFilter::Create(10.0f, 10.f, matrixFilter));
167 SkAutoTUnref<SkXfermode> arith(SkArithmeticMode::Create(0, SK_Scalar1, SK_Scalar1, 0));
168 SkAutoTUnref<SkXfermodeImageFilter> arithFilter(
169 SkXfermodeImageFilter::Create(arith, matrixFilter, offsetFilter));
172 paint.setImageFilter(arithFilter);
173 drawClippedBitmap(canvas, fBitmap, paint);
174 canvas->translate(SkIntToScalar(100), 0);
177 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(
178 SkIntToScalar(10), SkIntToScalar(10)));
180 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcIn_Mode));
181 SkImageFilter::CropRect cropRect(SkRect::MakeWH(SkIntToScalar(95), SkIntToScalar(100)));
182 SkAutoTUnref<SkImageFilter> blend(
183 SkXfermodeImageFilter::Create(mode, blur, NULL, &cropRect));
186 paint.setImageFilter(blend);
187 drawClippedBitmap(canvas, fBitmap, paint);
188 canvas->translate(SkIntToScalar(100), 0);
191 // Test that crop offsets are absolute, not relative to the parent's crop rect.
192 SkAutoTUnref<SkColorFilter> cf1(SkColorFilter::CreateModeFilter(SK_ColorBLUE,
193 SkXfermode::kSrcIn_Mode));
194 SkAutoTUnref<SkColorFilter> cf2(SkColorFilter::CreateModeFilter(SK_ColorGREEN,
195 SkXfermode::kSrcIn_Mode));
196 SkImageFilter::CropRect outerRect(SkRect::MakeXYWH(SkIntToScalar(10), SkIntToScalar(10),
197 SkIntToScalar(80), SkIntToScalar(80)));
198 SkImageFilter::CropRect innerRect(SkRect::MakeXYWH(SkIntToScalar(20), SkIntToScalar(20),
199 SkIntToScalar(60), SkIntToScalar(60)));
200 SkAutoTUnref<SkImageFilter> color1(SkColorFilterImageFilter::Create(cf1, NULL, &outerRect));
201 SkAutoTUnref<SkImageFilter> color2(SkColorFilterImageFilter::Create(cf2, color1, &innerRect));
204 paint.setImageFilter(color2);
205 paint.setColor(0xFFFF0000);
206 canvas->drawRect(SkRect::MakeXYWH(0, 0, 100, 100), paint);
207 canvas->translate(SkIntToScalar(100), 0);
212 typedef GM INHERITED;
216 ///////////////////////////////////////////////////////////////////////////////
218 static skiagm::GM* MyFactory(void*) { return new ImageFiltersGraphGM; }
219 static skiagm::GMRegistry reg(MyFactory);