xref: /third_party/skia/tests/ClipperTest.cpp (revision cb93a386)
1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2011 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h"
9cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h"
10cb93a386Sopenharmony_ci#include "include/core/SkColor.h"
11cb93a386Sopenharmony_ci#include "include/core/SkPaint.h"
12cb93a386Sopenharmony_ci#include "include/core/SkPoint.h"
13cb93a386Sopenharmony_ci#include "include/core/SkRect.h"
14cb93a386Sopenharmony_ci#include "include/core/SkScalar.h"
15cb93a386Sopenharmony_ci#include "include/core/SkTypes.h"
16cb93a386Sopenharmony_ci#include "src/core/SkEdgeClipper.h"
17cb93a386Sopenharmony_ci#include "src/core/SkLineClipper.h"
18cb93a386Sopenharmony_ci#include "tests/Test.h"
19cb93a386Sopenharmony_ci
20cb93a386Sopenharmony_ci#include <cstring>
21cb93a386Sopenharmony_ci
22cb93a386Sopenharmony_cistatic void test_hairclipping(skiatest::Reporter* reporter) {
23cb93a386Sopenharmony_ci    SkBitmap bm;
24cb93a386Sopenharmony_ci    bm.allocN32Pixels(4, 4);
25cb93a386Sopenharmony_ci    bm.eraseColor(SK_ColorWHITE);
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_ci    SkPaint paint;
28cb93a386Sopenharmony_ci    paint.setAntiAlias(true);
29cb93a386Sopenharmony_ci
30cb93a386Sopenharmony_ci    SkCanvas canvas(bm);
31cb93a386Sopenharmony_ci    canvas.clipRect(SkRect::MakeWH(SkIntToScalar(4), SkIntToScalar(2)));
32cb93a386Sopenharmony_ci    canvas.drawLine(1.5f, 1.5f,
33cb93a386Sopenharmony_ci                    3.5f, 3.5f, paint);
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_ci    /**
36cb93a386Sopenharmony_ci     *  We had a bug where we misinterpreted the bottom of the clip, and
37cb93a386Sopenharmony_ci     *  would draw another pixel (to the right in this case) on the same
38cb93a386Sopenharmony_ci     *  last scanline. i.e. we would draw to [2,1], even though this hairline
39cb93a386Sopenharmony_ci     *  should just draw to [1,1], [2,2], [3,3] modulo the clip.
40cb93a386Sopenharmony_ci     *
41cb93a386Sopenharmony_ci     *  The result of this entire draw should be that we only draw to [1,1]
42cb93a386Sopenharmony_ci     *
43cb93a386Sopenharmony_ci     *  Fixed in rev. 3366
44cb93a386Sopenharmony_ci     */
45cb93a386Sopenharmony_ci    for (int y = 0; y < 4; ++y) {
46cb93a386Sopenharmony_ci        for (int x = 0; x < 4; ++x) {
47cb93a386Sopenharmony_ci            bool nonWhite = (1 == y) && (1 == x);
48cb93a386Sopenharmony_ci            SkPMColor c = *bm.getAddr32(x, y);
49cb93a386Sopenharmony_ci            if (nonWhite) {
50cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, 0xFFFFFFFF != c);
51cb93a386Sopenharmony_ci            } else {
52cb93a386Sopenharmony_ci                REPORTER_ASSERT(reporter, 0xFFFFFFFF == c);
53cb93a386Sopenharmony_ci            }
54cb93a386Sopenharmony_ci        }
55cb93a386Sopenharmony_ci    }
56cb93a386Sopenharmony_ci}
57cb93a386Sopenharmony_ci
58cb93a386Sopenharmony_cistatic void test_edgeclipper() {
59cb93a386Sopenharmony_ci    SkEdgeClipper clipper(false);
60cb93a386Sopenharmony_ci
61cb93a386Sopenharmony_ci    const SkPoint pts[] = {
62cb93a386Sopenharmony_ci        { 3.0995476e+010f,  42.929779f },
63cb93a386Sopenharmony_ci        { -3.0995163e+010f, 51.050385f },
64cb93a386Sopenharmony_ci        { -3.0995157e+010f, 51.050392f },
65cb93a386Sopenharmony_ci        { -3.0995134e+010f, 51.050400f },
66cb93a386Sopenharmony_ci    };
67cb93a386Sopenharmony_ci
68cb93a386Sopenharmony_ci    const SkRect clip = { 0, 0, SkIntToScalar(300), SkIntToScalar(200) };
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci    // this should not assert, even though our choppers do a poor numerical
71cb93a386Sopenharmony_ci    // job when computing their t values.
72cb93a386Sopenharmony_ci    // http://code.google.com/p/skia/issues/detail?id=444
73cb93a386Sopenharmony_ci    clipper.clipCubic(pts, clip);
74cb93a386Sopenharmony_ci}
75cb93a386Sopenharmony_ci
76cb93a386Sopenharmony_cistatic void test_intersectline(skiatest::Reporter* reporter) {
77cb93a386Sopenharmony_ci    static const SkScalar L = 0;
78cb93a386Sopenharmony_ci    static const SkScalar T = 0;
79cb93a386Sopenharmony_ci    static const SkScalar R = SkIntToScalar(100);
80cb93a386Sopenharmony_ci    static const SkScalar B = SkIntToScalar(100);
81cb93a386Sopenharmony_ci    static const SkScalar CX = SkScalarHalf(L + R);
82cb93a386Sopenharmony_ci    static const SkScalar CY = SkScalarHalf(T + B);
83cb93a386Sopenharmony_ci    static const SkRect gR = { L, T, R, B };
84cb93a386Sopenharmony_ci
85cb93a386Sopenharmony_ci    size_t i;
86cb93a386Sopenharmony_ci    SkPoint dst[2];
87cb93a386Sopenharmony_ci
88cb93a386Sopenharmony_ci    static const SkPoint gEmpty[] = {
89cb93a386Sopenharmony_ci        // sides
90cb93a386Sopenharmony_ci        { L, CY }, { L - 10, CY },
91cb93a386Sopenharmony_ci        { R, CY }, { R + 10, CY },
92cb93a386Sopenharmony_ci        { CX, T }, { CX, T - 10 },
93cb93a386Sopenharmony_ci        { CX, B }, { CX, B + 10 },
94cb93a386Sopenharmony_ci        // corners
95cb93a386Sopenharmony_ci        { L, T }, { L - 10, T - 10 },
96cb93a386Sopenharmony_ci        { L, B }, { L - 10, B + 10 },
97cb93a386Sopenharmony_ci        { R, T }, { R + 10, T - 10 },
98cb93a386Sopenharmony_ci        { R, B }, { R + 10, B + 10 },
99cb93a386Sopenharmony_ci    };
100cb93a386Sopenharmony_ci    for (i = 0; i < SK_ARRAY_COUNT(gEmpty); i += 2) {
101cb93a386Sopenharmony_ci        bool valid = SkLineClipper::IntersectLine(&gEmpty[i], gR, dst);
102cb93a386Sopenharmony_ci        if (valid) {
103cb93a386Sopenharmony_ci            SkDebugf("----- [%zu] %g %g -> %g %g\n",
104cb93a386Sopenharmony_ci                     i/2, dst[0].fX, dst[0].fY, dst[1].fX, dst[1].fY);
105cb93a386Sopenharmony_ci        }
106cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, !valid);
107cb93a386Sopenharmony_ci    }
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_ci    static const SkPoint gFull[] = {
110cb93a386Sopenharmony_ci        // diagonals, chords
111cb93a386Sopenharmony_ci        { L, T }, { R, B },
112cb93a386Sopenharmony_ci        { L, B }, { R, T },
113cb93a386Sopenharmony_ci        { CX, T }, { CX, B },
114cb93a386Sopenharmony_ci        { L, CY }, { R, CY },
115cb93a386Sopenharmony_ci        { CX, T }, { R, CY },
116cb93a386Sopenharmony_ci        { CX, T }, { L, CY },
117cb93a386Sopenharmony_ci        { L, CY }, { CX, B },
118cb93a386Sopenharmony_ci        { R, CY }, { CX, B },
119cb93a386Sopenharmony_ci        // edges
120cb93a386Sopenharmony_ci        { L, T }, { L, B },
121cb93a386Sopenharmony_ci        { R, T }, { R, B },
122cb93a386Sopenharmony_ci        { L, T }, { R, T },
123cb93a386Sopenharmony_ci        { L, B }, { R, B },
124cb93a386Sopenharmony_ci    };
125cb93a386Sopenharmony_ci    for (i = 0; i < SK_ARRAY_COUNT(gFull); i += 2) {
126cb93a386Sopenharmony_ci        bool valid = SkLineClipper::IntersectLine(&gFull[i], gR, dst);
127cb93a386Sopenharmony_ci        if (!valid || 0 != memcmp(&gFull[i], dst, sizeof(dst))) {
128cb93a386Sopenharmony_ci            SkDebugf("++++ [%zu] %g %g -> %g %g\n",
129cb93a386Sopenharmony_ci                     i/2, dst[0].fX, dst[0].fY, dst[1].fX, dst[1].fY);
130cb93a386Sopenharmony_ci        }
131cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, valid && !memcmp(&gFull[i], dst, sizeof(dst)));
132cb93a386Sopenharmony_ci    }
133cb93a386Sopenharmony_ci
134cb93a386Sopenharmony_ci    static const SkPoint gPartial[] = {
135cb93a386Sopenharmony_ci        { L - 10, CY }, { CX, CY }, { L, CY }, { CX, CY },
136cb93a386Sopenharmony_ci        { CX, T - 10 }, { CX, CY }, { CX, T }, { CX, CY },
137cb93a386Sopenharmony_ci        { R + 10, CY }, { CX, CY }, { R, CY }, { CX, CY },
138cb93a386Sopenharmony_ci        { CX, B + 10 }, { CX, CY }, { CX, B }, { CX, CY },
139cb93a386Sopenharmony_ci        // extended edges
140cb93a386Sopenharmony_ci        { L, T - 10 }, { L, B + 10 }, { L, T }, { L, B },
141cb93a386Sopenharmony_ci        { R, T - 10 }, { R, B + 10 }, { R, T }, { R, B },
142cb93a386Sopenharmony_ci        { L - 10, T }, { R + 10, T }, { L, T }, { R, T },
143cb93a386Sopenharmony_ci        { L - 10, B }, { R + 10, B }, { L, B }, { R, B },
144cb93a386Sopenharmony_ci    };
145cb93a386Sopenharmony_ci    for (i = 0; i < SK_ARRAY_COUNT(gPartial); i += 4) {
146cb93a386Sopenharmony_ci        bool valid = SkLineClipper::IntersectLine(&gPartial[i], gR, dst);
147cb93a386Sopenharmony_ci        if (!valid || 0 != memcmp(&gPartial[i+2], dst, sizeof(dst))) {
148cb93a386Sopenharmony_ci            SkDebugf("++++ [%zu] %g %g -> %g %g\n",
149cb93a386Sopenharmony_ci                     i/2, dst[0].fX, dst[0].fY, dst[1].fX, dst[1].fY);
150cb93a386Sopenharmony_ci        }
151cb93a386Sopenharmony_ci        REPORTER_ASSERT(reporter, valid &&
152cb93a386Sopenharmony_ci                                  !memcmp(&gPartial[i+2], dst, sizeof(dst)));
153cb93a386Sopenharmony_ci    }
154cb93a386Sopenharmony_ci
155cb93a386Sopenharmony_ci}
156cb93a386Sopenharmony_ci
157cb93a386Sopenharmony_ciDEF_TEST(Clipper, reporter) {
158cb93a386Sopenharmony_ci    test_intersectline(reporter);
159cb93a386Sopenharmony_ci    test_edgeclipper();
160cb93a386Sopenharmony_ci    test_hairclipping(reporter);
161cb93a386Sopenharmony_ci}
162cb93a386Sopenharmony_ci
163cb93a386Sopenharmony_ciDEF_TEST(LineClipper_skbug_7981, r) {
164cb93a386Sopenharmony_ci    SkPoint src[] = {{ -5.77698802E+17f, -1.81758057E+23f}, {38127, 2}};
165cb93a386Sopenharmony_ci    SkPoint dst[2];
166cb93a386Sopenharmony_ci    SkRect clip = { -32767, -32767, 32767, 32767 };
167cb93a386Sopenharmony_ci
168cb93a386Sopenharmony_ci    SkLineClipper::IntersectLine(src, clip, dst);
169cb93a386Sopenharmony_ci}
170cb93a386Sopenharmony_ci
171