Flutter Engine
The Flutter Engine
Enumerations | Functions | Variables
PathOpsExtendedTest.cpp File Reference
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathTypes.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRegion.h"
#include "include/core/SkScalar.h"
#include "include/core/SkStream.h"
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkDebug.h"
#include "include/private/base/SkMutex.h"
#include "include/private/base/SkTDArray.h"
#include "include/utils/SkParsePath.h"
#include "src/base/SkFloatBits.h"
#include "src/core/SkPathPriv.h"
#include "src/pathops/SkPathOpsDebug.h"
#include "tests/PathOpsDebug.h"
#include "tests/PathOpsExtendedTest.h"
#include "tests/PathOpsThreadedCommon.h"
#include "tests/Test.h"
#include <algorithm>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <vector>
#include <sstream>

Go to the source code of this file.

Enumerations

enum class  ExpectSuccess { kNo , kYes , kFlaky }
 
enum class  SkipAssert { kNo , kYes }
 
enum class  ExpectMatch { kNo , kYes , kFlaky }
 

Functions

template<typename T >
std::string std_to_string (T value)
 
bool OpDebug (const SkPath &one, const SkPath &two, SkPathOp op, SkPath *result SkDEBUGPARAMS(bool skipAssert) SkDEBUGPARAMS(const char *testName))
 
bool SimplifyDebug (const SkPath &one, SkPath *result SkDEBUGPARAMS(bool skipAssert) SkDEBUGPARAMS(const char *testName))
 
void showOp (const SkPathOp op)
 
static void scaleMatrix (const SkPath &one, const SkPath &two, SkMatrix &scale)
 
static int pathsDrawTheSame (SkBitmap &bits, const SkPath &scaledOne, const SkPath &scaledTwo, int &error2x2)
 
static int pathsDrawTheSame (const SkPath &one, const SkPath &two, SkBitmap &bits, SkPath &scaledOne, SkPath &scaledTwo, int &error2x2)
 
bool drawAsciiPaths (const SkPath &one, const SkPath &two, bool drawPaths)
 
int comparePaths (skiatest::Reporter *reporter, const char *filename, const SkPath &one, const SkPath &two, SkBitmap &bitmap)
 
static void showPathOpPath (const char *testName, const SkPath &one, const SkPath &two, const SkPath &a, const SkPath &b, const SkPath &scaledOne, const SkPath &scaledTwo, const SkPathOp shapeOp, const SkMatrix &scale)
 
static int comparePaths (skiatest::Reporter *reporter, const char *testName, const SkPath &one, const SkPath &scaledOne, const SkPath &two, const SkPath &scaledTwo, SkBitmap &bitmap, const SkPath &a, const SkPath &b, const SkPathOp shapeOp, const SkMatrix &scale, ExpectMatch expectMatch)
 
static void appendTestName (const char *nameSuffix, std::string &out)
 
static void appendTest (const char *pathStr, const char *pathPrefix, const char *nameSuffix, const char *testFunction, bool twoPaths, std::string &out)
 
void markTestFlakyForPathKit ()
 
bool testSimplify (SkPath &path, bool useXor, SkPath &out, PathOpsThreadState &state, const char *pathStr)
 
static void json_status (ExpectSuccess expectSuccess, ExpectMatch expectMatch, bool opSucceeded)
 
static void json_path_out (const SkPath &path, const char *pathName, const char *fillTypeName, bool lastField)
 
static bool check_for_duplicate_names (const char *testName)
 
static bool inner_simplify (skiatest::Reporter *reporter, const SkPath &path, const char *filename, ExpectSuccess expectSuccess, SkipAssert skipAssert, ExpectMatch expectMatch)
 
bool testSimplify (skiatest::Reporter *reporter, const SkPath &path, const char *filename)
 
bool testSimplifyFuzz (skiatest::Reporter *reporter, const SkPath &path, const char *filename)
 
bool testSimplifyCheck (skiatest::Reporter *reporter, const SkPath &path, const char *filename, bool checkFail)
 
bool testSimplifyFail (skiatest::Reporter *reporter, const SkPath &path, const char *filename)
 
static bool innerPathOp (skiatest::Reporter *reporter, const SkPath &a, const SkPath &b, const SkPathOp shapeOp, const char *testName, ExpectSuccess expectSuccess, SkipAssert skipAssert, ExpectMatch expectMatch)
 
bool testPathOp (skiatest::Reporter *reporter, const SkPath &a, const SkPath &b, const SkPathOp shapeOp, const char *testName)
 
bool testPathOpCheck (skiatest::Reporter *reporter, const SkPath &a, const SkPath &b, const SkPathOp shapeOp, const char *testName, bool checkFail)
 
bool testPathOpFuzz (skiatest::Reporter *reporter, const SkPath &a, const SkPath &b, const SkPathOp shapeOp, const char *testName)
 
bool testPathOpFail (skiatest::Reporter *reporter, const SkPath &a, const SkPath &b, const SkPathOp shapeOp, const char *testName)
 
void initializeTests (skiatest::Reporter *reporter, const char *test)
 
void RunTestSet (skiatest::Reporter *reporter, TestDesc tests[], size_t count, void(*firstTest)(skiatest::Reporter *, const char *filename), void(*skipTest)(skiatest::Reporter *, const char *filename), void(*stopTest)(skiatest::Reporter *, const char *filename), bool reverse)
 

Variables

std::vector< std::string > gUniqueNames
 
static const char marker []
 
static const char * opStrs []
 
static const char * opSuffixes []
 
const int kBitWidth = 64
 
const int kBitHeight = 64
 
static SkTDArray< SkPathOpgTestOp
 
static int sTestNumber = 55
 
static const char * sTestName = "pathOpTest"
 

Enumeration Type Documentation

◆ ExpectMatch

enum class ExpectMatch
strong
Enumerator
kNo 
kYes 
kFlaky 

Definition at line 101 of file PathOpsExtendedTest.cpp.

101 {
102 kNo,
103 kYes,
104 kFlaky
105};
@ kYes
Do pre-clip the geometry before applying the (perspective) matrix.
@ kNo
Don't pre-clip the geometry before applying the (perspective) matrix.

◆ ExpectSuccess

enum class ExpectSuccess
strong
Enumerator
kNo 
kYes 
kFlaky 

