blob: f95f700660e64c1e791a81460935dd96131aacda [file] [log] [blame]
schenney@chromium.org4da06ab2011-12-20 15:14:18 +00001/*
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
reed@google.com22999c62013-05-23 19:30:48 +000012// skbug.com/1316 shows that this cubic, when slightly clipped, creates big
13// (incorrect) changes to its control points.
14class ClippedCubicGM : public skiagm::GM {
15public:
16 ClippedCubicGM() {}
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000017
reed@google.com22999c62013-05-23 19:30:48 +000018protected:
19 SkString onShortName() {
reed@google.com03ca64b2013-05-23 19:39:15 +000020 return SkString("clippedcubic");
reed@google.com22999c62013-05-23 19:30:48 +000021 }
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000022
reed@google.com22999c62013-05-23 19:30:48 +000023 SkISize onISize() { return SkISize::Make(1240, 390); }
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000024
reed@google.com22999c62013-05-23 19:30:48 +000025 virtual void onDraw(SkCanvas* canvas) {
26 SkPath path;
27 path.moveTo(0, 0);
28 path.cubicTo(140, 150, 40, 10, 170, 150);
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000029
reed@google.com22999c62013-05-23 19:30:48 +000030 SkPaint paint;
31 SkRect bounds = path.getBounds();
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000032
reed@google.com0f8990c2013-05-23 19:47:05 +000033 for (SkScalar dy = -1; dy <= 1; dy += 1) {
reed@google.com22999c62013-05-23 19:30:48 +000034 canvas->save();
reed@google.com0f8990c2013-05-23 19:47:05 +000035 for (SkScalar dx = -1; dx <= 1; dx += 1) {
reed@google.com22999c62013-05-23 19:30:48 +000036 canvas->save();
37 canvas->clipRect(bounds);
38 canvas->translate(dx, dy);
39 canvas->drawPath(path, paint);
40 canvas->restore();
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000041
reed@google.com22999c62013-05-23 19:30:48 +000042 canvas->translate(bounds.width(), 0);
43 }
44 canvas->restore();
45 canvas->translate(0, bounds.height());
46 }
47 }
skia.committer@gmail.com3e2345a2013-05-24 07:01:26 +000048
reed@google.com22999c62013-05-23 19:30:48 +000049private:
50 typedef skiagm::GM INHERITED;
51};
52
reed@google.com27b90fa2013-03-08 18:44:01 +000053class CubicPathGM : public skiagm::GM {
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +000054public:
55 CubicPathGM() {}
56
57protected:
58 SkString onShortName() {
59 return SkString("cubicpath");
60 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000061
reed@google.com27b90fa2013-03-08 18:44:01 +000062 SkISize onISize() { return SkISize::Make(1240, 390); }
rmistry@google.comd6176b02012-08-23 18:14:13 +000063
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +000064 void drawPath(SkPath& path,SkCanvas* canvas,SkColor color,
65 const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join,
66 SkPaint::Style style, SkPath::FillType fill,
67 SkScalar strokeWidth) {
68 path.setFillType(fill);
69 SkPaint paint;
70 paint.setStrokeCap(cap);
71 paint.setStrokeWidth(strokeWidth);
72 paint.setStrokeJoin(join);
73 paint.setColor(color);
74 paint.setStyle(style);
75 canvas->save();
76 canvas->clipRect(clip);
77 canvas->drawPath(path, paint);
78 canvas->restore();
79 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000080
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +000081 virtual void onDraw(SkCanvas* canvas) {
82 struct FillAndName {
83 SkPath::FillType fFill;
84 const char* fName;
85 };
86 static const FillAndName gFills[] = {
87 {SkPath::kWinding_FillType, "Winding"},
88 {SkPath::kEvenOdd_FillType, "Even / Odd"},
89 {SkPath::kInverseWinding_FillType, "Inverse Winding"},
90 {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"},
91 };
92 struct StyleAndName {
93 SkPaint::Style fStyle;
94 const char* fName;
95 };
96 static const StyleAndName gStyles[] = {
97 {SkPaint::kFill_Style, "Fill"},
98 {SkPaint::kStroke_Style, "Stroke"},
99 {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
100 };
101 struct CapAndName {
102 SkPaint::Cap fCap;
103 SkPaint::Join fJoin;
104 const char* fName;
105 };
106 static const CapAndName gCaps[] = {
107 {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
108 {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
109 {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
110 };
111 struct PathAndName {
112 SkPath fPath;
113 const char* fName;
114 };
115 PathAndName path;
116 path.fPath.moveTo(25*SK_Scalar1, 10*SK_Scalar1);
117 path.fPath.cubicTo(40*SK_Scalar1, 20*SK_Scalar1,
118 60*SK_Scalar1, 20*SK_Scalar1,
119 75*SK_Scalar1, 10*SK_Scalar1);
120 path.fName = "moveTo-cubic";
121
122 SkPaint titlePaint;
123 titlePaint.setColor(SK_ColorBLACK);
124 titlePaint.setAntiAlias(true);
125 titlePaint.setLCDRenderText(true);
126 titlePaint.setTextSize(15 * SK_Scalar1);
127 const char title[] = "Cubic Drawn Into Rectangle Clips With "
128 "Indicated Style, Fill and Linecaps, with stroke width 10";
129 canvas->drawText(title, strlen(title),
130 20 * SK_Scalar1,
131 20 * SK_Scalar1,
132 titlePaint);
133
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000134 SkLCGRandom rand;
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000135 SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
136 canvas->save();
137 canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1);
138 canvas->save();
139 for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) {
140 if (0 < cap) {
141 canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0);
142 }
143 canvas->save();
144 for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
145 if (0 < fill) {
146 canvas->translate(0, rect.height() + 40 * SK_Scalar1);
147 }
148 canvas->save();
149 for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
150 if (0 < style) {
151 canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
152 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000153
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000154 SkColor color = 0xff007000;
155 this->drawPath(path.fPath, canvas, color, rect,
156 gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle,
157 gFills[fill].fFill, SK_Scalar1*10);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000158
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000159 SkPaint rectPaint;
160 rectPaint.setColor(SK_ColorBLACK);
161 rectPaint.setStyle(SkPaint::kStroke_Style);
162 rectPaint.setStrokeWidth(-1);
163 rectPaint.setAntiAlias(true);
164 canvas->drawRect(rect, rectPaint);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000165
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000166 SkPaint labelPaint;
167 labelPaint.setColor(color);
168 labelPaint.setAntiAlias(true);
169 labelPaint.setLCDRenderText(true);
170 labelPaint.setTextSize(10 * SK_Scalar1);
171 canvas->drawText(gStyles[style].fName,
172 strlen(gStyles[style].fName),
173 0, rect.height() + 12 * SK_Scalar1,
174 labelPaint);
175 canvas->drawText(gFills[fill].fName,
176 strlen(gFills[fill].fName),
177 0, rect.height() + 24 * SK_Scalar1,
178 labelPaint);
179 canvas->drawText(gCaps[cap].fName,
180 strlen(gCaps[cap].fName),
181 0, rect.height() + 36 * SK_Scalar1,
182 labelPaint);
183 }
184 canvas->restore();
185 }
186 canvas->restore();
187 }
188 canvas->restore();
189 canvas->restore();
190 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000191
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000192private:
reed@google.com27b90fa2013-03-08 18:44:01 +0000193 typedef skiagm::GM INHERITED;
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000194};
195
reed@google.com27b90fa2013-03-08 18:44:01 +0000196class CubicClosePathGM : public skiagm::GM {
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000197public:
198 CubicClosePathGM() {}
199
200protected:
201 SkString onShortName() {
202 return SkString("cubicclosepath");
203 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000204
reed@google.com27b90fa2013-03-08 18:44:01 +0000205 SkISize onISize() { return SkISize::Make(1240, 390); }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000206
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000207 void drawPath(SkPath& path,SkCanvas* canvas,SkColor color,
208 const SkRect& clip,SkPaint::Cap cap, SkPaint::Join join,
209 SkPaint::Style style, SkPath::FillType fill,
210 SkScalar strokeWidth) {
211 path.setFillType(fill);
212 SkPaint paint;
213 paint.setStrokeCap(cap);
214 paint.setStrokeWidth(strokeWidth);
215 paint.setStrokeJoin(join);
216 paint.setColor(color);
217 paint.setStyle(style);
218 canvas->save();
219 canvas->clipRect(clip);
220 canvas->drawPath(path, paint);
221 canvas->restore();
222 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000223
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000224 virtual void onDraw(SkCanvas* canvas) {
225 struct FillAndName {
226 SkPath::FillType fFill;
227 const char* fName;
228 };
229 static const FillAndName gFills[] = {
230 {SkPath::kWinding_FillType, "Winding"},
231 {SkPath::kEvenOdd_FillType, "Even / Odd"},
232 {SkPath::kInverseWinding_FillType, "Inverse Winding"},
233 {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"},
234 };
235 struct StyleAndName {
236 SkPaint::Style fStyle;
237 const char* fName;
238 };
239 static const StyleAndName gStyles[] = {
240 {SkPaint::kFill_Style, "Fill"},
241 {SkPaint::kStroke_Style, "Stroke"},
242 {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"},
243 };
244 struct CapAndName {
245 SkPaint::Cap fCap;
246 SkPaint::Join fJoin;
247 const char* fName;
248 };
249 static const CapAndName gCaps[] = {
250 {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"},
251 {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"},
252 {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"}
253 };
254 struct PathAndName {
255 SkPath fPath;
256 const char* fName;
257 };
258 PathAndName path;
259 path.fPath.moveTo(25*SK_Scalar1, 10*SK_Scalar1);
260 path.fPath.cubicTo(40*SK_Scalar1, 20*SK_Scalar1,
261 60*SK_Scalar1, 20*SK_Scalar1,
262 75*SK_Scalar1, 10*SK_Scalar1);
263 path.fPath.close();
264 path.fName = "moveTo-cubic-close";
265
266 SkPaint titlePaint;
267 titlePaint.setColor(SK_ColorBLACK);
268 titlePaint.setAntiAlias(true);
269 titlePaint.setLCDRenderText(true);
270 titlePaint.setTextSize(15 * SK_Scalar1);
271 const char title[] = "Cubic Closed Drawn Into Rectangle Clips With "
272 "Indicated Style, Fill and Linecaps, with stroke width 10";
273 canvas->drawText(title, strlen(title),
274 20 * SK_Scalar1,
275 20 * SK_Scalar1,
276 titlePaint);
277
commit-bot@chromium.orge0e7cfe2013-09-09 20:09:12 +0000278 SkLCGRandom rand;
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000279 SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1);
280 canvas->save();
281 canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1);
282 canvas->save();
283 for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) {
284 if (0 < cap) {
285 canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0);
286 }
287 canvas->save();
288 for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) {
289 if (0 < fill) {
290 canvas->translate(0, rect.height() + 40 * SK_Scalar1);
291 }
292 canvas->save();
293 for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) {
294 if (0 < style) {
295 canvas->translate(rect.width() + 40 * SK_Scalar1, 0);
296 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000297
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000298 SkColor color = 0xff007000;
299 this->drawPath(path.fPath, canvas, color, rect,
300 gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle,
301 gFills[fill].fFill, SK_Scalar1*10);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000302
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000303 SkPaint rectPaint;
304 rectPaint.setColor(SK_ColorBLACK);
305 rectPaint.setStyle(SkPaint::kStroke_Style);
306 rectPaint.setStrokeWidth(-1);
307 rectPaint.setAntiAlias(true);
308 canvas->drawRect(rect, rectPaint);
rmistry@google.comd6176b02012-08-23 18:14:13 +0000309
schenney@chromium.org45cbfdd2011-12-20 21:48:14 +0000310 SkPaint labelPaint;
311 labelPaint.setColor(color);
312 labelPaint.setAntiAlias(true);
313 labelPaint.setLCDRenderText(true);
314 labelPaint.setTextSize(10 * SK_Scalar1);
315 canvas->drawText(gStyles[style].fName,
316 strlen(gStyles[style].fName),
317 0, rect.height() + 12 * SK_Scalar1,
318 labelPaint);
319 canvas->drawText(gFills[fill].fName,
320 strlen(gFills[fill].fName),
321 0, rect.height() + 24 * SK_Scalar1,
322 labelPaint);
323 canvas->drawText(gCaps[cap].fName,
324 strlen(gCaps[cap].fName),
325 0, rect.height() + 36 * SK_Scalar1,
326 labelPaint);
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000327 }
328 canvas->restore();
329 }
330 canvas->restore();
331 }
332 canvas->restore();
333 canvas->restore();
334 }
rmistry@google.comd6176b02012-08-23 18:14:13 +0000335
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000336private:
reed@google.com27b90fa2013-03-08 18:44:01 +0000337 typedef skiagm::GM INHERITED;
schenney@chromium.org4da06ab2011-12-20 15:14:18 +0000338};
339
340//////////////////////////////////////////////////////////////////////////////
341
reed@google.com27b90fa2013-03-08 18:44:01 +0000342DEF_GM( return new CubicPathGM; )
343DEF_GM( return new CubicClosePathGM; )
reed@google.com22999c62013-05-23 19:30:48 +0000344DEF_GM( return new ClippedCubicGM; )