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

Side by Side Diff: Source/core/html/canvas/CanvasRenderingContext2DTest.cpp

Issue 907453003: Move overdraw tracking code from GraphicsContext to CanvasRenderingContext2D (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: fix test copypasta Created 5 years, 10 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "config.h"
6
7 #include "core/html/canvas/CanvasRenderingContext2D.h"
8
9 #include "core/frame/FrameView.h"
10 #include "core/html/HTMLDocument.h"
11 #include "core/html/ImageData.h"
12 #include "core/html/canvas/CanvasGradient.h"
13 #include "core/html/canvas/CanvasPattern.h"
14 #include "core/html/canvas/WebGLRenderingContext.h"
15 #include "core/loader/EmptyClients.h"
16 #include "core/testing/DummyPageHolder.h"
17 #include "platform/graphics/StaticBitmapImage.h"
18 #include "platform/graphics/UnacceleratedImageBufferSurface.h"
19 #include "third_party/skia/include/core/SkSurface.h"
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22
23 using namespace blink;
24 using ::testing::Mock;
25
26 namespace {
27
28 enum BitmapOpacity {
29 OpaqueBitmap,
30 TransparentBitmap
31 };
32
33 class FakeImageSource : public CanvasImageSource {
34 public:
35 FakeImageSource(IntSize, BitmapOpacity);
36
37 PassRefPtr<Image> getSourceImageForCanvas(SourceImageMode, SourceImageStatus *) const override;
38
39 bool wouldTaintOrigin(SecurityOrigin* destinationSecurityOrigin) const overr ide { return false; }
40 FloatSize sourceSize() const override { return FloatSize(m_size); }
41 bool isOpaque() const override { return m_isOpaque; }
42
43 virtual ~FakeImageSource() { }
44
45 private:
46 IntSize m_size;
47 RefPtr<Image> m_image;
48 bool m_isOpaque;
49 };
50
51 FakeImageSource::FakeImageSource(IntSize size, BitmapOpacity opacity)
52 : m_size(size)
53 , m_isOpaque(opacity == OpaqueBitmap)
54 {
55 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(m_size.width() , m_size.height()));
56 surface->getCanvas()->clear(opacity == OpaqueBitmap ? SK_ColorWHITE : SK_Col orTRANSPARENT);
57 RefPtr<SkImage> image = adoptRef(surface->newImageSnapshot());
58 m_image = StaticBitmapImage::create(image);
59 }
60
61 PassRefPtr<Image> FakeImageSource::getSourceImageForCanvas(SourceImageMode, Sour ceImageStatus* status) const
62 {
63 if (status)
64 *status = NormalSourceImageStatus;
65 return m_image;
66 }
67
68 //============================================================================
69
70 class CanvasRenderingContext2DTest : public ::testing::Test {
71 protected:
72 CanvasRenderingContext2DTest();
73 virtual void SetUp() override;
74
75 DummyPageHolder& page() const { return *m_dummyPageHolder; }
76 HTMLDocument& document() const { return *m_document; }
77 HTMLCanvasElement& canvasElement() const { return *m_canvasElement; }
78 CanvasRenderingContext2D* context2d() const { return static_cast<CanvasRende ringContext2D*>(canvasElement().renderingContext()); }
79
80 void createContext(OpacityMode);
81
82 private:
83 OwnPtr<DummyPageHolder> m_dummyPageHolder;
84 RefPtrWillBePersistent<HTMLDocument> m_document;
85 RefPtrWillBePersistent<HTMLCanvasElement> m_canvasElement;
86
87 protected:
88 // Pre-canned objects for testing
89 RefPtrWillBePersistent<ImageData> m_fullImageData;
90 RefPtrWillBePersistent<ImageData> m_partialImageData;
91 FakeImageSource m_opaqueBitmap;
92 FakeImageSource m_alphaBitmap;
93 StringOrCanvasGradientOrCanvasPattern m_opaqueGradient;
94 StringOrCanvasGradientOrCanvasPattern m_alphaGradient;
95 };
96
97 CanvasRenderingContext2DTest::CanvasRenderingContext2DTest()
98 : m_opaqueBitmap(IntSize(10, 10), OpaqueBitmap)
99 , m_alphaBitmap(IntSize(10, 10), TransparentBitmap)
100 { }
101
102 void CanvasRenderingContext2DTest::createContext(OpacityMode opacityMode)
103 {
104 String canvasType("2d");
105 CanvasContextCreationAttributes attributes;
106 attributes.setAlpha(opacityMode == NonOpaque);
107 CanvasRenderingContext2DOrWebGLRenderingContext result;
108 m_canvasElement->getContext(canvasType, attributes, result);
109 }
110
111 void CanvasRenderingContext2DTest::SetUp()
112 {
113 Page::PageClients pageClients;
114 fillWithEmptyClients(pageClients);
115 m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600), &pageClients) ;
116 m_document = toHTMLDocument(&m_dummyPageHolder->document());
117 m_document->documentElement()->setInnerHTML("<body><canvas id='c'></canvas>< /body>", ASSERT_NO_EXCEPTION);
118 m_document->view()->updateLayoutAndStyleIfNeededRecursive();
119 m_canvasElement = toHTMLCanvasElement(m_document->getElementById("c"));
120
121 m_fullImageData = ImageData::create(IntSize(10, 10));
122 m_partialImageData = ImageData::create(IntSize(2, 2));
123
124 NonThrowableExceptionState exceptionState;
125 RefPtrWillBeRawPtr<CanvasGradient> opaqueGradient = CanvasGradient::create(F loatPoint(0, 0), FloatPoint(10, 0));
126 opaqueGradient->addColorStop(0, String("green"), exceptionState);
127 EXPECT_FALSE(exceptionState.hadException());
128 opaqueGradient->addColorStop(1, String("blue"), exceptionState);
129 EXPECT_FALSE(exceptionState.hadException());
130 m_opaqueGradient.setCanvasGradient(opaqueGradient);
131
132 RefPtrWillBeRawPtr<CanvasGradient> alphaGradient = CanvasGradient::create(Fl oatPoint(0, 0), FloatPoint(10, 0));
133 alphaGradient->addColorStop(0, String("green"), exceptionState);
134 EXPECT_FALSE(exceptionState.hadException());
135 alphaGradient->addColorStop(1, String("rgba(0, 0, 255, 0.5)"), exceptionStat e);
136 EXPECT_FALSE(exceptionState.hadException());
137 StringOrCanvasGradientOrCanvasPattern wrappedAlphaGradient;
138 m_alphaGradient.setCanvasGradient(alphaGradient);
139 }
140
141 //============================================================================
142
143 class MockImageBufferSurfaceForOverwriteTesting : public UnacceleratedImageBuffe rSurface {
144 public:
145 MockImageBufferSurfaceForOverwriteTesting(const IntSize& size, OpacityMode m ode) : UnacceleratedImageBufferSurface(size, mode) { }
146 virtual ~MockImageBufferSurfaceForOverwriteTesting() { }
147 bool isRecording() const override { return true; } // otherwise overwrites a re not tracked
148
149 MOCK_METHOD0(willOverwriteCanvas, void());
150 };
151
152 //============================================================================
153
154 #define TEST_OVERDRAW_SETUP(EXPECTED_OVERDRAWS) \
155 OwnPtr<MockImageBufferSurfaceForOverwriteTesting> mockSurface = adoptPtr (new MockImageBufferSurfaceForOverwriteTesting(IntSize(10, 10), NonOpaque)); \
156 MockImageBufferSurfaceForOverwriteTesting* surfacePtr = mockSurface.get( ); \
157 canvasElement().createImageBufferUsingSurface(mockSurface.release()); \
158 EXPECT_CALL(*surfacePtr, willOverwriteCanvas()).Times(EXPECTED_OVERDRAWS ); \
159 context2d()->save();
160
161 #define TEST_OVERDRAW_FINALIZE \
162 context2d()->restore(); \
163 Mock::VerifyAndClearExpectations(surfacePtr);
164
165 #define TEST_OVERDRAW_1(EXPECTED_OVERDRAWS, CALL1) \
166 do { \
167 TEST_OVERDRAW_SETUP(EXPECTED_OVERDRAWS) \
168 context2d()->CALL1; \
169 TEST_OVERDRAW_FINALIZE \
170 } while (0)
171
172 #define TEST_OVERDRAW_2(EXPECTED_OVERDRAWS, CALL1, CALL2) \
173 do { \
174 TEST_OVERDRAW_SETUP(EXPECTED_OVERDRAWS) \
175 context2d()->CALL1; \
176 context2d()->CALL2; \
177 TEST_OVERDRAW_FINALIZE \
178 } while (0)
179
180 #define TEST_OVERDRAW_3(EXPECTED_OVERDRAWS, CALL1, CALL2, CALL3) \
181 do { \
182 TEST_OVERDRAW_SETUP(EXPECTED_OVERDRAWS) \
183 context2d()->CALL1; \
184 context2d()->CALL2; \
185 context2d()->CALL3; \
186 TEST_OVERDRAW_FINALIZE \
187 } while (0)
188
189 #define TEST_OVERDRAW_4(EXPECTED_OVERDRAWS, CALL1, CALL2, CALL3, CALL4) \
190 do { \
191 TEST_OVERDRAW_SETUP(EXPECTED_OVERDRAWS) \
192 context2d()->CALL1; \
193 context2d()->CALL2; \
194 context2d()->CALL3; \
195 context2d()->CALL4; \
196 TEST_OVERDRAW_FINALIZE \
197 } while (0)
198
199 //============================================================================
200
201 TEST_F(CanvasRenderingContext2DTest, detectOverdrawWithFillRect)
202 {
203 createContext(NonOpaque);
204
205 TEST_OVERDRAW_1(1, fillRect(-1, -1, 12, 12));
206 TEST_OVERDRAW_1(1, fillRect(0, 0, 10, 10));
207 TEST_OVERDRAW_1(0, strokeRect(0, 0, 10, 10)); // stroking instead of filling does not overwrite
208 TEST_OVERDRAW_2(0, setGlobalAlpha(0.5f), fillRect(0, 0, 10, 10));
209 TEST_OVERDRAW_1(0, fillRect(0, 0, 9, 9));
210 TEST_OVERDRAW_2(0, translate(1, 1), fillRect(0, 0, 10, 10));
211 TEST_OVERDRAW_2(1, translate(1, 1), fillRect(-1, -1, 10, 10));
212 TEST_OVERDRAW_2(1, setFillStyle(m_opaqueGradient), fillRect(0, 0, 10, 10));
213 TEST_OVERDRAW_2(0, setFillStyle(m_alphaGradient), fillRect(0, 0, 10, 10));
214 TEST_OVERDRAW_3(0, setGlobalAlpha(0.5), setFillStyle(m_opaqueGradient), fill Rect(0, 0, 10, 10));
215 TEST_OVERDRAW_3(1, setGlobalAlpha(0.5f), setGlobalCompositeOperation(String( "copy")), fillRect(0, 0, 10, 10));
216 TEST_OVERDRAW_2(1, setGlobalCompositeOperation(String("copy")), fillRect(0, 0, 9, 9));
217 TEST_OVERDRAW_3(0, rect(0, 0, 5, 5), clip(), fillRect(0, 0, 10, 10));
218 TEST_OVERDRAW_4(0, rect(0, 0, 5, 5), clip(), setGlobalCompositeOperation(Str ing("copy")), fillRect(0, 0, 10, 10));
219 }
220
221 TEST_F(CanvasRenderingContext2DTest, detectOverdrawWithClearRect)
222 {
223 createContext(NonOpaque);
224
225 TEST_OVERDRAW_1(1, clearRect(0, 0, 10, 10));
226 TEST_OVERDRAW_1(0, clearRect(0, 0, 9, 9));
227 TEST_OVERDRAW_2(1, setGlobalAlpha(0.5f), clearRect(0, 0, 10, 10));
228 TEST_OVERDRAW_2(1, setFillStyle(m_alphaGradient), clearRect(0, 0, 10, 10));
229 TEST_OVERDRAW_2(0, translate(1, 1), clearRect(0, 0, 10, 10));
230 TEST_OVERDRAW_2(1, translate(1, 1), clearRect(-1, -1, 10, 10));
231 TEST_OVERDRAW_2(1, setGlobalCompositeOperation(String("destination-in")), cl earRect(0, 0, 10, 10)); // composite op ignored
232 TEST_OVERDRAW_3(0, rect(0, 0, 5, 5), clip(), clearRect(0, 0, 10, 10));
233 }
234
235 TEST_F(CanvasRenderingContext2DTest, detectOverdrawWithDrawImage)
236 {
237 createContext(NonOpaque);
238 NonThrowableExceptionState exceptionState;
239
240 TEST_OVERDRAW_1(1, drawImage(&m_opaqueBitmap, 0, 0, 10, 10, 0, 0, 10, 10, ex ceptionState));
241 EXPECT_FALSE(exceptionState.hadException());
242 TEST_OVERDRAW_1(1, drawImage(&m_opaqueBitmap, 0, 0, 1, 1, 0, 0, 10, 10, exce ptionState));
243 EXPECT_FALSE(exceptionState.hadException());
244 TEST_OVERDRAW_2(0, setGlobalAlpha(0.5f), drawImage(&m_opaqueBitmap, 0, 0, 10 , 10, 0, 0, 10, 10, exceptionState));
245 EXPECT_FALSE(exceptionState.hadException());
246 TEST_OVERDRAW_1(0, drawImage(&m_alphaBitmap, 0, 0, 10, 10, 0, 0, 10, 10, exc eptionState));
247 EXPECT_FALSE(exceptionState.hadException());
248 TEST_OVERDRAW_2(0, setGlobalAlpha(0.5f), drawImage(&m_alphaBitmap, 0, 0, 10, 10, 0, 0, 10, 10, exceptionState));
249 EXPECT_FALSE(exceptionState.hadException());
250 TEST_OVERDRAW_1(0, drawImage(&m_opaqueBitmap, 0, 0, 10, 10, 1, 0, 10, 10, ex ceptionState));
251 EXPECT_FALSE(exceptionState.hadException());
252 TEST_OVERDRAW_1(0, drawImage(&m_opaqueBitmap, 0, 0, 10, 10, 0, 0, 9, 9, exce ptionState));
253 EXPECT_FALSE(exceptionState.hadException());
254 TEST_OVERDRAW_1(1, drawImage(&m_opaqueBitmap, 0, 0, 10, 10, 0, 0, 11, 11, ex ceptionState));
255 EXPECT_FALSE(exceptionState.hadException());
256 TEST_OVERDRAW_2(1, translate(-1, 0), drawImage(&m_opaqueBitmap, 0, 0, 10, 10 , 1, 0, 10, 10, exceptionState));
257 EXPECT_FALSE(exceptionState.hadException());
258 TEST_OVERDRAW_2(0, translate(-1, 0), drawImage(&m_opaqueBitmap, 0, 0, 10, 10 , 0, 0, 10, 10, exceptionState));
259 EXPECT_FALSE(exceptionState.hadException());
260 TEST_OVERDRAW_2(0, setFillStyle(m_opaqueGradient), drawImage(&m_alphaBitmap, 0, 0, 10, 10, 0, 0, 10, 10, exceptionState)); // fillStyle ignored by drawImage
261 EXPECT_FALSE(exceptionState.hadException());
262 TEST_OVERDRAW_2(1, setFillStyle(m_alphaGradient), drawImage(&m_opaqueBitmap, 0, 0, 10, 10, 0, 0, 10, 10, exceptionState)); // fillStyle ignored by drawImage
263 EXPECT_FALSE(exceptionState.hadException());
264 TEST_OVERDRAW_2(1, setGlobalCompositeOperation(String("copy")), drawImage(&m _opaqueBitmap, 0, 0, 10, 10, 1, 0, 10, 10, exceptionState));
265 EXPECT_FALSE(exceptionState.hadException());
266 TEST_OVERDRAW_3(0, rect(0, 0, 5, 5), clip(), drawImage(&m_opaqueBitmap, 0, 0 , 10, 10, 0, 0, 10, 10, exceptionState));
267 EXPECT_FALSE(exceptionState.hadException());
268 }
269
270 TEST_F(CanvasRenderingContext2DTest, detectOverdrawWithPutImageData)
271 {
272 createContext(NonOpaque);
273
274 // Test putImageData
275 TEST_OVERDRAW_1(1, putImageData(m_fullImageData.get(), 0, 0));
276 TEST_OVERDRAW_1(1, putImageData(m_fullImageData.get(), 0, 0, 0, 0, 10, 10));
277 TEST_OVERDRAW_1(0, putImageData(m_fullImageData.get(), 0, 0, 1, 1, 8, 8));
278 TEST_OVERDRAW_2(1, setGlobalAlpha(0.5f), putImageData(m_fullImageData.get(), 0, 0)); // alpha has no effect
279 TEST_OVERDRAW_1(0, putImageData(m_partialImageData.get(), 0, 0));
280 TEST_OVERDRAW_2(1, translate(1, 1), putImageData(m_fullImageData.get(), 0, 0 )); // ignores tranforms
281 TEST_OVERDRAW_1(0, putImageData(m_fullImageData.get(), 1, 0));
282 TEST_OVERDRAW_3(1, rect(0, 0, 5, 5), clip(), putImageData(m_fullImageData.ge t(), 0, 0)); // ignores clip
283 }
284
285 TEST_F(CanvasRenderingContext2DTest, detectOverdrawWithCompositeOperations)
286 {
287 createContext(NonOpaque);
288
289 // Test composite operators with an opaque rect that covers the entire canva s
290 // Note: all the untested composite operations take the same code path as so urce-in,
291 // which assumes that the destination may not be overwritten
292 TEST_OVERDRAW_2(1, setGlobalCompositeOperation(String("clear")), fillRect(0, 0, 10, 10));
293 TEST_OVERDRAW_2(1, setGlobalCompositeOperation(String("copy")), fillRect(0, 0, 10, 10));
294 TEST_OVERDRAW_2(1, setGlobalCompositeOperation(String("source-over")), fillR ect(0, 0, 10, 10));
295 TEST_OVERDRAW_2(0, setGlobalCompositeOperation(String("source-in")), fillRec t(0, 0, 10, 10));
296 // Test composite operators with a transparent rect that covers the entire c anvas
297 TEST_OVERDRAW_3(1, setGlobalAlpha(0.5f), setGlobalCompositeOperation(String( "clear")), fillRect(0, 0, 10, 10));
298 TEST_OVERDRAW_3(1, setGlobalAlpha(0.5f), setGlobalCompositeOperation(String( "copy")), fillRect(0, 0, 10, 10));
299 TEST_OVERDRAW_3(0, setGlobalAlpha(0.5f), setGlobalCompositeOperation(String( "source-over")), fillRect(0, 0, 10, 10));
300 TEST_OVERDRAW_3(0, setGlobalAlpha(0.5f), setGlobalCompositeOperation(String( "source-in")), fillRect(0, 0, 10, 10));
301 // Test composite operators with an opaque rect that does not cover the enti re canvas
302 TEST_OVERDRAW_2(0, setGlobalCompositeOperation(String("clear")), fillRect(0, 0, 5, 5));
303 TEST_OVERDRAW_2(1, setGlobalCompositeOperation(String("copy")), fillRect(0, 0, 5, 5));
304 TEST_OVERDRAW_2(0, setGlobalCompositeOperation(String("source-over")), fillR ect(0, 0, 5, 5));
305 TEST_OVERDRAW_2(0, setGlobalCompositeOperation(String("source-in")), fillRec t(0, 0, 5, 5));
306 }
307
308 } // unnamed namespace
OLDNEW
« no previous file with comments | « Source/core/html/canvas/CanvasRenderingContext2D.cpp ('k') | Source/platform/blink_platform.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698