OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright 2013 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 "SkCanvas.h" | |
10 #include "SkPath.h" | |
11 | |
12 namespace skiagm { | |
13 | |
14 // This GM tests a grab-bag of non-closed paths. All these paths look like | |
15 // closed rects, but they don't call path.close(). Depending on the stroke | |
16 // settings these slightly different paths give widely different results. | |
17 class NonClosedPathsGM: public GM { | |
18 public: | |
19 NonClosedPathsGM() {} | |
20 | |
21 enum ClosureType { | |
robertphillips
2013/11/08 18:13:29
Please line up the comment.
| |
22 TotallyNonClosed, // The last point doesn't coincide with the first o ne in the contour. | |
23 // The path looks not closed at all. | |
24 | |
25 FakeCloseCorner, // The last point coincides with the first one at a co rner. | |
26 // The path looks closed, but final rendering has 2 en ds with cap. | |
27 | |
28 FakeCloseMiddle, // The last point coincides with the first one in the middle of a line. | |
29 // The path looks closed, and the final rendering look s closed too. | |
30 | |
31 kClosureTypeCount | |
32 }; | |
33 | |
34 protected: | |
35 virtual SkString onShortName() SK_OVERRIDE { | |
36 return SkString("nonclosedpaths"); | |
37 } | |
38 | |
39 // 12 * 18 + 3 cases, every case is 100 * 100 pixels. | |
40 virtual SkISize onISize() SK_OVERRIDE { | |
41 return SkISize::Make(1220, 1920); | |
42 } | |
43 | |
44 // Use rect-like geometry for non-closed path, for right angles make it | |
45 // easier to show the visual difference of lineCap and lineJoin. | |
46 static void MakePath(SkPath* path, ClosureType type) { | |
47 if (FakeCloseMiddle == type) { | |
48 path.moveTo(30, 50); | |
49 path.lineTo(30, 30); | |
50 } else { | |
51 path.moveTo(30, 30); | |
52 } | |
53 path.lineTo(70, 30); | |
54 path.lineTo(70, 70); | |
55 path.lineTo(30, 70); | |
56 path.lineTo(30, 50); | |
57 if (FakeCloseCorner == type) { | |
58 path.lineTo(30, 30); | |
59 } | |
60 } | |
61 | |
62 // Set the location for the current test on the canvas | |
63 static void SetLocation(SkCanvas* canvas, int counter, int lineNum) { | |
64 SkScalar x = SK_Scalar1 * 100 * (counter % lineNum) + 10 + SK_Scalar1 / 4; | |
65 SkScalar y = SK_Scalar1 * 100 * (counter / lineNum) + 10 + 3 * SK_Scalar 1 / 4; | |
66 canvas->translate(x, y); | |
67 } | |
68 | |
69 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { | |
70 // Stroke widths are: | |
71 // 0(may use hairline rendering), 10(common case for stroke-style) | |
72 // 40 and 50(>= geometry width/height, make the contour filled in fact) | |
73 static const int kStrokeWidth[] = {0, 10, 40, 50}; | |
74 size_t numWidths = SK_ARRAY_COUNT(kStrokeWidth); | |
75 | |
76 static const SkPaint::Style kStyle[] = { | |
77 SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style | |
78 }; | |
79 | |
80 static const SkPaint::Cap kCap[] = { | |
81 SkPaint::kButt_Cap, SkPaint::kRound_Cap, SkPaint::kSquare_Cap | |
82 }; | |
83 | |
84 static const SkPaint::Join kJoin[] = { | |
85 SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join | |
86 }; | |
87 | |
88 static const ClosureType kType[] = { | |
89 TotallyNonClosed, FakeCloseCorner, FakeCloseMiddle | |
90 }; | |
91 | |
92 int counter = 0; | |
93 SkPaint paint; | |
94 paint.setAntiAlias(true); | |
95 | |
96 // For stroke style painter and fill-and-stroke style painter | |
97 for (size_t type = 0; type < kClosureTypeCount; ++type) { | |
98 for (size_t style = 0; style < SK_ARRAY_COUNT(kStyle); ++style) { | |
99 for (size_t cap = 0; cap < SK_ARRAY_COUNT(kCap); ++cap) { | |
100 for (size_t join = 0; join < SK_ARRAY_COUNT(kJoin); ++join) { | |
101 for (size_t width = 0; width < numWidths; ++width) { | |
102 canvas->save(); | |
103 SetLocation(canvas, counter, SkPaint::kJoinCount * n umWidths); | |
104 | |
105 SkPath path; | |
106 MakePath(&path, kType[type]); | |
107 | |
108 paint.setStyle(kStyle[style]); | |
109 paint.setStrokeCap(kCap[cap]); | |
110 paint.setStrokeJoin(kJoin[join]); | |
111 paint.setStrokeWidth(SkIntToScalar(strokeWidth[width ])); | |
112 | |
113 canvas->drawPath(path, paint); | |
114 canvas->restore(); | |
115 ++counter; | |
116 } | |
117 } | |
118 } | |
119 } | |
120 } | |
121 | |
122 // For fill style painter | |
123 paint.setStyle(SkPaint::kFill_Style); | |
124 for (size_t type = 0; type < kClosureTypeCount; ++type) { | |
125 canvas->save(); | |
126 SetLocation(canvas, counter, SkPaint::kJoinCount * numWidths); | |
127 | |
128 SkPath path; | |
129 MakePath(&path, kType[type]); | |
130 | |
131 canvas->drawPath(path, paint); | |
132 canvas->restore(); | |
133 ++counter; | |
134 } | |
135 } | |
136 | |
137 private: | |
138 typedef GM INHERITED; | |
139 }; | |
140 | |
141 ////////////////////////////////////////////////////////////////////////////// | |
142 | |
143 DEF_GM(return new NonClosedPathsGM;) | |
144 | |
145 } | |
OLD | NEW |