#include "SkDebugCanvas.h"
#include "SkDrawPictureCallback.h"
#include "SkDropShadowImageFilter.h"
+#include "SkImagePriv.h"
#include "SkRecord.h"
#include "SkRecordDraw.h"
#include "SkRecordOpts.h"
#include "SkRecorder.h"
#include "SkRecords.h"
+#include "SkSurface.h"
static const int W = 1920, H = 1080;
}
struct TestBBH : public SkBBoxHierarchy {
- virtual void insert(void* data, const SkRect& bounds, bool defer) SK_OVERRIDE {
- Entry e = { (uintptr_t)data, bounds };
- entries.push(e);
+ virtual void insert(SkAutoTMalloc<SkRect>* boundsArray, int N) SK_OVERRIDE {
+ fEntries.setCount(N);
+ for (int i = 0; i < N; i++) {
+ Entry e = { (unsigned)i, (*boundsArray)[i] };
+ fEntries[i] = e;
+ }
}
- virtual int getCount() const SK_OVERRIDE { return entries.count(); }
- virtual void flushDeferredInserts() SK_OVERRIDE {}
-
- virtual void search(const SkRect& query, SkTDArray<void*>* results) const SK_OVERRIDE {}
- virtual void clear() SK_OVERRIDE {}
- virtual void rewindInserts() SK_OVERRIDE {}
- virtual int getDepth() const SK_OVERRIDE { return -1; }
+ virtual void search(const SkRect& query, SkTDArray<unsigned>* results) const SK_OVERRIDE {}
struct Entry {
- uintptr_t data;
+ unsigned opIndex;
SkRect bounds;
};
- SkTDArray<Entry> entries;
+ SkTDArray<Entry> fEntries;
};
// Like a==b, with a little slop recognizing that float equality can be weird.
recorder.restore();
TestBBH bbh;
- SkRecordFillBounds(record, &bbh);
+ SkRecordFillBounds(SkRect::MakeWH(SkIntToScalar(W), SkIntToScalar(H)), record, &bbh);
- REPORTER_ASSERT(r, bbh.entries.count() == 5);
- for (int i = 0; i < bbh.entries.count(); i++) {
- REPORTER_ASSERT(r, bbh.entries[i].data == (uintptr_t)i);
+ REPORTER_ASSERT(r, bbh.fEntries.count() == 5);
+ for (int i = 0; i < bbh.fEntries.count(); i++) {
+ REPORTER_ASSERT(r, bbh.fEntries[i].opIndex == (unsigned)i);
- REPORTER_ASSERT(r, sloppy_rect_eq(SkRect::MakeWH(400, 480), bbh.entries[i].bounds));
+ REPORTER_ASSERT(r, sloppy_rect_eq(SkRect::MakeWH(400, 480), bbh.fEntries[i].bounds));
}
}
recorder.drawPosText(text, bytes, pos, SkPaint());
TestBBH bbh;
- SkRecordFillBounds(record, &bbh);
- REPORTER_ASSERT(r, bbh.entries.count() == 2);
+ SkRecordFillBounds(SkRect::MakeWH(SkIntToScalar(W), SkIntToScalar(H)), record, &bbh);
+ REPORTER_ASSERT(r, bbh.fEntries.count() == 2);
// We can make these next assertions confidently because SkRecordFillBounds
// builds its bounds by overestimating font metrics in a platform-independent way.
// If that changes, these tests will need to be more flexible.
- REPORTER_ASSERT(r, sloppy_rect_eq(bbh.entries[0].bounds, SkRect::MakeLTRB(-86, 6, 116, 54)));
- REPORTER_ASSERT(r, sloppy_rect_eq(bbh.entries[1].bounds, SkRect::MakeLTRB(-56, 26, 156, 94)));
+ REPORTER_ASSERT(r, sloppy_rect_eq(bbh.fEntries[0].bounds, SkRect::MakeLTRB(0, 0, 140, 60)));
+ REPORTER_ASSERT(r, sloppy_rect_eq(bbh.fEntries[1].bounds, SkRect::MakeLTRB(0, 20, 180, 100)));
}
// Base test to ensure start/stop range is respected
// We draw a rectangle with a long drop shadow. We used to not update the clip
// bounds based on SaveLayer paints, so the drop shadow could be cut off.
SkPaint paint;
- paint.setImageFilter(SkDropShadowImageFilter::Create(20, 0, 0, 0, SK_ColorBLACK))->unref();
+ paint.setImageFilter(SkDropShadowImageFilter::Create(20, 0, 0, 0, SK_ColorBLACK,
+ SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode))->unref();
recorder.saveLayer(NULL, &paint);
recorder.clipRect(SkRect::MakeWH(20, 40));
// The second bug showed up as adjusting the picture bounds (0,0,50,50) by the drop shadow too.
// The saveLayer, clipRect, and restore bounds were incorrectly (0,0,70,50).
TestBBH bbh;
- SkRecordFillBounds(record, &bbh);
- REPORTER_ASSERT(r, bbh.entries.count() == 4);
- REPORTER_ASSERT(r, sloppy_rect_eq(bbh.entries[0].bounds, SkRect::MakeLTRB(0, 0, 50, 50)));
- REPORTER_ASSERT(r, sloppy_rect_eq(bbh.entries[1].bounds, SkRect::MakeLTRB(0, 0, 50, 50)));
- REPORTER_ASSERT(r, sloppy_rect_eq(bbh.entries[2].bounds, SkRect::MakeLTRB(0, 0, 40, 40)));
- REPORTER_ASSERT(r, sloppy_rect_eq(bbh.entries[3].bounds, SkRect::MakeLTRB(0, 0, 50, 50)));
+ SkRecordFillBounds(SkRect::MakeWH(50, 50), record, &bbh);
+ REPORTER_ASSERT(r, bbh.fEntries.count() == 4);
+ REPORTER_ASSERT(r, sloppy_rect_eq(bbh.fEntries[0].bounds, SkRect::MakeLTRB(0, 0, 50, 50)));
+ REPORTER_ASSERT(r, sloppy_rect_eq(bbh.fEntries[1].bounds, SkRect::MakeLTRB(0, 0, 50, 50)));
+ REPORTER_ASSERT(r, sloppy_rect_eq(bbh.fEntries[2].bounds, SkRect::MakeLTRB(0, 0, 40, 40)));
+ REPORTER_ASSERT(r, sloppy_rect_eq(bbh.fEntries[3].bounds, SkRect::MakeLTRB(0, 0, 50, 50)));
+}
+
+// When a saveLayer provides an explicit bound and has a complex paint (e.g., one that
+// affects transparent black), that bound should serve to shrink the area of the required
+// backing store.
+DEF_TEST(RecordDraw_SaveLayerBoundsAffectsClipBounds, r) {
+ SkRecord record;
+ SkRecorder recorder(&record, 50, 50);
+
+ SkPaint p;
+ p.setXfermodeMode(SkXfermode::kSrc_Mode);
+
+ SkRect bounds = SkRect::MakeLTRB(10, 10, 40, 40);
+ recorder.saveLayer(&bounds, &p);
+ recorder.drawRect(SkRect::MakeLTRB(20, 20, 30, 30), SkPaint());
+ recorder.restore();
+
+ TestBBH bbh;
+ SkRecordFillBounds(SkRect::MakeWH(50, 50), record, &bbh);
+ REPORTER_ASSERT(r, bbh.fEntries.count() == 3);
+ REPORTER_ASSERT(r, sloppy_rect_eq(bbh.fEntries[0].bounds, SkRect::MakeLTRB(10, 10, 40, 40)));
+ REPORTER_ASSERT(r, sloppy_rect_eq(bbh.fEntries[1].bounds, SkRect::MakeLTRB(20, 20, 30, 30)));
+ REPORTER_ASSERT(r, sloppy_rect_eq(bbh.fEntries[2].bounds, SkRect::MakeLTRB(10, 10, 40, 40)));
+}
+
+DEF_TEST(RecordDraw_drawImage, r){
+ class SkCanvasMock : public SkCanvas {
+ public:
+ SkCanvasMock(int width, int height) : INHERITED(width, height) {
+ this->resetTestValues();
+ }
+ virtual ~SkCanvasMock() {}
+ virtual void drawImage(const SkImage* image, SkScalar left, SkScalar top,
+ const SkPaint* paint = NULL) SK_OVERRIDE {
+
+ fDrawImageCalled = true;
+ }
+
+ virtual void drawImageRect(const SkImage* image, const SkRect* src,
+ const SkRect& dst,
+ const SkPaint* paint = NULL) SK_OVERRIDE {
+ fDrawImageRectCalled = true;
+ }
+
+ void resetTestValues() {
+ fDrawImageCalled = fDrawImageRectCalled = false;
+ }
+
+ bool fDrawImageCalled;
+ bool fDrawImageRectCalled;
+ private:
+ typedef SkCanvas INHERITED;
+ };
+
+ SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterPMColor(10, 10));
+ surface->getCanvas()->clear(SK_ColorGREEN);
+ SkAutoTUnref<SkImage> image(surface->newImageSnapshot());
+
+ SkCanvasMock canvas(10, 10);
+
+ {
+ SkRecord record;
+ SkRecorder recorder(&record, 10, 10);
+ recorder.drawImage(image, 0, 0);
+ SkRecordDraw(record, &canvas, 0, 0);
+ }
+ REPORTER_ASSERT(r, canvas.fDrawImageCalled);
+ canvas.resetTestValues();
+
+ {
+ SkRecord record;
+ SkRecorder recorder(&record, 10, 10);
+ recorder.drawImageRect(image, 0, SkRect::MakeWH(10, 10));
+ SkRecordDraw(record, &canvas, 0, 0);
+ }
+ REPORTER_ASSERT(r, canvas.fDrawImageRectCalled);
+
}