Definition at line 90 of file PathOpsExtendedTest.cpp.

90 {
91 kNo,
92 kYes,
93 kFlaky
94};

◆ SkipAssert

enum class SkipAssert
strong
Enumerator
kNo 
kYes 

Definition at line 96 of file PathOpsExtendedTest.cpp.

96 {
97 kNo,
98 kYes
99};

Function Documentation

◆ appendTest()

static void appendTest ( const char *  pathStr,
const char *  pathPrefix,
const char *  nameSuffix,
const char *  testFunction,
bool  twoPaths,
std::string &  out 
)
static

Definition at line 324 of file PathOpsExtendedTest.cpp.

325 {
326#if 0
327 out.append("\n<div id=\"");
328 appendTestName(nameSuffix, out);
329 out.append("\">\n");
330 if (pathPrefix) {
331 out.append(pathPrefix);
332 }
333 out.append(pathStr);
334 out.append("</div>\n\n");
335
336 out.append(marker);
337 out.append(" ");
338 appendTestName(nameSuffix, out);
339 out.append(",\n\n\n");
340#endif
341 out.append("static void ");
342 appendTestName(nameSuffix, out);
343 out.append("(skiatest::Reporter* reporter) {\n SkPath path");
344 if (twoPaths) {
345 out.append(", pathB");
346 }
347 out.append(";\n");
348 if (pathPrefix) {
349 out.append(pathPrefix);
350 }
351 out += pathStr;
352 out += " ";
353 out += testFunction;
354#if 0
355 out.append("static void (*firstTest)() = ");
356 appendTestName(nameSuffix, out);
357 out.append(";\n\n");
358
359 out.append("static struct {\n");
360 out.append(" void (*fun)();\n");
361 out.append(" const char* str;\n");
362 out.append("} tests[] = {\n");
363 out.append(" TEST(");
364 appendTestName(nameSuffix, out);
365 out.append("),\n");
366#endif
367}
static const char marker[]
static void appendTestName(const char *nameSuffix, std::string &out)
static int testFunction(int x)

◆ appendTestName()

static void appendTestName ( const char *  nameSuffix,
std::string &  out 
)
static

Definition at line 315 of file PathOpsExtendedTest.cpp.

315 {
316 out += sTestName;
318 ++sTestNumber;
319 if (nameSuffix) {
320 out.append(nameSuffix);
321 }
322}
std::string std_to_string(T value)
static int sTestNumber
static const char * sTestName

◆ check_for_duplicate_names()

static bool check_for_duplicate_names ( const char *  testName)
static

Definition at line 464 of file PathOpsExtendedTest.cpp.

464 {
466 if (gUniqueNames.end() != std::find(gUniqueNames.begin(), gUniqueNames.end(),
467 std::string(testName))) {
468 SkDebugf("%s", ""); // convenience for setting breakpoints
469 }
470 gUniqueNames.push_back(std::string(testName));
471 return true;
472 }
473 return false;
474}
std::vector< std::string > gUniqueNames
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
int find(T *array, int N, T item)
static bool gCheckForDuplicateNames
Definition: PathOpsDebug.h:18

◆ comparePaths() [1/2]

int comparePaths ( skiatest::Reporter reporter,
const char *  filename,
const SkPath one,
const SkPath two,
SkBitmap bitmap 
)

Definition at line 252 of file PathOpsExtendedTest.cpp.

253 {
254 int errors2x2;
255 SkPath scaledOne, scaledTwo;
256 (void) pathsDrawTheSame(one, two, bitmap, scaledOne, scaledTwo, errors2x2);
257 if (errors2x2 == 0) {
258 return 0;
259 }
260 const int MAX_ERRORS = 9;
261 return errors2x2 > MAX_ERRORS ? errors2x2 : 0;
262}
static int pathsDrawTheSame(SkBitmap &bits, const SkPath &scaledOne, const SkPath &scaledTwo, int &error2x2)
Definition: SkPath.h:59
Definition: bitmap.py:1

◆ comparePaths() [2/2]

static int comparePaths ( skiatest::Reporter reporter,
const char *  testName,
const SkPath one,
const SkPath scaledOne,
const SkPath two,
const SkPath scaledTwo,
SkBitmap bitmap,
const SkPath a,
const SkPath b,
const SkPathOp  shapeOp,
const SkMatrix scale,
ExpectMatch  expectMatch 
)
static

Definition at line 284 of file PathOpsExtendedTest.cpp.

287 {
288 static SkMutex& compareDebugOut3 = *(new SkMutex);
289 int errors2x2;
290 const int MAX_ERRORS = 8;
291 (void) pathsDrawTheSame(bitmap, scaledOne, scaledTwo, errors2x2);
292 if (ExpectMatch::kNo == expectMatch) {
293 if (errors2x2 < MAX_ERRORS) {
295 }
296 return 0;
297 }
298 if (errors2x2 == 0) {
299 return 0;
300 }
301 if (ExpectMatch::kYes == expectMatch && errors2x2 >= MAX_ERRORS) {
302 SkAutoMutexExclusive autoM(compareDebugOut3);
303 showPathOpPath(testName, one, two, a, b, scaledOne, scaledTwo, shapeOp, scale);
304 SkDebugf("\n/*");
306 SkDebugf(" */\n");
307 }
308 return errors2x2 >= MAX_ERRORS ? errors2x2 : 0;
309}
reporter
Definition: FontMgrTest.cpp:39
static void showPathOpPath(const char *testName, const SkPath &one, const SkPath &two, const SkPath &a, const SkPath &b, const SkPath &scaledOne, const SkPath &scaledTwo, const SkPathOp shapeOp, const SkMatrix &scale)
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
static bool b
struct MyStruct a[10]
const Scalar scale

◆ drawAsciiPaths()

bool drawAsciiPaths ( const SkPath one,
const SkPath two,
bool  drawPaths 
)

Definition at line 205 of file PathOpsExtendedTest.cpp.

