add a system for building SkCanvas wrappers for testing
This adds a way to build a wrapping canvas for testing that is allowed to manipulate the internal state of the canvas. It provides a way to add friends to SkCanvas without having to change SkCanvas. Change-Id: I40de8b236ba5acff45b3a8f7e440dcf6fa196fcf Reviewed-on: https://skia-review.googlesource.com/c/skia/+/524316 Reviewed-by: Greg Daniel <egdaniel@google.com> Commit-Queue: Herb Derby <herb@google.com>
This commit is contained in:
parent
f3539b6c47
commit
3b238ceae9
@ -78,6 +78,7 @@ skia_utils_sources = [
|
|||||||
"$_src/utils/SkShadowUtils.cpp",
|
"$_src/utils/SkShadowUtils.cpp",
|
||||||
"$_src/utils/SkShaperJSONWriter.cpp",
|
"$_src/utils/SkShaperJSONWriter.cpp",
|
||||||
"$_src/utils/SkShaperJSONWriter.h",
|
"$_src/utils/SkShaperJSONWriter.h",
|
||||||
|
"$_src/utils/SkTestCanvas.h",
|
||||||
"$_src/utils/SkTextUtils.cpp",
|
"$_src/utils/SkTextUtils.cpp",
|
||||||
"$_src/utils/SkThreadUtils_pthread.cpp",
|
"$_src/utils/SkThreadUtils_pthread.cpp",
|
||||||
"$_src/utils/SkThreadUtils_win.cpp",
|
"$_src/utils/SkThreadUtils_win.cpp",
|
||||||
|
@ -2402,6 +2402,9 @@ private:
|
|||||||
friend class SkPictureRecord; // predrawNotify (why does it need it? <reed>)
|
friend class SkPictureRecord; // predrawNotify (why does it need it? <reed>)
|
||||||
friend class SkOverdrawCanvas;
|
friend class SkOverdrawCanvas;
|
||||||
friend class SkRasterHandleAllocator;
|
friend class SkRasterHandleAllocator;
|
||||||
|
template <typename Key>
|
||||||
|
friend class SkTestCanvas;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// For use by SkNoDrawCanvas (via SkCanvasVirtualEnforcer, which can't be a friend)
|
// For use by SkNoDrawCanvas (via SkCanvasVirtualEnforcer, which can't be a friend)
|
||||||
SkCanvas(const SkIRect& bounds);
|
SkCanvas(const SkIRect& bounds);
|
||||||
|
@ -16,6 +16,12 @@
|
|||||||
class SK_API SkNWayCanvas : public SkCanvasVirtualEnforcer<SkNoDrawCanvas> {
|
class SK_API SkNWayCanvas : public SkCanvasVirtualEnforcer<SkNoDrawCanvas> {
|
||||||
public:
|
public:
|
||||||
SkNWayCanvas(int width, int height);
|
SkNWayCanvas(int width, int height);
|
||||||
|
|
||||||
|
#if SK_SUPPORT_GPU && GR_TEST_UTILS
|
||||||
|
// You can turn NWay canvas into a canvas a wrapper for a single canvas by passing the
|
||||||
|
// canvas.
|
||||||
|
SkNWayCanvas(SkCanvas*);
|
||||||
|
#endif
|
||||||
~SkNWayCanvas() override;
|
~SkNWayCanvas() override;
|
||||||
|
|
||||||
virtual void addCanvas(SkCanvas*);
|
virtual void addCanvas(SkCanvas*);
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
#include "include/private/chromium/GrSlug.h"
|
#include "include/private/chromium/GrSlug.h"
|
||||||
#include "src/gpu/BaseDevice.h"
|
#include "src/gpu/BaseDevice.h"
|
||||||
#include "src/gpu/SkGr.h"
|
#include "src/gpu/SkGr.h"
|
||||||
|
#include "src/utils/SkTestCanvas.h"
|
||||||
#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
|
#if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
|
||||||
# include "src/gpu/GrRenderTarget.h"
|
# include "src/gpu/GrRenderTarget.h"
|
||||||
# include "src/gpu/GrRenderTargetProxy.h"
|
# include "src/gpu/GrRenderTargetProxy.h"
|
||||||
@ -2874,4 +2875,28 @@ SkRasterHandleAllocator::MakeCanvas(std::unique_ptr<SkRasterHandleAllocator> all
|
|||||||
return hndl ? std::unique_ptr<SkCanvas>(new SkCanvas(bm, std::move(alloc), hndl)) : nullptr;
|
return hndl ? std::unique_ptr<SkCanvas>(new SkCanvas(bm, std::move(alloc), hndl)) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
#if SK_SUPPORT_GPU && GR_TEST_UTILS
|
||||||
|
SkTestCanvas<SkSlugTestKey>::SkTestCanvas(SkCanvas* convertCanvas)
|
||||||
|
: SkNWayCanvas(convertCanvas)
|
||||||
|
, fGPUCanvas(convertCanvas) { }
|
||||||
|
|
||||||
|
void SkTestCanvas<SkSlugTestKey>::onDrawGlyphRunList(
|
||||||
|
const SkGlyphRunList& glyphRunList, const SkPaint& paint) {
|
||||||
|
SkRect bounds = glyphRunList.sourceBounds();
|
||||||
|
if (this->internalQuickReject(bounds, paint)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto layer = this->aboutToDraw(this, paint, &bounds);
|
||||||
|
if (layer) {
|
||||||
|
if (glyphRunList.hasRSXForm()) {
|
||||||
|
fGPUCanvas->onDrawGlyphRunList(glyphRunList, layer->paint());
|
||||||
|
} else {
|
||||||
|
auto slug = fGPUCanvas->onConvertGlyphRunListToSlug(glyphRunList, layer->paint());
|
||||||
|
fGPUCanvas->drawSlug(slug.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -8,14 +8,26 @@
|
|||||||
#include "include/core/SkShader.h"
|
#include "include/core/SkShader.h"
|
||||||
#include "include/utils/SkNWayCanvas.h"
|
#include "include/utils/SkNWayCanvas.h"
|
||||||
#include "src/core/SkCanvasPriv.h"
|
#include "src/core/SkCanvasPriv.h"
|
||||||
|
#include "src/core/SkDevice.h"
|
||||||
|
|
||||||
SkNWayCanvas::SkNWayCanvas(int width, int height) : INHERITED(width, height) {}
|
SkNWayCanvas::SkNWayCanvas(int width, int height) : INHERITED(width, height) {}
|
||||||
|
#if SK_SUPPORT_GPU && GR_TEST_UTILS
|
||||||
|
SkNWayCanvas::SkNWayCanvas(SkCanvas* canvas) : INHERITED(sk_ref_sp(canvas->baseDevice())) {
|
||||||
|
this->addCanvas(canvas);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SkNWayCanvas::~SkNWayCanvas() {
|
SkNWayCanvas::~SkNWayCanvas() {
|
||||||
this->removeAll();
|
this->removeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkNWayCanvas::addCanvas(SkCanvas* canvas) {
|
void SkNWayCanvas::addCanvas(SkCanvas* canvas) {
|
||||||
|
if (!fList.isEmpty()) {
|
||||||
|
// We are using the nway canvas as a wrapper for the originally added canvas, and the device
|
||||||
|
// on the nway may contradict calls for the device on this canvas. So, to add a second
|
||||||
|
// canvas, the devices on the first canvas, and the nway base device must be different.
|
||||||
|
SkASSERT(fList[0]->baseDevice() != this->baseDevice());
|
||||||
|
}
|
||||||
if (canvas) {
|
if (canvas) {
|
||||||
*fList.append() = canvas;
|
*fList.append() = canvas;
|
||||||
}
|
}
|
||||||
|
38
src/utils/SkTestCanvas.h
Normal file
38
src/utils/SkTestCanvas.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2022 Google LLC
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license that can be
|
||||||
|
* found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// SkTestCanvas is a simple way to make a testing canvas which is allowed to use private
|
||||||
|
// facilities of SkCanvas without having to add a friend to SkCanvas.h.
|
||||||
|
//
|
||||||
|
// You create a Key (a simple empty struct) to make a template specialization class. You need to
|
||||||
|
// make a key for each of the different Canvases you need. The implementations of the canvases
|
||||||
|
// are in SkCanvas.cpp, which allows the use of helper classes.
|
||||||
|
|
||||||
|
#ifndef SkTestCanvas_DEFINED
|
||||||
|
#define SkTestCanvas_DEFINED
|
||||||
|
|
||||||
|
#include "include/core/SkSize.h"
|
||||||
|
#include "include/utils/SkNWayCanvas.h"
|
||||||
|
#include "src/core/SkDevice.h"
|
||||||
|
#include "src/core/SkGlyphRun.h"
|
||||||
|
|
||||||
|
// You can only make template specializations of SkTestCanvas.
|
||||||
|
template <typename Key> class SkTestCanvas;
|
||||||
|
|
||||||
|
// A test canvas to test using slug rendering instead of text blob rendering.
|
||||||
|
struct SkSlugTestKey {};
|
||||||
|
template <>
|
||||||
|
class SkTestCanvas<SkSlugTestKey> : public SkNWayCanvas {
|
||||||
|
public:
|
||||||
|
SkTestCanvas(SkCanvas* convertCanvas);
|
||||||
|
void onDrawGlyphRunList(const SkGlyphRunList& glyphRunList, const SkPaint& paint) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SkCanvas* fGPUCanvas;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SkTestCanvas_DEFINED
|
Loading…
Reference in New Issue
Block a user