• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
draw_stroke(SkCanvas * canvas,const SkRRect & rr,const SkPaint & p,SkColor color)17 static 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 
extract_pts(const SkBitmap & bm,SkTDArray<SkPoint> * pts,int xOff,int width)37 static 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 
draw_row(SkCanvas * canvas,int row,int width)51 static 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 
78 namespace 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).
85 class GaussianEdgeGM : public GM {
86 public:
GaussianEdgeGM()87     GaussianEdgeGM() {
88         this->setBGColor(SK_ColorWHITE);
89     }
90 
91 protected:
92 
onShortName()93     SkString onShortName() override {
94         return SkString("gaussianedge");
95     }
96 
onISize()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 
DrawRow(SkCanvas * canvas,int blurRad,int midLine)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 
onDraw(SkCanvas * canvas)188     void onDraw(SkCanvas* canvas) override {
189         GrRenderTargetContext* renderTargetContext =
190             canvas->internal_private_accessTopLayerRenderTargetContext();
191         if (!renderTargetContext) {
192             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 
205 private:
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 
218 DEF_GM(return new GaussianEdgeGM;)
219 }
220