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

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: adding missing test file 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 class CanvasRenderingContext2DTest : public ::testing::Test {
29 protected:
30 virtual void SetUp() override;
31
32 DummyPageHolder& page() const { return *m_dummyPageHolder; }
33 HTMLDocument& document() const { return *m_document; }
34 HTMLCanvasElement& canvasElement() const { return *m_canvasElement; }
35 CanvasRenderingContext2D* context2d() const { return static_cast<CanvasRende ringContext2D*>(canvasElement().renderingContext()); }
36
37 void createContext(OpacityMode);
38
39 private:
40 OwnPtr<DummyPageHolder> m_dummyPageHolder;
41 RefPtrWillBePersistent<HTMLDocument> m_document;
42 RefPtrWillBePersistent<HTMLCanvasElement> m_canvasElement;
43 };
44
45 void CanvasRenderingContext2DTest::createContext(OpacityMode opacityMode)
46 {
47 String canvasType("2d");
48 CanvasContextCreationAttributes attributes;
49 attributes.setAlpha(opacityMode == NonOpaque);
50 CanvasRenderingContext2DOrWebGLRenderingContext result;
51 m_canvasElement->getContext(canvasType, attributes, result);
52 }
53
54 void CanvasRenderingContext2DTest::SetUp()
55 {
56 Page::PageClients pageClients;
57 fillWithEmptyClients(pageClients);
58 m_dummyPageHolder = DummyPageHolder::create(IntSize(800, 600), &pageClients) ;
59 m_document = toHTMLDocument(&m_dummyPageHolder->document());
60 m_document->documentElement()->setInnerHTML("<body><canvas id='c'></canvas>< /body>", ASSERT_NO_EXCEPTION);
61 m_document->view()->updateLayoutAndStyleIfNeededRecursive();
62 m_canvasElement = toHTMLCanvasElement(m_document->getElementById("c"));
63 }
64
65 //============================================================================
66
67 class PLATFORM_EXPORT MockImageBufferSurfaceForOverwriteTesting : public Unaccel eratedImageBufferSurface {
68 public:
69 MockImageBufferSurfaceForOverwriteTesting(const IntSize& size, OpacityMode m ode) : UnacceleratedImageBufferSurface(size, mode) { }
70 virtual ~MockImageBufferSurfaceForOverwriteTesting() { }
71 bool isRecording() const override { return true; } // otherwise overwrites a re not tracked
72
73 MOCK_METHOD0(willOverwriteCanvas, void());
74 };
75
76 //============================================================================
77
78 #define TEST_OVERWRITE_SETUP(EXPECTED_OVERWRITES) \
Ken Russell (switch to Gerrit) 2015/02/11 10:11:44 Throughout this test file, would it make sense to
Justin Novosad 2015/02/11 18:59:54 Done.
79 OwnPtr<MockImageBufferSurfaceForOverwriteTesting> mockSurface = adoptPtr (new MockImageBufferSurfaceForOverwriteTesting(IntSize(10, 10), NonOpaque)); \
80 MockImageBufferSurfaceForOverwriteTesting* surfacePtr = mockSurface.get( ); \
81 canvasElement().createImageBufferUsingSurface(mockSurface.release()); \
82 EXPECT_CALL(*surfacePtr, willOverwriteCanvas()).Times(EXPECTED_OVERWRITE S); \
83 context2d()->save();
84
85 #define TEST_OVERWRITE_FINALIZE \
86 context2d()->restore(); \
87 Mock::VerifyAndClearExpectations(surfacePtr);
88
89 #define TEST_OVERWRITE_1(EXPECTED_OVERWRITES, CALL1) \
90 do { \
91 TEST_OVERWRITE_SETUP(EXPECTED_OVERWRITES) \
92 context2d()->CALL1; \
93 TEST_OVERWRITE_FINALIZE \
94 } while (0)
95
96 #define TEST_OVERWRITE_2(EXPECTED_OVERWRITES, CALL1, CALL2) \
97 do { \
98 TEST_OVERWRITE_SETUP(EXPECTED_OVERWRITES) \
99 context2d()->CALL1; \
100 context2d()->CALL2; \
101 TEST_OVERWRITE_FINALIZE \
102 } while (0)
103
104 #define TEST_OVERWRITE_3(EXPECTED_OVERWRITES, CALL1, CALL2, CALL3) \
105 do { \
106 TEST_OVERWRITE_SETUP(EXPECTED_OVERWRITES) \
107 context2d()->CALL1; \
108 context2d()->CALL2; \
109 context2d()->CALL3; \
110 TEST_OVERWRITE_FINALIZE \
111 } while (0)
112
113 enum BitmapOpacity {
114 OpaqueBitmap,
115 TransparentBitmap
116 };
117
118 //============================================================================
119
120 class FakeImageSource : public CanvasImageSource {
121 public:
122 FakeImageSource(IntSize, BitmapOpacity);
123
124 PassRefPtr<Image> getSourceImageForCanvas(SourceImageMode, SourceImageStatus *) const override;
125
126 bool wouldTaintOrigin(SecurityOrigin* destinationSecurityOrigin) const overr ide { return false; }
127 FloatSize sourceSize() const override { return FloatSize(m_size); }
128 bool isOpaque() const override { return m_isOpaque; }
129
130 virtual ~FakeImageSource() { }
131
132 private:
133 IntSize m_size;
134 RefPtr<Image> m_image;
135 bool m_isOpaque;
136 };
137
138 FakeImageSource::FakeImageSource(IntSize size, BitmapOpacity opacity)
139 : m_size(size)
140 , m_isOpaque(opacity == OpaqueBitmap)
141 {
142 SkAutoTUnref<SkSurface> surface(SkSurface::NewRasterN32Premul(m_size.width() , m_size.height()));
143 surface->getCanvas()->clear(opacity == OpaqueBitmap ? SK_ColorWHITE : SK_Col orTRANSPARENT);
144 RefPtr<SkImage> image = adoptRef(surface->newImageSnapshot());
145 m_image = StaticBitmapImage::create(image);
146 }
147
148 PassRefPtr<Image> FakeImageSource::getSourceImageForCanvas(SourceImageMode, Sour ceImageStatus* status) const
149 {
150 if (status)
151 *status = NormalSourceImageStatus;
152 return m_image;
153 }
154
155 //============================================================================
156
157 TEST_F(CanvasRenderingContext2DTest, detectOverwrite)
dshwang 2015/02/11 08:37:52 nice test!
Ken Russell (switch to Gerrit) 2015/02/11 10:11:44 Consider splitting up this test into a few so it's
Justin Novosad 2015/02/11 18:59:54 Done.
158 {
159 RefPtrWillBeRawPtr<ImageData> fullImageData = ImageData::create(IntSize(10, 10));
160 RefPtrWillBeRawPtr<ImageData> partialImageData = ImageData::create(IntSize(2 , 2));
161 FakeImageSource opaqueBitmap(IntSize(10, 10), OpaqueBitmap);
162 FakeImageSource alphaBitmap(IntSize(10, 10), TransparentBitmap);
163 NonThrowableExceptionState exceptionState;
164
165 RefPtrWillBeRawPtr<CanvasGradient> opaqueGradient = CanvasGradient::create(F loatPoint(0, 0), FloatPoint(10, 0));
166 opaqueGradient->addColorStop(0, String("green"), exceptionState);
167 EXPECT_FALSE(exceptionState.hadException());
168 opaqueGradient->addColorStop(1, String("blue"), exceptionState);
169 EXPECT_FALSE(exceptionState.hadException());
170 StringOrCanvasGradientOrCanvasPattern wrappedOpaqueGradient;
171 wrappedOpaqueGradient.setCanvasGradient(opaqueGradient);
172
173 RefPtrWillBeRawPtr<CanvasGradient> alphaGradient = CanvasGradient::create(Fl oatPoint(0, 0), FloatPoint(10, 0));
174 alphaGradient->addColorStop(0, String("green"), exceptionState);
175 EXPECT_FALSE(exceptionState.hadException());
176 alphaGradient->addColorStop(1, String("rgba(0, 0, 255, 0.5)"), exceptionStat e);
177 EXPECT_FALSE(exceptionState.hadException());
178 StringOrCanvasGradientOrCanvasPattern wrappedAlphaGradient;
179 wrappedAlphaGradient.setCanvasGradient(alphaGradient);
180
181 createContext(NonOpaque);
182
183 // Test fillRect
184 TEST_OVERWRITE_1(1, fillRect(-1, -1, 12, 12));
185 TEST_OVERWRITE_1(1, fillRect(0, 0, 10, 10));
186 TEST_OVERWRITE_1(0, strokeRect(0, 0, 10, 10)); // stroking instead of fillin g does not overwrite
187 TEST_OVERWRITE_2(0, setGlobalAlpha(0.5f), fillRect(0, 0, 10, 10));
188 TEST_OVERWRITE_1(0, fillRect(0, 0, 9, 9));
189 TEST_OVERWRITE_2(0, translate(1, 1), fillRect(0, 0, 10, 10));
Ken Russell (switch to Gerrit) 2015/02/11 10:11:44 Also test transformed rects that would still overd
Justin Novosad 2015/02/11 18:59:54 Done.
190 TEST_OVERWRITE_2(1, setFillStyle(wrappedOpaqueGradient), fillRect(0, 0, 10, 10));
191 TEST_OVERWRITE_2(0, setFillStyle(wrappedAlphaGradient), fillRect(0, 0, 10, 1 0));
192 TEST_OVERWRITE_3(0, setGlobalAlpha(0.5), setFillStyle(wrappedOpaqueGradient) , fillRect(0, 0, 10, 10));
193 TEST_OVERWRITE_3(1, setGlobalAlpha(0.5f), setGlobalCompositeOperation(String ("copy")), fillRect(0, 0, 10, 10));
194 TEST_OVERWRITE_2(1, setGlobalCompositeOperation(String("copy")), fillRect(0, 0, 9, 9));
Ken Russell (switch to Gerrit) 2015/02/11 10:11:44 I don't understand why setting the globalComposite
Justin Novosad 2015/02/11 18:59:54 Close. The way the spec defines the behavior: prim
195 TEST_OVERWRITE_3(0, rect(0, 0, 5, 5), clip(), fillRect(0, 0, 10, 10));
196
197 // Test clearRect
198 TEST_OVERWRITE_1(1, clearRect(0, 0, 10, 10));
199 TEST_OVERWRITE_1(0, clearRect(0, 0, 9, 9));
200 TEST_OVERWRITE_2(1, setGlobalAlpha(0.5f), clearRect(0, 0, 10, 10));
201 TEST_OVERWRITE_2(1, setFillStyle(wrappedAlphaGradient), clearRect(0, 0, 10, 10));
202 TEST_OVERWRITE_2(1, setGlobalCompositeOperation(String("destination-in")), c learRect(0, 0, 10, 10));
203 TEST_OVERWRITE_3(0, rect(0, 0, 5, 5), clip(), clearRect(0, 0, 10, 10));
Ken Russell (switch to Gerrit) 2015/02/11 10:11:44 What about transforms in conjunction with clearRec
Justin Novosad 2015/02/11 18:59:54 Done.
204
205 // Test drawImage
206 TEST_OVERWRITE_1(1, drawImage(&opaqueBitmap, 0, 0, 10, 10, 0, 0, 10, 10, exc eptionState));
207 EXPECT_FALSE(exceptionState.hadException());
208 TEST_OVERWRITE_1(1, drawImage(&opaqueBitmap, 0, 0, 1, 1, 0, 0, 10, 10, excep tionState));
209 EXPECT_FALSE(exceptionState.hadException());
210 TEST_OVERWRITE_2(0, setGlobalAlpha(0.5f), drawImage(&opaqueBitmap, 0, 0, 10, 10, 0, 0, 10, 10, exceptionState));
211 EXPECT_FALSE(exceptionState.hadException());
212 TEST_OVERWRITE_1(0, drawImage(&alphaBitmap, 0, 0, 10, 10, 0, 0, 10, 10, exce ptionState));
213 EXPECT_FALSE(exceptionState.hadException());
214 TEST_OVERWRITE_2(0, setGlobalAlpha(0.5f), drawImage(&alphaBitmap, 0, 0, 10, 10, 0, 0, 10, 10, exceptionState));
215 EXPECT_FALSE(exceptionState.hadException());
216 TEST_OVERWRITE_1(0, drawImage(&opaqueBitmap, 0, 0, 10, 10, 1, 0, 10, 10, exc eptionState));
217 EXPECT_FALSE(exceptionState.hadException());
218 TEST_OVERWRITE_1(0, drawImage(&opaqueBitmap, 0, 0, 10, 10, 0, 0, 9, 9, excep tionState));
219 EXPECT_FALSE(exceptionState.hadException());
220 TEST_OVERWRITE_1(1, drawImage(&opaqueBitmap, 0, 0, 10, 10, 0, 0, 11, 11, exc eptionState));
221 EXPECT_FALSE(exceptionState.hadException());
222 TEST_OVERWRITE_2(1, translate(-1, 0), drawImage(&opaqueBitmap, 0, 0, 10, 10, 1, 0, 10, 10, exceptionState));
Ken Russell (switch to Gerrit) 2015/02/11 10:11:44 Should also test the case where a transform makes
Justin Novosad 2015/02/11 18:59:54 Done.
223 EXPECT_FALSE(exceptionState.hadException());
224 TEST_OVERWRITE_2(0, setFillStyle(wrappedOpaqueGradient), drawImage(&alphaBit map, 0, 0, 10, 10, 0, 0, 10, 10, exceptionState)); // fillStyle ignored by drawI mage
225 EXPECT_FALSE(exceptionState.hadException());
226 TEST_OVERWRITE_2(1, setFillStyle(wrappedAlphaGradient), drawImage(&opaqueBit map, 0, 0, 10, 10, 0, 0, 10, 10, exceptionState)); // fillStyle ignored by drawI mage
227 EXPECT_FALSE(exceptionState.hadException());
228 TEST_OVERWRITE_2(1, setGlobalCompositeOperation(String("copy")), drawImage(& opaqueBitmap, 0, 0, 10, 10, 1, 0, 10, 10, exceptionState));
229 EXPECT_FALSE(exceptionState.hadException());
230 TEST_OVERWRITE_3(0, rect(0, 0, 5, 5), clip(), drawImage(&opaqueBitmap, 0, 0, 10, 10, 0, 0, 10, 10, exceptionState));
231 EXPECT_FALSE(exceptionState.hadException());
232
233 // Test putImageData
234 TEST_OVERWRITE_1(1, putImageData(fullImageData.get(), 0, 0));
235 TEST_OVERWRITE_1(1, putImageData(fullImageData.get(), 0, 0, 0, 0, 10, 10));
236 TEST_OVERWRITE_1(0, putImageData(fullImageData.get(), 0, 0, 1, 1, 8, 8));
237 TEST_OVERWRITE_2(1, setGlobalAlpha(0.5f), putImageData(fullImageData.get(), 0, 0)); // alpha has no effect
238 TEST_OVERWRITE_1(0, putImageData(partialImageData.get(), 0, 0));
239 TEST_OVERWRITE_2(1, translate(1, 1), putImageData(fullImageData.get(), 0, 0) ); // ignores tranforms
240 TEST_OVERWRITE_1(0, putImageData(fullImageData.get(), 1, 0));
241 TEST_OVERWRITE_3(1, rect(0, 0, 5, 5), clip(), putImageData(fullImageData.get (), 0, 0)); // ignores clip
242
243 // Test composite operators with an opaque rect that covers the entire canva s
244 // Note: all the untested composite operations take the same code path as so urce-in,
245 // which assumes that the destination may not be overwritten
246 TEST_OVERWRITE_2(1, setGlobalCompositeOperation(String("clear")), fillRect(0 , 0, 10, 10));
247 TEST_OVERWRITE_2(1, setGlobalCompositeOperation(String("copy")), fillRect(0, 0, 10, 10));
248 TEST_OVERWRITE_2(1, setGlobalCompositeOperation(String("source-over")), fill Rect(0, 0, 10, 10));
249 TEST_OVERWRITE_2(0, setGlobalCompositeOperation(String("source-in")), fillRe ct(0, 0, 10, 10));
250 // Test composite operators with a transparent rect that covers the entire c anvas
251 TEST_OVERWRITE_3(1, setGlobalAlpha(0.5f), setGlobalCompositeOperation(String ("clear")), fillRect(0, 0, 10, 10));
252 TEST_OVERWRITE_3(1, setGlobalAlpha(0.5f), setGlobalCompositeOperation(String ("copy")), fillRect(0, 0, 10, 10));
253 TEST_OVERWRITE_3(0, setGlobalAlpha(0.5f), setGlobalCompositeOperation(String ("source-over")), fillRect(0, 0, 10, 10));
254 TEST_OVERWRITE_3(0, setGlobalAlpha(0.5f), setGlobalCompositeOperation(String ("source-in")), fillRect(0, 0, 10, 10));
255 // Test composite operators with an opaque rect that does not cover the enti re canvas
256 TEST_OVERWRITE_2(0, setGlobalCompositeOperation(String("clear")), fillRect(0 , 0, 5, 5));
257 TEST_OVERWRITE_2(1, setGlobalCompositeOperation(String("copy")), fillRect(0, 0, 5, 5));
258 TEST_OVERWRITE_2(0, setGlobalCompositeOperation(String("source-over")), fill Rect(0, 0, 5, 5));
259 TEST_OVERWRITE_2(0, setGlobalCompositeOperation(String("source-in")), fillRe ct(0, 0, 5, 5));
260 }
261
262 } // unnamed namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698