Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright 2013 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 #include "SkPath.h"
      8 #include "SkPathOps.h"
      9 #include "SkPoint.h"
     10 #include "Test.h"
     11 
     12 static const SkPoint nonFinitePts[] = {
     13     { SK_ScalarInfinity, 0 },
     14     { 0, SK_ScalarInfinity },
     15     { SK_ScalarInfinity, SK_ScalarInfinity },
     16     { SK_ScalarNegativeInfinity, 0},
     17     { 0, SK_ScalarNegativeInfinity },
     18     { SK_ScalarNegativeInfinity, SK_ScalarNegativeInfinity },
     19     { SK_ScalarNegativeInfinity, SK_ScalarInfinity },
     20     { SK_ScalarInfinity, SK_ScalarNegativeInfinity },
     21     { SK_ScalarNaN, 0 },
     22     { 0, SK_ScalarNaN },
     23     { SK_ScalarNaN, SK_ScalarNaN },
     24 };
     25 
     26 const size_t nonFinitePtsCount = sizeof(nonFinitePts) / sizeof(nonFinitePts[0]);
     27 
     28 static const SkPoint finitePts[] = {
     29     { 0, 0 },
     30     { SK_ScalarMax, 0 },
     31     { 0, SK_ScalarMax },
     32     { SK_ScalarMax, SK_ScalarMax },
     33     { SK_ScalarMin, 0 },
     34     { 0, SK_ScalarMin },
     35     { SK_ScalarMin, SK_ScalarMin },
     36 };
     37 
     38 const size_t finitePtsCount = sizeof(finitePts) / sizeof(finitePts[0]);
     39 
     40 static void failOne(skiatest::Reporter* reporter, int index) {
     41     SkPath path;
     42     int i = (int) (index % nonFinitePtsCount);
     43     int f = (int) (index % finitePtsCount);
     44     int g = (int) ((f + 1) % finitePtsCount);
     45     switch (index % 13) {
     46         case 0: path.lineTo(nonFinitePts[i]); break;
     47         case 1: path.quadTo(nonFinitePts[i], nonFinitePts[i]); break;
     48         case 2: path.quadTo(nonFinitePts[i], finitePts[f]); break;
     49         case 3: path.quadTo(finitePts[f], nonFinitePts[i]); break;
     50         case 4: path.cubicTo(nonFinitePts[i], finitePts[f], finitePts[f]); break;
     51         case 5: path.cubicTo(finitePts[f], nonFinitePts[i], finitePts[f]); break;
     52         case 6: path.cubicTo(finitePts[f], finitePts[f], nonFinitePts[i]); break;
     53         case 7: path.cubicTo(nonFinitePts[i], nonFinitePts[i], finitePts[f]); break;
     54         case 8: path.cubicTo(nonFinitePts[i], finitePts[f], nonFinitePts[i]); break;
     55         case 9: path.cubicTo(finitePts[f], nonFinitePts[i], nonFinitePts[i]); break;
     56         case 10: path.cubicTo(nonFinitePts[i], nonFinitePts[i], nonFinitePts[i]); break;
     57         case 11: path.cubicTo(nonFinitePts[i], finitePts[f], finitePts[g]); break;
     58         case 12: path.moveTo(nonFinitePts[i]); break;
     59     }
     60     SkPath result;
     61     result.setFillType(SkPath::kWinding_FillType);
     62     bool success = Simplify(path, &result);
     63     REPORTER_ASSERT(reporter, !success);
     64     REPORTER_ASSERT(reporter, result.isEmpty());
     65     REPORTER_ASSERT(reporter, result.getFillType() == SkPath::kWinding_FillType);
     66     reporter->bumpTestCount();
     67 }
     68 
     69 static void dontFailOne(skiatest::Reporter* reporter, int index) {
     70     SkPath path;
     71     int f = (int) (index % finitePtsCount);
     72     int g = (int) ((f + 1) % finitePtsCount);
     73     switch (index % 11) {
     74         case 0: path.lineTo(finitePts[f]); break;
     75         case 1: path.quadTo(finitePts[f], finitePts[f]); break;
     76         case 2: path.quadTo(finitePts[f], finitePts[g]); break;
     77         case 3: path.quadTo(finitePts[g], finitePts[f]); break;
     78         case 4: path.cubicTo(finitePts[f], finitePts[f], finitePts[f]); break;
     79         case 5: path.cubicTo(finitePts[f], finitePts[f], finitePts[g]); break;
     80         case 6: path.cubicTo(finitePts[f], finitePts[g], finitePts[f]); break;
     81         case 7: path.cubicTo(finitePts[f], finitePts[g], finitePts[g]); break;
     82         case 8: path.cubicTo(finitePts[g], finitePts[f], finitePts[f]); break;
     83         case 9: path.cubicTo(finitePts[g], finitePts[f], finitePts[g]); break;
     84         case 10: path.moveTo(finitePts[f]); break;
     85     }
     86     SkPath result;
     87     result.setFillType(SkPath::kWinding_FillType);
     88     bool success = Simplify(path, &result);
     89     if (index != 17 && index != 31 && index != 38) {  // cubic fails to chop in two without creating NaNs
     90         REPORTER_ASSERT(reporter, success);
     91         REPORTER_ASSERT(reporter, result.getFillType() != SkPath::kWinding_FillType);
     92     }
     93     reporter->bumpTestCount();
     94 }
     95 
     96 DEF_TEST(PathOpsSimplifyFail, reporter) {
     97     for (int index = 0; index < (int) (13 * nonFinitePtsCount * finitePtsCount); ++index) {
     98         failOne(reporter, index);
     99     }
    100     for (int index = 0; index < (int) (11 * finitePtsCount); ++index) {
    101         dontFailOne(reporter, index);
    102     }
    103 }
    104 
    105 DEF_TEST(PathOpsSimplifyFailOne, reporter) {
    106     int index = 0;
    107     failOne(reporter, index);
    108 }
    109 
    110 DEF_TEST(PathOpsSimplifyDontFailOne, reporter) {
    111     int index = 17;
    112     dontFailOne(reporter, index);
    113 }
    114