205 {
206 if (!drawPaths) {
207 return true;
208 }
209 const SkRect& bounds1 = one.getBounds();
210 const SkRect& bounds2 = two.getBounds();
211 SkRect larger = bounds1;
212 larger.join(bounds2);
214 char out[256];
215 int bitWidth = SkScalarCeilToInt(larger.width()) + 2;
216 if (bitWidth * 2 + 1 >= (int) sizeof(out)) {
217 return false;
218 }
219 int bitHeight = SkScalarCeilToInt(larger.height()) + 2;
220 if (bitHeight >= (int) sizeof(out)) {
221 return false;
222 }
223 bits.allocN32Pixels(bitWidth * 2, bitHeight);
224 SkCanvas canvas(bits);
225 canvas.drawColor(SK_ColorWHITE);
227 canvas.save();
228 canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
229 canvas.drawPath(one, paint);
230 canvas.restore();
231 canvas.save();
232 canvas.translate(-bounds1.fLeft + 1 + bitWidth, -bounds1.fTop + 1);
233 canvas.drawPath(two, paint);
234 canvas.restore();
235 for (int y = 0; y < bitHeight; ++y) {
236 uint32_t* addr1 = bits.getAddr32(0, y);
237 int x;
238 char* outPtr = out;
239 for (x = 0; x < bitWidth; ++x) {
240 *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x';
241 }
242 *outPtr++ = '|';
243 for (x = bitWidth; x < bitWidth * 2; ++x) {
244 *outPtr++ = addr1[x] == (uint32_t) -1 ? '_' : 'x';
245 }
246 *outPtr++ = '\0';
247 SkDebugf("%s\n", out);
248 }
249 return true;
250}
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
#define SkScalarCeilToInt(x)
Definition: SkScalar.h:36
const SkRect & getBounds() const
Definition: SkPath.cpp:430
const Paint & paint
Definition: color_source.cc:38
double y
double x
SkScalar fLeft
smaller x-axis bounds
Definition: extension.cpp:14
constexpr float height() const
Definition: SkRect.h:769
constexpr float width() const
Definition: SkRect.h:762
void join(const SkRect &r)
Definition: SkRect.cpp:126
SkScalar fTop
smaller y-axis bounds
Definition: extension.cpp:15

◆ initializeTests()

void initializeTests ( skiatest::Reporter reporter,
const char *  test 
)

Definition at line 650 of file PathOpsExtendedTest.cpp.

650 {
651 static SkMutex& mu = *(new SkMutex);
652 if (reporter->verbose()) {
653 SkAutoMutexExclusive lock(mu);
654 sTestName = test;
655 size_t testNameSize = strlen(test);
656 SkFILEStream inFile("../../experimental/Intersection/op.htm");
657 if (inFile.isValid()) {
658 SkTDArray<char> inData;
659 inData.resize((int) inFile.getLength());
660 size_t inLen = inData.size();
661 inFile.read(inData.begin(), inLen);
662 inFile.close();
663 char* insert = strstr(inData.begin(), marker);
664 if (insert) {
665 insert += sizeof(marker) - 1;
666 const char* numLoc = insert + 4 /* indent spaces */ + testNameSize - 1;
667 sTestNumber = atoi(numLoc) + 1;
668 }
669 }
670 }
671}
#define test(name)
int size() const
Definition: SkTDArray.h:138
T * begin()
Definition: SkTDArray.h:150
void resize(int count)
Definition: SkTDArray.h:183

◆ inner_simplify()

static bool inner_simplify ( skiatest::Reporter reporter,
const SkPath path,
const char *  filename,
ExpectSuccess  expectSuccess,
SkipAssert  skipAssert,
ExpectMatch  expectMatch 
)
static

Definition at line 476 of file PathOpsExtendedTest.cpp.

477 {
479 if (check_for_duplicate_names(filename)) {
480 return true;
481 }
483 fprintf(PathOpsDebug::gOut, ",\n");
484 }
486 fprintf(PathOpsDebug::gOut, "\"%s\": {\n", filename);
487 json_path_out(path, "path", "", false);
488 }
489 SkPath out;
492 if (ExpectSuccess::kYes == expectSuccess) {
493 SkDebugf("%s did not expect %s failure\n", __FUNCTION__, filename);
495 }
497 json_status(expectSuccess, expectMatch, false);
498 fprintf(PathOpsDebug::gOut, " \"out\": \"\"\n}");
499 }
500 return false;
501 } else {
502 if (ExpectSuccess::kNo == expectSuccess) {
503 SkDebugf("%s %s unexpected success\n", __FUNCTION__, filename);
505 }
507 json_status(expectSuccess, expectMatch, true);
508 json_path_out(out, "out", "Out", true);
509 }
510 }
512 int errors = comparePaths(reporter, filename, path, out, bitmap);
513 if (ExpectMatch::kNo == expectMatch) {
514 if (!errors) {
515 SkDebugf("%s failing test %s now succeeds\n", __FUNCTION__, filename);
517 return false;
518 }
519 } else if (ExpectMatch::kYes == expectMatch && errors) {
521 }
522 reporter->bumpTestCount();
523 return errors == 0;
524}
bool SimplifyDebug(const SkPath &one, SkPath *result SkDEBUGPARAMS(bool skipAssert) SkDEBUGPARAMS(const char *testName))
static void json_path_out(const SkPath &path, const char *pathName, const char *fillTypeName, bool lastField)
int comparePaths(skiatest::Reporter *reporter, const char *filename, const SkPath &one, const SkPath &two, SkBitmap &bitmap)
static bool check_for_duplicate_names(const char *testName)
static void json_status(ExpectSuccess expectSuccess, ExpectMatch expectMatch, bool opSucceeded)
#define SkDEBUGPARAMS(...)
static FILE * gOut
Definition: PathOpsDebug.h:20
static bool gJson
Definition: PathOpsDebug.h:15
static bool gOutFirst
Definition: PathOpsDebug.h:17
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57

◆ innerPathOp()

static bool innerPathOp ( skiatest::Reporter reporter,
const SkPath a,
const SkPath b,
const SkPathOp  shapeOp,
const char *  testName,
ExpectSuccess  expectSuccess,
SkipAssert  skipAssert,
ExpectMatch  expectMatch 
)
static

Definition at line 547 of file PathOpsExtendedTest.cpp.

