1dceecc70a881508998323fd07dba270b07c53d7freed@google.com/*
2dceecc70a881508998323fd07dba270b07c53d7freed@google.com * Copyright 2012 Google Inc.
3dceecc70a881508998323fd07dba270b07c53d7freed@google.com *
4dceecc70a881508998323fd07dba270b07c53d7freed@google.com * Use of this source code is governed by a BSD-style license that can be
5dceecc70a881508998323fd07dba270b07c53d7freed@google.com * found in the LICENSE file.
6dceecc70a881508998323fd07dba270b07c53d7freed@google.com */
7dceecc70a881508998323fd07dba270b07c53d7freed@google.com
8dceecc70a881508998323fd07dba270b07c53d7freed@google.com#include "SkBitmap.h"
9dceecc70a881508998323fd07dba270b07c53d7freed@google.com#include "SkCanvas.h"
101df888bc3a502279eb46e6a71fbf257e1de940edreed@google.com#include "SkDashPathEffect.h"
11f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com#include "SkSurface.h"
128f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "Test.h"
13dceecc70a881508998323fd07dba270b07c53d7freed@google.com
14f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com// test that we can draw an aa-rect at coordinates > 32K (bigger than fixedpoint)
15f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.comstatic void test_big_aa_rect(skiatest::Reporter* reporter) {
16f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    SkBitmap output;
17f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    SkPMColor pixel[1];
1800f8d6c75d22ce8f95f932c5b101354b196fa0dfcommit-bot@chromium.org    output.installPixels(SkImageInfo::MakeN32Premul(1, 1), pixel, 4);
19f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com
20d28ba8010c6058bf073f7e815d5b2d7fdf698601reed@google.com    SkSurface* surf = SkSurface::NewRasterPMColor(300, 33300);
21f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    SkCanvas* canvas = surf->getCanvas();
22f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com
23f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    SkRect r = { 0, 33000, 300, 33300 };
24f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    int x = SkScalarRoundToInt(r.left());
25f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    int y = SkScalarRoundToInt(r.top());
26f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com
27f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    // check that the pixel in question starts as transparent (by the surface)
28f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    if (canvas->readPixels(&output, x, y)) {
29f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com        REPORTER_ASSERT(reporter, 0 == pixel[0]);
30f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    } else {
319f842d390499e7900e25767fc27504669455374bmtklein@google.com        REPORTER_ASSERT_MESSAGE(reporter, false, "readPixels failed");
32f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    }
33f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com
34f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    SkPaint paint;
35f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    paint.setAntiAlias(true);
36f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    paint.setColor(SK_ColorWHITE);
37f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com
38f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    canvas->drawRect(r, paint);
39f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com
40f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    // Now check that it is BLACK
41f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    if (canvas->readPixels(&output, x, y)) {
42f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com        // don't know what swizzling PMColor did, but white should always
43f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com        // appear the same.
44f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com        REPORTER_ASSERT(reporter, 0xFFFFFFFF == pixel[0]);
45f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    } else {
469f842d390499e7900e25767fc27504669455374bmtklein@google.com        REPORTER_ASSERT_MESSAGE(reporter, false, "readPixels failed");
47f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    }
48f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com    surf->unref();
49f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com}
50f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com
51f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com///////////////////////////////////////////////////////////////////////////////
52f272e3554aec86b5d6f7ba44f81f37e5a2070bdcreed@google.com
53b59ed515644331a12c779e8051c582aa3afd625creed@google.comstatic void moveToH(SkPath* path, const uint32_t raw[]) {
54b59ed515644331a12c779e8051c582aa3afd625creed@google.com    const float* fptr = (const float*)raw;
55b59ed515644331a12c779e8051c582aa3afd625creed@google.com    path->moveTo(fptr[0], fptr[1]);
56b59ed515644331a12c779e8051c582aa3afd625creed@google.com}
57b59ed515644331a12c779e8051c582aa3afd625creed@google.com
58b59ed515644331a12c779e8051c582aa3afd625creed@google.comstatic void cubicToH(SkPath* path, const uint32_t raw[]) {
59b59ed515644331a12c779e8051c582aa3afd625creed@google.com    const float* fptr = (const float*)raw;
60b59ed515644331a12c779e8051c582aa3afd625creed@google.com    path->cubicTo(fptr[0], fptr[1], fptr[2], fptr[3], fptr[4], fptr[5]);
61b59ed515644331a12c779e8051c582aa3afd625creed@google.com}
62b59ed515644331a12c779e8051c582aa3afd625creed@google.com
63b59ed515644331a12c779e8051c582aa3afd625creed@google.com// This used to assert, because we performed a cast (int)(pt[0].fX * scale) to
64b59ed515644331a12c779e8051c582aa3afd625creed@google.com// arrive at an int (SkFDot6) rather than calling sk_float_round2int. The assert
65b59ed515644331a12c779e8051c582aa3afd625creed@google.com// was that the initial line-segment produced by the cubic was not monotonically
66b59ed515644331a12c779e8051c582aa3afd625creed@google.com// going down (i.e. the initial DY was negative). By rounding the floats, we get
67b59ed515644331a12c779e8051c582aa3afd625creed@google.com// the more proper result.
68b59ed515644331a12c779e8051c582aa3afd625creed@google.com//
69b59ed515644331a12c779e8051c582aa3afd625creed@google.com// http://code.google.com/p/chromium/issues/detail?id=131181
70b59ed515644331a12c779e8051c582aa3afd625creed@google.com//
7105af1afd429808913683da75644e48bece12e820humper@google.com
7205af1afd429808913683da75644e48bece12e820humper@google.com// we're not calling this test anymore; is that for a reason?
7305af1afd429808913683da75644e48bece12e820humper@google.com
7454f0d1b7113cb0dc184e522539aab1030a28a421sugoi@google.comstatic void test_crbug131181() {
75b59ed515644331a12c779e8051c582aa3afd625creed@google.com    /*
76b59ed515644331a12c779e8051c582aa3afd625creed@google.com     fX = 18.8943768,
77b59ed515644331a12c779e8051c582aa3afd625creed@google.com     fY = 129.121277
78b59ed515644331a12c779e8051c582aa3afd625creed@google.com     }, {
79b59ed515644331a12c779e8051c582aa3afd625creed@google.com     fX = 18.8937435,
80b59ed515644331a12c779e8051c582aa3afd625creed@google.com     fY = 129.121689
81b59ed515644331a12c779e8051c582aa3afd625creed@google.com     }, {
82b59ed515644331a12c779e8051c582aa3afd625creed@google.com     fX = 18.8950119,
83b59ed515644331a12c779e8051c582aa3afd625creed@google.com     fY = 129.120422
84b59ed515644331a12c779e8051c582aa3afd625creed@google.com     }, {
85b59ed515644331a12c779e8051c582aa3afd625creed@google.com     fX = 18.5030727,
86b59ed515644331a12c779e8051c582aa3afd625creed@google.com     fY = 129.13121
87b59ed515644331a12c779e8051c582aa3afd625creed@google.com     */
88b59ed515644331a12c779e8051c582aa3afd625creed@google.com    uint32_t data[] = {
89b59ed515644331a12c779e8051c582aa3afd625creed@google.com        0x419727af, 0x43011f0c, 0x41972663, 0x43011f27,
90b59ed515644331a12c779e8051c582aa3afd625creed@google.com        0x419728fc, 0x43011ed4, 0x4194064b, 0x43012197
91b59ed515644331a12c779e8051c582aa3afd625creed@google.com    };
92d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
93b59ed515644331a12c779e8051c582aa3afd625creed@google.com    SkPath path;
94b59ed515644331a12c779e8051c582aa3afd625creed@google.com    moveToH(&path, &data[0]);
95b59ed515644331a12c779e8051c582aa3afd625creed@google.com    cubicToH(&path, &data[2]);
96d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
973107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    SkAutoTUnref<SkCanvas> canvas(SkCanvas::NewRasterN32(640, 480));
98d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
99b59ed515644331a12c779e8051c582aa3afd625creed@google.com    SkPaint paint;
100b59ed515644331a12c779e8051c582aa3afd625creed@google.com    paint.setAntiAlias(true);
101b59ed515644331a12c779e8051c582aa3afd625creed@google.com    canvas->drawPath(path, paint);
102b59ed515644331a12c779e8051c582aa3afd625creed@google.com}
103b59ed515644331a12c779e8051c582aa3afd625creed@google.com
104e2faf17bcc523557e44ef443b48a53f286886a53reed@google.com// This used to assert in debug builds (and crash writing bad memory in release)
105e2faf17bcc523557e44ef443b48a53f286886a53reed@google.com// because we overflowed an intermediate value (B coefficient) setting up our
106e2faf17bcc523557e44ef443b48a53f286886a53reed@google.com// stepper for the quadratic. Now we bias that value by 1/2 so we don't overflow
10754f0d1b7113cb0dc184e522539aab1030a28a421sugoi@google.comstatic void test_crbug_140803() {
108e2faf17bcc523557e44ef443b48a53f286886a53reed@google.com    SkBitmap bm;
109fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org    bm.allocN32Pixels(2700, 30*1024);
110e2faf17bcc523557e44ef443b48a53f286886a53reed@google.com    SkCanvas canvas(bm);
111d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
112e2faf17bcc523557e44ef443b48a53f286886a53reed@google.com    SkPath path;
113e2faf17bcc523557e44ef443b48a53f286886a53reed@google.com    path.moveTo(2762, 20);
114e2faf17bcc523557e44ef443b48a53f286886a53reed@google.com    path.quadTo(11, 21702, 10, 21706);
115e2faf17bcc523557e44ef443b48a53f286886a53reed@google.com    SkPaint paint;
116e2faf17bcc523557e44ef443b48a53f286886a53reed@google.com    paint.setAntiAlias(true);
117e2faf17bcc523557e44ef443b48a53f286886a53reed@google.com    canvas.drawPath(path, paint);
118e2faf17bcc523557e44ef443b48a53f286886a53reed@google.com}
119e2faf17bcc523557e44ef443b48a53f286886a53reed@google.com
1209d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com// Need to exercise drawing an inverse-path whose bounds intersect the clip,
1219d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com// but whose edges do not (since its a quad which draws only in the bottom half
1229d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com// of its bounds).
1239d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com// In the debug build, we used to assert in this case, until it was fixed.
1249d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com//
12554f0d1b7113cb0dc184e522539aab1030a28a421sugoi@google.comstatic void test_inversepathwithclip() {
1269d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    SkPath path;
127d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
1289d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    path.moveTo(0, SkIntToScalar(20));
1299d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    path.quadTo(SkIntToScalar(10), SkIntToScalar(10),
1309d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com                SkIntToScalar(20), SkIntToScalar(20));
1319d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    path.toggleInverseFillType();
1329d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com
1339d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    SkPaint paint;
1349d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com
1353107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    SkAutoTUnref<SkCanvas> canvas(SkCanvas::NewRasterN32(640, 480));
1369d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    canvas.get()->save();
1379d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    canvas.get()->clipRect(SkRect::MakeWH(SkIntToScalar(19), SkIntToScalar(11)));
1389d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com
1399d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    paint.setAntiAlias(false);
1409d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    canvas.get()->drawPath(path, paint);
1419d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    paint.setAntiAlias(true);
1429d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    canvas.get()->drawPath(path, paint);
1439d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com
1449d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    canvas.get()->restore();
145d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
1469d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    // Now do the test again, with the path flipped, so we only draw in the
1479d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    // top half of our bounds, and have the clip intersect our bounds at the
1489d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    // bottom.
1499d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    path.reset();   // preserves our filltype
1509d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    path.moveTo(0, SkIntToScalar(10));
1519d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    path.quadTo(SkIntToScalar(10), SkIntToScalar(20),
1529d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com                SkIntToScalar(20), SkIntToScalar(10));
1539d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    canvas.get()->clipRect(SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(19),
1549d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com                                            SkIntToScalar(19), SkIntToScalar(11)));
1559d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com
1569d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    paint.setAntiAlias(false);
1579d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    canvas.get()->drawPath(path, paint);
1589d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    paint.setAntiAlias(true);
1599d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com    canvas.get()->drawPath(path, paint);
1609d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com}
1619d5f76a250502620952d4aaa2926ff5bfeffc980reed@google.com
16254f0d1b7113cb0dc184e522539aab1030a28a421sugoi@google.comstatic void test_bug533() {
1636093e6582970364241a10d62b05efee50606c5e8mike@reedtribe.org    /*
1646093e6582970364241a10d62b05efee50606c5e8mike@reedtribe.org        http://code.google.com/p/skia/issues/detail?id=533
1656093e6582970364241a10d62b05efee50606c5e8mike@reedtribe.org        This particular test/bug only applies to the float case, where the
1666093e6582970364241a10d62b05efee50606c5e8mike@reedtribe.org        coordinates are very large.
1676093e6582970364241a10d62b05efee50606c5e8mike@reedtribe.org     */
1686093e6582970364241a10d62b05efee50606c5e8mike@reedtribe.org    SkPath path;
1696093e6582970364241a10d62b05efee50606c5e8mike@reedtribe.org    path.moveTo(64, 3);
1706093e6582970364241a10d62b05efee50606c5e8mike@reedtribe.org    path.quadTo(-329936, -100000000, 1153, 330003);
171d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
1726093e6582970364241a10d62b05efee50606c5e8mike@reedtribe.org    SkPaint paint;
1736093e6582970364241a10d62b05efee50606c5e8mike@reedtribe.org    paint.setAntiAlias(true);
1746093e6582970364241a10d62b05efee50606c5e8mike@reedtribe.org
1753107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    SkAutoTUnref<SkCanvas> canvas(SkCanvas::NewRasterN32(640, 480));
1766093e6582970364241a10d62b05efee50606c5e8mike@reedtribe.org    canvas.get()->drawPath(path, paint);
1776093e6582970364241a10d62b05efee50606c5e8mike@reedtribe.org}
1786093e6582970364241a10d62b05efee50606c5e8mike@reedtribe.org
17954f0d1b7113cb0dc184e522539aab1030a28a421sugoi@google.comstatic void test_crbug_140642() {
180d9ee348720f933d8a23547ee36693880296810c5reed@google.com    /*
181d9ee348720f933d8a23547ee36693880296810c5reed@google.com     *  We used to see this construct, and due to rounding as we accumulated
182d9ee348720f933d8a23547ee36693880296810c5reed@google.com     *  our length, the loop where we apply the phase would run off the end of
183d9ee348720f933d8a23547ee36693880296810c5reed@google.com     *  the array, since it relied on just -= each interval value, which did not
184d9ee348720f933d8a23547ee36693880296810c5reed@google.com     *  behave as "expected". Now the code explicitly checks for walking off the
185d9ee348720f933d8a23547ee36693880296810c5reed@google.com     *  end of that array.
186d9ee348720f933d8a23547ee36693880296810c5reed@google.com
187d9ee348720f933d8a23547ee36693880296810c5reed@google.com     *  A different (better) fix might be to rewrite dashing to do all of its
188d9ee348720f933d8a23547ee36693880296810c5reed@google.com     *  length/phase/measure math using double, but this may need to be
189d9ee348720f933d8a23547ee36693880296810c5reed@google.com     *  coordinated with SkPathMeasure, to be consistent between the two.
190d9ee348720f933d8a23547ee36693880296810c5reed@google.com
191d9ee348720f933d8a23547ee36693880296810c5reed@google.com     <path stroke="mintcream" stroke-dasharray="27734 35660 2157846850 247"
192d9ee348720f933d8a23547ee36693880296810c5reed@google.com           stroke-dashoffset="-248.135982067">
193d9ee348720f933d8a23547ee36693880296810c5reed@google.com     */
194d9ee348720f933d8a23547ee36693880296810c5reed@google.com
195d9ee348720f933d8a23547ee36693880296810c5reed@google.com    const SkScalar vals[] = { 27734, 35660, 2157846850.0f, 247 };
1960a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    SkAutoTUnref<SkDashPathEffect> dontAssert(SkDashPathEffect::Create(vals, 4, -248.135982067f));
197d9ee348720f933d8a23547ee36693880296810c5reed@google.com}
198d9ee348720f933d8a23547ee36693880296810c5reed@google.com
19954f0d1b7113cb0dc184e522539aab1030a28a421sugoi@google.comstatic void test_crbug_124652() {
2001df888bc3a502279eb46e6a71fbf257e1de940edreed@google.com    /*
2011df888bc3a502279eb46e6a71fbf257e1de940edreed@google.com        http://code.google.com/p/chromium/issues/detail?id=124652
2021df888bc3a502279eb46e6a71fbf257e1de940edreed@google.com        This particular test/bug only applies to the float case, where
2031df888bc3a502279eb46e6a71fbf257e1de940edreed@google.com        large values can "swamp" small ones.
2041df888bc3a502279eb46e6a71fbf257e1de940edreed@google.com     */
2051df888bc3a502279eb46e6a71fbf257e1de940edreed@google.com    SkScalar intervals[2] = {837099584, 33450};
20635c03fbf101306e8e82141853de4c664cbafedbbcommit-bot@chromium.org    SkAutoTUnref<SkDashPathEffect> dash(SkDashPathEffect::Create(intervals, 2, -10));
2071df888bc3a502279eb46e6a71fbf257e1de940edreed@google.com}
2081df888bc3a502279eb46e6a71fbf257e1de940edreed@google.com
20954f0d1b7113cb0dc184e522539aab1030a28a421sugoi@google.comstatic void test_bigcubic() {
210a90aa534986ffa2019b6a99260bbba086a5c608ereed@google.com    SkPath path;
211a90aa534986ffa2019b6a99260bbba086a5c608ereed@google.com    path.moveTo(64, 3);
212a90aa534986ffa2019b6a99260bbba086a5c608ereed@google.com    path.cubicTo(-329936, -100000000, -329936, 100000000, 1153, 330003);
213d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
214a90aa534986ffa2019b6a99260bbba086a5c608ereed@google.com    SkPaint paint;
215a90aa534986ffa2019b6a99260bbba086a5c608ereed@google.com    paint.setAntiAlias(true);
216d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
2173107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    SkAutoTUnref<SkCanvas> canvas(SkCanvas::NewRasterN32(640, 480));
218a90aa534986ffa2019b6a99260bbba086a5c608ereed@google.com    canvas.get()->drawPath(path, paint);
219a90aa534986ffa2019b6a99260bbba086a5c608ereed@google.com}
220a90aa534986ffa2019b6a99260bbba086a5c608ereed@google.com
221dceecc70a881508998323fd07dba270b07c53d7freed@google.com// we used to assert if the bounds of the device (clip) was larger than 32K
222dceecc70a881508998323fd07dba270b07c53d7freed@google.com// even when the path itself was smaller. We just draw and hope in the debug
223dceecc70a881508998323fd07dba270b07c53d7freed@google.com// version to not assert.
22454f0d1b7113cb0dc184e522539aab1030a28a421sugoi@google.comstatic void test_giantaa() {
225dceecc70a881508998323fd07dba270b07c53d7freed@google.com    const int W = 400;
226dceecc70a881508998323fd07dba270b07c53d7freed@google.com    const int H = 400;
2273107b6a85eee7914b37382f7145ab658e8c27667commit-bot@chromium.org    SkAutoTUnref<SkCanvas> canvas(SkCanvas::NewRasterN32(33000, 10));
228d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com
229dceecc70a881508998323fd07dba270b07c53d7freed@google.com    SkPaint paint;
230dceecc70a881508998323fd07dba270b07c53d7freed@google.com    paint.setAntiAlias(true);
231dceecc70a881508998323fd07dba270b07c53d7freed@google.com    SkPath path;
232dceecc70a881508998323fd07dba270b07c53d7freed@google.com    path.addOval(SkRect::MakeXYWH(-10, -10, 20 + W, 20 + H));
2336093e6582970364241a10d62b05efee50606c5e8mike@reedtribe.org    canvas.get()->drawPath(path, paint);
234dceecc70a881508998323fd07dba270b07c53d7freed@google.com}
235dceecc70a881508998323fd07dba270b07c53d7freed@google.com
236bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com// Extremely large path_length/dash_length ratios may cause infinite looping
237bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com// in SkDashPathEffect::filterPath() due to single precision rounding.
238bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com// The test is quite expensive, but it should get much faster after the fix
239bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com// for http://crbug.com/165432 goes in.
240bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.comstatic void test_infinite_dash(skiatest::Reporter* reporter) {
241bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com    SkPath path;
242bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com    path.moveTo(0, 0);
243bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com    path.lineTo(5000000, 0);
244bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com
245bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com    SkScalar intervals[] = { 0.2f, 0.2f };
2460a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    SkAutoTUnref<SkDashPathEffect> dash(SkDashPathEffect::Create(intervals, 2, 0));
247bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com
248bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com    SkPath filteredPath;
249bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com    SkPaint paint;
250bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com    paint.setStyle(SkPaint::kStroke_Style);
2510a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    paint.setPathEffect(dash);
252bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com
253bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com    paint.getFillPath(path, &filteredPath);
254bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com    // If we reach this, we passed.
255bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com    REPORTER_ASSERT(reporter, true);
256bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com}
257bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com
2586b18d2471fc8bc2b917eec7ceba10a6b602b9f01fmalita@google.com// http://crbug.com/165432
2596b18d2471fc8bc2b917eec7ceba10a6b602b9f01fmalita@google.com// Limit extreme dash path effects to avoid exhausting the system memory.
2606b18d2471fc8bc2b917eec7ceba10a6b602b9f01fmalita@google.comstatic void test_crbug_165432(skiatest::Reporter* reporter) {
2616b18d2471fc8bc2b917eec7ceba10a6b602b9f01fmalita@google.com    SkPath path;
2626b18d2471fc8bc2b917eec7ceba10a6b602b9f01fmalita@google.com    path.moveTo(0, 0);
2636b18d2471fc8bc2b917eec7ceba10a6b602b9f01fmalita@google.com    path.lineTo(10000000, 0);
2646b18d2471fc8bc2b917eec7ceba10a6b602b9f01fmalita@google.com
2656b18d2471fc8bc2b917eec7ceba10a6b602b9f01fmalita@google.com    SkScalar intervals[] = { 0.5f, 0.5f };
2660a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    SkAutoTUnref<SkDashPathEffect> dash(SkDashPathEffect::Create(intervals, 2, 0));
2676b18d2471fc8bc2b917eec7ceba10a6b602b9f01fmalita@google.com
2686b18d2471fc8bc2b917eec7ceba10a6b602b9f01fmalita@google.com    SkPaint paint;
2696b18d2471fc8bc2b917eec7ceba10a6b602b9f01fmalita@google.com    paint.setStyle(SkPaint::kStroke_Style);
2700a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    paint.setPathEffect(dash);
2716b18d2471fc8bc2b917eec7ceba10a6b602b9f01fmalita@google.com
2726b18d2471fc8bc2b917eec7ceba10a6b602b9f01fmalita@google.com    SkPath filteredPath;
2736b18d2471fc8bc2b917eec7ceba10a6b602b9f01fmalita@google.com    SkStrokeRec rec(paint);
2740a2bf90dccba3bde188e0386a7f0c60e6dde1ae9commit-bot@chromium.org    REPORTER_ASSERT(reporter, !dash->filterPath(&filteredPath, path, &rec, NULL));
2756b18d2471fc8bc2b917eec7ceba10a6b602b9f01fmalita@google.com    REPORTER_ASSERT(reporter, filteredPath.isEmpty());
2766b18d2471fc8bc2b917eec7ceba10a6b602b9f01fmalita@google.com}
2776b18d2471fc8bc2b917eec7ceba10a6b602b9f01fmalita@google.com
278e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.orgDEF_TEST(DrawPath, reporter) {
27954f0d1b7113cb0dc184e522539aab1030a28a421sugoi@google.com    test_giantaa();
28054f0d1b7113cb0dc184e522539aab1030a28a421sugoi@google.com    test_bug533();
28154f0d1b7113cb0dc184e522539aab1030a28a421sugoi@google.com    test_bigcubic();
28254f0d1b7113cb0dc184e522539aab1030a28a421sugoi@google.com    test_crbug_124652();
28354f0d1b7113cb0dc184e522539aab1030a28a421sugoi@google.com    test_crbug_140642();
28454f0d1b7113cb0dc184e522539aab1030a28a421sugoi@google.com    test_crbug_140803();
28554f0d1b7113cb0dc184e522539aab1030a28a421sugoi@google.com    test_inversepathwithclip();
28605af1afd429808913683da75644e48bece12e820humper@google.com    // why?
28754f0d1b7113cb0dc184e522539aab1030a28a421sugoi@google.com    if (false) test_crbug131181();
288bfa0401ab60b83abf30c7cca4c326282360948fefmalita@google.com    test_infinite_dash(reporter);
2896b18d2471fc8bc2b917eec7ceba10a6b602b9f01fmalita@google.com    test_crbug_165432(reporter);
2901c028bd395dc52ca12b99f85f0c297d15a288c2dreed@google.com    test_big_aa_rect(reporter);
291dceecc70a881508998323fd07dba270b07c53d7freed@google.com}
292