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 |
12 /** Draw a 2px border around the target, then red behind the target; | 204 /** Draw a 2px border around the target, then red behind the target; |
13 set the clip to match the target, then draw >> the target in blue. | 205 set the clip to match the target, then draw >> the target in blue. |
14 */ | 206 */ |
15 | 207 |
16 static void draw(SkCanvas* canvas, SkRect& target, int x, int y) { | 208 static void draw (SkCanvas* canvas, SkRect& target, int x, int y) { |
17 SkPaint borderPaint; | 209 SkPaint borderPaint; |
18 borderPaint.setColor(SkColorSetRGB(0x0, 0xDD, 0x0)); | 210 borderPaint.setColor(SkColorSetRGB(0x0, 0xDD, 0x0)); |
19 borderPaint.setAntiAlias(true); | 211 borderPaint.setAntiAlias(true); |
20 SkPaint backgroundPaint; | 212 SkPaint backgroundPaint; |
21 backgroundPaint.setColor(SkColorSetRGB(0xDD, 0x0, 0x0)); | 213 backgroundPaint.setColor(SkColorSetRGB(0xDD, 0x0, 0x0)); |
22 backgroundPaint.setAntiAlias(true); | 214 backgroundPaint.setAntiAlias(true); |
23 SkPaint foregroundPaint; | 215 SkPaint foregroundPaint; |
24 foregroundPaint.setColor(SkColorSetRGB(0x0, 0x0, 0xDD)); | 216 foregroundPaint.setColor(SkColorSetRGB(0x0, 0x0, 0xDD)); |
25 foregroundPaint.setAntiAlias(true); | 217 foregroundPaint.setAntiAlias(true); |
26 | 218 |
27 canvas->save(); | 219 canvas->save(); |
28 canvas->translate(SkIntToScalar(x), SkIntToScalar(y)); | 220 canvas->translate(SkIntToScalar(x), SkIntToScalar(y)); |
29 target.inset(SkIntToScalar(-2), SkIntToScalar(-2)); | 221 target.inset(SkIntToScalar(-2), SkIntToScalar(-2)); |
30 canvas->drawRect(target, borderPaint); | 222 canvas->drawRect(target, borderPaint); |
31 target.inset(SkIntToScalar(2), SkIntToScalar(2)); | 223 target.inset(SkIntToScalar(2), SkIntToScalar(2)); |
32 canvas->drawRect(target, backgroundPaint); | 224 canvas->drawRect(target, backgroundPaint); |
33 canvas->clipRect(target, SkRegion::kIntersect_Op, true); | 225 canvas->clipRect(target, SkRegion::kIntersect_Op, true); |
34 target.inset(SkIntToScalar(-4), SkIntToScalar(-4)); | 226 target.inset(SkIntToScalar(-4), SkIntToScalar(-4)); |
35 canvas->drawRect(target, foregroundPaint); | 227 canvas->drawRect(target, foregroundPaint); |
36 canvas->restore(); | 228 canvas->restore(); |
37 } | 229 } |
38 | 230 |
39 static void draw_square(SkCanvas* canvas, int x, int y) { | 231 static void draw_square (SkCanvas* canvas, int x, int y) { |
40 SkRect target (SkRect::MakeWH(10 * SK_Scalar1, 10 * SK_Scalar1)); | 232 SkRect target (SkRect::MakeWH(10 * SK_Scalar1, 10 * SK_Scalar1)); |
41 draw(canvas, target, x, y); | 233 draw(canvas, target, x, y); |
42 } | 234 } |
43 | 235 |
44 static void draw_column(SkCanvas* canvas, int x, int y) { | 236 static void draw_column (SkCanvas* canvas, int x, int y) { |
45 SkRect target (SkRect::MakeWH(1 * SK_Scalar1, 10 * SK_Scalar1)); | 237 SkRect target (SkRect::MakeWH(1 * SK_Scalar1, 10 * SK_Scalar1)); |
46 draw(canvas, target, x, y); | 238 draw(canvas, target, x, y); |
47 } | 239 } |
48 | 240 |
49 static void draw_bar(SkCanvas* canvas, int x, int y) { | 241 static void draw_bar (SkCanvas* canvas, int x, int y) { |
50 SkRect target (SkRect::MakeWH(10 * SK_Scalar1, 1 * SK_Scalar1)); | 242 SkRect target (SkRect::MakeWH(10 * SK_Scalar1, 1 * SK_Scalar1)); |
51 draw(canvas, target, x, y); | 243 draw(canvas, target, x, y); |
52 } | 244 } |
53 | 245 |
54 static void draw_rect_tests(SkCanvas* canvas) { | 246 static void draw_rect_tests (SkCanvas* canvas) { |
55 draw_square(canvas, 10, 10); | 247 draw_square(canvas, 10, 10); |
56 draw_column(canvas, 30, 10); | 248 draw_column(canvas, 30, 10); |
57 draw_bar(canvas, 10, 30); | 249 draw_bar(canvas, 10, 30); |
58 } | 250 } |
59 | 251 |
60 /** | 252 /** |
61 Test a set of clipping problems discovered while writing blitAntiRect, | 253 Test a set of clipping problems discovered while writing blitAntiRect, |
62 and test all the code paths through the clipping blitters. | 254 and test all the code paths through the clipping blitters. |
63 Each region should show as a blue center surrounded by a 2px green | 255 Each region should show as a blue center surrounded by a 2px green |
64 border, with no red. | 256 border, with no red. |
65 */ | 257 */ |
66 | 258 |
67 class AAClipGM : public skiagm::GM { | 259 class AAClipGM : public skiagm::GM { |
68 public: | 260 public: |
69 AAClipGM() { | 261 AAClipGM() { |
70 | 262 |
71 } | 263 } |
72 | 264 |
73 protected: | 265 protected: |
74 virtual SkString onShortName() SK_OVERRIDE { | 266 virtual SkString onShortName() SK_OVERRIDE { |
75 return SkString("aaclip"); | 267 return SkString("aaclip"); |
76 } | 268 } |
77 | 269 |
78 virtual SkISize onISize() SK_OVERRIDE { | 270 virtual SkISize onISize() SK_OVERRIDE { |
79 return SkISize::Make(640, 480); | 271 return SkISize::Make(640, 480); |
80 } | 272 } |
81 | 273 |
82 virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { | 274 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 |
83 // Initial pixel-boundary-aligned draw | 292 // Initial pixel-boundary-aligned draw |
84 draw_rect_tests(canvas); | 293 draw_rect_tests(canvas); |
85 | 294 |
86 // Repeat 4x with .2, .4, .6, .8 px offsets | 295 // Repeat 4x with .2, .4, .6, .8 px offsets |
87 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5); | 296 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5); |
88 canvas->translate(SkIntToScalar(50), 0); | 297 canvas->translate(SkIntToScalar(50), 0); |
89 draw_rect_tests(canvas); | 298 draw_rect_tests(canvas); |
90 | 299 |
91 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5); | 300 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5); |
92 canvas->translate(SkIntToScalar(50), 0); | 301 canvas->translate(SkIntToScalar(50), 0); |
93 draw_rect_tests(canvas); | 302 draw_rect_tests(canvas); |
94 | 303 |
95 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5); | 304 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5); |
96 canvas->translate(SkIntToScalar(50), 0); | 305 canvas->translate(SkIntToScalar(50), 0); |
97 draw_rect_tests(canvas); | 306 draw_rect_tests(canvas); |
98 | 307 |
99 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5); | 308 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5); |
100 canvas->translate(SkIntToScalar(50), 0); | 309 canvas->translate(SkIntToScalar(50), 0); |
101 draw_rect_tests(canvas); | 310 draw_rect_tests(canvas); |
102 } | 311 } |
103 | 312 |
104 virtual uint32_t onGetFlags() const { return kSkipPipe_Flag; } | 313 virtual uint32_t onGetFlags() const { return kSkipPipe_Flag; } |
105 | 314 |
106 private: | 315 private: |
107 typedef skiagm::GM INHERITED; | 316 typedef skiagm::GM INHERITED; |
108 }; | 317 }; |
109 | 318 |
110 DEF_GM( return SkNEW(AAClipGM); ) | 319 DEF_GM( return SkNEW(AAClipGM); ) |
OLD | NEW |