• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
11 #include "SkBitmap.h"
12 #include "SkGradientShader.h"
13 #include "SkPath.h"
14 #include "SkTLList.h"
15 
make_bmp(int w,int h)16 static SkBitmap make_bmp(int w, int h) {
17     SkBitmap bmp;
18     bmp.allocN32Pixels(w, h, true);
19 
20     SkCanvas canvas(bmp);
21     SkScalar wScalar = SkIntToScalar(w);
22     SkScalar hScalar = SkIntToScalar(h);
23 
24     SkPoint     pt = { wScalar / 2, hScalar / 2 };
25 
26     SkScalar    radius = 3 * SkMaxScalar(wScalar, hScalar);
27 
28     SkColor     colors[] = { sk_tool_utils::color_to_565(SK_ColorDKGRAY),
29                              sk_tool_utils::color_to_565(0xFF222255),
30                              sk_tool_utils::color_to_565(0xFF331133),
31                              sk_tool_utils::color_to_565(0xFF884422),
32                              sk_tool_utils::color_to_565(0xFF000022), SK_ColorWHITE,
33                              sk_tool_utils::color_to_565(0xFFAABBCC) };
34 
35     SkScalar    pos[] = {0,
36                          SK_Scalar1 / 6,
37                          2 * SK_Scalar1 / 6,
38                          3 * SK_Scalar1 / 6,
39                          4 * SK_Scalar1 / 6,
40                          5 * SK_Scalar1 / 6,
41                          SK_Scalar1};
42 
43     SkPaint paint;
44     SkRect rect = SkRect::MakeWH(wScalar, hScalar);
45     SkMatrix mat = SkMatrix::I();
46     for (int i = 0; i < 4; ++i) {
47         paint.setShader(SkGradientShader::MakeRadial(
48                         pt, radius,
49                         colors, pos,
50                         SK_ARRAY_COUNT(colors),
51                         SkShader::kRepeat_TileMode,
52                         0, &mat));
53         canvas.drawRect(rect, paint);
54         rect.inset(wScalar / 8, hScalar / 8);
55         mat.preTranslate(6 * wScalar, 6 * hScalar);
56         mat.postScale(SK_Scalar1 / 3, SK_Scalar1 / 3);
57     }
58 
59     paint.setAntiAlias(true);
60     sk_tool_utils::set_portable_typeface(&paint);
61     paint.setTextSize(wScalar / 2.2f);
62     paint.setShader(0);
63     paint.setColor(sk_tool_utils::color_to_565(SK_ColorLTGRAY));
64     constexpr char kTxt[] = "Skia";
65     SkPoint texPos = { wScalar / 17, hScalar / 2 + paint.getTextSize() / 2.5f };
66     canvas.drawText(kTxt, SK_ARRAY_COUNT(kTxt)-1, texPos.fX, texPos.fY, paint);
67     paint.setColor(SK_ColorBLACK);
68     paint.setStyle(SkPaint::kStroke_Style);
69     paint.setStrokeWidth(SK_Scalar1);
70     canvas.drawText(kTxt, SK_ARRAY_COUNT(kTxt)-1, texPos.fX, texPos.fY, paint);
71     return bmp;
72 }
73 
74 namespace skiagm {
75 /**
76  * This GM tests convex polygon clips.
77  */
78 class ConvexPolyClip : public GM {
79 public:
ConvexPolyClip()80     ConvexPolyClip() {
81         this->setBGColor(0xFFFFFFFF);
82     }
83 
84 protected:
onShortName()85     SkString onShortName() override {
86         return SkString("convex_poly_clip");
87     }
88 
onISize()89     SkISize onISize() override {
90         // When benchmarking the saveLayer set of draws is skipped.
91         int w = 435;
92         if (kBench_Mode != this->getMode()) {
93             w *= 2;
94         }
95         return SkISize::Make(w, 540);
96     }
97 
onOnceBeforeDraw()98     void onOnceBeforeDraw() override {
99         SkPath tri;
100         tri.moveTo(5.f, 5.f);
101         tri.lineTo(100.f, 20.f);
102         tri.lineTo(15.f, 100.f);
103 
104         fClips.addToTail()->setPath(tri);
105 
106         SkPath hexagon;
107         constexpr SkScalar kRadius = 45.f;
108         const SkPoint center = { kRadius, kRadius };
109         for (int i = 0; i < 6; ++i) {
110             SkScalar angle = 2 * SK_ScalarPI * i / 6;
111             SkPoint point;
112             point.fY = SkScalarSinCos(angle, &point.fX);
113             point.scale(kRadius);
114             point = center + point;
115             if (0 == i) {
116                 hexagon.moveTo(point);
117             } else {
118                 hexagon.lineTo(point);
119             }
120         }
121         fClips.addToTail()->setPath(hexagon);
122 
123         SkMatrix scaleM;
124         scaleM.setScale(1.1f, 0.4f, kRadius, kRadius);
125         hexagon.transform(scaleM);
126         fClips.addToTail()->setPath(hexagon);
127 
128         fClips.addToTail()->setRect(SkRect::MakeXYWH(8.3f, 11.6f, 78.2f, 72.6f));
129 
130         SkPath rotRect;
131         SkRect rect = SkRect::MakeLTRB(10.f, 12.f, 80.f, 86.f);
132         rotRect.addRect(rect);
133         SkMatrix rotM;
134         rotM.setRotate(23.f, rect.centerX(), rect.centerY());
135         rotRect.transform(rotM);
136         fClips.addToTail()->setPath(rotRect);
137 
138         fBmp = make_bmp(100, 100);
139     }
140 
onDraw(SkCanvas * canvas)141     void onDraw(SkCanvas* canvas) override {
142         SkScalar y = 0;
143         constexpr SkScalar kMargin = 10.f;
144 
145         SkPaint bgPaint;
146         bgPaint.setAlpha(0x15);
147         SkISize size = canvas->getBaseLayerSize();
148         canvas->drawBitmapRect(fBmp, SkRect::MakeIWH(size.fWidth, size.fHeight), &bgPaint);
149 
150         constexpr char kTxt[] = "Clip Me!";
151         SkPaint txtPaint;
152         txtPaint.setTextSize(23.f);
153         txtPaint.setAntiAlias(true);
154         sk_tool_utils::set_portable_typeface(&txtPaint);
155         txtPaint.setColor(sk_tool_utils::color_to_565(SK_ColorDKGRAY));
156         SkScalar textW = txtPaint.measureText(kTxt, SK_ARRAY_COUNT(kTxt)-1);
157 
158         SkScalar startX = 0;
159         int testLayers = kBench_Mode != this->getMode();
160         for (int doLayer = 0; doLayer <= testLayers; ++doLayer) {
161             for (ClipList::Iter iter(fClips, ClipList::Iter::kHead_IterStart);
162                  iter.get();
163                  iter.next()) {
164                 const Clip* clip = iter.get();
165                 SkScalar x = startX;
166                 for (int aa = 0; aa < 2; ++aa) {
167                     if (doLayer) {
168                         SkRect bounds;
169                         clip->getBounds(&bounds);
170                         bounds.outset(2, 2);
171                         bounds.offset(x, y);
172                         canvas->saveLayer(&bounds, nullptr);
173                     } else {
174                         canvas->save();
175                     }
176                     canvas->translate(x, y);
177                     clip->setOnCanvas(canvas, kIntersect_SkClipOp, SkToBool(aa));
178                     canvas->drawBitmap(fBmp, 0, 0);
179                     canvas->restore();
180                     x += fBmp.width() + kMargin;
181                 }
182                 for (int aa = 0; aa < 2; ++aa) {
183 
184                     SkPaint clipOutlinePaint;
185                     clipOutlinePaint.setAntiAlias(true);
186                     clipOutlinePaint.setColor(0x50505050);
187                     clipOutlinePaint.setStyle(SkPaint::kStroke_Style);
188                     clipOutlinePaint.setStrokeWidth(0);
189 
190                     if (doLayer) {
191                         SkRect bounds;
192                         clip->getBounds(&bounds);
193                         bounds.outset(2, 2);
194                         bounds.offset(x, y);
195                         canvas->saveLayer(&bounds, nullptr);
196                     } else {
197                         canvas->save();
198                     }
199                     canvas->translate(x, y);
200                     SkPath closedClipPath;
201                     clip->asClosedPath(&closedClipPath);
202                     canvas->drawPath(closedClipPath, clipOutlinePaint);
203                     clip->setOnCanvas(canvas, kIntersect_SkClipOp, SkToBool(aa));
204                     canvas->scale(1.f, 1.8f);
205                     canvas->drawText(kTxt, SK_ARRAY_COUNT(kTxt)-1,
206                                      0, 1.5f * txtPaint.getTextSize(),
207                                      txtPaint);
208                     canvas->restore();
209                     x += textW + 2 * kMargin;
210                 }
211                 y += fBmp.height() + kMargin;
212             }
213             y = 0;
214             startX += 2 * fBmp.width() + SkScalarCeilToInt(2 * textW) + 6 * kMargin;
215         }
216     }
217 
runAsBench() const218     bool runAsBench() const override { return true; }
219 
220 private:
221     class Clip {
222     public:
223         enum ClipType {
224             kNone_ClipType,
225             kPath_ClipType,
226             kRect_ClipType
227         };
228 
Clip()229         Clip () : fClipType(kNone_ClipType) {}
230 
setOnCanvas(SkCanvas * canvas,SkClipOp op,bool aa) const231         void setOnCanvas(SkCanvas* canvas, SkClipOp op, bool aa) const {
232             switch (fClipType) {
233                 case kPath_ClipType:
234                     canvas->clipPath(fPath, op, aa);
235                     break;
236                 case kRect_ClipType:
237                     canvas->clipRect(fRect, op, aa);
238                     break;
239                 case kNone_ClipType:
240                     SkDEBUGFAIL("Uninitialized Clip.");
241                     break;
242             }
243         }
244 
asClosedPath(SkPath * path) const245         void asClosedPath(SkPath* path) const {
246             switch (fClipType) {
247                 case kPath_ClipType:
248                     *path = fPath;
249                     path->close();
250                     break;
251                 case kRect_ClipType:
252                     path->reset();
253                     path->addRect(fRect);
254                     break;
255                 case kNone_ClipType:
256                     SkDEBUGFAIL("Uninitialized Clip.");
257                     break;
258             }
259         }
260 
setPath(const SkPath & path)261         void setPath(const SkPath& path) {
262             fClipType = kPath_ClipType;
263             fPath = path;
264         }
265 
setRect(const SkRect & rect)266         void setRect(const SkRect& rect) {
267             fClipType = kRect_ClipType;
268             fRect = rect;
269             fPath.reset();
270         }
271 
getType() const272         ClipType getType() const { return fClipType; }
273 
getBounds(SkRect * bounds) const274         void getBounds(SkRect* bounds) const {
275             switch (fClipType) {
276                 case kPath_ClipType:
277                     *bounds = fPath.getBounds();
278                     break;
279                 case kRect_ClipType:
280                     *bounds = fRect;
281                     break;
282                 case kNone_ClipType:
283                     SkDEBUGFAIL("Uninitialized Clip.");
284                     break;
285             }
286         }
287 
288     private:
289         ClipType fClipType;
290         SkPath fPath;
291         SkRect fRect;
292     };
293 
294     typedef SkTLList<Clip, 1> ClipList;
295     ClipList         fClips;
296     SkBitmap         fBmp;
297 
298     typedef GM INHERITED;
299 };
300 
301 DEF_GM(return new ConvexPolyClip;)
302 }
303