1 /*
2  * Copyright 2014 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 #include "sk_tool_utils.h"
10 #include "SkCanvas.h"
11 #include "SkColorFilter.h"
12 #include "SkColorPriv.h"
13 #include "SkShader.h"
14 
15 #include "SkBlurImageFilter.h"
16 #include "SkColorMatrixFilter.h"
17 #include "SkDisplacementMapEffect.h"
18 #include "SkDropShadowImageFilter.h"
19 #include "SkGradientShader.h"
20 #include "SkImageSource.h"
21 #include "SkMorphologyImageFilter.h"
22 #include "SkColorFilterImageFilter.h"
23 #include "SkLightingImageFilter.h"
24 #include "SkMergeImageFilter.h"
25 #include "SkOffsetImageFilter.h"
26 #include "SkPoint3.h"
27 #include "SkSurface.h"
28 
29 namespace {
30 
31 void make_checkerboard(SkBitmap* bitmap);
32 sk_sp<SkImage> make_gradient_circle(int width, int height);
33 void draw(SkCanvas* canvas, const SkBitmap& bitmap, const SkRect& rect,
34                  sk_sp<SkImageFilter> filter);
35 
36 };
37 
38 ///////////////////////////////////////////////////////////////////////////////
39 
40 DEF_SIMPLE_GM(imagefilterscropexpand, canvas, 730, 650) {
41     SkImageFilter::CropRect cropRect(
42         SkRect::Make(SkIRect::MakeXYWH(10, 10, 44, 44)),
43         SkImageFilter::CropRect::kHasAll_CropEdge);
44 
45     sk_sp<SkImage> gradientCircle(make_gradient_circle(64, 64));
46     SkBitmap checkerboard;
47     make_checkerboard(&checkerboard);
48 
49     sk_sp<SkImageFilter> gradientCircleSource(SkImageSource::Make(std::move(gradientCircle)));
50     sk_sp<SkImageFilter> noopCropped(SkOffsetImageFilter::Make(0, 0, nullptr, &cropRect));
51     // This color matrix saturates the green component but only partly increases the opacity.
52     // For the opaque checkerboard, the opacity boost doesn't matter but it does impact the
53     // area outside the checkerboard.
54     SkScalar matrix[20] = { 1, 0, 0, 0, 0,
55                             0, 1, 0, 0, 255,
56                             0, 0, 1, 0, 0,
57                             0, 0, 0, 1, 32 };
58     sk_sp<SkColorFilter> cfAlphaTrans(SkColorFilter::MakeMatrixFilterRowMajor255(matrix));
59 
60     SkRect r = SkRect::MakeWH(SkIntToScalar(64), SkIntToScalar(64));
61     SkScalar MARGIN = SkIntToScalar(12);
62 
63     SkPoint3 pointLocation = SkPoint3::Make(0, 0, SkIntToScalar(10));
64     SkScalar kd = SkIntToScalar(2);
65     SkScalar surfaceScale = SkIntToScalar(1);
66     SkIRect bounds;
67     r.roundOut(&bounds);
68 
69     SkPaint paint;
70     canvas->translate(MARGIN, MARGIN);
71     for (int outset = -15; outset <= 20; outset += 5) {
72         canvas->save();
73         SkRect rect = cropRect.rect();
74         rect.outset(SkIntToScalar(outset),
75                     SkIntToScalar(outset));
76         SkImageFilter::CropRect bigRect(rect, SkImageFilter::CropRect::kHasAll_CropEdge);
77 
78         draw(canvas, checkerboard, rect, SkColorFilterImageFilter::Make(cfAlphaTrans,
79                                                                         noopCropped,
80                                                                         &bigRect));
81 
82         draw(canvas, checkerboard, rect, SkBlurImageFilter::Make(0.3f, 0.3f,
83                                                                  noopCropped,
84                                                                  &bigRect));
85 
86         draw(canvas, checkerboard, rect, SkBlurImageFilter::Make(8.0f, 8.0f,
87                                                                  noopCropped,
88                                                                  &bigRect));
89 
90         draw(canvas, checkerboard, rect, SkDilateImageFilter::Make(2, 2,
91                                                                    noopCropped,
92                                                                    &bigRect));
93 
94         draw(canvas, checkerboard, rect, SkErodeImageFilter::Make(2, 2,
95                                                                   noopCropped,
96                                                                   &bigRect));
97 
98         draw(canvas, checkerboard, rect,
99              SkDropShadowImageFilter::Make(
100                                 SkIntToScalar(10),
101                                 SkIntToScalar(10),
102                                 SkIntToScalar(3),
103                                 SkIntToScalar(3),
104                                 SK_ColorBLUE,
105                                 SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode,
106                                 noopCropped,
107                                 &bigRect));
108 
109         draw(canvas, checkerboard, rect,
110              SkDisplacementMapEffect::Make(SkDisplacementMapEffect::kR_ChannelSelectorType,
111                                            SkDisplacementMapEffect::kR_ChannelSelectorType,
112                                            SkIntToScalar(12),
113                                            gradientCircleSource,
114                                            noopCropped,
115                                            &bigRect));
116 
117         draw(canvas, checkerboard, rect,
118              SkOffsetImageFilter::Make(SkIntToScalar(-8), SkIntToScalar(16),
119                                        noopCropped,
120                                        &bigRect));
121 
122         draw(canvas, checkerboard, rect,
123              SkLightingImageFilter::MakePointLitDiffuse(pointLocation,
124                                                         SK_ColorWHITE,
125                                                         surfaceScale,
126                                                         kd,
127                                                         noopCropped,
128                                                         &bigRect));
129 
130         canvas->restore();
131         canvas->translate(0, SkIntToScalar(80));
132     }
133 }
134 
135 namespace {
136     void make_checkerboard(SkBitmap* bitmap) {
137         bitmap->allocN32Pixels(64, 64);
138         SkCanvas canvas(*bitmap);
139         canvas.clear(0xFFFF0000);
140         SkPaint darkPaint;
141         darkPaint.setColor(sk_tool_utils::color_to_565(0xFF404040));
142         SkPaint lightPaint;
143         lightPaint.setColor(sk_tool_utils::color_to_565(0xFFA0A0A0));
144         for (int y = 8; y < 48; y += 16) {
145             for (int x = 8; x < 48; x += 16) {
146                 canvas.save();
147                 canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
148                 canvas.drawRect(SkRect::MakeXYWH(0, 0, 8, 8), darkPaint);
149                 canvas.drawRect(SkRect::MakeXYWH(8, 0, 8, 8), lightPaint);
150                 canvas.drawRect(SkRect::MakeXYWH(0, 8, 8, 8), lightPaint);
151                 canvas.drawRect(SkRect::MakeXYWH(8, 8, 8, 8), darkPaint);
152                 canvas.restore();
153             }
154         }
155     }
156 
157     sk_sp<SkImage> make_gradient_circle(int width, int height) {
158         SkScalar x = SkIntToScalar(width / 2);
159         SkScalar y = SkIntToScalar(height / 2);
160         SkScalar radius = SkMinScalar(x, y) * 0.8f;
161         auto surface(SkSurface::MakeRasterN32Premul(width, height));
162         SkCanvas* canvas = surface->getCanvas();
163         canvas->clear(0x00000000);
164         SkColor colors[2];
165         colors[0] = SK_ColorWHITE;
166         colors[1] = SK_ColorBLACK;
167         SkPaint paint;
168         paint.setShader(SkGradientShader::MakeRadial(SkPoint::Make(x, y), radius, colors, nullptr,
169                                                      2, SkShader::kClamp_TileMode));
170         canvas->drawCircle(x, y, radius, paint);
171 
172         return surface->makeImageSnapshot();
173     }
174 
175     void draw(SkCanvas* canvas, const SkBitmap& bitmap, const SkRect& rect,
176                      sk_sp<SkImageFilter> filter) {
177         SkPaint paint;
178         paint.setImageFilter(std::move(filter));
179         canvas->saveLayer(&rect, &paint);
180         canvas->drawBitmap(bitmap, 0, 0);
181         canvas->restore();
182 
183         SkPaint strokePaint;
184         strokePaint.setColor(0xFFFF0000);
185         strokePaint.setStyle(SkPaint::kStroke_Style);
186         canvas->drawRect(rect, strokePaint);
187 
188         canvas->translate(SkIntToScalar(80), 0);
189     }
190 };
191