9a53fd7c41
This CL starts the process of pushing kLegacyFontHost_InitType-type SkSurfaceProps up the call stack and out of Skia. It: Gets rid of the default SkBaseDevice ctor. This means everyone has to always hand an explicit SkSurfaceProps to it. It makes public the SkBitmapDevice creation methods that require SkSurfaceProps. Removes (in Skia's code base) all SkBitmapDevice ctor calls w/o SkSurfaceProps. Makes the "recording" canvases (e.g., pdf, svg, xps) explicitly not use kLegacyFontHost_InitType. Replicates the creating canvas/device's flags on saveLayer devices BUG=skia:3934 Review URL: https://codereview.chromium.org/1204433002
170 lines
6.5 KiB
C++
170 lines
6.5 KiB
C++
/*
|
|
* Copyright 2013 Google Inc.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
* found in the LICENSE file.
|
|
*/
|
|
|
|
#include "SkBitmap.h"
|
|
#include "SkBitmapDevice.h"
|
|
#include "SkCanvas.h"
|
|
#include "SkDraw.h"
|
|
#include "SkLayerDrawLooper.h"
|
|
#include "SkMatrix.h"
|
|
#include "SkPaint.h"
|
|
#include "SkRect.h"
|
|
#include "SkRefCnt.h"
|
|
#include "SkScalar.h"
|
|
#include "SkSmallAllocator.h"
|
|
#include "SkXfermode.h"
|
|
#include "Test.h"
|
|
|
|
static SkBitmap make_bm(int w, int h) {
|
|
SkBitmap bm;
|
|
bm.allocN32Pixels(w, h);
|
|
return bm;
|
|
}
|
|
|
|
// TODO: can this be derived from SkBaseDevice?
|
|
class FakeDevice : public SkBitmapDevice {
|
|
public:
|
|
FakeDevice() : INHERITED(make_bm(100, 100), SkSurfaceProps(0, kUnknown_SkPixelGeometry)) {
|
|
}
|
|
|
|
void drawRect(const SkDraw& draw, const SkRect& r, const SkPaint& paint) override {
|
|
fLastMatrix = *draw.fMatrix;
|
|
this->INHERITED::drawRect(draw, r, paint);
|
|
}
|
|
|
|
SkMatrix fLastMatrix;
|
|
|
|
private:
|
|
typedef SkBitmapDevice INHERITED;
|
|
};
|
|
|
|
static void test_frontToBack(skiatest::Reporter* reporter) {
|
|
SkLayerDrawLooper::Builder looperBuilder;
|
|
SkLayerDrawLooper::LayerInfo layerInfo;
|
|
|
|
// Add the front layer, with the defaults.
|
|
(void)looperBuilder.addLayer(layerInfo);
|
|
|
|
// Add the back layer, with some layer info set.
|
|
layerInfo.fOffset.set(10.0f, 20.0f);
|
|
layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
|
|
SkPaint* layerPaint = looperBuilder.addLayer(layerInfo);
|
|
layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
|
|
|
|
FakeDevice device;
|
|
SkCanvas canvas(&device);
|
|
SkPaint paint;
|
|
SkAutoTUnref<SkLayerDrawLooper> looper(looperBuilder.detachLooper());
|
|
SkSmallAllocator<1, 32> allocator;
|
|
void* buffer = allocator.reserveT<SkDrawLooper::Context>(looper->contextSize());
|
|
SkDrawLooper::Context* context = looper->createContext(&canvas, buffer);
|
|
|
|
// The back layer should come first.
|
|
REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
|
|
REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode));
|
|
canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
|
|
REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
|
|
REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
|
|
paint.reset();
|
|
|
|
// Then the front layer.
|
|
REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
|
|
REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode));
|
|
canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
|
|
REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
|
|
REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
|
|
|
|
// Only two layers were added, so that should be the end.
|
|
REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
|
|
}
|
|
|
|
static void test_backToFront(skiatest::Reporter* reporter) {
|
|
SkLayerDrawLooper::Builder looperBuilder;
|
|
SkLayerDrawLooper::LayerInfo layerInfo;
|
|
|
|
// Add the back layer, with the defaults.
|
|
(void)looperBuilder.addLayerOnTop(layerInfo);
|
|
|
|
// Add the front layer, with some layer info set.
|
|
layerInfo.fOffset.set(10.0f, 20.0f);
|
|
layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
|
|
SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
|
|
layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
|
|
|
|
FakeDevice device;
|
|
SkCanvas canvas(&device);
|
|
SkPaint paint;
|
|
SkAutoTUnref<SkLayerDrawLooper> looper(looperBuilder.detachLooper());
|
|
SkSmallAllocator<1, 32> allocator;
|
|
void* buffer = allocator.reserveT<SkDrawLooper::Context>(looper->contextSize());
|
|
SkDrawLooper::Context* context = looper->createContext(&canvas, buffer);
|
|
|
|
// The back layer should come first.
|
|
REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
|
|
REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode));
|
|
canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
|
|
REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
|
|
REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
|
|
paint.reset();
|
|
|
|
// Then the front layer.
|
|
REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
|
|
REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode));
|
|
canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
|
|
REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
|
|
REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
|
|
|
|
// Only two layers were added, so that should be the end.
|
|
REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
|
|
}
|
|
|
|
static void test_mixed(skiatest::Reporter* reporter) {
|
|
SkLayerDrawLooper::Builder looperBuilder;
|
|
SkLayerDrawLooper::LayerInfo layerInfo;
|
|
|
|
// Add the back layer, with the defaults.
|
|
(void)looperBuilder.addLayer(layerInfo);
|
|
|
|
// Add the front layer, with some layer info set.
|
|
layerInfo.fOffset.set(10.0f, 20.0f);
|
|
layerInfo.fPaintBits |= SkLayerDrawLooper::kXfermode_Bit;
|
|
SkPaint* layerPaint = looperBuilder.addLayerOnTop(layerInfo);
|
|
layerPaint->setXfermodeMode(SkXfermode::kSrc_Mode);
|
|
|
|
FakeDevice device;
|
|
SkCanvas canvas(&device);
|
|
SkPaint paint;
|
|
SkAutoTUnref<SkLayerDrawLooper> looper(looperBuilder.detachLooper());
|
|
SkSmallAllocator<1, 32> allocator;
|
|
void* buffer = allocator.reserveT<SkDrawLooper::Context>(looper->contextSize());
|
|
SkDrawLooper::Context* context = looper->createContext(&canvas, buffer);
|
|
|
|
// The back layer should come first.
|
|
REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
|
|
REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrcOver_Mode));
|
|
canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
|
|
REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateX());
|
|
REPORTER_ASSERT(reporter, 0.0f == device.fLastMatrix.getTranslateY());
|
|
paint.reset();
|
|
|
|
// Then the front layer.
|
|
REPORTER_ASSERT(reporter, context->next(&canvas, &paint));
|
|
REPORTER_ASSERT(reporter, SkXfermode::IsMode(paint.getXfermode(), SkXfermode::kSrc_Mode));
|
|
canvas.drawRect(SkRect::MakeWH(50.0f, 50.0f), paint);
|
|
REPORTER_ASSERT(reporter, 10.0f == device.fLastMatrix.getTranslateX());
|
|
REPORTER_ASSERT(reporter, 20.0f == device.fLastMatrix.getTranslateY());
|
|
|
|
// Only two layers were added, so that should be the end.
|
|
REPORTER_ASSERT(reporter, !context->next(&canvas, &paint));
|
|
}
|
|
|
|
DEF_TEST(LayerDrawLooper, reporter) {
|
|
test_frontToBack(reporter);
|
|
test_backToFront(reporter);
|
|
test_mixed(reporter);
|
|
}
|