1 /* 2 * Copyright 2013 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkBitmap.h" 9 #include "SkBitmapDevice.h" 10 #include "SkBitmapSource.h" 11 #include "SkBlurImageFilter.h" 12 #include "SkCanvas.h" 13 #include "SkColorFilterImageFilter.h" 14 #include "SkColorMatrixFilter.h" 15 #include "SkDeviceImageFilterProxy.h" 16 #include "SkDisplacementMapEffect.h" 17 #include "SkDropShadowImageFilter.h" 18 #include "SkFlattenableSerialization.h" 19 #include "SkGradientShader.h" 20 #include "SkLightingImageFilter.h" 21 #include "SkMatrixConvolutionImageFilter.h" 22 #include "SkMatrixImageFilter.h" 23 #include "SkMergeImageFilter.h" 24 #include "SkMorphologyImageFilter.h" 25 #include "SkOffsetImageFilter.h" 26 #include "SkPicture.h" 27 #include "SkPictureImageFilter.h" 28 #include "SkPictureRecorder.h" 29 #include "SkReadBuffer.h" 30 #include "SkRect.h" 31 #include "SkTileImageFilter.h" 32 #include "SkXfermodeImageFilter.h" 33 #include "Test.h" 34 35 #if SK_SUPPORT_GPU 36 #include "GrContextFactory.h" 37 #include "SkGpuDevice.h" 38 #endif 39 40 static const int kBitmapSize = 4; 41 42 namespace { 43 44 class MatrixTestImageFilter : public SkImageFilter { 45 public: 46 MatrixTestImageFilter(skiatest::Reporter* reporter, const SkMatrix& expectedMatrix) 47 : SkImageFilter(0, NULL), fReporter(reporter), fExpectedMatrix(expectedMatrix) { 48 } 49 50 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context& ctx, 51 SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE { 52 REPORTER_ASSERT(fReporter, ctx.ctm() == fExpectedMatrix); 53 return true; 54 } 55 56 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(MatrixTestImageFilter) 57 58 protected: 59 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 60 explicit MatrixTestImageFilter(SkReadBuffer& buffer) : SkImageFilter(0, NULL) { 61 fReporter = static_cast<skiatest::Reporter*>(buffer.readFunctionPtr()); 62 buffer.readMatrix(&fExpectedMatrix); 63 } 64 #endif 65 66 virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE { 67 this->INHERITED::flatten(buffer); 68 buffer.writeFunctionPtr(fReporter); 69 buffer.writeMatrix(fExpectedMatrix); 70 } 71 72 private: 73 skiatest::Reporter* fReporter; 74 SkMatrix fExpectedMatrix; 75 76 typedef SkImageFilter INHERITED; 77 }; 78 79 } 80 81 SkFlattenable* MatrixTestImageFilter::CreateProc(SkReadBuffer& buffer) { 82 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); 83 skiatest::Reporter* reporter = (skiatest::Reporter*)buffer.readFunctionPtr(); 84 SkMatrix matrix; 85 buffer.readMatrix(&matrix); 86 return SkNEW_ARGS(MatrixTestImageFilter, (reporter, matrix)); 87 } 88 89 static void make_small_bitmap(SkBitmap& bitmap) { 90 bitmap.allocN32Pixels(kBitmapSize, kBitmapSize); 91 SkCanvas canvas(bitmap); 92 canvas.clear(0x00000000); 93 SkPaint darkPaint; 94 darkPaint.setColor(0xFF804020); 95 SkPaint lightPaint; 96 lightPaint.setColor(0xFF244484); 97 const int i = kBitmapSize / 4; 98 for (int y = 0; y < kBitmapSize; y += i) { 99 for (int x = 0; x < kBitmapSize; x += i) { 100 canvas.save(); 101 canvas.translate(SkIntToScalar(x), SkIntToScalar(y)); 102 canvas.drawRect(SkRect::MakeXYWH(0, 0, 103 SkIntToScalar(i), 104 SkIntToScalar(i)), darkPaint); 105 canvas.drawRect(SkRect::MakeXYWH(SkIntToScalar(i), 106 0, 107 SkIntToScalar(i), 108 SkIntToScalar(i)), lightPaint); 109 canvas.drawRect(SkRect::MakeXYWH(0, 110 SkIntToScalar(i), 111 SkIntToScalar(i), 112 SkIntToScalar(i)), lightPaint); 113 canvas.drawRect(SkRect::MakeXYWH(SkIntToScalar(i), 114 SkIntToScalar(i), 115 SkIntToScalar(i), 116 SkIntToScalar(i)), darkPaint); 117 canvas.restore(); 118 } 119 } 120 } 121 122 static SkImageFilter* make_scale(float amount, SkImageFilter* input = NULL) { 123 SkScalar s = amount; 124 SkScalar matrix[20] = { s, 0, 0, 0, 0, 125 0, s, 0, 0, 0, 126 0, 0, s, 0, 0, 127 0, 0, 0, s, 0 }; 128 SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix)); 129 return SkColorFilterImageFilter::Create(filter, input); 130 } 131 132 static SkImageFilter* make_grayscale(SkImageFilter* input = NULL, const SkImageFilter::CropRect* cropRect = NULL) { 133 SkScalar matrix[20]; 134 memset(matrix, 0, 20 * sizeof(SkScalar)); 135 matrix[0] = matrix[5] = matrix[10] = 0.2126f; 136 matrix[1] = matrix[6] = matrix[11] = 0.7152f; 137 matrix[2] = matrix[7] = matrix[12] = 0.0722f; 138 matrix[18] = 1.0f; 139 SkAutoTUnref<SkColorFilter> filter(SkColorMatrixFilter::Create(matrix)); 140 return SkColorFilterImageFilter::Create(filter, input, cropRect); 141 } 142 143 DEF_TEST(ImageFilter, reporter) { 144 { 145 // Check that two non-clipping color matrices concatenate into a single filter. 146 SkAutoTUnref<SkImageFilter> halfBrightness(make_scale(0.5f)); 147 SkAutoTUnref<SkImageFilter> quarterBrightness(make_scale(0.5f, halfBrightness)); 148 REPORTER_ASSERT(reporter, NULL == quarterBrightness->getInput(0)); 149 } 150 151 { 152 // Check that a clipping color matrix followed by a grayscale does not concatenate into a single filter. 153 SkAutoTUnref<SkImageFilter> doubleBrightness(make_scale(2.0f)); 154 SkAutoTUnref<SkImageFilter> halfBrightness(make_scale(0.5f, doubleBrightness)); 155 REPORTER_ASSERT(reporter, halfBrightness->getInput(0)); 156 } 157 158 { 159 // Check that a color filter image filter without a crop rect can be 160 // expressed as a color filter. 161 SkAutoTUnref<SkImageFilter> gray(make_grayscale()); 162 REPORTER_ASSERT(reporter, true == gray->asColorFilter(NULL)); 163 } 164 165 { 166 // Check that a color filter image filter with a crop rect cannot 167 // be expressed as a color filter. 168 SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(0, 0, 100, 100)); 169 SkAutoTUnref<SkImageFilter> grayWithCrop(make_grayscale(NULL, &cropRect)); 170 REPORTER_ASSERT(reporter, false == grayWithCrop->asColorFilter(NULL)); 171 } 172 173 { 174 // Check that two non-commutative matrices are concatenated in 175 // the correct order. 176 SkScalar blueToRedMatrix[20] = { 0 }; 177 blueToRedMatrix[2] = blueToRedMatrix[18] = SK_Scalar1; 178 SkScalar redToGreenMatrix[20] = { 0 }; 179 redToGreenMatrix[5] = redToGreenMatrix[18] = SK_Scalar1; 180 SkAutoTUnref<SkColorFilter> blueToRed(SkColorMatrixFilter::Create(blueToRedMatrix)); 181 SkAutoTUnref<SkImageFilter> filter1(SkColorFilterImageFilter::Create(blueToRed.get())); 182 SkAutoTUnref<SkColorFilter> redToGreen(SkColorMatrixFilter::Create(redToGreenMatrix)); 183 SkAutoTUnref<SkImageFilter> filter2(SkColorFilterImageFilter::Create(redToGreen.get(), filter1.get())); 184 185 SkBitmap result; 186 result.allocN32Pixels(kBitmapSize, kBitmapSize); 187 188 SkPaint paint; 189 paint.setColor(SK_ColorBLUE); 190 paint.setImageFilter(filter2.get()); 191 SkCanvas canvas(result); 192 canvas.clear(0x0); 193 SkRect rect = SkRect::Make(SkIRect::MakeWH(kBitmapSize, kBitmapSize)); 194 canvas.drawRect(rect, paint); 195 uint32_t pixel = *result.getAddr32(0, 0); 196 // The result here should be green, since we have effectively shifted blue to green. 197 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN); 198 } 199 200 { 201 // Tests pass by not asserting 202 SkBitmap bitmap, result; 203 make_small_bitmap(bitmap); 204 result.allocN32Pixels(kBitmapSize, kBitmapSize); 205 206 { 207 // This tests for : 208 // 1 ) location at (0,0,1) 209 SkPoint3 location(0, 0, SK_Scalar1); 210 // 2 ) location and target at same value 211 SkPoint3 target(location.fX, location.fY, location.fZ); 212 // 3 ) large negative specular exponent value 213 SkScalar specularExponent = -1000; 214 215 SkAutoTUnref<SkImageFilter> bmSrc(SkBitmapSource::Create(bitmap)); 216 SkPaint paint; 217 paint.setImageFilter(SkLightingImageFilter::CreateSpotLitSpecular( 218 location, target, specularExponent, 180, 219 0xFFFFFFFF, SK_Scalar1, SK_Scalar1, SK_Scalar1, 220 bmSrc))->unref(); 221 SkCanvas canvas(result); 222 SkRect r = SkRect::MakeWH(SkIntToScalar(kBitmapSize), 223 SkIntToScalar(kBitmapSize)); 224 canvas.drawRect(r, paint); 225 } 226 } 227 } 228 229 static void test_crop_rects(SkBaseDevice* device, skiatest::Reporter* reporter) { 230 // Check that all filters offset to their absolute crop rect, 231 // unaffected by the input crop rect. 232 // Tests pass by not asserting. 233 SkBitmap bitmap; 234 bitmap.allocN32Pixels(100, 100); 235 bitmap.eraseARGB(0, 0, 0, 0); 236 SkDeviceImageFilterProxy proxy(device); 237 238 SkImageFilter::CropRect inputCropRect(SkRect::MakeXYWH(8, 13, 80, 80)); 239 SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 30, 60, 60)); 240 SkAutoTUnref<SkImageFilter> input(make_grayscale(NULL, &inputCropRect)); 241 242 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode)); 243 SkPoint3 location(0, 0, SK_Scalar1); 244 SkPoint3 target(SK_Scalar1, SK_Scalar1, SK_Scalar1); 245 SkScalar kernel[9] = { 246 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1), 247 SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1), 248 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1), 249 }; 250 SkISize kernelSize = SkISize::Make(3, 3); 251 SkScalar gain = SK_Scalar1, bias = 0; 252 253 SkImageFilter* filters[] = { 254 SkColorFilterImageFilter::Create(cf.get(), input.get(), &cropRect), 255 SkDisplacementMapEffect::Create(SkDisplacementMapEffect::kR_ChannelSelectorType, 256 SkDisplacementMapEffect::kB_ChannelSelectorType, 257 40.0f, input.get(), input.get(), &cropRect), 258 SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect), 259 SkDropShadowImageFilter::Create(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN, input.get(), &cropRect), 260 SkLightingImageFilter::CreatePointLitDiffuse(location, SK_ColorGREEN, 0, 0, input.get(), &cropRect), 261 SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0, input.get(), &cropRect), 262 SkMatrixConvolutionImageFilter::Create(kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1), SkMatrixConvolutionImageFilter::kRepeat_TileMode, false, input.get(), &cropRect), 263 SkMergeImageFilter::Create(input.get(), input.get(), SkXfermode::kSrcOver_Mode, &cropRect), 264 SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect), 265 SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1, input.get(), &cropRect), 266 SkDilateImageFilter::Create(3, 2, input.get(), &cropRect), 267 SkErodeImageFilter::Create(2, 3, input.get(), &cropRect), 268 SkTileImageFilter::Create(inputCropRect.rect(), cropRect.rect(), input.get()), 269 SkXfermodeImageFilter::Create(SkXfermode::Create(SkXfermode::kSrcOver_Mode), input.get(), input.get(), &cropRect), 270 }; 271 272 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) { 273 SkImageFilter* filter = filters[i]; 274 SkBitmap result; 275 SkIPoint offset; 276 SkString str; 277 str.printf("filter %d", static_cast<int>(i)); 278 SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeLargest(), NULL); 279 REPORTER_ASSERT_MESSAGE(reporter, filter->filterImage(&proxy, bitmap, ctx, 280 &result, &offset), str.c_str()); 281 REPORTER_ASSERT_MESSAGE(reporter, offset.fX == 20 && offset.fY == 30, str.c_str()); 282 } 283 284 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) { 285 SkSafeUnref(filters[i]); 286 } 287 } 288 289 static SkBitmap make_gradient_circle(int width, int height) { 290 SkBitmap bitmap; 291 SkScalar x = SkIntToScalar(width / 2); 292 SkScalar y = SkIntToScalar(height / 2); 293 SkScalar radius = SkMinScalar(x, y) * 0.8f; 294 bitmap.allocN32Pixels(width, height); 295 SkCanvas canvas(bitmap); 296 canvas.clear(0x00000000); 297 SkColor colors[2]; 298 colors[0] = SK_ColorWHITE; 299 colors[1] = SK_ColorBLACK; 300 SkAutoTUnref<SkShader> shader( 301 SkGradientShader::CreateRadial(SkPoint::Make(x, y), radius, colors, NULL, 2, 302 SkShader::kClamp_TileMode) 303 ); 304 SkPaint paint; 305 paint.setShader(shader); 306 canvas.drawCircle(x, y, radius, paint); 307 return bitmap; 308 } 309 310 static void test_negative_blur_sigma(SkBaseDevice* device, skiatest::Reporter* reporter) { 311 // Check that SkBlurImageFilter will accept a negative sigma, either in 312 // the given arguments or after CTM application. 313 int width = 32, height = 32; 314 SkDeviceImageFilterProxy proxy(device); 315 SkScalar five = SkIntToScalar(5); 316 317 SkAutoTUnref<SkBlurImageFilter> positiveFilter( 318 SkBlurImageFilter::Create(five, five) 319 ); 320 321 SkAutoTUnref<SkBlurImageFilter> negativeFilter( 322 SkBlurImageFilter::Create(-five, five) 323 ); 324 325 SkBitmap gradient = make_gradient_circle(width, height); 326 SkBitmap positiveResult1, negativeResult1; 327 SkBitmap positiveResult2, negativeResult2; 328 SkIPoint offset; 329 SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeLargest(), NULL); 330 positiveFilter->filterImage(&proxy, gradient, ctx, &positiveResult1, &offset); 331 negativeFilter->filterImage(&proxy, gradient, ctx, &negativeResult1, &offset); 332 SkMatrix negativeScale; 333 negativeScale.setScale(-SK_Scalar1, SK_Scalar1); 334 SkImageFilter::Context negativeCTX(negativeScale, SkIRect::MakeLargest(), NULL); 335 positiveFilter->filterImage(&proxy, gradient, negativeCTX, &negativeResult2, &offset); 336 negativeFilter->filterImage(&proxy, gradient, negativeCTX, &positiveResult2, &offset); 337 SkAutoLockPixels lockP1(positiveResult1); 338 SkAutoLockPixels lockP2(positiveResult2); 339 SkAutoLockPixels lockN1(negativeResult1); 340 SkAutoLockPixels lockN2(negativeResult2); 341 for (int y = 0; y < height; y++) { 342 int diffs = memcmp(positiveResult1.getAddr32(0, y), negativeResult1.getAddr32(0, y), positiveResult1.rowBytes()); 343 REPORTER_ASSERT(reporter, !diffs); 344 if (diffs) { 345 break; 346 } 347 diffs = memcmp(positiveResult1.getAddr32(0, y), negativeResult2.getAddr32(0, y), positiveResult1.rowBytes()); 348 REPORTER_ASSERT(reporter, !diffs); 349 if (diffs) { 350 break; 351 } 352 diffs = memcmp(positiveResult1.getAddr32(0, y), positiveResult2.getAddr32(0, y), positiveResult1.rowBytes()); 353 REPORTER_ASSERT(reporter, !diffs); 354 if (diffs) { 355 break; 356 } 357 } 358 } 359 360 DEF_TEST(TestNegativeBlurSigma, reporter) { 361 SkBitmap temp; 362 temp.allocN32Pixels(100, 100); 363 SkBitmapDevice device(temp); 364 test_negative_blur_sigma(&device, reporter); 365 } 366 367 DEF_TEST(ImageFilterDrawTiled, reporter) { 368 // Check that all filters when drawn tiled (with subsequent clip rects) exactly 369 // match the same filters drawn with a single full-canvas bitmap draw. 370 // Tests pass by not asserting. 371 372 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorRED, SkXfermode::kSrcIn_Mode)); 373 SkPoint3 location(0, 0, SK_Scalar1); 374 SkPoint3 target(SK_Scalar1, SK_Scalar1, SK_Scalar1); 375 SkScalar kernel[9] = { 376 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1), 377 SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1), 378 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1), 379 }; 380 SkISize kernelSize = SkISize::Make(3, 3); 381 SkScalar gain = SK_Scalar1, bias = 0; 382 SkScalar five = SkIntToScalar(5); 383 384 SkAutoTUnref<SkImageFilter> gradient_source(SkBitmapSource::Create(make_gradient_circle(64, 64))); 385 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(five, five)); 386 SkMatrix matrix; 387 388 matrix.setTranslate(SK_Scalar1, SK_Scalar1); 389 matrix.postRotate(SkIntToScalar(45), SK_Scalar1, SK_Scalar1); 390 391 SkRTreeFactory factory; 392 SkPictureRecorder recorder; 393 SkCanvas* recordingCanvas = recorder.beginRecording(64, 64, &factory, 0); 394 395 SkPaint greenPaint; 396 greenPaint.setColor(SK_ColorGREEN); 397 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeXYWH(10, 10, 30, 20)), greenPaint); 398 SkAutoTUnref<SkPicture> picture(recorder.endRecording()); 399 SkAutoTUnref<SkImageFilter> pictureFilter(SkPictureImageFilter::Create(picture.get())); 400 401 struct { 402 const char* fName; 403 SkImageFilter* fFilter; 404 } filters[] = { 405 { "color filter", SkColorFilterImageFilter::Create(cf.get()) }, 406 { "displacement map", SkDisplacementMapEffect::Create( 407 SkDisplacementMapEffect::kR_ChannelSelectorType, 408 SkDisplacementMapEffect::kB_ChannelSelectorType, 409 20.0f, gradient_source.get()) }, 410 { "blur", SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1) }, 411 { "drop shadow", SkDropShadowImageFilter::Create( 412 SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_ColorGREEN) }, 413 { "diffuse lighting", SkLightingImageFilter::CreatePointLitDiffuse( 414 location, SK_ColorGREEN, 0, 0) }, 415 { "specular lighting", 416 SkLightingImageFilter::CreatePointLitSpecular(location, SK_ColorGREEN, 0, 0, 0) }, 417 { "matrix convolution", 418 SkMatrixConvolutionImageFilter::Create( 419 kernelSize, kernel, gain, bias, SkIPoint::Make(1, 1), 420 SkMatrixConvolutionImageFilter::kRepeat_TileMode, false) }, 421 { "merge", SkMergeImageFilter::Create(NULL, NULL, SkXfermode::kSrcOver_Mode) }, 422 { "offset", SkOffsetImageFilter::Create(SK_Scalar1, SK_Scalar1) }, 423 { "dilate", SkDilateImageFilter::Create(3, 2) }, 424 { "erode", SkErodeImageFilter::Create(2, 3) }, 425 { "tile", SkTileImageFilter::Create(SkRect::MakeXYWH(0, 0, 50, 50), 426 SkRect::MakeXYWH(0, 0, 100, 100), NULL) }, 427 { "matrix", SkMatrixImageFilter::Create(matrix, SkPaint::kLow_FilterLevel) }, 428 { "blur and offset", SkOffsetImageFilter::Create(five, five, blur.get()) }, 429 { "picture and blur", SkBlurImageFilter::Create(five, five, pictureFilter.get()) }, 430 }; 431 432 SkBitmap untiledResult, tiledResult; 433 int width = 64, height = 64; 434 untiledResult.allocN32Pixels(width, height); 435 tiledResult.allocN32Pixels(width, height); 436 SkCanvas tiledCanvas(tiledResult); 437 SkCanvas untiledCanvas(untiledResult); 438 int tileSize = 8; 439 440 for (int scale = 1; scale <= 2; ++scale) { 441 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) { 442 tiledCanvas.clear(0); 443 untiledCanvas.clear(0); 444 SkPaint paint; 445 paint.setImageFilter(filters[i].fFilter); 446 paint.setTextSize(SkIntToScalar(height)); 447 paint.setColor(SK_ColorWHITE); 448 SkString str; 449 const char* text = "ABC"; 450 SkScalar ypos = SkIntToScalar(height); 451 untiledCanvas.save(); 452 untiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale)); 453 untiledCanvas.drawText(text, strlen(text), 0, ypos, paint); 454 untiledCanvas.restore(); 455 for (int y = 0; y < height; y += tileSize) { 456 for (int x = 0; x < width; x += tileSize) { 457 tiledCanvas.save(); 458 tiledCanvas.clipRect(SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize))); 459 tiledCanvas.scale(SkIntToScalar(scale), SkIntToScalar(scale)); 460 tiledCanvas.drawText(text, strlen(text), 0, ypos, paint); 461 tiledCanvas.restore(); 462 } 463 } 464 untiledCanvas.flush(); 465 tiledCanvas.flush(); 466 for (int y = 0; y < height; y++) { 467 int diffs = memcmp(untiledResult.getAddr32(0, y), tiledResult.getAddr32(0, y), untiledResult.rowBytes()); 468 REPORTER_ASSERT_MESSAGE(reporter, !diffs, filters[i].fName); 469 if (diffs) { 470 break; 471 } 472 } 473 } 474 } 475 476 for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) { 477 SkSafeUnref(filters[i].fFilter); 478 } 479 } 480 481 static void draw_saveLayer_picture(int width, int height, int tileSize, 482 SkBBHFactory* factory, SkBitmap* result) { 483 484 SkMatrix matrix; 485 matrix.setTranslate(SkIntToScalar(50), 0); 486 487 SkAutoTUnref<SkColorFilter> cf(SkColorFilter::CreateModeFilter(SK_ColorWHITE, SkXfermode::kSrc_Mode)); 488 SkAutoTUnref<SkImageFilter> cfif(SkColorFilterImageFilter::Create(cf.get())); 489 SkAutoTUnref<SkImageFilter> imageFilter(SkMatrixImageFilter::Create(matrix, SkPaint::kNone_FilterLevel, cfif.get())); 490 491 SkPaint paint; 492 paint.setImageFilter(imageFilter.get()); 493 SkPictureRecorder recorder; 494 SkRect bounds = SkRect::Make(SkIRect::MakeXYWH(0, 0, 50, 50)); 495 SkCanvas* recordingCanvas = recorder.beginRecording(SkIntToScalar(width), 496 SkIntToScalar(height), 497 factory, 0); 498 recordingCanvas->translate(-55, 0); 499 recordingCanvas->saveLayer(&bounds, &paint); 500 recordingCanvas->restore(); 501 SkAutoTUnref<SkPicture> picture1(recorder.endRecording()); 502 503 result->allocN32Pixels(width, height); 504 SkCanvas canvas(*result); 505 canvas.clear(0); 506 canvas.clipRect(SkRect::Make(SkIRect::MakeWH(tileSize, tileSize))); 507 canvas.drawPicture(picture1.get()); 508 } 509 510 DEF_TEST(ImageFilterDrawMatrixBBH, reporter) { 511 // Check that matrix filter when drawn tiled with BBH exactly 512 // matches the same thing drawn without BBH. 513 // Tests pass by not asserting. 514 515 const int width = 200, height = 200; 516 const int tileSize = 100; 517 SkBitmap result1, result2; 518 SkRTreeFactory factory; 519 520 draw_saveLayer_picture(width, height, tileSize, &factory, &result1); 521 draw_saveLayer_picture(width, height, tileSize, NULL, &result2); 522 523 for (int y = 0; y < height; y++) { 524 int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes()); 525 REPORTER_ASSERT(reporter, !diffs); 526 if (diffs) { 527 break; 528 } 529 } 530 } 531 532 static SkImageFilter* makeBlur(SkImageFilter* input = NULL) { 533 return SkBlurImageFilter::Create(SK_Scalar1, SK_Scalar1, input); 534 } 535 536 static SkImageFilter* makeDropShadow(SkImageFilter* input = NULL) { 537 return SkDropShadowImageFilter::Create( 538 SkIntToScalar(100), SkIntToScalar(100), 539 SkIntToScalar(10), SkIntToScalar(10), 540 SK_ColorBLUE, input); 541 } 542 543 DEF_TEST(ImageFilterBlurThenShadowBounds, reporter) { 544 SkAutoTUnref<SkImageFilter> filter1(makeBlur()); 545 SkAutoTUnref<SkImageFilter> filter2(makeDropShadow(filter1.get())); 546 547 SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100); 548 SkIRect expectedBounds = SkIRect::MakeXYWH(-133, -133, 236, 236); 549 filter2->filterBounds(bounds, SkMatrix::I(), &bounds); 550 551 REPORTER_ASSERT(reporter, bounds == expectedBounds); 552 } 553 554 DEF_TEST(ImageFilterShadowThenBlurBounds, reporter) { 555 SkAutoTUnref<SkImageFilter> filter1(makeDropShadow()); 556 SkAutoTUnref<SkImageFilter> filter2(makeBlur(filter1.get())); 557 558 SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100); 559 SkIRect expectedBounds = SkIRect::MakeXYWH(-133, -133, 236, 236); 560 filter2->filterBounds(bounds, SkMatrix::I(), &bounds); 561 562 REPORTER_ASSERT(reporter, bounds == expectedBounds); 563 } 564 565 DEF_TEST(ImageFilterDilateThenBlurBounds, reporter) { 566 SkAutoTUnref<SkImageFilter> filter1(SkDilateImageFilter::Create(2, 2)); 567 SkAutoTUnref<SkImageFilter> filter2(makeDropShadow(filter1.get())); 568 569 SkIRect bounds = SkIRect::MakeXYWH(0, 0, 100, 100); 570 SkIRect expectedBounds = SkIRect::MakeXYWH(-132, -132, 234, 234); 571 filter2->filterBounds(bounds, SkMatrix::I(), &bounds); 572 573 REPORTER_ASSERT(reporter, bounds == expectedBounds); 574 } 575 576 static void draw_blurred_rect(SkCanvas* canvas) { 577 SkAutoTUnref<SkImageFilter> filter(SkBlurImageFilter::Create(SkIntToScalar(8), 0)); 578 SkPaint filterPaint; 579 filterPaint.setColor(SK_ColorWHITE); 580 filterPaint.setImageFilter(filter); 581 canvas->saveLayer(NULL, &filterPaint); 582 SkPaint whitePaint; 583 whitePaint.setColor(SK_ColorWHITE); 584 canvas->drawRect(SkRect::Make(SkIRect::MakeWH(4, 4)), whitePaint); 585 canvas->restore(); 586 } 587 588 static void draw_picture_clipped(SkCanvas* canvas, const SkRect& clipRect, const SkPicture* picture) { 589 canvas->save(); 590 canvas->clipRect(clipRect); 591 canvas->drawPicture(picture); 592 canvas->restore(); 593 } 594 595 DEF_TEST(ImageFilterDrawTiledBlurRTree, reporter) { 596 // Check that the blur filter when recorded with RTree acceleration, 597 // and drawn tiled (with subsequent clip rects) exactly 598 // matches the same filter drawn with without RTree acceleration. 599 // This tests that the "bleed" from the blur into the otherwise-blank 600 // tiles is correctly rendered. 601 // Tests pass by not asserting. 602 603 int width = 16, height = 8; 604 SkBitmap result1, result2; 605 result1.allocN32Pixels(width, height); 606 result2.allocN32Pixels(width, height); 607 SkCanvas canvas1(result1); 608 SkCanvas canvas2(result2); 609 int tileSize = 8; 610 611 canvas1.clear(0); 612 canvas2.clear(0); 613 614 SkRTreeFactory factory; 615 616 SkPictureRecorder recorder1, recorder2; 617 // The only difference between these two pictures is that one has RTree aceleration. 618 SkCanvas* recordingCanvas1 = recorder1.beginRecording(SkIntToScalar(width), 619 SkIntToScalar(height), 620 NULL, 0); 621 SkCanvas* recordingCanvas2 = recorder2.beginRecording(SkIntToScalar(width), 622 SkIntToScalar(height), 623 &factory, 0); 624 draw_blurred_rect(recordingCanvas1); 625 draw_blurred_rect(recordingCanvas2); 626 SkAutoTUnref<SkPicture> picture1(recorder1.endRecording()); 627 SkAutoTUnref<SkPicture> picture2(recorder2.endRecording()); 628 for (int y = 0; y < height; y += tileSize) { 629 for (int x = 0; x < width; x += tileSize) { 630 SkRect tileRect = SkRect::Make(SkIRect::MakeXYWH(x, y, tileSize, tileSize)); 631 draw_picture_clipped(&canvas1, tileRect, picture1); 632 draw_picture_clipped(&canvas2, tileRect, picture2); 633 } 634 } 635 for (int y = 0; y < height; y++) { 636 int diffs = memcmp(result1.getAddr32(0, y), result2.getAddr32(0, y), result1.rowBytes()); 637 REPORTER_ASSERT(reporter, !diffs); 638 if (diffs) { 639 break; 640 } 641 } 642 } 643 644 DEF_TEST(ImageFilterMatrixConvolution, reporter) { 645 // Check that a 1x3 filter does not cause a spurious assert. 646 SkScalar kernel[3] = { 647 SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1), 648 }; 649 SkISize kernelSize = SkISize::Make(1, 3); 650 SkScalar gain = SK_Scalar1, bias = 0; 651 SkIPoint kernelOffset = SkIPoint::Make(0, 0); 652 653 SkAutoTUnref<SkImageFilter> filter( 654 SkMatrixConvolutionImageFilter::Create( 655 kernelSize, kernel, gain, bias, kernelOffset, 656 SkMatrixConvolutionImageFilter::kRepeat_TileMode, false)); 657 658 SkBitmap result; 659 int width = 16, height = 16; 660 result.allocN32Pixels(width, height); 661 SkCanvas canvas(result); 662 canvas.clear(0); 663 664 SkPaint paint; 665 paint.setImageFilter(filter); 666 SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height)); 667 canvas.drawRect(rect, paint); 668 } 669 670 DEF_TEST(ImageFilterMatrixConvolutionBorder, reporter) { 671 // Check that a filter with borders outside the target bounds 672 // does not crash. 673 SkScalar kernel[3] = { 674 0, 0, 0, 675 }; 676 SkISize kernelSize = SkISize::Make(3, 1); 677 SkScalar gain = SK_Scalar1, bias = 0; 678 SkIPoint kernelOffset = SkIPoint::Make(2, 0); 679 680 SkAutoTUnref<SkImageFilter> filter( 681 SkMatrixConvolutionImageFilter::Create( 682 kernelSize, kernel, gain, bias, kernelOffset, 683 SkMatrixConvolutionImageFilter::kClamp_TileMode, true)); 684 685 SkBitmap result; 686 687 int width = 10, height = 10; 688 result.allocN32Pixels(width, height); 689 SkCanvas canvas(result); 690 canvas.clear(0); 691 692 SkPaint filterPaint; 693 filterPaint.setImageFilter(filter); 694 SkRect bounds = SkRect::MakeWH(1, 10); 695 SkRect rect = SkRect::Make(SkIRect::MakeWH(width, height)); 696 SkPaint rectPaint; 697 canvas.saveLayer(&bounds, &filterPaint); 698 canvas.drawRect(rect, rectPaint); 699 canvas.restore(); 700 } 701 702 DEF_TEST(ImageFilterCropRect, reporter) { 703 SkBitmap temp; 704 temp.allocN32Pixels(100, 100); 705 SkBitmapDevice device(temp); 706 test_crop_rects(&device, reporter); 707 } 708 709 DEF_TEST(ImageFilterMatrix, reporter) { 710 SkBitmap temp; 711 temp.allocN32Pixels(100, 100); 712 SkBitmapDevice device(temp); 713 SkCanvas canvas(&device); 714 canvas.scale(SkIntToScalar(2), SkIntToScalar(2)); 715 716 SkMatrix expectedMatrix = canvas.getTotalMatrix(); 717 718 SkRTreeFactory factory; 719 SkPictureRecorder recorder; 720 SkCanvas* recordingCanvas = recorder.beginRecording(100, 100, &factory, 0); 721 722 SkPaint paint; 723 SkAutoTUnref<MatrixTestImageFilter> imageFilter( 724 new MatrixTestImageFilter(reporter, expectedMatrix)); 725 paint.setImageFilter(imageFilter.get()); 726 recordingCanvas->saveLayer(NULL, &paint); 727 SkPaint solidPaint; 728 solidPaint.setColor(0xFFFFFFFF); 729 recordingCanvas->save(); 730 recordingCanvas->scale(SkIntToScalar(10), SkIntToScalar(10)); 731 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(100, 100)), solidPaint); 732 recordingCanvas->restore(); // scale 733 recordingCanvas->restore(); // saveLayer 734 SkAutoTUnref<SkPicture> picture(recorder.endRecording()); 735 736 canvas.drawPicture(picture); 737 } 738 739 DEF_TEST(ImageFilterCrossProcessPictureImageFilter, reporter) { 740 SkRTreeFactory factory; 741 SkPictureRecorder recorder; 742 SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0); 743 744 // Create an SkPicture which simply draws a green 1x1 rectangle. 745 SkPaint greenPaint; 746 greenPaint.setColor(SK_ColorGREEN); 747 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint); 748 SkAutoTUnref<SkPicture> picture(recorder.endRecording()); 749 750 // Wrap that SkPicture in an SkPictureImageFilter. 751 SkAutoTUnref<SkImageFilter> imageFilter( 752 SkPictureImageFilter::Create(picture.get())); 753 754 // Check that SkPictureImageFilter successfully serializes its contained 755 // SkPicture when not in cross-process mode. 756 SkPaint paint; 757 paint.setImageFilter(imageFilter.get()); 758 SkPictureRecorder outerRecorder; 759 SkCanvas* outerCanvas = outerRecorder.beginRecording(1, 1, &factory, 0); 760 SkPaint redPaintWithFilter; 761 redPaintWithFilter.setColor(SK_ColorRED); 762 redPaintWithFilter.setImageFilter(imageFilter.get()); 763 outerCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter); 764 SkAutoTUnref<SkPicture> outerPicture(outerRecorder.endRecording()); 765 766 SkBitmap bitmap; 767 bitmap.allocN32Pixels(1, 1); 768 SkBitmapDevice device(bitmap); 769 SkCanvas canvas(&device); 770 771 // The result here should be green, since the filter replaces the primitive's red interior. 772 canvas.clear(0x0); 773 canvas.drawPicture(outerPicture); 774 uint32_t pixel = *bitmap.getAddr32(0, 0); 775 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN); 776 777 // Check that, for now, SkPictureImageFilter does not serialize or 778 // deserialize its contained picture when the filter is serialized 779 // cross-process. Do this by "laundering" it through SkValidatingReadBuffer. 780 SkAutoTUnref<SkData> data(SkValidatingSerializeFlattenable(imageFilter.get())); 781 SkAutoTUnref<SkFlattenable> flattenable(SkValidatingDeserializeFlattenable( 782 data->data(), data->size(), SkImageFilter::GetFlattenableType())); 783 SkImageFilter* unflattenedFilter = static_cast<SkImageFilter*>(flattenable.get()); 784 785 redPaintWithFilter.setImageFilter(unflattenedFilter); 786 SkPictureRecorder crossProcessRecorder; 787 SkCanvas* crossProcessCanvas = crossProcessRecorder.beginRecording(1, 1, &factory, 0); 788 crossProcessCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), redPaintWithFilter); 789 SkAutoTUnref<SkPicture> crossProcessPicture(crossProcessRecorder.endRecording()); 790 791 canvas.clear(0x0); 792 canvas.drawPicture(crossProcessPicture); 793 pixel = *bitmap.getAddr32(0, 0); 794 // The result here should not be green, since the filter draws nothing. 795 REPORTER_ASSERT(reporter, pixel != SK_ColorGREEN); 796 } 797 798 DEF_TEST(ImageFilterClippedPictureImageFilter, reporter) { 799 SkRTreeFactory factory; 800 SkPictureRecorder recorder; 801 SkCanvas* recordingCanvas = recorder.beginRecording(1, 1, &factory, 0); 802 803 // Create an SkPicture which simply draws a green 1x1 rectangle. 804 SkPaint greenPaint; 805 greenPaint.setColor(SK_ColorGREEN); 806 recordingCanvas->drawRect(SkRect::Make(SkIRect::MakeWH(1, 1)), greenPaint); 807 SkAutoTUnref<SkPicture> picture(recorder.endRecording()); 808 809 SkAutoTUnref<SkImageFilter> imageFilter( 810 SkPictureImageFilter::Create(picture.get())); 811 812 SkBitmap result; 813 SkIPoint offset; 814 SkImageFilter::Context ctx(SkMatrix::I(), SkIRect::MakeXYWH(1, 1, 1, 1), NULL); 815 SkBitmap bitmap; 816 bitmap.allocN32Pixels(2, 2); 817 SkBitmapDevice device(bitmap); 818 SkDeviceImageFilterProxy proxy(&device); 819 REPORTER_ASSERT(reporter, !imageFilter->filterImage(&proxy, bitmap, ctx, &result, &offset)); 820 } 821 822 DEF_TEST(ImageFilterEmptySaveLayer, reporter) { 823 // Even when there's an empty saveLayer()/restore(), ensure that an image 824 // filter or color filter which affects transparent black still draws. 825 826 SkBitmap bitmap; 827 bitmap.allocN32Pixels(10, 10); 828 SkBitmapDevice device(bitmap); 829 SkCanvas canvas(&device); 830 831 SkRTreeFactory factory; 832 SkPictureRecorder recorder; 833 834 SkAutoTUnref<SkColorFilter> green( 835 SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrc_Mode)); 836 SkAutoTUnref<SkColorFilterImageFilter> imageFilter( 837 SkColorFilterImageFilter::Create(green.get())); 838 SkPaint imageFilterPaint; 839 imageFilterPaint.setImageFilter(imageFilter.get()); 840 SkPaint colorFilterPaint; 841 colorFilterPaint.setColorFilter(green.get()); 842 843 SkRect bounds = SkRect::MakeWH(10, 10); 844 845 SkCanvas* recordingCanvas = recorder.beginRecording(10, 10, &factory, 0); 846 recordingCanvas->saveLayer(&bounds, &imageFilterPaint); 847 recordingCanvas->restore(); 848 SkAutoTUnref<SkPicture> picture(recorder.endRecording()); 849 850 canvas.clear(0); 851 canvas.drawPicture(picture); 852 uint32_t pixel = *bitmap.getAddr32(0, 0); 853 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN); 854 855 recordingCanvas = recorder.beginRecording(10, 10, &factory, 0); 856 recordingCanvas->saveLayer(NULL, &imageFilterPaint); 857 recordingCanvas->restore(); 858 SkAutoTUnref<SkPicture> picture2(recorder.endRecording()); 859 860 canvas.clear(0); 861 canvas.drawPicture(picture2); 862 pixel = *bitmap.getAddr32(0, 0); 863 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN); 864 865 recordingCanvas = recorder.beginRecording(10, 10, &factory, 0); 866 recordingCanvas->saveLayer(&bounds, &colorFilterPaint); 867 recordingCanvas->restore(); 868 SkAutoTUnref<SkPicture> picture3(recorder.endRecording()); 869 870 canvas.clear(0); 871 canvas.drawPicture(picture3); 872 pixel = *bitmap.getAddr32(0, 0); 873 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN); 874 } 875 876 static void test_huge_blur(SkBaseDevice* device, skiatest::Reporter* reporter) { 877 SkCanvas canvas(device); 878 879 SkBitmap bitmap; 880 bitmap.allocN32Pixels(100, 100); 881 bitmap.eraseARGB(0, 0, 0, 0); 882 883 // Check that a blur with an insane radius does not crash or assert. 884 SkAutoTUnref<SkImageFilter> blur(SkBlurImageFilter::Create(SkIntToScalar(1<<30), SkIntToScalar(1<<30))); 885 886 SkPaint paint; 887 paint.setImageFilter(blur); 888 canvas.drawSprite(bitmap, 0, 0, &paint); 889 } 890 891 DEF_TEST(HugeBlurImageFilter, reporter) { 892 SkBitmap temp; 893 temp.allocN32Pixels(100, 100); 894 SkBitmapDevice device(temp); 895 test_huge_blur(&device, reporter); 896 } 897 898 DEF_TEST(MatrixConvolutionSanityTest, reporter) { 899 SkScalar kernel[1] = { 0 }; 900 SkScalar gain = SK_Scalar1, bias = 0; 901 SkIPoint kernelOffset = SkIPoint::Make(1, 1); 902 903 // Check that an enormous (non-allocatable) kernel gives a NULL filter. 904 SkAutoTUnref<SkImageFilter> conv(SkMatrixConvolutionImageFilter::Create( 905 SkISize::Make(1<<30, 1<<30), 906 kernel, 907 gain, 908 bias, 909 kernelOffset, 910 SkMatrixConvolutionImageFilter::kRepeat_TileMode, 911 false)); 912 913 REPORTER_ASSERT(reporter, NULL == conv.get()); 914 915 // Check that a NULL kernel gives a NULL filter. 916 conv.reset(SkMatrixConvolutionImageFilter::Create( 917 SkISize::Make(1, 1), 918 NULL, 919 gain, 920 bias, 921 kernelOffset, 922 SkMatrixConvolutionImageFilter::kRepeat_TileMode, 923 false)); 924 925 REPORTER_ASSERT(reporter, NULL == conv.get()); 926 927 // Check that a kernel width < 1 gives a NULL filter. 928 conv.reset(SkMatrixConvolutionImageFilter::Create( 929 SkISize::Make(0, 1), 930 kernel, 931 gain, 932 bias, 933 kernelOffset, 934 SkMatrixConvolutionImageFilter::kRepeat_TileMode, 935 false)); 936 937 REPORTER_ASSERT(reporter, NULL == conv.get()); 938 939 // Check that kernel height < 1 gives a NULL filter. 940 conv.reset(SkMatrixConvolutionImageFilter::Create( 941 SkISize::Make(1, -1), 942 kernel, 943 gain, 944 bias, 945 kernelOffset, 946 SkMatrixConvolutionImageFilter::kRepeat_TileMode, 947 false)); 948 949 REPORTER_ASSERT(reporter, NULL == conv.get()); 950 } 951 952 static void test_xfermode_cropped_input(SkBaseDevice* device, skiatest::Reporter* reporter) { 953 SkCanvas canvas(device); 954 canvas.clear(0); 955 956 SkBitmap bitmap; 957 bitmap.allocN32Pixels(1, 1); 958 bitmap.eraseARGB(255, 255, 255, 255); 959 960 SkAutoTUnref<SkColorFilter> green( 961 SkColorFilter::CreateModeFilter(SK_ColorGREEN, SkXfermode::kSrcIn_Mode)); 962 SkAutoTUnref<SkColorFilterImageFilter> greenFilter( 963 SkColorFilterImageFilter::Create(green.get())); 964 SkImageFilter::CropRect cropRect(SkRect::MakeEmpty()); 965 SkAutoTUnref<SkColorFilterImageFilter> croppedOut( 966 SkColorFilterImageFilter::Create(green.get(), NULL, &cropRect)); 967 968 // Check that an xfermode image filter whose input has been cropped out still draws the other 969 // input. Also check that drawing with both inputs cropped out doesn't cause a GPU warning. 970 SkXfermode* mode = SkXfermode::Create(SkXfermode::kSrcOver_Mode); 971 SkAutoTUnref<SkImageFilter> xfermodeNoFg( 972 SkXfermodeImageFilter::Create(mode, greenFilter, croppedOut)); 973 SkAutoTUnref<SkImageFilter> xfermodeNoBg( 974 SkXfermodeImageFilter::Create(mode, croppedOut, greenFilter)); 975 SkAutoTUnref<SkImageFilter> xfermodeNoFgNoBg( 976 SkXfermodeImageFilter::Create(mode, croppedOut, croppedOut)); 977 978 SkPaint paint; 979 paint.setImageFilter(xfermodeNoFg); 980 canvas.drawSprite(bitmap, 0, 0, &paint); 981 982 uint32_t pixel; 983 SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1); 984 canvas.readPixels(info, &pixel, 4, 0, 0); 985 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN); 986 987 paint.setImageFilter(xfermodeNoBg); 988 canvas.drawSprite(bitmap, 0, 0, &paint); 989 canvas.readPixels(info, &pixel, 4, 0, 0); 990 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN); 991 992 paint.setImageFilter(xfermodeNoFgNoBg); 993 canvas.drawSprite(bitmap, 0, 0, &paint); 994 canvas.readPixels(info, &pixel, 4, 0, 0); 995 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN); 996 } 997 998 DEF_TEST(ImageFilterNestedSaveLayer, reporter) { 999 SkBitmap temp; 1000 temp.allocN32Pixels(50, 50); 1001 SkBitmapDevice device(temp); 1002 SkCanvas canvas(&device); 1003 canvas.clear(0x0); 1004 1005 SkBitmap bitmap; 1006 bitmap.allocN32Pixels(10, 10); 1007 bitmap.eraseColor(SK_ColorGREEN); 1008 1009 SkMatrix matrix; 1010 matrix.setScale(SkIntToScalar(2), SkIntToScalar(2)); 1011 matrix.postTranslate(SkIntToScalar(-20), SkIntToScalar(-20)); 1012 SkAutoTUnref<SkImageFilter> matrixFilter( 1013 SkMatrixImageFilter::Create(matrix, SkPaint::kLow_FilterLevel)); 1014 1015 // Test that saveLayer() with a filter nested inside another saveLayer() applies the 1016 // correct offset to the filter matrix. 1017 SkRect bounds1 = SkRect::MakeXYWH(10, 10, 30, 30); 1018 canvas.saveLayer(&bounds1, NULL); 1019 SkPaint filterPaint; 1020 filterPaint.setImageFilter(matrixFilter); 1021 SkRect bounds2 = SkRect::MakeXYWH(20, 20, 10, 10); 1022 canvas.saveLayer(&bounds2, &filterPaint); 1023 SkPaint greenPaint; 1024 greenPaint.setColor(SK_ColorGREEN); 1025 canvas.drawRect(bounds2, greenPaint); 1026 canvas.restore(); 1027 canvas.restore(); 1028 SkPaint strokePaint; 1029 strokePaint.setStyle(SkPaint::kStroke_Style); 1030 strokePaint.setColor(SK_ColorRED); 1031 1032 SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1); 1033 uint32_t pixel; 1034 canvas.readPixels(info, &pixel, 4, 25, 25); 1035 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN); 1036 1037 // Test that drawSprite() with a filter nested inside a saveLayer() applies the 1038 // correct offset to the filter matrix. 1039 canvas.clear(0x0); 1040 canvas.readPixels(info, &pixel, 4, 25, 25); 1041 canvas.saveLayer(&bounds1, NULL); 1042 canvas.drawSprite(bitmap, 20, 20, &filterPaint); 1043 canvas.restore(); 1044 1045 canvas.readPixels(info, &pixel, 4, 25, 25); 1046 REPORTER_ASSERT(reporter, pixel == SK_ColorGREEN); 1047 } 1048 1049 DEF_TEST(XfermodeImageFilterCroppedInput, reporter) { 1050 SkBitmap temp; 1051 temp.allocN32Pixels(100, 100); 1052 SkBitmapDevice device(temp); 1053 test_xfermode_cropped_input(&device, reporter); 1054 } 1055 1056 #if SK_SUPPORT_GPU 1057 const SkSurfaceProps gProps = SkSurfaceProps(SkSurfaceProps::kLegacyFontHost_InitType); 1058 1059 DEF_GPUTEST(ImageFilterCropRectGPU, reporter, factory) { 1060 GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0)); 1061 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context, 1062 SkImageInfo::MakeN32Premul(100, 100), 1063 gProps, 1064 0)); 1065 test_crop_rects(device, reporter); 1066 } 1067 1068 DEF_GPUTEST(HugeBlurImageFilterGPU, reporter, factory) { 1069 GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0)); 1070 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context, 1071 SkImageInfo::MakeN32Premul(100, 100), 1072 gProps, 1073 0)); 1074 test_huge_blur(device, reporter); 1075 } 1076 1077 DEF_GPUTEST(XfermodeImageFilterCroppedInputGPU, reporter, factory) { 1078 GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0)); 1079 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context, 1080 SkImageInfo::MakeN32Premul(1, 1), 1081 gProps, 1082 0)); 1083 test_xfermode_cropped_input(device, reporter); 1084 } 1085 1086 DEF_GPUTEST(TestNegativeBlurSigmaGPU, reporter, factory) { 1087 GrContext* context = factory->get(static_cast<GrContextFactory::GLContextType>(0)); 1088 SkAutoTUnref<SkGpuDevice> device(SkGpuDevice::Create(context, 1089 SkImageInfo::MakeN32Premul(1, 1), 1090 gProps, 1091 0)); 1092 test_negative_blur_sigma(device, reporter); 1093 } 1094 #endif 1095