Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / tests / RecordDrawTest.cpp
1 /*
2  * Copyright 2014 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #include "Test.h"
9 #include "RecordTestUtils.h"
10
11 #include "SkDebugCanvas.h"
12 #include "SkDrawPictureCallback.h"
13 #include "SkDropShadowImageFilter.h"
14 #include "SkRecord.h"
15 #include "SkRecordDraw.h"
16 #include "SkRecordOpts.h"
17 #include "SkRecorder.h"
18 #include "SkRecords.h"
19
20 static const int W = 1920, H = 1080;
21
22 class JustOneDraw : public SkDrawPictureCallback {
23 public:
24     JustOneDraw() : fCalls(0) {}
25
26     virtual bool abortDrawing() SK_OVERRIDE { return fCalls++ > 0; }
27 private:
28     int fCalls;
29 };
30
31 DEF_TEST(RecordDraw_Abort, r) {
32     // Record two commands.
33     SkRecord record;
34     SkRecorder recorder(&record, W, H);
35     recorder.drawRect(SkRect::MakeWH(200, 300), SkPaint());
36     recorder.clipRect(SkRect::MakeWH(100, 200));
37
38     SkRecord rerecord;
39     SkRecorder canvas(&rerecord, W, H);
40
41     JustOneDraw callback;
42     SkRecordDraw(record, &canvas, NULL/*bbh*/, &callback);
43
44     REPORTER_ASSERT(r, 3 == rerecord.count());
45     assert_type<SkRecords::Save>    (r, rerecord, 0);
46     assert_type<SkRecords::DrawRect>(r, rerecord, 1);
47     assert_type<SkRecords::Restore> (r, rerecord, 2);
48 }
49
50 DEF_TEST(RecordDraw_Unbalanced, r) {
51     SkRecord record;
52     SkRecorder recorder(&record, W, H);
53     recorder.save();  // We won't balance this, but SkRecordDraw will for us.
54
55     SkRecord rerecord;
56     SkRecorder canvas(&rerecord, W, H);
57     SkRecordDraw(record, &canvas, NULL/*bbh*/, NULL/*callback*/);
58
59     REPORTER_ASSERT(r, 4 == rerecord.count());
60     assert_type<SkRecords::Save>    (r, rerecord, 0);
61     assert_type<SkRecords::Save>    (r, rerecord, 1);
62     assert_type<SkRecords::Restore> (r, rerecord, 2);
63     assert_type<SkRecords::Restore> (r, rerecord, 3);
64 }
65
66 DEF_TEST(RecordDraw_SetMatrixClobber, r) {
67     // Set up an SkRecord that just scales by 2x,3x.
68     SkRecord scaleRecord;
69     SkRecorder scaleCanvas(&scaleRecord, W, H);
70     SkMatrix scale;
71     scale.setScale(2, 3);
72     scaleCanvas.setMatrix(scale);
73
74     // Set up an SkRecord with an initial +20, +20 translate.
75     SkRecord translateRecord;
76     SkRecorder translateCanvas(&translateRecord, W, H);
77     SkMatrix translate;
78     translate.setTranslate(20, 20);
79     translateCanvas.setMatrix(translate);
80
81     SkRecordDraw(scaleRecord, &translateCanvas, NULL/*bbh*/, NULL/*callback*/);
82     REPORTER_ASSERT(r, 4 == translateRecord.count());
83     assert_type<SkRecords::SetMatrix>(r, translateRecord, 0);
84     assert_type<SkRecords::Save>     (r, translateRecord, 1);
85     assert_type<SkRecords::SetMatrix>(r, translateRecord, 2);
86     assert_type<SkRecords::Restore>  (r, translateRecord, 3);
87
88     // When we look at translateRecord now, it should have its first +20,+20 translate,
89     // then a 2x,3x scale that's been concatted with that +20,+20 translate.
90     const SkRecords::SetMatrix* setMatrix;
91     setMatrix = assert_type<SkRecords::SetMatrix>(r, translateRecord, 0);
92     REPORTER_ASSERT(r, setMatrix->matrix == translate);
93
94     setMatrix = assert_type<SkRecords::SetMatrix>(r, translateRecord, 2);
95     SkMatrix expected = scale;
96     expected.postConcat(translate);
97     REPORTER_ASSERT(r, setMatrix->matrix == expected);
98 }
99
100 struct TestBBH : public SkBBoxHierarchy {
101     virtual void insert(void* data, const SkRect& bounds, bool defer) SK_OVERRIDE {
102         Entry e = { (uintptr_t)data, bounds };
103         entries.push(e);
104     }
105     virtual int getCount() const SK_OVERRIDE { return entries.count(); }
106
107     virtual void flushDeferredInserts() SK_OVERRIDE {}
108
109     virtual void search(const SkRect& query, SkTDArray<void*>* results) const SK_OVERRIDE {}
110     virtual void clear() SK_OVERRIDE {}
111     virtual void rewindInserts() SK_OVERRIDE {}
112     virtual int getDepth() const SK_OVERRIDE { return -1; }
113
114     struct Entry {
115         uintptr_t data;
116         SkRect bounds;
117     };
118     SkTDArray<Entry> entries;
119 };
120
121 // Like a==b, with a little slop recognizing that float equality can be weird.
122 static bool sloppy_rect_eq(SkRect a, SkRect b) {
123     SkRect inset(a), outset(a);
124     inset.inset(1, 1);
125     outset.outset(1, 1);
126     return outset.contains(b) && !inset.contains(b);
127 }
128
129 // This test is not meant to make total sense yet.  It's testing the status quo
130 // of SkRecordFillBounds(), which itself doesn't make total sense yet.
131 DEF_TEST(RecordDraw_BBH, r) {
132     SkRecord record;
133     SkRecorder recorder(&record, W, H);
134     recorder.save();
135         recorder.clipRect(SkRect::MakeWH(400, 500));
136         recorder.scale(2, 2);
137         recorder.drawRect(SkRect::MakeWH(320, 240), SkPaint());
138     recorder.restore();
139
140     TestBBH bbh;
141     SkRecordFillBounds(record, &bbh);
142
143     REPORTER_ASSERT(r, bbh.entries.count() == 5);
144     for (int i = 0; i < bbh.entries.count(); i++) {
145         REPORTER_ASSERT(r, bbh.entries[i].data == (uintptr_t)i);
146
147         REPORTER_ASSERT(r, sloppy_rect_eq(SkRect::MakeWH(400, 480), bbh.entries[i].bounds));
148     }
149 }
150
151 // A regression test for crbug.com/409110.
152 DEF_TEST(RecordDraw_TextBounds, r) {
153     SkRecord record;
154     SkRecorder recorder(&record, W, H);
155
156     // Two Chinese characters in UTF-8.
157     const char text[] = { '\xe6', '\xbc', '\xa2', '\xe5', '\xad', '\x97' };
158     const size_t bytes = SK_ARRAY_COUNT(text);
159
160     const SkScalar xpos[] = { 10, 20 };
161     recorder.drawPosTextH(text, bytes, xpos, 30, SkPaint());
162
163     const SkPoint pos[] = { {40, 50}, {60, 70} };
164     recorder.drawPosText(text, bytes, pos, SkPaint());
165
166     TestBBH bbh;
167     SkRecordFillBounds(record, &bbh);
168     REPORTER_ASSERT(r, bbh.entries.count() == 2);
169
170     // We can make these next assertions confidently because SkRecordFillBounds
171     // builds its bounds by overestimating font metrics in a platform-independent way.
172     // If that changes, these tests will need to be more flexible.
173     REPORTER_ASSERT(r, sloppy_rect_eq(bbh.entries[0].bounds, SkRect::MakeLTRB(-86,  6, 116, 54)));
174     REPORTER_ASSERT(r, sloppy_rect_eq(bbh.entries[1].bounds, SkRect::MakeLTRB(-56, 26, 156, 94)));
175 }
176
177 // Base test to ensure start/stop range is respected
178 DEF_TEST(RecordDraw_PartialStartStop, r) {
179     static const int kWidth = 10, kHeight = 10;
180
181     SkRect r1 = { 0, 0, kWidth,   kHeight };
182     SkRect r2 = { 0, 0, kWidth,   kHeight/2 };
183     SkRect r3 = { 0, 0, kWidth/2, kHeight };
184     SkPaint p;
185
186     SkRecord record;
187     SkRecorder recorder(&record, kWidth, kHeight);
188     recorder.drawRect(r1, p);
189     recorder.drawRect(r2, p);
190     recorder.drawRect(r3, p);
191
192     SkRecord rerecord;
193     SkRecorder canvas(&rerecord, kWidth, kHeight);
194     SkRecordPartialDraw(record, &canvas, r1, 1, 2, SkMatrix::I()); // replay just drawRect of r2
195
196     REPORTER_ASSERT(r, 3 == rerecord.count());
197     assert_type<SkRecords::Save>     (r, rerecord, 0);
198     assert_type<SkRecords::DrawRect> (r, rerecord, 1);
199     assert_type<SkRecords::Restore>  (r, rerecord, 2);
200
201     const SkRecords::DrawRect* drawRect = assert_type<SkRecords::DrawRect>(r, rerecord, 1);
202     REPORTER_ASSERT(r, drawRect->rect == r2);
203 }
204
205 // Check that clears are converted to drawRects
206 DEF_TEST(RecordDraw_PartialClear, r) {
207     static const int kWidth = 10, kHeight = 10;
208
209     SkRect rect = { 0, 0, kWidth, kHeight };
210
211     SkRecord record;
212     SkRecorder recorder(&record, kWidth, kHeight);
213     recorder.clear(SK_ColorRED);
214
215     SkRecord rerecord;
216     SkRecorder canvas(&rerecord, kWidth, kHeight);
217     SkRecordPartialDraw(record, &canvas, rect, 0, 1, SkMatrix::I()); // replay just the clear
218
219     REPORTER_ASSERT(r, 3 == rerecord.count());
220     assert_type<SkRecords::Save>    (r, rerecord, 0);
221     assert_type<SkRecords::DrawRect>(r, rerecord, 1);
222     assert_type<SkRecords::Restore> (r, rerecord, 2);
223
224     const SkRecords::DrawRect* drawRect = assert_type<SkRecords::DrawRect>(r, rerecord, 1);
225     REPORTER_ASSERT(r, drawRect->rect == rect);
226     REPORTER_ASSERT(r, drawRect->paint.getColor() == SK_ColorRED);
227 }
228
229 // A regression test for crbug.com/415468 and skbug.com/2957.
230 //
231 // This also now serves as a regression test for crbug.com/418417.  We used to adjust the
232 // bounds for the saveLayer, clip, and restore to be greater than the bounds of the picture.
233 // (We were applying the saveLayer paint to the bounds after restore, which makes no sense.)
234 DEF_TEST(RecordDraw_SaveLayerAffectsClipBounds, r) {
235     SkRecord record;
236     SkRecorder recorder(&record, 50, 50);
237
238     // We draw a rectangle with a long drop shadow.  We used to not update the clip
239     // bounds based on SaveLayer paints, so the drop shadow could be cut off.
240     SkPaint paint;
241     paint.setImageFilter(SkDropShadowImageFilter::Create(20, 0, 0, 0, SK_ColorBLACK))->unref();
242
243     recorder.saveLayer(NULL, &paint);
244         recorder.clipRect(SkRect::MakeWH(20, 40));
245         recorder.drawRect(SkRect::MakeWH(20, 40), SkPaint());
246     recorder.restore();
247
248     // Under the original bug, the right edge value of the drawRect would be 20 less than asserted
249     // here because we intersected it with a clip that had not been adjusted for the drop shadow.
250     //
251     // The second bug showed up as adjusting the picture bounds (0,0,50,50) by the drop shadow too.
252     // The saveLayer, clipRect, and restore bounds were incorrectly (0,0,70,50).
253     TestBBH bbh;
254     SkRecordFillBounds(record, &bbh);
255     REPORTER_ASSERT(r, bbh.entries.count() == 4);
256     REPORTER_ASSERT(r, sloppy_rect_eq(bbh.entries[0].bounds, SkRect::MakeLTRB(0, 0, 50, 50)));
257     REPORTER_ASSERT(r, sloppy_rect_eq(bbh.entries[1].bounds, SkRect::MakeLTRB(0, 0, 50, 50)));
258     REPORTER_ASSERT(r, sloppy_rect_eq(bbh.entries[2].bounds, SkRect::MakeLTRB(0, 0, 40, 40)));
259     REPORTER_ASSERT(r, sloppy_rect_eq(bbh.entries[3].bounds, SkRect::MakeLTRB(0, 0, 50, 50)));
260 }