aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar mtklein <mtklein@chromium.org>2014-09-02 12:03:31 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-09-02 12:03:31 -0700
commit00f30bdc9e34b013da54b4406f36556c5be8d041 (patch)
treebc3dac91df9e6d0f2e610855a0ca21fb97594c6a
parentaca21d6d2f9984da8f941b76f4ee11772d0e48ec (diff)
SkRecordPartialDraw with less code duplication
BUG=skia: R=robertphillips@google.com, mtklein@google.com Author: mtklein@chromium.org Review URL: https://codereview.chromium.org/527423002
-rw-r--r--src/core/SkRecordDraw.cpp18
-rw-r--r--src/core/SkRecordDraw.h31
-rw-r--r--tests/RecordDrawTest.cpp52
-rw-r--r--tools/DumpRecord.cpp14
4 files changed, 100 insertions, 15 deletions
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index 0117adeefa..f7f02997df 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -35,15 +35,29 @@ void SkRecordDraw(const SkRecord& record,
}
} else {
// Draw all ops.
- for (SkRecords::Draw draw(canvas); draw.index() < record.count(); draw.next()) {
+ SkRecords::Draw draw(canvas);
+ for (unsigned i = 0; i < record.count(); i++) {
if (NULL != callback && callback->abortDrawing()) {
return;
}
- record.visit<void>(draw.index(), draw);
+ record.visit<void>(i, draw);
}
}
}
+void SkRecordPartialDraw(const SkRecord& record,
+ SkCanvas* canvas,
+ const SkRect& clearRect,
+ unsigned start, unsigned stop) {
+ SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
+
+ stop = SkTMin(stop, record.count());
+ SkRecords::PartialDraw draw(canvas, clearRect);
+ for (unsigned i = start; i < stop; i++) {
+ record.visit<void>(i, draw);
+ }
+}
+
namespace SkRecords {
// FIXME: SkBitmaps are stateful, so we need to copy them to play back in multiple threads.
diff --git a/src/core/SkRecordDraw.h b/src/core/SkRecordDraw.h
index 8da7fb5e4a..033b76d34a 100644
--- a/src/core/SkRecordDraw.h
+++ b/src/core/SkRecordDraw.h
@@ -19,16 +19,16 @@ void SkRecordFillBounds(const SkRecord&, SkBBoxHierarchy*);
// Draw an SkRecord into an SkCanvas. A convenience wrapper around SkRecords::Draw.
void SkRecordDraw(const SkRecord&, SkCanvas*, const SkBBoxHierarchy*, SkDrawPictureCallback*);
+// Draw a portion of an SkRecord into an SkCanvas while replacing clears with drawRects.
+void SkRecordPartialDraw(const SkRecord&, SkCanvas*, const SkRect&, unsigned start, unsigned stop);
+
namespace SkRecords {
// This is an SkRecord visitor that will draw that SkRecord to an SkCanvas.
class Draw : SkNoncopyable {
public:
explicit Draw(SkCanvas* canvas)
- : fInitialCTM(canvas->getTotalMatrix()), fCanvas(canvas), fIndex(0) {}
-
- unsigned index() const { return fIndex; }
- void next() { ++fIndex; }
+ : fInitialCTM(canvas->getTotalMatrix()), fCanvas(canvas) {}
template <typename T> void operator()(const T& r) {
this->draw(r);
@@ -40,7 +40,28 @@ private:
const SkMatrix fInitialCTM;
SkCanvas* fCanvas;
- unsigned fIndex;
+};
+
+// Used by SkRecordPartialDraw.
+class PartialDraw : public Draw {
+public:
+ PartialDraw(SkCanvas* canvas, const SkRect& clearRect)
+ : INHERITED(canvas), fClearRect(clearRect) {}
+
+ // Same as Draw for all ops except Clear.
+ template <typename T> void operator()(const T& r) {
+ this->INHERITED::operator()(r);
+ }
+ void operator()(const Clear& c) {
+ SkPaint p;
+ p.setColor(c.color);
+ DrawRect drawRect(p, fClearRect);
+ this->INHERITED::operator()(drawRect);
+ }
+
+private:
+ const SkRect fClearRect;
+ typedef Draw INHERITED;
};
} // namespace SkRecords
diff --git a/tests/RecordDrawTest.cpp b/tests/RecordDrawTest.cpp
index 80f645defd..11b835b0ca 100644
--- a/tests/RecordDrawTest.cpp
+++ b/tests/RecordDrawTest.cpp
@@ -143,3 +143,55 @@ DEF_TEST(RecordDraw_BBH, r) {
REPORTER_ASSERT(r, !SkRect::MakeLTRB(+1, +1, 399, 479).contains(bbh.entries[i].bounds));
}
}
+
+// Base test to ensure start/stop range is respected
+DEF_TEST(RecordDraw_PartialStartStop, r) {
+ static const int kWidth = 10, kHeight = 10;
+
+ SkRect r1 = { 0, 0, kWidth, kHeight };
+ SkRect r2 = { 0, 0, kWidth, kHeight/2 };
+ SkRect r3 = { 0, 0, kWidth/2, kHeight };
+ SkPaint p;
+
+ SkRecord record;
+ SkRecorder recorder(&record, kWidth, kHeight);
+ recorder.drawRect(r1, p);
+ recorder.drawRect(r2, p);
+ recorder.drawRect(r3, p);
+
+ SkRecord rerecord;
+ SkRecorder canvas(&rerecord, kWidth, kHeight);
+ SkRecordPartialDraw(record, &canvas, r1, 1, 2); // replay just drawRect of r2
+
+ REPORTER_ASSERT(r, 3 == rerecord.count());
+ assert_type<SkRecords::Save> (r, rerecord, 0);
+ assert_type<SkRecords::DrawRect> (r, rerecord, 1);
+ assert_type<SkRecords::Restore> (r, rerecord, 2);
+
+ const SkRecords::DrawRect* drawRect = assert_type<SkRecords::DrawRect>(r, rerecord, 1);
+ REPORTER_ASSERT(r, drawRect->rect == r2);
+}
+
+// Check that clears are converted to drawRects
+DEF_TEST(RecordDraw_PartialClear, r) {
+ static const int kWidth = 10, kHeight = 10;
+
+ SkRect rect = { 0, 0, kWidth, kHeight };
+
+ SkRecord record;
+ SkRecorder recorder(&record, kWidth, kHeight);
+ recorder.clear(SK_ColorRED);
+
+ SkRecord rerecord;
+ SkRecorder canvas(&rerecord, kWidth, kHeight);
+ SkRecordPartialDraw(record, &canvas, rect, 0, 1); // replay just the clear
+
+ REPORTER_ASSERT(r, 3 == rerecord.count());
+ assert_type<SkRecords::Save> (r, rerecord, 0);
+ assert_type<SkRecords::DrawRect>(r, rerecord, 1);
+ assert_type<SkRecords::Restore> (r, rerecord, 2);
+
+ const SkRecords::DrawRect* drawRect = assert_type<SkRecords::DrawRect>(r, rerecord, 1);
+ REPORTER_ASSERT(r, drawRect->rect == rect);
+ REPORTER_ASSERT(r, drawRect->paint.getColor() == SK_ColorRED);
+}
diff --git a/tools/DumpRecord.cpp b/tools/DumpRecord.cpp
index 6e679a5430..c505123acd 100644
--- a/tools/DumpRecord.cpp
+++ b/tools/DumpRecord.cpp
@@ -20,6 +20,7 @@ public:
explicit Dumper(SkCanvas* canvas, int count, bool timeWithCommand)
: fDigits(0)
, fIndent(0)
+ , fIndex(0)
, fDraw(canvas)
, fTimeWithCommand(timeWithCommand) {
while (count > 0) {
@@ -28,9 +29,6 @@ public:
}
}
- unsigned index() const { return fDraw.index(); }
- void next() { fDraw.next(); }
-
template <typename T>
void operator()(const T& command) {
Timer timer;
@@ -71,7 +69,7 @@ private:
if (!fTimeWithCommand) {
printf("%6.1f ", time * 1000);
}
- printf("%*d ", fDigits, fDraw.index());
+ printf("%*d ", fDigits, fIndex++);
for (int i = 0; i < fIndent; i++) {
putchar('\t');
}
@@ -96,6 +94,7 @@ private:
int fDigits;
int fIndent;
+ int fIndex;
SkRecords::Draw fDraw;
const bool fTimeWithCommand;
};
@@ -105,9 +104,8 @@ private:
void DumpRecord(const SkRecord& record,
SkCanvas* canvas,
bool timeWithCommand) {
- for (Dumper dumper(canvas, record.count(), timeWithCommand);
- dumper.index() < record.count();
- dumper.next()) {
- record.visit<void>(dumper.index(), dumper);
+ Dumper dumper(canvas, record.count(), timeWithCommand);
+ for (unsigned i = 0; i < record.count(); i++) {
+ record.visit<void>(i, dumper);
}
}