blob: 947bf8802903c20d32b7fb3340f181a1ed9c0e64 [file] [log] [blame]
reed@google.comdceecc72012-02-23 19:20:19 +00001/*
2 * Copyright 2012 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 "Test.h"
9#include "SkBitmap.h"
10#include "SkCanvas.h"
reed@google.com1df888b2012-04-24 22:47:21 +000011#include "SkDashPathEffect.h"
reed@google.comdceecc72012-02-23 19:20:19 +000012
13static SkCanvas* create(SkBitmap::Config config, int w, int h, int rb,
14 void* addr = NULL) {
15 SkBitmap bm;
16 bm.setConfig(config, w, h, rb);
17 if (addr) {
18 bm.setPixels(addr);
19 } else {
20 bm.allocPixels();
21 }
22 return new SkCanvas(bm);
23}
24
mike@reedtribe.org6093e652012-04-14 12:55:17 +000025static SkCanvas* new_canvas(int w, int h) {
26 return create(SkBitmap::kARGB_8888_Config, w, h, 0, NULL);
27}
28
reed@google.coma90aa532012-04-16 16:27:09 +000029///////////////////////////////////////////////////////////////////////////////
30
reed@google.comb59ed512012-06-15 18:26:04 +000031static void moveToH(SkPath* path, const uint32_t raw[]) {
32 const float* fptr = (const float*)raw;
33 path->moveTo(fptr[0], fptr[1]);
34}
35
36static void cubicToH(SkPath* path, const uint32_t raw[]) {
37 const float* fptr = (const float*)raw;
38 path->cubicTo(fptr[0], fptr[1], fptr[2], fptr[3], fptr[4], fptr[5]);
39}
40
41// This used to assert, because we performed a cast (int)(pt[0].fX * scale) to
42// arrive at an int (SkFDot6) rather than calling sk_float_round2int. The assert
43// was that the initial line-segment produced by the cubic was not monotonically
44// going down (i.e. the initial DY was negative). By rounding the floats, we get
45// the more proper result.
46//
47// http://code.google.com/p/chromium/issues/detail?id=131181
48//
49static void test_crbug131181(skiatest::Reporter*) {
50 /*
51 fX = 18.8943768,
52 fY = 129.121277
53 }, {
54 fX = 18.8937435,
55 fY = 129.121689
56 }, {
57 fX = 18.8950119,
58 fY = 129.120422
59 }, {
60 fX = 18.5030727,
61 fY = 129.13121
62 */
63 uint32_t data[] = {
64 0x419727af, 0x43011f0c, 0x41972663, 0x43011f27,
65 0x419728fc, 0x43011ed4, 0x4194064b, 0x43012197
66 };
67
68 SkPath path;
69 moveToH(&path, &data[0]);
70 cubicToH(&path, &data[2]);
71
72 SkAutoTUnref<SkCanvas> canvas(new_canvas(640, 480));
73
74 SkPaint paint;
75 paint.setAntiAlias(true);
76 canvas->drawPath(path, paint);
77}
78
reed@google.com9d5f76a2012-05-01 14:49:28 +000079// Need to exercise drawing an inverse-path whose bounds intersect the clip,
80// but whose edges do not (since its a quad which draws only in the bottom half
81// of its bounds).
82// In the debug build, we used to assert in this case, until it was fixed.
83//
84static void test_inversepathwithclip(skiatest::Reporter* reporter) {
85 SkPath path;
86
87 path.moveTo(0, SkIntToScalar(20));
88 path.quadTo(SkIntToScalar(10), SkIntToScalar(10),
89 SkIntToScalar(20), SkIntToScalar(20));
90 path.toggleInverseFillType();
91
92 SkPaint paint;
93
94 SkAutoTUnref<SkCanvas> canvas(new_canvas(640, 480));
95 canvas.get()->save();
96 canvas.get()->clipRect(SkRect::MakeWH(SkIntToScalar(19), SkIntToScalar(11)));
97
98 paint.setAntiAlias(false);
99 canvas.get()->drawPath(path, paint);
100 paint.setAntiAlias(true);
101 canvas.get()->drawPath(path, paint);
102
103 canvas.get()->restore();
104
105 // Now do the test again, with the path flipped, so we only draw in the
106 // top half of our bounds, and have the clip intersect our bounds at the
107 // bottom.
108 path.reset(); // preserves our filltype
109 path.moveTo(0, SkIntToScalar(10));
110 path.quadTo(SkIntToScalar(10), SkIntToScalar(20),
111 SkIntToScalar(20), SkIntToScalar(10));
112 canvas.get()->clipRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(19),
113 SkIntToScalar(19), SkIntToScalar(11)));
114
115 paint.setAntiAlias(false);
116 canvas.get()->drawPath(path, paint);
117 paint.setAntiAlias(true);
118 canvas.get()->drawPath(path, paint);
119}
120
mike@reedtribe.org6093e652012-04-14 12:55:17 +0000121static void test_bug533(skiatest::Reporter* reporter) {
122#ifdef SK_SCALAR_IS_FLOAT
123 /*
124 http://code.google.com/p/skia/issues/detail?id=533
125 This particular test/bug only applies to the float case, where the
126 coordinates are very large.
127 */
128 SkPath path;
129 path.moveTo(64, 3);
130 path.quadTo(-329936, -100000000, 1153, 330003);
131
132 SkPaint paint;
133 paint.setAntiAlias(true);
134
135 SkAutoTUnref<SkCanvas> canvas(new_canvas(640, 480));
136 canvas.get()->drawPath(path, paint);
137#endif
138}
139
reed@google.com1df888b2012-04-24 22:47:21 +0000140static void test_crbug_124652(skiatest::Reporter* reporter) {
141#ifdef SK_SCALAR_IS_FLOAT
142 /*
143 http://code.google.com/p/chromium/issues/detail?id=124652
144 This particular test/bug only applies to the float case, where
145 large values can "swamp" small ones.
146 */
147 SkScalar intervals[2] = {837099584, 33450};
148 SkAutoTUnref<SkDashPathEffect> dash(
149 new SkDashPathEffect(intervals, 2, -10, false));
150#endif
151}
152
reed@google.coma90aa532012-04-16 16:27:09 +0000153static void test_bigcubic(skiatest::Reporter* reporter) {
154#ifdef SK_SCALAR_IS_FLOAT
155 SkPath path;
156 path.moveTo(64, 3);
157 path.cubicTo(-329936, -100000000, -329936, 100000000, 1153, 330003);
158
159 SkPaint paint;
160 paint.setAntiAlias(true);
161
162 SkAutoTUnref<SkCanvas> canvas(new_canvas(640, 480));
163 canvas.get()->drawPath(path, paint);
164#endif
165}
166
reed@google.comdceecc72012-02-23 19:20:19 +0000167// we used to assert if the bounds of the device (clip) was larger than 32K
168// even when the path itself was smaller. We just draw and hope in the debug
169// version to not assert.
170static void test_giantaa(skiatest::Reporter* reporter) {
171 const int W = 400;
172 const int H = 400;
mike@reedtribe.org6093e652012-04-14 12:55:17 +0000173 SkAutoTUnref<SkCanvas> canvas(new_canvas(33000, 10));
174 canvas.get()->clear(0);
reed@google.comdceecc72012-02-23 19:20:19 +0000175
176 SkPaint paint;
177 paint.setAntiAlias(true);
178 SkPath path;
179 path.addOval(SkRect::MakeXYWH(-10, -10, 20 + W, 20 + H));
mike@reedtribe.org6093e652012-04-14 12:55:17 +0000180 canvas.get()->drawPath(path, paint);
reed@google.comdceecc72012-02-23 19:20:19 +0000181}
182
183static void TestDrawPath(skiatest::Reporter* reporter) {
184 test_giantaa(reporter);
mike@reedtribe.org6093e652012-04-14 12:55:17 +0000185 test_bug533(reporter);
reed@google.coma90aa532012-04-16 16:27:09 +0000186 test_bigcubic(reporter);
reed@google.com1df888b2012-04-24 22:47:21 +0000187 test_crbug_124652(reporter);
reed@google.com9d5f76a2012-05-01 14:49:28 +0000188 test_inversepathwithclip(reporter);
reed@google.comb59ed512012-06-15 18:26:04 +0000189// test_crbug131181(reporter);
reed@google.comdceecc72012-02-23 19:20:19 +0000190}
191
192#include "TestClassDef.h"
193DEFINE_TESTCLASS("DrawPath", TestDrawPathClass, TestDrawPath)