OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
11 * documentation and/or other materials provided with the distribution. | 11 * documentation and/or other materials provided with the distribution. |
12 * | 12 * |
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND AN
Y | 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND AN
Y |
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR AN
Y | 16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR AN
Y |
17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND O
N | 19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND O
N |
20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
23 */ | 23 */ |
24 | 24 |
25 #include "config.h" | 25 #include "config.h" |
26 | 26 |
27 #include "platform/graphics/GraphicsContext.h" | 27 #include "platform/graphics/GraphicsContext.h" |
28 | 28 |
29 #include "platform/graphics/BitmapImage.h" | 29 #include "platform/graphics/BitmapImage.h" |
30 #include "platform/graphics/GraphicsContextClient.h" | |
31 #include "platform/graphics/ImageBuffer.h" | 30 #include "platform/graphics/ImageBuffer.h" |
32 #include "platform/graphics/skia/NativeImageSkia.h" | 31 #include "platform/graphics/skia/NativeImageSkia.h" |
33 #include "third_party/skia/include/core/SkBitmap.h" | 32 #include "third_party/skia/include/core/SkBitmap.h" |
34 #include "third_party/skia/include/core/SkCanvas.h" | 33 #include "third_party/skia/include/core/SkCanvas.h" |
35 #include "third_party/skia/include/core/SkPicture.h" | 34 #include "third_party/skia/include/core/SkPicture.h" |
36 #include "third_party/skia/include/core/SkShader.h" | 35 #include "third_party/skia/include/core/SkShader.h" |
37 #include "third_party/skia/include/effects/SkBlurDrawLooper.h" | 36 #include "third_party/skia/include/effects/SkBlurDrawLooper.h" |
38 #include "third_party/skia/include/effects/SkBlurImageFilter.h" | 37 #include "third_party/skia/include/effects/SkBlurImageFilter.h" |
39 #include "third_party/skia/include/effects/SkBlurMaskFilter.h" | 38 #include "third_party/skia/include/effects/SkBlurMaskFilter.h" |
40 | 39 |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 | 161 |
163 // We can't have an opaque mask actually, but we can pretend here like it wo
uld look if we did. | 162 // We can't have an opaque mask actually, but we can pretend here like it wo
uld look if we did. |
164 context.fillRect(FloatRect(12, 12, 3, 3), opaque, SkXfermode::kSrcOver_Mode)
; | 163 context.fillRect(FloatRect(12, 12, 3, 3), opaque, SkXfermode::kSrcOver_Mode)
; |
165 | 164 |
166 context.endLayer(); | 165 context.endLayer(); |
167 context.endLayer(); | 166 context.endLayer(); |
168 | 167 |
169 EXPECT_OPAQUE_PIXELS_ONLY_IN_RECT(bitmap, IntRect(12, 12, 3, 3)); | 168 EXPECT_OPAQUE_PIXELS_ONLY_IN_RECT(bitmap, IntRect(12, 12, 3, 3)); |
170 } | 169 } |
171 | 170 |
172 #define TEST_CLEAR_SETUP \ | |
173 SkBitmap bitmap; \ | |
174 bitmap.allocN32Pixels(10, 10); \ | |
175 bitmap.eraseColor(0); \ | |
176 SkCanvas canvas(bitmap); \ | |
177 TestGraphicsContextClient gcClient; \ | |
178 GraphicsContext context(&canvas, nullptr); \ | |
179 context.setClient(&gcClient); | |
180 | |
181 #define TEST_CLEAR_1(SHOULD_CLEAR, CALL1) \ | |
182 do { \ | |
183 TEST_CLEAR_SETUP \ | |
184 context.CALL1; \ | |
185 EXPECT_TRUE((SHOULD_CLEAR == gcClient.didClear())); \ | |
186 } while (0) | |
187 | |
188 #define TEST_CLEAR_2(SHOULD_CLEAR, CALL1, CALL2) \ | |
189 do { \ | |
190 TEST_CLEAR_SETUP \ | |
191 context.CALL1; \ | |
192 context.CALL2; \ | |
193 EXPECT_TRUE((SHOULD_CLEAR == gcClient.didClear())); \ | |
194 } while (0) | |
195 | |
196 #define TEST_CLEAR_3(SHOULD_CLEAR, CALL1, CALL2, CALL3) \ | |
197 do { \ | |
198 TEST_CLEAR_SETUP \ | |
199 context.CALL1; \ | |
200 context.CALL2; \ | |
201 context.CALL3; \ | |
202 EXPECT_TRUE((SHOULD_CLEAR == gcClient.didClear())); \ | |
203 } while (0) | |
204 | |
205 class TestGraphicsContextClient : public blink::GraphicsContextClient { | |
206 public: | |
207 TestGraphicsContextClient() : m_didClear(false) { } | |
208 bool didClear() { return m_didClear; } | |
209 | |
210 protected: | |
211 virtual void willOverwriteCanvas() { m_didClear = true; } | |
212 | |
213 private: | |
214 bool m_didClear; | |
215 }; | |
216 | |
217 enum BitmapOpacity { | |
218 OpaqueBitmap, | |
219 TransparentBitmap | |
220 }; | |
221 | |
222 static SkBitmap createTestBitmap(BitmapOpacity opacity) | |
223 { | |
224 SkBitmap bitmap; | |
225 SkColor color = opacity == OpaqueBitmap ? SK_ColorWHITE : SK_ColorTRANSPAREN
T; | |
226 bitmap.allocN32Pixels(10, 10, opacity == OpaqueBitmap); | |
227 for (int y = 0; y < bitmap.height(); ++y) | |
228 for (int x = 0; x < bitmap.width(); ++x) | |
229 *bitmap.getAddr32(x, y) = color; | |
230 return bitmap; | |
231 } | |
232 | |
233 TEST(GraphicsContextTest, detectClear) | |
234 { | |
235 SkRect fullRect = SkRect::MakeWH(10, 10); | |
236 SkPaint opaquePaint; | |
237 SkPaint alphaPaint; | |
238 alphaPaint.setAlpha(0x7F); | |
239 SkRect partialRect = SkRect::MakeWH(1, 1); | |
240 SkImageInfo opaqueImageInfo = SkImageInfo::MakeN32(10, 10, kOpaque_SkAlphaTy
pe); | |
241 SkImageInfo alphaImageInfo = SkImageInfo::MakeN32(10, 10, kPremul_SkAlphaTyp
e); | |
242 SkImageInfo smallImageInfo = SkImageInfo::MakeN32(1, 1, kOpaque_SkAlphaType)
; | |
243 | |
244 SkBitmap opaqueBitmap = createTestBitmap(OpaqueBitmap); | |
245 SkBitmap alphaBitmap = createTestBitmap(TransparentBitmap); | |
246 | |
247 SkAutoLockPixels alp(opaqueBitmap); | |
248 const void* imageData = opaqueBitmap.getAddr32(0, 0); | |
249 size_t imageRowBytes = opaqueBitmap.rowBytes(); | |
250 | |
251 // Test drawRect | |
252 TEST_CLEAR_1(true, drawRect(fullRect, opaquePaint)); | |
253 TEST_CLEAR_1(false, drawRect(fullRect, alphaPaint)); | |
254 TEST_CLEAR_1(false, drawRect(partialRect, opaquePaint)); | |
255 TEST_CLEAR_2(false, translate(1, 1), drawRect(fullRect, opaquePaint)); | |
256 | |
257 // Test drawBitmap | |
258 TEST_CLEAR_1(true, drawBitmap(opaqueBitmap, 0, 0, 0)); | |
259 TEST_CLEAR_1(true, drawBitmap(opaqueBitmap, 0, 0, &opaquePaint)); | |
260 TEST_CLEAR_1(true, drawBitmap(opaqueBitmap, 0, 0, &alphaPaint)); | |
261 TEST_CLEAR_1(false, drawBitmap(alphaBitmap, 0, 0, &opaquePaint)); | |
262 TEST_CLEAR_1(false, drawBitmap(alphaBitmap, 0, 0, &alphaPaint)); | |
263 TEST_CLEAR_1(false, drawBitmap(opaqueBitmap, 1, 0, 0)); | |
264 TEST_CLEAR_2(true, translate(-1, 0), drawBitmap(opaqueBitmap, 1, 0, 0)); | |
265 TEST_CLEAR_1(true, drawBitmapRect(opaqueBitmap, 0, fullRect, 0)); | |
266 TEST_CLEAR_1(true, drawBitmapRect(opaqueBitmap, &partialRect, fullRect, 0)); | |
267 TEST_CLEAR_1(false, drawBitmapRect(opaqueBitmap, 0, partialRect, 0)); | |
268 TEST_CLEAR_2(true, scale(10, 10), drawBitmapRect(opaqueBitmap, 0, partialRec
t, 0)); | |
269 | |
270 // Test writePixels | |
271 TEST_CLEAR_1(true, writePixels(opaqueImageInfo, imageData, imageRowBytes, 0,
0)); | |
272 TEST_CLEAR_1(true, writePixels(alphaImageInfo, imageData, imageRowBytes, 0,
0)); // alpha has no effect | |
273 TEST_CLEAR_1(false, writePixels(smallImageInfo, imageData, imageRowBytes, 0,
0)); | |
274 TEST_CLEAR_2(true, translate(1, 1), writePixels(opaqueImageInfo, imageData,
imageRowBytes, 0, 0)); // ignores tranforms | |
275 TEST_CLEAR_1(false, writePixels(opaqueImageInfo, imageData, imageRowBytes, 1
, 0)); | |
276 | |
277 // Test clipping | |
278 TEST_CLEAR_2(false, clipRect(partialRect), drawRect(fullRect, opaquePaint)); | |
279 } | |
280 | |
281 TEST(GraphicsContextTest, detectClearWithOpaquePaint) | |
282 { | |
283 // This test ensures that a draw that covers the canvas is detected as a cle
ar | |
284 // if its paint is opaque. | |
285 | |
286 SkRect fullRect = SkRect::MakeWH(10, 10); | |
287 | |
288 SkBitmap opaqueBitmap = createTestBitmap(OpaqueBitmap); | |
289 SkBitmap alphaBitmap = createTestBitmap(TransparentBitmap); | |
290 | |
291 SkAutoTUnref<SkShader> opaqueShader(SkShader::CreateBitmapShader(opaqueBitma
p, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode)); | |
292 | |
293 { | |
294 SkPaint paint; | |
295 paint.setStyle(SkPaint::kFill_Style); | |
296 TEST_CLEAR_1(true, drawRect(fullRect, paint)); | |
297 } | |
298 { | |
299 SkPaint paint; | |
300 paint.setStyle(SkPaint::kStrokeAndFill_Style); | |
301 TEST_CLEAR_1(true, drawRect(fullRect, paint)); | |
302 } | |
303 { | |
304 SkPaint paint; | |
305 paint.setShader(opaqueShader); | |
306 TEST_CLEAR_1(true, drawRect(fullRect, paint)); | |
307 } | |
308 { | |
309 SkPaint paint; | |
310 paint.setAlpha(0x7F); // shader overrides color | |
311 paint.setShader(opaqueShader); | |
312 TEST_CLEAR_1(true, drawRect(fullRect, paint)); | |
313 } | |
314 { | |
315 SkPaint paint; | |
316 paint.setShader(opaqueShader); // shader overrides the bitmap | |
317 TEST_CLEAR_1(true, drawBitmap(alphaBitmap, 0, 0, &paint)); | |
318 } | |
319 { | |
320 SkPaint paint; | |
321 paint.setAlpha(0); // bitmap overrides color | |
322 TEST_CLEAR_1(true, drawBitmap(opaqueBitmap, 0, 0, &paint)); | |
323 } | |
324 { | |
325 SkPaint paint; | |
326 paint.setAlpha(0x7F); | |
327 paint.setXfermodeMode(SkXfermode::kSrc_Mode); | |
328 TEST_CLEAR_1(true, drawRect(fullRect, paint)); | |
329 } | |
330 { | |
331 SkPaint paint; | |
332 paint.setAlpha(0x7F); | |
333 paint.setXfermodeMode(SkXfermode::kClear_Mode); | |
334 TEST_CLEAR_1(true, drawRect(fullRect, paint)); | |
335 } | |
336 } | |
337 | |
338 TEST(GraphicsContextTest, detectNoClearWithTransparentPaint) | |
339 { | |
340 // This test ensures that a draw that covers the canvas is never detected as
a clear | |
341 // if its paint has any properties that make it non-opaque | |
342 SkRect fullRect = SkRect::MakeWH(10, 10); | |
343 | |
344 SkBitmap opaqueBitmap = createTestBitmap(OpaqueBitmap); | |
345 SkBitmap alphaBitmap = createTestBitmap(TransparentBitmap); | |
346 | |
347 SkAutoTUnref<SkShader> alphaShader(SkShader::CreateBitmapShader(alphaBitmap,
SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode)); | |
348 | |
349 { | |
350 SkPaint paint; | |
351 paint.setStyle(SkPaint::kStroke_Style); | |
352 TEST_CLEAR_1(false, drawRect(fullRect, paint)); | |
353 } | |
354 { | |
355 SkPaint paint; | |
356 paint.setColor(SK_ColorTRANSPARENT); | |
357 TEST_CLEAR_1(false, drawRect(fullRect, paint)); | |
358 } | |
359 { | |
360 SkPaint paint; | |
361 paint.setShader(alphaShader); | |
362 TEST_CLEAR_1(false, drawRect(fullRect, paint)); | |
363 } | |
364 { | |
365 SkPaint paint; | |
366 paint.setShader(alphaShader); // shader overrides the bitmap. | |
367 TEST_CLEAR_1(false, drawBitmap(opaqueBitmap, 0, 0, &paint)); | |
368 } | |
369 for (int mode = SkXfermode::kDstOver_Mode; mode <= SkXfermode::kLastMode; mo
de++) { | |
370 SkPaint paint; | |
371 paint.setXfermodeMode(static_cast<SkXfermode::Mode>(mode)); | |
372 TEST_CLEAR_1(false, drawRect(fullRect, paint)); | |
373 } | |
374 { | |
375 SkPaint paint; | |
376 SkAutoTUnref<SkMaskFilter> filter(SkBlurMaskFilter::Create(kNormal_SkBlu
rStyle, 1)); | |
377 paint.setMaskFilter(filter.get()); | |
378 TEST_CLEAR_1(false, drawRect(fullRect, paint)); | |
379 } | |
380 { | |
381 SkPaint paint; | |
382 SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(1, 1)); | |
383 paint.setImageFilter(filter.get()); | |
384 TEST_CLEAR_1(false, drawRect(fullRect, paint)); | |
385 } | |
386 { | |
387 SkPaint paint; | |
388 SkAutoTUnref<SkDrawLooper> looper(SkBlurDrawLooper::Create(SK_ColorWHITE
, 1, 1, 1)); | |
389 paint.setLooper(looper.get()); | |
390 TEST_CLEAR_1(false, drawRect(fullRect, paint)); | |
391 } | |
392 { | |
393 SkPaint paint; | |
394 TEST_CLEAR_3(false, beginLayer(1.0f, SkXfermode::kSrcOver_Mode), drawRec
t(fullRect, paint), endLayer()); | |
395 } | |
396 } | |
397 | |
398 TEST(GraphicsContextTest, UnboundedDrawsAreClipped) | 171 TEST(GraphicsContextTest, UnboundedDrawsAreClipped) |
399 { | 172 { |
400 SkBitmap bitmap; | 173 SkBitmap bitmap; |
401 bitmap.allocN32Pixels(400, 400); | 174 bitmap.allocN32Pixels(400, 400); |
402 bitmap.eraseColor(0); | 175 bitmap.eraseColor(0); |
403 SkCanvas canvas(bitmap); | 176 SkCanvas canvas(bitmap); |
404 | 177 |
405 GraphicsContext context(&canvas, nullptr); | 178 GraphicsContext context(&canvas, nullptr); |
406 | 179 |
407 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); | 180 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 | 272 |
500 // endRecording finally makes the picture accessible | 273 // endRecording finally makes the picture accessible |
501 RefPtr<const SkPicture> picture = context.endRecording(); | 274 RefPtr<const SkPicture> picture = context.endRecording(); |
502 EXPECT_TRUE(picture); | 275 EXPECT_TRUE(picture); |
503 EXPECT_TRUE(picture->unique()); | 276 EXPECT_TRUE(picture->unique()); |
504 | 277 |
505 context.endRecording(); | 278 context.endRecording(); |
506 } | 279 } |
507 | 280 |
508 } // namespace | 281 } // namespace |
OLD | NEW |