Exemplo n.º 1
0
static void test_evalquadat(skiatest::Reporter* reporter) {
    SkRandom rand;
    for (int i = 0; i < 1000; ++i) {
        SkPoint pts[3];
        for (int j = 0; j < 3; ++j) {
            pts[j].set(rand.nextSScalar1() * 100, rand.nextSScalar1() * 100);
        }
        const SkScalar dt = SK_Scalar1 / 128;
        SkScalar t = dt;
        for (int j = 1; j < 128; ++j) {
            SkPoint r0;
            SkEvalQuadAt(pts, t, &r0);
            SkPoint r1 = SkEvalQuadAt(pts, t);
            check_pairs(reporter, i, t, "quad-pos", r0.fX, r0.fY, r1.fX, r1.fY);
            
            SkVector v0;
            SkEvalQuadAt(pts, t, nullptr, &v0);
            SkVector v1 = SkEvalQuadTangentAt(pts, t);
            check_pairs(reporter, i, t, "quad-tan", v0.fX, v0.fY, v1.fX, v1.fY);

            t += dt;
        }
    }
}
inline bool intersection_pattern_common_interior1(std::size_t& selected_rank,
           std::vector<sort_by_side::rank_with_rings> const& aggregation)
{
    // Pattern: coming from exterior ring, encountering an isolated
    // parallel interior ring, which should be skipped, and the first
    // left (normally intersection takes first right) should be taken.
    // Solves cases #case_133_multi
    // and #case_recursive_boxes_49

    std::size_t const n = aggregation.size();
    if (n < 4)
    {
        return false;
    }

    sort_by_side::rank_with_rings const& incoming = aggregation.front();
    sort_by_side::rank_with_rings const& outgoing = aggregation.back();

    bool const incoming_ok =
        incoming.all_from()
        && incoming.rings.size() == 1
        && incoming.has_only(operation_intersection);

    if (! incoming_ok)
    {
        return false;
    }

    bool const outgoing_ok =
        outgoing.all_to()
        && outgoing.rings.size() == 1
        && outgoing.has_only(operation_intersection)
        && outgoing.region_id() == incoming.region_id();

    if (! outgoing_ok)
    {
        return false;
    }

    if (check_pairs(aggregation, incoming.region_id(), 1, n - 2))
    {
        selected_rank = n - 1;
        return true;
    }
    return false;
}
inline bool intersection_pattern_common_interior4(std::size_t& selected_rank,
           std::vector<sort_by_side::rank_with_rings> const& aggregation)
{
    // Pattern: approaches colocated turn (exterior+interior) from same
    // direction, but leaves in two different directions

    // See #case_137_multi:

    // INCOMING:
    //Rank 0  {11[0] (s:0, m:0) i F rgn: 1 ISO}            {10[1] (s:1, m:0) i F rgn: 1 ISO}

    // PAIR:
    //Rank 1  {13[0] (s:0, r:0, m:0) i T rgn: 2 ISO ->15}  {11[1] (s:1, r:1, m:0) i T rgn: 2 ISO ->15}
    //Rank 2  {13[0] (s:0, r:0, m:0) i F rgn: 2 ISO}       {11[1] (s:1, r:1, m:0) i F rgn: 2 ISO}

    // LEAVING (in two different directions, take penultimate one)
    //Rank 3  {10[1] (s:1, m:0) i T rgn: 1 ISO ->0}
    //Rank 4  {11[0] (s:0, m:0) i T rgn: 1 ISO ->12}

    std::size_t const n = aggregation.size();
    if (n < 4)
    {
        return false;
    }

    sort_by_side::rank_with_rings const& incoming = aggregation.front();
    sort_by_side::rank_with_rings const& extra = aggregation[n - 2];
    sort_by_side::rank_with_rings const& outgoing = aggregation.back();

    bool const incoming_ok =
        incoming.all_from()
        && incoming.rings.size() == 2
        && incoming.has_unique_region_id()
        && incoming.has_only(operation_intersection);

    if (! incoming_ok)
    {
        return false;
    }

    bool const outgoing_ok =
        outgoing.all_to()
        && outgoing.rings.size() == 1
        && outgoing.has_only(operation_intersection)
        && outgoing.region_id() == incoming.region_id()
        && extra.all_to()
        && extra.rings.size() == 1
        && extra.has_only(operation_intersection)
        && extra.region_id() == incoming.region_id();

    if (! outgoing_ok)
    {
        return false;
    }

    // Check if pairs 1,2 (and possibly 3,4 and 5,6 etc) satisfy
    if (check_pairs(aggregation, incoming.region_id(), 1, n - 3))
    {
        selected_rank = n - 2;
        return true;
    }
    return false;
}
inline bool intersection_pattern_common_interior3(std::size_t& selected_rank,
           std::vector<sort_by_side::rank_with_rings> const& aggregation)
{
    // Pattern: approaches colocated turn (exterior+interior) from two
    // different directions, and both leaves in the same direction

    // See #case_136_multi:
    // INCOMING:
    //Rank 0  {10[0] (s:0, m:0) c F rgn: 1 ISO}

    // PAIR:
    //Rank 1  {14[0] (s:0, r:0, m:0) i T rgn: 2 ISO ->16} {11[1] (s:1, r:1, m:0) i T rgn: 2 ISO ->16}
    //Rank 2  {14[0] (s:0, r:0, m:0) i F rgn: 2 ISO}      {11[1] (s:1, r:1, m:0) i F rgn: 2 ISO}

    // LEAVING (select this one):
    //Rank 3  {10[0] (s:0, m:0) c T rgn: 1 ISO ->12}      {10[1] (s:1, m:0) c T rgn: 1 ISO ->12}

    // ADDITIONALLY: (other polygon coming in)
    //Rank 4  {10[1] (s:1, m:0) c F rgn: 1 ISO}

    std::size_t const n = aggregation.size();
    if (n < 4)
    {
        return false;
    }

    sort_by_side::rank_with_rings const& incoming = aggregation.front();
    sort_by_side::rank_with_rings const& outgoing = aggregation[n - 2];
    sort_by_side::rank_with_rings const& last = aggregation.back();

    bool const incoming_ok =
        incoming.all_from()
        && incoming.rings.size() == 1
        && incoming.has_only(operation_continue);

    if (! incoming_ok)
    {
        return false;
    }

    bool const outgoing_ok =
        outgoing.all_to()
        && outgoing.rings.size() == 2
        && outgoing.has_only(operation_continue)
        && outgoing.has_unique_region_id()
        && outgoing.region_id() == incoming.region_id()
        && last.all_from()
        && last.rings.size() == 1
        && last.region_id() == incoming.region_id()
        && last.all_from();

    if (! outgoing_ok)
    {
        return false;
    }

    // Check if pairs 1,2 (and possibly 3,4 and 5,6 etc) satisfy
    if (check_pairs(aggregation, incoming.region_id(), 1, n - 3))
    {
        selected_rank = n - 2;
        return true;
    }
    return false;
}
inline bool intersection_pattern_common_interior2(std::size_t& selected_rank,
           std::vector<sort_by_side::rank_with_rings> const& aggregation)
{
    // Pattern: coming from two exterior rings, encountering two isolated
    // equal interior rings

    // See (for example, for ii) #case_recursive_boxes_53:

    // INCOMING:
    // Rank 0  {11[0] (s:0, m:0) i F rgn: 1 ISO}             {13[1] (s:1, m:0) i F rgn: 1 ISO}

    // PAIR:
    // Rank 1  {13[0] (s:0, r:1, m:0) i T rgn: 3 ISO ->16}   {11[1] (s:1, r:5, m:0) i T rgn: 3 ISO ->16}
    // Rank 2  {13[0] (s:0, r:1, m:0) i F rgn: 3 ISO}        {11[1] (s:1, r:5, m:0) i F rgn: 3 ISO}

    // LEAVING (in the same direction, take last one)
    // Rank 3  {11[0] (s:0, m:0) i T rgn: 1 ISO ->10}        {13[1] (s:1, m:0) i T rgn: 1 ISO ->10}


    std::size_t const n = aggregation.size();
    if (n < 4)
    {
        return false;
    }

    sort_by_side::rank_with_rings const& incoming = aggregation.front();
    sort_by_side::rank_with_rings const& outgoing = aggregation.back();

    bool const incoming_ok =
        incoming.all_from()
        && incoming.rings.size() == 2
        && incoming.has_unique_region_id();

    if (! incoming_ok)
    {
        return false;
    }

    bool const outgoing_ok =
        outgoing.all_to()
        && outgoing.rings.size() == 2
        && outgoing.has_unique_region_id()
        && outgoing.region_id() == incoming.region_id();

    if (! outgoing_ok)
    {
        return false;
    }

    bool const operation_ok =
            (incoming.has_only(operation_continue) && outgoing.has_only(operation_continue))
             || (incoming.has_only(operation_intersection) && outgoing.has_only(operation_intersection));

    if (! operation_ok)
    {
        return false;
    }

    // Check if pairs 1,2 (and possibly 3,4 and 5,6 etc) satisfy
    if (check_pairs(aggregation, incoming.region_id(), 1, n - 2))
    {
        selected_rank = n - 1;
        return true;
    }
    return false;
}
Exemplo n.º 6
0
static void test_conic_eval_tan(skiatest::Reporter* reporter, const SkConic& conic, SkScalar t) {
    SkVector v0, v1;
    conic.evalAt(t, nullptr, &v0);
    v1 = conic.evalTangentAt(t);
    check_pairs(reporter, 0, t, "conic-tan", v0.fX, v0.fY, v1.fX, v1.fY);
}
Exemplo n.º 7
0
static void test_conic_eval_pos(skiatest::Reporter* reporter, const SkConic& conic, SkScalar t) {
    SkPoint p0, p1;
    conic.evalAt(t, &p0, nullptr);
    p1 = conic.evalAt(t);
    check_pairs(reporter, 0, t, "conic-pos", p0.fX, p0.fY, p1.fX, p1.fY);
}