Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Side by Side Diff: tests/RecordingXfermodeTest.cpp

Issue 568073004: Fix recording of saveLayout with unusual Xfermodes. (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Fixed member var names, formatting, copied comment Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« src/core/SkRecordDraw.cpp ('K') | « src/core/SkRecordDraw.cpp ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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) c onst {
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(fImageInfo.width(),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 #if 0
70 void writeToFile(std::string fname, SkPicture* picture) {
mtklein 2014/09/12 20:57:17 remove before submitting?
71 SkFILEWStream fs(fname.c_str());
72 picture->serialize(&fs,NULL);
73 fs.flush();
74 }
75 #endif
76
77 class RecordingStrategy {
78 public:
79 virtual ~RecordingStrategy() {}
80 virtual void init(const SkImageInfo&) = 0;
81 virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
82 const SkRect& intoClip,
mtklein 2014/09/12 20:57:17 some of the indents seem to have gone crazy here.
83 SkXfermode::Mode) = 0;
84 };
85
86 class BitmapBackedCanvasStrategy : public RecordingStrategy {
87 // This version just draws into a bitmap-backed canvas.
88 public:
89 BitmapBackedCanvasStrategy() {}
90
91 virtual void init(const SkImageInfo& imageInfo) {
92 fBitmap.allocPixels(imageInfo);
93 }
94
95 virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
96 const SkRect& intoClip,
97 SkXfermode::Mode mode) {
98 SkCanvas canvas(fBitmap);
99 canvas.clear(0xffffffff);
100 // Note that the scene is drawn just into the clipped region!
101 canvas.clipRect(intoClip);
102 drawer.draw(&canvas, intoClip, mode); // Shouild be canvas-wide...
103 return fBitmap;
104 }
105
106 private:
107 SkBitmap fBitmap;
108 };
109
110 class TiledPictureRecorderStrategy : public RecordingStrategy {
111 // This version draws the entire scene into an SkPictureRecorder,
112 // then replays through a clip rectangle.
113 // As of this writing, SkPictureRecorder is a deprecated API, but is
114 // still used in Chrome.
115 // It's also the one that proved to be buggy.
116 public:
117 TiledPictureRecorderStrategy() {}
118
119 virtual void init(const SkImageInfo& imageInfo) {
120 fBitmap.allocPixels(imageInfo);
121 fWidth = imageInfo.width();
122 fHeight= imageInfo.height();
123 }
124
125 virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
126 const SkRect& intoClip,
127 SkXfermode::Mode mode) {
128 SkTileGridFactory::TileGridInfo tileGridInfo = { {100,100}, {0,0}, {0,0} };
129 SkTileGridFactory factory(tileGridInfo);
130 SkPictureRecorder recorder;
131 SkRect canvasRect(SkRect::MakeWH(fWidth,fHeight));
132 SkCanvas* canvas = recorder.beginRecording( fWidth, fHeight, &factory);
mtklein 2014/09/12 20:38:27 If you'd like to test new vs. old, the better thin
133 drawer.draw(canvas, canvasRect, mode);
134 SkAutoTDelete<SkPicture> picture(recorder.endRecording());
135
136 SkCanvas replayCanvas(fBitmap);
137 replayCanvas.clear(0xffffffff);
138 replayCanvas.clipRect(intoClip);
139 picture->playback(&replayCanvas);
140
141 return fBitmap;
142 }
143
144 private:
145 SkBitmap fBitmap;
146 int fWidth;
147 int fHeight;
148 };
149
150 class SkRecordingStrategy : public RecordingStrategy {
151 // This version draws the entire scene via the SkRecording API.
152 // then replays through a clip rectangle.
153 // As of this writing, SkRecording is an experimental API.
154 public:
155 SkRecordingStrategy() {}
156
157 virtual void init(const SkImageInfo& imageInfo) {
158 fBitmap.allocPixels(imageInfo);
159 fWidth = imageInfo.width();
160 fHeight= imageInfo.height();
161 }
162
163 virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
164 const SkRect& intoClip,
165 SkXfermode::Mode mode) {
166 EXPERIMENTAL::SkRecording recording(fWidth, fHeight);
167 SkRect canvasRect(SkRect::MakeWH(fWidth,fHeight));
168 drawer.draw(recording.canvas(), canvasRect, mode);
169 SkAutoTDelete<const EXPERIMENTAL::SkPlayback> playback(recording.release Playback());
170
171 SkCanvas replayCanvas(fBitmap);
172 replayCanvas.clear(0xffffffff);
173 replayCanvas.clipRect(intoClip);
174 playback->draw(&replayCanvas);
175
176 return fBitmap;
177 }
178
179 private:
180 SkBitmap fBitmap;
181 int fWidth;
182 int fHeight;
183 };
184
185 }
186
187
188
189 DEF_TEST(SkRecordingAccuracyXfermode, reporter) {
190 #define FINEGRAIN 0
191
192 const Drawer drawer;
193
194 BitmapBackedCanvasStrategy golden; // This is the expected result.
195 TiledPictureRecorderStrategy tiled;
196 SkRecordingStrategy recording;
197
198 golden.init(drawer.imageInfo());
199 tiled.init(drawer.imageInfo());
200 recording.init(drawer.imageInfo());
201
202 #if !FINEGRAIN
203 unsigned numErrors = 0;
204 SkString errors;
205 #endif
206
207 for (int iMode = 0; iMode < int(SkXfermode::kLastMode) ; iMode++ ) {
208 const SkRect& clip = SkRect::MakeXYWH(100,0,100,100);
209 SkXfermode::Mode mode = SkXfermode::Mode(iMode);
210
211 const SkBitmap& goldenBM = golden.recordAndReplay(drawer, clip, mode);
212 const SkBitmap& tiledBM = tiled.recordAndReplay(drawer, clip, mode);
213 const SkBitmap& recordingBM = recording.recordAndReplay(drawer, clip, mo de);
214
215 size_t pixelsSize = goldenBM.getSize();
216 REPORTER_ASSERT( reporter, pixelsSize == tiledBM.getSize() );
217 REPORTER_ASSERT( reporter, pixelsSize == recordingBM.getSize() );
218
219 // The pixel arrays should match.
220 #if FINEGRAIN
221 REPORTER_ASSERT_MESSAGE( reporter,
222 0==memcmp( goldenBM.getPixels(), tiledBM.getPix els(), pixelsSize ),
223 "Tiled bitmap is wrong");
224 REPORTER_ASSERT_MESSAGE( reporter,
225 0==memcmp( goldenBM.getPixels(), recordingBM.ge tPixels(), pixelsSize ),
226 "SkRecorder bitmap is wrong");
227 #else
228 if ( memcmp( goldenBM.getPixels(), tiledBM.getPixels(), pixelsSize ) ) {
229 numErrors++;
230 SkString str;
231 str.printf("For SkXfermode %d %s: Tiled recorder bitmap is wrong\ n", iMode, SkXfermode::ModeName(mode));
232 errors.append(str);
233 }
234 if ( memcmp( goldenBM.getPixels(), recordingBM.getPixels(), pixelsSize ) ) {
235 numErrors++;
236 SkString str;
237 str.printf("For SkXfermode %d %s: SkRecording bitmap is wrong\n", iMode, SkXfermode::ModeName(mode));
238 errors.append(str);
239 }
240 #endif
241 }
242 #if !FINEGRAIN
243 REPORTER_ASSERT_MESSAGE( reporter, 0==numErrors, errors.c_str() );
mtklein 2014/09/12 20:57:17 might just move this line up into the #else?
244 #endif
245 }
OLDNEW
« src/core/SkRecordDraw.cpp ('K') | « src/core/SkRecordDraw.cpp ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698