549 {
552 return true;
553 }
555 fprintf(PathOpsDebug::gOut, ",\n");
556 }
558 fprintf(PathOpsDebug::gOut, "\"%s\": {\n", testName);
559 json_path_out(a, "p1", "1", false);
560 json_path_out(b, "p2", "2", false);
561 fprintf(PathOpsDebug::gOut, " \"op\": \"%s\",\n", opStrs[shapeOp]);
562 }
563 SkPath out;
564 if (!OpDebug(a, b, shapeOp, &out SkDEBUGPARAMS(SkipAssert::kYes == skipAssert)
566 if (ExpectSuccess::kYes == expectSuccess) {
567 SkDebugf("%s %s did not expect failure\n", __FUNCTION__, testName);
569 }
571 json_status(expectSuccess, expectMatch, false);
572 fprintf(PathOpsDebug::gOut, " \"out\": \"\"\n}");
573 }
574 return false;
575 } else {
576 if (ExpectSuccess::kNo == expectSuccess) {
577 SkDebugf("%s %s unexpected success\n", __FUNCTION__, testName);
579 }
581 json_status(expectSuccess, expectMatch, true);
582 json_path_out(out, "out", "Out", true);
583 }
584 }
585 if (!reporter->verbose()) {
586 return true;
587 }
588 SkPath pathOut, scaledPathOut;
589 SkRegion rgnA, rgnB, openClip, rgnOut;
590 openClip.setRect({-16000, -16000, 16000, 16000});
591 rgnA.setPath(a, openClip);
592 rgnB.setPath(b, openClip);
593 rgnOut.op(rgnA, rgnB, (SkRegion::Op) shapeOp);
594 rgnOut.getBoundaryPath(&pathOut);
595
597 scaleMatrix(a, b, scale);
598 SkRegion scaledRgnA, scaledRgnB, scaledRgnOut;
599 SkPath scaledA, scaledB;
600 scaledA.addPath(a, scale);
601 scaledA.setFillType(a.getFillType());
602 scaledB.addPath(b, scale);
603 scaledB.setFillType(b.getFillType());
604 scaledRgnA.setPath(scaledA, openClip);
605 scaledRgnB.setPath(scaledB, openClip);
606 scaledRgnOut.op(scaledRgnA, scaledRgnB, (SkRegion::Op) shapeOp);
607 scaledRgnOut.getBoundaryPath(&scaledPathOut);
609 SkPath scaledOut;
610 scaledOut.addPath(out, scale);
611 scaledOut.setFillType(out.getFillType());
612 int result = comparePaths(reporter, testName, pathOut, scaledPathOut, out, scaledOut, bitmap,
613 a, b, shapeOp, scale, expectMatch);
614 reporter->bumpTestCount();
615 return result == 0;
616}
bool OpDebug(const SkPath &one, const SkPath &two, SkPathOp op, SkPath *result SkDEBUGPARAMS(bool skipAssert) SkDEBUGPARAMS(const char *testName))
static const char * opStrs[]
static void scaleMatrix(const SkPath &one, const SkPath &two, SkMatrix &scale)
void setFillType(SkPathFillType ft)
Definition: SkPath.h:235
SkPath & addPath(const SkPath &src, SkScalar dx, SkScalar dy, AddPathMode mode=kAppend_AddPathMode)
Definition: SkPath.cpp:1506
bool getBoundaryPath(SkPath *path) const
bool op(const SkIRect &rect, Op op)
Definition: SkRegion.h:384
bool setRect(const SkIRect &rect)
Definition: SkRegion.cpp:192
bool setPath(const SkPath &path, const SkRegion &clip)
GAsyncResult * result

◆ json_path_out()

static void json_path_out ( const SkPath path,
const char *  pathName,
const char *  fillTypeName,
bool  lastField 
)
static

Definition at line 423 of file PathOpsExtendedTest.cpp.

424 {
425 char const * const gFillTypeStrs[] = {
426 "Winding",
427 "EvenOdd",
428 "InverseWinding",
429 "InverseEvenOdd",
430 };
433 fprintf(PathOpsDebug::gOut, " \"%s\": \"%s\",\n", pathName, svg.c_str());
434 } else {
435 // MOVE, LINE, QUAD, CONIC, CUBIC, CLOSE
436 const int verbConst[] = { 0, 1, 2, 3, 4, 5 };
437 const int pointIndex[] = { 0, 1, 1, 1, 1, 0 };
438 const int pointCount[] = { 1, 2, 3, 3, 4, 0 };
439 fprintf(PathOpsDebug::gOut, " \"%s\": [", pathName);
440 bool first = true;
441 for (auto [verb, points, w] : SkPathPriv::Iterate(path)) {
442 if (first) {
443 first = false;
444 } else {
445 fprintf(PathOpsDebug::gOut, ",\n ");
446 }
447 int verbIndex = (int) verb;
448 fprintf(PathOpsDebug::gOut, "[%d", verbConst[verbIndex]);
449 for (int i = pointIndex[verbIndex]; i < pointCount[verbIndex]; ++i) {
450 fprintf(PathOpsDebug::gOut, ", \"0x%08x\", \"0x%08x\"",
452 }
453 if (SkPathVerb::kConic == verb) {
454 fprintf(PathOpsDebug::gOut, ", \"0x%08x\"", SkFloat2Bits(*w));
455 }
456 fprintf(PathOpsDebug::gOut, "]");
457 }
458 fprintf(PathOpsDebug::gOut, "],\n");
459 }
460 fprintf(PathOpsDebug::gOut, " \"fillType%s\": \"k%s_FillType\"%s", fillTypeName,
461 gFillTypeStrs[(int) path.getFillType()], lastField ? "\n}" : ",\n");
462}
static const int points[]
static uint32_t SkFloat2Bits(float value)
Definition: SkFloatBits.h:41
@ kConic
SkPath::RawIter returns 3 points + 1 weight.
static bool gOutputSVG
Definition: PathOpsDebug.h:19
static SkString ToSVGString(const SkPath &, PathEncoding=PathEncoding::Absolute)
SkScalar w
const char * svg

◆ json_status()

static void json_status ( ExpectSuccess  expectSuccess,
ExpectMatch  expectMatch,
bool  opSucceeded 
)
static

Definition at line 409 of file PathOpsExtendedTest.cpp.

