1 /* 2 * Copyright (C) 2012 Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 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 ANY 17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 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 ON 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 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25 #include "config.h" 26 27 #include "platform/graphics/GraphicsContext.h" 28 29 #include "platform/graphics/BitmapImage.h" 30 #include "platform/graphics/DisplayList.h" 31 #include "platform/graphics/ImageBuffer.h" 32 #include "platform/graphics/skia/NativeImageSkia.h" 33 #include "third_party/skia/include/core/SkBitmap.h" 34 #include "third_party/skia/include/core/SkCanvas.h" 35 #include "third_party/skia/include/core/SkPicture.h" 36 #include <gtest/gtest.h> 37 38 using namespace WebCore; 39 40 namespace { 41 42 #define EXPECT_EQ_RECT(a, b) \ 43 EXPECT_EQ(a.x(), b.x()); \ 44 EXPECT_EQ(a.y(), b.y()); \ 45 EXPECT_EQ(a.width(), b.width()); \ 46 EXPECT_EQ(a.height(), b.height()); 47 48 #define EXPECT_PIXELS_MATCH(bitmap, opaqueRect) \ 49 { \ 50 SkAutoLockPixels locker(bitmap); \ 51 for (int y = opaqueRect.y(); y < opaqueRect.maxY(); ++y) \ 52 for (int x = opaqueRect.x(); x < opaqueRect.maxX(); ++x) { \ 53 int alpha = *bitmap.getAddr32(x, y) >> 24; \ 54 EXPECT_EQ(255, alpha); \ 55 } \ 56 } 57 58 #define EXPECT_PIXELS_MATCH_EXACT(bitmap, opaqueRect) \ 59 { \ 60 SkAutoLockPixels locker(bitmap); \ 61 for (int y = 0; y < bitmap.height(); ++y) \ 62 for (int x = 0; x < bitmap.width(); ++x) { \ 63 int alpha = *bitmap.getAddr32(x, y) >> 24; \ 64 bool opaque = opaqueRect.contains(x, y); \ 65 EXPECT_EQ(opaque, alpha == 255); \ 66 } \ 67 } 68 69 TEST(GraphicsContextTest, trackOpaqueTest) 70 { 71 SkBitmap bitmap; 72 ASSERT_TRUE(bitmap.allocN32Pixels(400, 400)); 73 bitmap.eraseColor(0); 74 SkCanvas canvas(bitmap); 75 76 GraphicsContext context(&canvas); 77 context.setTrackOpaqueRegion(true); 78 79 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 80 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 81 82 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 83 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 84 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 85 86 context.fillRect(FloatRect(10, 10, 90, 90), alpha, CompositeSourceOver); 87 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 88 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 89 90 context.fillRect(FloatRect(99, 13, 10, 90), opaque, CompositePlusLighter); 91 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 92 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 93 94 context.fillRect(FloatRect(99, 13, 10, 90), opaque, CompositeSourceIn); 95 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 96 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 97 98 context.fillRect(FloatRect(99, 13, 10, 90), alpha, CompositeSourceIn); 99 EXPECT_EQ_RECT(IntRect(10, 10, 89, 90), context.opaqueRegion().asRect()); 100 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 101 102 context.fillRect(FloatRect(8, 8, 3, 90), opaque, CompositeSourceOut); 103 EXPECT_EQ_RECT(IntRect(11, 10, 88, 90), context.opaqueRegion().asRect()); 104 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 105 106 context.fillRect(FloatRect(30, 30, 290, 290), opaque, CompositeSourceOver); 107 EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), context.opaqueRegion().asRect()); 108 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 109 110 context.fillRect(FloatRect(40, 20, 290, 50), opaque, CompositeSourceOver); 111 EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), context.opaqueRegion().asRect()); 112 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 113 114 context.fillRect(FloatRect(10, 10, 390, 50), opaque, CompositeSourceIn); 115 EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), context.opaqueRegion().asRect()); 116 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 117 118 context.fillRect(FloatRect(10, 10, 390, 50), alpha); 119 EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), context.opaqueRegion().asRect()); 120 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 121 122 context.fillRect(FloatRect(10, 10, 390, 50), opaque, CompositeSourceOver); 123 EXPECT_EQ_RECT(IntRect(30, 10, 290, 310), context.opaqueRegion().asRect()); 124 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 125 } 126 127 TEST(GraphicsContextTest, trackOpaqueClipTest) 128 { 129 SkBitmap bitmap; 130 ASSERT_TRUE(bitmap.allocN32Pixels(400, 400)); 131 SkCanvas canvas(bitmap); 132 133 GraphicsContext context(&canvas); 134 context.setTrackOpaqueRegion(true); 135 136 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 137 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 138 139 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 140 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 141 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 142 143 context.clearRect(FloatRect(10, 10, 90, 90)); 144 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 145 146 context.save(); 147 context.clip(FloatRect(0, 0, 10, 10)); 148 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 149 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 150 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 151 context.restore(); 152 153 context.clearRect(FloatRect(10, 10, 90, 90)); 154 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 155 156 context.save(); 157 context.clip(FloatRect(20, 20, 10, 10)); 158 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 159 EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect()); 160 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 161 162 context.clearRect(FloatRect(10, 10, 90, 90)); 163 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 164 165 // The intersection of the two clips becomes empty. 166 context.clip(FloatRect(30, 20, 10, 10)); 167 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 168 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 169 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 170 context.restore(); 171 172 context.clearRect(FloatRect(10, 10, 90, 90)); 173 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 174 175 // The transform and the clip need to interact correctly (transform first) 176 context.save(); 177 context.translate(10, 10); 178 context.clip(FloatRect(20, 20, 10, 10)); 179 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 180 EXPECT_EQ_RECT(IntRect(30, 30, 10, 10), context.opaqueRegion().asRect()); 181 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 182 context.restore(); 183 184 context.clearRect(FloatRect(10, 10, 90, 90)); 185 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 186 187 // The transform and the clip need to interact correctly (clip first) 188 context.save(); 189 context.clip(FloatRect(20, 20, 10, 10)); 190 context.translate(10, 10); 191 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 192 EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect()); 193 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 194 context.restore(); 195 196 context.clearRect(FloatRect(10, 10, 90, 90)); 197 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 198 199 Path path; 200 path.moveTo(FloatPoint(0, 0)); 201 path.addLineTo(FloatPoint(100, 0)); 202 203 // Non-rectangular clips just cause the paint to be considered non-opaque. 204 context.save(); 205 context.clipPath(path, RULE_EVENODD); 206 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 207 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 208 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 209 context.restore(); 210 211 // Another non-rectangular clip. 212 context.save(); 213 context.clip(IntRect(30, 30, 20, 20)); 214 context.clipOut(IntRect(30, 30, 10, 10)); 215 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 216 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 217 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 218 context.restore(); 219 } 220 221 TEST(GraphicsContextTest, trackImageMask) 222 { 223 SkBitmap bitmap; 224 ASSERT_TRUE(bitmap.allocN32Pixels(400, 400)); 225 bitmap.eraseColor(0); 226 SkCanvas canvas(bitmap); 227 228 GraphicsContext context(&canvas); 229 context.setTrackOpaqueRegion(true); 230 231 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 232 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 233 234 // Image masks are done by drawing a bitmap into a transparency layer that uses DstIn to mask 235 // out a transparency layer below that is filled with the mask color. In the end this should 236 // not be marked opaque. 237 238 context.setCompositeOperation(CompositeSourceOver); 239 context.beginTransparencyLayer(1); 240 context.fillRect(FloatRect(10, 10, 10, 10), opaque, CompositeSourceOver); 241 242 context.setCompositeOperation(CompositeDestinationIn); 243 context.beginTransparencyLayer(1); 244 245 OwnPtr<ImageBuffer> alphaImage = ImageBuffer::create(IntSize(100, 100)); 246 alphaImage->context()->fillRect(IntRect(0, 0, 100, 100), alpha); 247 248 context.setCompositeOperation(CompositeSourceOver); 249 context.drawImageBuffer(alphaImage.get(), FloatRect(10, 10, 10, 10)); 250 251 context.endLayer(); 252 context.endLayer(); 253 254 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 255 EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect()); 256 } 257 258 TEST(GraphicsContextTest, trackImageMaskWithOpaqueRect) 259 { 260 SkBitmap bitmap; 261 ASSERT_TRUE(bitmap.allocN32Pixels(400, 400)); 262 bitmap.eraseColor(0); 263 SkCanvas canvas(bitmap); 264 265 GraphicsContext context(&canvas); 266 context.setTrackOpaqueRegion(true); 267 268 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 269 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 270 271 // Image masks are done by drawing a bitmap into a transparency layer that uses DstIn to mask 272 // out a transparency layer below that is filled with the mask color. In the end this should 273 // not be marked opaque. 274 275 context.setCompositeOperation(CompositeSourceOver); 276 context.beginTransparencyLayer(1); 277 context.fillRect(FloatRect(10, 10, 10, 10), opaque, CompositeSourceOver); 278 279 context.setCompositeOperation(CompositeDestinationIn); 280 context.beginTransparencyLayer(1); 281 282 OwnPtr<ImageBuffer> alphaImage = ImageBuffer::create(IntSize(100, 100)); 283 alphaImage->context()->fillRect(IntRect(0, 0, 100, 100), alpha); 284 285 context.setCompositeOperation(CompositeSourceOver); 286 context.drawImageBuffer(alphaImage.get(), FloatRect(10, 10, 10, 10)); 287 288 // We can't have an opaque mask actually, but we can pretend here like it would look if we did. 289 context.fillRect(FloatRect(12, 12, 3, 3), opaque, CompositeSourceOver); 290 291 context.endLayer(); 292 context.endLayer(); 293 294 EXPECT_EQ_RECT(IntRect(12, 12, 3, 3), context.opaqueRegion().asRect()); 295 EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect()); 296 } 297 298 TEST(GraphicsContextTest, trackOpaqueJoinTest) 299 { 300 SkBitmap bitmap; 301 ASSERT_TRUE(bitmap.allocN32Pixels(400, 400)); 302 SkCanvas canvas(bitmap); 303 304 GraphicsContext context(&canvas); 305 context.setTrackOpaqueRegion(true); 306 307 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 308 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 309 310 context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver); 311 EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect()); 312 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 313 314 // Doesn't join 315 context.fillRect(FloatRect(31, 20, 10, 10), opaque, CompositeSourceOver); 316 EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect()); 317 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 318 319 // Does join 320 context.fillRect(FloatRect(30, 20, 10, 10), opaque, CompositeSourceOver); 321 EXPECT_EQ_RECT(IntRect(20, 20, 20, 10), context.opaqueRegion().asRect()); 322 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 323 324 // Doesn't join 325 context.fillRect(FloatRect(20, 31, 20, 10), opaque, CompositeSourceOver); 326 EXPECT_EQ_RECT(IntRect(20, 20, 20, 10), context.opaqueRegion().asRect()); 327 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 328 329 // Does join 330 context.fillRect(FloatRect(20, 30, 20, 10), opaque, CompositeSourceOver); 331 EXPECT_EQ_RECT(IntRect(20, 20, 20, 20), context.opaqueRegion().asRect()); 332 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 333 334 // Doesn't join 335 context.fillRect(FloatRect(9, 20, 10, 20), opaque, CompositeSourceOver); 336 EXPECT_EQ_RECT(IntRect(20, 20, 20, 20), context.opaqueRegion().asRect()); 337 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 338 339 // Does join 340 context.fillRect(FloatRect(10, 20, 10, 20), opaque, CompositeSourceOver); 341 EXPECT_EQ_RECT(IntRect(10, 20, 30, 20), context.opaqueRegion().asRect()); 342 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 343 344 // Doesn't join 345 context.fillRect(FloatRect(10, 9, 30, 10), opaque, CompositeSourceOver); 346 EXPECT_EQ_RECT(IntRect(10, 20, 30, 20), context.opaqueRegion().asRect()); 347 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 348 349 // Does join 350 context.fillRect(FloatRect(10, 10, 30, 10), opaque, CompositeSourceOver); 351 EXPECT_EQ_RECT(IntRect(10, 10, 30, 30), context.opaqueRegion().asRect()); 352 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 353 } 354 355 TEST(GraphicsContextTest, trackOpaqueLineTest) 356 { 357 SkBitmap bitmap; 358 ASSERT_TRUE(bitmap.allocN32Pixels(200, 200)); 359 bitmap.eraseColor(0); 360 SkCanvas canvas(bitmap); 361 362 GraphicsContext context(&canvas); 363 context.setTrackOpaqueRegion(true); 364 365 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 366 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 367 368 context.setShouldAntialias(false); 369 context.setMiterLimit(0); 370 context.setStrokeThickness(4); 371 context.setLineCap(SquareCap); 372 context.setStrokeStyle(SolidStroke); 373 context.setCompositeOperation(CompositeSourceOver); 374 375 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 376 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 377 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 378 379 context.setCompositeOperation(CompositeSourceIn); 380 381 context.save(); 382 context.setStrokeColor(alpha); 383 context.drawLine(IntPoint(0, 0), IntPoint(100, 0)); 384 context.restore(); 385 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 386 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 387 388 context.save(); 389 context.setStrokeColor(opaque); 390 context.drawLine(IntPoint(0, 10), IntPoint(100, 10)); 391 context.restore(); 392 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 393 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 394 395 context.save(); 396 context.setStrokeColor(alpha); 397 context.drawLine(IntPoint(0, 10), IntPoint(100, 10)); 398 context.restore(); 399 EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect()); 400 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 401 402 context.save(); 403 context.setStrokeColor(alpha); 404 context.drawLine(IntPoint(0, 11), IntPoint(100, 11)); 405 context.restore(); 406 EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect()); 407 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 408 409 context.setShouldAntialias(true); 410 context.setCompositeOperation(CompositeSourceOver); 411 412 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 413 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 414 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 415 416 context.setCompositeOperation(CompositeSourceIn); 417 418 context.save(); 419 context.setStrokeColor(alpha); 420 context.drawLine(IntPoint(0, 0), IntPoint(100, 0)); 421 context.restore(); 422 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 423 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 424 425 context.setShouldAntialias(false); 426 context.save(); 427 context.setStrokeColor(opaque); 428 context.drawLine(IntPoint(0, 10), IntPoint(100, 10)); 429 context.restore(); 430 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 431 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 432 433 context.setShouldAntialias(true); 434 context.save(); 435 context.setStrokeColor(opaque); 436 context.drawLine(IntPoint(0, 10), IntPoint(100, 10)); 437 context.restore(); 438 EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect()); 439 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 440 441 context.save(); 442 context.setStrokeColor(alpha); 443 context.drawLine(IntPoint(0, 11), IntPoint(100, 11)); 444 context.restore(); 445 EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect()); 446 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 447 } 448 449 TEST(GraphicsContextTest, trackOpaquePathTest) 450 { 451 SkBitmap bitmap; 452 ASSERT_TRUE(bitmap.allocN32Pixels(200, 200)); 453 SkCanvas canvas(bitmap); 454 455 GraphicsContext context(&canvas); 456 context.setTrackOpaqueRegion(true); 457 458 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 459 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 460 461 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 462 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 463 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 464 465 context.setShouldAntialias(false); 466 context.setMiterLimit(1); 467 context.setStrokeThickness(5); 468 context.setLineCap(SquareCap); 469 context.setStrokeStyle(SolidStroke); 470 context.setCompositeOperation(CompositeSourceIn); 471 472 Path path; 473 474 context.setFillColor(alpha); 475 path.moveTo(FloatPoint(0, 0)); 476 path.addLineTo(FloatPoint(100, 0)); 477 context.fillPath(path); 478 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 479 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 480 path.clear(); 481 482 context.setFillColor(opaque); 483 path.moveTo(FloatPoint(0, 10)); 484 path.addLineTo(FloatPoint(100, 13)); 485 context.fillPath(path); 486 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 487 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 488 path.clear(); 489 490 context.setFillColor(alpha); 491 path.moveTo(FloatPoint(0, 10)); 492 path.addLineTo(FloatPoint(100, 13)); 493 context.fillPath(path); 494 EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect()); 495 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 496 path.clear(); 497 498 context.setFillColor(alpha); 499 path.moveTo(FloatPoint(0, 14)); 500 path.addLineTo(FloatPoint(100, 10)); 501 context.fillPath(path); 502 EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect()); 503 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 504 path.clear(); 505 } 506 507 TEST(GraphicsContextTest, trackOpaqueImageTest) 508 { 509 SkBitmap bitmap; 510 ASSERT_TRUE(bitmap.allocN32Pixels(200, 200)); 511 SkCanvas canvas(bitmap); 512 513 GraphicsContext context(&canvas); 514 context.setTrackOpaqueRegion(true); 515 516 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 517 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 518 519 SkBitmap opaqueBitmap; 520 ASSERT_TRUE(opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */)); 521 522 for (int y = 0; y < opaqueBitmap.height(); ++y) 523 for (int x = 0; x < opaqueBitmap.width(); ++x) 524 *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF; 525 RefPtr<BitmapImage> opaqueImage = BitmapImage::create(NativeImageSkia::create(opaqueBitmap)); 526 EXPECT_TRUE(opaqueImage->currentFrameKnownToBeOpaque()); 527 528 SkBitmap alphaBitmap; 529 ASSERT_TRUE(alphaBitmap.allocN32Pixels(10, 10)); 530 531 for (int y = 0; y < alphaBitmap.height(); ++y) 532 for (int x = 0; x < alphaBitmap.width(); ++x) 533 *alphaBitmap.getAddr32(x, y) = 0x00000000; 534 RefPtr<BitmapImage> alphaImage = BitmapImage::create(NativeImageSkia::create(alphaBitmap)); 535 EXPECT_FALSE(alphaImage->currentFrameKnownToBeOpaque()); 536 537 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 538 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 539 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 540 541 context.drawImage(opaqueImage.get(), IntPoint(0, 0)); 542 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 543 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 544 context.drawImage(alphaImage.get(), IntPoint(0, 0)); 545 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 546 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 547 548 context.drawImage(opaqueImage.get(), IntPoint(5, 5)); 549 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 550 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 551 context.drawImage(alphaImage.get(), IntPoint(5, 5)); 552 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 553 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 554 555 context.drawImage(opaqueImage.get(), IntPoint(10, 10)); 556 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 557 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 558 context.drawImage(alphaImage.get(), IntPoint(10, 10)); 559 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 560 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 561 562 context.drawImage(alphaImage.get(), IntPoint(20, 10), CompositeSourceIn); 563 EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), context.opaqueRegion().asRect()); 564 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 565 566 context.save(); 567 context.setAlphaAsFloat(0.5); 568 context.drawImage(opaqueImage.get(), IntPoint(25, 15), CompositeSourceIn); 569 context.restore(); 570 EXPECT_EQ_RECT(IntRect(10, 25, 90, 75), context.opaqueRegion().asRect()); 571 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 572 573 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 574 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 575 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 576 577 context.drawImage(alphaImage.get(), IntPoint(10, 20), CompositeSourceIn); 578 EXPECT_EQ_RECT(IntRect(20, 10, 80, 90), context.opaqueRegion().asRect()); 579 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 580 581 context.save(); 582 context.setAlphaAsFloat(0.5); 583 context.drawImage(opaqueImage.get(), IntPoint(15, 25), CompositeSourceIn); 584 context.restore(); 585 EXPECT_EQ_RECT(IntRect(25, 10, 75, 90), context.opaqueRegion().asRect()); 586 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 587 } 588 589 TEST(GraphicsContextTest, trackOpaqueOvalTest) 590 { 591 SkBitmap bitmap; 592 ASSERT_TRUE(bitmap.allocN32Pixels(200, 200)); 593 bitmap.eraseColor(0); 594 SkCanvas canvas(bitmap); 595 596 GraphicsContext context(&canvas); 597 context.setTrackOpaqueRegion(true); 598 599 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 600 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 601 602 EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect()); 603 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 604 605 context.fillEllipse(FloatRect(10, 10, 90, 90)); 606 context.strokeEllipse(FloatRect(10, 10, 90, 90)); 607 EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect()); 608 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 609 610 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 611 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 612 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 613 614 context.setCompositeOperation(CompositeSourceIn); 615 616 context.setShouldAntialias(false); 617 618 context.setFillColor(opaque); 619 context.fillEllipse(FloatRect(10, 10, 50, 30)); 620 context.strokeEllipse(FloatRect(10, 10, 50, 30)); 621 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 622 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 623 624 context.setFillColor(alpha); 625 context.fillEllipse(FloatRect(10, 10, 30, 50)); 626 context.strokeEllipse(FloatRect(10, 10, 30, 50)); 627 EXPECT_EQ_RECT(IntRect(40, 10, 60, 90), context.opaqueRegion().asRect()); 628 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 629 630 context.setShouldAntialias(true); 631 632 context.setFillColor(opaque); 633 context.fillEllipse(FloatRect(10, 10, 50, 30)); 634 context.strokeEllipse(FloatRect(10, 10, 50, 30)); 635 EXPECT_EQ_RECT(IntRect(40, 41, 60, 59), context.opaqueRegion().asRect()); 636 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 637 638 context.setFillColor(alpha); 639 context.fillEllipse(FloatRect(20, 10, 30, 50)); 640 context.strokeEllipse(FloatRect(20, 10, 30, 50)); 641 EXPECT_EQ_RECT(IntRect(51, 41, 49, 59), context.opaqueRegion().asRect()); 642 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 643 } 644 645 TEST(GraphicsContextTest, trackOpaqueRoundedRectTest) 646 { 647 SkBitmap bitmap; 648 ASSERT_TRUE(bitmap.allocN32Pixels(200, 200)); 649 SkCanvas canvas(bitmap); 650 651 GraphicsContext context(&canvas); 652 context.setTrackOpaqueRegion(true); 653 654 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 655 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 656 IntSize radii(10, 10); 657 658 EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect()); 659 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 660 661 context.fillRoundedRect(IntRect(10, 10, 90, 90), radii, radii, radii, radii, opaque); 662 EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect()); 663 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 664 665 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 666 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 667 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 668 669 context.setCompositeOperation(CompositeSourceIn); 670 context.setShouldAntialias(false); 671 672 context.fillRoundedRect(IntRect(10, 10, 50, 30), radii, radii, radii, radii, opaque); 673 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 674 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 675 676 context.fillRoundedRect(IntRect(10, 10, 30, 50), radii, radii, radii, radii, alpha); 677 EXPECT_EQ_RECT(IntRect(40, 10, 60, 90), context.opaqueRegion().asRect()); 678 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 679 680 context.fillRoundedRect(IntRect(10, 0, 50, 30), radii, radii, radii, radii, alpha); 681 EXPECT_EQ_RECT(IntRect(40, 30, 60, 70), context.opaqueRegion().asRect()); 682 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 683 684 context.fillRoundedRect(IntRect(30, 0, 70, 50), radii, radii, radii, radii, opaque); 685 EXPECT_EQ_RECT(IntRect(40, 30, 60, 70), context.opaqueRegion().asRect()); 686 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 687 } 688 689 TEST(GraphicsContextTest, trackOpaqueTextTest) 690 { 691 int width = 200, height = 200; 692 SkBitmap bitmap; 693 ASSERT_TRUE(bitmap.allocN32Pixels(width, height)); 694 bitmap.eraseColor(0); 695 SkCanvas canvas(bitmap); 696 SkRect textRect = SkRect::MakeWH(width, height); 697 698 GraphicsContext context(&canvas); 699 context.setTrackOpaqueRegion(true); 700 701 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 702 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 703 704 SkPaint opaquePaint; 705 opaquePaint.setColor(opaque.rgb()); 706 opaquePaint.setXfermodeMode(SkXfermode::kSrc_Mode); 707 SkPaint alphaPaint; 708 alphaPaint.setColor(alpha.rgb()); 709 alphaPaint.setXfermodeMode(SkXfermode::kSrc_Mode); 710 711 SkPoint point = SkPoint::Make(0, 0); 712 713 context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver); 714 EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect()); 715 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 716 717 context.drawPosText("A", 1, &point, textRect, opaquePaint); 718 EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect()); 719 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 720 721 context.drawPosText("A", 1, &point, textRect, alphaPaint); 722 EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect()); 723 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 724 725 context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver); 726 EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect()); 727 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 728 729 context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver); 730 EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect()); 731 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 732 } 733 734 TEST(GraphicsContextTest, trackOpaqueWritePixelsTest) 735 { 736 SkBitmap bitmap; 737 ASSERT_TRUE(bitmap.allocN32Pixels(200, 200)); 738 bitmap.eraseColor(0); 739 SkCanvas canvas(bitmap); 740 741 GraphicsContext context(&canvas); 742 context.setTrackOpaqueRegion(true); 743 744 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 745 746 SkBitmap opaqueBitmap; 747 ASSERT_TRUE(opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */)); 748 for (int y = 0; y < opaqueBitmap.height(); ++y) 749 for (int x = 0; x < opaqueBitmap.width(); ++x) 750 *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF; 751 752 SkBitmap alphaBitmap; 753 ASSERT_TRUE(alphaBitmap.allocN32Pixels(10, 10)); 754 for (int y = 0; y < alphaBitmap.height(); ++y) 755 for (int x = 0; x < alphaBitmap.width(); ++x) 756 *alphaBitmap.getAddr32(x, y) = 0x00000000; 757 758 SkPaint paint; 759 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 760 761 context.writePixels(opaqueBitmap, 50, 50); 762 EXPECT_EQ_RECT(IntRect(50, 50, 10, 10), context.opaqueRegion().asRect()); 763 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 764 765 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 766 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 767 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 768 769 context.writePixels(alphaBitmap, 10, 0); 770 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 771 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 772 773 context.writePixels(alphaBitmap, 10, 1); 774 EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect()); 775 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 776 777 context.writePixels(alphaBitmap, 0, 10); 778 EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect()); 779 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 780 781 context.writePixels(alphaBitmap, 1, 10); 782 EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect()); 783 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 784 } 785 786 TEST(GraphicsContextTest, trackOpaqueDrawBitmapTest) 787 { 788 SkBitmap bitmap; 789 ASSERT_TRUE(bitmap.allocN32Pixels(200, 200)); 790 bitmap.eraseColor(0); 791 SkCanvas canvas(bitmap); 792 793 GraphicsContext context(&canvas); 794 context.setTrackOpaqueRegion(true); 795 796 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 797 798 SkBitmap opaqueBitmap; 799 ASSERT_TRUE(opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */)); 800 for (int y = 0; y < opaqueBitmap.height(); ++y) 801 for (int x = 0; x < opaqueBitmap.width(); ++x) 802 *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF; 803 804 SkBitmap alphaBitmap; 805 ASSERT_TRUE(alphaBitmap.allocN32Pixels(10, 10)); 806 for (int y = 0; y < alphaBitmap.height(); ++y) 807 for (int x = 0; x < alphaBitmap.width(); ++x) 808 *alphaBitmap.getAddr32(x, y) = 0x00000000; 809 810 SkPaint paint; 811 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 812 813 context.drawBitmap(opaqueBitmap, 10, 10, &paint); 814 EXPECT_EQ_RECT(IntRect(10, 10, 10, 10), context.opaqueRegion().asRect()); 815 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 816 817 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 818 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 819 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 820 821 context.drawBitmap(alphaBitmap, 10, 0, &paint); 822 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 823 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 824 825 context.drawBitmap(alphaBitmap, 10, 1, &paint); 826 EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect()); 827 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 828 829 context.drawBitmap(alphaBitmap, 0, 10, &paint); 830 EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect()); 831 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 832 833 context.drawBitmap(alphaBitmap, 1, 10, &paint); 834 EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect()); 835 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 836 } 837 838 TEST(GraphicsContextTest, trackOpaqueDrawBitmapRectTest) 839 { 840 SkBitmap bitmap; 841 ASSERT_TRUE(bitmap.allocN32Pixels(200, 200)); 842 bitmap.eraseColor(0); 843 SkCanvas canvas(bitmap); 844 845 GraphicsContext context(&canvas); 846 context.setTrackOpaqueRegion(true); 847 848 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 849 850 SkBitmap opaqueBitmap; 851 ASSERT_TRUE(opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */)); 852 for (int y = 0; y < opaqueBitmap.height(); ++y) 853 for (int x = 0; x < opaqueBitmap.width(); ++x) 854 *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF; 855 856 SkBitmap alphaBitmap; 857 ASSERT_TRUE(alphaBitmap.allocN32Pixels(10, 10)); 858 for (int y = 0; y < alphaBitmap.height(); ++y) 859 for (int x = 0; x < alphaBitmap.width(); ++x) 860 *alphaBitmap.getAddr32(x, y) = 0x00000000; 861 862 SkPaint paint; 863 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 864 865 context.drawBitmapRect(opaqueBitmap, 0, SkRect::MakeXYWH(10, 10, 90, 90), &paint); 866 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 867 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 868 869 context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(10, 0, 10, 10), &paint); 870 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 871 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 872 873 context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(10, 0, 10, 11), &paint); 874 EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect()); 875 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 876 877 context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(0, 10, 10, 10), &paint); 878 EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect()); 879 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 880 881 context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(0, 10, 11, 10), &paint); 882 EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect()); 883 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 884 } 885 886 TEST(GraphicsContextTest, contextTransparencyLayerTest) 887 { 888 SkBitmap bitmap; 889 ASSERT_TRUE(bitmap.allocN32Pixels(400, 400)); 890 bitmap.eraseColor(0); 891 SkCanvas canvas(bitmap); 892 893 GraphicsContext context(&canvas); 894 context.setTrackOpaqueRegion(true); 895 896 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 897 context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver); 898 EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect()); 899 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 900 901 context.clearRect(FloatRect(20, 20, 10, 10)); 902 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 903 904 context.beginTransparencyLayer(0.5); 905 context.save(); 906 context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver); 907 context.restore(); 908 context.endLayer(); 909 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 910 911 context.clearRect(FloatRect(20, 20, 10, 10)); 912 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 913 914 context.beginTransparencyLayer(0.5); 915 context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver); 916 context.endLayer(); 917 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 918 } 919 920 TEST(GraphicsContextTest, UnboundedDrawsAreClipped) 921 { 922 SkBitmap bitmap; 923 ASSERT_TRUE(bitmap.allocN32Pixels(400, 400)); 924 bitmap.eraseColor(0); 925 SkCanvas canvas(bitmap); 926 927 GraphicsContext context(&canvas); 928 context.setTrackOpaqueRegion(true); 929 930 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 931 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 932 933 Path path; 934 context.setShouldAntialias(false); 935 context.setMiterLimit(1); 936 context.setStrokeThickness(5); 937 context.setLineCap(SquareCap); 938 context.setStrokeStyle(SolidStroke); 939 940 // Make skia unable to compute fast bounds for our paths. 941 DashArray dashArray; 942 dashArray.append(1); 943 dashArray.append(0); 944 context.setLineDash(dashArray, 0); 945 946 // Make the device opaque in 10,10 40x40. 947 context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver); 948 EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect()); 949 EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect()); 950 951 // Clip to the left edge of the opaque area. 952 context.clip(IntRect(10, 10, 10, 40)); 953 954 // Draw a path that gets clipped. This should destroy the opaque area but only inside the clip. 955 context.setCompositeOperation(CompositeSourceOut); 956 context.setFillColor(alpha); 957 path.moveTo(FloatPoint(10, 10)); 958 path.addLineTo(FloatPoint(40, 40)); 959 context.strokePath(path); 960 961 EXPECT_EQ_RECT(IntRect(20, 10, 30, 40), context.opaqueRegion().asRect()); 962 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 963 } 964 965 TEST(GraphicsContextTest, PreserveOpaqueOnlyMattersForFirstLayer) 966 { 967 SkBitmap bitmap; 968 ASSERT_TRUE(bitmap.allocN32Pixels(400, 400)); 969 bitmap.eraseColor(0); 970 SkCanvas canvas(bitmap); 971 972 GraphicsContext context(&canvas); 973 context.setTrackOpaqueRegion(true); 974 975 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 976 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 977 978 Path path; 979 context.setShouldAntialias(false); 980 context.setMiterLimit(1); 981 context.setStrokeThickness(5); 982 context.setLineCap(SquareCap); 983 context.setStrokeStyle(SolidStroke); 984 985 // Make skia unable to compute fast bounds for our paths. 986 DashArray dashArray; 987 dashArray.append(1); 988 dashArray.append(0); 989 context.setLineDash(dashArray, 0); 990 991 // Make the device opaque in 10,10 40x40. 992 context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver); 993 EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect()); 994 EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect()); 995 996 // Begin a layer that preserves opaque. 997 context.setCompositeOperation(CompositeSourceOver); 998 context.beginTransparencyLayer(0.5); 999 1000 // Begin a layer that does not preserve opaque. 1001 context.setCompositeOperation(CompositeSourceOut); 1002 context.beginTransparencyLayer(0.5); 1003 1004 // This should not destroy the device opaqueness. 1005 context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver); 1006 1007 // This should not destroy the device opaqueness either. 1008 context.setFillColor(opaque); 1009 path.moveTo(FloatPoint(10, 10)); 1010 path.addLineTo(FloatPoint(40, 40)); 1011 context.strokePath(path); 1012 1013 context.endLayer(); 1014 context.endLayer(); 1015 EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect()); 1016 EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect()); 1017 1018 // Now begin a layer that does not preserve opaque and draw through it to the device. 1019 context.setCompositeOperation(CompositeSourceOut); 1020 context.beginTransparencyLayer(0.5); 1021 1022 // This should destroy the device opaqueness. 1023 context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver); 1024 1025 context.endLayer(); 1026 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 1027 EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect()); 1028 1029 // Now we draw with a path for which it cannot compute fast bounds. This should destroy the entire opaque region. 1030 1031 context.setCompositeOperation(CompositeSourceOut); 1032 context.beginTransparencyLayer(0.5); 1033 1034 // This should nuke the device opaqueness. 1035 context.setFillColor(opaque); 1036 path.moveTo(FloatPoint(10, 10)); 1037 path.addLineTo(FloatPoint(40, 40)); 1038 context.strokePath(path); 1039 1040 context.endLayer(); 1041 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 1042 EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect()); 1043 } 1044 1045 #define DISPATCH1(c1, c2, op, param1) do { c1.op(param1); c2.op(param1); } while (0); 1046 #define DISPATCH2(c1, c2, op, param1, param2) do { c1.op(param1, param2); c2.op(param1, param2); } while (0); 1047 1048 TEST(GraphicsContextTest, RecordingTotalMatrix) 1049 { 1050 SkBitmap bitmap; 1051 ASSERT_TRUE(bitmap.allocN32Pixels(400, 400)); 1052 bitmap.eraseColor(0); 1053 SkCanvas canvas(bitmap); 1054 GraphicsContext context(&canvas); 1055 1056 SkCanvas controlCanvas(400, 400); 1057 GraphicsContext controlContext(&controlCanvas); 1058 1059 EXPECT_EQ(context.getCTM(), controlContext.getCTM()); 1060 DISPATCH2(context, controlContext, scale, 2, 2); 1061 EXPECT_EQ(context.getCTM(), controlContext.getCTM()); 1062 1063 controlContext.save(); 1064 context.beginRecording(FloatRect(0, 0, 200, 200)); 1065 DISPATCH2(context, controlContext, translate, 10, 10); 1066 EXPECT_EQ(context.getCTM(), controlContext.getCTM()); 1067 1068 controlContext.save(); 1069 context.beginRecording(FloatRect(10, 10, 100, 100)); 1070 DISPATCH1(context, controlContext, rotate, 45); 1071 EXPECT_EQ(context.getCTM(), controlContext.getCTM()); 1072 1073 controlContext.restore(); 1074 context.endRecording(); 1075 EXPECT_EQ(context.getCTM(), controlContext.getCTM()); 1076 1077 controlContext.restore(); 1078 context.endRecording(); 1079 EXPECT_EQ(context.getCTM(), controlContext.getCTM()); 1080 } 1081 1082 TEST(GraphicsContextTest, DisplayList) 1083 { 1084 FloatRect rect(0, 0, 1, 1); 1085 RefPtr<DisplayList> dl = adoptRef(new DisplayList(rect)); 1086 1087 // picture() returns 0 initially 1088 SkPicture* pic = dl->picture(); 1089 EXPECT_FALSE(pic); 1090 1091 // endRecording without a beginRecording does nothing 1092 dl->endRecording(); 1093 pic = dl->picture(); 1094 EXPECT_FALSE(pic); 1095 1096 // Two beginRecordings in a row generate two canvases. 1097 // Unfortunately the new one could be allocated in the same 1098 // spot as the old one so ref the first one to prolong its life. 1099 IntSize size(1, 1); 1100 SkCanvas* canvas1 = dl->beginRecording(size); 1101 EXPECT_TRUE(canvas1); 1102 canvas1->ref(); 1103 SkCanvas* canvas2 = dl->beginRecording(size); 1104 EXPECT_TRUE(canvas2); 1105 1106 EXPECT_NE(canvas1, canvas2); 1107 EXPECT_EQ(1, canvas1->getRefCnt()); 1108 canvas1->unref(); 1109 1110 EXPECT_TRUE(dl->isRecording()); 1111 1112 // picture() returns 0 during recording 1113 pic = dl->picture(); 1114 EXPECT_FALSE(pic); 1115 1116 // endRecording finally makes the picture accessible 1117 dl->endRecording(); 1118 pic = dl->picture(); 1119 EXPECT_TRUE(pic); 1120 EXPECT_EQ(1, pic->getRefCnt()); 1121 } 1122 1123 } // namespace 1124