|  | /* | 
|  | * Copyright 2012 Google Inc. | 
|  | * | 
|  | * Use of this source code is governed by a BSD-style license that can be | 
|  | * found in the LICENSE file. | 
|  | */ | 
|  |  | 
|  | #include "include/core/SkPath.h" | 
|  | #include "include/core/SkPathTypes.h" | 
|  | #include "include/core/SkScalar.h" | 
|  | #include "include/core/SkString.h" | 
|  | #include "include/core/SkTypes.h" | 
|  | #include "include/private/base/SkMacros.h" | 
|  | #include "include/private/base/SkTDArray.h" | 
|  | #include "tests/PathOpsExtendedTest.h" | 
|  | #include "tests/PathOpsThreadedCommon.h" | 
|  | #include "tests/Test.h" | 
|  |  | 
|  | // four rects, of four sizes | 
|  | // for 3 smaller sizes, tall, wide | 
|  | // top upper mid lower bottom aligned (3 bits, 5 values) | 
|  | // same with x (3 bits, 5 values) | 
|  | // not included, square, tall, wide (2 bits) | 
|  | // cw or ccw (1 bit) | 
|  |  | 
|  | static void testSimplify4x4RectsMain(PathOpsThreadState* data) | 
|  | { | 
|  | SkASSERT(data); | 
|  | PathOpsThreadState& state = *data; | 
|  | int aShape = state.fA & 0x03; | 
|  | SkPathDirection aCW = state.fA >> 2 ? SkPathDirection::kCCW : SkPathDirection::kCW; | 
|  | int bShape = state.fB & 0x03; | 
|  | SkPathDirection bCW = state.fB >> 2 ? SkPathDirection::kCCW : SkPathDirection::kCW; | 
|  | int cShape = state.fC & 0x03; | 
|  | SkPathDirection cCW = state.fC >> 2 ? SkPathDirection::kCCW : SkPathDirection::kCW; | 
|  | int dShape = state.fD & 0x03; | 
|  | SkPathDirection dCW = state.fD >> 2 ? SkPathDirection::kCCW : SkPathDirection::kCW; | 
|  | for (int aXAlign = 0; aXAlign < 5; ++aXAlign) { | 
|  | for (int aYAlign = 0; aYAlign < 5; ++aYAlign) { | 
|  | for (int bXAlign = 0; bXAlign < 5; ++bXAlign) { | 
|  | for (int bYAlign = 0; bYAlign < 5; ++bYAlign) { | 
|  | for (int cXAlign = 0; cXAlign < 5; ++cXAlign) { | 
|  | for (int cYAlign = 0; cYAlign < 5; ++cYAlign) { | 
|  | for (int dXAlign = 0; dXAlign < 5; ++dXAlign) { | 
|  | for (int dYAlign = 0; dYAlign < 5; ++dYAlign) { | 
|  | SkString pathStr; | 
|  | SkPath path, out; | 
|  | int l SK_INIT_TO_AVOID_WARNING, t SK_INIT_TO_AVOID_WARNING, | 
|  | r SK_INIT_TO_AVOID_WARNING, b SK_INIT_TO_AVOID_WARNING; | 
|  | if (aShape) { | 
|  | switch (aShape) { | 
|  | case 1:  // square | 
|  | l =  0; r = 60; | 
|  | t =  0; b = 60; | 
|  | aXAlign = 5; | 
|  | aYAlign = 5; | 
|  | break; | 
|  | case 2: | 
|  | l =  aXAlign * 12; | 
|  | r =  l + 30; | 
|  | t =  0; b = 60; | 
|  | aYAlign = 5; | 
|  | break; | 
|  | case 3: | 
|  | l =  0; r = 60; | 
|  | t =  aYAlign * 12; | 
|  | b =  l + 30; | 
|  | aXAlign = 5; | 
|  | break; | 
|  | } | 
|  | path.addRect(SkIntToScalar(l), SkIntToScalar(t), SkIntToScalar(r), SkIntToScalar(b), | 
|  | aCW); | 
|  | if (state.fReporter->verbose()) { | 
|  | pathStr.appendf("    path.addRect(%d, %d, %d, %d," | 
|  | " SkPathDirection::kC%sW);\n", l, t, r, b, | 
|  | aCW == SkPathDirection::kCCW ? "C" : ""); | 
|  | } | 
|  | } else { | 
|  | aXAlign = 5; | 
|  | aYAlign = 5; | 
|  | } | 
|  | if (bShape) { | 
|  | switch (bShape) { | 
|  | case 1:  // square | 
|  | l =  bXAlign * 10; | 
|  | r =  l + 20; | 
|  | t =  bYAlign * 10; | 
|  | b =  l + 20; | 
|  | break; | 
|  | case 2: | 
|  | l =  bXAlign * 10; | 
|  | r =  l + 20; | 
|  | t =  10; b = 40; | 
|  | bYAlign = 5; | 
|  | break; | 
|  | case 3: | 
|  | l =  10; r = 40; | 
|  | t =  bYAlign * 10; | 
|  | b =  l + 20; | 
|  | bXAlign = 5; | 
|  | break; | 
|  | } | 
|  | path.addRect(SkIntToScalar(l), SkIntToScalar(t), SkIntToScalar(r), SkIntToScalar(b), | 
|  | bCW); | 
|  | if (state.fReporter->verbose()) { | 
|  | pathStr.appendf("    path.addRect(%d, %d, %d, %d," | 
|  | " SkPathDirection::kC%sW);\n", l, t, r, b, | 
|  | bCW == SkPathDirection::kCCW ? "C" : ""); | 
|  | } | 
|  | } else { | 
|  | bXAlign = 5; | 
|  | bYAlign = 5; | 
|  | } | 
|  | if (cShape) { | 
|  | switch (cShape) { | 
|  | case 1:  // square | 
|  | l =  cXAlign * 6; | 
|  | r =  l + 12; | 
|  | t =  cYAlign * 6; | 
|  | b =  l + 12; | 
|  | break; | 
|  | case 2: | 
|  | l =  cXAlign * 6; | 
|  | r =  l + 12; | 
|  | t =  20; b = 30; | 
|  | cYAlign = 5; | 
|  | break; | 
|  | case 3: | 
|  | l =  20; r = 30; | 
|  | t =  cYAlign * 6; | 
|  | b =  l + 20; | 
|  | cXAlign = 5; | 
|  | break; | 
|  | } | 
|  | path.addRect(SkIntToScalar(l), SkIntToScalar(t), SkIntToScalar(r), SkIntToScalar(b), | 
|  | cCW); | 
|  | if (state.fReporter->verbose()) { | 
|  | pathStr.appendf("    path.addRect(%d, %d, %d, %d," | 
|  | " SkPathDirection::kC%sW);\n", l, t, r, b, | 
|  | cCW == SkPathDirection::kCCW ? "C" : ""); | 
|  | } | 
|  | } else { | 
|  | cXAlign = 5; | 
|  | cYAlign = 5; | 
|  | } | 
|  | if (dShape) { | 
|  | switch (dShape) { | 
|  | case 1:  // square | 
|  | l =  dXAlign * 4; | 
|  | r =  l + 9; | 
|  | t =  dYAlign * 4; | 
|  | b =  l + 9; | 
|  | break; | 
|  | case 2: | 
|  | l =  dXAlign * 6; | 
|  | r =  l + 9; | 
|  | t =  32; b = 36; | 
|  | dYAlign = 5; | 
|  | break; | 
|  | case 3: | 
|  | l =  32; r = 36; | 
|  | t =  dYAlign * 6; | 
|  | b =  l + 9; | 
|  | dXAlign = 5; | 
|  | break; | 
|  | } | 
|  | path.addRect(SkIntToScalar(l), SkIntToScalar(t), SkIntToScalar(r), SkIntToScalar(b), | 
|  | dCW); | 
|  | if (state.fReporter->verbose()) { | 
|  | pathStr.appendf("    path.addRect(%d, %d, %d, %d," | 
|  | " SkPathDirection::kC%sW);\n", l, t, r, b, | 
|  | dCW == SkPathDirection::kCCW ? "C" : ""); | 
|  | } | 
|  | } else { | 
|  | dXAlign = 5; | 
|  | dYAlign = 5; | 
|  | } | 
|  | path.close(); | 
|  | if (state.fReporter->verbose()) { | 
|  | state.outputProgress(pathStr.c_str(), SkPathFillType::kWinding); | 
|  | } | 
|  | testSimplify(path, false, out, state, pathStr.c_str()); | 
|  | if (state.fReporter->verbose()) { | 
|  | state.outputProgress(pathStr.c_str(), SkPathFillType::kEvenOdd); | 
|  | } | 
|  | testSimplify(path, true, out, state, pathStr.c_str()); | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | DEF_TEST(PathOpsSimplifyRectsThreaded, reporter) { | 
|  | initializeTests(reporter, "testLine"); | 
|  | PathOpsThreadedTestRunner testRunner(reporter); | 
|  | for (int a = 0; a < 8; ++a) {  // outermost | 
|  | for (int b = a ; b < 8; ++b) { | 
|  | for (int c = b ; c < 8; ++c) { | 
|  | for (int d = c; d < 8; ++d) { | 
|  | *testRunner.fRunnables.append() = new PathOpsThreadedRunnable( | 
|  | &testSimplify4x4RectsMain, a, b, c, d, &testRunner); | 
|  | } | 
|  | if (!reporter->allowExtendedTest()) goto finish; | 
|  | } | 
|  | } | 
|  | } | 
|  | finish: | 
|  | testRunner.render(); | 
|  | } |