• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2025 Google LLC
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 "tests/Test.h"
8 
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkColorSpace.h"
11 #include "include/core/SkImageInfo.h"
12 #include "include/core/SkPaint.h"
13 #include "include/core/SkPixmap.h"
14 #include "include/core/SkSurface.h"
15 #include "src/core/SkBlitter.h"
16 #include "src/core/SkCoreBlitters.h"
17 #include "src/core/SkMask.h"
18 
19 #include <memory>
20 
all_pixels_same_color(uint32_t * buffer,size_t len)21 static bool all_pixels_same_color(uint32_t* buffer, size_t len) {
22     for (size_t i = 1; i < len; ++i) {
23         if (buffer[0] != buffer[i]) {
24             return false;
25         }
26     }
27     return true;
28 }
29 
30 using BlitterFactory = std::unique_ptr<SkBlitter> (*)(const SkPixmap&, const SkPaint&);
31 
compare_mask_and_antiH(skiatest::Reporter * reporter,SkColor backgroundColor,SkColor paintColor,BlitterFactory makeBlitter)32 static void compare_mask_and_antiH(skiatest::Reporter* reporter,
33                                    SkColor backgroundColor,
34                                    SkColor paintColor,
35                                    BlitterFactory makeBlitter) {
36     // 19 is big enough to exercise any multi-lane code (e.g. SIMD/NEON)
37     // and have some remainder to exercise single-pixel code.
38     constexpr size_t kPixelsToBlit = 19;
39     static_assert(kPixelsToBlit % 4 != 0);
40     static_assert(kPixelsToBlit % 8 != 0);
41     static_assert(kPixelsToBlit % 16 != 0);
42 
43     // Space for a kPixelsToBlit by 1 pixel image of 8888 color
44     SkColor buffer1[kPixelsToBlit * 1];
45     SkColor buffer2[kPixelsToBlit * 1];
46     auto ii = SkImageInfo::Make(
47             {kPixelsToBlit, 1},
48             SkColorInfo(kN32_SkColorType, kPremul_SkAlphaType, SkColorSpace::MakeSRGB()));
49 
50     SkPixmap device1(ii, buffer1, ii.minRowBytes());
51     auto surface1 = SkSurfaces::WrapPixels(device1);
52     SkASSERT(surface1);
53 
54     SkPixmap device2(ii, buffer2, ii.minRowBytes());
55     auto surface2 = SkSurfaces::WrapPixels(device2);
56     SkASSERT(surface2);
57 
58     SkPaint paint;
59     paint.setColor(paintColor);
60 
61     auto blitter1 = makeBlitter(device1, paint);
62     SkASSERT(blitter1);
63     auto blitter2 = makeBlitter(device2, paint);
64     SkASSERT(blitter2);
65 
66     SkAlpha antiAlias[1];
67     // The blitAntiH needs a buffer where the first value is the number of pixels
68     // to blit and then at least that many 0s so we don't read off the end of the
69     // buffer to figure out we need to stop.
70     int16_t runs[kPixelsToBlit+1] = {kPixelsToBlit};
71 
72     uint8_t maskImage[kPixelsToBlit];
73     auto maskBounds = SkIRect::MakeXYWH(0, 0, kPixelsToBlit, 1);
74     for (int alpha = 0; alpha <= 255; ++alpha) {
75         antiAlias[0] = static_cast<SkAlpha>(alpha);
76         std::fill_n(maskImage, kPixelsToBlit, static_cast<SkAlpha>(alpha));
77 
78         SkMask mask(maskImage, maskBounds, kPixelsToBlit, SkMask::kA8_Format);
79 
80         surface1->getCanvas()->clear(backgroundColor);
81         blitter1->blitAntiH(0, 0, antiAlias, runs);
82 
83         surface2->getCanvas()->clear(backgroundColor);
84         blitter2->blitMask(mask, mask.fBounds);
85 
86         if (!all_pixels_same_color(buffer1, std::size(buffer1))) {
87             REPORT_FAILURE(reporter,
88                            "blitAntiH was not the same for all pixels",
89                            SkStringPrintf("background=%08x, paint=%08x, alpha=%d",
90                                           backgroundColor,
91                                           paintColor,
92                                           alpha));
93             return;
94         }
95         if (!all_pixels_same_color(buffer2, std::size(buffer2))) {
96             REPORT_FAILURE(reporter,
97                            "blitMask was not the same for all pixels",
98                            SkStringPrintf("background=%08x, paint=%08x, alpha=%d",
99                                           backgroundColor,
100                                           paintColor,
101                                           alpha));
102             return;
103         }
104 
105         SkColor antiHColor = buffer1[0];
106         SkColor maskColor = buffer2[0];
107 
108         REPORTER_ASSERT(reporter,
109                         antiHColor == maskColor,
110                         "background=%08x, paint=%08x, alpha=%d, "
111                         "blitAntiH=%08x, blitMask=%08x, "
112                         "diff=%02x %02x %02x %02x",
113                         backgroundColor, paintColor, alpha,
114                         antiHColor, maskColor,
115                         abs((int)(SkColorGetA(antiHColor) - SkColorGetA(maskColor))),
116                         abs((int)(SkColorGetR(antiHColor) - SkColorGetR(maskColor))),
117                         abs((int)(SkColorGetG(antiHColor) - SkColorGetG(maskColor))),
118                         abs((int)(SkColorGetB(antiHColor) - SkColorGetB(maskColor))));
119     }
120 }
121 
DEF_TEST(SkARGB32OpaqueBlitter_MaskAndAntiHDrawTheSame,r)122 DEF_TEST(SkARGB32OpaqueBlitter_MaskAndAntiHDrawTheSame, r) {
123     SkColor backgroundColors[] = {
124             SK_ColorWHITE, SK_ColorBLACK, SK_ColorGRAY,
125             SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
126             SK_ColorYELLOW, SK_ColorCYAN, SK_ColorMAGENTA,
127             // arbitrary opaque color with uneven channels
128             SkColorSetARGB(255, 255 / 4, 255 / 3, 255 / 2),
129     };
130     SkColor paintColors[] = {
131             SK_ColorWHITE, SK_ColorBLACK, SK_ColorGRAY,
132             SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
133             SK_ColorYELLOW, SK_ColorCYAN, SK_ColorMAGENTA,
134             SkColorSetARGB(255, 255 / 4, 255 / 3, 255 / 2),
135     };
136 
137     for (SkColor backgroundColor : backgroundColors) {
138         for (SkColor paintColor : paintColors) {
139             compare_mask_and_antiH(r,
140                                    backgroundColor,
141                                    paintColor,
142                                    [](const SkPixmap& device, const SkPaint& paint) -> std::unique_ptr<SkBlitter> {
143                                        return std::make_unique<SkARGB32_Opaque_Blitter>(device, paint);
144                                    });
145         }
146     }
147 }
148 
DEF_TEST(SkARGB32BlackBlitter_MaskAndAntiHDrawTheSame,r)149 DEF_TEST(SkARGB32BlackBlitter_MaskAndAntiHDrawTheSame, r) {
150     SkColor backgroundColors[] = {
151             SK_ColorWHITE, SK_ColorBLACK, SK_ColorGRAY,
152             SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
153             SK_ColorYELLOW, SK_ColorCYAN, SK_ColorMAGENTA,
154             // arbitrary opaque color with uneven channels
155             SkColorSetARGB(255, 255 / 4, 255 / 3, 255 / 2),
156     };
157 
158     for (SkColor backgroundColor : backgroundColors) {
159         compare_mask_and_antiH(r,
160                                backgroundColor,
161                                SK_ColorBLACK,
162                                [](const SkPixmap& device, const SkPaint& paint) -> std::unique_ptr<SkBlitter> {
163                                    return std::make_unique<SkARGB32_Black_Blitter>(device, paint);
164                                });
165     }
166 }
167 
DEF_TEST(SkARGB32Blitter_MaskAndAntiHDrawTheSame,r)168 DEF_TEST(SkARGB32Blitter_MaskAndAntiHDrawTheSame, r) {
169     SkColor backgroundColors[] = {
170             SK_ColorWHITE, SK_ColorBLACK, SK_ColorGRAY,
171             SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
172             SK_ColorYELLOW, SK_ColorCYAN, SK_ColorMAGENTA,
173             // arbitrary opaque color with uneven channels
174             SkColorSetARGB(255, 255 / 4, 255 / 3, 255 / 2),
175     };
176     SkColor paintColors[] = {
177             SK_ColorWHITE, SK_ColorBLACK, SK_ColorGRAY,
178             SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
179             SK_ColorYELLOW, SK_ColorCYAN, SK_ColorMAGENTA,
180             SkColorSetARGB(255, 255 / 4, 255 / 3, 255 / 2),
181     };
182     SkAlpha alphaValues[] = {
183             0, 10, 100, 200, 245 /*SkARGB32_Opaque_Blitter is used when alpha is 255*/
184     };
185 
186     for (SkColor backgroundColor : backgroundColors) {
187         for (SkColor paintColor : paintColors) {
188             for (SkAlpha alpha : alphaValues) {
189                 SkColor newColor = SkColorSetA(paintColor, alpha);
190                 compare_mask_and_antiH(r,
191                                        backgroundColor,
192                                        newColor,
193                                        [](const SkPixmap& device, const SkPaint& paint) -> std::unique_ptr<SkBlitter> {
194                                            return std::make_unique<SkARGB32_Blitter>(device, paint);
195                                        });
196             }
197         }
198     }
199 }
200