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