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

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: 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 virtual ~Drawer() {}
29 virtual const SkImageInfo& imageInfo() const = 0;
30 virtual void draw(SkCanvas*, const SkRect&, SkXfermode::Mode) const = 0;
31 };
32
33 class ExampleDrawer : public Drawer {
mtklein 2014/09/12 19:20:08 Generally I'm keen on interfaces like this, but pe
dneto 2014/09/12 20:41:42 Done.
34 public:
35 explicit ExampleDrawer()
36 : imageInfo_(SkImageInfo::MakeN32Premul(200,100))
mtklein 2014/09/12 19:20:08 Generally, Skia style wants a big "foo_ -> fFoo" a
dneto 2014/09/12 20:41:42 Done.
37 {
38 circleBM_.allocPixels( SkImageInfo::MakeN32Premul(100,100) );
39 SkCanvas canvas(circleBM_);
40 canvas.clear(0xffffffff);
41 SkPaint circlePaint;
42 circlePaint.setColor(0xff000000);
43 canvas.drawCircle(50,50,50,circlePaint);
44 }
45
46 const SkImageInfo& imageInfo() const { return imageInfo_; }
47
48 void draw(SkCanvas* canvas, const SkRect& clipRect, SkXfermode::Mode mode) con st {
49 SkPaint greenPaint;
50 greenPaint.setColor(0xff008000);
51 SkPaint blackPaint;
52 blackPaint.setColor(0xff000000);
53 SkPaint whitePaint;
54 whitePaint.setColor(0xffffffff);
55 SkPaint layerPaint;
56 layerPaint.setColor(0xff000000);
57 layerPaint.setXfermodeMode(mode);
58 SkRect canvasRect(SkRect::MakeWH(imageInfo_.width(),imageInfo_.height()));
59
60 canvas->clipRect(clipRect);
61 canvas->clear(0xff000000);
62
63 canvas->saveLayer(NULL,&blackPaint);
64 canvas->drawRect(canvasRect,greenPaint);
65 canvas->saveLayer(NULL,&layerPaint);
66 canvas->drawBitmapRect(circleBM_,SkRect::MakeXYWH(20,20,60,60),&blackPai nt);
67 canvas->restore();
68 canvas->restore();
69 }
70
71 private:
72 const SkImageInfo imageInfo_;
73 SkBitmap circleBM_;
74 };
75
76 #if 0
77 void writeToFile(std::string fname, SkPicture* picture) {
78 SkFILEWStream fs(fname.c_str());
79 picture->serialize(&fs,NULL);
80 fs.flush();
81 }
82 #endif
83
84 class RecordingStrategy {
85 public:
86 virtual ~RecordingStrategy() {}
87 virtual void init(const SkImageInfo&) = 0;
88 virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
89 const SkRect& intoClip,
90 SkXfermode::Mode) = 0;
91 };
92
93 class BitmapBackedCanvasStrategy : public RecordingStrategy {
94 // This version just draws into a bitmap-backed canvas.
95 public:
96 BitmapBackedCanvasStrategy() {}
97
98 virtual void init(const SkImageInfo& imageInfo) {
99 bitmap_.allocPixels(imageInfo);
100 }
101
102 virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
103 const SkRect& intoClip,
104 SkXfermode::Mode mode) {
105 SkCanvas canvas(bitmap_);
106 canvas.clear(0xffffffff);
107 // Note that the scene is drawn just into the clipped region!
108 canvas.clipRect(intoClip);
109 drawer.draw(&canvas, intoClip, mode); // Shouild be canvas-wide...
110 return bitmap_;
111 }
112
113 private:
114 SkBitmap bitmap_;
115 };
116
117 class TiledPictureRecorderStrategy : public RecordingStrategy {
118 // This version draws the entire scene into an SkPictureRecorder,
119 // then replays through a clip rectangle.
120 // As of this writing, SkPictureRecorder is a deprecated API, but is
121 // still used in Chrome.
122 // It's also the one that proved to be buggy.
123 public:
124 TiledPictureRecorderStrategy() {}
125
126 virtual void init(const SkImageInfo& imageInfo) {
127 bitmap_.allocPixels(imageInfo);
128 width_ = imageInfo.width();
129 height_= imageInfo.height();
130 }
131
132 virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
133 const SkRect& intoClip,
134 SkXfermode::Mode mode) {
135 SkTileGridFactory::TileGridInfo tileGridInfo = { {100,100}, {0,0}, {0,0} };
136 SkTileGridFactory factory(tileGridInfo);
137 SkPictureRecorder recorder;
138 SkRect canvasRect(SkRect::MakeWH(width_,height_));
139 SkCanvas* canvas = recorder.beginRecording( width_, height_, &factory);
140 drawer.draw(canvas, canvasRect, mode);
141 SkAutoTDelete<SkPicture> picture(recorder.endRecording());
142
143 SkCanvas replayCanvas(bitmap_);
144 replayCanvas.clear(0xffffffff);
145 replayCanvas.clipRect(intoClip);
146 picture->playback(&replayCanvas);
147
148 return bitmap_;
149 }
150
151 private:
152 SkBitmap bitmap_;
153 int width_;
154 int height_;
155 };
156
157 class SkRecordingStrategy : public RecordingStrategy {
158 // This version draws the entire scene via the SkRecording API.
159 // then replays through a clip rectangle.
160 // As of this writing, SkRecording is an experimental API.
161 public:
162 SkRecordingStrategy() {}
163
164 virtual void init(const SkImageInfo& imageInfo) {
165 bitmap_.allocPixels(imageInfo);
166 width_ = imageInfo.width();
167 height_= imageInfo.height();
168 }
169
170 virtual const SkBitmap& recordAndReplay(const Drawer& drawer,
171 const SkRect& intoClip,
172 SkXfermode::Mode mode) {
173 EXPERIMENTAL::SkRecording recording(width_, height_);
174 SkRect canvasRect(SkRect::MakeWH(width_,height_));
175 drawer.draw(recording.canvas(), canvasRect, mode);
176 SkAutoTDelete<const EXPERIMENTAL::SkPlayback> playback(recording.releasePlay back());
177
178 SkCanvas replayCanvas(bitmap_);
179 replayCanvas.clear(0xffffffff);
180 replayCanvas.clipRect(intoClip);
181 playback->draw(&replayCanvas);
182
183 return bitmap_;
184 }
185
186 private:
187 SkBitmap bitmap_;
188 int width_;
189 int height_;
190 };
191
192 }
193
194
195
196 DEF_TEST(SkRecordingAccuracyXfermode, reporter) {
197 #define FINEGRAIN 0
198
199 const ExampleDrawer drawer;
200
201 BitmapBackedCanvasStrategy golden; // This is the expected result.
202 TiledPictureRecorderStrategy tiled;
203 SkRecordingStrategy recording;
204
205 golden.init(drawer.imageInfo());
206 tiled.init(drawer.imageInfo());
207 recording.init(drawer.imageInfo());
208
209 #if !FINEGRAIN
210 unsigned numErrors = 0;
211 SkString errors;
212 #endif
213
214 for (int iMode = 0; iMode < int(SkXfermode::kLastMode) ; iMode++ ) {
215 const SkRect& clip = SkRect::MakeXYWH(100,0,100,100);
216 SkXfermode::Mode mode = SkXfermode::Mode(iMode);
217
218 const SkBitmap& goldenBM = golden.recordAndReplay(drawer, clip, mode);
219 const SkBitmap& tiledBM = tiled.recordAndReplay(drawer, clip, mode);
220 const SkBitmap& recordingBM = recording.recordAndReplay(drawer, clip, mode);
221
222 size_t pixelsSize = goldenBM.getSize();
223 REPORTER_ASSERT( reporter, pixelsSize == tiledBM.getSize() );
224 REPORTER_ASSERT( reporter, pixelsSize == recordingBM.getSize() );
225
226 // The pixel arrays should match.
227 #if FINEGRAIN
228 REPORTER_ASSERT_MESSAGE( reporter,
229 0==memcmp( goldenBM.getPixels(), tiledBM.getPixels( ), pixelsSize ),
230 "Tiled bitmap is wrong");
231 REPORTER_ASSERT_MESSAGE( reporter,
232 0==memcmp( goldenBM.getPixels(), recordingBM.getPix els(), pixelsSize )
233 "SkRecorder bitmap is wrong");
234 #else
235 if ( memcmp( goldenBM.getPixels(), tiledBM.getPixels(), pixelsSize ) ) {
236 numErrors++;
237 SkString str;
238 str.printf("For SkXfermode %d %s: Tiled recorder bitmap is wrong\n", iMod e, SkXfermode::ModeName(mode));
239 errors.append(str);
240 }
241 if ( memcmp( goldenBM.getPixels(), recordingBM.getPixels(), pixelsSize ) ) {
242 numErrors++;
243 SkString str;
244 str.printf("For SkXfermode %d %s: SkRecording bitmap is wrong\n", iMode, SkXfermode::ModeName(mode));
245 errors.append(str);
246 }
247 #endif
248 }
249 REPORTER_ASSERT_MESSAGE( reporter, 0==numErrors, errors.c_str() );
250 }
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