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 blink; 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 bitmap.allocN32Pixels(400, 400); 73 bitmap.eraseColor(0); 74 SkCanvas canvas(bitmap); 75 76 GraphicsContext context(&canvas); 77 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 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 bitmap.allocN32Pixels(400, 400); 131 SkCanvas canvas(bitmap); 132 133 GraphicsContext context(&canvas); 134 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 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 bitmap.allocN32Pixels(400, 400); 225 bitmap.eraseColor(0); 226 SkCanvas canvas(bitmap); 227 228 GraphicsContext context(&canvas); 229 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 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 EXPECT_FALSE(!alphaImage); 247 alphaImage->context()->fillRect(IntRect(0, 0, 100, 100), alpha); 248 249 context.setCompositeOperation(CompositeSourceOver); 250 context.drawImageBuffer(alphaImage.get(), FloatRect(10, 10, 10, 10)); 251 252 context.endLayer(); 253 context.endLayer(); 254 255 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 256 EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect()); 257 } 258 259 TEST(GraphicsContextTest, trackImageMaskWithOpaqueRect) 260 { 261 SkBitmap bitmap; 262 bitmap.allocN32Pixels(400, 400); 263 bitmap.eraseColor(0); 264 SkCanvas canvas(bitmap); 265 266 GraphicsContext context(&canvas); 267 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 268 269 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 270 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 271 272 // Image masks are done by drawing a bitmap into a transparency layer that uses DstIn to mask 273 // out a transparency layer below that is filled with the mask color. In the end this should 274 // not be marked opaque. 275 276 context.setCompositeOperation(CompositeSourceOver); 277 context.beginTransparencyLayer(1); 278 context.fillRect(FloatRect(10, 10, 10, 10), opaque, CompositeSourceOver); 279 280 context.setCompositeOperation(CompositeDestinationIn); 281 context.beginTransparencyLayer(1); 282 283 OwnPtr<ImageBuffer> alphaImage = ImageBuffer::create(IntSize(100, 100)); 284 EXPECT_FALSE(!alphaImage); 285 alphaImage->context()->fillRect(IntRect(0, 0, 100, 100), alpha); 286 287 context.setCompositeOperation(CompositeSourceOver); 288 context.drawImageBuffer(alphaImage.get(), FloatRect(10, 10, 10, 10)); 289 290 // We can't have an opaque mask actually, but we can pretend here like it would look if we did. 291 context.fillRect(FloatRect(12, 12, 3, 3), opaque, CompositeSourceOver); 292 293 context.endLayer(); 294 context.endLayer(); 295 296 EXPECT_EQ_RECT(IntRect(12, 12, 3, 3), context.opaqueRegion().asRect()); 297 EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect()); 298 } 299 300 TEST(GraphicsContextTest, trackOpaqueJoinTest) 301 { 302 SkBitmap bitmap; 303 bitmap.allocN32Pixels(400, 400); 304 SkCanvas canvas(bitmap); 305 306 GraphicsContext context(&canvas); 307 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 308 309 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 310 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 311 312 context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver); 313 EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect()); 314 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 315 316 // Doesn't join 317 context.fillRect(FloatRect(31, 20, 10, 10), opaque, CompositeSourceOver); 318 EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect()); 319 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 320 321 // Does join 322 context.fillRect(FloatRect(30, 20, 10, 10), opaque, CompositeSourceOver); 323 EXPECT_EQ_RECT(IntRect(20, 20, 20, 10), context.opaqueRegion().asRect()); 324 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 325 326 // Doesn't join 327 context.fillRect(FloatRect(20, 31, 20, 10), opaque, CompositeSourceOver); 328 EXPECT_EQ_RECT(IntRect(20, 20, 20, 10), context.opaqueRegion().asRect()); 329 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 330 331 // Does join 332 context.fillRect(FloatRect(20, 30, 20, 10), opaque, CompositeSourceOver); 333 EXPECT_EQ_RECT(IntRect(20, 20, 20, 20), context.opaqueRegion().asRect()); 334 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 335 336 // Doesn't join 337 context.fillRect(FloatRect(9, 20, 10, 20), opaque, CompositeSourceOver); 338 EXPECT_EQ_RECT(IntRect(20, 20, 20, 20), context.opaqueRegion().asRect()); 339 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 340 341 // Does join 342 context.fillRect(FloatRect(10, 20, 10, 20), opaque, CompositeSourceOver); 343 EXPECT_EQ_RECT(IntRect(10, 20, 30, 20), context.opaqueRegion().asRect()); 344 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 345 346 // Doesn't join 347 context.fillRect(FloatRect(10, 9, 30, 10), opaque, CompositeSourceOver); 348 EXPECT_EQ_RECT(IntRect(10, 20, 30, 20), context.opaqueRegion().asRect()); 349 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 350 351 // Does join 352 context.fillRect(FloatRect(10, 10, 30, 10), opaque, CompositeSourceOver); 353 EXPECT_EQ_RECT(IntRect(10, 10, 30, 30), context.opaqueRegion().asRect()); 354 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 355 } 356 357 TEST(GraphicsContextTest, trackOpaqueLineTest) 358 { 359 SkBitmap bitmap; 360 bitmap.allocN32Pixels(200, 200); 361 bitmap.eraseColor(0); 362 SkCanvas canvas(bitmap); 363 364 GraphicsContext context(&canvas); 365 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 366 367 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 368 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 369 370 context.setShouldAntialias(false); 371 context.setMiterLimit(0); 372 context.setStrokeThickness(4); 373 context.setLineCap(SquareCap); 374 context.setStrokeStyle(SolidStroke); 375 context.setCompositeOperation(CompositeSourceOver); 376 377 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 378 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 379 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 380 381 context.setCompositeOperation(CompositeSourceIn); 382 383 context.save(); 384 context.setStrokeColor(alpha); 385 context.drawLine(IntPoint(0, 0), IntPoint(100, 0)); 386 context.restore(); 387 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 388 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 389 390 context.save(); 391 context.setStrokeColor(opaque); 392 context.drawLine(IntPoint(0, 10), IntPoint(100, 10)); 393 context.restore(); 394 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 395 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 396 397 context.save(); 398 context.setStrokeColor(alpha); 399 context.drawLine(IntPoint(0, 10), IntPoint(100, 10)); 400 context.restore(); 401 EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect()); 402 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 403 404 context.save(); 405 context.setStrokeColor(alpha); 406 context.drawLine(IntPoint(0, 11), IntPoint(100, 11)); 407 context.restore(); 408 EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect()); 409 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 410 411 context.setShouldAntialias(true); 412 context.setCompositeOperation(CompositeSourceOver); 413 414 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 415 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 416 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 417 418 context.setCompositeOperation(CompositeSourceIn); 419 420 context.save(); 421 context.setStrokeColor(alpha); 422 context.drawLine(IntPoint(0, 0), IntPoint(100, 0)); 423 context.restore(); 424 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 425 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 426 427 context.setShouldAntialias(false); 428 context.save(); 429 context.setStrokeColor(opaque); 430 context.drawLine(IntPoint(0, 10), IntPoint(100, 10)); 431 context.restore(); 432 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 433 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 434 435 context.setShouldAntialias(true); 436 context.save(); 437 context.setStrokeColor(opaque); 438 context.drawLine(IntPoint(0, 10), IntPoint(100, 10)); 439 context.restore(); 440 EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect()); 441 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 442 443 context.save(); 444 context.setStrokeColor(alpha); 445 context.drawLine(IntPoint(0, 11), IntPoint(100, 11)); 446 context.restore(); 447 EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect()); 448 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 449 } 450 451 TEST(GraphicsContextTest, trackOpaquePathTest) 452 { 453 SkBitmap bitmap; 454 bitmap.allocN32Pixels(200, 200); 455 SkCanvas canvas(bitmap); 456 457 GraphicsContext context(&canvas); 458 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 459 460 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 461 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 462 463 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 464 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 465 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 466 467 context.setShouldAntialias(false); 468 context.setMiterLimit(1); 469 context.setStrokeThickness(5); 470 context.setLineCap(SquareCap); 471 context.setStrokeStyle(SolidStroke); 472 context.setCompositeOperation(CompositeSourceIn); 473 474 Path path; 475 476 context.setFillColor(alpha); 477 path.moveTo(FloatPoint(0, 0)); 478 path.addLineTo(FloatPoint(100, 0)); 479 context.fillPath(path); 480 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 481 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 482 path.clear(); 483 484 context.setFillColor(opaque); 485 path.moveTo(FloatPoint(0, 10)); 486 path.addLineTo(FloatPoint(100, 13)); 487 context.fillPath(path); 488 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 489 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 490 path.clear(); 491 492 context.setFillColor(alpha); 493 path.moveTo(FloatPoint(0, 10)); 494 path.addLineTo(FloatPoint(100, 13)); 495 context.fillPath(path); 496 EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect()); 497 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 498 path.clear(); 499 500 context.setFillColor(alpha); 501 path.moveTo(FloatPoint(0, 14)); 502 path.addLineTo(FloatPoint(100, 10)); 503 context.fillPath(path); 504 EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect()); 505 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 506 path.clear(); 507 } 508 509 TEST(GraphicsContextTest, trackOpaqueImageTest) 510 { 511 SkBitmap bitmap; 512 bitmap.allocN32Pixels(200, 200); 513 SkCanvas canvas(bitmap); 514 515 GraphicsContext context(&canvas); 516 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 517 518 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 519 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 520 521 SkBitmap opaqueBitmap; 522 opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */); 523 524 for (int y = 0; y < opaqueBitmap.height(); ++y) 525 for (int x = 0; x < opaqueBitmap.width(); ++x) 526 *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF; 527 RefPtr<BitmapImage> opaqueImage = BitmapImage::create(NativeImageSkia::create(opaqueBitmap)); 528 EXPECT_TRUE(opaqueImage->currentFrameKnownToBeOpaque()); 529 530 SkBitmap alphaBitmap; 531 alphaBitmap.allocN32Pixels(10, 10); 532 533 for (int y = 0; y < alphaBitmap.height(); ++y) 534 for (int x = 0; x < alphaBitmap.width(); ++x) 535 *alphaBitmap.getAddr32(x, y) = 0x00000000; 536 RefPtr<BitmapImage> alphaImage = BitmapImage::create(NativeImageSkia::create(alphaBitmap)); 537 EXPECT_FALSE(alphaImage->currentFrameKnownToBeOpaque()); 538 539 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 540 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 541 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 542 543 context.drawImage(opaqueImage.get(), IntPoint(0, 0)); 544 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 545 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 546 context.drawImage(alphaImage.get(), IntPoint(0, 0)); 547 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 548 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 549 550 context.drawImage(opaqueImage.get(), IntPoint(5, 5)); 551 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 552 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 553 context.drawImage(alphaImage.get(), IntPoint(5, 5)); 554 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 555 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 556 557 context.drawImage(opaqueImage.get(), IntPoint(10, 10)); 558 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 559 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 560 context.drawImage(alphaImage.get(), IntPoint(10, 10)); 561 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 562 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 563 564 context.drawImage(alphaImage.get(), IntPoint(20, 10), CompositeSourceIn); 565 EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), context.opaqueRegion().asRect()); 566 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 567 568 context.save(); 569 context.setAlphaAsFloat(0.5); 570 context.drawImage(opaqueImage.get(), IntPoint(25, 15), CompositeSourceIn); 571 context.restore(); 572 EXPECT_EQ_RECT(IntRect(10, 25, 90, 75), context.opaqueRegion().asRect()); 573 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 574 575 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 576 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 577 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 578 579 context.drawImage(alphaImage.get(), IntPoint(10, 20), CompositeSourceIn); 580 EXPECT_EQ_RECT(IntRect(20, 10, 80, 90), context.opaqueRegion().asRect()); 581 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 582 583 context.save(); 584 context.setAlphaAsFloat(0.5); 585 context.drawImage(opaqueImage.get(), IntPoint(15, 25), CompositeSourceIn); 586 context.restore(); 587 EXPECT_EQ_RECT(IntRect(25, 10, 75, 90), context.opaqueRegion().asRect()); 588 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 589 } 590 591 TEST(GraphicsContextTest, trackOpaqueOvalTest) 592 { 593 SkBitmap bitmap; 594 bitmap.allocN32Pixels(200, 200); 595 bitmap.eraseColor(0); 596 SkCanvas canvas(bitmap); 597 598 GraphicsContext context(&canvas); 599 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 600 601 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 602 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 603 604 EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect()); 605 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 606 607 context.fillEllipse(FloatRect(10, 10, 90, 90)); 608 context.strokeEllipse(FloatRect(10, 10, 90, 90)); 609 EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect()); 610 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 611 612 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 613 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 614 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 615 616 context.setCompositeOperation(CompositeSourceIn); 617 618 context.setShouldAntialias(false); 619 620 context.setFillColor(opaque); 621 context.fillEllipse(FloatRect(10, 10, 50, 30)); 622 context.strokeEllipse(FloatRect(10, 10, 50, 30)); 623 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 624 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 625 626 context.setFillColor(alpha); 627 context.fillEllipse(FloatRect(10, 10, 30, 50)); 628 context.strokeEllipse(FloatRect(10, 10, 30, 50)); 629 EXPECT_EQ_RECT(IntRect(40, 10, 60, 90), context.opaqueRegion().asRect()); 630 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 631 632 context.setShouldAntialias(true); 633 634 context.setFillColor(opaque); 635 context.fillEllipse(FloatRect(10, 10, 50, 30)); 636 context.strokeEllipse(FloatRect(10, 10, 50, 30)); 637 EXPECT_EQ_RECT(IntRect(40, 41, 60, 59), context.opaqueRegion().asRect()); 638 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 639 640 context.setFillColor(alpha); 641 context.fillEllipse(FloatRect(20, 10, 30, 50)); 642 context.strokeEllipse(FloatRect(20, 10, 30, 50)); 643 EXPECT_EQ_RECT(IntRect(51, 41, 49, 59), context.opaqueRegion().asRect()); 644 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 645 } 646 647 TEST(GraphicsContextTest, trackOpaqueRoundedRectTest) 648 { 649 SkBitmap bitmap; 650 bitmap.allocN32Pixels(200, 200); 651 SkCanvas canvas(bitmap); 652 653 GraphicsContext context(&canvas); 654 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 655 656 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 657 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 658 IntSize radii(10, 10); 659 660 EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect()); 661 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 662 663 context.fillRoundedRect(IntRect(10, 10, 90, 90), radii, radii, radii, radii, opaque); 664 EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect()); 665 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 666 667 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 668 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 669 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 670 671 context.setCompositeOperation(CompositeSourceIn); 672 context.setShouldAntialias(false); 673 674 context.fillRoundedRect(IntRect(10, 10, 50, 30), radii, radii, radii, radii, opaque); 675 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 676 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 677 678 context.fillRoundedRect(IntRect(10, 10, 30, 50), radii, radii, radii, radii, alpha); 679 EXPECT_EQ_RECT(IntRect(40, 10, 60, 90), context.opaqueRegion().asRect()); 680 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 681 682 context.fillRoundedRect(IntRect(10, 0, 50, 30), radii, radii, radii, radii, alpha); 683 EXPECT_EQ_RECT(IntRect(40, 30, 60, 70), context.opaqueRegion().asRect()); 684 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 685 686 context.fillRoundedRect(IntRect(30, 0, 70, 50), radii, radii, radii, radii, opaque); 687 EXPECT_EQ_RECT(IntRect(40, 30, 60, 70), context.opaqueRegion().asRect()); 688 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 689 } 690 691 TEST(GraphicsContextTest, trackOpaqueTextTest) 692 { 693 int width = 200, height = 200; 694 SkBitmap bitmap; 695 bitmap.allocN32Pixels(width, height); 696 bitmap.eraseColor(0); 697 SkCanvas canvas(bitmap); 698 SkRect textRect = SkRect::MakeWH(width, height); 699 700 GraphicsContext context(&canvas); 701 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 702 703 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 704 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 705 706 SkPaint opaquePaint; 707 opaquePaint.setColor(opaque.rgb()); 708 opaquePaint.setXfermodeMode(SkXfermode::kSrc_Mode); 709 SkPaint alphaPaint; 710 alphaPaint.setColor(alpha.rgb()); 711 alphaPaint.setXfermodeMode(SkXfermode::kSrc_Mode); 712 713 SkPoint point = SkPoint::Make(0, 0); 714 715 context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver); 716 EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect()); 717 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 718 719 context.drawPosText("A", 1, &point, textRect, opaquePaint); 720 EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect()); 721 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 722 723 context.drawPosText("A", 1, &point, textRect, alphaPaint); 724 EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect()); 725 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 726 727 context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver); 728 EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect()); 729 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 730 731 context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver); 732 EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect()); 733 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 734 } 735 736 TEST(GraphicsContextTest, trackOpaqueWritePixelsTest) 737 { 738 SkBitmap bitmap; 739 bitmap.allocN32Pixels(200, 200); 740 bitmap.eraseColor(0); 741 SkCanvas canvas(bitmap); 742 743 GraphicsContext context(&canvas); 744 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 745 746 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 747 748 SkBitmap opaqueBitmap; 749 opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */); 750 for (int y = 0; y < opaqueBitmap.height(); ++y) 751 for (int x = 0; x < opaqueBitmap.width(); ++x) 752 *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF; 753 754 SkBitmap alphaBitmap; 755 alphaBitmap.allocN32Pixels(10, 10); 756 for (int y = 0; y < alphaBitmap.height(); ++y) 757 for (int x = 0; x < alphaBitmap.width(); ++x) 758 *alphaBitmap.getAddr32(x, y) = 0x00000000; 759 760 SkPaint paint; 761 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 762 763 context.writePixels(opaqueBitmap, 50, 50); 764 EXPECT_EQ_RECT(IntRect(50, 50, 10, 10), context.opaqueRegion().asRect()); 765 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 766 767 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 768 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 769 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 770 771 context.writePixels(alphaBitmap, 10, 0); 772 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 773 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 774 775 context.writePixels(alphaBitmap, 10, 1); 776 EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect()); 777 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 778 779 context.writePixels(alphaBitmap, 0, 10); 780 EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect()); 781 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 782 783 context.writePixels(alphaBitmap, 1, 10); 784 EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect()); 785 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 786 } 787 788 TEST(GraphicsContextTest, trackOpaqueDrawBitmapTest) 789 { 790 SkBitmap bitmap; 791 bitmap.allocN32Pixels(200, 200); 792 bitmap.eraseColor(0); 793 SkCanvas canvas(bitmap); 794 795 GraphicsContext context(&canvas); 796 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 797 798 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 799 800 SkBitmap opaqueBitmap; 801 opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */); 802 for (int y = 0; y < opaqueBitmap.height(); ++y) 803 for (int x = 0; x < opaqueBitmap.width(); ++x) 804 *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF; 805 806 SkBitmap alphaBitmap; 807 alphaBitmap.allocN32Pixels(10, 10); 808 for (int y = 0; y < alphaBitmap.height(); ++y) 809 for (int x = 0; x < alphaBitmap.width(); ++x) 810 *alphaBitmap.getAddr32(x, y) = 0x00000000; 811 812 SkPaint paint; 813 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 814 815 context.drawBitmap(opaqueBitmap, 10, 10, &paint); 816 EXPECT_EQ_RECT(IntRect(10, 10, 10, 10), context.opaqueRegion().asRect()); 817 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 818 819 context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver); 820 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 821 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 822 823 context.drawBitmap(alphaBitmap, 10, 0, &paint); 824 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 825 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 826 827 context.drawBitmap(alphaBitmap, 10, 1, &paint); 828 EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect()); 829 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 830 831 context.drawBitmap(alphaBitmap, 0, 10, &paint); 832 EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect()); 833 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 834 835 context.drawBitmap(alphaBitmap, 1, 10, &paint); 836 EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect()); 837 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 838 } 839 840 TEST(GraphicsContextTest, trackOpaqueDrawBitmapRectTest) 841 { 842 SkBitmap bitmap; 843 bitmap.allocN32Pixels(200, 200); 844 bitmap.eraseColor(0); 845 SkCanvas canvas(bitmap); 846 847 GraphicsContext context(&canvas); 848 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 849 850 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 851 852 SkBitmap opaqueBitmap; 853 opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */); 854 for (int y = 0; y < opaqueBitmap.height(); ++y) 855 for (int x = 0; x < opaqueBitmap.width(); ++x) 856 *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF; 857 858 SkBitmap alphaBitmap; 859 alphaBitmap.allocN32Pixels(10, 10); 860 for (int y = 0; y < alphaBitmap.height(); ++y) 861 for (int x = 0; x < alphaBitmap.width(); ++x) 862 *alphaBitmap.getAddr32(x, y) = 0x00000000; 863 864 SkPaint paint; 865 paint.setXfermodeMode(SkXfermode::kSrc_Mode); 866 867 context.drawBitmapRect(opaqueBitmap, 0, SkRect::MakeXYWH(10, 10, 90, 90), &paint); 868 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 869 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 870 871 context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(10, 0, 10, 10), &paint); 872 EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect()); 873 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 874 875 context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(10, 0, 10, 11), &paint); 876 EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect()); 877 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 878 879 context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(0, 10, 10, 10), &paint); 880 EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect()); 881 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 882 883 context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(0, 10, 11, 10), &paint); 884 EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect()); 885 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 886 } 887 888 TEST(GraphicsContextTest, contextTransparencyLayerTest) 889 { 890 SkBitmap bitmap; 891 bitmap.allocN32Pixels(400, 400); 892 bitmap.eraseColor(0); 893 SkCanvas canvas(bitmap); 894 895 GraphicsContext context(&canvas); 896 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 897 898 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 899 context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver); 900 EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect()); 901 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 902 903 context.clearRect(FloatRect(20, 20, 10, 10)); 904 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 905 906 context.beginTransparencyLayer(0.5); 907 context.save(); 908 context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver); 909 context.restore(); 910 context.endLayer(); 911 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 912 913 context.clearRect(FloatRect(20, 20, 10, 10)); 914 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 915 916 context.beginTransparencyLayer(0.5); 917 context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver); 918 context.endLayer(); 919 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 920 } 921 922 TEST(GraphicsContextTest, UnboundedDrawsAreClipped) 923 { 924 SkBitmap bitmap; 925 bitmap.allocN32Pixels(400, 400); 926 bitmap.eraseColor(0); 927 SkCanvas canvas(bitmap); 928 929 GraphicsContext context(&canvas); 930 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 931 932 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 933 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 934 935 Path path; 936 context.setShouldAntialias(false); 937 context.setMiterLimit(1); 938 context.setStrokeThickness(5); 939 context.setLineCap(SquareCap); 940 context.setStrokeStyle(SolidStroke); 941 942 // Make skia unable to compute fast bounds for our paths. 943 DashArray dashArray; 944 dashArray.append(1); 945 dashArray.append(0); 946 context.setLineDash(dashArray, 0); 947 948 // Make the device opaque in 10,10 40x40. 949 context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver); 950 EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect()); 951 EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect()); 952 953 // Clip to the left edge of the opaque area. 954 context.clip(IntRect(10, 10, 10, 40)); 955 956 // Draw a path that gets clipped. This should destroy the opaque area but only inside the clip. 957 context.setCompositeOperation(CompositeSourceOut); 958 context.setFillColor(alpha); 959 path.moveTo(FloatPoint(10, 10)); 960 path.addLineTo(FloatPoint(40, 40)); 961 context.strokePath(path); 962 963 EXPECT_EQ_RECT(IntRect(20, 10, 30, 40), context.opaqueRegion().asRect()); 964 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 965 } 966 967 TEST(GraphicsContextTest, PreserveOpaqueOnlyMattersForFirstLayer) 968 { 969 SkBitmap bitmap; 970 bitmap.allocN32Pixels(400, 400); 971 bitmap.eraseColor(0); 972 SkCanvas canvas(bitmap); 973 974 GraphicsContext context(&canvas); 975 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 976 977 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 978 Color alpha(0.0f, 0.0f, 0.0f, 0.0f); 979 980 Path path; 981 context.setShouldAntialias(false); 982 context.setMiterLimit(1); 983 context.setStrokeThickness(5); 984 context.setLineCap(SquareCap); 985 context.setStrokeStyle(SolidStroke); 986 987 // Make skia unable to compute fast bounds for our paths. 988 DashArray dashArray; 989 dashArray.append(1); 990 dashArray.append(0); 991 context.setLineDash(dashArray, 0); 992 993 // Make the device opaque in 10,10 40x40. 994 context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver); 995 EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect()); 996 EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect()); 997 998 // Begin a layer that preserves opaque. 999 context.setCompositeOperation(CompositeSourceOver); 1000 context.beginTransparencyLayer(0.5); 1001 1002 // Begin a layer that does not preserve opaque. 1003 context.setCompositeOperation(CompositeSourceOut); 1004 context.beginTransparencyLayer(0.5); 1005 1006 // This should not destroy the device opaqueness. 1007 context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver); 1008 1009 // This should not destroy the device opaqueness either. 1010 context.setFillColor(opaque); 1011 path.moveTo(FloatPoint(10, 10)); 1012 path.addLineTo(FloatPoint(40, 40)); 1013 context.strokePath(path); 1014 1015 context.endLayer(); 1016 context.endLayer(); 1017 EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect()); 1018 EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect()); 1019 1020 // Now begin a layer that does not preserve opaque and draw through it to the device. 1021 context.setCompositeOperation(CompositeSourceOut); 1022 context.beginTransparencyLayer(0.5); 1023 1024 // This should destroy the device opaqueness. 1025 context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver); 1026 1027 context.endLayer(); 1028 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 1029 EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect()); 1030 1031 // Now we draw with a path for which it cannot compute fast bounds. This should destroy the entire opaque region. 1032 1033 context.setCompositeOperation(CompositeSourceOut); 1034 context.beginTransparencyLayer(0.5); 1035 1036 // This should nuke the device opaqueness. 1037 context.setFillColor(opaque); 1038 path.moveTo(FloatPoint(10, 10)); 1039 path.addLineTo(FloatPoint(40, 40)); 1040 context.strokePath(path); 1041 1042 context.endLayer(); 1043 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 1044 EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect()); 1045 } 1046 1047 TEST(GraphicsContextTest, OpaqueRegionForLayerWithNonRectDeviceClip) 1048 { 1049 SkBitmap bitmap; 1050 bitmap.allocN32Pixels(100, 100); 1051 bitmap.eraseColor(0); 1052 SkCanvas canvas(bitmap); 1053 1054 GraphicsContext context(&canvas); 1055 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 1056 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 1057 1058 context.fillRect(FloatRect(30, 30, 90, 90), opaque, CompositeSourceOver); 1059 1060 context.setCompositeOperation(CompositeSourceOver); 1061 context.beginTransparencyLayer(0.5); 1062 context.endLayer(); 1063 EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), context.opaqueRegion().asRect()); 1064 1065 Path path; 1066 path.moveTo(FloatPoint(0, 0)); 1067 path.addLineTo(FloatPoint(50, 50)); 1068 1069 // For opaque preserving mode and deviceClip is not rect 1070 // we will not alter opaque rect. 1071 context.clipPath(path, RULE_EVENODD); 1072 1073 context.setCompositeOperation(CompositeSourceOver); 1074 context.beginTransparencyLayer(0.5); 1075 context.endLayer(); 1076 EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), context.opaqueRegion().asRect()); 1077 1078 // For non-opaque preserving mode and deviceClip is not rect 1079 // we will mark opaque rect as empty. 1080 context.setCompositeOperation(CompositeSourceOut); 1081 context.beginTransparencyLayer(0.5); 1082 1083 context.endLayer(); 1084 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 1085 } 1086 1087 TEST(GraphicsContextTest, OpaqueRegionForLayerWithRectDeviceClip) 1088 { 1089 SkBitmap bitmap; 1090 bitmap.allocN32Pixels(100, 100); 1091 bitmap.eraseColor(0); 1092 SkCanvas canvas(bitmap); 1093 1094 Color opaque(1.0f, 0.0f, 0.0f, 1.0f); 1095 1096 GraphicsContext context(&canvas); 1097 context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque); 1098 1099 context.fillRect(FloatRect(30, 30, 90, 90), opaque, CompositeSourceOver); 1100 EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), context.opaqueRegion().asRect()); 1101 1102 // For non-opaque preserving mode and deviceClip is rect 1103 // we will mark device clip rect as non opaque. 1104 context.setCompositeOperation(CompositeSourceOut); 1105 context.beginTransparencyLayer(0.5); 1106 context.endLayer(); 1107 EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect()); 1108 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 1109 1110 context.clip(FloatRect(0, 0, 50, 50)); 1111 context.fillRect(FloatRect(20, 20, 100, 100), opaque, CompositeSourceOver); 1112 1113 // For opaque preserving mode and deviceClip is rect 1114 // we will intersect device clip rect with src opaque rect. 1115 context.setCompositeOperation(CompositeSourceOver); 1116 context.beginTransparencyLayer(0.5); 1117 context.endLayer(); 1118 EXPECT_EQ_RECT(IntRect(20, 20, 30, 30), context.opaqueRegion().asRect()); 1119 EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect()); 1120 } 1121 1122 #define DISPATCH1(c1, c2, op, param1) do { c1.op(param1); c2.op(param1); } while (0); 1123 #define DISPATCH2(c1, c2, op, param1, param2) do { c1.op(param1, param2); c2.op(param1, param2); } while (0); 1124 1125 TEST(GraphicsContextTest, RecordingTotalMatrix) 1126 { 1127 SkBitmap bitmap; 1128 bitmap.allocN32Pixels(400, 400); 1129 bitmap.eraseColor(0); 1130 SkCanvas canvas(bitmap); 1131 GraphicsContext context(&canvas); 1132 1133 SkCanvas controlCanvas(400, 400); 1134 GraphicsContext controlContext(&controlCanvas); 1135 1136 EXPECT_EQ(context.getCTM(), controlContext.getCTM()); 1137 DISPATCH2(context, controlContext, scale, 2, 2); 1138 EXPECT_EQ(context.getCTM(), controlContext.getCTM()); 1139 1140 controlContext.save(); 1141 context.beginRecording(FloatRect(0, 0, 200, 200)); 1142 DISPATCH2(context, controlContext, translate, 10, 10); 1143 EXPECT_EQ(context.getCTM(), controlContext.getCTM()); 1144 1145 controlContext.save(); 1146 context.beginRecording(FloatRect(10, 10, 100, 100)); 1147 DISPATCH1(context, controlContext, rotate, 45); 1148 EXPECT_EQ(context.getCTM(), controlContext.getCTM()); 1149 1150 controlContext.restore(); 1151 context.endRecording(); 1152 EXPECT_EQ(context.getCTM(), controlContext.getCTM()); 1153 1154 controlContext.restore(); 1155 context.endRecording(); 1156 EXPECT_EQ(context.getCTM(), controlContext.getCTM()); 1157 } 1158 1159 TEST(GraphicsContextTest, RecordingCanvas) 1160 { 1161 SkBitmap bitmap; 1162 bitmap.allocN32Pixels(1, 1); 1163 bitmap.eraseColor(0); 1164 SkCanvas canvas(bitmap); 1165 GraphicsContext context(&canvas); 1166 1167 FloatRect rect(0, 0, 1, 1); 1168 1169 // Two beginRecordings in a row generate two canvases. 1170 // Unfortunately the new one could be allocated in the same 1171 // spot as the old one so ref the first one to prolong its life. 1172 context.beginRecording(rect); 1173 SkCanvas* canvas1 = context.canvas(); 1174 EXPECT_TRUE(canvas1); 1175 context.beginRecording(rect); 1176 SkCanvas* canvas2 = context.canvas(); 1177 EXPECT_TRUE(canvas2); 1178 1179 EXPECT_NE(canvas1, canvas2); 1180 EXPECT_EQ(1, canvas1->getRefCnt()); 1181 1182 // endRecording finally makes the picture accessible 1183 RefPtr<DisplayList> dl = context.endRecording(); 1184 SkPicture* pic = dl->picture(); 1185 EXPECT_TRUE(pic); 1186 EXPECT_EQ(1, pic->getRefCnt()); 1187 1188 context.endRecording(); 1189 } 1190 1191 } // namespace 1192