blob: f67ac17a9f8a4b20d00e8ef613eece4a5017e4cf [file] [log] [blame]
tomhudson@google.comef279d32011-12-21 14:27:14 +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
8#include "gm.h"
9#include "SkCanvas.h"
10#include "SkPath.h"
11
reed@google.com5aff0ef2012-05-09 15:04:11 +000012static SkCanvas* MakeCanvas(const SkIRect& bounds) {
13 SkBitmap bm;
14 bm.setConfig(SkBitmap::kARGB_8888_Config, bounds.width(), bounds.height());
15 bm.allocPixels();
16 bm.eraseColor(0);
17
18 SkCanvas* canvas = new SkCanvas(bm);
19 canvas->translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop));
20 return canvas;
21}
22
23static void GetBitmap(const SkCanvas* canvas, SkBitmap* bm) {
24 *bm = canvas->getDevice()->accessBitmap(false);
25}
26
27static void compare_canvas(const SkCanvas* a, const SkCanvas* b) {
28 SkBitmap bma, bmb;
29 GetBitmap(a, &bma);
30 GetBitmap(b, &bmb);
31
32 SkASSERT(bma.width() == bmb.width());
33 SkASSERT(bma.height() == bmb.height());
34
35 bma.lockPixels();
36 bmb.lockPixels();
37 for (int y = 0; y < bma.height(); ++y) {
38 const SkPMColor* rowa = bma.getAddr32(0, y);
39 const SkPMColor* rowb = bmb.getAddr32(0, y);
40 SkASSERT(!memcmp(rowa, rowb, bma.width() << 2));
rmistry@google.comd6176b02012-08-23 18:14:13 +000041
reed@google.com5aff0ef2012-05-09 15:04:11 +000042 for (int x = 1; x < bma.width() - 1; ++x) {
43 SkASSERT(0xFF000000 == rowa[x]);
44 SkASSERT(0xFF000000 == rowb[x]);
45 }
46 }
47}
48
49static void drawRectAsPath(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
50 SkPath path;
51 path.addRect(r);
52 canvas->drawPath(path, p);
53}
54
55static void test_maskFromPath(const SkPath& path) {
56 SkIRect bounds;
57 path.getBounds().roundOut(&bounds);
58
59 SkPaint paint;
60 paint.setAntiAlias(true);
61
62 SkAutoTUnref<SkCanvas> path_canvas(MakeCanvas(bounds));
63 path_canvas->drawPath(path, paint);
64
65 SkAutoTUnref<SkCanvas> rect_canvas(MakeCanvas(bounds));
66 drawRectAsPath(rect_canvas, path.getBounds(), paint);
67
68 compare_canvas(path_canvas, rect_canvas);
69}
70
71static void test_mask() {
72 for (int i = 1; i <= 20; ++i) {
73 const SkScalar dx = SK_Scalar1 / i;
74 const SkRect constr = SkRect::MakeWH(dx, SkIntToScalar(2));
75 for (int n = 2; n < 20; ++n) {
76 SkPath path;
77 path.setFillType(SkPath::kEvenOdd_FillType);
78 SkRect r = constr;
79 while (r.fRight < SkIntToScalar(4)) {
80 path.addRect(r);
81 r.offset(dx, 0);
82 }
83 test_maskFromPath(path);
84 }
85 }
86}
87
tomhudson@google.comef279d32011-12-21 14:27:14 +000088namespace skiagm {
89
90/** Draw a 2px border around the target, then red behind the target;
91 set the clip to match the target, then draw >> the target in blue.
92*/
93
caryclark@google.com13130862012-06-06 12:10:45 +000094static void draw (SkCanvas* canvas, SkRect& target, int x, int y) {
tomhudson@google.comef279d32011-12-21 14:27:14 +000095 SkPaint borderPaint;
96 borderPaint.setColor(SkColorSetRGB(0x0, 0xDD, 0x0));
97 borderPaint.setAntiAlias(true);
98 SkPaint backgroundPaint;
99 backgroundPaint.setColor(SkColorSetRGB(0xDD, 0x0, 0x0));
100 backgroundPaint.setAntiAlias(true);
101 SkPaint foregroundPaint;
102 foregroundPaint.setColor(SkColorSetRGB(0x0, 0x0, 0xDD));
103 foregroundPaint.setAntiAlias(true);
104
105 canvas->save();
tomhudson@google.comabfa8d12011-12-28 19:40:48 +0000106 canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
107 target.inset(SkIntToScalar(-2), SkIntToScalar(-2));
tomhudson@google.comef279d32011-12-21 14:27:14 +0000108 canvas->drawRect(target, borderPaint);
tomhudson@google.comabfa8d12011-12-28 19:40:48 +0000109 target.inset(SkIntToScalar(2), SkIntToScalar(2));
tomhudson@google.comef279d32011-12-21 14:27:14 +0000110 canvas->drawRect(target, backgroundPaint);
111 canvas->clipRect(target, SkRegion::kIntersect_Op, true);
tomhudson@google.comabfa8d12011-12-28 19:40:48 +0000112 target.inset(SkIntToScalar(-4), SkIntToScalar(-4));
tomhudson@google.comef279d32011-12-21 14:27:14 +0000113 canvas->drawRect(target, foregroundPaint);
114 canvas->restore();
115}
116
caryclark@google.com13130862012-06-06 12:10:45 +0000117static void draw_square (SkCanvas* canvas, int x, int y) {
tomhudson@google.comef279d32011-12-21 14:27:14 +0000118 SkRect target (SkRect::MakeWH(10 * SK_Scalar1, 10 * SK_Scalar1));
119 draw(canvas, target, x, y);
120}
121
caryclark@google.com13130862012-06-06 12:10:45 +0000122static void draw_column (SkCanvas* canvas, int x, int y) {
tomhudson@google.comef279d32011-12-21 14:27:14 +0000123 SkRect target (SkRect::MakeWH(1 * SK_Scalar1, 10 * SK_Scalar1));
124 draw(canvas, target, x, y);
125}
126
caryclark@google.com13130862012-06-06 12:10:45 +0000127static void draw_bar (SkCanvas* canvas, int x, int y) {
tomhudson@google.comef279d32011-12-21 14:27:14 +0000128 SkRect target (SkRect::MakeWH(10 * SK_Scalar1, 1 * SK_Scalar1));
129 draw(canvas, target, x, y);
130}
131
caryclark@google.com13130862012-06-06 12:10:45 +0000132static void draw_rect_tests (SkCanvas* canvas) {
tomhudson@google.comef279d32011-12-21 14:27:14 +0000133 draw_square(canvas, 10, 10);
134 draw_column(canvas, 30, 10);
135 draw_bar(canvas, 10, 30);
136}
137
138/**
139 Test a set of clipping problems discovered while writing blitAntiRect,
140 and test all the code paths through the clipping blitters.
141 Each region should show as a blue center surrounded by a 2px green
142 border, with no red.
143*/
144
145class AAClipGM : public GM {
146public:
147 AAClipGM() {
reed@google.com71121732012-09-18 15:14:33 +0000148
tomhudson@google.comef279d32011-12-21 14:27:14 +0000149 }
150
151protected:
152 virtual SkString onShortName() {
153 return SkString("aaclip");
154 }
155
156 virtual SkISize onISize() {
157 return make_isize(640, 480);
158 }
159
160 virtual void onDraw(SkCanvas* canvas) {
caryclark@google.com13130862012-06-06 12:10:45 +0000161 if (false) { // avoid bit rot, suppress warning
162 test_mask();
163 }
reed@google.com5aff0ef2012-05-09 15:04:11 +0000164
tomhudson@google.comef279d32011-12-21 14:27:14 +0000165 // Initial pixel-boundary-aligned draw
166 draw_rect_tests(canvas);
167
168 // Repeat 4x with .2, .4, .6, .8 px offsets
169 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5);
tomhudson@google.comabfa8d12011-12-28 19:40:48 +0000170 canvas->translate(SkIntToScalar(50), 0);
tomhudson@google.comef279d32011-12-21 14:27:14 +0000171 draw_rect_tests(canvas);
172
173 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5);
tomhudson@google.comabfa8d12011-12-28 19:40:48 +0000174 canvas->translate(SkIntToScalar(50), 0);
tomhudson@google.comef279d32011-12-21 14:27:14 +0000175 draw_rect_tests(canvas);
176
177 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5);
tomhudson@google.comabfa8d12011-12-28 19:40:48 +0000178 canvas->translate(SkIntToScalar(50), 0);
tomhudson@google.comef279d32011-12-21 14:27:14 +0000179 draw_rect_tests(canvas);
180
181 canvas->translate(SK_Scalar1 / 5, SK_Scalar1 / 5);
tomhudson@google.comabfa8d12011-12-28 19:40:48 +0000182 canvas->translate(SkIntToScalar(50), 0);
tomhudson@google.comef279d32011-12-21 14:27:14 +0000183 draw_rect_tests(canvas);
184 }
185
borenet@google.comb4e70432012-07-20 18:45:10 +0000186 virtual uint32_t onGetFlags() const { return kSkipPipe_Flag; }
187
tomhudson@google.comef279d32011-12-21 14:27:14 +0000188private:
189 typedef GM INHERITED;
190};
191
192//////////////////////////////////////////////////////////////////////////////
193
194static GM* MyFactory(void*) { return new AAClipGM; }
195static GMRegistry reg(MyFactory);
196
197}