split SkPictureRecorder out of SkPicture

https://codereview.chromium.org/214953003/



git-svn-id: http://skia.googlecode.com/svn/trunk@14171 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
robertphillips@google.com 2014-04-13 19:09:42 +00:00
parent c202ea7cc6
commit 84b18c7e3e
39 changed files with 571 additions and 447 deletions

View File

@ -37,16 +37,15 @@ protected:
virtual void onDraw(const int loops, SkCanvas* canvas) {
SkPicture picture;
SkCanvas* pCanvas = picture.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT);
recordCanvas(pCanvas);
picture.endRecording();
SkPictureRecorder recorder;
SkCanvas* pCanvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT);
this->recordCanvas(pCanvas);
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
const SkPoint translateDelta = getTranslateDelta(loops);
for (int i = 0; i < loops; i++) {
picture.draw(canvas);
picture->draw(canvas);
canvas->translate(translateDelta.fX, translateDelta.fY);
}
}
@ -71,7 +70,7 @@ class TextPlaybackBench : public PicturePlaybackBench {
public:
TextPlaybackBench() : INHERITED("drawText") { }
protected:
virtual void recordCanvas(SkCanvas* canvas) {
virtual void recordCanvas(SkCanvas* canvas) SK_OVERRIDE {
SkPaint paint;
paint.setTextSize(fTextSize);
paint.setColor(SK_ColorBLACK);
@ -96,7 +95,7 @@ public:
: INHERITED(drawPosH ? "drawPosTextH" : "drawPosText")
, fDrawPosH(drawPosH) { }
protected:
virtual void recordCanvas(SkCanvas* canvas) {
virtual void recordCanvas(SkCanvas* canvas) SK_OVERRIDE {
SkPaint paint;
paint.setTextSize(fTextSize);
paint.setColor(SK_ColorBLACK);

View File

@ -51,15 +51,15 @@ public:
protected:
virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
SkAutoTDelete<SkPicture> picture;
SkPictureRecorder recorder;
SkCanvas* canvas = NULL;
const SkPoint translateDelta = getTranslateDelta(loops);
for (int i = 0; i < loops; i++) {
if (0 == i % kMaxLoopsPerCanvas) {
picture.reset(SkNEW(SkPicture));
canvas = picture->beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT);
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
canvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT);
}
SkColor color = SK_ColorYELLOW + (i % 255);
@ -120,12 +120,12 @@ protected:
virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
SkRandom rand;
SkPaint paint;
SkAutoTDelete<SkPicture> picture;
SkPictureRecorder recorder;
SkCanvas* canvas = NULL;
for (int i = 0; i < loops; i++) {
if (0 == i % kMaxLoopsPerCanvas) {
picture.reset(SkNEW(SkPicture));
canvas = picture->beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT);
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
canvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT);
}
paint.setColor(rand.nextU());
canvas->drawPaint(paint);
@ -158,8 +158,8 @@ public:
};
protected:
virtual void onDraw(const int loops, SkCanvas*) SK_OVERRIDE {
SkPicture picture;
SkCanvas* canvas = picture.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT);
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(PICTURE_WIDTH, PICTURE_HEIGHT);
for (int i = 0; i < loops; i++) {
canvas->drawPaint(fPaint[i % ObjCount]);
}

View File

@ -122,7 +122,7 @@ static void saveFile(const char name[], const char config[], const char dir[],
stream.write(data->data(), data->size());
}
static void performClip(SkCanvas* canvas, int w, int h) {
static void perform_clip(SkCanvas* canvas, int w, int h) {
SkRect r;
r.set(SkIntToScalar(10), SkIntToScalar(10),
@ -134,7 +134,7 @@ static void performClip(SkCanvas* canvas, int w, int h) {
canvas->clipRect(r, SkRegion::kXOR_Op);
}
static void performRotate(SkCanvas* canvas, int w, int h) {
static void perform_rotate(SkCanvas* canvas, int w, int h) {
const SkScalar x = SkIntToScalar(w) / 2;
const SkScalar y = SkIntToScalar(h) / 2;
@ -143,7 +143,7 @@ static void performRotate(SkCanvas* canvas, int w, int h) {
canvas->translate(-x, -y);
}
static void performScale(SkCanvas* canvas, int w, int h) {
static void perform_scale(SkCanvas* canvas, int w, int h) {
const SkScalar x = SkIntToScalar(w) / 2;
const SkScalar y = SkIntToScalar(h) / 2;
@ -480,7 +480,8 @@ int tool_main(int argc, char** argv) {
#endif
SkAutoTUnref<SkCanvas> canvas;
SkPicture recordFrom, recordTo;
SkAutoTUnref<SkPicture> recordFrom;
SkPictureRecorder recorderTo;
const SkIPoint dim = bench->getSize();
const SkPicture::RecordingFlags kRecordFlags =
@ -505,13 +506,15 @@ int tool_main(int argc, char** argv) {
canvas.reset(SkDeferredCanvas::Create(surface.get()));
break;
case kRecord_BenchMode:
canvas.reset(SkRef(recordTo.beginRecording(dim.fX, dim.fY, kRecordFlags)));
canvas.reset(SkRef(recorderTo.beginRecording(dim.fX, dim.fY, kRecordFlags)));
break;
case kPictureRecord_BenchMode:
bench->draw(1, recordFrom.beginRecording(dim.fX, dim.fY, kRecordFlags));
recordFrom.endRecording();
canvas.reset(SkRef(recordTo.beginRecording(dim.fX, dim.fY, kRecordFlags)));
case kPictureRecord_BenchMode: {
SkPictureRecorder recorderFrom;
bench->draw(1, recorderFrom.beginRecording(dim.fX, dim.fY, kRecordFlags));
recordFrom.reset(recorderFrom.endRecording());
canvas.reset(SkRef(recorderTo.beginRecording(dim.fX, dim.fY, kRecordFlags)));
break;
}
case kNormal_BenchMode:
canvas.reset(SkRef(surface->getCanvas()));
break;
@ -522,9 +525,15 @@ int tool_main(int argc, char** argv) {
if (NULL != canvas) {
canvas->clear(SK_ColorWHITE);
if (FLAGS_clip) { performClip(canvas, dim.fX, dim.fY); }
if (FLAGS_scale) { performScale(canvas, dim.fX, dim.fY); }
if (FLAGS_rotate) { performRotate(canvas, dim.fX, dim.fY); }
if (FLAGS_clip) {
perform_clip(canvas, dim.fX, dim.fY);
}
if (FLAGS_scale) {
perform_scale(canvas, dim.fX, dim.fY);
}
if (FLAGS_rotate) {
perform_rotate(canvas, dim.fX, dim.fY);
}
}
if (!loggedBenchName) {
@ -569,7 +578,7 @@ int tool_main(int argc, char** argv) {
if ((benchMode == kRecord_BenchMode || benchMode == kPictureRecord_BenchMode)) {
// Clear the recorded commands so that they do not accumulate.
canvas.reset(SkRef(recordTo.beginRecording(dim.fX, dim.fY, kRecordFlags)));
canvas.reset(SkRef(recorderTo.beginRecording(dim.fX, dim.fY, kRecordFlags)));
}
timer.start();
@ -591,7 +600,7 @@ int tool_main(int argc, char** argv) {
}
if (benchMode == kPictureRecord_BenchMode) {
recordFrom.draw(canvas);
recordFrom->draw(canvas);
} else {
bench->draw(loops, canvas);
}

View File

@ -41,8 +41,8 @@ void SkDebugger::loadPicture(SkPicture* picture) {
SkPicture* SkDebugger::copyPicture() {
// We can't just call clone here since we want to removed the "deleted"
// commands. Playing back will strip those out.
SkPicture* newPicture = new SkPicture;
SkCanvas* canvas = newPicture->beginRecording(fPictureWidth, fPictureHeight);
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(fPictureWidth, fPictureHeight);
bool vizMode = fDebugCanvas->getMegaVizMode();
fDebugCanvas->setMegaVizMode(false);
@ -62,8 +62,7 @@ SkPicture* SkDebugger::copyPicture() {
fDebugCanvas->setOverdrawViz(overDraw);
fDebugCanvas->setOutstandingSaveCount(saveCount);
newPicture->endRecording();
return newPicture;
return recorder.endRecording();
}
void SkDebugger::getOverviewText(const SkTDArray<double>* typeTimes,

View File

@ -22,13 +22,12 @@ ReplayTask::ReplayTask(const Task& parent,
{}
void ReplayTask::draw() {
SkPicture recorded;
const uint32_t flags = fUseRTree ? SkPicture::kOptimizeForClippedPlayback_RecordingFlag : 0;
RecordPicture(fGM.get(), &recorded, flags);
SkAutoTUnref<SkPicture> recorded(RecordPicture(fGM.get(), flags));
SkBitmap bitmap;
SetupBitmap(fReference.colorType(), fGM.get(), &bitmap);
DrawPicture(&recorded, &bitmap);
DrawPicture(recorded, &bitmap);
if (!BitmapsEqual(bitmap, fReference)) {
this->fail();
this->spawnChild(SkNEW_ARGS(WriteTask, (*this, bitmap)));

View File

@ -20,11 +20,10 @@ SerializeTask::SerializeTask(const Task& parent,
{}
void SerializeTask::draw() {
SkPicture recorded;
RecordPicture(fGM.get(), &recorded);
SkAutoTUnref<SkPicture> recorded(RecordPicture(fGM.get()));
SkDynamicMemoryWStream wStream;
recorded.serialize(&wStream, NULL);
recorded->serialize(&wStream, NULL);
SkAutoTUnref<SkStream> rStream(wStream.detachAsStream());
SkAutoTUnref<SkPicture> reconstructed(SkPicture::CreateFromStream(rStream));

View File

@ -29,9 +29,10 @@ void TileGridTask::draw() {
SkISize::Make(0,0), // Overlap between adjacent tiles.
SkIPoint::Make(0,0), // Offset.
};
const SkISize size = fGM->getISize();
SkTileGridPicture recorded(size.width(), size.height(), info);
RecordPicture(fGM.get(), &recorded, SkPicture::kUsePathBoundsForClip_RecordingFlag);
SkAutoTUnref<SkPictureFactory> factory(SkNEW_ARGS(SkTileGridPictureFactory, (info)));
SkAutoTUnref<SkPicture> recorded(RecordPicture(fGM.get(),
SkPicture::kUsePathBoundsForClip_RecordingFlag,
factory));
SkBitmap full;
SetupBitmap(fReference.colorType(), fGM.get(), &full);
@ -55,7 +56,7 @@ void TileGridTask::draw() {
matrix.postTranslate(-xOffset, -yOffset);
tileCanvas.setMatrix(matrix);
recorded.draw(&tileCanvas);
recorded->draw(&tileCanvas);
tileCanvas.flush();
fullCanvas.drawBitmap(tile, xOffset, yOffset, &paint);
}

View File

@ -10,13 +10,14 @@ SkString UnderJoin(const char* a, const char* b) {
return s;
}
void RecordPicture(skiagm::GM* gm, SkPicture* picture, uint32_t recordFlags) {
SkPicture* RecordPicture(skiagm::GM* gm, uint32_t recordFlags, SkPictureFactory* factory) {
const SkISize size = gm->getISize();
SkCanvas* canvas = picture->beginRecording(size.width(), size.height(), recordFlags);
SkPictureRecorder recorder(factory);
SkCanvas* canvas = recorder.beginRecording(size.width(), size.height(), recordFlags);
canvas->concat(gm->getInitialTransform());
gm->draw(canvas);
canvas->flush();
picture->endRecording();
return recorder.endRecording();
}
static void setup_bitmap(SkColorType ct, int width, int height, SkBitmap* bitmap) {

View File

@ -6,6 +6,8 @@
#include "SkString.h"
#include "gm_expectations.h"
class SkPictureFactory;
// Small free functions used in more than one place in DM.
namespace DM {
@ -13,8 +15,10 @@ namespace DM {
// UnderJoin("a", "b") -> "a_b"
SkString UnderJoin(const char* a, const char* b);
// Draw gm to picture. Passes recordFlags to SkPicture::beginRecording().
void RecordPicture(skiagm::GM* gm, SkPicture* picture, uint32_t recordFlags = 0);
// Draw gm to picture. Passes recordFlags to SkPictureRecorder::beginRecording().
SkPicture* RecordPicture(skiagm::GM* gm,
uint32_t recordFlags = 0,
SkPictureFactory* factory = NULL);
// Prepare bitmap to have gm or bench draw into it with this config.
// TODO(mtklein): make SkBenchmark::getSize()/GM::getISize() const.

View File

@ -29,11 +29,11 @@ protected:
int offset = 35000;
int extents = 1000;
SkPictureRecorder recorder;
// We record a picture of huge vertical extents in which we clear the canvas to red, create
// a 'extents' by 'extents' round rect clip at a vertical offset of 'offset', then draw
// green into that.
SkPicture pict;
SkCanvas* rec = pict.beginRecording(100, offset + extents);
SkCanvas* rec = recorder.beginRecording(100, offset + extents);
rec->drawColor(0xffff0000);
rec->save();
SkRect r = {
@ -47,18 +47,17 @@ protected:
rec->clipPath(p, SkRegion::kIntersect_Op, true);
rec->drawColor(0xff00ff00);
rec->restore();
pict.endRecording();
SkAutoTUnref<SkPicture> pict(recorder.endRecording());
// Next we play that picture into another picture of the same size.
SkPicture pict2;
pict.draw(pict2.beginRecording(100, offset + extents));
pict2.endRecording();
pict->draw(recorder.beginRecording(100, offset + extents));
SkAutoTUnref<SkPicture> pict2(recorder.endRecording());
// Finally we play the part of that second picture that should be green into the canvas.
canvas->save();
canvas->translate(SkIntToScalar(extents / 2),
SkIntToScalar(-(offset - extents / 2)));
pict2.draw(canvas);
pict2->draw(canvas);
canvas->restore();
// If the image is red, we erroneously decided the clipPath was empty and didn't record

View File

@ -1008,29 +1008,25 @@ public:
static SkPicture* generate_new_picture(GM* gm, BbhType bbhType, uint32_t recordFlags,
SkScalar scale = SK_Scalar1) {
// Pictures are refcounted so must be on heap
SkPicture* pict;
int width = SkScalarCeilToInt(SkScalarMul(SkIntToScalar(gm->getISize().width()), scale));
int height = SkScalarCeilToInt(SkScalarMul(SkIntToScalar(gm->getISize().height()), scale));
SkAutoTUnref<SkPictureFactory> factory;
if (kTileGrid_BbhType == bbhType) {
SkTileGridPicture::TileGridInfo info;
info.fMargin.setEmpty();
info.fOffset.setZero();
info.fTileInterval.set(16, 16);
pict = new SkTileGridPicture(width, height, info);
} else {
pict = new SkPicture;
factory.reset(SkNEW_ARGS(SkTileGridPictureFactory, (info)));
}
if (kNone_BbhType != bbhType) {
recordFlags |= SkPicture::kOptimizeForClippedPlayback_RecordingFlag;
}
SkCanvas* cv = pict->beginRecording(width, height, recordFlags);
SkPictureRecorder recorder(factory);
SkCanvas* cv = recorder.beginRecording(width, height, recordFlags);
cv->scale(scale, scale);
invokeGM(gm, cv, false, false);
pict->endRecording();
return pict;
return recorder.endRecording();
}
static SkPicture* stream_to_new_picture(const SkPicture& src) {

View File

@ -79,11 +79,11 @@ static SkPicture* create_save_layer_opt_1(SkTDArray<DrawType>* preOptPattern,
(*postOptPattern)[6] = RESTORE;
}
SkPicture* result = new SkPicture;
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(100, 100);
// have to disable the optimizations while generating the picture
SkCanvas* canvas = result->beginRecording(100, 100);
result->internalOnly_EnableOpts(false);
recorder.internalOnly_EnableOpts(false);
SkPaint saveLayerPaint;
saveLayerPaint.setColor(0xCC000000);
@ -112,9 +112,7 @@ static SkPicture* create_save_layer_opt_1(SkTDArray<DrawType>* preOptPattern,
}
canvas->restore();
result->endRecording();
return result;
return recorder.endRecording();
}
// straight-ahead version that is seen in the skps
@ -215,11 +213,11 @@ static SkPicture* create_save_layer_opt_2(SkTDArray<DrawType>* preOptPattern,
(*postOptPattern)[9] = RESTORE;
}
SkPicture* result = new SkPicture;
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(100, 100);
// have to disable the optimizations while generating the picture
SkCanvas* canvas = result->beginRecording(100, 100);
result->internalOnly_EnableOpts(false);
recorder.internalOnly_EnableOpts(false);
SkPaint saveLayerPaint;
saveLayerPaint.setColor(0xCC000000);
@ -252,9 +250,7 @@ static SkPicture* create_save_layer_opt_2(SkTDArray<DrawType>* preOptPattern,
canvas->restore();
canvas->restore();
result->endRecording();
return result;
return recorder.endRecording();
}
// straight-ahead version that is seen in the skps
@ -360,13 +356,13 @@ protected:
canvas->restore();
// re-render the 'pre' picture and thus 'apply' the optimization
SkAutoTUnref<SkPicture> post(new SkPicture);
SkPictureRecorder recorder;
SkCanvas* recordCanvas = post->beginRecording(pre->width(), pre->height());
SkCanvas* recordCanvas = recorder.beginRecording(pre->width(), pre->height());
pre->draw(recordCanvas);
post->endRecording();
SkAutoTUnref<SkPicture> post(recorder.endRecording());
if (!(check_pattern(*post, postPattern))) {
WARN("Post optimization pattern mismatch");

View File

@ -32,8 +32,8 @@ protected:
}
virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
SkPicture* pict = SkNEW(SkPicture);
SkCanvas* rec = pict->beginRecording(1200, 900);
SkPictureRecorder recorder;
SkCanvas* rec = recorder.beginRecording(1200, 900);
SkPath p;
SkRect r = {
SkIntToScalar(100),
@ -46,7 +46,7 @@ protected:
rec->translate(SkIntToScalar(250), SkIntToScalar(250));
rec->clipPath(p, SkRegion::kIntersect_Op, true);
rec->drawColor(0xffff0000);
pict->endRecording();
SkAutoTUnref<SkPicture> pict(recorder.endRecording());
canvas->setAllowSimplifyClip(true);
canvas->save();
@ -58,7 +58,6 @@ protected:
canvas->translate(SkIntToScalar(1200 / 2), 0);
canvas->drawPicture(*pict);
canvas->restore();
SkSafeUnref(pict);
}
private:

View File

@ -22,7 +22,8 @@ protected:
}
void makePicture() {
SkCanvas* canvas = fPicture.beginRecording(100, 100);
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(100, 100);
canvas->clear(0x00000000);
SkPaint paint;
paint.setAntiAlias(true);
@ -30,7 +31,7 @@ protected:
paint.setTextSize(SkIntToScalar(96));
const char* str = "e";
canvas->drawText(str, strlen(str), SkIntToScalar(20), SkIntToScalar(70), paint);
fPicture.endRecording();
fPicture.reset(recorder.endRecording());
}
virtual SkISize onISize() SK_OVERRIDE { return SkISize::Make(500, 150); }
@ -54,9 +55,9 @@ protected:
SkRect srcRect = SkRect::MakeXYWH(20, 20, 30, 30);
SkRect emptyRect = SkRect::MakeXYWH(20, 20, 0, 0);
SkRect bounds = SkRect::MakeXYWH(0, 0, 100, 100);
SkAutoTUnref<SkImageFilter> pictureSource(SkPictureImageFilter::Create(&fPicture));
SkAutoTUnref<SkImageFilter> pictureSourceSrcRect(SkPictureImageFilter::Create(&fPicture, srcRect));
SkAutoTUnref<SkImageFilter> pictureSourceEmptyRect(SkPictureImageFilter::Create(&fPicture, emptyRect));
SkAutoTUnref<SkImageFilter> pictureSource(SkPictureImageFilter::Create(fPicture));
SkAutoTUnref<SkImageFilter> pictureSourceSrcRect(SkPictureImageFilter::Create(fPicture, srcRect));
SkAutoTUnref<SkImageFilter> pictureSourceEmptyRect(SkPictureImageFilter::Create(fPicture, emptyRect));
// Draw the picture unscaled.
fillRectFiltered(canvas, bounds, pictureSource);
@ -82,7 +83,7 @@ protected:
}
private:
SkPicture fPicture;
SkAutoTUnref<SkPicture> fPicture;
typedef GM INHERITED;
};

View File

@ -31,11 +31,11 @@ public:
, fSceneSize(sceneSize) {
// Build the picture.
SkAutoTUnref<SkPicture> p(SkNEW(SkPicture));
SkCanvas* pictureCanvas = p->beginRecording(SkScalarRoundToInt(tileSize),
SkScalarRoundToInt(tileSize));
SkPictureRecorder recorder;
SkCanvas* pictureCanvas = recorder.beginRecording(SkScalarRoundToInt(tileSize),
SkScalarRoundToInt(tileSize));
this->drawTile(pictureCanvas);
p->endRecording();
SkAutoTUnref<SkPicture> p(recorder.endRecording());
// Build a reference bitmap.
SkBitmap bm;

View File

@ -15,6 +15,7 @@
'skia_for_chromium_defines': [
'SK_SUPPORT_LEGACY_PUBLICEFFECTCONSTRUCTORS=1',
'SK_SUPPORT_LEGACY_GETTOPDEVICE',
'SK_SUPPORT_LEGACY_PICTURE_CAN_RECORD',
'SK_SUPPORT_LEGACY_N32_NAME',
],
},

View File

@ -160,6 +160,13 @@ public:
kOptimizeForClippedPlayback_RecordingFlag = 0x02,
};
#ifndef SK_SUPPORT_LEGACY_PICTURE_CAN_RECORD
private:
friend class SkPictureRecorder;
friend class SkImage_Picture;
friend class SkSurface_Picture;
#endif
/** Returns the canvas that records the drawing commands.
@param width the base width for the picture, as if the recording
canvas' bitmap had this width.
@ -181,6 +188,10 @@ public:
*/
void endRecording();
#ifndef SK_SUPPORT_LEGACY_PICTURE_CAN_RECORD
public:
#endif
/** Replays the drawing commands on the specified canvas. This internally
calls endRecording() if that has not already been called.
@param canvas the canvas receiving the drawing commands.
@ -388,4 +399,81 @@ public:
virtual bool abortDrawing() = 0;
};
class SkPictureFactory : public SkRefCnt {
public:
/**
* Allocate a new SkPicture. Return NULL on failure.
*/
virtual SkPicture* create(int width, int height) = 0;
};
class SK_API SkPictureRecorder : SkNoncopyable {
public:
SkPictureRecorder(SkPictureFactory* factory = NULL) {
fFactory.reset(factory);
if (NULL != fFactory.get()) {
fFactory.get()->ref();
}
}
/** Returns the canvas that records the drawing commands.
@param width the base width for the picture, as if the recording
canvas' bitmap had this width.
@param height the base width for the picture, as if the recording
canvas' bitmap had this height.
@param recordFlags optional flags that control recording.
@return the canvas.
*/
SkCanvas* beginRecording(int width, int height, uint32_t recordFlags = 0) {
if (NULL != fFactory) {
fPicture.reset(fFactory->create(width, height));
} else {
fPicture.reset(SkNEW(SkPicture));
}
return fPicture->beginRecording(width, height, recordFlags);
}
/** Returns the recording canvas if one is active, or NULL if recording is
not active. This does not alter the refcnt on the canvas (if present).
*/
SkCanvas* getRecordingCanvas() {
if (NULL != fPicture.get()) {
return fPicture->getRecordingCanvas();
}
return NULL;
}
/** Signal that the caller is done recording. This invalidates the canvas
returned by beginRecording/getRecordingCanvas, and returns the
created SkPicture. Note that the returned picture has its creation
ref which the caller must take ownership of.
*/
SkPicture* endRecording() {
if (NULL != fPicture.get()) {
fPicture->endRecording();
return fPicture.detach();
}
return NULL;
}
/** Enable/disable all the picture recording optimizations (i.e.,
those in SkPictureRecord). It is mainly intended for testing the
existing optimizations (i.e., to actually have the pattern
appear in an .skp we have to disable the optimization). Call right
after 'beginRecording'.
*/
void internalOnly_EnableOpts(bool enableOpts) {
if (NULL != fPicture.get()) {
fPicture->internalOnly_EnableOpts(enableOpts);
}
}
private:
SkAutoTUnref<SkPictureFactory> fFactory;
SkAutoTUnref<SkPicture> fPicture;
typedef SkNoncopyable INHERITED;
};
#endif

View File

@ -51,6 +51,23 @@ public:
private:
int fXTileCount, fYTileCount;
TileGridInfo fInfo;
typedef SkPicture INHERITED;
};
class SkTileGridPictureFactory : public SkPictureFactory {
public:
SkTileGridPictureFactory(const SkTileGridPicture::TileGridInfo& info) : fInfo(info) { }
virtual SkPicture* create(int width, int height) SK_OVERRIDE {
return SkNEW_ARGS(SkTileGridPicture, (width, height, fInfo));
}
protected:
SkTileGridPicture::TileGridInfo fInfo;
private:
typedef SkPictureFactory INHERITED;
};
#endif

View File

@ -302,13 +302,17 @@ protected:
virtual void onDrawContent(SkCanvas* canvas) {
canvas->save();
drawPicture(canvas, 0);
this->drawPicture(canvas, 0);
canvas->restore();
{
SkPicture picture;
SkCanvas* record = picture.beginRecording(320, 480);
drawPicture(record, 120);
SkPictureRecorder recorder;
{
SkCanvas* record = recorder.beginRecording(320, 480);
this->drawPicture(record, 120);
}
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
canvas->translate(0, SkIntToScalar(120));
SkRect clip;
@ -316,7 +320,7 @@ protected:
do {
canvas->save();
canvas->clipRect(clip);
picture.draw(canvas);
picture->draw(canvas);
canvas->restore();
if (clip.fRight < SkIntToScalar(320))
clip.offset(SkIntToScalar(160), 0);

View File

@ -834,8 +834,6 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
fclose(f);
#endif
fPicture = NULL;
fDeviceType = kRaster_DeviceType;
#if DEFAULT_TO_GPU
@ -990,7 +988,6 @@ SampleWindow::SampleWindow(void* hwnd, int argc, char** argv, DeviceManager* dev
}
SampleWindow::~SampleWindow() {
delete fPicture;
delete fPdfCanvas;
fTypeface->unref();
@ -1379,8 +1376,7 @@ SkCanvas* SampleWindow::beforeChildren(SkCanvas* canvas) {
pdfDevice->unref();
canvas = fPdfCanvas;
} else if (kPicture_DeviceType == fDeviceType) {
fPicture = new SkPicture;
canvas = fPicture->beginRecording(9999, 9999);
canvas = fRecorder.beginRecording(9999, 9999);
} else {
#if SK_SUPPORT_GPU
if (kNullGPU_DeviceType != fDeviceType)
@ -1459,16 +1455,16 @@ void SampleWindow::afterChildren(SkCanvas* orig) {
}
if (kPicture_DeviceType == fDeviceType) {
SkAutoTUnref<SkPicture> picture(fRecorder.endRecording());
if (true) {
SkPicture* pict = new SkPicture(*fPicture);
fPicture->unref();
SkPicture* pict = new SkPicture(*picture);
this->installDrawFilter(orig);
orig->drawPicture(*pict);
pict->unref();
} else if (true) {
SkDynamicMemoryWStream ostream;
fPicture->serialize(&ostream);
fPicture->unref();
picture->serialize(&ostream);
SkAutoDataUnref data(ostream.copyToData());
SkMemoryStream istream(data->data(), data->size());
@ -1477,10 +1473,8 @@ void SampleWindow::afterChildren(SkCanvas* orig) {
orig->drawPicture(*pict.get());
}
} else {
fPicture->draw(orig);
fPicture->unref();
picture->draw(orig);
}
fPicture = NULL;
}
// Do this after presentGL and other finishing, rather than in afterChild

View File

@ -10,6 +10,7 @@
#include "SkOSMenu.h"
#include "SkPath.h"
#include "SkPicture.h"
#include "SkScalar.h"
#include "SkTDArray.h"
#include "SkTouchGesture.h"
@ -21,7 +22,6 @@ class GrRenderTarget;
class SkCanvas;
class SkData;
class SkEvent;
class SkPicture;
class SkTypeface;
class SkViewFactory;
@ -168,7 +168,7 @@ private:
int fCurrIndex;
SkPicture* fPicture;
SkPictureRecorder fRecorder;
SkPath fClipPath;
SkTouchGesture fGesture;

View File

@ -122,19 +122,19 @@ private:
SkSize fTileSize;
SkPicture* LoadPicture(const char path[], BBoxType bbox) {
SkPicture* pic = NULL;
SkAutoTUnref<SkPicture> pic;
SkBitmap bm;
if (SkImageDecoder::DecodeFile(path, &bm)) {
bm.setImmutable();
pic = SkNEW(SkPicture);
SkCanvas* can = pic->beginRecording(bm.width(), bm.height());
SkPictureRecorder recorder;
SkCanvas* can = recorder.beginRecording(bm.width(), bm.height());
can->drawBitmap(bm, 0, 0, NULL);
pic->endRecording();
pic.reset(recorder.endRecording());
} else {
SkFILEStream stream(path);
if (stream.isValid()) {
pic = SkPicture::CreateFromStream(&stream);
pic.reset(SkPicture::CreateFromStream(&stream));
} else {
SkDebugf("coun't load picture at \"path\"\n", path);
}
@ -145,32 +145,30 @@ private:
surf->unref();
}
if (false) { // re-record
SkPicture p2;
pic->draw(p2.beginRecording(pic->width(), pic->height()));
p2.endRecording();
SkPictureRecorder recorder;
pic->draw(recorder.beginRecording(pic->width(), pic->height()));
SkAutoTUnref<SkPicture> p2(recorder.endRecording());
SkString path2(path);
path2.append(".new.skp");
SkFILEWStream writer(path2.c_str());
p2.serialize(&writer);
p2->serialize(&writer);
}
}
if (!pic) {
if (NULL == pic) {
return NULL;
}
SkPicture* bboxPicture = NULL;
SkAutoTUnref<SkPictureFactory> factory;
switch (bbox) {
case kNo_BBoxType:
// no bbox playback necessary
break;
return pic.detach();
case kRTree_BBoxType:
bboxPicture = SkNEW(SkPicture);
break;
case kQuadTree_BBoxType:
bboxPicture = SkNEW_ARGS(SkQuadTreePicture,
(SkIRect::MakeWH(pic->width(), pic->height())));
factory.reset(SkNEW(SkQuadTreePictureFactory));
break;
case kTileGrid_BBoxType: {
SkASSERT(!fTileSize.isEmpty());
@ -178,21 +176,17 @@ private:
gridInfo.fMargin = SkISize::Make(0, 0);
gridInfo.fOffset = SkIPoint::Make(0, 0);
gridInfo.fTileInterval = fTileSize.toRound();
bboxPicture = SkNEW_ARGS(SkTileGridPicture, (pic->width(), pic->height(), gridInfo));
} break;
factory.reset(SkNEW_ARGS(SkTileGridPictureFactory, (gridInfo)));
break;
}
default:
SkASSERT(false);
}
if (bboxPicture) {
pic->draw(bboxPicture->beginRecording(pic->width(), pic->height(),
SkPicture::kOptimizeForClippedPlayback_RecordingFlag));
bboxPicture->endRecording();
SkDELETE(pic);
return bboxPicture;
}
return pic;
SkPictureRecorder recorder(factory);
pic->draw(recorder.beginRecording(pic->width(), pic->height(),
SkPicture::kOptimizeForClippedPlayback_RecordingFlag));
return recorder.endRecording();
}
typedef SampleView INHERITED;

View File

@ -61,15 +61,18 @@ public:
fBitmap = load_bitmap();
fPicture = new SkPicture;
SkCanvas* canvas = fPicture->beginRecording(100, 100);
SkPictureRecorder recorder;
recorder.beginRecording(100, 100);
fSubPicture = recorder.endRecording();
SkCanvas* canvas = recorder.beginRecording(100, 100);
SkPaint paint;
paint.setAntiAlias(true);
canvas->drawBitmap(fBitmap, 0, 0, NULL);
drawCircle(canvas, 50, SK_ColorBLACK);
fSubPicture = new SkPicture;
canvas->drawPicture(*fSubPicture);
canvas->translate(SkIntToScalar(50), 0);
canvas->drawPicture(*fSubPicture);
@ -77,8 +80,11 @@ public:
canvas->drawPicture(*fSubPicture);
canvas->translate(SkIntToScalar(-50), 0);
canvas->drawPicture(*fSubPicture);
// fPicture now has (4) references to us. We can release ours, and just
// unref fPicture in our destructor, and it will in turn take care of
fPicture = recorder.endRecording();
// fPicture now has (4) references to fSubPicture. We can release our ref,
// and just unref fPicture in our destructor, and it will in turn take care of
// the other references to fSubPicture
fSubPicture->unref();
}
@ -123,13 +129,11 @@ protected:
}
virtual void onDrawContent(SkCanvas* canvas) {
drawSomething(canvas);
this->drawSomething(canvas);
SkPicture* pict = new SkPicture;
SkAutoUnref aur(pict);
drawSomething(pict->beginRecording(100, 100));
pict->endRecording();
SkPictureRecorder recorder;
this->drawSomething(recorder.beginRecording(100, 100));
SkAutoTUnref<SkPicture> pict(recorder.endRecording());
canvas->save();
canvas->translate(SkIntToScalar(300), SkIntToScalar(50));
@ -160,12 +164,11 @@ protected:
}
#endif
// test that we can re-record a subpicture, and see the results
// This used to re-record the sub-picture and redraw the parent
// A capability that is now forbidden!
SkRandom rand(SampleCode::GetAnimTime());
canvas->translate(SkIntToScalar(10), SkIntToScalar(250));
drawCircle(fSubPicture->beginRecording(50, 50), 25,
rand.nextU() | 0xFF000000);
canvas->drawPicture(*fPicture);
delayInval(500);
}

View File

@ -62,21 +62,19 @@ static const int gWidth = 32;
static const int gHeight = 32;
class TilingView : public SampleView {
SkPicture* fTextPicture;
SkBlurDrawLooper fLooper;
SkAutoTUnref<SkPicture> fTextPicture;
SkBlurDrawLooper fLooper;
public:
TilingView()
: fLooper(0x88000000,
SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(1)),
SkIntToScalar(2), SkIntToScalar(2)) {
fTextPicture = new SkPicture();
for (size_t i = 0; i < SK_ARRAY_COUNT(gColorTypes); i++) {
makebm(&fTexture[i], gColorTypes[i], gWidth, gHeight);
}
}
~TilingView() {
fTextPicture->unref();
virtual ~TilingView() {
}
SkBitmap fTexture[SK_ARRAY_COUNT(gColorTypes)];
@ -105,12 +103,13 @@ protected:
SkScalar y = SkIntToScalar(24);
SkScalar x = SkIntToScalar(10);
SkPictureRecorder recorder;
SkCanvas* textCanvas = NULL;
if (fTextPicture->width() == 0) {
textCanvas = fTextPicture->beginRecording(1000, 1000);
textCanvas = recorder.beginRecording(1000, 1000);
}
if (textCanvas) {
if (NULL != textCanvas) {
for (size_t kx = 0; kx < SK_ARRAY_COUNT(gModes); kx++) {
for (size_t ky = 0; ky < SK_ARRAY_COUNT(gModes); ky++) {
SkPaint p;
@ -160,6 +159,8 @@ protected:
}
}
fTextPicture.reset(recorder.endRecording());
canvas->drawPicture(*fTextPicture);
}

View File

@ -290,7 +290,7 @@ const SkPicture::OperationList& SkPicture::OperationList::InvalidList() {
}
const SkPicture::OperationList& SkPicture::EXPERIMENTAL_getActiveOps(const SkIRect& queryRect) {
this->endRecording();
this->endRecording(); // TODO: remove eventually
if (NULL != fPlayback) {
return fPlayback->getActiveOps(queryRect);
}
@ -305,7 +305,7 @@ size_t SkPicture::EXPERIMENTAL_curOpID() const {
}
void SkPicture::draw(SkCanvas* surface, SkDrawPictureCallback* callback) {
this->endRecording();
this->endRecording(); // TODO: remove eventually
if (NULL != fPlayback) {
fPlayback->draw(*surface, callback);
}

View File

@ -24,6 +24,18 @@ public:
virtual SkBBoxHierarchy* createBBoxHierarchy() const SK_OVERRIDE;
private:
SkIRect fBounds;
typedef SkPicture INHERITED;
};
class SkQuadTreePictureFactory : public SkPictureFactory {
private:
virtual SkPicture* create(int width, int height) SK_OVERRIDE {
return SkNEW_ARGS(SkQuadTreePicture, (SkIRect::MakeWH(width, height)));
}
private:
typedef SkPictureFactory INHERITED;
};
#endif

View File

@ -495,12 +495,13 @@ TEST_STEP_NO_PDF(DrawVerticesShader, DrawVerticesShaderTestStep);
static void DrawPictureTestStep(SkCanvas* canvas,
skiatest::Reporter*,
CanvasTestStep*) {
SkPicture* testPicture = SkNEW_ARGS(SkPicture, ());
SkAutoUnref aup(testPicture);
SkCanvas* testCanvas = testPicture->beginRecording(kWidth, kHeight);
SkPictureRecorder recorder;
SkCanvas* testCanvas = recorder.beginRecording(kWidth, kHeight);
testCanvas->scale(SkIntToScalar(2), SkIntToScalar(1));
testCanvas->clipRect(kTestRect);
testCanvas->drawRect(kTestRect, kTestPaint);
SkAutoTUnref<SkPicture> testPicture(recorder.endRecording());
canvas->drawPicture(*testPicture);
}
TEST_STEP(DrawPicture, DrawPictureTestStep);
@ -722,24 +723,23 @@ public:
// Verify that when a test step is executed twice, no extra resources
// are flattened during the second execution
testStep->setAssertMessageFormat(kPictureDrawAssertMessageFormat);
SkPicture referencePicture;
SkCanvas* referenceCanvas = referencePicture.beginRecording(kWidth,
kHeight, recordFlags);
SkPictureRecorder referenceRecorder;
SkCanvas* referenceCanvas = referenceRecorder.beginRecording(kWidth,
kHeight, recordFlags);
testStep->draw(referenceCanvas, reporter);
SkPicture testPicture;
SkCanvas* testCanvas = testPicture.beginRecording(kWidth,
kHeight, recordFlags);
SkPictureRecorder testRecorder;
SkCanvas* testCanvas = testRecorder.beginRecording(kWidth,
kHeight, recordFlags);
testStep->draw(testCanvas, reporter);
testStep->setAssertMessageFormat(kPictureSecondDrawAssertMessageFormat);
testStep->draw(testCanvas, reporter);
SkPictureRecord* referenceRecord = static_cast<SkPictureRecord*>(
referenceCanvas);
SkPictureRecord* testRecord = static_cast<SkPictureRecord*>(
testCanvas);
SkPictureRecord* referenceRecord = static_cast<SkPictureRecord*>(referenceCanvas);
SkPictureRecord* testRecord = static_cast<SkPictureRecord*>(testCanvas);
testStep->setAssertMessageFormat(kPictureResourceReuseMessageFormat);
AssertFlattenedObjectsEqual(referenceRecord, testRecord,
reporter, testStep);
reporter, testStep);
}
};

View File

@ -276,8 +276,8 @@ DEF_TEST(ImageFilterMatrixTest, reporter) {
SkMatrix expectedMatrix = canvas.getTotalMatrix();
SkPicture picture;
SkCanvas* recordingCanvas = picture.beginRecording(100, 100,
SkPictureRecorder recorder;
SkCanvas* recordingCanvas = recorder.beginRecording(100, 100,
SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
SkPaint paint;
@ -294,9 +294,9 @@ DEF_TEST(ImageFilterMatrixTest, reporter) {
recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(100, 100)), solidPaint);
recordingCanvas->restore(); // scale
recordingCanvas->restore(); // saveLayer
picture.endRecording();
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
canvas.drawPicture(picture);
canvas.drawPicture(*picture);
}
static void test_huge_blur(SkBaseDevice* device, skiatest::Reporter* reporter) {

View File

@ -32,7 +32,7 @@ public:
virtual void drawRect(const SkDraw& draw, const SkRect& r,
const SkPaint& paint) SK_OVERRIDE {
fLastMatrix = *draw.fMatrix;
INHERITED::drawRect(draw, r, paint);
this->INHERITED::drawRect(draw, r, paint);
}
SkMatrix fLastMatrix;

View File

@ -301,8 +301,8 @@ static SkPicture* record_bitmaps(const SkBitmap bm[],
SkTDArray<SkPixelRef*> analytic[],
int count,
DrawBitmapProc proc) {
SkPicture* pic = new SkPicture;
SkCanvas* canvas = pic->beginRecording(1000, 1000);
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(1000, 1000);
for (int i = 0; i < count; ++i) {
analytic[i].rewind();
canvas->save();
@ -313,8 +313,7 @@ static SkPicture* record_bitmaps(const SkBitmap bm[],
proc(canvas, bm[i], bm[count+i], pos[i], &analytic[i]);
canvas->restore();
}
pic->endRecording();
return pic;
return recorder.endRecording();
}
static void rand_rect(SkRect* rect, SkRandom& rand, SkScalar W, SkScalar H) {
@ -657,22 +656,22 @@ static void test_gatherpixelrefsandrects(skiatest::Reporter* reporter) {
// Ensure that deleting SkPicturePlayback does not assert. Asserts only fire in debug mode, so only
// run in debug mode.
static void test_deleting_empty_playback() {
SkPicture picture;
SkPictureRecorder recorder;
// Creates an SkPictureRecord
picture.beginRecording(0, 0);
recorder.beginRecording(0, 0);
// Turns that into an SkPicturePlayback
picture.endRecording();
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
// Deletes the old SkPicturePlayback, and creates a new SkPictureRecord
picture.beginRecording(0, 0);
recorder.beginRecording(0, 0);
}
// Ensure that serializing an empty picture does not assert. Likewise only runs in debug mode.
static void test_serializing_empty_picture() {
SkPicture picture;
picture.beginRecording(0, 0);
picture.endRecording();
SkPictureRecorder recorder;
recorder.beginRecording(0, 0);
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
SkDynamicMemoryWStream stream;
picture.serialize(&stream);
picture->serialize(&stream);
}
#endif
@ -712,66 +711,78 @@ static void test_unbalanced_save_restores(skiatest::Reporter* reporter) {
SkPaint paint;
SkRect rect = SkRect::MakeLTRB(-10000000, -10000000, 10000000, 10000000);
SkPicture extra_save_picture;
extra_save_picture.beginRecording(100, 100);
extra_save_picture.getRecordingCanvas()->save();
extra_save_picture.getRecordingCanvas()->translate(10, 10);
extra_save_picture.getRecordingCanvas()->drawRect(rect, paint);
extra_save_picture.getRecordingCanvas()->save();
extra_save_picture.getRecordingCanvas()->translate(10, 10);
extra_save_picture.getRecordingCanvas()->drawRect(rect, paint);
SkPictureRecorder recorder;
testCanvas.drawPicture(extra_save_picture);
REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
{
// Create picture with 2 unbalanced saves
SkCanvas* canvas = recorder.beginRecording(100, 100);
canvas->save();
canvas->translate(10, 10);
canvas->drawRect(rect, paint);
canvas->save();
canvas->translate(10, 10);
canvas->drawRect(rect, paint);
SkAutoTUnref<SkPicture> extraSavePicture(recorder.endRecording());
testCanvas.drawPicture(*extraSavePicture);
REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
}
set_canvas_to_save_count_4(&testCanvas);
SkPicture extra_restore_picture;
extra_restore_picture.beginRecording(100, 100);
extra_restore_picture.getRecordingCanvas()->save();
extra_restore_picture.getRecordingCanvas()->translate(10, 10);
extra_restore_picture.getRecordingCanvas()->drawRect(rect, paint);
extra_restore_picture.getRecordingCanvas()->save();
extra_restore_picture.getRecordingCanvas()->translate(10, 10);
extra_restore_picture.getRecordingCanvas()->drawRect(rect, paint);
extra_restore_picture.getRecordingCanvas()->restore();
extra_restore_picture.getRecordingCanvas()->restore();
extra_restore_picture.getRecordingCanvas()->restore();
extra_restore_picture.getRecordingCanvas()->restore();
{
// Create picture with 2 unbalanced restores
SkCanvas* canvas = recorder.beginRecording(100, 100);
canvas->save();
canvas->translate(10, 10);
canvas->drawRect(rect, paint);
canvas->save();
canvas->translate(10, 10);
canvas->drawRect(rect, paint);
canvas->restore();
canvas->restore();
canvas->restore();
canvas->restore();
SkAutoTUnref<SkPicture> extraRestorePicture(recorder.endRecording());
testCanvas.drawPicture(extra_save_picture);
REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
testCanvas.drawPicture(*extraRestorePicture);
REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
}
SkPicture no_save_picture;
extra_restore_picture.beginRecording(100, 100);
extra_restore_picture.getRecordingCanvas()->translate(10, 10);
extra_restore_picture.getRecordingCanvas()->drawRect(rect, paint);
set_canvas_to_save_count_4(&testCanvas);
testCanvas.drawPicture(extra_save_picture);
REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
REPORTER_ASSERT(reporter, testCanvas.getTotalMatrix().isIdentity());
{
SkCanvas* canvas = recorder.beginRecording(100, 100);
canvas->translate(10, 10);
canvas->drawRect(rect, paint);
SkAutoTUnref<SkPicture> noSavePicture(recorder.endRecording());
testCanvas.drawPicture(*noSavePicture);
REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount());
REPORTER_ASSERT(reporter, testCanvas.getTotalMatrix().isIdentity());
}
}
static void test_peephole() {
SkRandom rand;
SkPictureRecorder recorder;
for (int j = 0; j < 100; j++) {
SkRandom rand2(rand); // remember the seed
SkPicture picture;
SkCanvas* canvas = picture.beginRecording(100, 100);
SkCanvas* canvas = recorder.beginRecording(100, 100);
for (int i = 0; i < 1000; ++i) {
rand_op(canvas, rand);
}
picture.endRecording();
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
rand = rand2;
}
{
SkPicture picture;
SkCanvas* canvas = picture.beginRecording(100, 100);
SkCanvas* canvas = recorder.beginRecording(100, 100);
SkRect rect = SkRect::MakeWH(50, 50);
for (int i = 0; i < 100; ++i) {
@ -781,7 +792,7 @@ static void test_peephole() {
canvas->clipRect(rect);
canvas->restore();
}
picture.endRecording();
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
}
}
@ -793,13 +804,13 @@ static void test_bad_bitmap() {
// fail.
SkBitmap bm;
bm.setConfig(SkImageInfo::MakeN32Premul(100, 100));
SkPicture picture;
SkCanvas* recordingCanvas = picture.beginRecording(100, 100);
SkPictureRecorder recorder;
SkCanvas* recordingCanvas = recorder.beginRecording(100, 100);
recordingCanvas->drawBitmap(bm, 0, 0);
picture.endRecording();
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
SkCanvas canvas;
canvas.drawPicture(picture);
canvas.drawPicture(*picture);
}
#endif
@ -808,11 +819,13 @@ static SkData* encode_bitmap_to_data(size_t*, const SkBitmap& bm) {
}
static SkData* serialized_picture_from_bitmap(const SkBitmap& bitmap) {
SkPicture picture;
SkCanvas* canvas = picture.beginRecording(bitmap.width(), bitmap.height());
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(bitmap.width(), bitmap.height());
canvas->drawBitmap(bitmap, 0, 0);
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
SkDynamicMemoryWStream wStream;
picture.serialize(&wStream, &encode_bitmap_to_data);
picture->serialize(&wStream, &encode_bitmap_to_data);
return wStream.copyToData();
}
@ -872,20 +885,11 @@ static void test_clone_empty(skiatest::Reporter* reporter) {
// Before the fix, we used to crash accessing a null pointer when we
// had a picture with no paints. This test passes by not crashing.
{
SkPicture picture;
picture.beginRecording(1, 1);
picture.endRecording();
SkPicture* destPicture = picture.clone();
SkPictureRecorder recorder;
recorder.beginRecording(1, 1);
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
SkAutoTUnref<SkPicture> destPicture(picture->clone());
REPORTER_ASSERT(reporter, NULL != destPicture);
destPicture->unref();
}
{
// Test without call to endRecording
SkPicture picture;
picture.beginRecording(1, 1);
SkPicture* destPicture = picture.clone();
REPORTER_ASSERT(reporter, NULL != destPicture);
destPicture->unref();
}
}
@ -897,11 +901,11 @@ static void test_draw_empty(skiatest::Reporter* reporter) {
{
// stock SkPicture
SkPicture picture;
picture.beginRecording(1, 1);
picture.endRecording();
SkPictureRecorder recorder;
recorder.beginRecording(1, 1);
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
canvas.drawPicture(picture);
canvas.drawPicture(*picture);
}
{
@ -911,29 +915,31 @@ static void test_draw_empty(skiatest::Reporter* reporter) {
gridInfo.fOffset.setZero();
gridInfo.fTileInterval.set(1, 1);
SkTileGridPicture picture(1, 1, gridInfo);
picture.beginRecording(1, 1, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
picture.endRecording();
SkAutoTUnref<SkPictureFactory> factory(SkNEW_ARGS(SkTileGridPictureFactory, (gridInfo)));
SkPictureRecorder recorder(factory);
recorder.beginRecording(1, 1, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
canvas.drawPicture(picture);
canvas.drawPicture(*picture);
}
{
// RTree
SkPicture picture;
picture.beginRecording(1, 1, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
picture.endRecording();
SkPictureRecorder recorder;
recorder.beginRecording(1, 1, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
canvas.drawPicture(picture);
canvas.drawPicture(*picture);
}
{
// quad tree
SkQuadTreePicture picture(SkIRect::MakeWH(1, 1));
picture.beginRecording(1, 1, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
picture.endRecording();
SkAutoTUnref<SkPictureFactory> factory(SkNEW(SkQuadTreePictureFactory));
SkPictureRecorder recorder(factory);
recorder.beginRecording(1, 1, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
canvas.drawPicture(picture);
canvas.drawPicture(*picture);
}
}
@ -954,11 +960,11 @@ static void test_clip_bound_opt(skiatest::Reporter* reporter) {
SkPath path2;
path2.addOval(rect3);
SkIRect clipBounds;
SkPictureRecorder recorder;
// Minimalist test set for 100% code coverage of
// SkPictureRecord::updateClipConservativelyUsingBounds
{
SkPicture picture;
SkCanvas* canvas = picture.beginRecording(10, 10,
SkCanvas* canvas = recorder.beginRecording(10, 10,
SkPicture::kUsePathBoundsForClip_RecordingFlag);
canvas->clipPath(invPath, SkRegion::kIntersect_Op);
bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds);
@ -969,8 +975,7 @@ static void test_clip_bound_opt(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, 10 == clipBounds.fRight);
}
{
SkPicture picture;
SkCanvas* canvas = picture.beginRecording(10, 10,
SkCanvas* canvas = recorder.beginRecording(10, 10,
SkPicture::kUsePathBoundsForClip_RecordingFlag);
canvas->clipPath(path, SkRegion::kIntersect_Op);
canvas->clipPath(invPath, SkRegion::kIntersect_Op);
@ -982,8 +987,7 @@ static void test_clip_bound_opt(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, 8 == clipBounds.fRight);
}
{
SkPicture picture;
SkCanvas* canvas = picture.beginRecording(10, 10,
SkCanvas* canvas = recorder.beginRecording(10, 10,
SkPicture::kUsePathBoundsForClip_RecordingFlag);
canvas->clipPath(path, SkRegion::kIntersect_Op);
canvas->clipPath(invPath, SkRegion::kUnion_Op);
@ -995,8 +999,7 @@ static void test_clip_bound_opt(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, 10 == clipBounds.fRight);
}
{
SkPicture picture;
SkCanvas* canvas = picture.beginRecording(10, 10,
SkCanvas* canvas = recorder.beginRecording(10, 10,
SkPicture::kUsePathBoundsForClip_RecordingFlag);
canvas->clipPath(path, SkRegion::kDifference_Op);
bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds);
@ -1007,8 +1010,7 @@ static void test_clip_bound_opt(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, 10 == clipBounds.fRight);
}
{
SkPicture picture;
SkCanvas* canvas = picture.beginRecording(10, 10,
SkCanvas* canvas = recorder.beginRecording(10, 10,
SkPicture::kUsePathBoundsForClip_RecordingFlag);
canvas->clipPath(path, SkRegion::kReverseDifference_Op);
bool nonEmpty = canvas->getClipDeviceBounds(&clipBounds);
@ -1022,8 +1024,7 @@ static void test_clip_bound_opt(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, 8 == clipBounds.fRight);
}
{
SkPicture picture;
SkCanvas* canvas = picture.beginRecording(10, 10,
SkCanvas* canvas = recorder.beginRecording(10, 10,
SkPicture::kUsePathBoundsForClip_RecordingFlag);
canvas->clipPath(path, SkRegion::kIntersect_Op);
canvas->clipPath(path2, SkRegion::kXOR_Op);
@ -1081,8 +1082,8 @@ private:
};
static void test_clip_expansion(skiatest::Reporter* reporter) {
SkPicture picture;
SkCanvas* canvas = picture.beginRecording(10, 10, 0);
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(10, 10, 0);
canvas->clipRect(SkRect::MakeEmpty(), SkRegion::kReplace_Op);
// The following expanding clip should not be skipped.
@ -1091,9 +1092,10 @@ static void test_clip_expansion(skiatest::Reporter* reporter) {
SkPaint p;
p.setColor(SK_ColorBLUE);
canvas->drawPaint(p);
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
ClipCountingCanvas testCanvas(10, 10);
picture.draw(&testCanvas);
picture->draw(&testCanvas);
// Both clips should be present on playback.
REPORTER_ASSERT(reporter, testCanvas.getClipCount() == 2);
@ -1103,95 +1105,87 @@ static void test_hierarchical(skiatest::Reporter* reporter) {
SkBitmap bm;
make_bm(&bm, 10, 10, SK_ColorRED, true);
SkCanvas* canvas;
SkPictureRecorder recorder;
SkPicture childPlain;
childPlain.beginRecording(10, 10);
childPlain.endRecording();
REPORTER_ASSERT(reporter, !childPlain.willPlayBackBitmaps()); // 0
recorder.beginRecording(10, 10);
SkAutoTUnref<SkPicture> childPlain(recorder.endRecording());
REPORTER_ASSERT(reporter, !childPlain->willPlayBackBitmaps()); // 0
SkPicture childWithBitmap;
childWithBitmap.beginRecording(10, 10)->drawBitmap(bm, 0, 0);
childWithBitmap.endRecording();
REPORTER_ASSERT(reporter, childWithBitmap.willPlayBackBitmaps()); // 1
recorder.beginRecording(10, 10)->drawBitmap(bm, 0, 0);
SkAutoTUnref<SkPicture> childWithBitmap(recorder.endRecording());
REPORTER_ASSERT(reporter, childWithBitmap->willPlayBackBitmaps()); // 1
SkPicture parentPP;
canvas = parentPP.beginRecording(10, 10);
canvas->drawPicture(childPlain);
parentPP.endRecording();
REPORTER_ASSERT(reporter, !parentPP.willPlayBackBitmaps()); // 0
SkPicture parentPWB;
canvas = parentPWB.beginRecording(10, 10);
canvas->drawPicture(childWithBitmap);
parentPWB.endRecording();
REPORTER_ASSERT(reporter, parentPWB.willPlayBackBitmaps()); // 1
SkPicture parentWBP;
canvas = parentWBP.beginRecording(10, 10);
canvas->drawBitmap(bm, 0, 0);
canvas->drawPicture(childPlain);
parentWBP.endRecording();
REPORTER_ASSERT(reporter, parentWBP.willPlayBackBitmaps()); // 1
SkPicture parentWBWB;
canvas = parentWBWB.beginRecording(10, 10);
canvas->drawBitmap(bm, 0, 0);
canvas->drawPicture(childWithBitmap);
parentWBWB.endRecording();
REPORTER_ASSERT(reporter, parentWBWB.willPlayBackBitmaps()); // 2
{
SkCanvas* canvas = recorder.beginRecording(10, 10);
canvas->drawPicture(*childPlain);
SkAutoTUnref<SkPicture> parentPP(recorder.endRecording());
REPORTER_ASSERT(reporter, !parentPP->willPlayBackBitmaps()); // 0
}
{
SkCanvas* canvas = recorder.beginRecording(10, 10);
canvas->drawPicture(*childWithBitmap);
SkAutoTUnref<SkPicture> parentPWB(recorder.endRecording());
REPORTER_ASSERT(reporter, parentPWB->willPlayBackBitmaps()); // 1
}
{
SkCanvas* canvas = recorder.beginRecording(10, 10);
canvas->drawBitmap(bm, 0, 0);
canvas->drawPicture(*childPlain);
SkAutoTUnref<SkPicture> parentWBP(recorder.endRecording());
REPORTER_ASSERT(reporter, parentWBP->willPlayBackBitmaps()); // 1
}
{
SkCanvas* canvas = recorder.beginRecording(10, 10);
canvas->drawBitmap(bm, 0, 0);
canvas->drawPicture(*childWithBitmap);
SkAutoTUnref<SkPicture> parentWBWB(recorder.endRecording());
REPORTER_ASSERT(reporter, parentWBWB->willPlayBackBitmaps()); // 2
}
}
static void test_gen_id(skiatest::Reporter* reporter) {
SkPicture hasData, empty, midRecord;
SkPicture empty;
uint32_t beforeID = hasData.uniqueID();
REPORTER_ASSERT(reporter, SK_InvalidGenID != beforeID);
// Empty pictures should still have a valid ID
REPORTER_ASSERT(reporter, empty.uniqueID() != SK_InvalidGenID);
// all 3 pictures should have different ids
REPORTER_ASSERT(reporter, beforeID != empty.uniqueID());
REPORTER_ASSERT(reporter, beforeID != midRecord.uniqueID());
REPORTER_ASSERT(reporter, empty.uniqueID() != midRecord.uniqueID());
SkPictureRecorder recorder;
hasData.beginRecording(1, 1);
// gen ID should be invalid mid-record
REPORTER_ASSERT(reporter, SK_InvalidGenID == hasData.uniqueID());
hasData.endRecording();
// picture should get a new (non-zero) id after recording
REPORTER_ASSERT(reporter, hasData.uniqueID() != beforeID);
REPORTER_ASSERT(reporter, hasData.uniqueID() != SK_InvalidGenID);
SkCanvas* canvas = recorder.beginRecording(1, 1);
canvas->drawARGB(255, 255, 255, 255);
SkAutoTUnref<SkPicture> hasData(recorder.endRecording());
// picture should have a non-zero id after recording
REPORTER_ASSERT(reporter, hasData->uniqueID() != SK_InvalidGenID);
midRecord.beginRecording(1, 1);
REPORTER_ASSERT(reporter, SK_InvalidGenID == midRecord.uniqueID());
// both pictures should have different ids
REPORTER_ASSERT(reporter, hasData->uniqueID() != empty.uniqueID());
// test out copy constructor
SkPicture copyWithData(hasData);
REPORTER_ASSERT(reporter, hasData.uniqueID() == copyWithData.uniqueID());
SkPicture copyWithData(*hasData);
REPORTER_ASSERT(reporter, hasData->uniqueID() == copyWithData.uniqueID());
SkPicture emptyCopy(empty);
REPORTER_ASSERT(reporter, empty.uniqueID() != emptyCopy.uniqueID());
SkPicture copyMidRecord(midRecord);
REPORTER_ASSERT(reporter, midRecord.uniqueID() != copyMidRecord.uniqueID());
REPORTER_ASSERT(reporter, copyMidRecord.uniqueID() != SK_InvalidGenID);
// test out swap
beforeID = copyMidRecord.uniqueID();
copyWithData.swap(copyMidRecord);
REPORTER_ASSERT(reporter, copyWithData.uniqueID() == beforeID);
REPORTER_ASSERT(reporter, copyMidRecord.uniqueID() == hasData.uniqueID());
{
SkPicture swapWithData;
uint32_t beforeID1 = swapWithData.uniqueID();
uint32_t beforeID2 = copyWithData.uniqueID();
swapWithData.swap(copyWithData);
REPORTER_ASSERT(reporter, copyWithData.uniqueID() == beforeID1);
REPORTER_ASSERT(reporter, swapWithData.uniqueID() == beforeID2);
}
// test out clone
SkAutoTUnref<SkPicture> cloneWithData(hasData.clone());
REPORTER_ASSERT(reporter, hasData.uniqueID() == cloneWithData->uniqueID());
{
SkAutoTUnref<SkPicture> cloneWithData(hasData->clone());
REPORTER_ASSERT(reporter, hasData->uniqueID() == cloneWithData->uniqueID());
SkAutoTUnref<SkPicture> emptyClone(empty.clone());
REPORTER_ASSERT(reporter, empty.uniqueID() != emptyClone->uniqueID());
SkAutoTUnref<SkPicture> cloneMidRecord(midRecord.clone());
REPORTER_ASSERT(reporter, midRecord.uniqueID() != cloneMidRecord->uniqueID());
REPORTER_ASSERT(reporter, cloneMidRecord->uniqueID() != SK_InvalidGenID);
SkAutoTUnref<SkPicture> emptyClone(empty.clone());
REPORTER_ASSERT(reporter, empty.uniqueID() != emptyClone->uniqueID());
}
}
DEF_TEST(Picture, reporter) {
@ -1235,9 +1229,9 @@ static void test_draw_bitmaps(SkCanvas* canvas) {
}
DEF_TEST(Picture_EmptyBitmap, r) {
SkPicture picture;
test_draw_bitmaps(picture.beginRecording(10, 10));
picture.endRecording();
SkPictureRecorder recorder;
test_draw_bitmaps(recorder.beginRecording(10, 10));
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
}
DEF_TEST(Canvas_EmptyBitmap, r) {

View File

@ -369,11 +369,10 @@ DEF_TEST(Serialization, reporter) {
// Test simple SkPicture serialization
{
SkPicture* pict = new SkPicture;
SkAutoUnref aur(pict);
bool didDraw = drawSomething(pict->beginRecording(kBitmapSize, kBitmapSize));
SkPictureRecorder recorder;
bool didDraw = drawSomething(recorder.beginRecording(kBitmapSize, kBitmapSize));
REPORTER_ASSERT(reporter, didDraw);
pict->endRecording();
SkAutoTUnref<SkPicture> pict(recorder.endRecording());
// Serialize picture
SkWriteBuffer writer(SkWriteBuffer::kValidation_Flag);

View File

@ -56,16 +56,17 @@ DEF_TEST(TileGrid_UnalignedQuery, reporter) {
info.fMargin.setEmpty();
info.fOffset.setZero();
info.fTileInterval.set(10, 10);
SkTileGridPicture picture(20, 20, info);
SkRect rect1 = SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
SkIntToScalar(8), SkIntToScalar(8));
SkRect rect2 = SkRect::MakeXYWH(SkIntToScalar(11), SkIntToScalar(11),
SkIntToScalar(1), SkIntToScalar(1));
SkCanvas* canvas = picture.beginRecording(20, 20, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
SkAutoTUnref<SkPictureFactory> factory(SkNEW_ARGS(SkTileGridPictureFactory, (info)));
SkPictureRecorder recorder(factory);
SkCanvas* canvas = recorder.beginRecording(20, 20, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
SkPaint paint;
canvas->drawRect(rect1, paint);
canvas->drawRect(rect2, paint);
picture.endRecording();
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
SkBitmap store;
store.allocN32Pixels(1, 1);
@ -73,14 +74,14 @@ DEF_TEST(TileGrid_UnalignedQuery, reporter) {
// Test parts of top-left tile
{
MockCanvas mockCanvas(store);
picture.draw(&mockCanvas);
picture->draw(&mockCanvas);
REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]);
}
{
MockCanvas mockCanvas(store);
mockCanvas.translate(-7.99f, -7.99f);
picture.draw(&mockCanvas);
picture->draw(&mockCanvas);
REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]);
}
@ -88,7 +89,7 @@ DEF_TEST(TileGrid_UnalignedQuery, reporter) {
{
MockCanvas mockCanvas(store);
mockCanvas.translate(-9.5f, -9.5f);
picture.draw(&mockCanvas);
picture->draw(&mockCanvas);
REPORTER_ASSERT(reporter, 2 == mockCanvas.fRects.count());
REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]);
REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[1]);
@ -97,7 +98,7 @@ DEF_TEST(TileGrid_UnalignedQuery, reporter) {
{
MockCanvas mockCanvas(store);
mockCanvas.translate(-16.0f, -16.0f);
picture.draw(&mockCanvas);
picture->draw(&mockCanvas);
REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[0]);
}
@ -105,28 +106,28 @@ DEF_TEST(TileGrid_UnalignedQuery, reporter) {
{
MockCanvas mockCanvas(store);
mockCanvas.translate(2.0f, 0.0f);
picture.draw(&mockCanvas);
picture->draw(&mockCanvas);
REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]);
}
{
MockCanvas mockCanvas(store);
mockCanvas.translate(0.0f, 2.0f);
picture.draw(&mockCanvas);
picture->draw(&mockCanvas);
REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]);
}
{
MockCanvas mockCanvas(store);
mockCanvas.translate(-22.0f, -16.0f);
picture.draw(&mockCanvas);
picture->draw(&mockCanvas);
REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[0]);
}
{
MockCanvas mockCanvas(store);
mockCanvas.translate(-16.0f, -22.0f);
picture.draw(&mockCanvas);
picture->draw(&mockCanvas);
REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[0]);
}
@ -138,7 +139,6 @@ DEF_TEST(TileGrid_OverlapOffsetQueryAlignment, reporter) {
info.fMargin.set(1, 1);
info.fOffset.set(-1, -1);
info.fTileInterval.set(8, 8);
SkTileGridPicture picture(20, 20, info);
// rect landing entirely in top left tile
SkRect rect1 = SkRect::MakeXYWH(SkIntToScalar(0), SkIntToScalar(0),
@ -149,12 +149,14 @@ DEF_TEST(TileGrid_OverlapOffsetQueryAlignment, reporter) {
// rect landing entirely in bottomright tile
SkRect rect3 = SkRect::MakeXYWH(SkIntToScalar(19), SkIntToScalar(19),
SkIntToScalar(1), SkIntToScalar(1));
SkCanvas* canvas = picture.beginRecording(20, 20, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
SkAutoTUnref<SkPictureFactory> factory(SkNEW_ARGS(SkTileGridPictureFactory, (info)));
SkPictureRecorder recorder(factory);
SkCanvas* canvas = recorder.beginRecording(20, 20, SkPicture::kOptimizeForClippedPlayback_RecordingFlag);
SkPaint paint;
canvas->drawRect(rect1, paint);
canvas->drawRect(rect2, paint);
canvas->drawRect(rect3, paint);
picture.endRecording();
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
SkBitmap tileBitmap;
tileBitmap.allocN32Pixels(10, 10);
@ -167,14 +169,14 @@ DEF_TEST(TileGrid_OverlapOffsetQueryAlignment, reporter) {
// The offset should cancel the top and left borders of the top left tile
// So a look-up at interval 0-10 should be grid aligned,
MockCanvas mockCanvas(tileBitmap);
picture.draw(&mockCanvas);
picture->draw(&mockCanvas);
REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]);
}
{
// Encroaching border by one pixel
MockCanvas mockCanvas(moreThanATileBitmap);
picture.draw(&mockCanvas);
picture->draw(&mockCanvas);
REPORTER_ASSERT(reporter, 2 == mockCanvas.fRects.count());
REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]);
REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[1]);
@ -185,14 +187,14 @@ DEF_TEST(TileGrid_OverlapOffsetQueryAlignment, reporter) {
// with middle tile.
MockCanvas mockCanvas(tileBitmap);
mockCanvas.translate(SkIntToScalar(-8), SkIntToScalar(-8));
picture.draw(&mockCanvas);
picture->draw(&mockCanvas);
REPORTER_ASSERT(reporter, 1 == mockCanvas.fRects.count());
REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[0]);
}
{
MockCanvas mockCanvas(tileBitmap);
mockCanvas.translate(-7.9f, -7.9f);
picture.draw(&mockCanvas);
picture->draw(&mockCanvas);
REPORTER_ASSERT(reporter, 2 == mockCanvas.fRects.count());
REPORTER_ASSERT(reporter, rect1 == mockCanvas.fRects[0]);
REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[1]);
@ -200,7 +202,7 @@ DEF_TEST(TileGrid_OverlapOffsetQueryAlignment, reporter) {
{
MockCanvas mockCanvas(tileBitmap);
mockCanvas.translate(-8.1f, -8.1f);
picture.draw(&mockCanvas);
picture->draw(&mockCanvas);
REPORTER_ASSERT(reporter, 2 == mockCanvas.fRects.count());
REPORTER_ASSERT(reporter, rect2 == mockCanvas.fRects[0]);
REPORTER_ASSERT(reporter, rect3 == mockCanvas.fRects[1]);
@ -211,7 +213,7 @@ DEF_TEST(TileGrid_OverlapOffsetQueryAlignment, reporter) {
// adjusted region, sitting right on top of the tile boundary.
MockCanvas mockCanvas(tinyBitmap);
mockCanvas.translate(-8.0f, -8.0f);
picture.draw(&mockCanvas);
picture->draw(&mockCanvas);
// This test passes by not asserting. We do not validate the rects recorded
// because the result is numerically unstable (floating point equality).
// The content of any one of the four tiles of the tilegrid would be a valid

View File

@ -27,11 +27,10 @@ namespace sk_tools {
SkASSERT(pict != NULL);
// Only work with absolute widths (as opposed to percentages).
SkASSERT(this->getTileWidth() != 0 && this->getTileHeight() != 0);
fPicture = pict;
fPicture.reset(pict)->ref();
this->CopyString(&fOutputDir, outputDir);
this->CopyString(&fInputFilename, inputFilename);
fUseChecksumBasedFilenames = useChecksumBasedFilenames;
fPicture->ref();
this->buildBBoxHierarchy();
// In order to avoid allocating a large canvas (particularly important for GPU), create one
// canvas that is a multiple of the tile size, and draw portions of the picture.

View File

@ -120,7 +120,7 @@ void PictureRenderer::init(SkPicture* pict, const SkString* outputDir,
SkASSERT(NULL == fPicture);
SkASSERT(NULL == fCanvas.get());
if (fPicture != NULL || NULL != fCanvas.get()) {
if (NULL != fPicture || NULL != fCanvas.get()) {
return;
}
@ -129,8 +129,7 @@ void PictureRenderer::init(SkPicture* pict, const SkString* outputDir,
return;
}
fPicture = pict;
fPicture->ref();
fPicture.reset(pict)->ref();
fCanvas.reset(this->setupCanvas());
}
@ -246,8 +245,7 @@ void PictureRenderer::scaleToScaleFactor(SkCanvas* canvas) {
void PictureRenderer::end() {
this->resetState(true);
SkSafeUnref(fPicture);
fPicture = NULL;
fPicture.reset(NULL);
fCanvas.reset(NULL);
}
@ -276,13 +274,12 @@ int PictureRenderer::getViewHeight() {
void PictureRenderer::buildBBoxHierarchy() {
SkASSERT(NULL != fPicture);
if (kNone_BBoxHierarchyType != fBBoxHierarchyType && NULL != fPicture) {
SkPicture* newPicture = this->createPicture();
SkCanvas* recorder = newPicture->beginRecording(fPicture->width(), fPicture->height(),
this->recordFlags());
fPicture->draw(recorder);
newPicture->endRecording();
fPicture->unref();
fPicture = newPicture;
SkAutoTUnref<SkPictureFactory> factory(this->getFactory());
SkPictureRecorder recorder(factory);
SkCanvas* canvas = recorder.beginRecording(fPicture->width(), fPicture->height(),
this->recordFlags());
fPicture->draw(canvas);
fPicture.reset(recorder.endRecording());
}
}
@ -438,17 +435,18 @@ static SkData* encode_bitmap_to_data(size_t*, const SkBitmap& bm) {
}
bool RecordPictureRenderer::render(SkBitmap** out) {
SkAutoTUnref<SkPicture> replayer(this->createPicture());
SkCanvas* recorder = replayer->beginRecording(this->getViewWidth(), this->getViewHeight(),
this->recordFlags());
this->scaleToScaleFactor(recorder);
fPicture->draw(recorder);
replayer->endRecording();
SkAutoTUnref<SkPictureFactory> factory(this->getFactory());
SkPictureRecorder recorder(factory);
SkCanvas* canvas = recorder.beginRecording(this->getViewWidth(), this->getViewHeight(),
this->recordFlags());
this->scaleToScaleFactor(canvas);
fPicture->draw(canvas);
SkAutoTUnref<SkPicture> picture(recorder.endRecording());
if (!fOutputDir.isEmpty()) {
// Record the new picture as a new SKP with PNG encoded bitmaps.
SkString skpPath = SkOSPath::SkPathJoin(fOutputDir.c_str(), fInputFilename.c_str());
SkFILEWStream stream(skpPath.c_str());
replayer->serialize(&stream, &encode_bitmap_to_data);
picture->serialize(&stream, &encode_bitmap_to_data);
return true;
}
return false;
@ -499,7 +497,7 @@ void SimplePictureRenderer::init(SkPicture* picture, const SkString* outputDir,
bool SimplePictureRenderer::render(SkBitmap** out) {
SkASSERT(fCanvas.get() != NULL);
SkASSERT(fPicture != NULL);
SkASSERT(NULL != fPicture);
if (NULL == fCanvas.get() || NULL == fPicture) {
return false;
}
@ -538,7 +536,7 @@ TiledPictureRenderer::TiledPictureRenderer()
void TiledPictureRenderer::init(SkPicture* pict, const SkString* outputDir,
const SkString* inputFilename, bool useChecksumBasedFilenames) {
SkASSERT(pict != NULL);
SkASSERT(NULL != pict);
SkASSERT(0 == fTileRects.count());
if (NULL == pict || fTileRects.count() != 0) {
return;
@ -546,7 +544,7 @@ void TiledPictureRenderer::init(SkPicture* pict, const SkString* outputDir,
// Do not call INHERITED::init(), which would create a (potentially large) canvas which is not
// used by bench_pictures.
fPicture = SkRef(pict);
fPicture.reset(pict)->ref();
this->CopyString(&fOutputDir, outputDir);
this->CopyString(&fInputFilename, inputFilename);
fUseChecksumBasedFilenames = useChecksumBasedFilenames;
@ -956,15 +954,16 @@ SkString MultiCorePictureRenderer::getConfigNameInternal() {
///////////////////////////////////////////////////////////////////////////////////////////////
void PlaybackCreationRenderer::setup() {
fReplayer.reset(this->createPicture());
SkCanvas* recorder = fReplayer->beginRecording(this->getViewWidth(), this->getViewHeight(),
this->recordFlags());
this->scaleToScaleFactor(recorder);
recorder->drawPicture(*fPicture);
SkAutoTUnref<SkPictureFactory> factory(this->getFactory());
fRecorder.reset(SkNEW_ARGS(SkPictureRecorder, (factory)));
SkCanvas* canvas = fRecorder->beginRecording(this->getViewWidth(), this->getViewHeight(),
this->recordFlags());
this->scaleToScaleFactor(canvas);
canvas->drawPicture(*fPicture);
}
bool PlaybackCreationRenderer::render(SkBitmap** out) {
fReplayer->endRecording();
fPicture.reset(fRecorder->endRecording());
// Since this class does not actually render, return false.
return false;
}
@ -978,7 +977,7 @@ SkString PlaybackCreationRenderer::getConfigNameInternal() {
class RTreePicture : public SkPicture {
public:
virtual SkBBoxHierarchy* createBBoxHierarchy() const SK_OVERRIDE{
virtual SkBBoxHierarchy* createBBoxHierarchy() const SK_OVERRIDE {
static const int kRTreeMinChildren = 6;
static const int kRTreeMaxChildren = 11;
SkScalar aspectRatio = SkScalarDiv(SkIntToScalar(fWidth),
@ -989,18 +988,26 @@ public:
}
};
SkPicture* PictureRenderer::createPicture() {
class SkRTreePictureFactory : public SkPictureFactory {
private:
virtual SkPicture* create(int width, int height) SK_OVERRIDE {
return SkNEW(RTreePicture);
}
private:
typedef SkPictureFactory INHERITED;
};
SkPictureFactory* PictureRenderer::getFactory() {
switch (fBBoxHierarchyType) {
case kNone_BBoxHierarchyType:
return SkNEW(SkPicture);
return NULL;
case kQuadTree_BBoxHierarchyType:
return SkNEW_ARGS(SkQuadTreePicture, (SkIRect::MakeWH(fPicture->width(),
fPicture->height())));
return SkNEW(SkQuadTreePictureFactory);
case kRTree_BBoxHierarchyType:
return SkNEW(RTreePicture);
return SkNEW(SkRTreePictureFactory);
case kTileGrid_BBoxHierarchyType:
return SkNEW_ARGS(SkTileGridPicture, (fPicture->width(),
fPicture->height(), fGridInfo));
return new SkTileGridPictureFactory(fGridInfo);
}
SkASSERT(0); // invalid bbhType
return NULL;

View File

@ -376,8 +376,7 @@ public:
}
PictureRenderer()
: fPicture(NULL)
, fJsonSummaryPtr(NULL)
: fJsonSummaryPtr(NULL)
, fDeviceType(kBitmap_DeviceType)
, fBBoxHierarchyType(kNone_BBoxHierarchyType)
, fScaleFactor(SK_Scalar1)
@ -401,7 +400,7 @@ public:
protected:
SkAutoTUnref<SkCanvas> fCanvas;
SkPicture* fPicture;
SkAutoTUnref<SkPicture> fPicture;
bool fUseChecksumBasedFilenames;
ImageResultsSummary* fJsonSummaryPtr;
SkDeviceTypes fDeviceType;
@ -431,7 +430,7 @@ protected:
*/
void scaleToScaleFactor(SkCanvas*);
SkPicture* createPicture();
SkPictureFactory* getFactory();
uint32_t recordFlags();
SkCanvas* setupCanvas();
virtual SkCanvas* setupCanvas(int width, int height);
@ -665,7 +664,7 @@ public:
virtual SkString getNormalTimeFormat() SK_OVERRIDE { return SkString("%6.4f"); }
private:
SkAutoTUnref<SkPicture> fReplayer;
SkAutoTDelete<SkPictureRecorder> fRecorder;
virtual SkString getConfigNameInternal() SK_OVERRIDE;

View File

@ -33,40 +33,48 @@ DEFINE_int32(tileGridSize, 512, "Set the tile grid size. Has no effect if bbh is
DEFINE_string(bbh, "", "Turn on the bbh and select the type, one of rtree, tilegrid, quadtree");
DEFINE_bool(skr, false, "Record SKR instead of SKP.");
typedef SkPicture* (*PictureFactory)(const int width, const int height, int* recordingFlags);
typedef SkPictureFactory* (*PictureFactory)(int* recordingFlags);
static SkPicture* vanilla_factory(const int width, const int height, int* recordingFlags) {
return SkNEW(SkPicture);
static SkPictureFactory* vanilla_factory(int* recordingFlags) {
return NULL;
}
static SkPicture* rtree_factory(const int width, const int height, int* recordingFlags) {
static SkPictureFactory* rtree_factory(int* recordingFlags) {
*recordingFlags |= SkPicture::kOptimizeForClippedPlayback_RecordingFlag;
return SkNEW(SkPicture);
return NULL;
}
static SkPicture* tilegrid_factory(const int width, const int height, int* recordingFlags) {
static SkPictureFactory* tilegrid_factory(int* recordingFlags) {
*recordingFlags |= SkPicture::kOptimizeForClippedPlayback_RecordingFlag;
SkTileGridPicture::TileGridInfo info;
info.fTileInterval.set(FLAGS_tileGridSize, FLAGS_tileGridSize);
info.fMargin.setEmpty();
info.fOffset.setZero();
return SkNEW_ARGS(SkTileGridPicture, (width, height, info));
return SkNEW_ARGS(SkTileGridPictureFactory, (info));
}
static SkPicture* quadtree_factory(const int width, const int height, int* recordingFlags) {
static SkPictureFactory* quadtree_factory(int* recordingFlags) {
*recordingFlags |= SkPicture::kOptimizeForClippedPlayback_RecordingFlag;
return SkNEW_ARGS(SkQuadTreePicture, (SkIRect::MakeWH(width, height)));
return SkNEW(SkQuadTreePictureFactory);
}
static PictureFactory parse_FLAGS_bbh() {
if (FLAGS_bbh.isEmpty()) { return &vanilla_factory; }
if (FLAGS_bbh.isEmpty()) {
return &vanilla_factory;
}
if (FLAGS_bbh.count() != 1) {
SkDebugf("Multiple bbh arguments supplied.\n");
return NULL;
}
if (FLAGS_bbh.contains("rtree")) { return rtree_factory; }
if (FLAGS_bbh.contains("tilegrid")) { return tilegrid_factory; }
if (FLAGS_bbh.contains("quadtree")) { return quadtree_factory; }
if (FLAGS_bbh.contains("rtree")) {
return rtree_factory;
}
if (FLAGS_bbh.contains("tilegrid")) {
return tilegrid_factory;
}
if (FLAGS_bbh.contains("quadtree")) {
return quadtree_factory;
}
SkDebugf("Invalid bbh type %s, must be one of rtree, tilegrid, quadtree.\n", FLAGS_bbh[0]);
return NULL;
}
@ -85,13 +93,14 @@ static void bench_record(SkPicture* src, const char* name, PictureFactory pictur
}
} else {
int recordingFlags = FLAGS_flags;
SkAutoTUnref<SkPicture> dst(pictureFactory(width, height, &recordingFlags));
SkCanvas* canvas = dst->beginRecording(width, height, recordingFlags);
SkAutoTUnref<SkPictureFactory> factory(pictureFactory(&recordingFlags));
SkPictureRecorder recorder(factory);
SkCanvas* canvas = recorder.beginRecording(width, height, recordingFlags);
if (NULL != src) {
src->draw(canvas);
}
if (FLAGS_endRecording) {
dst->endRecording();
SkAutoTUnref<SkPicture> dst(recorder.endRecording());
}
}
}

View File

@ -717,15 +717,14 @@ static int filter_picture(const SkString& inFile, const SkString& outFile) {
int numAfter = debugCanvas.getSize();
if (!outFile.isEmpty()) {
SkPicture outPicture;
SkCanvas* canvas = outPicture.beginRecording(inPicture->width(), inPicture->height());
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(inPicture->width(), inPicture->height());
debugCanvas.draw(canvas);
outPicture.endRecording();
SkAutoTUnref<SkPicture> outPicture(recorder.endRecording());
SkFILEWStream outStream(outFile.c_str());
outPicture.serialize(&outStream);
outPicture->serialize(&outStream);
}
bool someOptFired = false;

View File

@ -174,9 +174,9 @@ static bool render_picture_internal(const SkString& inputPath, const SkString* o
while (FLAGS_bench_record) {
const int kRecordFlags = 0;
SkPicture other;
picture->draw(other.beginRecording(picture->width(), picture->height(), kRecordFlags));
other.endRecording();
SkPictureRecorder recorder;
picture->draw(recorder.beginRecording(picture->width(), picture->height(), kRecordFlags));
SkAutoTUnref<SkPicture> other(recorder.endRecording());
}
for (int i = 0; i < FLAGS_clone; ++i) {

View File

@ -26,8 +26,8 @@ DEFINE_string(writePath, "", "Filepath to write the SKP into.");
static void skpmaker(int width, int height, int border, SkColor color,
const char *writePath) {
SkPicture pict;
SkCanvas* canvas = pict.beginRecording(width, height);
SkPictureRecorder recorder;
SkCanvas* canvas = recorder.beginRecording(width, height);
SkPaint paint;
paint.setStyle(SkPaint::kFill_Style);
paint.setColor(SK_ColorBLACK);
@ -36,9 +36,9 @@ static void skpmaker(int width, int height, int border, SkColor color,
canvas->drawRectCoords(SkIntToScalar(border), SkIntToScalar(border),
SkIntToScalar(width - border*2), SkIntToScalar(height - border*2),
paint);
pict.endRecording();
SkAutoTUnref<SkPicture> pict(recorder.endRecording());
SkFILEWStream stream(writePath);
pict.serialize(&stream);
pict->serialize(&stream);
}
int tool_main(int argc, char** argv);