166560ca776773858abfffd59974eac32c942acc3caryclark@google.com/*
266560ca776773858abfffd59974eac32c942acc3caryclark@google.com * Copyright 2013 Google Inc.
366560ca776773858abfffd59974eac32c942acc3caryclark@google.com *
466560ca776773858abfffd59974eac32c942acc3caryclark@google.com * Use of this source code is governed by a BSD-style license that can be
566560ca776773858abfffd59974eac32c942acc3caryclark@google.com * found in the LICENSE file.
666560ca776773858abfffd59974eac32c942acc3caryclark@google.com */
766560ca776773858abfffd59974eac32c942acc3caryclark@google.com#include "SkPath.h"
88f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "SkPathOps.h"
966560ca776773858abfffd59974eac32c942acc3caryclark@google.com#include "SkPoint.h"
1066560ca776773858abfffd59974eac32c942acc3caryclark@google.com#include "Test.h"
1166560ca776773858abfffd59974eac32c942acc3caryclark@google.com
1266560ca776773858abfffd59974eac32c942acc3caryclark@google.comstatic const SkPoint nonFinitePts[] = {
1366560ca776773858abfffd59974eac32c942acc3caryclark@google.com    { SK_ScalarInfinity, 0 },
1466560ca776773858abfffd59974eac32c942acc3caryclark@google.com    { 0, SK_ScalarInfinity },
1566560ca776773858abfffd59974eac32c942acc3caryclark@google.com    { SK_ScalarInfinity, SK_ScalarInfinity },
1666560ca776773858abfffd59974eac32c942acc3caryclark@google.com    { SK_ScalarNegativeInfinity, 0},
1766560ca776773858abfffd59974eac32c942acc3caryclark@google.com    { 0, SK_ScalarNegativeInfinity },
1866560ca776773858abfffd59974eac32c942acc3caryclark@google.com    { SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity },
1966560ca776773858abfffd59974eac32c942acc3caryclark@google.com    { SK_ScalarNegativeInfinity, SK_ScalarInfinity },
2066560ca776773858abfffd59974eac32c942acc3caryclark@google.com    { SK_ScalarInfinity, SK_ScalarNegativeInfinity },
2166560ca776773858abfffd59974eac32c942acc3caryclark@google.com    { SK_ScalarNaN, 0 },
2266560ca776773858abfffd59974eac32c942acc3caryclark@google.com    { 0, SK_ScalarNaN },
2366560ca776773858abfffd59974eac32c942acc3caryclark@google.com    { SK_ScalarNaN, SK_ScalarNaN },
2466560ca776773858abfffd59974eac32c942acc3caryclark@google.com};
2566560ca776773858abfffd59974eac32c942acc3caryclark@google.com
2666560ca776773858abfffd59974eac32c942acc3caryclark@google.comconst size_t nonFinitePtsCount = sizeof(nonFinitePts) / sizeof(nonFinitePts[0]);
2766560ca776773858abfffd59974eac32c942acc3caryclark@google.com
2866560ca776773858abfffd59974eac32c942acc3caryclark@google.comstatic const SkPoint finitePts[] = {
2966560ca776773858abfffd59974eac32c942acc3caryclark@google.com    { 0, 0 },
3066560ca776773858abfffd59974eac32c942acc3caryclark@google.com    { SK_ScalarMax, 0 },
3166560ca776773858abfffd59974eac32c942acc3caryclark@google.com    { 0, SK_ScalarMax },
3266560ca776773858abfffd59974eac32c942acc3caryclark@google.com    { SK_ScalarMax, SK_ScalarMax },
3366560ca776773858abfffd59974eac32c942acc3caryclark@google.com    { SK_ScalarMin, 0 },
3466560ca776773858abfffd59974eac32c942acc3caryclark@google.com    { 0, SK_ScalarMin },
3566560ca776773858abfffd59974eac32c942acc3caryclark@google.com    { SK_ScalarMin, SK_ScalarMin },
3666560ca776773858abfffd59974eac32c942acc3caryclark@google.com};
3766560ca776773858abfffd59974eac32c942acc3caryclark@google.com
3866560ca776773858abfffd59974eac32c942acc3caryclark@google.comconst size_t finitePtsCount = sizeof(finitePts) / sizeof(finitePts[0]);
3966560ca776773858abfffd59974eac32c942acc3caryclark@google.com
40570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comstatic void failOne(skiatest::Reporter* reporter, int index) {
41570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    SkPath path;
42570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    int i = (int) (index % nonFinitePtsCount);
43570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    int f = (int) (index % finitePtsCount);
44570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    int g = (int) ((f + 1) % finitePtsCount);
45570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    switch (index % 13) {
46570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 0: path.lineTo(nonFinitePts[i]); break;
47570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 1: path.quadTo(nonFinitePts[i], nonFinitePts[i]); break;
48570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 2: path.quadTo(nonFinitePts[i], finitePts[f]); break;
49570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 3: path.quadTo(finitePts[f], nonFinitePts[i]); break;
50570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 4: path.cubicTo(nonFinitePts[i], finitePts[f], finitePts[f]); break;
51570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 5: path.cubicTo(finitePts[f], nonFinitePts[i], finitePts[f]); break;
52570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 6: path.cubicTo(finitePts[f], finitePts[f], nonFinitePts[i]); break;
53570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 7: path.cubicTo(nonFinitePts[i], nonFinitePts[i], finitePts[f]); break;
54570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 8: path.cubicTo(nonFinitePts[i], finitePts[f], nonFinitePts[i]); break;
55570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 9: path.cubicTo(finitePts[f], nonFinitePts[i], nonFinitePts[i]); break;
56570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 10: path.cubicTo(nonFinitePts[i], nonFinitePts[i], nonFinitePts[i]); break;
57570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 11: path.cubicTo(nonFinitePts[i], finitePts[f], finitePts[g]); break;
58570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 12: path.moveTo(nonFinitePts[i]); break;
59570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
60570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    SkPath result;
61570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    result.setFillType(SkPath::kWinding_FillType);
62570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    bool success = Simplify(path, &result);
63570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    REPORTER_ASSERT(reporter, !success);
64570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    REPORTER_ASSERT(reporter, result.isEmpty());
65570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    REPORTER_ASSERT(reporter, result.getFillType() == SkPath::kWinding_FillType);
66570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    reporter->bumpTestCount();
67570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com}
68570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
69570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.comstatic void dontFailOne(skiatest::Reporter* reporter, int index) {
70570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    SkPath path;
71570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    int f = (int) (index % finitePtsCount);
72570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    int g = (int) ((f + 1) % finitePtsCount);
73570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    switch (index % 11) {
74570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 0: path.lineTo(finitePts[f]); break;
75570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 1: path.quadTo(finitePts[f], finitePts[f]); break;
76570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 2: path.quadTo(finitePts[f], finitePts[g]); break;
77570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 3: path.quadTo(finitePts[g], finitePts[f]); break;
78570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 4: path.cubicTo(finitePts[f], finitePts[f], finitePts[f]); break;
79570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 5: path.cubicTo(finitePts[f], finitePts[f], finitePts[g]); break;
80570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 6: path.cubicTo(finitePts[f], finitePts[g], finitePts[f]); break;
81570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 7: path.cubicTo(finitePts[f], finitePts[g], finitePts[g]); break;
82570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 8: path.cubicTo(finitePts[g], finitePts[f], finitePts[f]); break;
83570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 9: path.cubicTo(finitePts[g], finitePts[f], finitePts[g]); break;
84570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        case 10: path.moveTo(finitePts[f]); break;
85570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    }
86570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    SkPath result;
87570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    result.setFillType(SkPath::kWinding_FillType);
88570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    bool success = Simplify(path, &result);
894431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    // linux 32 debug fails test 13 because the quad is not treated as linear
90a1ed7aec95eb8c77d1a39834fea476780007cadeskia.committer@gmail.com    // there's no error in the math that I can find -- it looks like a processor
914431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    // or compiler bug -- so for now, allow either to work
924431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    REPORTER_ASSERT(reporter, success || index == 13);
93570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    REPORTER_ASSERT(reporter, result.getFillType() != SkPath::kWinding_FillType);
94570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    reporter->bumpTestCount();
95570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com}
96570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
9778e7b4e1b928fa69f672be3c743df6d6c3ecbcedtfarina@chromium.orgDEF_TEST(PathOpsSimplifyFail, reporter) {
9866560ca776773858abfffd59974eac32c942acc3caryclark@google.com    for (int index = 0; index < (int) (13 * nonFinitePtsCount * finitePtsCount); ++index) {
99570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        failOne(reporter, index);
100e23b4a4f9e82329ba305e190ddd1f17c4746ca96caryclark@google.com    }
10166560ca776773858abfffd59974eac32c942acc3caryclark@google.com    for (int index = 0; index < (int) (11 * finitePtsCount); ++index) {
102570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com        dontFailOne(reporter, index);
10366560ca776773858abfffd59974eac32c942acc3caryclark@google.com    }
10466560ca776773858abfffd59974eac32c942acc3caryclark@google.com}
10566560ca776773858abfffd59974eac32c942acc3caryclark@google.com
10678e7b4e1b928fa69f672be3c743df6d6c3ecbcedtfarina@chromium.orgDEF_TEST(PathOpsSimplifyFailOne, reporter) {
107570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    int index = 0;
108570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    failOne(reporter, index);
109570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com}
110570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com
11178e7b4e1b928fa69f672be3c743df6d6c3ecbcedtfarina@chromium.orgDEF_TEST(PathOpsSimplifyDontFailOne, reporter) {
1124431e7757cfcb8cfa99535eed0e9f156dabf95c2commit-bot@chromium.org    int index = 13;
113570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com    dontFailOne(reporter, index);
114570863f2e22b8ea7d7c504bd15e4f766af097df2caryclark@google.com}
115