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