SkPaintFilterCanvas should inherit the target canvas state

Currently, SkPaintFilterCanvas does not provide any help in cloning
target canvas state.  While that could be handled in subclasses, it is
easy to miss (see linked bug).

This CL adds a new constructor variant which ensures that the initial
matrix and clip bounds are inherited from the target canvas.

BUG=516790
R=reed@google.com,robertphillips@google.com

Review URL: https://codereview.chromium.org/1294013002
This commit is contained in:
fmalita 2015-08-17 08:05:13 -07:00 committed by Commit bot
parent 340f3074b4
commit f433bb2beb
3 changed files with 57 additions and 0 deletions

View File

@ -16,8 +16,17 @@
*/ */
class SK_API SkPaintFilterCanvas : public SkNWayCanvas { class SK_API SkPaintFilterCanvas : public SkNWayCanvas {
public: public:
/**
* DEPRECATED: use the variant below.
*/
SkPaintFilterCanvas(int width, int height); SkPaintFilterCanvas(int width, int height);
/**
* The new SkPaintFilterCanvas is configured for forwarding to the
* specified canvas. Also copies the target canvas matrix and clip bounds.
*/
SkPaintFilterCanvas(SkCanvas* canvas);
enum Type { enum Type {
kPaint_Type, kPaint_Type,
kPoint_Type, kPoint_Type,

View File

@ -30,6 +30,18 @@ private:
SkPaintFilterCanvas::SkPaintFilterCanvas(int width, int height) : INHERITED(width, height) { } SkPaintFilterCanvas::SkPaintFilterCanvas(int width, int height) : INHERITED(width, height) { }
SkPaintFilterCanvas::SkPaintFilterCanvas(SkCanvas *canvas)
: INHERITED(canvas->imageInfo().width(), canvas->imageInfo().height()) {
// Transfer matrix & clip state before adding the target canvas.
SkIRect devClip;
canvas->getClipDeviceBounds(&devClip);
this->clipRect(SkRect::Make(devClip));
this->setMatrix(canvas->getTotalMatrix());
this->addCanvas(canvas);
}
void SkPaintFilterCanvas::onDrawPaint(const SkPaint& paint) { void SkPaintFilterCanvas::onDrawPaint(const SkPaint& paint) {
AutoPaintFilter apf(this, kPaint_Type, paint); AutoPaintFilter apf(this, kPaint_Type, paint);
this->INHERITED::onDrawPaint(*apf.paint()); this->INHERITED::onDrawPaint(*apf.paint());

View File

@ -52,6 +52,7 @@
#include "SkMatrix.h" #include "SkMatrix.h"
#include "SkNWayCanvas.h" #include "SkNWayCanvas.h"
#include "SkPaint.h" #include "SkPaint.h"
#include "SkPaintFilterCanvas.h"
#include "SkPath.h" #include "SkPath.h"
#include "SkPicture.h" #include "SkPicture.h"
#include "SkPictureRecord.h" #include "SkPictureRecord.h"
@ -782,3 +783,38 @@ DEF_TEST(Canvas_ClipEmptyPath, reporter) {
canvas.clipPath(path); // should not assert here canvas.clipPath(path); // should not assert here
canvas.restore(); canvas.restore();
} }
namespace {
class MockFilterCanvas : public SkPaintFilterCanvas {
public:
MockFilterCanvas(SkCanvas* canvas) : INHERITED(canvas) { }
protected:
void onFilterPaint(SkPaint *paint, Type type) const override { }
private:
typedef SkPaintFilterCanvas INHERITED;
};
} // anonymous namespace
// SkPaintFilterCanvas should inherit the initial target canvas state.
DEF_TEST(PaintFilterCanvas_ConsistentState, reporter) {
SkCanvas canvas(100, 100);
canvas.clipRect(SkRect::MakeXYWH(12.7f, 12.7f, 75, 75));
canvas.scale(0.5f, 0.75f);
SkRect clip1, clip2;
MockFilterCanvas filterCanvas(&canvas);
REPORTER_ASSERT(reporter, canvas.getTotalMatrix() == filterCanvas.getTotalMatrix());
REPORTER_ASSERT(reporter, canvas.getClipBounds(&clip1) == filterCanvas.getClipBounds(&clip2));
REPORTER_ASSERT(reporter, clip1 == clip2);
filterCanvas.clipRect(SkRect::MakeXYWH(30.5f, 30.7f, 100, 100));
filterCanvas.scale(0.75f, 0.5f);
REPORTER_ASSERT(reporter, canvas.getTotalMatrix() == filterCanvas.getTotalMatrix());
REPORTER_ASSERT(reporter, canvas.getClipBounds(&clip1) == filterCanvas.getClipBounds(&clip2));
REPORTER_ASSERT(reporter, clip1 == clip2);
}