119 lines
4.3 KiB
C++
119 lines
4.3 KiB
C++
/*
|
|
* Copyright 2022 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "gm/gm.h"
|
|
#include "include/core/SkCanvas.h"
|
|
#include "include/core/SkImage.h"
|
|
#include "include/core/SkPaint.h"
|
|
#include "include/core/SkPixmap.h"
|
|
#include "include/core/SkShader.h"
|
|
#include "include/core/SkSurface.h"
|
|
|
|
/**
|
|
* Tests drawing images are half pixel offsets in device space with nearest filtering to show how
|
|
* rasterization and image sample snapping at boundary points interact. Both drawImage and drawRect
|
|
* with an image shader are tested. Scale factors 1 and -1 are tested. The images are all two pixels
|
|
* wide or tall so we either get both values once each or one value repeated twice.
|
|
*/
|
|
DEF_SIMPLE_GM_CAN_FAIL(nearest_half_pixel_image, canvas, errorMsg, 264, 235) {
|
|
// We don't run this test on the GPU because we're at the driver/hw's mercy for how this
|
|
// is handled.
|
|
if (canvas->recordingContext() || (canvas->getSurface() && canvas->getSurface()->recorder())) {
|
|
*errorMsg = "Test is only relevant to CPU backend";
|
|
return skiagm::DrawResult::kSkip;
|
|
}
|
|
|
|
// We make 2x1 and 1x2 images for each color type.
|
|
struct Images {
|
|
sk_sp<SkImage> imageX;
|
|
sk_sp<SkImage> imageY;
|
|
};
|
|
|
|
Images images[2];
|
|
uint32_t colors[] {0xFFFF0000, 0xFF0000FF};
|
|
SkPixmap cpmx(SkImageInfo::Make({2, 1},
|
|
kRGBA_8888_SkColorType,
|
|
kPremul_SkAlphaType),
|
|
colors,
|
|
sizeof(colors));
|
|
SkPixmap cpmy(SkImageInfo::Make({1, 2},
|
|
kRGBA_8888_SkColorType,
|
|
kPremul_SkAlphaType),
|
|
colors,
|
|
sizeof(colors[0]));
|
|
images[0] = {SkImage::MakeRasterCopy(cpmx), SkImage::MakeRasterCopy(cpmy)};
|
|
|
|
uint8_t alphas[] {0xFF, 0xAA};
|
|
SkPixmap apmx(SkImageInfo::Make({2, 1},
|
|
kAlpha_8_SkColorType,
|
|
kPremul_SkAlphaType),
|
|
alphas,
|
|
sizeof(alphas));
|
|
SkPixmap apmy(SkImageInfo::Make({1, 2},
|
|
kAlpha_8_SkColorType,
|
|
kPremul_SkAlphaType),
|
|
alphas,
|
|
sizeof(alphas[0]));
|
|
images[1] = {SkImage::MakeRasterCopy(apmx), SkImage::MakeRasterCopy(apmy)};
|
|
|
|
// We draw offscreen and then zoom that up to make the result clear.
|
|
auto surf = canvas->makeSurface(canvas->imageInfo().makeWH(80, 80));
|
|
if (!surf) {
|
|
*errorMsg = "Test only works with SkSurface backed canvases";
|
|
return skiagm::DrawResult::kSkip;
|
|
}
|
|
auto* c = surf->getCanvas();
|
|
c->clear(SK_ColorWHITE);
|
|
|
|
// We scale up in the direction not being tested, the one with image dimension of 1, to make the
|
|
// result more easily visible.
|
|
static const float kOffAxisScale = 4;
|
|
|
|
auto draw = [&](sk_sp<SkImage> image, bool shader, bool doX, bool mirror, uint8_t alpha) {
|
|
c->save();
|
|
SkPaint paint;
|
|
paint.setAlpha(alpha);
|
|
if (shader) {
|
|
paint.setShader(image->makeShader(SkSamplingOptions{}));
|
|
}
|
|
if (doX) {
|
|
c->scale(mirror ? -1 : 1, kOffAxisScale);
|
|
c->translate(mirror ? -2.5 : 0.5, 0);
|
|
} else {
|
|
c->scale(kOffAxisScale, mirror ? -1 : 1);
|
|
c->translate(0, mirror ? -2.5 : 0.5);
|
|
}
|
|
|
|
if (shader) {
|
|
c->drawRect(SkRect::Make(image->dimensions()), paint);
|
|
} else {
|
|
c->drawImage(image, 0, 0, SkSamplingOptions{}, &paint);
|
|
}
|
|
c->restore();
|
|
};
|
|
|
|
for (bool shader : {false, true})
|
|
for (uint8_t alpha : {0xFF , 0x70}) {
|
|
c->save();
|
|
for (const auto& i : images)
|
|
for (auto mirror : {false, true}) {
|
|
draw(i.imageX, shader, /*doX=*/true, mirror, alpha);
|
|
c->save();
|
|
c->translate(4, 0);
|
|
draw(i.imageY, shader, /*doX=*/false, mirror, alpha);
|
|
c->restore();
|
|
c->translate(0, kOffAxisScale*2);
|
|
}
|
|
c->restore();
|
|
c->translate(kOffAxisScale*2, 0);
|
|
}
|
|
canvas->scale(8, 8);
|
|
canvas->drawImage(surf->makeImageSnapshot(), 0, 0);
|
|
|
|
return skiagm::DrawResult::kOk;
|
|
}
|