• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 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 #include "gm.h"
8 #include "SkCanvas.h"
9 #include "SkPaint.h"
10 #include "SkRandom.h"
11 
12 // skbug.com/1316 shows that this cubic, when slightly clipped, creates big
13 // (incorrect) changes to its control points.
14 class ClippedCubicGM : public skiagm::GM {
15 public:
ClippedCubicGM()16     ClippedCubicGM() {}
17 
18 protected:
19 
onShortName()20     SkString onShortName() {
21         return SkString("clippedcubic");
22     }
23 
onISize()24     SkISize onISize() { return SkISize::Make(1240, 390); }
25 
onDraw(SkCanvas * canvas)26     virtual void onDraw(SkCanvas* canvas) {
27         SkPath path;
28         path.moveTo(0, 0);
29         path.cubicTo(140, 150, 40, 10, 170, 150);
30 
31         SkPaint paint;
32         SkRect bounds = path.getBounds();
33 
34         for (SkScalar dy = -1; dy <= 1; dy += 1) {
35             canvas->save();
36             for (SkScalar dx = -1; dx <= 1; dx += 1) {
37                 canvas->save();
38                 canvas->clipRect(bounds);
39                 canvas->translate(dx, dy);
40                 canvas->drawPath(path, paint);
41                 canvas->restore();
42 
43                 canvas->translate(bounds.width(), 0);
44             }
45             canvas->restore();
46             canvas->translate(0, bounds.height());
47         }
48     }
49 
50 private:
51     typedef skiagm::GM INHERITED;
52 };
53 
54 class CubicPathGM : public skiagm::GM {
55 public:
CubicPathGM()56     CubicPathGM() {}
57 
58 protected:
59 
onShortName()60     SkString onShortName() {
61         return SkString("cubicpath");
62     }
63 
onISize()64     SkISize onISize() { return SkISize::Make(1240, 390); }
65 
drawPath(SkPath & path,SkCanvas * canvas,SkColor color,const SkRect & clip,SkPaint::Cap cap,SkPaint::Join join,SkPaint::Style style,SkPath::FillType fill,SkScalar strokeWidth)66     void drawPath(SkPath& path,SkCanvas* canvas,SkColor color,
67                   const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join,
68                   SkPaint::Style style, SkPath::FillType fill,
69                   SkScalar strokeWidth) {
70         path.setFillType(fill);
71         SkPaint paint;
72         paint.setStrokeCap(cap);
73         paint.setStrokeWidth(strokeWidth);
74         paint.setStrokeJoin(join);
75         paint.setColor(color);
76         paint.setStyle(style);
77         canvas->save();
78         canvas->clipRect(clip);
79         canvas->drawPath(path, paint);
80         canvas->restore();
81     }
82 
onDraw(SkCanvas * canvas)83     virtual void onDraw(SkCanvas* canvas) {
84         struct FillAndName {
85             SkPath::FillType fFill;
86             const char*      fName;
87         };
88         static const FillAndName gFills[] = {
89             {SkPath::kWinding_FillType, "Winding"},
90             {SkPath::kEvenOdd_FillType, "Even / Odd"},
91             {SkPath::kInverseWinding_FillType, "Inverse Winding"},
92             {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"},
93         };
94         struct StyleAndName {
95             SkPaint::Style fStyle;
96             const char*    fName;
97         };
98         static const StyleAndName gStyles[] = {
99             {SkPaint::kFill_Style, "Fill"},
100             {SkPaint::kStroke_Style, "Stroke"},
101             {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
102         };
103         struct CapAndName {
104             SkPaint::Cap  fCap;
105             SkPaint::Join fJoin;
106             const char*   fName;
107         };
108         static const CapAndName gCaps[] = {
109             {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
110             {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
111             {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
112         };
113         struct PathAndName {
114             SkPath      fPath;
115             const char* fName;
116         };
117         PathAndName path;
118         path.fPath.moveTo(25*SK_Scalar1, 10*SK_Scalar1);
119         path.fPath.cubicTo(40*SK_Scalar1, 20*SK_Scalar1,
120                            60*SK_Scalar1, 20*SK_Scalar1,
121                            75*SK_Scalar1, 10*SK_Scalar1);
122         path.fName = "moveTo-cubic";
123 
124         SkPaint titlePaint;
125         titlePaint.setColor(SK_ColorBLACK);
126         titlePaint.setAntiAlias(true);
127         sk_tool_utils::set_portable_typeface(&titlePaint);
128         titlePaint.setLCDRenderText(true);
129         titlePaint.setTextSize(15 * SK_Scalar1);
130         const char title[] = "Cubic Drawn Into Rectangle Clips With "
131                              "Indicated Style, Fill and Linecaps, with stroke width 10";
132         canvas->drawText(title, strlen(title),
133                             20 * SK_Scalar1,
134                             20 * SK_Scalar1,
135                             titlePaint);
136 
137         SkRandom rand;
138         SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
139         canvas->save();
140         canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1);
141         canvas->save();
142         for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) {
143             if (0 < cap) {
144                 canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0);
145             }
146             canvas->save();
147             for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
148                 if (0 < fill) {
149                     canvas->translate(0, rect.height() + 40 * SK_Scalar1);
150                 }
151                 canvas->save();
152                 for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
153                     if (0 < style) {
154                         canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
155                     }
156 
157                     SkColor color = 0xff007000;
158                     this->drawPath(path.fPath, canvas, color, rect,
159                                     gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle,
160                                     gFills[fill].fFill, SK_Scalar1*10);
161 
162                     SkPaint rectPaint;
163                     rectPaint.setColor(SK_ColorBLACK);
164                     rectPaint.setStyle(SkPaint::kStroke_Style);
165                     rectPaint.setStrokeWidth(-1);
166                     rectPaint.setAntiAlias(true);
167                     canvas->drawRect(rect, rectPaint);
168 
169                     SkPaint labelPaint;
170                     labelPaint.setColor(color);
171                     labelPaint.setAntiAlias(true);
172                     sk_tool_utils::set_portable_typeface(&labelPaint);
173                     labelPaint.setLCDRenderText(true);
174                     labelPaint.setTextSize(10 * SK_Scalar1);
175                     canvas->drawText(gStyles[style].fName,
176                                         strlen(gStyles[style].fName),
177                                         0, rect.height() + 12 * SK_Scalar1,
178                                         labelPaint);
179                     canvas->drawText(gFills[fill].fName,
180                                         strlen(gFills[fill].fName),
181                                         0, rect.height() + 24 * SK_Scalar1,
182                                         labelPaint);
183                     canvas->drawText(gCaps[cap].fName,
184                                         strlen(gCaps[cap].fName),
185                                         0, rect.height() + 36 * SK_Scalar1,
186                                         labelPaint);
187                 }
188                 canvas->restore();
189             }
190             canvas->restore();
191         }
192         canvas->restore();
193         canvas->restore();
194     }
195 
196 private:
197     typedef skiagm::GM INHERITED;
198 };
199 
200 class CubicClosePathGM : public skiagm::GM {
201 public:
CubicClosePathGM()202     CubicClosePathGM() {}
203 
204 protected:
205 
onShortName()206     SkString onShortName() {
207         return SkString("cubicclosepath");
208     }
209 
onISize()210     SkISize onISize() { return SkISize::Make(1240, 390); }
211 
drawPath(SkPath & path,SkCanvas * canvas,SkColor color,const SkRect & clip,SkPaint::Cap cap,SkPaint::Join join,SkPaint::Style style,SkPath::FillType fill,SkScalar strokeWidth)212     void drawPath(SkPath& path,SkCanvas* canvas,SkColor color,
213                   const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join,
214                   SkPaint::Style style, SkPath::FillType fill,
215                   SkScalar strokeWidth) {
216         path.setFillType(fill);
217         SkPaint paint;
218         paint.setStrokeCap(cap);
219         paint.setStrokeWidth(strokeWidth);
220         paint.setStrokeJoin(join);
221         paint.setColor(color);
222         paint.setStyle(style);
223         canvas->save();
224         canvas->clipRect(clip);
225         canvas->drawPath(path, paint);
226         canvas->restore();
227     }
228 
onDraw(SkCanvas * canvas)229     virtual void onDraw(SkCanvas* canvas) {
230         struct FillAndName {
231             SkPath::FillType fFill;
232             const char*      fName;
233         };
234         static const FillAndName gFills[] = {
235             {SkPath::kWinding_FillType, "Winding"},
236             {SkPath::kEvenOdd_FillType, "Even / Odd"},
237             {SkPath::kInverseWinding_FillType, "Inverse Winding"},
238             {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"},
239         };
240         struct StyleAndName {
241             SkPaint::Style fStyle;
242             const char*    fName;
243         };
244         static const StyleAndName gStyles[] = {
245             {SkPaint::kFill_Style, "Fill"},
246             {SkPaint::kStroke_Style, "Stroke"},
247             {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
248         };
249         struct CapAndName {
250             SkPaint::Cap  fCap;
251             SkPaint::Join fJoin;
252             const char*   fName;
253         };
254         static const CapAndName gCaps[] = {
255             {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
256             {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
257             {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
258         };
259         struct PathAndName {
260             SkPath      fPath;
261             const char* fName;
262         };
263         PathAndName path;
264         path.fPath.moveTo(25*SK_Scalar1, 10*SK_Scalar1);
265         path.fPath.cubicTo(40*SK_Scalar1, 20*SK_Scalar1,
266                            60*SK_Scalar1, 20*SK_Scalar1,
267                            75*SK_Scalar1, 10*SK_Scalar1);
268         path.fPath.close();
269         path.fName = "moveTo-cubic-close";
270 
271         SkPaint titlePaint;
272         titlePaint.setColor(SK_ColorBLACK);
273         titlePaint.setAntiAlias(true);
274         sk_tool_utils::set_portable_typeface(&titlePaint);
275         titlePaint.setLCDRenderText(true);
276         titlePaint.setTextSize(15 * SK_Scalar1);
277         const char title[] = "Cubic Closed Drawn Into Rectangle Clips With "
278                              "Indicated Style, Fill and Linecaps, with stroke width 10";
279         canvas->drawText(title, strlen(title),
280                             20 * SK_Scalar1,
281                             20 * SK_Scalar1,
282                             titlePaint);
283 
284         SkRandom rand;
285         SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
286         canvas->save();
287         canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1);
288         canvas->save();
289         for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) {
290             if (0 < cap) {
291                 canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0);
292             }
293             canvas->save();
294             for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
295                 if (0 < fill) {
296                     canvas->translate(0, rect.height() + 40 * SK_Scalar1);
297                 }
298                 canvas->save();
299                 for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
300                     if (0 < style) {
301                         canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
302                     }
303 
304                     SkColor color = 0xff007000;
305                     this->drawPath(path.fPath, canvas, color, rect,
306                                     gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle,
307                                     gFills[fill].fFill, SK_Scalar1*10);
308 
309                     SkPaint rectPaint;
310                     rectPaint.setColor(SK_ColorBLACK);
311                     rectPaint.setStyle(SkPaint::kStroke_Style);
312                     rectPaint.setStrokeWidth(-1);
313                     rectPaint.setAntiAlias(true);
314                     canvas->drawRect(rect, rectPaint);
315 
316                     SkPaint labelPaint;
317                     labelPaint.setColor(color);
318                     labelPaint.setAntiAlias(true);
319                     sk_tool_utils::set_portable_typeface(&labelPaint);
320                     labelPaint.setLCDRenderText(true);
321                     labelPaint.setTextSize(10 * SK_Scalar1);
322                     canvas->drawText(gStyles[style].fName,
323                                         strlen(gStyles[style].fName),
324                                         0, rect.height() + 12 * SK_Scalar1,
325                                         labelPaint);
326                     canvas->drawText(gFills[fill].fName,
327                                         strlen(gFills[fill].fName),
328                                         0, rect.height() + 24 * SK_Scalar1,
329                                         labelPaint);
330                     canvas->drawText(gCaps[cap].fName,
331                                         strlen(gCaps[cap].fName),
332                                         0, rect.height() + 36 * SK_Scalar1,
333                                         labelPaint);
334                 }
335                 canvas->restore();
336             }
337             canvas->restore();
338         }
339         canvas->restore();
340         canvas->restore();
341     }
342 
343 private:
344     typedef skiagm::GM INHERITED;
345 };
346 
347 //////////////////////////////////////////////////////////////////////////////
348 
349 DEF_GM( return new CubicPathGM; )
350 DEF_GM( return new CubicClosePathGM; )
351 DEF_GM( return new ClippedCubicGM; )
352