diff options
author | 2014-05-19 13:53:10 +0000 | |
---|---|---|
committer | 2014-05-19 13:53:10 +0000 | |
commit | 2a67e123a3e559774a16a58cbe5106bc0fb86740 (patch) | |
tree | b55bd6606e329ded2b58310f925a78e615bbe1d1 /src/utils/debugger | |
parent | 2ee3c2ce6499cb7ce15b59420dd4514ad01d0318 (diff) |
This adds a checkbox to the debugger to allow seeing the effect pathops has on the clip. A new tab shows the C code that the pathops generate.
Once in place, this CL found a bug in the pathops code where it was not handling empty clip stack elements correctly. The Cl also has the change to SkCanvas to fix this bug.
R=robertphillips@google.com, reed@google.com
Author: caryclark@google.com
Review URL: https://codereview.chromium.org/282283002
git-svn-id: http://skia.googlecode.com/svn/trunk@14774 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/utils/debugger')
-rw-r--r-- | src/utils/debugger/SkDebugCanvas.cpp | 151 | ||||
-rw-r--r-- | src/utils/debugger/SkDebugCanvas.h | 19 |
2 files changed, 169 insertions, 1 deletions
diff --git a/src/utils/debugger/SkDebugCanvas.cpp b/src/utils/debugger/SkDebugCanvas.cpp index 14fbf8888a..89a388e110 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; +} diff --git a/src/utils/debugger/SkDebugCanvas.h b/src/utils/debugger/SkDebugCanvas.h index d4fded7c1a..be1b8608be 100644 --- a/src/utils/debugger/SkDebugCanvas.h +++ b/src/utils/debugger/SkDebugCanvas.h @@ -12,6 +12,7 @@ #include "SkCanvas.h" #include "SkDrawCommand.h" +#include "SkPathOps.h" #include "SkPicture.h" #include "SkTArray.h" #include "SkString.h" @@ -37,6 +38,8 @@ public: void setOutstandingSaveCount(int saveCount) { fOutstandingSaveCount = saveCount; } int getOutstandingSaveCount() const { return fOutstandingSaveCount; } + bool getAllowSimplifyClip() const { return fAllowSimplifyClip; } + void setPicture(SkPicture* picture) { fPicture = picture; } /** @@ -151,6 +154,8 @@ public: fUserMatrix = matrix; } + SkString clipStackData() const { return fClipStackData; } + //////////////////////////////////////////////////////////////////////////////// // Inherited from SkCanvas //////////////////////////////////////////////////////////////////////////////// @@ -266,6 +271,10 @@ private: SkMatrix fMatrix; SkIRect fClip; + SkString fClipStackData; + bool fCalledAddStackData; + SkPath fSaveDevPath; + bool fOverdrawViz; SkDrawFilter* fOverdrawFilter; @@ -311,6 +320,16 @@ private: return 0; } + void resetClipStackData() { fClipStackData.reset(); fCalledAddStackData = false; } + + void addClipStackData(const SkPath& devPath, const SkPath& operand, SkRegion::Op elementOp); + void addPathData(const SkPath& path, const char* pathName); + bool lastClipStackData(const SkPath& devPath); + void outputConicPoints(const SkPoint* pts, SkScalar weight); + void outputPoints(const SkPoint* pts, int count); + void outputPointsCommon(const SkPoint* pts, int count); + void outputScalar(SkScalar num); + typedef SkCanvas INHERITED; }; |