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 {
31 SkFlattenable::Register("SimpleOffsetFilter",
32 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
33 SimpleOffsetFilter::DeepCreateProc,
35 SimpleOffsetFilter::CreateProc,
37 SimpleOffsetFilter::GetFlattenableType());
40 static SkImageFilter* Create(SkScalar dx, SkScalar dy, SkImageFilter* input) {
41 return SkNEW_ARGS(SimpleOffsetFilter, (dx, dy, input));
44 virtual bool onFilterImage(Proxy* proxy, const SkBitmap& src, const Context& ctx,
45 SkBitmap* dst, SkIPoint* offset) const SK_OVERRIDE {
46 SkBitmap source = src;
47 SkImageFilter* input = getInput(0);
48 SkIPoint srcOffset = SkIPoint::Make(0, 0);
49 if (input && !input->filterImage(proxy, src, ctx, &source, &srcOffset)) {
54 if (!this->applyCropRect(ctx, proxy, source, &srcOffset, &bounds, &source)) {
58 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
59 SkCanvas canvas(device);
61 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
62 canvas.drawBitmap(source, fDX - bounds.left(), fDY - bounds.top(), &paint);
63 *dst = device->accessBitmap(false);
64 offset->fX += bounds.left();
65 offset->fY += bounds.top();
69 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SimpleOffsetFilter);
72 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
73 explicit SimpleOffsetFilter(SkReadBuffer& buffer)
74 : SkImageFilter(1, buffer) {
75 fDX = buffer.readScalar();
76 fDY = buffer.readScalar();
80 virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE {
81 this->INHERITED::flatten(buffer);
82 buffer.writeScalar(fDX);
83 buffer.writeScalar(fDY);
87 SimpleOffsetFilter(SkScalar dx, SkScalar dy, SkImageFilter* input)
88 : SkImageFilter(1, &input), fDX(dx), fDY(dy) {}
92 typedef SkImageFilter INHERITED;
95 static SimpleOffsetFilter::Registrar gReg;
97 SkFlattenable* SimpleOffsetFilter::CreateProc(SkReadBuffer& buffer) {
98 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
99 SkScalar dx = buffer.readScalar();
100 SkScalar dy = buffer.readScalar();
101 return Create(dx, dy, common.getInput(0));
104 class ImageFiltersGraphGM : public skiagm::GM {
106 ImageFiltersGraphGM() {}
109 virtual uint32_t onGetFlags() const SK_OVERRIDE {
110 return kSkipTiled_Flag;
113 virtual SkString onShortName() {
114 return SkString("imagefiltersgraph");
118 fBitmap.allocN32Pixels(100, 100);
119 SkCanvas canvas(fBitmap);
120 canvas.clear(0x00000000);
122 paint.setAntiAlias(true);
123 sk_tool_utils::set_portable_typeface(&paint);
124 paint.setColor(0xFFFFFFFF);
125 paint.setTextSize(SkIntToScalar(96));
126 const char* str = "e";
127 canvas.drawText(str, strlen(str), SkIntToScalar(20), SkIntToScalar(70), paint);
130 void drawClippedBitmap(SkCanvas* canvas, const SkBitmap& bitmap, const SkPaint& paint) {
132 canvas->clipRect(SkRect::MakeXYWH(0, 0,
133 SkIntToScalar(bitmap.width()), SkIntToScalar(bitmap.height())));
134 canvas->drawBitmap(bitmap, 0, 0, &paint);
138 virtual SkISize onISize() { return SkISize::Make(500, 150); }
140 virtual void onOnceBeforeDraw() {
144 virtual void onDraw(SkCanvas* canvas) {
145 canvas->clear(0x00000000);
147 SkAutoTUnref<SkImageFilter> bitmapSource(SkBitmapSource::Create(fBitmap));
148 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED,
149 SkXfermode::kSrcIn_Mode));
150 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(4.0f, 4.0f, bitmapSource));
151 SkAutoTUnref<SkImageFilter> erode(SkErodeImageFilter::Create(4, 4, blur));
152 SkAutoTUnref<SkImageFilter> color(SkColorFilterImageFilter::Create(cf, erode));
153 SkAutoTUnref<SkImageFilter> merge(SkMergeImageFilter::Create(blur, color));
156 paint.setImageFilter(merge);
157 canvas->drawPaint(paint);
158 canvas->translate(SkIntToScalar(100), 0);
161 SkAutoTUnref<SkImageFilter> morph(SkDilateImageFilter::Create(5, 5));
163 SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
164 0, SK_Scalar1, 0, 0, 0,
165 0, 0, SK_Scalar1, 0, 0,
168 SkAutoTUnref<SkColorFilter> matrixFilter(SkColorMatrixFilter::Create(matrix));
169 SkAutoTUnref<SkImageFilter> colorMorph(SkColorFilterImageFilter::Create(matrixFilter, morph));
170 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
171 SkAutoTUnref<SkImageFilter> blendColor(SkXfermodeImageFilter::Create(mode, colorMorph));
174 paint.setImageFilter(blendColor);
175 drawClippedBitmap(canvas, fBitmap, paint);
176 canvas->translate(SkIntToScalar(100), 0);
179 SkScalar matrix[20] = { SK_Scalar1, 0, 0, 0, 0,
180 0, SK_Scalar1, 0, 0, 0,
181 0, 0, SK_Scalar1, 0, 0,
183 SkAutoTUnref<SkColorMatrixFilter> matrixCF(SkColorMatrixFilter::Create(matrix));
184 SkAutoTUnref<SkImageFilter> matrixFilter(SkColorFilterImageFilter::Create(matrixCF));
185 SkAutoTUnref<SkImageFilter> offsetFilter(
186 SimpleOffsetFilter::Create(10.0f, 10.f, matrixFilter));
188 SkAutoTUnref<SkXfermode> arith(SkArithmeticMode::Create(0, SK_Scalar1, SK_Scalar1, 0));
189 SkAutoTUnref<SkXfermodeImageFilter> arithFilter(
190 SkXfermodeImageFilter::Create(arith, matrixFilter, offsetFilter));
193 paint.setImageFilter(arithFilter);
194 drawClippedBitmap(canvas, fBitmap, paint);
195 canvas->translate(SkIntToScalar(100), 0);
198 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(
199 SkIntToScalar(10), SkIntToScalar(10)));
201 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcIn_Mode));
202 SkImageFilter::CropRect cropRect(SkRect::MakeWH(SkIntToScalar(95), SkIntToScalar(100)));
203 SkAutoTUnref<SkImageFilter> blend(
204 SkXfermodeImageFilter::Create(mode, blur, NULL, &cropRect));
207 paint.setImageFilter(blend);
208 drawClippedBitmap(canvas, fBitmap, paint);
209 canvas->translate(SkIntToScalar(100), 0);
212 // Test that crop offsets are absolute, not relative to the parent's crop rect.
213 SkAutoTUnref<SkColorFilter> cf1(SkColorFilter::CreateModeFilter(SK_ColorBLUE,
214 SkXfermode::kSrcIn_Mode));
215 SkAutoTUnref<SkColorFilter> cf2(SkColorFilter::CreateModeFilter(SK_ColorGREEN,
216 SkXfermode::kSrcIn_Mode));
217 SkImageFilter::CropRect outerRect(SkRect::MakeXYWH(SkIntToScalar(10), SkIntToScalar(10),
218 SkIntToScalar(80), SkIntToScalar(80)));
219 SkImageFilter::CropRect innerRect(SkRect::MakeXYWH(SkIntToScalar(20), SkIntToScalar(20),
220 SkIntToScalar(60), SkIntToScalar(60)));
221 SkAutoTUnref<SkImageFilter> color1(SkColorFilterImageFilter::Create(cf1, NULL, &outerRect));
222 SkAutoTUnref<SkImageFilter> color2(SkColorFilterImageFilter::Create(cf2, color1, &innerRect));
225 paint.setImageFilter(color2);
226 paint.setColor(0xFFFF0000);
227 canvas->drawRect(SkRect::MakeXYWH(0, 0, 100, 100), paint);
228 canvas->translate(SkIntToScalar(100), 0);
233 typedef GM INHERITED;
237 ///////////////////////////////////////////////////////////////////////////////
239 static skiagm::GM* MyFactory(void*) { return new ImageFiltersGraphGM; }
240 static skiagm::GMRegistry reg(MyFactory);