| 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 |