Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / tests / RecordingXfermodeTest.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
10 #include "../include/core/SkCanvas.h"
11 #include "../include/core/SkPicture.h"
12 #include "../include/core/SkStream.h"
13 #include "../include/core/SkString.h"
14 #include "../include/record/SkRecording.h"
15 #include "../include/core/SkPictureRecorder.h"
16 #include <cstring>
17
18 // Verify that replay of a recording into a clipped canvas
19 // produces the correct bitmap.
20 // This arose from http://crbug.com/401593 which has
21 // https://code.google.com/p/skia/issues/detail?id=1291 as its root cause.
22
23
24 namespace {
25
26 class Drawer {
27  public:
28     explicit Drawer()
29             : fImageInfo(SkImageInfo::MakeN32Premul(200,100))
30     {
31         fCircleBM.allocPixels( SkImageInfo::MakeN32Premul(100,100) );
32         SkCanvas canvas(fCircleBM);
33         canvas.clear(0xffffffff);
34         SkPaint circlePaint;
35         circlePaint.setColor(0xff000000);
36         canvas.drawCircle(50,50,50,circlePaint);
37     }
38
39     const SkImageInfo& imageInfo() const { return fImageInfo; }
40
41     void draw(SkCanvas* canvas, const SkRect& clipRect, SkXfermode::Mode mode) const {
42         SkPaint greenPaint;
43         greenPaint.setColor(0xff008000);
44         SkPaint blackPaint;
45         blackPaint.setColor(0xff000000);
46         SkPaint whitePaint;
47         whitePaint.setColor(0xffffffff);
48         SkPaint layerPaint;
49         layerPaint.setColor(0xff000000);
50         layerPaint.setXfermodeMode(mode);
51         SkRect canvasRect(SkRect::MakeWH(SkIntToScalar(fImageInfo.width()),SkIntToScalar(fImageInfo.height())));
52
53         canvas->clipRect(clipRect);
54         canvas->clear(0xff000000);
55
56         canvas->saveLayer(NULL,&blackPaint);
57             canvas->drawRect(canvasRect,greenPaint);
58             canvas->saveLayer(NULL,&layerPaint);
59                 canvas->drawBitmapRect(fCircleBM,SkRect::MakeXYWH(20,20,60,60),&blackPaint);
60             canvas->restore();
61         canvas->restore();
62     }
63
64  private:
65     const SkImageInfo fImageInfo;
66     SkBitmap fCircleBM;
67 };
68
69 class RecordingStrategy {
70  public:
71     virtual ~RecordingStrategy() {}
72     virtual void init(const SkImageInfo&) = 0;
73     virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
74                                             const SkRect& intoClip,
75                                             SkXfermode::Mode) = 0;
76 };
77
78 class BitmapBackedCanvasStrategy : public RecordingStrategy {
79     // This version just draws into a bitmap-backed canvas.
80  public:
81     BitmapBackedCanvasStrategy() {}
82
83     virtual void init(const SkImageInfo& imageInfo) {
84         fBitmap.allocPixels(imageInfo);
85     }
86
87     virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
88                                             const SkRect& intoClip,
89                                             SkXfermode::Mode mode) {
90         SkCanvas canvas(fBitmap);
91         canvas.clear(0xffffffff);
92         // Note that the scene is drawn just into the clipped region!
93         canvas.clipRect(intoClip);
94         drawer.draw(&canvas, intoClip, mode); // Shouild be canvas-wide...
95         return fBitmap;
96     }
97
98  private:
99     SkBitmap fBitmap;
100 };
101
102 class DeprecatedRecorderStrategy : public RecordingStrategy {
103     // This version draws the entire scene into an SkPictureRecorder,
104     // using the deprecated recording backend.
105     // Then it then replays the scene through a clip rectangle.
106     // This backend proved to be buggy.
107  public:
108     DeprecatedRecorderStrategy() {}
109
110     virtual void init(const SkImageInfo& imageInfo) {
111         fBitmap.allocPixels(imageInfo);
112         fWidth = imageInfo.width();
113         fHeight= imageInfo.height();
114     }
115
116     virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
117                                             const SkRect& intoClip,
118                                             SkXfermode::Mode mode) {
119         SkTileGridFactory::TileGridInfo tileGridInfo = { {100,100}, {0,0}, {0,0} };
120         SkTileGridFactory factory(tileGridInfo);
121         SkPictureRecorder recorder;
122         SkRect canvasRect(SkRect::MakeWH(SkIntToScalar(fWidth),SkIntToScalar(fHeight)));
123         SkCanvas* canvas = recorder.DEPRECATED_beginRecording( SkIntToScalar(fWidth), SkIntToScalar(fHeight), &factory);
124         drawer.draw(canvas, canvasRect, mode);
125         SkAutoTDelete<SkPicture> picture(recorder.endRecording());
126
127         SkCanvas replayCanvas(fBitmap);
128         replayCanvas.clear(0xffffffff);
129         replayCanvas.clipRect(intoClip);
130         picture->playback(&replayCanvas);
131
132         return fBitmap;
133     }
134
135  private:
136     SkBitmap fBitmap;
137     int fWidth;
138     int fHeight;
139 };
140
141 class NewRecordingStrategy : public RecordingStrategy {
142     // This version draws the entire scene into an SkPictureRecorder,
143     // using the new recording backend.
144     // Then it then replays the scene through a clip rectangle.
145     // This backend proved to be buggy.
146  public:
147     NewRecordingStrategy() {}
148
149     virtual void init(const SkImageInfo& imageInfo) {
150         fBitmap.allocPixels(imageInfo);
151         fWidth = imageInfo.width();
152         fHeight= imageInfo.height();
153     }
154
155     virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
156                                             const SkRect& intoClip,
157                                             SkXfermode::Mode mode) {
158         SkTileGridFactory::TileGridInfo tileGridInfo = { {100,100}, {0,0}, {0,0} };
159         SkTileGridFactory factory(tileGridInfo);
160         SkPictureRecorder recorder;
161         SkRect canvasRect(SkRect::MakeWH(SkIntToScalar(fWidth),SkIntToScalar(fHeight)));
162         SkCanvas* canvas = recorder.EXPERIMENTAL_beginRecording( SkIntToScalar(fWidth), SkIntToScalar(fHeight), &factory);
163
164         drawer.draw(canvas, canvasRect, mode);
165         SkAutoTDelete<SkPicture> picture(recorder.endRecording());
166
167         SkCanvas replayCanvas(fBitmap);
168         replayCanvas.clear(0xffffffff);
169         replayCanvas.clipRect(intoClip);
170         picture->playback(&replayCanvas);
171         return fBitmap;
172     }
173
174  private:
175     SkBitmap fBitmap;
176     int fWidth;
177     int fHeight;
178 };
179
180 }
181
182
183
184 DEF_TEST(SkRecordingAccuracyXfermode, reporter) {
185 #define FINEGRAIN 0
186
187     const Drawer drawer;
188
189     BitmapBackedCanvasStrategy golden; // This is the expected result.
190     DeprecatedRecorderStrategy deprecatedRecording;
191     NewRecordingStrategy newRecording;
192
193     golden.init(drawer.imageInfo());
194     deprecatedRecording.init(drawer.imageInfo());
195     newRecording.init(drawer.imageInfo());
196
197 #if !FINEGRAIN
198     unsigned numErrors = 0;
199     SkString errors;
200 #endif
201
202     for (int iMode = 0; iMode < int(SkXfermode::kLastMode) ; iMode++ ) {
203         const SkRect& clip = SkRect::MakeXYWH(100,0,100,100);
204         SkXfermode::Mode mode = SkXfermode::Mode(iMode);
205
206         const SkBitmap& goldenBM = golden.recordAndReplay(drawer, clip, mode);
207         const SkBitmap& deprecatedBM = deprecatedRecording.recordAndReplay(drawer, clip, mode);
208         const SkBitmap& newRecordingBM = newRecording.recordAndReplay(drawer, clip, mode);
209
210         size_t pixelsSize = goldenBM.getSize();
211         REPORTER_ASSERT( reporter, pixelsSize == deprecatedBM.getSize() );
212         REPORTER_ASSERT( reporter, pixelsSize == newRecordingBM.getSize() );
213
214         // The pixel arrays should match.
215 #if FINEGRAIN
216         REPORTER_ASSERT_MESSAGE( reporter,
217                                  0==memcmp( goldenBM.getPixels(), deprecatedBM.getPixels(), pixelsSize ),
218                                  "Tiled bitmap is wrong");
219         REPORTER_ASSERT_MESSAGE( reporter,
220                                  0==memcmp( goldenBM.getPixels(), recordingBM.getPixels(), pixelsSize ),
221                                  "SkRecorder bitmap is wrong");
222 #else
223         if ( memcmp( goldenBM.getPixels(), deprecatedBM.getPixels(), pixelsSize ) ) {
224             numErrors++;
225             SkString str;
226             str.printf("For SkXfermode %d %s:    Deprecated recorder bitmap is wrong\n", iMode, SkXfermode::ModeName(mode));
227             errors.append(str);
228         }
229         if ( memcmp( goldenBM.getPixels(), newRecordingBM.getPixels(), pixelsSize ) ) {
230             numErrors++;
231             SkString str;
232             str.printf("For SkXfermode %d %s:    SkPictureRecorder bitmap is wrong\n", iMode, SkXfermode::ModeName(mode));
233             errors.append(str);
234         }
235 #endif
236     }
237 #if !FINEGRAIN
238     REPORTER_ASSERT_MESSAGE( reporter, 0==numErrors, errors.c_str() );
239 #endif
240 }