blob: eca84958219ea4568f9f02e4f1f5ef509bdc8e05 [file] [log] [blame]
Robert Phillips568c9862016-10-11 10:18:18 -04001/*
2 * Copyright 2016 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"
Robert Phillipsa2cedff2017-03-28 11:59:48 -04009#include "SkColorFilter.h"
Robert Phillips568c9862016-10-11 10:18:18 -040010#include "SkGaussianEdgeShader.h"
Robert Phillipsa2cedff2017-03-28 11:59:48 -040011#include "SkRRect.h"
Robert Phillips568c9862016-10-11 10:18:18 -040012
13//#define VIZ 1
14
15#ifdef VIZ
16#include "SkStroke.h"
17
18static void draw_stroke(SkCanvas* canvas, const SkRRect& rr, const SkPaint& p, SkColor color) {
19 SkPath output;
20
21 if (SkPaint::kFill_Style == p.getStyle()) {
22 output.addRRect(rr);
23 } else {
24 SkPath input;
25 input.addRRect(rr);
26
27 SkStroke stroke(p);
28 stroke.strokePath(input, &output);
29 }
30
31 SkPaint paint;
32 paint.setStyle(SkPaint::kStroke_Style);
33 paint.setColor(color);
34
35 canvas->drawPath(output, paint);
36}
37
38static void extract_pts(const SkBitmap& bm, SkTDArray<SkPoint>* pts,
39 int xOff, int width) {
40 pts->rewind();
41
42 for (int x = 0; x < width; ++x) {
43 SkColor color = bm.getColor(xOff+x, 0);
44
45 pts->append()->set(SkIntToScalar(x), 255.0f-SkColorGetB(color));
46 if (x > 0 && x < width-1) {
47 pts->append()->set(SkIntToScalar(x), 255.0f-SkColorGetB(color));
48 }
49 }
50}
51
52static void draw_row(SkCanvas* canvas, int row, int width) {
53 SkPaint paint;
54 paint.setAntiAlias(true);
55
56 SkBitmap readback;
57
58 if (!canvas->readPixels(SkIRect::MakeXYWH(0, row, width, 1), &readback)) {
59 return;
60 }
61
62 SkTDArray<SkPoint> pts;
63 pts.setReserve(width/3);
64
65 extract_pts(readback, &pts, 0, width/3);
66 paint.setColor(SK_ColorRED);
67 canvas->drawPoints(SkCanvas::kLines_PointMode, pts.count(), pts.begin(), paint);
68
69 extract_pts(readback, &pts, width/3, width/3);
70 paint.setColor(SK_ColorGREEN);
71 canvas->drawPoints(SkCanvas::kLines_PointMode, pts.count(), pts.begin(), paint);
72
73 extract_pts(readback, &pts, 2*width/3, width/3);
74 paint.setColor(SK_ColorBLUE);
75 canvas->drawPoints(SkCanvas::kLines_PointMode, pts.count(), pts.begin(), paint);
76}
77#endif
78
79namespace skiagm {
80
81// This GM exercises the SkGaussianEdgeShader.
82// It draws three columns showing filled, stroked, and stroke and filled rendering.
83// It draws three rows showing a blur radius smaller than, equal to
84// and, finally, double the RRect's corner radius
85// In VIZ mode an extra column is drawn showing the blur ramps (they should all line up).
86class GaussianEdgeGM : public GM {
87public:
88 GaussianEdgeGM() {
89 this->setBGColor(SK_ColorWHITE);
90 }
91
92protected:
93
94 SkString onShortName() override {
95 return SkString("gaussianedge");
96 }
97
98 SkISize onISize() override {
99 int numCols = kNumBaseCols;
100#ifdef VIZ
101 numCols++;
102#endif
103
104 return SkISize::Make(kPad + numCols*(kCellWidth+kPad),
105 kPad + kNumRows*(kCellWidth+kPad));
106 }
107
108 static void DrawRow(SkCanvas* canvas, int blurRad, int midLine) {
109 SkAutoCanvasRestore acr(canvas, true);
110
111 SkRRect rrects[kNumBaseCols];
112 SkPaint paints[kNumBaseCols];
113
114 {
115 const SkRect r = SkRect::MakeIWH(kRRSize, kRRSize);
116 const SkRRect baseRR = SkRRect::MakeRectXY(r,
117 SkIntToScalar(kRRRad),
118 SkIntToScalar(kRRRad));
119
120 SkPaint basePaint;
121 basePaint.setAntiAlias(true);
Robert Phillips568c9862016-10-11 10:18:18 -0400122 basePaint.setColor(SkColorSetARGB(255, (4 * blurRad) >> 8, (4 * blurRad) & 0xff, 0));
Robert Phillipsa2cedff2017-03-28 11:59:48 -0400123 basePaint.setShader(SkGaussianEdgeShader::Make());
124 basePaint.setColorFilter(SkColorFilter::MakeModeFilter(SK_ColorRED,
125 SkBlendMode::kModulate));
Robert Phillips568c9862016-10-11 10:18:18 -0400126
127 //----
128 paints[0] = basePaint;
129 rrects[0] = baseRR;
130
131 //----
132 paints[1] = basePaint;
133 paints[1].setStyle(SkPaint::kStroke_Style);
134
135 rrects[1] = baseRR;
136 if (blurRad/2.0f < kRRRad) {
137 rrects[1].inset(blurRad/2.0f, blurRad/2.0f);
138 paints[1].setStrokeWidth(SkIntToScalar(blurRad));
139 } else {
140 SkScalar inset = kRRRad - 0.5f;
141 rrects[1].inset(inset, inset);
142 SkScalar pad = blurRad/2.0f - inset;
143 paints[1].setStrokeWidth(blurRad + 2.0f * pad);
144 paints[1].setColor(SkColorSetARGB(255, (4 * blurRad) >> 8, (4 * blurRad) & 0xff,
145 (int)(4.0f*pad)));
146 }
147
148 //----
149 paints[2] = basePaint;
150 paints[2].setStyle(SkPaint::kStrokeAndFill_Style);
151
152 rrects[2] = baseRR;
153 if (blurRad/2.0f < kRRRad) {
154 rrects[2].inset(blurRad/2.0f, blurRad/2.0f);
155 paints[2].setStrokeWidth(SkIntToScalar(blurRad));
156 } else {
157 SkScalar inset = kRRRad - 0.5f;
158 rrects[2].inset(inset, inset);
159 SkScalar pad = blurRad/2.0f - inset;
160 paints[2].setStrokeWidth(blurRad + 2.0f * pad);
161 paints[2].setColor(SkColorSetARGB(255, (4 * blurRad) >> 8, (4 * blurRad) & 0xff,
162 (int)(4.0f*pad)));
163 }
164 }
165
166 //----
167 canvas->save();
168 // draw the shadows
169 for (int i = 0; i < kNumBaseCols; ++i) {
170 canvas->drawRRect(rrects[i], paints[i]);
171 canvas->translate(SkIntToScalar(kCellWidth+kPad), 0.0f);
172 }
173
174#ifdef VIZ
175 // draw the visualization of the shadow ramps
176 draw_row(canvas, midLine, 3*(kRRSize+kPad));
177#endif
178 canvas->restore();
179
180#ifdef VIZ
181 const SkColor colors[kNumBaseCols] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
182
183 // circle back and draw the stroked geometry (they would mess up the viz otherwise)
184 for (int i = 0; i < kNumBaseCols; ++i) {
185 draw_stroke(canvas, rrects[i], paints[i], colors[i]);
186 canvas->translate(SkIntToScalar(kCellWidth+kPad), 0.0f);
187 }
188#endif
189 }
190
191 void onDraw(SkCanvas* canvas) override {
Brian Osman11052242016-10-27 14:47:55 -0400192 GrRenderTargetContext* renderTargetContext =
193 canvas->internal_private_accessTopLayerRenderTargetContext();
194 if (!renderTargetContext) {
Robert Phillips568c9862016-10-11 10:18:18 -0400195 skiagm::GM::DrawGpuOnlyMessage(canvas);
196 return;
197 }
198
199 const int blurRadii[kNumRows] = { kRRRad/2, kRRRad, 2*kRRRad };
200
201 canvas->translate(SkIntToScalar(kPad), SkIntToScalar(kPad));
202 for (int i = 0; i < kNumRows; ++i) {
203 DrawRow(canvas, blurRadii[i], kPad+(i*kRRSize)+kRRSize/2);
204 canvas->translate(0.0f, SkIntToScalar(kCellWidth+kPad));
205 }
206 }
207
208private:
209 static const int kNumRows = 3;
210 static const int kNumBaseCols = 3;
211 static const int kPad = 5;
212 static const int kRRSize = 256;
213 static const int kRRRad = 64;
214 static const int kCellWidth = kRRSize;
215
216 typedef GM INHERITED;
217};
218
219//////////////////////////////////////////////////////////////////////////////
220
221DEF_GM(return new GaussianEdgeGM;)
222}