15587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com/* 25587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com * Copyright 2013 Google Inc. 35587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com * 45587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com * Use of this source code is governed by a BSD-style license that can be 55587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com * found in the LICENSE file. 65587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com */ 75587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 824519371cb541db6f59d903d21878ed9c45eb549scroggo#include "CanvasStateHelpers.h" 95587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com#include "SkCanvas.h" 105587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com#include "SkCanvasStateUtils.h" 1124519371cb541db6f59d903d21878ed9c45eb549scroggo#include "SkCommandLineFlags.h" 125587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com#include "SkDrawFilter.h" 1307f6cf372dc003694c79cfb313923fef9eaf8dc8commit-bot@chromium.org#include "SkError.h" 145587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com#include "SkPaint.h" 155587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com#include "SkRRect.h" 168f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "SkRect.h" 178f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#include "Test.h" 185587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 1924519371cb541db6f59d903d21878ed9c45eb549scroggo// dlopen and the library flag are only used for tests which require this flag. 20b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG 2124519371cb541db6f59d903d21878ed9c45eb549scroggo#include <dlfcn.h> 2224519371cb541db6f59d903d21878ed9c45eb549scroggo 2324519371cb541db6f59d903d21878ed9c45eb549scroggoDEFINE_string(library, "", "Support library to use for CanvasState test. If empty (the default), " 2424519371cb541db6f59d903d21878ed9c45eb549scroggo "the test will be run without crossing a library boundary. Otherwise, " 2524519371cb541db6f59d903d21878ed9c45eb549scroggo "it is expected to be a full path to a shared library file, which will" 2624519371cb541db6f59d903d21878ed9c45eb549scroggo " be dynamically loaded. Functions from the library will be called to " 2724519371cb541db6f59d903d21878ed9c45eb549scroggo "test SkCanvasState. Instructions for generating the library are in " 2824519371cb541db6f59d903d21878ed9c45eb549scroggo "gyp/canvas_state_lib.gyp"); 2924519371cb541db6f59d903d21878ed9c45eb549scroggo 3024519371cb541db6f59d903d21878ed9c45eb549scroggo 3124519371cb541db6f59d903d21878ed9c45eb549scroggo// This class calls dlopen on the library passed in to the command line flag library, and handles 3224519371cb541db6f59d903d21878ed9c45eb549scroggo// calling dlclose when it goes out of scope. 3324519371cb541db6f59d903d21878ed9c45eb549scroggoclass OpenLibResult { 3424519371cb541db6f59d903d21878ed9c45eb549scroggopublic: 3524519371cb541db6f59d903d21878ed9c45eb549scroggo // If the flag library was passed to this run of the test, attempt to open it using dlopen and 3624519371cb541db6f59d903d21878ed9c45eb549scroggo // report whether it succeeded. 3724519371cb541db6f59d903d21878ed9c45eb549scroggo OpenLibResult(skiatest::Reporter* reporter) { 3824519371cb541db6f59d903d21878ed9c45eb549scroggo if (FLAGS_library.count() == 1) { 3924519371cb541db6f59d903d21878ed9c45eb549scroggo fHandle = dlopen(FLAGS_library[0], RTLD_LAZY | RTLD_LOCAL); 4024519371cb541db6f59d903d21878ed9c45eb549scroggo REPORTER_ASSERT_MESSAGE(reporter, fHandle != NULL, "Failed to open library!"); 4124519371cb541db6f59d903d21878ed9c45eb549scroggo } else { 4224519371cb541db6f59d903d21878ed9c45eb549scroggo fHandle = NULL; 4324519371cb541db6f59d903d21878ed9c45eb549scroggo } 4424519371cb541db6f59d903d21878ed9c45eb549scroggo } 4524519371cb541db6f59d903d21878ed9c45eb549scroggo 4624519371cb541db6f59d903d21878ed9c45eb549scroggo // Automatically call dlclose when going out of scope. 4724519371cb541db6f59d903d21878ed9c45eb549scroggo ~OpenLibResult() { 4824519371cb541db6f59d903d21878ed9c45eb549scroggo if (fHandle) { 4924519371cb541db6f59d903d21878ed9c45eb549scroggo dlclose(fHandle); 5024519371cb541db6f59d903d21878ed9c45eb549scroggo } 5124519371cb541db6f59d903d21878ed9c45eb549scroggo } 5224519371cb541db6f59d903d21878ed9c45eb549scroggo 5324519371cb541db6f59d903d21878ed9c45eb549scroggo // Pointer to the shared library object. 5424519371cb541db6f59d903d21878ed9c45eb549scroggo void* handle() { return fHandle; } 5524519371cb541db6f59d903d21878ed9c45eb549scroggo 5624519371cb541db6f59d903d21878ed9c45eb549scroggoprivate: 5724519371cb541db6f59d903d21878ed9c45eb549scroggo void* fHandle; 5824519371cb541db6f59d903d21878ed9c45eb549scroggo}; 5924519371cb541db6f59d903d21878ed9c45eb549scroggo 6024519371cb541db6f59d903d21878ed9c45eb549scroggoDEF_TEST(CanvasState_test_complex_layers, reporter) { 615587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com const int WIDTH = 400; 625587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com const int HEIGHT = 400; 635587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com const int SPACER = 10; 645587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 6520146b3f7339d2c71c416397135e70e34f7fedb1djsollen@google.com SkRect rect = SkRect::MakeXYWH(SkIntToScalar(SPACER), SkIntToScalar(SPACER), 6620146b3f7339d2c71c416397135e70e34f7fedb1djsollen@google.com SkIntToScalar(WIDTH-(2*SPACER)), 6720146b3f7339d2c71c416397135e70e34f7fedb1djsollen@google.com SkIntToScalar((HEIGHT-(2*SPACER)) / 7)); 685587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 69fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org const SkColorType colorTypes[] = { 7028fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org kRGB_565_SkColorType, kN32_SkColorType 715587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com }; 725587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 735587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com const int layerAlpha[] = { 255, 255, 0 }; 745587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com const SkCanvas::SaveFlags flags[] = { SkCanvas::kARGB_NoClipLayer_SaveFlag, 755587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com SkCanvas::kARGB_ClipLayer_SaveFlag, 765587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com SkCanvas::kARGB_NoClipLayer_SaveFlag 775587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com }; 785587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com REPORTER_ASSERT(reporter, sizeof(layerAlpha) == sizeof(flags)); 7924519371cb541db6f59d903d21878ed9c45eb549scroggo 8024519371cb541db6f59d903d21878ed9c45eb549scroggo bool (*drawFn)(SkCanvasState* state, float l, float t, 8124519371cb541db6f59d903d21878ed9c45eb549scroggo float r, float b, int32_t s); 8224519371cb541db6f59d903d21878ed9c45eb549scroggo 8324519371cb541db6f59d903d21878ed9c45eb549scroggo OpenLibResult openLibResult(reporter); 8424519371cb541db6f59d903d21878ed9c45eb549scroggo if (openLibResult.handle() != NULL) { 8524519371cb541db6f59d903d21878ed9c45eb549scroggo *(void**) (&drawFn) = dlsym(openLibResult.handle(), 8624519371cb541db6f59d903d21878ed9c45eb549scroggo "complex_layers_draw_from_canvas_state"); 8724519371cb541db6f59d903d21878ed9c45eb549scroggo } else { 8824519371cb541db6f59d903d21878ed9c45eb549scroggo drawFn = complex_layers_draw_from_canvas_state; 8924519371cb541db6f59d903d21878ed9c45eb549scroggo } 9024519371cb541db6f59d903d21878ed9c45eb549scroggo 9124519371cb541db6f59d903d21878ed9c45eb549scroggo REPORTER_ASSERT(reporter, drawFn); 9224519371cb541db6f59d903d21878ed9c45eb549scroggo if (!drawFn) { 9324519371cb541db6f59d903d21878ed9c45eb549scroggo return; 9424519371cb541db6f59d903d21878ed9c45eb549scroggo } 955587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 96ecce60bad6e3b7a72e1eba820bc3be15d39a1c21scroggo for (size_t i = 0; i < SK_ARRAY_COUNT(colorTypes); ++i) { 975587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com SkBitmap bitmaps[2]; 985587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com for (int j = 0; j < 2; ++j) { 99fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org bitmaps[j].allocPixels(SkImageInfo::Make(WIDTH, HEIGHT, 100fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org colorTypes[i], 101fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org kPremul_SkAlphaType)); 1025587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 1035587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com SkCanvas canvas(bitmaps[j]); 1045587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 1055587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com canvas.drawColor(SK_ColorRED); 1065587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 10724519371cb541db6f59d903d21878ed9c45eb549scroggo for (size_t k = 0; k < SK_ARRAY_COUNT(layerAlpha); ++k) { 1085587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com // draw a rect within the layer's bounds and again outside the layer's bounds 1095587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com canvas.saveLayerAlpha(&rect, layerAlpha[k], flags[k]); 1105587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 1115587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com if (j) { 11224519371cb541db6f59d903d21878ed9c45eb549scroggo // Capture from the first Skia. 11324519371cb541db6f59d903d21878ed9c45eb549scroggo SkCanvasState* state = SkCanvasStateUtils::CaptureCanvasState(&canvas); 1145587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com REPORTER_ASSERT(reporter, state); 1155587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 11624519371cb541db6f59d903d21878ed9c45eb549scroggo // And draw to it in the second Skia. 11724519371cb541db6f59d903d21878ed9c45eb549scroggo bool success = complex_layers_draw_from_canvas_state(state, 11824519371cb541db6f59d903d21878ed9c45eb549scroggo rect.fLeft, rect.fTop, rect.fRight, rect.fBottom, SPACER); 11924519371cb541db6f59d903d21878ed9c45eb549scroggo REPORTER_ASSERT(reporter, success); 1205587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 12124519371cb541db6f59d903d21878ed9c45eb549scroggo // And release it in the *first* Skia. 12224519371cb541db6f59d903d21878ed9c45eb549scroggo SkCanvasStateUtils::ReleaseCanvasState(state); 12324519371cb541db6f59d903d21878ed9c45eb549scroggo } else { 12424519371cb541db6f59d903d21878ed9c45eb549scroggo // Draw in the first Skia. 12524519371cb541db6f59d903d21878ed9c45eb549scroggo complex_layers_draw(&canvas, rect.fLeft, rect.fTop, 12624519371cb541db6f59d903d21878ed9c45eb549scroggo rect.fRight, rect.fBottom, SPACER); 12724519371cb541db6f59d903d21878ed9c45eb549scroggo } 1285587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 1295587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com canvas.restore(); 1305587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 1315587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com // translate the canvas for the next iteration 1325587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com canvas.translate(0, 2*(rect.height() + SPACER)); 1335587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com } 1345587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com } 1355587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 1365587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com // now we memcmp the two bitmaps 1375587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com REPORTER_ASSERT(reporter, bitmaps[0].getSize() == bitmaps[1].getSize()); 1385587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com REPORTER_ASSERT(reporter, !memcmp(bitmaps[0].getPixels(), 1395587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com bitmaps[1].getPixels(), 1405587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com bitmaps[0].getSize())); 1415587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com } 1425587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com} 14324519371cb541db6f59d903d21878ed9c45eb549scroggo#endif 1445587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 1455587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com//////////////////////////////////////////////////////////////////////////////// 1465587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 147b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG 14824519371cb541db6f59d903d21878ed9c45eb549scroggoDEF_TEST(CanvasState_test_complex_clips, reporter) { 149339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com const int WIDTH = 400; 150339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com const int HEIGHT = 400; 1511037c7b9f2f0220c4f0a90faebe3c89d4981c1e3djsollen@google.com const int SPACER = 10; 152339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 1531037c7b9f2f0220c4f0a90faebe3c89d4981c1e3djsollen@google.com SkIRect layerRect = SkIRect::MakeWH(WIDTH, HEIGHT / 4); 154339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com layerRect.inset(2*SPACER, 2*SPACER); 155339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 1561037c7b9f2f0220c4f0a90faebe3c89d4981c1e3djsollen@google.com SkIRect clipRect = layerRect; 157339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com clipRect.fRight = clipRect.fLeft + (clipRect.width() / 2) - (2*SPACER); 158339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com clipRect.outset(SPACER, SPACER); 159339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 1601037c7b9f2f0220c4f0a90faebe3c89d4981c1e3djsollen@google.com SkIRect regionBounds = clipRect; 161339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com regionBounds.offset(clipRect.width() + (2*SPACER), 0); 162339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 163339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com SkIRect regionInterior = regionBounds; 164339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com regionInterior.inset(SPACER*3, SPACER*3); 165339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 166339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com SkRegion clipRegion; 167339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com clipRegion.setRect(regionBounds); 168339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com clipRegion.op(regionInterior, SkRegion::kDifference_Op); 169339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 170339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 171339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com const SkRegion::Op clipOps[] = { SkRegion::kIntersect_Op, 172339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com SkRegion::kIntersect_Op, 173339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com SkRegion::kReplace_Op, 174339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com }; 175339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com const SkCanvas::SaveFlags flags[] = { SkCanvas::kARGB_NoClipLayer_SaveFlag, 176339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com SkCanvas::kARGB_ClipLayer_SaveFlag, 177339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com SkCanvas::kARGB_NoClipLayer_SaveFlag, 178339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com }; 179339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com REPORTER_ASSERT(reporter, sizeof(clipOps) == sizeof(flags)); 18024519371cb541db6f59d903d21878ed9c45eb549scroggo 18124519371cb541db6f59d903d21878ed9c45eb549scroggo bool (*drawFn)(SkCanvasState* state, int32_t l, int32_t t, 18224519371cb541db6f59d903d21878ed9c45eb549scroggo int32_t r, int32_t b, int32_t clipOp, 18324519371cb541db6f59d903d21878ed9c45eb549scroggo int32_t regionRects, int32_t* rectCoords); 18424519371cb541db6f59d903d21878ed9c45eb549scroggo 18524519371cb541db6f59d903d21878ed9c45eb549scroggo OpenLibResult openLibResult(reporter); 18624519371cb541db6f59d903d21878ed9c45eb549scroggo if (openLibResult.handle() != NULL) { 18724519371cb541db6f59d903d21878ed9c45eb549scroggo *(void**) (&drawFn) = dlsym(openLibResult.handle(), 18824519371cb541db6f59d903d21878ed9c45eb549scroggo "complex_clips_draw_from_canvas_state"); 18924519371cb541db6f59d903d21878ed9c45eb549scroggo } else { 19024519371cb541db6f59d903d21878ed9c45eb549scroggo drawFn = complex_clips_draw_from_canvas_state; 19124519371cb541db6f59d903d21878ed9c45eb549scroggo } 19224519371cb541db6f59d903d21878ed9c45eb549scroggo 19324519371cb541db6f59d903d21878ed9c45eb549scroggo REPORTER_ASSERT(reporter, drawFn); 19424519371cb541db6f59d903d21878ed9c45eb549scroggo if (!drawFn) { 19524519371cb541db6f59d903d21878ed9c45eb549scroggo return; 19624519371cb541db6f59d903d21878ed9c45eb549scroggo } 197339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 198339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com SkBitmap bitmaps[2]; 199339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com for (int i = 0; i < 2; ++i) { 200fa9e5fa42a555712fb7a29d08d2ae2bdef0ed68ecommit-bot@chromium.org bitmaps[i].allocN32Pixels(WIDTH, HEIGHT); 201339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 202339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com SkCanvas canvas(bitmaps[i]); 203339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 204339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com canvas.drawColor(SK_ColorRED); 205339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 206339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com SkRegion localRegion = clipRegion; 207339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 20824519371cb541db6f59d903d21878ed9c45eb549scroggo for (size_t j = 0; j < SK_ARRAY_COUNT(flags); ++j) { 2091037c7b9f2f0220c4f0a90faebe3c89d4981c1e3djsollen@google.com SkRect layerBounds = SkRect::Make(layerRect); 2101037c7b9f2f0220c4f0a90faebe3c89d4981c1e3djsollen@google.com canvas.saveLayerAlpha(&layerBounds, 128, flags[j]); 211339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 212339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com if (i) { 21324519371cb541db6f59d903d21878ed9c45eb549scroggo SkCanvasState* state = SkCanvasStateUtils::CaptureCanvasState(&canvas); 214339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com REPORTER_ASSERT(reporter, state); 215339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 21624519371cb541db6f59d903d21878ed9c45eb549scroggo SkRegion::Iterator iter(localRegion); 21724519371cb541db6f59d903d21878ed9c45eb549scroggo SkTDArray<int32_t> rectCoords; 21824519371cb541db6f59d903d21878ed9c45eb549scroggo for (; !iter.done(); iter.next()) { 21924519371cb541db6f59d903d21878ed9c45eb549scroggo const SkIRect& rect = iter.rect(); 22024519371cb541db6f59d903d21878ed9c45eb549scroggo *rectCoords.append() = rect.fLeft; 22124519371cb541db6f59d903d21878ed9c45eb549scroggo *rectCoords.append() = rect.fTop; 22224519371cb541db6f59d903d21878ed9c45eb549scroggo *rectCoords.append() = rect.fRight; 22324519371cb541db6f59d903d21878ed9c45eb549scroggo *rectCoords.append() = rect.fBottom; 22424519371cb541db6f59d903d21878ed9c45eb549scroggo } 22524519371cb541db6f59d903d21878ed9c45eb549scroggo bool success = drawFn(state, clipRect.fLeft, clipRect.fTop, 22624519371cb541db6f59d903d21878ed9c45eb549scroggo clipRect.fRight, clipRect.fBottom, clipOps[j], 22724519371cb541db6f59d903d21878ed9c45eb549scroggo rectCoords.count() / 4, rectCoords.begin()); 22824519371cb541db6f59d903d21878ed9c45eb549scroggo REPORTER_ASSERT(reporter, success); 229339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 23024519371cb541db6f59d903d21878ed9c45eb549scroggo SkCanvasStateUtils::ReleaseCanvasState(state); 23124519371cb541db6f59d903d21878ed9c45eb549scroggo } else { 23224519371cb541db6f59d903d21878ed9c45eb549scroggo complex_clips_draw(&canvas, clipRect.fLeft, clipRect.fTop, 23324519371cb541db6f59d903d21878ed9c45eb549scroggo clipRect.fRight, clipRect.fBottom, clipOps[j], 23424519371cb541db6f59d903d21878ed9c45eb549scroggo localRegion); 23524519371cb541db6f59d903d21878ed9c45eb549scroggo } 236339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 237339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com canvas.restore(); 238339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 239339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com // translate the canvas and region for the next iteration 2401037c7b9f2f0220c4f0a90faebe3c89d4981c1e3djsollen@google.com canvas.translate(0, SkIntToScalar(2*(layerRect.height() + (SPACER)))); 241339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com localRegion.translate(0, 2*(layerRect.height() + SPACER)); 242339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com } 243339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com } 244339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 245339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com // now we memcmp the two bitmaps 246339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com REPORTER_ASSERT(reporter, bitmaps[0].getSize() == bitmaps[1].getSize()); 247339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com REPORTER_ASSERT(reporter, !memcmp(bitmaps[0].getPixels(), 248339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com bitmaps[1].getPixels(), 249339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com bitmaps[0].getSize())); 250339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com} 25124519371cb541db6f59d903d21878ed9c45eb549scroggo#endif 252339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 253339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com//////////////////////////////////////////////////////////////////////////////// 254339e79fbeabae18a8b9ea094293c7c25eaf9dd68djsollen@google.com 2555587ac09beec4c056332504f3fa85990520b43fddjsollen@google.comclass TestDrawFilter : public SkDrawFilter { 2565587ac09beec4c056332504f3fa85990520b43fddjsollen@google.compublic: 25736352bf5e38f45a70ee4f4fc132a38048d38206dmtklein bool filter(SkPaint*, Type) override { return true; } 2585587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com}; 2595587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 26024519371cb541db6f59d903d21878ed9c45eb549scroggoDEF_TEST(CanvasState_test_draw_filters, reporter) { 2615587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com TestDrawFilter drawFilter; 26215a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org SkBitmap bitmap; 26315a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org bitmap.allocN32Pixels(10, 10); 26415a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org SkCanvas canvas(bitmap); 2655587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 2665587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com canvas.setDrawFilter(&drawFilter); 2675587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 2685587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com SkCanvasState* state = SkCanvasStateUtils::CaptureCanvasState(&canvas); 2695587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com REPORTER_ASSERT(reporter, state); 2705587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com SkCanvas* tmpCanvas = SkCanvasStateUtils::CreateFromCanvasState(state); 2715587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com REPORTER_ASSERT(reporter, tmpCanvas); 2725587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 27349f085dddff10473b6ebf832a974288300224e60bsalomon REPORTER_ASSERT(reporter, canvas.getDrawFilter()); 2745587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com REPORTER_ASSERT(reporter, NULL == tmpCanvas->getDrawFilter()); 2755587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 2765587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com tmpCanvas->unref(); 2775587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com SkCanvasStateUtils::ReleaseCanvasState(state); 2785587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com} 2795587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 2805587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com//////////////////////////////////////////////////////////////////////////////// 2815587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 28207f6cf372dc003694c79cfb313923fef9eaf8dc8commit-bot@chromium.org// we need this function to prevent SkError from printing to stdout 28307f6cf372dc003694c79cfb313923fef9eaf8dc8commit-bot@chromium.orgstatic void error_callback(SkError code, void* ctx) {} 28407f6cf372dc003694c79cfb313923fef9eaf8dc8commit-bot@chromium.org 28524519371cb541db6f59d903d21878ed9c45eb549scroggoDEF_TEST(CanvasState_test_soft_clips, reporter) { 28615a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org SkBitmap bitmap; 28715a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org bitmap.allocN32Pixels(10, 10); 28815a140599942f70e47380e3f700a825c7cece3b4commit-bot@chromium.org SkCanvas canvas(bitmap); 2895587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 2905587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com SkRRect roundRect; 2915587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com roundRect.setOval(SkRect::MakeWH(5, 5)); 2925587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 2935587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com canvas.clipRRect(roundRect, SkRegion::kIntersect_Op, true); 2945587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 29507f6cf372dc003694c79cfb313923fef9eaf8dc8commit-bot@chromium.org SkSetErrorCallback(error_callback, NULL); 29607f6cf372dc003694c79cfb313923fef9eaf8dc8commit-bot@chromium.org 2975587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com SkCanvasState* state = SkCanvasStateUtils::CaptureCanvasState(&canvas); 2985587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com REPORTER_ASSERT(reporter, !state); 29907f6cf372dc003694c79cfb313923fef9eaf8dc8commit-bot@chromium.org 30007f6cf372dc003694c79cfb313923fef9eaf8dc8commit-bot@chromium.org REPORTER_ASSERT(reporter, kInvalidOperation_SkError == SkGetLastError()); 30107f6cf372dc003694c79cfb313923fef9eaf8dc8commit-bot@chromium.org SkClearLastError(); 3025587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com} 3035587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com 304b93ba45b58ad24e0e2cb75b842e24ff711c368b0reed@google.com#ifdef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG 30524519371cb541db6f59d903d21878ed9c45eb549scroggoDEF_TEST(CanvasState_test_saveLayer_clip, reporter) { 30689f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org const int WIDTH = 100; 30789f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org const int HEIGHT = 100; 30889f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org const int LAYER_WIDTH = 50; 30989f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org const int LAYER_HEIGHT = 50; 31089f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org 31189f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org SkBitmap bitmap; 31289f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org bitmap.allocN32Pixels(WIDTH, HEIGHT); 31389f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org SkCanvas canvas(bitmap); 31489f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org 31589f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org SkRect bounds = SkRect::MakeWH(SkIntToScalar(LAYER_WIDTH), SkIntToScalar(LAYER_HEIGHT)); 31689f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org canvas.clipRect(SkRect::MakeWH(SkIntToScalar(WIDTH), SkIntToScalar(HEIGHT))); 31789f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org 31889f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org // Check that saveLayer without the kClipToLayer_SaveFlag leaves the 31989f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org // clip stack unchanged. 32089f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org canvas.saveLayer(&bounds, NULL, SkCanvas::kARGB_NoClipLayer_SaveFlag); 32189f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org SkRect clipStackBounds; 32289f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org SkClipStack::BoundsType boundsType; 32389f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org canvas.getClipStack()->getBounds(&clipStackBounds, &boundsType); 32489f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org REPORTER_ASSERT(reporter, clipStackBounds.width() == WIDTH); 32589f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org REPORTER_ASSERT(reporter, clipStackBounds.height() == HEIGHT); 32689f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org canvas.restore(); 32789f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org 32889f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org // Check that saveLayer with the kClipToLayer_SaveFlag sets the clip 32989f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org // stack to the layer bounds. 33089f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org canvas.saveLayer(&bounds, NULL, SkCanvas::kARGB_ClipLayer_SaveFlag); 33189f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org canvas.getClipStack()->getBounds(&clipStackBounds, &boundsType); 33289f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org REPORTER_ASSERT(reporter, clipStackBounds.width() == LAYER_WIDTH); 33389f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org REPORTER_ASSERT(reporter, clipStackBounds.height() == LAYER_HEIGHT); 33489f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org 33589f077ced4918ded7e911bc5052b61c90ad57a9asenorblanco@chromium.org canvas.restore(); 3365587ac09beec4c056332504f3fa85990520b43fddjsollen@google.com} 33724519371cb541db6f59d903d21878ed9c45eb549scroggo#endif 338