diff options
39 files changed, 575 insertions, 451 deletions
diff --git a/bench/PicturePlaybackBench.cpp b/bench/PicturePlaybackBench.cpp index 815ef0b777..fa693c2468 100644 --- a/bench/PicturePlaybackBench.cpp +++ b/bench/PicturePlaybackBench.cpp @@ -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); diff --git a/bench/PictureRecordBench.cpp b/bench/PictureRecordBench.cpp index 4083f81af7..4c82fe2881 100644 --- a/bench/PictureRecordBench.cpp +++ b/bench/PictureRecordBench.cpp @@ -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]); } diff --git a/bench/benchmain.cpp b/bench/benchmain.cpp index cc55bb9f29..eb3947abad 100644 --- a/bench/benchmain.cpp +++ b/bench/benchmain.cpp @@ -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); } diff --git a/debugger/SkDebugger.cpp b/debugger/SkDebugger.cpp index 82b26a1270..5bdc8a9fb4 100644 --- a/debugger/SkDebugger.cpp +++ b/debugger/SkDebugger.cpp @@ -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, diff --git a/dm/DMReplayTask.cpp b/dm/DMReplayTask.cpp index c915be20d2..2c23caec4b 100644 --- a/dm/DMReplayTask.cpp +++ b/dm/DMReplayTask.cpp @@ -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))); diff --git a/dm/DMSerializeTask.cpp b/dm/DMSerializeTask.cpp index 4f55de57d5..aa0dabe0ac 100644 --- a/dm/DMSerializeTask.cpp +++ b/dm/DMSerializeTask.cpp @@ -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)); diff --git a/dm/DMTileGridTask.cpp b/dm/DMTileGridTask.cpp index f9cac07de3..bc76b8018a 100644 --- a/dm/DMTileGridTask.cpp +++ b/dm/DMTileGridTask.cpp @@ -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); } diff --git a/dm/DMUtil.cpp b/dm/DMUtil.cpp index 5a849fb5f6..638f0d9b4f 100644 --- a/dm/DMUtil.cpp +++ b/dm/DMUtil.cpp @@ -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) { diff --git a/dm/DMUtil.h b/dm/DMUtil.h index faa4e39737..803e44022c 100644 --- a/dm/DMUtil.h +++ b/dm/DMUtil.h @@ -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. diff --git a/gm/distantclip.cpp b/gm/distantclip.cpp index 6fd14206c4..0f78dbd3ee 100644 --- a/gm/distantclip.cpp +++ b/gm/distantclip.cpp @@ -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 diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp index 03556e70e9..4d5866a3d2 100644 --- a/gm/gmmain.cpp +++ b/gm/gmmain.cpp @@ -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) { diff --git a/gm/optimizations.cpp b/gm/optimizations.cpp index ff88e3d1f0..1e6ddfa1d6 100644 --- a/gm/optimizations.cpp +++ b/gm/optimizations.cpp @@ -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"); diff --git a/gm/pathopsskpclip.cpp b/gm/pathopsskpclip.cpp index b85b294fef..0d936983b9 100644 --- a/gm/pathopsskpclip.cpp +++ b/gm/pathopsskpclip.cpp @@ -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: diff --git a/gm/pictureimagefilter.cpp b/gm/pictureimagefilter.cpp index 2b3cd14ea2..12806618b3 100644 --- a/gm/pictureimagefilter.cpp +++ b/gm/pictureimagefilter.cpp @@ -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; }; diff --git a/gm/pictureshader.cpp b/gm/pictureshader.cpp index 5d37c907ac..51ce0b1bcd 100644 --- a/gm/pictureshader.cpp +++ b/gm/pictureshader.cpp @@ -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; diff --git a/gyp/skia_for_chromium_defines.gypi b/gyp/skia_for_chromium_defines.gypi index 1bbd0c3054..c555214be1 100644 --- a/gyp/skia_for_chromium_defines.gypi +++ b/gyp/skia_for_chromium_defines.gypi @@ -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', ], }, diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h index 70691179db..c298b3de2d 100644 --- a/include/core/SkPicture.h +++ b/include/core/SkPicture.h @@ -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 diff --git a/include/core/SkTileGridPicture.h b/include/core/SkTileGridPicture.h index af7f0e2d78..c1929f46a6 100644 --- a/include/core/SkTileGridPicture.h +++ b/include/core/SkTileGridPicture.h @@ -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 diff --git a/samplecode/SampleAll.cpp b/samplecode/SampleAll.cpp index e0058c4b79..79c6c3658e 100644 --- a/samplecode/SampleAll.cpp +++ b/samplecode/SampleAll.cpp @@ -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); diff --git a/samplecode/SampleApp.cpp b/samplecode/SampleApp.cpp index 050fc4aa8c..5020ec2b4c 100644 --- a/samplecode/SampleApp.cpp +++ b/samplecode/SampleApp.cpp @@ -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 diff --git a/samplecode/SampleApp.h b/samplecode/SampleApp.h index 106931cf4d..13bc697bd5 100644 --- a/samplecode/SampleApp.h +++ b/samplecode/SampleApp.h @@ -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; diff --git a/samplecode/SamplePictFile.cpp b/samplecode/SamplePictFile.cpp index ea15524476..ab45555e91 100644 --- a/samplecode/SamplePictFile.cpp +++ b/samplecode/SamplePictFile.cpp @@ -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; diff --git a/samplecode/SamplePicture.cpp b/samplecode/SamplePicture.cpp index b76f36f9d6..a786750454 100644 --- a/samplecode/SamplePicture.cpp +++ b/samplecode/SamplePicture.cpp @@ -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); - - SkPicture* pict = new SkPicture; - SkAutoUnref aur(pict); + this->drawSomething(canvas); - 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); } diff --git a/samplecode/SampleTiling.cpp b/samplecode/SampleTiling.cpp index 9ffccebf1a..faa8d80144 100644 --- a/samplecode/SampleTiling.cpp +++ b/samplecode/SampleTiling.cpp @@ -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); } diff --git a/src/core/SkPicture.cpp b/src/core/SkPicture.cpp index e67830e223..d805fc52a2 100644 --- a/src/core/SkPicture.cpp +++ b/src/core/SkPicture.cpp @@ -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); } diff --git a/src/core/SkQuadTreePicture.h b/src/core/SkQuadTreePicture.h index 0427b394a0..67e6658deb 100644 --- a/src/core/SkQuadTreePicture.h +++ b/src/core/SkQuadTreePicture.h @@ -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 diff --git a/tests/CanvasTest.cpp b/tests/CanvasTest.cpp index 50371d149d..9b34b08033 100644 --- a/tests/CanvasTest.cpp +++ b/tests/CanvasTest.cpp @@ -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); } }; diff --git a/tests/ImageFilterTest.cpp b/tests/ImageFilterTest.cpp index d2a5843a6b..acc9bd517f 100644 --- a/tests/ImageFilterTest.cpp +++ b/tests/ImageFilterTest.cpp @@ -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) { diff --git a/tests/LayerDrawLooperTest.cpp b/tests/LayerDrawLooperTest.cpp index 1facb23b51..bc76a02a4b 100644 --- a/tests/LayerDrawLooperTest.cpp +++ b/tests/LayerDrawLooperTest.cpp @@ -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; diff --git a/tests/PictureTest.cpp b/tests/PictureTest.cpp index b77beca334..defb2e93ed 100644 --- a/tests/PictureTest.cpp +++ b/tests/PictureTest.cpp @@ -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(); - - testCanvas.drawPicture(extra_save_picture); - REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount()); + { + // 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()); - SkPicture no_save_picture; - extra_restore_picture.beginRecording(100, 100); - extra_restore_picture.getRecordingCanvas()->translate(10, 10); - extra_restore_picture.getRecordingCanvas()->drawRect(rect, paint); + testCanvas.drawPicture(*extraRestorePicture); + REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount()); + } - testCanvas.drawPicture(extra_save_picture); - REPORTER_ASSERT(reporter, 4 == testCanvas.getSaveCount()); - REPORTER_ASSERT(reporter, testCanvas.getTotalMatrix().isIdentity()); + set_canvas_to_save_count_4(&testCanvas); + + { + 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(); - REPORTER_ASSERT(reporter, NULL != destPicture); - destPicture->unref(); - } - { - // Test without call to endRecording - SkPicture picture; - picture.beginRecording(1, 1); - 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(); } } @@ -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; - - SkPicture childPlain; - childPlain.beginRecording(10, 10); - childPlain.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 - - 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 + SkPictureRecorder recorder; + + recorder.beginRecording(10, 10); + SkAutoTUnref<SkPicture> childPlain(recorder.endRecording()); + REPORTER_ASSERT(reporter, !childPlain->willPlayBackBitmaps()); // 0 + + recorder.beginRecording(10, 10)->drawBitmap(bm, 0, 0); + SkAutoTUnref<SkPicture> childWithBitmap(recorder.endRecording()); + REPORTER_ASSERT(reporter, childWithBitmap->willPlayBackBitmaps()); // 1 + + { + 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> emptyClone(empty.clone()); - REPORTER_ASSERT(reporter, empty.uniqueID() != emptyClone->uniqueID()); + { + SkAutoTUnref<SkPicture> cloneWithData(hasData->clone()); + REPORTER_ASSERT(reporter, hasData->uniqueID() == cloneWithData->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) { diff --git a/tests/SerializationTest.cpp b/tests/SerializationTest.cpp index a039e55d02..1c57aaf11b 100644 --- a/tests/SerializationTest.cpp +++ b/tests/SerializationTest.cpp @@ -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); diff --git a/tests/TileGridTest.cpp b/tests/TileGridTest.cpp index f23324a69d..25425fa5bb 100644 --- a/tests/TileGridTest.cpp +++ b/tests/TileGridTest.cpp @@ -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 diff --git a/tools/CopyTilesRenderer.cpp b/tools/CopyTilesRenderer.cpp index 341d93edae..9e919e0a4f 100644 --- a/tools/CopyTilesRenderer.cpp +++ b/tools/CopyTilesRenderer.cpp @@ -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. diff --git a/tools/PictureRenderer.cpp b/tools/PictureRenderer.cpp index f71b9544e0..a1098d9c16 100644 --- a/tools/PictureRenderer.cpp +++ b/tools/PictureRenderer.cpp @@ -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; diff --git a/tools/PictureRenderer.h b/tools/PictureRenderer.h index 26bdb7790f..4c5b426887 100644 --- a/tools/PictureRenderer.h +++ b/tools/PictureRenderer.h @@ -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; diff --git a/tools/bench_record.cpp b/tools/bench_record.cpp index e59744b1dc..283ba6ca57 100644 --- a/tools/bench_record.cpp +++ b/tools/bench_record.cpp @@ -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()); } } } diff --git a/tools/filtermain.cpp b/tools/filtermain.cpp index 39c484d724..b61e15d656 100644 --- a/tools/filtermain.cpp +++ b/tools/filtermain.cpp @@ -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; diff --git a/tools/render_pictures_main.cpp b/tools/render_pictures_main.cpp index 7ebbdbd3aa..0e68117c72 100644 --- a/tools/render_pictures_main.cpp +++ b/tools/render_pictures_main.cpp @@ -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) { diff --git a/tools/skpmaker.cpp b/tools/skpmaker.cpp index 00082075c7..740d522366 100644 --- a/tools/skpmaker.cpp +++ b/tools/skpmaker.cpp @@ -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); |