1 /*
2 * Copyright 2013 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/gm.h"
9 #include "include/core/SkBitmap.h"
10 #include "include/core/SkBlendMode.h"
11 #include "include/core/SkCanvas.h"
12 #include "include/core/SkColor.h"
13 #include "include/core/SkColorFilter.h"
14 #include "include/core/SkFont.h"
15 #include "include/core/SkImageFilter.h"
16 #include "include/core/SkPaint.h"
17 #include "include/core/SkRRect.h"
18 #include "include/core/SkRect.h"
19 #include "include/core/SkRefCnt.h"
20 #include "include/core/SkScalar.h"
21 #include "include/core/SkTypeface.h"
22 #include "include/core/SkTypes.h"
23 #include "include/effects/SkImageFilters.h"
24 #include "include/utils/SkTextUtils.h"
25 #include "tools/ToolUtils.h"
26 #include "tools/fonts/FontToolUtils.h"
27
28 #include <utility>
29
30 ///////////////////////////////////////////////////////////////////////////////
31
draw_paint(SkCanvas * canvas,const SkRect & r,sk_sp<SkImageFilter> imf)32 static void draw_paint(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
33 SkPaint paint;
34 paint.setImageFilter(std::move(imf));
35 paint.setColor(SK_ColorBLACK);
36 canvas->save();
37 canvas->clipRect(r);
38 canvas->drawPaint(paint);
39 canvas->restore();
40 }
41
draw_path(SkCanvas * canvas,const SkRect & r,sk_sp<SkImageFilter> imf)42 static void draw_path(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
43 SkPaint paint;
44 paint.setColor(SK_ColorGREEN);
45 paint.setImageFilter(std::move(imf));
46 paint.setAntiAlias(true);
47 canvas->save();
48 canvas->clipRect(r);
49 canvas->drawCircle(r.centerX(), r.centerY(), r.width()/3, paint);
50 canvas->restore();
51 }
52
draw_text(SkCanvas * canvas,const SkRect & r,sk_sp<SkImageFilter> imf)53 static void draw_text(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
54 SkPaint paint;
55 paint.setImageFilter(std::move(imf));
56 paint.setColor(SK_ColorGREEN);
57 paint.setAntiAlias(true);
58
59 SkFont font(ToolUtils::DefaultPortableTypeface(), r.height() / 2);
60 canvas->save();
61 canvas->clipRect(r);
62 SkTextUtils::DrawString(canvas, "Text", r.centerX(), r.centerY(), font, paint, SkTextUtils::kCenter_Align);
63 canvas->restore();
64 }
65
draw_bitmap(SkCanvas * canvas,const SkRect & r,sk_sp<SkImageFilter> imf)66 static void draw_bitmap(SkCanvas* canvas, const SkRect& r, sk_sp<SkImageFilter> imf) {
67 SkPaint paint;
68
69 SkIRect bounds;
70 r.roundOut(&bounds);
71
72 auto surf = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(bounds.width(), bounds.height()));
73 draw_path(surf->getCanvas(), r, nullptr);
74
75 paint.setImageFilter(std::move(imf));
76 canvas->save();
77 canvas->clipRect(r);
78 surf->draw(canvas, 0, 0, SkSamplingOptions(), &paint);
79 canvas->restore();
80 }
81
82 ///////////////////////////////////////////////////////////////////////////////
83
84 DEF_SIMPLE_GM(dropshadowimagefilter, canvas, 400, 656) {
85 void (*drawProc[])(SkCanvas*, const SkRect&, sk_sp<SkImageFilter>) = {
86 draw_bitmap, draw_path, draw_paint, draw_text
87 };
88
89 sk_sp<SkColorFilter> cf(SkColorFilters::Blend(SK_ColorMAGENTA, SkBlendMode::kSrcIn));
90 sk_sp<SkImageFilter> cfif(SkImageFilters::ColorFilter(std::move(cf), nullptr));
91 SkIRect cropRect = SkIRect::MakeXYWH(10, 10, 44, 44);
92 SkIRect bogusRect = SkIRect::MakeXYWH(-100, -100, 10, 10);
93
94 sk_sp<SkColorSpace> spinCS = SkColorSpace::MakeSRGB()->makeColorSpin();
95 sk_sp<SkImageFilter> filters[] = {
96 nullptr,
97 SkImageFilters::DropShadow(7.0f, 0.0f, 0.0f, 3.0f, SK_ColorBLUE, nullptr),
98 SkImageFilters::DropShadow(0.0f, 7.0f, 3.0f, 0.0f, SK_ColorBLUE, nullptr),
99 SkImageFilters::DropShadow(7.0f, 7.0f, 3.0f, 3.0f, SK_ColorBLUE, nullptr),
100 SkImageFilters::DropShadow(7.0f, 7.0f, 3.0f, 3.0f, SK_ColorBLUE, std::move(cfif)),
101 SkImageFilters::DropShadow(
102 7.0f, 7.0f, 3.0f, 3.0f, SkColors::kGreen, spinCS, nullptr, &cropRect),
103 SkImageFilters::DropShadow(7.0f, 7.0f, 3.0f, 3.0f, SK_ColorBLUE, nullptr, &bogusRect),
104 SkImageFilters::DropShadowOnly(7.0f, 7.0f, 3.0f, 3.0f, SK_ColorBLUE, nullptr),
105 };
106
107 SkRect r = SkRect::MakeWH(SkIntToScalar(64), SkIntToScalar(64));
108 SkScalar MARGIN = SkIntToScalar(16);
109 SkScalar DX = r.width() + MARGIN;
110 SkScalar DY = r.height() + MARGIN;
111
112 canvas->translate(MARGIN, MARGIN);
113 for (size_t j = 0; j < std::size(drawProc); ++j) {
114 canvas->save();
115 for (size_t i = 0; i < std::size(filters); ++i) {
116 drawProc[j](canvas, r, filters[i]);
117 canvas->translate(0, DY);
118 }
119 canvas->restore();
120 canvas->translate(DX, 0);
121 }
122 }
123
124 DEF_SIMPLE_GM(dropshadow_pseudopersp, canvas, 155, 155) {
125 canvas->clear(SK_ColorLTGRAY);
126 canvas->concat(SkM44{0.5f, 0.f, 0.f, -75.f,
127 0.f, 0.5f, 0.f, -30.f,
128 0.f, 0.f, 1.f, 0.f,
129 0.f, 0.f, 0.f, 1.f});
130 // This 4x4 matrtix technically has perspective, but it only impacts the Z values and the
131 // projection doesn't appear to have any distortion. However, the projected coordinates have
132 // Z values very different from 0. When inversing the device bounds with an assumed Z=0, the
133 // layer bounds end up empty. This GM ensures layer mapping calculations don't discard it.
134 canvas->concat(SkM44{1360.f, 0.f, 275.4f, 294100.f,
135 0.f, 1360.f, 489.6f, 98344.f,
136 0.f, 0.f, -0.51f, -2180.67f,
137 0.f, 0.f, 0.51f, 2181.67f});
138
139 SkRect layerBounds{42.5f, 42.5f, 457.5f, 457.5f};
140 SkPaint layerPaint;
141 layerPaint.setImageFilter(SkImageFilters::DropShadow(
142 /*dx=*/30.f, /*dy=*/30.f,
143 /*sigmaX=*/12.f, /*sigmaY=*/12.f,
144 /*color=*/{0.14902f, 0.215686f, 0.329412f, 0.666667f},
145 /*colorSpace=*/nullptr,
146 /*input=*/nullptr));
147 canvas->saveLayer(&layerBounds, &layerPaint);
148
149 SkRRect rrect = SkRRect::MakeRectXY({-250.f, -250.f, 250.f, 250.f}, 45.f, 45.f);
150 SkPaint rrectPaint;
151 rrectPaint.setColor4f(SkColors::kWhite);
152 rrectPaint.setAntiAlias(true);
153
154 canvas->concat(SkM44{0.83f, 0.f, 0.f, 250.f,
155 0.f, 0.83f, 0.f, 250.f,
156 0.f, 0.f, 1.f, 0.f,
157 0.f, 0.f, 0.f, 1.f});
158 canvas->drawRRect(rrect, rrectPaint);
159 canvas->restore();
160
161 canvas->concat(SkM44{0.83f, 0.f, 0.f, 250.f,
162 0.f, 0.83f, 0.f, 250.f,
163 0.f, 0.f, 1.f, 0.f,
164 0.f, 0.f, 0.f, 1.f});
165
166 rrectPaint.setColor4f(SkColors::kBlack);
167 rrectPaint.setStyle(SkPaint::kStroke_Style);
168 canvas->drawRRect(rrect, rrectPaint);
169 }
170