OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "gm.h" | 8 #include "gm.h" |
9 #include "SkCanvas.h" | 9 #include "SkCanvas.h" |
10 #include "SkPath.h" | 10 #include "SkPath.h" |
11 | 11 |
12 static void test_quadstroke(SkCanvas* canvas) { | |
13 SkPath path; | |
14 path.moveTo(6, 0); | |
15 path.quadTo(150, 150, 0, 6); | |
16 | |
17 SkPaint paint; | |
18 | |
19 paint.setAntiAlias(true); | |
20 paint.setStyle(SkPaint::kStroke_Style); | |
21 canvas->translate(20, 20); | |
22 | |
23 #if 1 | |
24 canvas->drawPath(path, paint); | |
25 canvas->translate(100, 0); | |
26 #endif | |
27 | |
28 paint.setStrokeWidth(1.01f); | |
29 canvas->drawPath(path, paint); | |
30 } | |
31 | |
32 static void draw_conic(SkCanvas* canvas, SkScalar weight, const SkPaint& paint)
{ | |
33 SkPath path; | |
34 path.moveTo(100, 100); | |
35 path.conicTo(300, 100, 300, 300, weight); | |
36 canvas->drawPath(path, paint); | |
37 } | |
38 | |
39 static void test_conic(SkCanvas* canvas) { | |
40 SkPaint paint; | |
41 paint.setAntiAlias(true); | |
42 paint.setStyle(SkPaint::kStroke_Style); | |
43 | |
44 static const struct { | |
45 SkScalar fWeight; | |
46 SkColor fColor; | |
47 } gRec[] = { | |
48 { 2 , SK_ColorRED }, | |
49 { 1 , SK_ColorGREEN }, | |
50 { 0.5f, SK_ColorBLUE }, | |
51 }; | |
52 | |
53 for (SkScalar width = 0; width <= 20; width += 20) { | |
54 canvas->save(); | |
55 paint.setStrokeWidth(width); | |
56 for (size_t i = 0; i < SK_ARRAY_COUNT(gRec); ++i) { | |
57 paint.setColor(gRec[i].fColor); | |
58 draw_conic(canvas, gRec[i].fWeight, paint); | |
59 canvas->translate(-30, 30); | |
60 } | |
61 canvas->restore(); | |
62 canvas->translate(300, 0); | |
63 } | |
64 } | |
65 | |
66 #include "SkGradientShader.h" | |
67 static void test_shallow_gradient(SkCanvas* canvas, SkScalar width, SkScalar hei
ght) { | |
68 SkColor colors[] = { 0xFF7F7F7F, 0xFF7F7F7F, 0xFF000000 }; | |
69 SkScalar pos[] = { 0, 0.35f, SK_Scalar1 }; | |
70 SkPoint pts[] = { { 0, 0 }, { width, height } }; | |
71 SkShader* s = SkGradientShader::CreateLinear(pts, colors, pos, | |
72 SK_ARRAY_COUNT(colors), | |
73 SkShader::kClamp_TileMode); | |
74 SkPaint paint; | |
75 paint.setShader(s)->unref(); | |
76 canvas->drawPaint(paint); | |
77 } | |
78 | |
79 #include "SkDashPathEffect.h" | |
80 static void test_giant_dash(SkCanvas* canvas) { | |
81 SkPaint paint; | |
82 const SkScalar intervals[] = { SK_Scalar1, SK_Scalar1 }; | |
83 | |
84 paint.setStrokeWidth(2); | |
85 paint.setPathEffect(new SkDashPathEffect(intervals, 2, 0))->unref(); | |
86 | |
87 SkScalar big = 500 * 1000; | |
88 | |
89 canvas->drawLine(10, 10, big, 10, paint); | |
90 canvas->drawLine(-big, 20, 500, 20, paint); | |
91 canvas->drawLine(-big, 30, big, 30, paint); | |
92 | |
93 const SkScalar intervals2[] = { 20, 5, 10, 5 }; | |
94 paint.setPathEffect(new SkDashPathEffect(intervals2, 4, 17))->unref(); | |
95 | |
96 canvas->translate(0, 40); | |
97 SkScalar x = -500; | |
98 SkScalar width = 3173; | |
99 for (int i = 0; i < 40; ++i) { | |
100 if (i > 10) | |
101 canvas->drawLine(x, 0, x + width, 0, paint); | |
102 x += 1; | |
103 canvas->translate(0, 4); | |
104 } | |
105 } | |
106 | |
107 | |
108 | |
109 // Reproduces bug found here: http://jsfiddle.net/R8Cu5/1/ | |
110 // | |
111 #include "SkGradientShader.h" | |
112 static void test_grad(SkCanvas* canvas) { | |
113 SkPoint pts[] = { | |
114 { 478.544067f, -84.2041016f }, | |
115 { 602.455933f, 625.204102f }, | |
116 }; | |
117 SkColor colors[] = { SK_ColorBLACK, SK_ColorBLACK, SK_ColorRED, SK_ColorRED
}; | |
118 SkScalar pos[] = { 0, 0.3f, 0.3f, 1.0f }; | |
119 SkShader* s = SkGradientShader::CreateLinear(pts, colors, pos, 4, SkShader::
kClamp_TileMode); | |
120 SkPaint p; | |
121 p.setShader(s)->unref(); | |
122 canvas->drawPaint(p); | |
123 } | |
124 | |
125 static SkCanvas* MakeCanvas(const SkIRect& bounds) { | |
126 SkBitmap bm; | |
127 bm.allocN32Pixels(bounds.width(), bounds.height()); | |
128 bm.eraseColor(SK_ColorTRANSPARENT); | |
129 | |
130 SkCanvas* canvas = new SkCanvas(bm); | |
131 canvas->translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop))
; | |
132 return canvas; | |
133 } | |
134 | |
135 #ifdef SK_DEBUG | |
136 static void GetBitmap(const SkCanvas* canvas, SkBitmap* bm) { | |
137 *bm = canvas->getDevice()->accessBitmap(false); | |
138 } | |
139 #endif | |
140 | |
141 static void compare_canvas(const SkCanvas* a, const SkCanvas* b) { | |
142 #ifdef SK_DEBUG | |
143 SkBitmap bma, bmb; | |
144 GetBitmap(a, &bma); | |
145 GetBitmap(b, &bmb); | |
146 | |
147 SkASSERT(bma.width() == bmb.width()); | |
148 SkASSERT(bma.height() == bmb.height()); | |
149 | |
150 bma.lockPixels(); | |
151 bmb.lockPixels(); | |
152 for (int y = 0; y < bma.height(); ++y) { | |
153 const SkPMColor* rowa = bma.getAddr32(0, y); | |
154 const SkPMColor* rowb = bmb.getAddr32(0, y); | |
155 SkASSERT(!memcmp(rowa, rowb, bma.width() << 2)); | |
156 | |
157 for (int x = 1; x < bma.width() - 1; ++x) { | |
158 SkASSERT(0xFF000000 == rowa[x]); | |
159 SkASSERT(0xFF000000 == rowb[x]); | |
160 } | |
161 } | |
162 #endif | |
163 } | |
164 | |
165 static void drawRectAsPath(SkCanvas* canvas, const SkRect& r, const SkPaint& p)
{ | |
166 SkPath path; | |
167 path.addRect(r); | |
168 canvas->drawPath(path, p); | |
169 } | |
170 | |
171 static void test_maskFromPath(const SkPath& path) { | |
172 SkIRect bounds; | |
173 path.getBounds().roundOut(&bounds); | |
174 | |
175 SkPaint paint; | |
176 paint.setAntiAlias(true); | |
177 | |
178 SkAutoTUnref<SkCanvas> path_canvas(MakeCanvas(bounds)); | |
179 path_canvas->drawPath(path, paint); | |
180 | |
181 SkAutoTUnref<SkCanvas> rect_canvas(MakeCanvas(bounds)); | |
182 drawRectAsPath(rect_canvas, path.getBounds(), paint); | |
183 | |
184 compare_canvas(path_canvas, rect_canvas); | |
185 } | |
186 | |
187 static void test_mask() { | |
188 for (int i = 1; i <= 20; ++i) { | |
189 const SkScalar dx = SK_Scalar1 / i; | |
190 const SkRect constr = SkRect::MakeWH(dx, SkIntToScalar(2)); | |
191 for (int n = 2; n < 20; ++n) { | |
192 SkPath path; | |
193 path.setFillType(SkPath::kEvenOdd_FillType); | |
194 SkRect r = constr; | |
195 while (r.fRight < SkIntToScalar(4)) { | |
196 path.addRect(r); | |
197 r.offset(dx, 0); | |
198 } | |
199 test_maskFromPath(path); | |
200 } | |
201 } | |
202 } | |
203 | |
204 /** Draw a 2px border around the target, then red behind the target; | 12 /** Draw a 2px border around the target, then red behind the target; |
205 set the clip to match the target, then draw >> the target in blue. | 13 set the clip to match the target, then draw >> the target in blue. |
206 */ | 14 */ |
207 | 15 |
208 static void draw (SkCanvas* canvas, SkRect& target, int x, int y) { | 16 static void draw(SkCanvas* canvas, SkRect& target, int x, int y) { |
209 SkPaint borderPaint; | 17 SkPaint borderPaint; |
210 borderPaint.setColor(SkColorSetRGB(0x0, 0xDD, 0x0)); | 18 borderPaint.setColor(SkColorSetRGB(0x0, 0xDD, 0x0)); |
211 borderPaint.setAntiAlias(true); | 19 borderPaint.setAntiAlias(true); |
212 SkPaint backgroundPaint; | 20 SkPaint backgroundPaint; |
213 backgroundPaint.setColor(SkColorSetRGB(0xDD, 0x0, 0x0)); | 21 backgroundPaint.setColor(SkColorSetRGB(0xDD, 0x0, 0x0)); |
214 backgroundPaint.setAntiAlias(true); | 22 backgroundPaint.setAntiAlias(true); |
215 SkPaint foregroundPaint; | 23 SkPaint foregroundPaint; |
216 foregroundPaint.setColor(SkColorSetRGB(0x0, 0x0, 0xDD)); | 24 foregroundPaint.setColor(SkColorSetRGB(0x0, 0x0, 0xDD)); |
217 foregroundPaint.setAntiAlias(true); | 25 foregroundPaint.setAntiAlias(true); |
218 | 26 |
219 canvas->save(); | 27 canvas->save(); |
220 canvas->translate(SkIntToScalar(x), SkIntToScalar(y)); | 28 canvas->translate(SkIntToScalar(x), SkIntToScalar(y)); |
221 target.inset(SkIntToScalar(-2), SkIntToScalar(-2)); | 29 target.inset(SkIntToScalar(-2), SkIntToScalar(-2)); |
222 canvas->drawRect(target, borderPaint); | 30 canvas->drawRect(target, borderPaint); |
223 target.inset(SkIntToScalar(2), SkIntToScalar(2)); | 31 target.inset(SkIntToScalar(2), SkIntToScalar(2)); |
224 canvas->drawRect(target, backgroundPaint); | 32 canvas->drawRect(target, backgroundPaint); |
225 canvas->clipRect(target, SkRegion::kIntersect_Op, true); | 33 canvas->clipRect(target, SkRegion::kIntersect_Op, true); |
226 target.inset(SkIntToScalar(-4), SkIntToScalar(-4)); | 34 target.inset(SkIntToScalar(-4), SkIntToScalar(-4)); |
227 canvas->drawRect(target, foregroundPaint); | 35 canvas->drawRect(target, foregroundPaint); |
228 canvas->restore(); | 36 canvas->restore(); |
229 } | 37 } |
230 | 38 |
231 static void draw_square (SkCanvas* canvas, int x, int y) { | 39 static void draw_square(SkCanvas* canvas, int x, int y) { |
232 SkRect target (SkRect::MakeWH(10 * SK_Scalar1, 10 * SK_Scalar1)); | 40 SkRect target (SkRect::MakeWH(10 * SK_Scalar1, 10 * SK_Scalar1)); |
233 draw(canvas, target, x, y); | 41 draw(canvas, target, x, y); |
234 } | 42 } |
235 | 43 |
236 static void draw_column (SkCanvas* canvas, int x, int y) { | 44 static void draw_column(SkCanvas* canvas, int x, int y) { |
237 SkRect target (SkRect::MakeWH(1 * SK_Scalar1, 10 * SK_Scalar1)); | 45 SkRect target (SkRect::MakeWH(1 * SK_Scalar1, 10 * SK_Scalar1)); |
238 draw(canvas, target, x, y); | 46 draw(canvas, target, x, y); |
239 } | 47 } |
240 | 48 |
241 static void draw_bar (SkCanvas* canvas, int x, int y) { | 49 static void draw_bar(SkCanvas* canvas, int x, int y) { |
242 SkRect target (SkRect::MakeWH(10 * SK_Scalar1, 1 * SK_Scalar1)); | 50 SkRect target (SkRect::MakeWH(10 * SK_Scalar1, 1 * SK_Scalar1)); |
243 draw(canvas, target, x, y); | 51 draw(canvas, target, x, y); |
244 } | 52 } |
245 | 53 |
246 static void draw_rect_tests (SkCanvas* canvas) { | 54 static void draw_rect_tests(SkCanvas* canvas) { |
247 draw_square(canvas, 10, 10); | 55 draw_square(canvas, 10, 10); |
248 draw_column(canvas, 30, 10); | 56 draw_column(canvas, 30, 10); |
249 draw_bar(canvas, 10, 30); | 57 draw_bar(canvas, 10, 30); |
250 } | 58 } |
251 | 59 |
252 /** | 60 /** |
253 Test a set of clipping problems discovered while writing blitAntiRect, | 61 Test a set of clipping problems discovered while writing blitAntiRect, |
254 and test all the code paths through the clipping blitters. | 62 and test all the code paths through the clipping blitters. |
255 Each region should show as a blue center surrounded by a 2px green | 63 Each region should show as a blue center surrounded by a 2px green |
256 border, with no red. | 64 border, with no red. |
257 */ | 65 */ |
258 | 66 |
259 class AAClipGM : public skiagm::GM { | 67 class AAClipGM : public skiagm::GM { |
260 public: | 68 public: |
261 AAClipGM() { | 69 AAClipGM() { |
262 | 70 |
263 } | 71 } |
264 | 72 |
265 protected: | 73 protected: |
266 virtual SkString onShortName() SK_OVERRIDE { | 74 virtual SkString onShortName() SK_OVERRIDE { |
267 return SkString("aaclip"); | 75 return SkString("aaclip"); |
268 } | 76 } |
269 | 77 |
270 virtual SkISize onISize() SK_OVERRIDE { | 78 virtual SkISize onISize() SK_OVERRIDE { |
271 return SkISize::Make(640, 480); | 79 return SkISize::Make(640, 480); |
272 } | 80 } |
273 | 81 |
274 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { | 82 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { |
275 if (false) { test_quadstroke(canvas); return; } | |
276 if (false) { test_conic(canvas); return; } | |
277 if (false) { | |
278 SkRect bounds; | |
279 canvas->getClipBounds(&bounds); | |
280 test_shallow_gradient(canvas, bounds.width(), bounds.height()); retu
rn; | |
281 } | |
282 if (false) { | |
283 test_giant_dash(canvas); return; | |
284 } | |
285 if (false) { | |
286 test_grad(canvas); return; | |
287 } | |
288 if (false) { // avoid bit rot, suppress warning | |
289 test_mask(); | |
290 } | |
291 | |
292 // Initial pixel-boundary-aligned draw | 83 // Initial pixel-boundary-aligned draw |
293 draw_rect_tests(canvas); | 84 draw_rect_tests(canvas); |
294 | 85 |
295 // Repeat 4x with .2, .4, .6, .8 px offsets | 86 // Repeat 4x with .2, .4, .6, .8 px offsets |
296 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5); | 87 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5); |
297 canvas->translate(SkIntToScalar(50), 0); | 88 canvas->translate(SkIntToScalar(50), 0); |
298 draw_rect_tests(canvas); | 89 draw_rect_tests(canvas); |
299 | 90 |
300 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5); | 91 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5); |
301 canvas->translate(SkIntToScalar(50), 0); | 92 canvas->translate(SkIntToScalar(50), 0); |
302 draw_rect_tests(canvas); | 93 draw_rect_tests(canvas); |
303 | 94 |
304 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5); | 95 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5); |
305 canvas->translate(SkIntToScalar(50), 0); | 96 canvas->translate(SkIntToScalar(50), 0); |
306 draw_rect_tests(canvas); | 97 draw_rect_tests(canvas); |
307 | 98 |
308 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5); | 99 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5); |
309 canvas->translate(SkIntToScalar(50), 0); | 100 canvas->translate(SkIntToScalar(50), 0); |
310 draw_rect_tests(canvas); | 101 draw_rect_tests(canvas); |
311 } | 102 } |
312 | 103 |
313 virtual uint32_t onGetFlags() const { return kSkipPipe_Flag; } | 104 virtual uint32_t onGetFlags() const { return kSkipPipe_Flag; } |
314 | 105 |
315 private: | 106 private: |
316 typedef skiagm::GM INHERITED; | 107 typedef skiagm::GM INHERITED; |
317 }; | 108 }; |
318 | 109 |
319 DEF_GM( return SkNEW(AAClipGM); ) | 110 DEF_GM( return SkNEW(AAClipGM); ) |
OLD | NEW |