Home | History | Annotate | Download | only in tests
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 #include "Test.h"
      9 #include "SkPathMeasure.h"
     10 
     11 static void test_small_segment3(skiatest::Reporter* reporter) {
     12 #ifdef SK_SCALAR_IS_FLOAT
     13     SkPath path;
     14     const SkPoint pts[] = {
     15         { 0, 0 },
     16         { 100000000000.0f, 100000000000.0f }, { 0, 0 }, { 10, 10 },
     17         { 10, 10 }, { 0, 0 }, { 10, 10 }
     18     };
     19 
     20     path.moveTo(pts[0]);
     21     for (size_t i = 1; i < SK_ARRAY_COUNT(pts); i += 3) {
     22         path.cubicTo(pts[i], pts[i + 1], pts[i + 2]);
     23     }
     24 
     25     SkPathMeasure meas(path, false);
     26     meas.getLength();
     27 #endif
     28 }
     29 
     30 static void test_small_segment2(skiatest::Reporter* reporter) {
     31 #ifdef SK_SCALAR_IS_FLOAT
     32     SkPath path;
     33     const SkPoint pts[] = {
     34         { 0, 0 },
     35         { 100000000000.0f, 100000000000.0f }, { 0, 0 },
     36         { 10, 10 }, { 0, 0 },
     37     };
     38 
     39     path.moveTo(pts[0]);
     40     for (size_t i = 1; i < SK_ARRAY_COUNT(pts); i += 2) {
     41         path.quadTo(pts[i], pts[i + 1]);
     42     }
     43     SkPathMeasure meas(path, false);
     44     meas.getLength();
     45 #endif
     46 }
     47 
     48 static void test_small_segment(skiatest::Reporter* reporter) {
     49 #ifdef SK_SCALAR_IS_FLOAT
     50     SkPath path;
     51     const SkPoint pts[] = {
     52         { 100000, 100000},
     53         // big jump between these points, makes a big segment
     54         { SkFloatToScalar(1.0005f), SkFloatToScalar(0.9999f) },
     55         // tiny (non-zero) jump between these points
     56         { SK_Scalar1, SK_Scalar1 },
     57     };
     58 
     59     path.moveTo(pts[0]);
     60     for (size_t i = 1; i < SK_ARRAY_COUNT(pts); ++i) {
     61         path.lineTo(pts[i]);
     62     }
     63     SkPathMeasure meas(path, false);
     64 
     65     /*  this would assert (before a fix) because we added a segment with
     66         the same length as the prev segment, due to the follow (bad) pattern
     67 
     68         d = distance(pts[0], pts[1]);
     69         distance += d;
     70         seg->fDistance = distance;
     71 
     72         SkASSERT(d > 0);    // TRUE
     73         SkASSERT(seg->fDistance > prevSeg->fDistance);  // FALSE
     74 
     75         This 2nd assert failes because (distance += d) didn't affect distance
     76         because distance >>> d.
     77      */
     78     meas.getLength();
     79 #endif
     80 }
     81 
     82 static void TestPathMeasure(skiatest::Reporter* reporter) {
     83     SkPath  path;
     84 
     85     path.moveTo(0, 0);
     86     path.lineTo(SK_Scalar1, 0);
     87     path.lineTo(SK_Scalar1, SK_Scalar1);
     88     path.lineTo(0, SK_Scalar1);
     89 
     90     SkPathMeasure   meas(path, true);
     91     SkScalar        length = meas.getLength();
     92     SkASSERT(length == SK_Scalar1*4);
     93 
     94     path.reset();
     95     path.moveTo(0, 0);
     96     path.lineTo(SK_Scalar1*3, SK_Scalar1*4);
     97     meas.setPath(&path, false);
     98     length = meas.getLength();
     99     REPORTER_ASSERT(reporter, length == SK_Scalar1*5);
    100 
    101     path.reset();
    102     path.addCircle(0, 0, SK_Scalar1);
    103     meas.setPath(&path, true);
    104     length = meas.getLength();
    105 //    SkDebugf("circle arc-length = %g\n", length);
    106 
    107     // Test the behavior following a close not followed by a move.
    108     path.reset();
    109     path.lineTo(SK_Scalar1, 0);
    110     path.lineTo(SK_Scalar1, SK_Scalar1);
    111     path.lineTo(0, SK_Scalar1);
    112     path.close();
    113     path.lineTo(-SK_Scalar1, 0);
    114     meas.setPath(&path, false);
    115     length = meas.getLength();
    116     REPORTER_ASSERT(reporter, length == SK_Scalar1 * 4);
    117     meas.nextContour();
    118     length = meas.getLength();
    119     REPORTER_ASSERT(reporter, length == SK_Scalar1);
    120     SkPoint position;
    121     SkVector tangent;
    122     REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
    123     REPORTER_ASSERT(reporter,
    124         SkScalarNearlyEqual(position.fX,
    125                             -SK_ScalarHalf,
    126                             SkFloatToScalar(0.0001f)));
    127     REPORTER_ASSERT(reporter, position.fY == 0);
    128     REPORTER_ASSERT(reporter, tangent.fX == -SK_Scalar1);
    129     REPORTER_ASSERT(reporter, tangent.fY == 0);
    130 
    131     // Test degenerate paths
    132     path.reset();
    133     path.moveTo(0, 0);
    134     path.lineTo(0, 0);
    135     path.lineTo(SK_Scalar1, 0);
    136     path.quadTo(SK_Scalar1, 0, SK_Scalar1, 0);
    137     path.quadTo(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1 * 2);
    138     path.cubicTo(SK_Scalar1, SK_Scalar1 * 2,
    139                  SK_Scalar1, SK_Scalar1 * 2,
    140                  SK_Scalar1, SK_Scalar1 * 2);
    141     path.cubicTo(SK_Scalar1*2, SK_Scalar1 * 2,
    142                  SK_Scalar1*3, SK_Scalar1 * 2,
    143                  SK_Scalar1*4, SK_Scalar1 * 2);
    144     meas.setPath(&path, false);
    145     length = meas.getLength();
    146     REPORTER_ASSERT(reporter, length == SK_Scalar1 * 6);
    147     REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
    148     REPORTER_ASSERT(reporter,
    149         SkScalarNearlyEqual(position.fX,
    150                             SK_ScalarHalf,
    151                             SkFloatToScalar(0.0001f)));
    152     REPORTER_ASSERT(reporter, position.fY == 0);
    153     REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1);
    154     REPORTER_ASSERT(reporter, tangent.fY == 0);
    155     REPORTER_ASSERT(reporter, meas.getPosTan(SkFloatToScalar(2.5f), &position, &tangent));
    156     REPORTER_ASSERT(reporter,
    157         SkScalarNearlyEqual(position.fX, SK_Scalar1, SkFloatToScalar(0.0001f)));
    158     REPORTER_ASSERT(reporter,
    159         SkScalarNearlyEqual(position.fY, SkFloatToScalar(1.5f)));
    160     REPORTER_ASSERT(reporter, tangent.fX == 0);
    161     REPORTER_ASSERT(reporter, tangent.fY == SK_Scalar1);
    162     REPORTER_ASSERT(reporter, meas.getPosTan(SkFloatToScalar(4.5f), &position, &tangent));
    163     REPORTER_ASSERT(reporter,
    164         SkScalarNearlyEqual(position.fX,
    165                             SkFloatToScalar(2.5f),
    166                             SkFloatToScalar(0.0001f)));
    167     REPORTER_ASSERT(reporter,
    168         SkScalarNearlyEqual(position.fY,
    169                             SkFloatToScalar(2.0f),
    170                             SkFloatToScalar(0.0001f)));
    171     REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1);
    172     REPORTER_ASSERT(reporter, tangent.fY == 0);
    173 
    174     path.reset();
    175     path.moveTo(0, 0);
    176     path.lineTo(SK_Scalar1, 0);
    177     path.moveTo(SK_Scalar1, SK_Scalar1);
    178     path.moveTo(SK_Scalar1 * 2, SK_Scalar1 * 2);
    179     path.lineTo(SK_Scalar1, SK_Scalar1 * 2);
    180     meas.setPath(&path, false);
    181     length = meas.getLength();
    182     REPORTER_ASSERT(reporter, length == SK_Scalar1);
    183     REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
    184     REPORTER_ASSERT(reporter,
    185         SkScalarNearlyEqual(position.fX,
    186                             SK_ScalarHalf,
    187                             SkFloatToScalar(0.0001f)));
    188     REPORTER_ASSERT(reporter, position.fY == 0);
    189     REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1);
    190     REPORTER_ASSERT(reporter, tangent.fY == 0);
    191     meas.nextContour();
    192     length = meas.getLength();
    193     REPORTER_ASSERT(reporter, length == SK_Scalar1);
    194     REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
    195     REPORTER_ASSERT(reporter,
    196         SkScalarNearlyEqual(position.fX,
    197                             SkFloatToScalar(1.5f),
    198                             SkFloatToScalar(0.0001f)));
    199     REPORTER_ASSERT(reporter,
    200         SkScalarNearlyEqual(position.fY,
    201                             SkFloatToScalar(2.0f),
    202                             SkFloatToScalar(0.0001f)));
    203     REPORTER_ASSERT(reporter, tangent.fX == -SK_Scalar1);
    204     REPORTER_ASSERT(reporter, tangent.fY == 0);
    205 
    206     test_small_segment(reporter);
    207     test_small_segment2(reporter);
    208     test_small_segment3(reporter);
    209 }
    210 
    211 #include "TestClassDef.h"
    212 DEFINE_TESTCLASS("PathMeasure", PathMeasureTestClass, TestPathMeasure)
    213