| Index: src/utils/debugger/SkDebugCanvas.cpp
|
| diff --git a/src/utils/debugger/SkDebugCanvas.cpp b/src/utils/debugger/SkDebugCanvas.cpp
|
| index 14fbf8888a6d149f7d6e9b304ad403daefbbe708..89a388e11003d0958131367356d91444a3f9a506 100644
|
| --- a/src/utils/debugger/SkDebugCanvas.cpp
|
| +++ b/src/utils/debugger/SkDebugCanvas.cpp
|
| @@ -240,12 +240,14 @@ void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) {
|
| SkASSERT(index < fCommandVector.count());
|
| int i = 0;
|
|
|
| + bool pathOpsMode = getAllowSimplifyClip();
|
| + canvas->setAllowSimplifyClip(pathOpsMode);
|
| // This only works assuming the canvas and device are the same ones that
|
| // were previously drawn into because they need to preserve all saves
|
| // and restores.
|
| // The visibility filter also requires a full re-draw - otherwise we can
|
| // end up drawing the filter repeatedly.
|
| - if (fIndex < index && !fFilter && !fMegaVizMode) {
|
| + if (fIndex < index && !fFilter && !fMegaVizMode && !pathOpsMode) {
|
| i = fIndex + 1;
|
| } else {
|
| for (int j = 0; j < fOutstandingSaveCount; j++) {
|
| @@ -335,6 +337,28 @@ void SkDebugCanvas::drawTo(SkCanvas* canvas, int index) {
|
|
|
| canvas->restore();
|
| }
|
| + if (pathOpsMode) {
|
| + this->resetClipStackData();
|
| + const SkClipStack* clipStack = canvas->getClipStack();
|
| + SkClipStack::Iter iter(*clipStack, SkClipStack::Iter::kBottom_IterStart);
|
| + const SkClipStack::Element* element;
|
| + SkPath devPath;
|
| + while ((element = iter.next())) {
|
| + SkClipStack::Element::Type type = element->getType();
|
| + SkPath operand;
|
| + if (type != SkClipStack::Element::kEmpty_Type) {
|
| + element->asPath(&operand);
|
| + }
|
| + SkRegion::Op elementOp = element->getOp();
|
| + this->addClipStackData(devPath, operand, elementOp);
|
| + if (elementOp == SkRegion::kReplace_Op) {
|
| + devPath = operand;
|
| + } else {
|
| + Op(devPath, operand, (SkPathOp) elementOp, &devPath);
|
| + }
|
| + }
|
| + this->lastClipStackData(devPath);
|
| + }
|
| fMatrix = canvas->getTotalMatrix();
|
| if (!canvas->getClipDeviceBounds(&fClip)) {
|
| fClip.setEmpty();
|
| @@ -588,3 +612,128 @@ void SkDebugCanvas::toggleCommand(int index, bool toggle) {
|
| SkASSERT(index < fCommandVector.count());
|
| fCommandVector[index]->setVisible(toggle);
|
| }
|
| +
|
| +static const char* gFillTypeStrs[] = {
|
| + "kWinding_FillType",
|
| + "kEvenOdd_FillType",
|
| + "kInverseWinding_FillType",
|
| + "kInverseEvenOdd_FillType"
|
| +};
|
| +
|
| +static const char* gOpStrs[] = {
|
| + "kDifference_PathOp",
|
| + "kIntersect_PathOp",
|
| + "kUnion_PathOp",
|
| + "kXor_PathOp",
|
| + "kReverseDifference_PathOp",
|
| +};
|
| +
|
| +static const char kHTML4SpaceIndent[] = " ";
|
| +
|
| +void SkDebugCanvas::outputScalar(SkScalar num) {
|
| + if (num == (int) num) {
|
| + fClipStackData.appendf("%d", (int) num);
|
| + } else {
|
| + SkString str;
|
| + str.printf("%1.9g", num);
|
| + int width = (int) str.size();
|
| + const char* cStr = str.c_str();
|
| + while (cStr[width - 1] == '0') {
|
| + --width;
|
| + }
|
| + str.resize(width);
|
| + fClipStackData.appendf("%sf", str.c_str());
|
| + }
|
| +}
|
| +
|
| +void SkDebugCanvas::outputPointsCommon(const SkPoint* pts, int count) {
|
| + for (int index = 0; index < count; ++index) {
|
| + this->outputScalar(pts[index].fX);
|
| + fClipStackData.appendf(", ");
|
| + this->outputScalar(pts[index].fY);
|
| + if (index + 1 < count) {
|
| + fClipStackData.appendf(", ");
|
| + }
|
| + }
|
| +}
|
| +
|
| +void SkDebugCanvas::outputPoints(const SkPoint* pts, int count) {
|
| + this->outputPointsCommon(pts, count);
|
| + fClipStackData.appendf(");<br>");
|
| +}
|
| +
|
| +void SkDebugCanvas::outputConicPoints(const SkPoint* pts, SkScalar weight) {
|
| + this->outputPointsCommon(pts, 2);
|
| + fClipStackData.appendf(", ");
|
| + this->outputScalar(weight);
|
| + fClipStackData.appendf(");<br>");
|
| +}
|
| +
|
| +void SkDebugCanvas::addPathData(const SkPath& path, const char* pathName) {
|
| + SkPath::RawIter iter(path);
|
| + SkPath::FillType fillType = path.getFillType();
|
| + fClipStackData.appendf("%sSkPath %s;<br>", kHTML4SpaceIndent, pathName);
|
| + fClipStackData.appendf("%s%s.setFillType(SkPath::%s);<br>", kHTML4SpaceIndent, pathName,
|
| + gFillTypeStrs[fillType]);
|
| + iter.setPath(path);
|
| + uint8_t verb;
|
| + SkPoint pts[4];
|
| + while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
|
| + switch (verb) {
|
| + case SkPath::kMove_Verb:
|
| + fClipStackData.appendf("%s%s.moveTo(", kHTML4SpaceIndent, pathName);
|
| + this->outputPoints(&pts[0], 1);
|
| + continue;
|
| + case SkPath::kLine_Verb:
|
| + fClipStackData.appendf("%s%s.lineTo(", kHTML4SpaceIndent, pathName);
|
| + this->outputPoints(&pts[1], 1);
|
| + break;
|
| + case SkPath::kQuad_Verb:
|
| + fClipStackData.appendf("%s%s.quadTo(", kHTML4SpaceIndent, pathName);
|
| + this->outputPoints(&pts[1], 2);
|
| + break;
|
| + case SkPath::kConic_Verb:
|
| + fClipStackData.appendf("%s%s.conicTo(", kHTML4SpaceIndent, pathName);
|
| + this->outputConicPoints(&pts[1], iter.conicWeight());
|
| + break;
|
| + case SkPath::kCubic_Verb:
|
| + fClipStackData.appendf("%s%s.cubicTo(", kHTML4SpaceIndent, pathName);
|
| + this->outputPoints(&pts[1], 3);
|
| + break;
|
| + case SkPath::kClose_Verb:
|
| + fClipStackData.appendf("%s%s.close();<br>", kHTML4SpaceIndent, pathName);
|
| + break;
|
| + default:
|
| + SkDEBUGFAIL("bad verb");
|
| + return;
|
| + }
|
| + }
|
| +}
|
| +
|
| +void SkDebugCanvas::addClipStackData(const SkPath& devPath, const SkPath& operand,
|
| + SkRegion::Op elementOp) {
|
| + if (elementOp == SkRegion::kReplace_Op) {
|
| + if (!lastClipStackData(devPath)) {
|
| + fSaveDevPath = operand;
|
| + }
|
| + fCalledAddStackData = false;
|
| + } else {
|
| + fClipStackData.appendf("<br>static void test(skiatest::Reporter* reporter,"
|
| + " const char* filename) {<br>");
|
| + addPathData(fCalledAddStackData ? devPath : fSaveDevPath, "path");
|
| + addPathData(operand, "pathB");
|
| + fClipStackData.appendf("%stestPathOp(reporter, path, pathB, %s, filename);<br>",
|
| + kHTML4SpaceIndent, gOpStrs[elementOp]);
|
| + fClipStackData.appendf("}<br>");
|
| + fCalledAddStackData = true;
|
| + }
|
| +}
|
| +
|
| +bool SkDebugCanvas::lastClipStackData(const SkPath& devPath) {
|
| + if (fCalledAddStackData) {
|
| + fClipStackData.appendf("<br>");
|
| + addPathData(devPath, "pathOut");
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
|
|