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