• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 * Copyright 2022 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 "gm/gm.h"
9 #include "include/core/SkCanvas.h"
10 #include "include/core/SkImage.h"
11 #include "include/core/SkPaint.h"
12 #include "include/core/SkPixmap.h"
13 #include "include/core/SkShader.h"
14 #include "include/core/SkSurface.h"
15 #include "include/core/SkTileMode.h"
16 
17 /**
18  * Tests image shader mirror tile mode with scale factors of 1 and -1, with nearest and linear
19  * filtering, and with/without a half pixel offset between device and image space. The linear filter
20  * should only have an effect when there is a half pixel offset. We test mirror tile mode in x and
21  * in y separately.
22  */
23 DEF_SIMPLE_GM_CAN_FAIL(mirror_tile, canvas, errorMsg, 140, 370) {
24     // We don't run this test on the GPU because we're at the driver/hw's mercy for how this
25     // is handled. We also don't test this on recording or vector canvases.
26     if (SkPixmap unused; !canvas->peekPixels(&unused)) {
27         *errorMsg = "Test only works with canvases backed by CPU pixels";
28         return skiagm::DrawResult::kSkip;
29     }
30 
31     uint32_t colors[] {0xFFFF0000, 0xFF00FF00, 0xFF0000FF};
32     SkPixmap pmx(SkImageInfo::Make({std::size(colors), 1},
33                                    kRGBA_8888_SkColorType,
34                                    kPremul_SkAlphaType),
35                  colors,
36                  sizeof(colors));
37     auto imgx = SkImage::MakeRasterCopy(pmx);
38 
39     SkPixmap pmy(SkImageInfo::Make({1, std::size(colors)},
40                                    kRGBA_8888_SkColorType,
41                                    kPremul_SkAlphaType),
42                  colors,
43                  sizeof(colors[0]));
44     auto imgy = SkImage::MakeRasterCopy(pmy);
45 
46     // We draw offscreen and then zoom that up to make the result clear.
47     auto surf = canvas->makeSurface(canvas->imageInfo().makeWH(80, 80));
48     SkASSERT(surf);
49     auto* c = surf->getCanvas();
50     c->clear(SK_ColorWHITE);
51 
52     for (bool offset : {false, true}) {
53         for (SkFilterMode fm : {SkFilterMode::kNearest, SkFilterMode::kLinear}) {
54             SkPaint paint;
55 
56             // Draw single row image with mirror tiling in x and clamped in y.
57             paint.setShader(imgx->makeShader(SkTileMode::kMirror,
58                                              SkTileMode::kClamp,
59                                              SkSamplingOptions{fm}));
60             c->save();
61             c->translate(imgx->width(), 0);
62             if (offset) {
63                 c->translate(0.5, 0);
64             }
65             c->drawRect(SkRect::MakeXYWH(-imgx->width(), 0, 3*imgx->width(), 5), paint);
66             c->restore();
67 
68             // Draw single column image with mirror tiling in y and clamped in x.
69             paint.setShader(imgy->makeShader(SkTileMode::kClamp,
70                                              SkTileMode::kMirror,
71                                              SkSamplingOptions{fm}));
72             c->save();
73             c->translate(3*imgx->width() + 3, imgy->height());
74             if (offset) {
75                 c->translate(0, 0.5);
76             }
77             c->drawRect(SkRect::MakeXYWH(0, -imgy->height(), 5, 3*imgy->height()), paint);
78             c->restore();
79 
80             c->translate(0, 3*imgy->height() + 3);
81         }
82     }
83 
84     canvas->scale(8, 8);
85     canvas->drawImage(surf->makeImageSnapshot(), 0, 0);
86     return skiagm::DrawResult::kOk;
87 }
88