409 {
410 fprintf(PathOpsDebug::gOut, " \"expectSuccess\": \"%s\",\n",
411 ExpectSuccess::kNo == expectSuccess ? "no" :
412 ExpectSuccess::kYes == expectSuccess ? "yes" : "flaky");
414 expectMatch = ExpectMatch::kFlaky;
416 }
417 fprintf(PathOpsDebug::gOut, " \"expectMatch\": \"%s\",\n",
418 ExpectMatch::kNo == expectMatch ? "no" :
419 ExpectMatch::kYes == expectMatch ? "yes" : "flaky");
420 fprintf(PathOpsDebug::gOut, " \"succeeded\": %s,\n", opSucceeded ? "true" : "false");
421}
static bool gMarkJsonFlaky
Definition: PathOpsDebug.h:16

◆ markTestFlakyForPathKit()

void markTestFlakyForPathKit ( )

Definition at line 369 of file PathOpsExtendedTest.cpp.

369 {
373 }
374}
#define SkASSERT(cond)
Definition: SkAssert.h:116

◆ OpDebug()

bool OpDebug ( const SkPath one,
const SkPath two,
SkPathOp  op,
SkPath *result   SkDEBUGPARAMSbool skipAssert) SkDEBUGPARAMS(const char *testName 
)

Definition at line 252 of file SkPathOpsOp.cpp.

