1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2012 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h" 9cb93a386Sopenharmony_ci#include "include/core/SkCanvas.h" 10cb93a386Sopenharmony_ci#include "include/core/SkMatrix.h" 11cb93a386Sopenharmony_ci#include "include/core/SkPaint.h" 12cb93a386Sopenharmony_ci#include "include/core/SkRegion.h" 13cb93a386Sopenharmony_ci#include "include/core/SkStream.h" 14cb93a386Sopenharmony_ci#include "include/private/SkMutex.h" 15cb93a386Sopenharmony_ci#include "include/utils/SkParsePath.h" 16cb93a386Sopenharmony_ci#include "src/core/SkPathPriv.h" 17cb93a386Sopenharmony_ci#include "tests/PathOpsDebug.h" 18cb93a386Sopenharmony_ci#include "tests/PathOpsExtendedTest.h" 19cb93a386Sopenharmony_ci#include "tests/PathOpsThreadedCommon.h" 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ci#include <stdlib.h> 22cb93a386Sopenharmony_ci#include <vector> 23cb93a386Sopenharmony_ci#include <string> 24cb93a386Sopenharmony_ci#include <algorithm> 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_cistd::vector<std::string> gUniqueNames; 27cb93a386Sopenharmony_ci 28cb93a386Sopenharmony_ci#ifdef SK_BUILD_FOR_MAC 29cb93a386Sopenharmony_ci#include <sys/sysctl.h> 30cb93a386Sopenharmony_ci#endif 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_ci// std::to_string isn't implemented on android 33cb93a386Sopenharmony_ci#include <sstream> 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_citemplate <typename T> 36cb93a386Sopenharmony_cistd::string std_to_string(T value) 37cb93a386Sopenharmony_ci{ 38cb93a386Sopenharmony_ci std::ostringstream os ; 39cb93a386Sopenharmony_ci os << value ; 40cb93a386Sopenharmony_ci return os.str() ; 41cb93a386Sopenharmony_ci} 42cb93a386Sopenharmony_ci 43cb93a386Sopenharmony_cibool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result 44cb93a386Sopenharmony_ci SkDEBUGPARAMS(bool skipAssert) 45cb93a386Sopenharmony_ci SkDEBUGPARAMS(const char* testName)); 46cb93a386Sopenharmony_ci 47cb93a386Sopenharmony_cibool SimplifyDebug(const SkPath& one, SkPath* result 48cb93a386Sopenharmony_ci SkDEBUGPARAMS(bool skipAssert) 49cb93a386Sopenharmony_ci SkDEBUGPARAMS(const char* testName)); 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_cistatic const char marker[] = 52cb93a386Sopenharmony_ci "</div>\n" 53cb93a386Sopenharmony_ci "\n" 54cb93a386Sopenharmony_ci "<script type=\"text/javascript\">\n" 55cb93a386Sopenharmony_ci "\n" 56cb93a386Sopenharmony_ci "var testDivs = [\n"; 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_cistatic const char* opStrs[] = { 59cb93a386Sopenharmony_ci "kDifference_SkPathOp", 60cb93a386Sopenharmony_ci "kIntersect_SkPathOp", 61cb93a386Sopenharmony_ci "kUnion_SkPathOp", 62cb93a386Sopenharmony_ci "kXOR_PathOp", 63cb93a386Sopenharmony_ci "kReverseDifference_SkPathOp", 64cb93a386Sopenharmony_ci}; 65cb93a386Sopenharmony_ci 66cb93a386Sopenharmony_cistatic const char* opSuffixes[] = { 67cb93a386Sopenharmony_ci "d", 68cb93a386Sopenharmony_ci "i", 69cb93a386Sopenharmony_ci "u", 70cb93a386Sopenharmony_ci "o", 71cb93a386Sopenharmony_ci "r", 72cb93a386Sopenharmony_ci}; 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_cienum class ExpectSuccess { 75cb93a386Sopenharmony_ci kNo, 76cb93a386Sopenharmony_ci kYes, 77cb93a386Sopenharmony_ci kFlaky 78cb93a386Sopenharmony_ci}; 79cb93a386Sopenharmony_ci 80cb93a386Sopenharmony_cienum class SkipAssert { 81cb93a386Sopenharmony_ci kNo, 82cb93a386Sopenharmony_ci kYes 83cb93a386Sopenharmony_ci}; 84cb93a386Sopenharmony_ci 85cb93a386Sopenharmony_cienum class ExpectMatch { 86cb93a386Sopenharmony_ci kNo, 87cb93a386Sopenharmony_ci kYes, 88cb93a386Sopenharmony_ci kFlaky 89cb93a386Sopenharmony_ci}; 90cb93a386Sopenharmony_ci 91cb93a386Sopenharmony_civoid showOp(const SkPathOp op) { 92cb93a386Sopenharmony_ci switch (op) { 93cb93a386Sopenharmony_ci case kDifference_SkPathOp: 94cb93a386Sopenharmony_ci SkDebugf("op difference\n"); 95cb93a386Sopenharmony_ci break; 96cb93a386Sopenharmony_ci case kIntersect_SkPathOp: 97cb93a386Sopenharmony_ci SkDebugf("op intersect\n"); 98cb93a386Sopenharmony_ci break; 99cb93a386Sopenharmony_ci case kUnion_SkPathOp: 100cb93a386Sopenharmony_ci SkDebugf("op union\n"); 101cb93a386Sopenharmony_ci break; 102cb93a386Sopenharmony_ci case kXOR_SkPathOp: 103cb93a386Sopenharmony_ci SkDebugf("op xor\n"); 104cb93a386Sopenharmony_ci break; 105cb93a386Sopenharmony_ci case kReverseDifference_SkPathOp: 106cb93a386Sopenharmony_ci SkDebugf("op reverse difference\n"); 107cb93a386Sopenharmony_ci break; 108cb93a386Sopenharmony_ci default: 109cb93a386Sopenharmony_ci SkASSERT(0); 110cb93a386Sopenharmony_ci } 111cb93a386Sopenharmony_ci} 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ciconst int kBitWidth = 64; 114cb93a386Sopenharmony_ciconst int kBitHeight = 64; 115cb93a386Sopenharmony_ci 116cb93a386Sopenharmony_cistatic void scaleMatrix(const SkPath& one, const SkPath& two, SkMatrix& scale) { 117cb93a386Sopenharmony_ci SkRect larger = one.getBounds(); 118cb93a386Sopenharmony_ci larger.join(two.getBounds()); 119cb93a386Sopenharmony_ci SkScalar largerWidth = larger.width(); 120cb93a386Sopenharmony_ci if (largerWidth < 4) { 121cb93a386Sopenharmony_ci largerWidth = 4; 122cb93a386Sopenharmony_ci } 123cb93a386Sopenharmony_ci SkScalar largerHeight = larger.height(); 124cb93a386Sopenharmony_ci if (largerHeight < 4) { 125cb93a386Sopenharmony_ci largerHeight = 4; 126cb93a386Sopenharmony_ci } 127cb93a386Sopenharmony_ci SkScalar hScale = (kBitWidth - 2) / largerWidth; 128cb93a386Sopenharmony_ci SkScalar vScale = (kBitHeight - 2) / largerHeight; 129cb93a386Sopenharmony_ci scale.reset(); 130cb93a386Sopenharmony_ci scale.preScale(hScale, vScale); 131cb93a386Sopenharmony_ci larger.fLeft *= hScale; 132cb93a386Sopenharmony_ci larger.fRight *= hScale; 133cb93a386Sopenharmony_ci larger.fTop *= vScale; 134cb93a386Sopenharmony_ci larger.fBottom *= vScale; 135cb93a386Sopenharmony_ci SkScalar dx = -16000 > larger.fLeft ? -16000 - larger.fLeft 136cb93a386Sopenharmony_ci : 16000 < larger.fRight ? 16000 - larger.fRight : 0; 137cb93a386Sopenharmony_ci SkScalar dy = -16000 > larger.fTop ? -16000 - larger.fTop 138cb93a386Sopenharmony_ci : 16000 < larger.fBottom ? 16000 - larger.fBottom : 0; 139cb93a386Sopenharmony_ci scale.postTranslate(dx, dy); 140cb93a386Sopenharmony_ci} 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_cistatic int pathsDrawTheSame(SkBitmap& bits, const SkPath& scaledOne, const SkPath& scaledTwo, 143cb93a386Sopenharmony_ci int& error2x2) { 144cb93a386Sopenharmony_ci if (bits.width() == 0) { 145cb93a386Sopenharmony_ci bits.allocN32Pixels(kBitWidth * 2, kBitHeight); 146cb93a386Sopenharmony_ci } 147cb93a386Sopenharmony_ci SkCanvas canvas(bits); 148cb93a386Sopenharmony_ci canvas.drawColor(SK_ColorWHITE); 149cb93a386Sopenharmony_ci SkPaint paint; 150cb93a386Sopenharmony_ci canvas.save(); 151cb93a386Sopenharmony_ci const SkRect& bounds1 = scaledOne.getBounds(); 152cb93a386Sopenharmony_ci canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1); 153cb93a386Sopenharmony_ci canvas.drawPath(scaledOne, paint); 154cb93a386Sopenharmony_ci canvas.restore(); 155cb93a386Sopenharmony_ci canvas.save(); 156cb93a386Sopenharmony_ci canvas.translate(-bounds1.fLeft + 1 + kBitWidth, -bounds1.fTop + 1); 157cb93a386Sopenharmony_ci canvas.drawPath(scaledTwo, paint); 158cb93a386Sopenharmony_ci canvas.restore(); 159cb93a386Sopenharmony_ci int errors2 = 0; 160cb93a386Sopenharmony_ci int errors = 0; 161cb93a386Sopenharmony_ci for (int y = 0; y < kBitHeight - 1; ++y) { 162cb93a386Sopenharmony_ci uint32_t* addr1 = bits.getAddr32(0, y); 163cb93a386Sopenharmony_ci uint32_t* addr2 = bits.getAddr32(0, y + 1); 164cb93a386Sopenharmony_ci uint32_t* addr3 = bits.getAddr32(kBitWidth, y); 165cb93a386Sopenharmony_ci uint32_t* addr4 = bits.getAddr32(kBitWidth, y + 1); 166cb93a386Sopenharmony_ci for (int x = 0; x < kBitWidth - 1; ++x) { 167cb93a386Sopenharmony_ci // count 2x2 blocks 168cb93a386Sopenharmony_ci bool err = addr1[x] != addr3[x]; 169cb93a386Sopenharmony_ci if (err) { 170cb93a386Sopenharmony_ci errors2 += addr1[x + 1] != addr3[x + 1] 171cb93a386Sopenharmony_ci && addr2[x] != addr4[x] && addr2[x + 1] != addr4[x + 1]; 172cb93a386Sopenharmony_ci errors++; 173cb93a386Sopenharmony_ci } 174cb93a386Sopenharmony_ci } 175cb93a386Sopenharmony_ci } 176cb93a386Sopenharmony_ci error2x2 = errors2; 177cb93a386Sopenharmony_ci return errors; 178cb93a386Sopenharmony_ci} 179cb93a386Sopenharmony_ci 180cb93a386Sopenharmony_cistatic int pathsDrawTheSame(const SkPath& one, const SkPath& two, SkBitmap& bits, SkPath& scaledOne, 181cb93a386Sopenharmony_ci SkPath& scaledTwo, int& error2x2) { 182cb93a386Sopenharmony_ci SkMatrix scale; 183cb93a386Sopenharmony_ci scaleMatrix(one, two, scale); 184cb93a386Sopenharmony_ci one.transform(scale, &scaledOne); 185cb93a386Sopenharmony_ci two.transform(scale, &scaledTwo); 186cb93a386Sopenharmony_ci return pathsDrawTheSame(bits, scaledOne, scaledTwo, error2x2); 187cb93a386Sopenharmony_ci} 188cb93a386Sopenharmony_ci 189cb93a386Sopenharmony_cibool drawAsciiPaths(const SkPath& one, const SkPath& two, bool drawPaths) { 190cb93a386Sopenharmony_ci if (!drawPaths) { 191cb93a386Sopenharmony_ci return true; 192cb93a386Sopenharmony_ci } 193cb93a386Sopenharmony_ci const SkRect& bounds1 = one.getBounds(); 194cb93a386Sopenharmony_ci const SkRect& bounds2 = two.getBounds(); 195cb93a386Sopenharmony_ci SkRect larger = bounds1; 196cb93a386Sopenharmony_ci larger.join(bounds2); 197cb93a386Sopenharmony_ci SkBitmap bits; 198cb93a386Sopenharmony_ci char out[256]; 199cb93a386Sopenharmony_ci int bitWidth = SkScalarCeilToInt(larger.width()) + 2; 200cb93a386Sopenharmony_ci if (bitWidth * 2 + 1 >= (int) sizeof(out)) { 201cb93a386Sopenharmony_ci return false; 202cb93a386Sopenharmony_ci } 203cb93a386Sopenharmony_ci int bitHeight = SkScalarCeilToInt(larger.height()) + 2; 204cb93a386Sopenharmony_ci if (bitHeight >= (int) sizeof(out)) { 205cb93a386Sopenharmony_ci return false; 206cb93a386Sopenharmony_ci } 207cb93a386Sopenharmony_ci bits.allocN32Pixels(bitWidth * 2, bitHeight); 208cb93a386Sopenharmony_ci SkCanvas canvas(bits); 209cb93a386Sopenharmony_ci canvas.drawColor(SK_ColorWHITE); 210cb93a386Sopenharmony_ci SkPaint paint; 211cb93a386Sopenharmony_ci canvas.save(); 212cb93a386Sopenharmony_ci canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1); 213cb93a386Sopenharmony_ci canvas.drawPath(one, paint); 214cb93a386Sopenharmony_ci canvas.restore(); 215cb93a386Sopenharmony_ci canvas.save(); 216cb93a386Sopenharmony_ci canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1); 217cb93a386Sopenharmony_ci canvas.drawPath(two, paint); 218cb93a386Sopenharmony_ci canvas.restore(); 219cb93a386Sopenharmony_ci for (int y = 0; y < bitHeight; ++y) { 220cb93a386Sopenharmony_ci uint32_t* addr1 = bits.getAddr32(0, y); 221cb93a386Sopenharmony_ci int x; 222cb93a386Sopenharmony_ci char* outPtr = out; 223cb93a386Sopenharmony_ci for (x = 0; x < bitWidth; ++x) { 224cb93a386Sopenharmony_ci *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x'; 225cb93a386Sopenharmony_ci } 226cb93a386Sopenharmony_ci *outPtr++ = '|'; 227cb93a386Sopenharmony_ci for (x = bitWidth; x < bitWidth * 2; ++x) { 228cb93a386Sopenharmony_ci *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x'; 229cb93a386Sopenharmony_ci } 230cb93a386Sopenharmony_ci *outPtr++ = '\0'; 231cb93a386Sopenharmony_ci SkDebugf("%s\n", out); 232cb93a386Sopenharmony_ci } 233cb93a386Sopenharmony_ci return true; 234cb93a386Sopenharmony_ci} 235cb93a386Sopenharmony_ci 236cb93a386Sopenharmony_ciint comparePaths(skiatest::Reporter* reporter, const char* filename, const SkPath& one, 237cb93a386Sopenharmony_ci const SkPath& two, SkBitmap& bitmap) { 238cb93a386Sopenharmony_ci int errors2x2; 239cb93a386Sopenharmony_ci SkPath scaledOne, scaledTwo; 240cb93a386Sopenharmony_ci (void) pathsDrawTheSame(one, two, bitmap, scaledOne, scaledTwo, errors2x2); 241cb93a386Sopenharmony_ci if (errors2x2 == 0) { 242cb93a386Sopenharmony_ci return 0; 243cb93a386Sopenharmony_ci } 244cb93a386Sopenharmony_ci const int MAX_ERRORS = 9; 245cb93a386Sopenharmony_ci return errors2x2 > MAX_ERRORS ? errors2x2 : 0; 246cb93a386Sopenharmony_ci} 247cb93a386Sopenharmony_ci 248cb93a386Sopenharmony_cistatic SkTDArray<SkPathOp> gTestOp; 249cb93a386Sopenharmony_ci 250cb93a386Sopenharmony_cistatic void showPathOpPath(const char* testName, const SkPath& one, const SkPath& two, 251cb93a386Sopenharmony_ci const SkPath& a, const SkPath& b, const SkPath& scaledOne, const SkPath& scaledTwo, 252cb93a386Sopenharmony_ci const SkPathOp shapeOp, const SkMatrix& scale) { 253cb93a386Sopenharmony_ci SkASSERT((unsigned) shapeOp < SK_ARRAY_COUNT(opStrs)); 254cb93a386Sopenharmony_ci if (!testName) { 255cb93a386Sopenharmony_ci testName = "xOp"; 256cb93a386Sopenharmony_ci } 257cb93a386Sopenharmony_ci SkDebugf("static void %s_%s(skiatest::Reporter* reporter, const char* filename) {\n", 258cb93a386Sopenharmony_ci testName, opSuffixes[shapeOp]); 259cb93a386Sopenharmony_ci *gTestOp.append() = shapeOp; 260cb93a386Sopenharmony_ci SkDebugf(" SkPath path, pathB;\n"); 261cb93a386Sopenharmony_ci SkPathOpsDebug::ShowOnePath(a, "path", false); 262cb93a386Sopenharmony_ci SkPathOpsDebug::ShowOnePath(b, "pathB", false); 263cb93a386Sopenharmony_ci SkDebugf(" testPathOp(reporter, path, pathB, %s, filename);\n", opStrs[shapeOp]); 264cb93a386Sopenharmony_ci SkDebugf("}\n"); 265cb93a386Sopenharmony_ci drawAsciiPaths(scaledOne, scaledTwo, true); 266cb93a386Sopenharmony_ci} 267cb93a386Sopenharmony_ci 268cb93a386Sopenharmony_cistatic int comparePaths(skiatest::Reporter* reporter, const char* testName, const SkPath& one, 269cb93a386Sopenharmony_ci const SkPath& scaledOne, const SkPath& two, const SkPath& scaledTwo, SkBitmap& bitmap, 270cb93a386Sopenharmony_ci const SkPath& a, const SkPath& b, const SkPathOp shapeOp, const SkMatrix& scale, 271cb93a386Sopenharmony_ci ExpectMatch expectMatch) { 272cb93a386Sopenharmony_ci static SkMutex& compareDebugOut3 = *(new SkMutex); 273cb93a386Sopenharmony_ci int errors2x2; 274cb93a386Sopenharmony_ci const int MAX_ERRORS = 8; 275cb93a386Sopenharmony_ci (void) pathsDrawTheSame(bitmap, scaledOne, scaledTwo, errors2x2); 276cb93a386Sopenharmony_ci if (ExpectMatch::kNo == expectMatch) { 277cb93a386Sopenharmony_ci if (errors2x2 < MAX_ERRORS) { 278cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0); 279cb93a386Sopenharmony_ci } 280cb93a386Sopenharmony_ci return 0; 281cb93a386Sopenharmony_ci } 282cb93a386Sopenharmony_ci if (errors2x2 == 0) { 283cb93a386Sopenharmony_ci return 0; 284cb93a386Sopenharmony_ci } 285cb93a386Sopenharmony_ci if (ExpectMatch::kYes == expectMatch && errors2x2 >= MAX_ERRORS) { 286cb93a386Sopenharmony_ci SkAutoMutexExclusive autoM(compareDebugOut3); 287cb93a386Sopenharmony_ci showPathOpPath(testName, one, two, a, b, scaledOne, scaledTwo, shapeOp, scale); 288cb93a386Sopenharmony_ci SkDebugf("\n/*"); 289cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0); 290cb93a386Sopenharmony_ci SkDebugf(" */\n"); 291cb93a386Sopenharmony_ci } 292cb93a386Sopenharmony_ci return errors2x2 >= MAX_ERRORS ? errors2x2 : 0; 293cb93a386Sopenharmony_ci} 294cb93a386Sopenharmony_ci 295cb93a386Sopenharmony_ci// Default values for when reporter->verbose() is false. 296cb93a386Sopenharmony_cistatic int sTestNumber = 55; 297cb93a386Sopenharmony_cistatic const char* sTestName = "pathOpTest"; 298cb93a386Sopenharmony_ci 299cb93a386Sopenharmony_cistatic void appendTestName(const char* nameSuffix, std::string& out) { 300cb93a386Sopenharmony_ci out += sTestName; 301cb93a386Sopenharmony_ci out += std_to_string(sTestNumber); 302cb93a386Sopenharmony_ci ++sTestNumber; 303cb93a386Sopenharmony_ci if (nameSuffix) { 304cb93a386Sopenharmony_ci out.append(nameSuffix); 305cb93a386Sopenharmony_ci } 306cb93a386Sopenharmony_ci} 307cb93a386Sopenharmony_ci 308cb93a386Sopenharmony_cistatic void appendTest(const char* pathStr, const char* pathPrefix, const char* nameSuffix, 309cb93a386Sopenharmony_ci const char* testFunction, bool twoPaths, std::string& out) { 310cb93a386Sopenharmony_ci#if 0 311cb93a386Sopenharmony_ci out.append("\n<div id=\""); 312cb93a386Sopenharmony_ci appendTestName(nameSuffix, out); 313cb93a386Sopenharmony_ci out.append("\">\n"); 314cb93a386Sopenharmony_ci if (pathPrefix) { 315cb93a386Sopenharmony_ci out.append(pathPrefix); 316cb93a386Sopenharmony_ci } 317cb93a386Sopenharmony_ci out.append(pathStr); 318cb93a386Sopenharmony_ci out.append("</div>\n\n"); 319cb93a386Sopenharmony_ci 320cb93a386Sopenharmony_ci out.append(marker); 321cb93a386Sopenharmony_ci out.append(" "); 322cb93a386Sopenharmony_ci appendTestName(nameSuffix, out); 323cb93a386Sopenharmony_ci out.append(",\n\n\n"); 324cb93a386Sopenharmony_ci#endif 325cb93a386Sopenharmony_ci out.append("static void "); 326cb93a386Sopenharmony_ci appendTestName(nameSuffix, out); 327cb93a386Sopenharmony_ci out.append("(skiatest::Reporter* reporter) {\n SkPath path"); 328cb93a386Sopenharmony_ci if (twoPaths) { 329cb93a386Sopenharmony_ci out.append(", pathB"); 330cb93a386Sopenharmony_ci } 331cb93a386Sopenharmony_ci out.append(";\n"); 332cb93a386Sopenharmony_ci if (pathPrefix) { 333cb93a386Sopenharmony_ci out.append(pathPrefix); 334cb93a386Sopenharmony_ci } 335cb93a386Sopenharmony_ci out += pathStr; 336cb93a386Sopenharmony_ci out += " "; 337cb93a386Sopenharmony_ci out += testFunction; 338cb93a386Sopenharmony_ci#if 0 339cb93a386Sopenharmony_ci out.append("static void (*firstTest)() = "); 340cb93a386Sopenharmony_ci appendTestName(nameSuffix, out); 341cb93a386Sopenharmony_ci out.append(";\n\n"); 342cb93a386Sopenharmony_ci 343cb93a386Sopenharmony_ci out.append("static struct {\n"); 344cb93a386Sopenharmony_ci out.append(" void (*fun)();\n"); 345cb93a386Sopenharmony_ci out.append(" const char* str;\n"); 346cb93a386Sopenharmony_ci out.append("} tests[] = {\n"); 347cb93a386Sopenharmony_ci out.append(" TEST("); 348cb93a386Sopenharmony_ci appendTestName(nameSuffix, out); 349cb93a386Sopenharmony_ci out.append("),\n"); 350cb93a386Sopenharmony_ci#endif 351cb93a386Sopenharmony_ci} 352cb93a386Sopenharmony_ci 353cb93a386Sopenharmony_civoid markTestFlakyForPathKit() { 354cb93a386Sopenharmony_ci if (PathOpsDebug::gJson) { 355cb93a386Sopenharmony_ci SkASSERT(!PathOpsDebug::gMarkJsonFlaky); 356cb93a386Sopenharmony_ci PathOpsDebug::gMarkJsonFlaky = true; 357cb93a386Sopenharmony_ci } 358cb93a386Sopenharmony_ci} 359cb93a386Sopenharmony_ci 360cb93a386Sopenharmony_cibool testSimplify(SkPath& path, bool useXor, SkPath& out, PathOpsThreadState& state, 361cb93a386Sopenharmony_ci const char* pathStr) { 362cb93a386Sopenharmony_ci static SkMutex& simplifyDebugOut = *(new SkMutex); 363cb93a386Sopenharmony_ci SkPathFillType fillType = useXor ? SkPathFillType::kEvenOdd : SkPathFillType::kWinding; 364cb93a386Sopenharmony_ci path.setFillType(fillType); 365cb93a386Sopenharmony_ci state.fReporter->bumpTestCount(); 366cb93a386Sopenharmony_ci if (!Simplify(path, &out)) { 367cb93a386Sopenharmony_ci SkDebugf("%s did not expect failure\n", __FUNCTION__); 368cb93a386Sopenharmony_ci REPORTER_ASSERT(state.fReporter, 0); 369cb93a386Sopenharmony_ci return false; 370cb93a386Sopenharmony_ci } 371cb93a386Sopenharmony_ci if (!state.fReporter->verbose()) { 372cb93a386Sopenharmony_ci return true; 373cb93a386Sopenharmony_ci } 374cb93a386Sopenharmony_ci int result = comparePaths(state.fReporter, nullptr, path, out, *state.fBitmap); 375cb93a386Sopenharmony_ci if (result) { 376cb93a386Sopenharmony_ci SkAutoMutexExclusive autoM(simplifyDebugOut); 377cb93a386Sopenharmony_ci std::string str; 378cb93a386Sopenharmony_ci const char* pathPrefix = nullptr; 379cb93a386Sopenharmony_ci const char* nameSuffix = nullptr; 380cb93a386Sopenharmony_ci if (fillType == SkPathFillType::kEvenOdd) { 381cb93a386Sopenharmony_ci pathPrefix = " path.setFillType(SkPathFillType::kEvenOdd);\n"; 382cb93a386Sopenharmony_ci nameSuffix = "x"; 383cb93a386Sopenharmony_ci } 384cb93a386Sopenharmony_ci const char testFunction[] = "testSimplify(reporter, path);"; 385cb93a386Sopenharmony_ci appendTest(pathStr, pathPrefix, nameSuffix, testFunction, false, str); 386cb93a386Sopenharmony_ci SkDebugf("%s", str.c_str()); 387cb93a386Sopenharmony_ci REPORTER_ASSERT(state.fReporter, 0); 388cb93a386Sopenharmony_ci } 389cb93a386Sopenharmony_ci state.fReporter->bumpTestCount(); 390cb93a386Sopenharmony_ci return result == 0; 391cb93a386Sopenharmony_ci} 392cb93a386Sopenharmony_ci 393cb93a386Sopenharmony_cistatic void json_status(ExpectSuccess expectSuccess, ExpectMatch expectMatch, bool opSucceeded) { 394cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, " \"expectSuccess\": \"%s\",\n", 395cb93a386Sopenharmony_ci ExpectSuccess::kNo == expectSuccess ? "no" : 396cb93a386Sopenharmony_ci ExpectSuccess::kYes == expectSuccess ? "yes" : "flaky"); 397cb93a386Sopenharmony_ci if (PathOpsDebug::gMarkJsonFlaky) { 398cb93a386Sopenharmony_ci expectMatch = ExpectMatch::kFlaky; 399cb93a386Sopenharmony_ci PathOpsDebug::gMarkJsonFlaky = false; 400cb93a386Sopenharmony_ci } 401cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, " \"expectMatch\": \"%s\",\n", 402cb93a386Sopenharmony_ci ExpectMatch::kNo == expectMatch ? "no" : 403cb93a386Sopenharmony_ci ExpectMatch::kYes == expectMatch ? "yes" : "flaky"); 404cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, " \"succeeded\": %s,\n", opSucceeded ? "true" : "false"); 405cb93a386Sopenharmony_ci} 406cb93a386Sopenharmony_ci 407cb93a386Sopenharmony_cistatic void json_path_out(const SkPath& path, const char* pathName, const char* fillTypeName, 408cb93a386Sopenharmony_ci bool lastField) { 409cb93a386Sopenharmony_ci char const * const gFillTypeStrs[] = { 410cb93a386Sopenharmony_ci "Winding", 411cb93a386Sopenharmony_ci "EvenOdd", 412cb93a386Sopenharmony_ci "InverseWinding", 413cb93a386Sopenharmony_ci "InverseEvenOdd", 414cb93a386Sopenharmony_ci }; 415cb93a386Sopenharmony_ci if (PathOpsDebug::gOutputSVG) { 416cb93a386Sopenharmony_ci SkString svg; 417cb93a386Sopenharmony_ci SkParsePath::ToSVGString(path, &svg); 418cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, " \"%s\": \"%s\",\n", pathName, svg.c_str()); 419cb93a386Sopenharmony_ci } else { 420cb93a386Sopenharmony_ci // MOVE, LINE, QUAD, CONIC, CUBIC, CLOSE 421cb93a386Sopenharmony_ci const int verbConst[] = { 0, 1, 2, 3, 4, 5 }; 422cb93a386Sopenharmony_ci const int pointIndex[] = { 0, 1, 1, 1, 1, 0 }; 423cb93a386Sopenharmony_ci const int pointCount[] = { 1, 2, 3, 3, 4, 0 }; 424cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, " \"%s\": [", pathName); 425cb93a386Sopenharmony_ci bool first = true; 426cb93a386Sopenharmony_ci for (auto [verb, points, w] : SkPathPriv::Iterate(path)) { 427cb93a386Sopenharmony_ci if (first) { 428cb93a386Sopenharmony_ci first = false; 429cb93a386Sopenharmony_ci } else { 430cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, ",\n "); 431cb93a386Sopenharmony_ci } 432cb93a386Sopenharmony_ci int verbIndex = (int) verb; 433cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, "[%d", verbConst[verbIndex]); 434cb93a386Sopenharmony_ci for (int i = pointIndex[verbIndex]; i < pointCount[verbIndex]; ++i) { 435cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, ", \"0x%08x\", \"0x%08x\"", 436cb93a386Sopenharmony_ci SkFloat2Bits(points[i].fX), SkFloat2Bits(points[i].fY)); 437cb93a386Sopenharmony_ci } 438cb93a386Sopenharmony_ci if (SkPathVerb::kConic == verb) { 439cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, ", \"0x%08x\"", SkFloat2Bits(*w)); 440cb93a386Sopenharmony_ci } 441cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, "]"); 442cb93a386Sopenharmony_ci } 443cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, "],\n"); 444cb93a386Sopenharmony_ci } 445cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, " \"fillType%s\": \"k%s_FillType\"%s", fillTypeName, 446cb93a386Sopenharmony_ci gFillTypeStrs[(int) path.getFillType()], lastField ? "\n}" : ",\n"); 447cb93a386Sopenharmony_ci} 448cb93a386Sopenharmony_ci 449cb93a386Sopenharmony_cistatic bool check_for_duplicate_names(const char* testName) { 450cb93a386Sopenharmony_ci if (PathOpsDebug::gCheckForDuplicateNames) { 451cb93a386Sopenharmony_ci if (gUniqueNames.end() != std::find(gUniqueNames.begin(), gUniqueNames.end(), 452cb93a386Sopenharmony_ci std::string(testName))) { 453cb93a386Sopenharmony_ci SkDebugf("%s", ""); // convenience for setting breakpoints 454cb93a386Sopenharmony_ci } 455cb93a386Sopenharmony_ci gUniqueNames.push_back(std::string(testName)); 456cb93a386Sopenharmony_ci return true; 457cb93a386Sopenharmony_ci } 458cb93a386Sopenharmony_ci return false; 459cb93a386Sopenharmony_ci} 460cb93a386Sopenharmony_ci 461cb93a386Sopenharmony_cistatic bool inner_simplify(skiatest::Reporter* reporter, const SkPath& path, const char* filename, 462cb93a386Sopenharmony_ci ExpectSuccess expectSuccess, SkipAssert skipAssert, ExpectMatch expectMatch) { 463cb93a386Sopenharmony_ci if (PathOpsDebug::gJson) { 464cb93a386Sopenharmony_ci if (check_for_duplicate_names(filename)) { 465cb93a386Sopenharmony_ci return true; 466cb93a386Sopenharmony_ci } 467cb93a386Sopenharmony_ci if (!PathOpsDebug::gOutFirst) { 468cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, ",\n"); 469cb93a386Sopenharmony_ci } 470cb93a386Sopenharmony_ci PathOpsDebug::gOutFirst = false; 471cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, "\"%s\": {\n", filename); 472cb93a386Sopenharmony_ci json_path_out(path, "path", "", false); 473cb93a386Sopenharmony_ci } 474cb93a386Sopenharmony_ci SkPath out; 475cb93a386Sopenharmony_ci if (!SimplifyDebug(path, &out SkDEBUGPARAMS(SkipAssert::kYes == skipAssert) 476cb93a386Sopenharmony_ci SkDEBUGPARAMS(sTestName))) { 477cb93a386Sopenharmony_ci if (ExpectSuccess::kYes == expectSuccess) { 478cb93a386Sopenharmony_ci SkDebugf("%s did not expect %s failure\n", __FUNCTION__, filename); 479cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0); 480cb93a386Sopenharmony_ci } 481cb93a386Sopenharmony_ci if (PathOpsDebug::gJson) { 482cb93a386Sopenharmony_ci json_status(expectSuccess, expectMatch, false); 483cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, " \"out\": \"\"\n}"); 484cb93a386Sopenharmony_ci } 485cb93a386Sopenharmony_ci return false; 486cb93a386Sopenharmony_ci } else { 487cb93a386Sopenharmony_ci if (ExpectSuccess::kNo == expectSuccess) { 488cb93a386Sopenharmony_ci SkDebugf("%s %s unexpected success\n", __FUNCTION__, filename); 489cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0); 490cb93a386Sopenharmony_ci } 491cb93a386Sopenharmony_ci if (PathOpsDebug::gJson) { 492cb93a386Sopenharmony_ci json_status(expectSuccess, expectMatch, true); 493cb93a386Sopenharmony_ci json_path_out(out, "out", "Out", true); 494cb93a386Sopenharmony_ci } 495cb93a386Sopenharmony_ci } 496cb93a386Sopenharmony_ci SkBitmap bitmap; 497cb93a386Sopenharmony_ci int errors = comparePaths(reporter, filename, path, out, bitmap); 498cb93a386Sopenharmony_ci if (ExpectMatch::kNo == expectMatch) { 499cb93a386Sopenharmony_ci if (!errors) { 500cb93a386Sopenharmony_ci SkDebugf("%s failing test %s now succeeds\n", __FUNCTION__, filename); 501cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0); 502cb93a386Sopenharmony_ci return false; 503cb93a386Sopenharmony_ci } 504cb93a386Sopenharmony_ci } else if (ExpectMatch::kYes == expectMatch && errors) { 505cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0); 506cb93a386Sopenharmony_ci } 507cb93a386Sopenharmony_ci reporter->bumpTestCount(); 508cb93a386Sopenharmony_ci return errors == 0; 509cb93a386Sopenharmony_ci} 510cb93a386Sopenharmony_ci 511cb93a386Sopenharmony_cibool testSimplify(skiatest::Reporter* reporter, const SkPath& path, const char* filename) { 512cb93a386Sopenharmony_ci return inner_simplify(reporter, path, filename, ExpectSuccess::kYes, SkipAssert::kNo, 513cb93a386Sopenharmony_ci ExpectMatch::kYes); 514cb93a386Sopenharmony_ci} 515cb93a386Sopenharmony_ci 516cb93a386Sopenharmony_cibool testSimplifyFuzz(skiatest::Reporter* reporter, const SkPath& path, const char* filename) { 517cb93a386Sopenharmony_ci return inner_simplify(reporter, path, filename, ExpectSuccess::kFlaky, SkipAssert::kYes, 518cb93a386Sopenharmony_ci ExpectMatch::kFlaky); 519cb93a386Sopenharmony_ci} 520cb93a386Sopenharmony_ci 521cb93a386Sopenharmony_cibool testSimplifyCheck(skiatest::Reporter* reporter, const SkPath& path, const char* filename, 522cb93a386Sopenharmony_ci bool checkFail) { 523cb93a386Sopenharmony_ci return inner_simplify(reporter, path, filename, checkFail ? 524cb93a386Sopenharmony_ci ExpectSuccess::kYes : ExpectSuccess::kNo, SkipAssert::kNo, ExpectMatch::kNo); 525cb93a386Sopenharmony_ci} 526cb93a386Sopenharmony_ci 527cb93a386Sopenharmony_cibool testSimplifyFail(skiatest::Reporter* reporter, const SkPath& path, const char* filename) { 528cb93a386Sopenharmony_ci return inner_simplify(reporter, path, filename, 529cb93a386Sopenharmony_ci ExpectSuccess::kNo, SkipAssert::kYes, ExpectMatch::kNo); 530cb93a386Sopenharmony_ci} 531cb93a386Sopenharmony_ci 532cb93a386Sopenharmony_cistatic bool innerPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b, 533cb93a386Sopenharmony_ci const SkPathOp shapeOp, const char* testName, ExpectSuccess expectSuccess, 534cb93a386Sopenharmony_ci SkipAssert skipAssert, ExpectMatch expectMatch) { 535cb93a386Sopenharmony_ci if (PathOpsDebug::gJson) { 536cb93a386Sopenharmony_ci if (check_for_duplicate_names(testName)) { 537cb93a386Sopenharmony_ci return true; 538cb93a386Sopenharmony_ci } 539cb93a386Sopenharmony_ci if (!PathOpsDebug::gOutFirst) { 540cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, ",\n"); 541cb93a386Sopenharmony_ci } 542cb93a386Sopenharmony_ci PathOpsDebug::gOutFirst = false; 543cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, "\"%s\": {\n", testName); 544cb93a386Sopenharmony_ci json_path_out(a, "p1", "1", false); 545cb93a386Sopenharmony_ci json_path_out(b, "p2", "2", false); 546cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, " \"op\": \"%s\",\n", opStrs[shapeOp]); 547cb93a386Sopenharmony_ci } 548cb93a386Sopenharmony_ci SkPath out; 549cb93a386Sopenharmony_ci if (!OpDebug(a, b, shapeOp, &out SkDEBUGPARAMS(SkipAssert::kYes == skipAssert) 550cb93a386Sopenharmony_ci SkDEBUGPARAMS(testName))) { 551cb93a386Sopenharmony_ci if (ExpectSuccess::kYes == expectSuccess) { 552cb93a386Sopenharmony_ci SkDebugf("%s %s did not expect failure\n", __FUNCTION__, testName); 553cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0); 554cb93a386Sopenharmony_ci } 555cb93a386Sopenharmony_ci if (PathOpsDebug::gJson) { 556cb93a386Sopenharmony_ci json_status(expectSuccess, expectMatch, false); 557cb93a386Sopenharmony_ci fprintf(PathOpsDebug::gOut, " \"out\": \"\"\n}"); 558cb93a386Sopenharmony_ci } 559cb93a386Sopenharmony_ci return false; 560cb93a386Sopenharmony_ci } else { 561cb93a386Sopenharmony_ci if (ExpectSuccess::kNo == expectSuccess) { 562cb93a386Sopenharmony_ci SkDebugf("%s %s unexpected success\n", __FUNCTION__, testName); 563cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0); 564cb93a386Sopenharmony_ci } 565cb93a386Sopenharmony_ci if (PathOpsDebug::gJson) { 566cb93a386Sopenharmony_ci json_status(expectSuccess, expectMatch, true); 567cb93a386Sopenharmony_ci json_path_out(out, "out", "Out", true); 568cb93a386Sopenharmony_ci } 569cb93a386Sopenharmony_ci } 570cb93a386Sopenharmony_ci if (!reporter->verbose()) { 571cb93a386Sopenharmony_ci return true; 572cb93a386Sopenharmony_ci } 573cb93a386Sopenharmony_ci SkPath pathOut, scaledPathOut; 574cb93a386Sopenharmony_ci SkRegion rgnA, rgnB, openClip, rgnOut; 575cb93a386Sopenharmony_ci openClip.setRect({-16000, -16000, 16000, 16000}); 576cb93a386Sopenharmony_ci rgnA.setPath(a, openClip); 577cb93a386Sopenharmony_ci rgnB.setPath(b, openClip); 578cb93a386Sopenharmony_ci rgnOut.op(rgnA, rgnB, (SkRegion::Op) shapeOp); 579cb93a386Sopenharmony_ci rgnOut.getBoundaryPath(&pathOut); 580cb93a386Sopenharmony_ci 581cb93a386Sopenharmony_ci SkMatrix scale; 582cb93a386Sopenharmony_ci scaleMatrix(a, b, scale); 583cb93a386Sopenharmony_ci SkRegion scaledRgnA, scaledRgnB, scaledRgnOut; 584cb93a386Sopenharmony_ci SkPath scaledA, scaledB; 585cb93a386Sopenharmony_ci scaledA.addPath(a, scale); 586cb93a386Sopenharmony_ci scaledA.setFillType(a.getFillType()); 587cb93a386Sopenharmony_ci scaledB.addPath(b, scale); 588cb93a386Sopenharmony_ci scaledB.setFillType(b.getFillType()); 589cb93a386Sopenharmony_ci scaledRgnA.setPath(scaledA, openClip); 590cb93a386Sopenharmony_ci scaledRgnB.setPath(scaledB, openClip); 591cb93a386Sopenharmony_ci scaledRgnOut.op(scaledRgnA, scaledRgnB, (SkRegion::Op) shapeOp); 592cb93a386Sopenharmony_ci scaledRgnOut.getBoundaryPath(&scaledPathOut); 593cb93a386Sopenharmony_ci SkBitmap bitmap; 594cb93a386Sopenharmony_ci SkPath scaledOut; 595cb93a386Sopenharmony_ci scaledOut.addPath(out, scale); 596cb93a386Sopenharmony_ci scaledOut.setFillType(out.getFillType()); 597cb93a386Sopenharmony_ci int result = comparePaths(reporter, testName, pathOut, scaledPathOut, out, scaledOut, bitmap, 598cb93a386Sopenharmony_ci a, b, shapeOp, scale, expectMatch); 599cb93a386Sopenharmony_ci reporter->bumpTestCount(); 600cb93a386Sopenharmony_ci return result == 0; 601cb93a386Sopenharmony_ci} 602cb93a386Sopenharmony_ci 603cb93a386Sopenharmony_cibool testPathOp(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b, 604cb93a386Sopenharmony_ci const SkPathOp shapeOp, const char* testName) { 605cb93a386Sopenharmony_ci return innerPathOp(reporter, a, b, shapeOp, testName, ExpectSuccess::kYes, SkipAssert::kNo, 606cb93a386Sopenharmony_ci ExpectMatch::kYes); 607cb93a386Sopenharmony_ci} 608cb93a386Sopenharmony_ci 609cb93a386Sopenharmony_cibool testPathOpCheck(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b, 610cb93a386Sopenharmony_ci const SkPathOp shapeOp, const char* testName, bool checkFail) { 611cb93a386Sopenharmony_ci return innerPathOp(reporter, a, b, shapeOp, testName, checkFail ? 612cb93a386Sopenharmony_ci ExpectSuccess::kYes : ExpectSuccess::kNo, SkipAssert::kNo, ExpectMatch::kNo); 613cb93a386Sopenharmony_ci} 614cb93a386Sopenharmony_ci 615cb93a386Sopenharmony_cibool testPathOpFuzz(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b, 616cb93a386Sopenharmony_ci const SkPathOp shapeOp, const char* testName) { 617cb93a386Sopenharmony_ci return innerPathOp(reporter, a, b, shapeOp, testName, ExpectSuccess::kFlaky, SkipAssert::kYes, 618cb93a386Sopenharmony_ci ExpectMatch::kFlaky); 619cb93a386Sopenharmony_ci} 620cb93a386Sopenharmony_ci 621cb93a386Sopenharmony_cibool testPathOpFail(skiatest::Reporter* reporter, const SkPath& a, const SkPath& b, 622cb93a386Sopenharmony_ci const SkPathOp shapeOp, const char* testName) { 623cb93a386Sopenharmony_ci SkPath orig; 624cb93a386Sopenharmony_ci orig.lineTo(54, 43); 625cb93a386Sopenharmony_ci SkPath out = orig; 626cb93a386Sopenharmony_ci if (Op(a, b, shapeOp, &out) ) { 627cb93a386Sopenharmony_ci SkDebugf("%s test is expected to fail\n", __FUNCTION__); 628cb93a386Sopenharmony_ci REPORTER_ASSERT(reporter, 0); 629cb93a386Sopenharmony_ci return false; 630cb93a386Sopenharmony_ci } 631cb93a386Sopenharmony_ci SkASSERT(out == orig); 632cb93a386Sopenharmony_ci return true; 633cb93a386Sopenharmony_ci} 634cb93a386Sopenharmony_ci 635cb93a386Sopenharmony_civoid initializeTests(skiatest::Reporter* reporter, const char* test) { 636cb93a386Sopenharmony_ci static SkMutex& mu = *(new SkMutex); 637cb93a386Sopenharmony_ci if (reporter->verbose()) { 638cb93a386Sopenharmony_ci SkAutoMutexExclusive lock(mu); 639cb93a386Sopenharmony_ci sTestName = test; 640cb93a386Sopenharmony_ci size_t testNameSize = strlen(test); 641cb93a386Sopenharmony_ci SkFILEStream inFile("../../experimental/Intersection/op.htm"); 642cb93a386Sopenharmony_ci if (inFile.isValid()) { 643cb93a386Sopenharmony_ci SkTDArray<char> inData; 644cb93a386Sopenharmony_ci inData.setCount((int) inFile.getLength()); 645cb93a386Sopenharmony_ci size_t inLen = inData.count(); 646cb93a386Sopenharmony_ci inFile.read(inData.begin(), inLen); 647cb93a386Sopenharmony_ci inFile.close(); 648cb93a386Sopenharmony_ci char* insert = strstr(inData.begin(), marker); 649cb93a386Sopenharmony_ci if (insert) { 650cb93a386Sopenharmony_ci insert += sizeof(marker) - 1; 651cb93a386Sopenharmony_ci const char* numLoc = insert + 4 /* indent spaces */ + testNameSize - 1; 652cb93a386Sopenharmony_ci sTestNumber = atoi(numLoc) + 1; 653cb93a386Sopenharmony_ci } 654cb93a386Sopenharmony_ci } 655cb93a386Sopenharmony_ci } 656cb93a386Sopenharmony_ci} 657cb93a386Sopenharmony_ci 658cb93a386Sopenharmony_civoid PathOpsThreadState::outputProgress(const char* pathStr, SkPathFillType pathFillType) { 659cb93a386Sopenharmony_ci const char testFunction[] = "testSimplify(path);"; 660cb93a386Sopenharmony_ci const char* pathPrefix = nullptr; 661cb93a386Sopenharmony_ci const char* nameSuffix = nullptr; 662cb93a386Sopenharmony_ci if (pathFillType == SkPathFillType::kEvenOdd) { 663cb93a386Sopenharmony_ci pathPrefix = " path.setFillType(SkPathFillType::kEvenOdd);\n"; 664cb93a386Sopenharmony_ci nameSuffix = "x"; 665cb93a386Sopenharmony_ci } 666cb93a386Sopenharmony_ci appendTest(pathStr, pathPrefix, nameSuffix, testFunction, false, fPathStr); 667cb93a386Sopenharmony_ci} 668cb93a386Sopenharmony_ci 669cb93a386Sopenharmony_civoid PathOpsThreadState::outputProgress(const char* pathStr, SkPathOp op) { 670cb93a386Sopenharmony_ci const char testFunction[] = "testOp(path);"; 671cb93a386Sopenharmony_ci SkASSERT((size_t) op < SK_ARRAY_COUNT(opSuffixes)); 672cb93a386Sopenharmony_ci const char* nameSuffix = opSuffixes[op]; 673cb93a386Sopenharmony_ci appendTest(pathStr, nullptr, nameSuffix, testFunction, true, fPathStr); 674cb93a386Sopenharmony_ci} 675cb93a386Sopenharmony_ci 676cb93a386Sopenharmony_civoid RunTestSet(skiatest::Reporter* reporter, TestDesc tests[], size_t count, 677cb93a386Sopenharmony_ci void (*firstTest)(skiatest::Reporter* , const char* filename), 678cb93a386Sopenharmony_ci void (*skipTest)(skiatest::Reporter* , const char* filename), 679cb93a386Sopenharmony_ci void (*stopTest)(skiatest::Reporter* , const char* filename), bool reverse) { 680cb93a386Sopenharmony_ci size_t index; 681cb93a386Sopenharmony_ci if (firstTest) { 682cb93a386Sopenharmony_ci index = count - 1; 683cb93a386Sopenharmony_ci while (index > 0 && tests[index].fun != firstTest) { 684cb93a386Sopenharmony_ci --index; 685cb93a386Sopenharmony_ci } 686cb93a386Sopenharmony_ci (*tests[index].fun)(reporter, tests[index].str); 687cb93a386Sopenharmony_ci if (tests[index].fun == stopTest) { 688cb93a386Sopenharmony_ci return; 689cb93a386Sopenharmony_ci } 690cb93a386Sopenharmony_ci } 691cb93a386Sopenharmony_ci index = reverse ? count - 1 : 0; 692cb93a386Sopenharmony_ci size_t last = reverse ? 0 : count - 1; 693cb93a386Sopenharmony_ci bool foundSkip = !skipTest; 694cb93a386Sopenharmony_ci do { 695cb93a386Sopenharmony_ci if (tests[index].fun == skipTest) { 696cb93a386Sopenharmony_ci foundSkip = true; 697cb93a386Sopenharmony_ci } 698cb93a386Sopenharmony_ci if (foundSkip && tests[index].fun != firstTest) { 699cb93a386Sopenharmony_ci (*tests[index].fun)(reporter, tests[index].str); 700cb93a386Sopenharmony_ci } 701cb93a386Sopenharmony_ci if (tests[index].fun == stopTest || index == last) { 702cb93a386Sopenharmony_ci break; 703cb93a386Sopenharmony_ci } 704cb93a386Sopenharmony_ci index += reverse ? -1 : 1; 705cb93a386Sopenharmony_ci } while (true); 706cb93a386Sopenharmony_ci} 707