skia2/tests/RecordingXfermodeTest.cpp
Mike Klein c0bd9f9fe5 rewrite includes to not need so much -Ifoo
Current strategy: everything from the top

Things to look at first are the manual changes:

   - added tools/rewrite_includes.py
   - removed -Idirectives from BUILD.gn
   - various compile.sh simplifications
   - tweak tools/embed_resources.py
   - update gn/find_headers.py to write paths from the top
   - update gn/gn_to_bp.py SkUserConfig.h layout
     so that #include "include/config/SkUserConfig.h" always
     gets the header we want.

No-Presubmit: true
Change-Id: I73a4b181654e0e38d229bc456c0d0854bae3363e
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/209706
Commit-Queue: Mike Klein <mtklein@google.com>
Reviewed-by: Hal Canary <halcanary@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Reviewed-by: Florin Malita <fmalita@chromium.org>
2019-04-24 16:27:11 +00:00

175 lines
5.6 KiB
C++

/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "tests/Test.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkStream.h"
#include "include/core/SkString.h"
#include "src/core/SkBlendModePriv.h"
#include <cstring>
// Verify that replay of a recording into a clipped canvas
// produces the correct bitmap.
// This arose from http://crbug.com/401593 which has
// https://code.google.com/p/skia/issues/detail?id=1291 as its root cause.
namespace {
class Drawer {
public:
explicit Drawer() : fImageInfo(SkImageInfo::MakeN32Premul(200, 100)) {
fCircleBM.allocPixels(SkImageInfo::MakeN32Premul(100, 100));
SkCanvas canvas(fCircleBM);
canvas.clear(0xffffffff);
SkPaint circlePaint;
circlePaint.setColor(0xff000000);
canvas.drawCircle(50, 50, 50, circlePaint);
}
const SkImageInfo& imageInfo() const { return fImageInfo; }
void draw(SkCanvas* canvas, const SkRect& clipRect, SkBlendMode mode) const {
SkPaint greenPaint;
greenPaint.setColor(0xff008000);
SkPaint blackPaint;
blackPaint.setColor(0xff000000);
SkPaint whitePaint;
whitePaint.setColor(0xffffffff);
SkPaint layerPaint;
layerPaint.setColor(0xff000000);
layerPaint.setBlendMode(mode);
SkRect canvasRect(SkRect::MakeWH(SkIntToScalar(fImageInfo.width()),
SkIntToScalar(fImageInfo.height())));
canvas->clipRect(clipRect);
canvas->clear(0xff000000);
canvas->saveLayer(nullptr, &blackPaint);
canvas->drawRect(canvasRect, greenPaint);
canvas->saveLayer(nullptr, &layerPaint);
canvas->drawBitmapRect(fCircleBM, SkRect::MakeXYWH(20,20,60,60), &blackPaint);
canvas->restore();
canvas->restore();
}
private:
const SkImageInfo fImageInfo;
SkBitmap fCircleBM;
};
class RecordingStrategy {
public:
virtual ~RecordingStrategy() {}
virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
const SkRect& intoClip,
SkBlendMode) = 0;
};
class BitmapBackedCanvasStrategy : public RecordingStrategy {
// This version just draws into a bitmap-backed canvas.
public:
BitmapBackedCanvasStrategy(const SkImageInfo& imageInfo) {
fBitmap.allocPixels(imageInfo);
}
const SkBitmap& recordAndReplay(const Drawer& drawer, const SkRect& intoClip,
SkBlendMode mode) override {
SkCanvas canvas(fBitmap);
canvas.clear(0xffffffff);
// Note that the scene is drawn just into the clipped region!
canvas.clipRect(intoClip);
drawer.draw(&canvas, intoClip, mode); // Shouild be canvas-wide...
return fBitmap;
}
private:
SkBitmap fBitmap;
};
class PictureStrategy : public RecordingStrategy {
// This version draws the entire scene into an SkPictureRecorder.
// Then it then replays the scene through a clip rectangle.
// This backend proved to be buggy.
public:
PictureStrategy(const SkImageInfo& imageInfo) {
fBitmap.allocPixels(imageInfo);
fWidth = imageInfo.width();
fHeight = imageInfo.height();
}
const SkBitmap& recordAndReplay(const Drawer& drawer, const SkRect& intoClip,
SkBlendMode mode) override {
SkRTreeFactory factory;
SkPictureRecorder recorder;
SkRect canvasRect(SkRect::MakeWH(SkIntToScalar(fWidth),SkIntToScalar(fHeight)));
SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(fWidth),
SkIntToScalar(fHeight),
&factory);
drawer.draw(canvas, canvasRect, mode);
sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
SkCanvas replayCanvas(fBitmap);
replayCanvas.clear(0xffffffff);
replayCanvas.clipRect(intoClip);
picture->playback(&replayCanvas);
return fBitmap;
}
private:
SkBitmap fBitmap;
int fWidth;
int fHeight;
};
} // namespace
DEF_TEST(SkRecordingAccuracyXfermode, reporter) {
#define FINEGRAIN 0
const Drawer drawer;
BitmapBackedCanvasStrategy golden(drawer.imageInfo());
PictureStrategy picture(drawer.imageInfo());
#if !FINEGRAIN
unsigned numErrors = 0;
SkString errors;
#endif
for (int iMode = 0; iMode < int(SkBlendMode::kLastMode); iMode++) {
const SkRect& clip = SkRect::MakeXYWH(100, 0, 100, 100);
SkBlendMode mode = SkBlendMode(iMode);
const SkBitmap& goldenBM = golden.recordAndReplay(drawer, clip, mode);
const SkBitmap& pictureBM = picture.recordAndReplay(drawer, clip, mode);
size_t pixelsSize = goldenBM.computeByteSize();
REPORTER_ASSERT(reporter, pixelsSize == pictureBM.computeByteSize());
// The pixel arrays should match.
#if FINEGRAIN
REPORTER_ASSERT(reporter,
0 == memcmp(goldenBM.getPixels(), pictureBM.getPixels(), pixelsSize));
#else
if (memcmp(goldenBM.getPixels(), pictureBM.getPixels(), pixelsSize)) {
numErrors++;
errors.appendf("For SkXfermode %d %s: SkPictureRecorder bitmap is wrong\n",
iMode, SkBlendMode_Name(mode));
}
#endif
}
#if !FINEGRAIN
REPORTER_ASSERT(reporter, 0 == numErrors, errors.c_str());
#endif
}