253 {
254#if DEBUG_DUMP_VERIFY
255#ifndef SK_DEBUG
256 const char* testName = "release";
257#endif
258 if (SkPathOpsDebug::gDumpOp) {
259 DumpOp(one, two, op, testName);
260 }
261#endif
262 op = gOpInverse[op][one.isInverseFillType()][two.isInverseFillType()];
263 bool inverseFill = gOutInverse[op][one.isInverseFillType()][two.isInverseFillType()];
264 SkPathFillType fillType = inverseFill ? SkPathFillType::kInverseEvenOdd :
266 SkRect rect1, rect2;
267 if (kIntersect_SkPathOp == op && one.isRect(&rect1) && two.isRect(&rect2)) {
268 result->reset();
269 result->setFillType(fillType);
270 if (rect1.intersect(rect2)) {
271 result->addRect(rect1);
272 }
273 return true;
274 }
275 if (one.isEmpty() || two.isEmpty()) {
276 SkPath work;
277 switch (op) {
279 break;
280 case kUnion_SkPathOp:
281 case kXOR_SkPathOp:
282 work = one.isEmpty() ? two : one;
283 break;
285 if (!one.isEmpty()) {
286 work = one;
287 }
288 break;
290 if (!two.isEmpty()) {
291 work = two;
292 }
293 break;
294 default:
295 SkASSERT(0); // unhandled case
296 }
297 if (inverseFill != work.isInverseFillType()) {
299 }
300 return Simplify(work, result);
301 }
302 SkSTArenaAlloc<4096> allocator; // FIXME: add a constant expression here, tune
304 SkOpContourHead* contourList = static_cast<SkOpContourHead*>(&contour);
305 SkOpGlobalState globalState(contourList, &allocator
307 SkOpCoincidence coincidence(&globalState);
308 const SkPath* minuend = &one;
309 const SkPath* subtrahend = &two;
310 if (op == kReverseDifference_SkPathOp) {
311 using std::swap;
312 swap(minuend, subtrahend);
314 }
315#if DEBUG_SORT
316 SkPathOpsDebug::gSortCount = SkPathOpsDebug::gSortCountDefault;
317#endif
318 // turn path into list of segments
319 SkOpEdgeBuilder builder(*minuend, contourList, &globalState);
320 if (builder.unparseable()) {
321 return false;
322 }
323 const int xorMask = builder.xorMask();
324 builder.addOperand(*subtrahend);
325 if (!builder.finish()) {
326 return false;
327 }
328#if DEBUG_DUMP_SEGMENTS
329 contourList->dumpSegments("seg", op);
330#endif
331
332 const int xorOpMask = builder.xorMask();
333 if (!SortContourList(&contourList, xorMask == kEvenOdd_PathOpsMask,
334 xorOpMask == kEvenOdd_PathOpsMask)) {
335 result->reset();
336 result->setFillType(fillType);
337 return true;
338 }
339 // find all intersections between segments
340 SkOpContour* current = contourList;
341 do {
342 SkOpContour* next = current;
343 while (AddIntersectTs(current, next, &coincidence)
344 && (next = next->next()))
345 ;
346 } while ((current = current->next()));
347#if DEBUG_VALIDATE
348 globalState.setPhase(SkOpPhase::kWalking);
349#endif
350 bool success = HandleCoincidence(contourList, &coincidence);
351#if DEBUG_COIN
352 globalState.debugAddToGlobalCoinDicts();
353#endif
354 if (!success) {
355 return false;
356 }
357#if DEBUG_ALIGNMENT
358 contourList->dumpSegments("aligned");
359#endif
360 // construct closed contours
361 SkPath original = *result;
362 result->reset();
363 result->setFillType(fillType);
364 SkPathWriter wrapper(*result);
365 if (!bridgeOp(contourList, op, xorMask, xorOpMask, &wrapper)) {
366 *result = original;
367 return false;
368 }
369 wrapper.assemble(); // if some edges could not be resolved, assemble remaining
370#if DEBUG_T_SECT_LOOP_COUNT
371 static SkMutex& debugWorstLoop = *(new SkMutex);
372 {
373 SkAutoMutexExclusive autoM(debugWorstLoop);
374 if (!gVerboseFinalize) {
375 gVerboseFinalize = &ReportPathOpsDebugging;
376 }
377 debugWorstState.debugDoYourWorst(&globalState);
378 }
379#endif
380 return true;
381}
static float next(float f)
bool AddIntersectTs(SkOpContour *test, SkOpContour *next, SkOpCoincidence *coincidence)
bool SortContourList(SkOpContourHead **contourList, bool evenOdd, bool oppEvenOdd)
bool HandleCoincidence(SkOpContourHead *contourList, SkOpCoincidence *coincidence)
static const bool gOutInverse[kReverseDifference_SkPathOp+1][2][2]
static bool bridgeOp(SkOpContourHead *contourList, const SkPathOp op, const int xorMask, const int xorOpMask, SkPathWriter *writer)
static const SkPathOp gOpInverse[kReverseDifference_SkPathOp+1][2][2]
@ kEvenOdd_PathOpsMask
@ kReverseDifference_SkPathOp
subtract the first path from the op path
Definition: SkPathOps.h:27
@ kDifference_SkPathOp
subtract the op path from the first path
Definition: SkPathOps.h:23
@ kIntersect_SkPathOp
intersect the two paths
Definition: SkPathOps.h:24
@ kUnion_SkPathOp
union (inclusive-or) the two paths
Definition: SkPathOps.h:25
@ kXOR_SkPathOp
exclusive-or the two paths
Definition: SkPathOps.h:26
bool SK_API Simplify(const SkPath &path, SkPath *result)
SkPathFillType
Definition: SkPathTypes.h:11
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition: SkRefCnt.h:341
void dumpSegments(const char *prefix="seg", SkPathOp op=(SkPathOp) -1) const
SkOpContour * next()
Definition: SkOpContour.h:266
bool isEmpty() const
Definition: SkPath.cpp:416
bool isInverseFillType() const
Definition: SkPath.h:244
void toggleInverseFillType()
Definition: SkPath.h:249
bool isRect(SkRect *rect, bool *isClosed=nullptr, SkPathDirection *direction=nullptr) const
Definition: SkPath.cpp:516
bool intersect(const SkRect &r)
Definition: SkRect.cpp:114

◆ pathsDrawTheSame() [1/2]

static int pathsDrawTheSame ( const SkPath one,
const SkPath two,
SkBitmap bits,
SkPath scaledOne,
SkPath scaledTwo,
int error2x2 
)
static

Definition at line 196 of file PathOpsExtendedTest.cpp.

197 {
199 scaleMatrix(one, two, scale);
200 one.transform(scale, &scaledOne);
201 two.transform(scale, &scaledTwo);
202 return pathsDrawTheSame(bits, scaledOne, scaledTwo, error2x2);
203}
void transform(const SkMatrix &matrix, SkPath *dst, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
Definition: SkPath.cpp:1711

◆ pathsDrawTheSame() [2/2]

static int pathsDrawTheSame ( SkBitmap bits,
const SkPath scaledOne,
const SkPath scaledTwo,
int error2x2 
)
static

Definition at line 158 of file PathOpsExtendedTest.cpp.

159 {
160 if (bits.width() == 0) {
161 bits.allocN32Pixels(kBitWidth * 2, kBitHeight);
162 }
163 SkCanvas canvas(bits);
164 canvas.drawColor(SK_ColorWHITE);
166 canvas.save();
167 const SkRect& bounds1 = scaledOne.getBounds();
168 canvas.translate(-bounds1.fLeft + 1, -bounds1.fTop + 1);
169 canvas.drawPath(scaledOne, paint);
170 canvas.restore();
171 canvas.save();
172 canvas.translate(-bounds1.fLeft + 1 + kBitWidth, -bounds1.fTop + 1);
173 canvas.drawPath(scaledTwo, paint);
174 canvas.restore();
175 int errors2 = 0;
176 int errors = 0;
177 for (int y = 0; y < kBitHeight - 1; ++y) {
178 uint32_t* addr1 = bits.getAddr32(0, y);
179 uint32_t* addr2 = bits.getAddr32(0, y + 1);
180 uint32_t* addr3 = bits.getAddr32(kBitWidth, y);
181 uint32_t* addr4 = bits.getAddr32(kBitWidth, y + 1);
182 for (int x = 0; x < kBitWidth - 1; ++x) {
183 // count 2x2 blocks
184 bool err = addr1[x] != addr3[x];
185 if (err) {
186 errors2 += addr1[x + 1] != addr3[x + 1]
187 && addr2[x] != addr4[x] && addr2[x + 1] != addr4[x + 1];
188 errors++;
189 }
190 }
191 }
192 error2x2 = errors2;
193 return errors;
194}
const int kBitHeight
const int kBitWidth

◆ RunTestSet()

void RunTestSet ( skiatest::Reporter reporter,
TestDesc  tests[],
size_t  count,
void(*)(skiatest::Reporter *, const char *filename)  firstTest,
void(*)(skiatest::Reporter *, const char *filename)  skipTest,
void(*)(skiatest::Reporter *, const char *filename)  stopTest,
bool  reverse 
)

Definition at line 691 of file PathOpsExtendedTest.cpp.

694 {
695 size_t index;
696 if (firstTest) {
697 index = count - 1;
698 while (index > 0 && tests[index].fun != firstTest) {
699 --index;
700 }
701 (*tests[index].fun)(reporter, tests[index].str);
702 if (tests[index].fun == stopTest) {
703 return;
704 }
705 }
706 index = reverse ? count - 1 : 0;
707 size_t last = reverse ? 0 : count - 1;
708 bool foundSkip = !skipTest;
709 do {
710 if (tests[index].fun == skipTest) {
711 foundSkip = true;
712 }
713 if (foundSkip && tests[index].fun != firstTest) {
714 (*tests[index].fun)(reporter, tests[index].str);
715 }
716 if (tests[index].fun == stopTest || index == last) {
717 break;
718 }
719 index += reverse ? -1 : 1;
720 } while (true);
721}
static BlurTest tests[]
Definition: BlurTest.cpp:84
int count
Definition: FontMgrTest.cpp:50
static void(* stopTest)(skiatest::Reporter *, const char *filename)
static void(* firstTest)(skiatest::Reporter *, const char *filename)

◆ scaleMatrix()

static void scaleMatrix ( const SkPath one,
const SkPath two,
SkMatrix scale 
)
static

Definition at line 132 of file PathOpsExtendedTest.cpp.

132 {
133 SkRect larger = one.getBounds();
134 larger.join(two.getBounds());
135 SkScalar largerWidth = larger.width();
136 if (largerWidth < 4) {
137 largerWidth = 4;
138 }
139 SkScalar largerHeight = larger.height();
140 if (largerHeight < 4) {
141 largerHeight = 4;
142 }
143 SkScalar hScale = (kBitWidth - 2) / largerWidth;
144 SkScalar vScale = (kBitHeight - 2) / largerHeight;
145 scale.reset();
146 scale.preScale(hScale, vScale);
147 larger.fLeft *= hScale;
148 larger.fRight *= hScale;
149 larger.fTop *= vScale;
150 larger.fBottom *= vScale;
151 SkScalar dx = -16000 > larger.fLeft ? -16000 - larger.fLeft
152 : 16000 < larger.fRight ? 16000 - larger.fRight : 0;
153 SkScalar dy = -16000 > larger.fTop ? -16000 - larger.fTop
154 : 16000 < larger.fBottom ? 16000 - larger.fBottom : 0;
155 scale.postTranslate(dx, dy);
156}
float SkScalar
Definition: extension.cpp:12
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
Definition: SkRecords.h:208
SkScalar fBottom
larger y-axis bounds
Definition: extension.cpp:17
SkScalar fRight
larger x-axis bounds
Definition: extension.cpp:16

◆ showOp()

void showOp ( const SkPathOp  op)

Definition at line 107 of file PathOpsExtendedTest.cpp.

107 {
108 switch (op) {
110 SkDebugf("op difference\n");
111 break;
113 SkDebugf("op intersect\n");
114 break;
115 case kUnion_SkPathOp:
116 SkDebugf("op union\n");
117 break;
118 case kXOR_SkPathOp:
119 SkDebugf("op xor\n");
120 break;
122 SkDebugf("op reverse difference\n");
123 break;
124 default:
125 SkASSERT(0);
126 }
127}

◆ showPathOpPath()

static void showPathOpPath ( const char *  testName,
const SkPath one,
const SkPath two,
const SkPath a,
const SkPath b,
const SkPath scaledOne,
const SkPath scaledTwo,
const SkPathOp  shapeOp,
const SkMatrix scale 
)
static

Definition at line 266 of file PathOpsExtendedTest.cpp.

268 {
269 SkASSERT((unsigned) shapeOp < std::size(opStrs));
270 if (!testName) {
271 testName = "xOp";
272 }
273 SkDebugf("static void %s_%s(skiatest::Reporter* reporter, const char* filename) {\n",
274 testName, opSuffixes[shapeOp]);
275 *gTestOp.append() = shapeOp;
276 SkDebugf(" SkPath path, pathB;\n");
277 SkPathOpsDebug::ShowOnePath(a, "path", false);
278 SkPathOpsDebug::ShowOnePath(b, "pathB", false);
279 SkDebugf(" testPathOp(reporter, path, pathB, %s, filename);\n", opStrs[shapeOp]);
280 SkDebugf("}\n");
281 drawAsciiPaths(scaledOne, scaledTwo, true);
282}
static SkTDArray< SkPathOp > gTestOp
static const char * opSuffixes[]
bool drawAsciiPaths(const SkPath &one, const SkPath &two, bool drawPaths)
static void ShowOnePath(const SkPath &path, const char *name, bool includeDeclaration)
T * append()
Definition: SkTDArray.h:191
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259

◆ SimplifyDebug()

bool SimplifyDebug ( const SkPath one,
SkPath *result   SkDEBUGPARAMSbool skipAssert) SkDEBUGPARAMS(const char *testName 
)

Definition at line 205 of file SkPathOpsSimplify.cpp.

206 {
207 // returns 1 for evenodd, -1 for winding, regardless of inverse-ness
208 SkPathFillType fillType = path.isInverseFillType() ? SkPathFillType::kInverseEvenOdd
210
211 if (path.isConvex()) {
212 // If the path is trivially convex, simplify to empty.
213 if (path_is_trivial(path)) {
214 result->reset();
215 } else if (result != &path) {
216 *result = path;
217 }
218 result->setFillType(fillType);
219 return true;
220 }
221 // turn path into list of segments
222 SkSTArenaAlloc<4096> allocator; // FIXME: constant-ize, tune
224 SkOpContourHead* contourList = static_cast<SkOpContourHead*>(&contour);
225 SkOpGlobalState globalState(contourList, &allocator
227 SkOpCoincidence coincidence(&globalState);
228#if DEBUG_DUMP_VERIFY
229#ifndef SK_DEBUG
230 const char* testName = "release";
231#endif
232 if (SkPathOpsDebug::gDumpOp) {
233 DumpSimplify(path, testName);
234 }
235#endif
236#if DEBUG_SORT
237 SkPathOpsDebug::gSortCount = SkPathOpsDebug::gSortCountDefault;
238#endif
239 SkOpEdgeBuilder builder(path, contourList, &globalState);
240 if (!builder.finish()) {
241 return false;
242 }
243#if DEBUG_DUMP_SEGMENTS
244 contour.dumpSegments();
245#endif
246 if (!SortContourList(&contourList, false, false)) {
247 result->reset();
248 result->setFillType(fillType);
249 return true;
250 }
251 // find all intersections between segments
252 SkOpContour* current = contourList;
253 do {
254 SkOpContour* next = current;
255 while (AddIntersectTs(current, next, &coincidence)
256 && (next = next->next()));
257 } while ((current = current->next()));
258#if DEBUG_VALIDATE
259 globalState.setPhase(SkOpPhase::kWalking);
260#endif
261 bool success = HandleCoincidence(contourList, &coincidence);
262#if DEBUG_COIN
263 globalState.debugAddToGlobalCoinDicts();
264#endif
265 if (!success) {
266 return false;
267 }
268#if DEBUG_DUMP_ALIGNMENT
269 contour.dumpSegments("aligned");
270#endif
271 // construct closed contours
272 result->reset();
273 result->setFillType(fillType);
274 SkPathWriter wrapper(*result);
275 if (builder.xorMask() == kWinding_PathOpsMask ? !bridgeWinding(contourList, &wrapper)
276 : !bridgeXor(contourList, &wrapper)) {
277 return false;
278 }
279 wrapper.assemble(); // if some edges could not be resolved, assemble remaining
280 return true;
281}
static bool bridgeWinding(SkOpContourHead *contourList, SkPathWriter *writer)
static bool bridgeXor(SkOpContourHead *contourList, SkPathWriter *writer)
static bool path_is_trivial(const SkPath &path)
@ kWinding_PathOpsMask

◆ std_to_string()

template<typename T >
std::string std_to_string ( T  value)

Definition at line 52 of file PathOpsExtendedTest.cpp.

53{
54 std::ostringstream os ;
55 os << value ;
56 return os.str() ;
57}
uint8_t value

◆ testPathOp()

bool testPathOp ( skiatest::Reporter reporter,
const SkPath a,
const SkPath b,
const SkPathOp  shapeOp,
const char *  testName 
)

Definition at line 618 of file PathOpsExtendedTest.cpp.

619 {
622}
static bool innerPathOp(skiatest::Reporter *reporter, const SkPath &a, const SkPath &b, const SkPathOp shapeOp, const char *testName, ExpectSuccess expectSuccess, SkipAssert skipAssert, ExpectMatch expectMatch)

◆ testPathOpCheck()

bool testPathOpCheck ( skiatest::Reporter reporter,
const SkPath a,
const SkPath b,
const SkPathOp  shapeOp,
const char *  testName,
bool  checkFail 
)

Definition at line 624 of file PathOpsExtendedTest.cpp.

625 {
626 return innerPathOp(reporter, a, b, shapeOp, testName, checkFail ?
628}

◆ testPathOpFail()

bool testPathOpFail ( skiatest::Reporter reporter,
const SkPath a,
const SkPath b,
const SkPathOp  shapeOp,
const char *  testName 
)

Definition at line 636 of file PathOpsExtendedTest.cpp.

637 {
638 SkPath orig;
639 orig.lineTo(54, 43);
640 SkPath out = orig;
641 if (Op(a, b, shapeOp, &out) ) {
642 SkDebugf("%s test is expected to fail\n", __FUNCTION__);
644 return false;
645 }
646 SkASSERT(out == orig);
647 return true;
648}
SkPath & lineTo(SkScalar x, SkScalar y)
Definition: SkPath.cpp:728

◆ testPathOpFuzz()

bool testPathOpFuzz ( skiatest::Reporter reporter,
const SkPath a,
const SkPath b,
const SkPathOp  shapeOp,
const char *  testName 
)

Definition at line 630 of file PathOpsExtendedTest.cpp.

◆ testSimplify() [1/2]

bool testSimplify ( skiatest::Reporter reporter,
const SkPath path,
const char *  filename 
)

Definition at line 526 of file PathOpsExtendedTest.cpp.

526 {
529}
static bool inner_simplify(skiatest::Reporter *reporter, const SkPath &path, const char *filename, ExpectSuccess expectSuccess, SkipAssert skipAssert, ExpectMatch expectMatch)

◆ testSimplify() [2/2]

bool testSimplify ( SkPath path,
bool  useXor,
SkPath out,
PathOpsThreadState state,
const char *  pathStr 
)

Definition at line 376 of file PathOpsExtendedTest.cpp.

377 {
378 static SkMutex& simplifyDebugOut = *(new SkMutex);
380 path.setFillType(fillType);
381 state.fReporter->bumpTestCount();
382 if (!Simplify(path, &out)) {
383 SkDebugf("%s did not expect failure\n", __FUNCTION__);
384 REPORTER_ASSERT(state.fReporter, 0);
385 return false;
386 }
387 if (!state.fReporter->verbose()) {
388 return true;
389 }
390 int result = comparePaths(state.fReporter, nullptr, path, out, *state.fBitmap);
391 if (result) {
392 SkAutoMutexExclusive autoM(simplifyDebugOut);
393 std::string str;
394 const char* pathPrefix = nullptr;
395 const char* nameSuffix = nullptr;
396 if (fillType == SkPathFillType::kEvenOdd) {
397 pathPrefix = " path.setFillType(SkPathFillType::kEvenOdd);\n";
398 nameSuffix = "x";
399 }
400 const char testFunction[] = "testSimplify(reporter, path);";
401 appendTest(pathStr, pathPrefix, nameSuffix, testFunction, false, str);
402 SkDebugf("%s", str.c_str());
403 REPORTER_ASSERT(state.fReporter, 0);
404 }
405 state.fReporter->bumpTestCount();
406 return result == 0;
407}
static void appendTest(const char *pathStr, const char *pathPrefix, const char *nameSuffix, const char *testFunction, bool twoPaths, std::string &out)
AtkStateType state

◆ testSimplifyCheck()

bool testSimplifyCheck ( skiatest::Reporter reporter,
const SkPath path,
const char *  filename,
bool  checkFail 
)

Definition at line 536 of file PathOpsExtendedTest.cpp.

537 {
538 return inner_simplify(reporter, path, filename, checkFail ?
540}

◆ testSimplifyFail()

bool testSimplifyFail ( skiatest::Reporter reporter,
const SkPath path,
const char *  filename 
)

Definition at line 542 of file PathOpsExtendedTest.cpp.

◆ testSimplifyFuzz()

bool testSimplifyFuzz ( skiatest::Reporter reporter,
const SkPath path,
const char *  filename 
)

Definition at line 531 of file PathOpsExtendedTest.cpp.

Variable Documentation

◆ gTestOp

SkTDArray<SkPathOp> gTestOp
static

Definition at line 264 of file PathOpsExtendedTest.cpp.

◆ gUniqueNames

std::vector<std::string> gUniqueNames

Definition at line 42 of file PathOpsExtendedTest.cpp.

◆ kBitHeight

const int kBitHeight = 64

Definition at line 130 of file PathOpsExtendedTest.cpp.

◆ kBitWidth

const int kBitWidth = 64

Definition at line 129 of file PathOpsExtendedTest.cpp.

◆ marker

const char marker[]
static
Initial value:
=
"</div>\n"
"\n"
"<script type=\"text/javascript\">\n"
"\n"
"var testDivs = [\n"

Definition at line 67 of file PathOpsExtendedTest.cpp.

◆ opStrs

const char* opStrs[]
static
Initial value:
= {
"kDifference_SkPathOp",
"kIntersect_SkPathOp",
"kUnion_SkPathOp",
"kXOR_PathOp",
"kReverseDifference_SkPathOp",
}

Definition at line 74 of file PathOpsExtendedTest.cpp.

◆ opSuffixes

const char* opSuffixes[]
static
Initial value:
= {
"d",
"i",
"u",
"o",
"r",
}

Definition at line 82 of file PathOpsExtendedTest.cpp.

◆ sTestName

const char* sTestName = "pathOpTest"
static

Definition at line 313 of file PathOpsExtendedTest.cpp.

◆ sTestNumber

int sTestNumber = 55
static

Definition at line 312 of file PathOpsExtendedTest.cpp.