connect(fSettingsWidget.getRasterCheckBox(), SIGNAL(toggled(bool)), this, SLOT(actionRasterWidget(bool)));
connect(fSettingsWidget.getOverdrawVizCheckBox(), SIGNAL(toggled(bool)), this, SLOT(actionOverdrawVizWidget(bool)));
connect(fSettingsWidget.getMegaVizCheckBox(), SIGNAL(toggled(bool)), this, SLOT(actionMegaVizWidget(bool)));
+ connect(fSettingsWidget.getPathOpsCheckBox(), SIGNAL(toggled(bool)), this, SLOT(actionPathOpsWidget(bool)));
connect(&fActionPause, SIGNAL(toggled(bool)), this, SLOT(pauseDrawing(bool)));
connect(&fActionCreateBreakpoint, SIGNAL(activated()), this, SLOT(toggleBreakpoint()));
connect(&fActionShowDeletes, SIGNAL(triggered()), this, SLOT(showDeletes()));
}
setupOverviewText(picture->typeTimes(), picture->totTime(), kNumRepeats);
+ setupClipStackText();
}
void SkDebuggerGUI::actionCancel() {
fCanvasWidget.update();
}
+void SkDebuggerGUI::actionPathOpsWidget(bool isToggled) {
+ fDebugger.setPathOps(isToggled);
+ fCanvasWidget.update();
+}
+
void SkDebuggerGUI::actionTextureFilter() {
SkPaint::FilterLevel level;
bool enabled = fSettingsWidget.getFilterOverride(&level);
fInspectorWidget.setText(info, SkInspectorWidget::kDetail_TabType);
fInspectorWidget.setDisabled(false);
}
+ setupClipStackText();
}
}
fInspectorWidget.setText(overview.c_str(), SkInspectorWidget::kOverview_TabType);
}
+void SkDebuggerGUI::setupClipStackText() {
+ SkString clipStack;
+ fDebugger.getClipStackText(&clipStack);
+ fInspectorWidget.setText(clipStack.c_str(), SkInspectorWidget::kClipStack_TabType);
+}
+
void SkDebuggerGUI::setupComboBox(SkTArray<SkString>* command) {
fFilter.clear();
fFilter.addItem("--Filter By Available Commands--");
*/
void actionMegaVizWidget(bool isToggled);
+ /**
+ Toggles using path ops to simplify the clip stack
+ */
+ void actionPathOpsWidget(bool );
+
/**
Applies the new texture filter override
*/
*/
void setupOverviewText(const SkTDArray<double>* typeTimes, double totTime, int numRuns);
+ /**
+ Fills in the clip stack pane with text
+ */
+ void setupClipStackText();
+
/**
Render the supplied picture several times tracking the time consumed
by each command.
QString tabNames[kTotalTabCount];
tabNames[kOverview_TabType] = "Overview";
tabNames[kDetail_TabType] = "Details";
+ tabNames[kClipStack_TabType] = "Clip Stack";
for (int i = 0; i < kTotalTabCount; i++) {
fTabTexts[i].setReadOnly(true);
enum TabType {
kOverview_TabType,
kDetail_TabType,
+ kClipStack_TabType,
kTotalTabCount,
};
fRasterLabel.setMinimumWidth(178);
fRasterLabel.setMaximumWidth(178);
+ fPathOpsLabel.setText("PathOps: ");
+ fPathOpsLabel.setMinimumWidth(178);
+ fPathOpsLabel.setMaximumWidth(178);
+
fRasterCheckBox.setChecked(true);
fOverdrawVizLabel.setText(" Overdraw Viz: ");
fRasterLayout.addWidget(&fRasterLabel);
fRasterLayout.addWidget(&fRasterCheckBox);
+ fRasterLayout.addWidget(&fPathOpsLabel);
+ fRasterLayout.addWidget(&fPathOpsCheckBox);
fVizLayout.addWidget(&fOverdrawVizLabel);
fVizLayout.addWidget(&fOverdrawVizCheckBox);
return &fMegaVizCheckBox;
}
+ QCheckBox* getPathOpsCheckBox() {
+ return &fPathOpsCheckBox;
+ }
+
private slots:
void updateCommand(int newCommand);
void updateHit(int newHit);
QCheckBox fOverdrawVizCheckBox;
QLabel fMegaVizLabel;
QCheckBox fMegaVizCheckBox;
+ QLabel fPathOpsLabel;
+ QCheckBox fPathOpsCheckBox;
#if SK_SUPPORT_GPU
QHBoxLayout fGLLayout;
fDebugCanvas->setMegaVizMode(false);
bool overDraw = fDebugCanvas->getOverdrawViz();
fDebugCanvas->setOverdrawViz(false);
+ bool pathOps = fDebugCanvas->getAllowSimplifyClip();
+ fDebugCanvas->setAllowSimplifyClip(false);
int saveCount = fDebugCanvas->getOutstandingSaveCount();
fDebugCanvas->setOutstandingSaveCount(0);
fDebugCanvas->setMegaVizMode(vizMode);
fDebugCanvas->setOverdrawViz(overDraw);
fDebugCanvas->setOutstandingSaveCount(saveCount);
+ fDebugCanvas->setAllowSimplifyClip(pathOps);
return recorder.endRecording();
}
overview->appendS32(pictureHeight());
overview->append("px");
}
+
+void SkDebugger::getClipStackText(SkString* clipStack) {
+ clipStack->set(fDebugCanvas->clipStackData());
+}
+
}
}
+ void setPathOps(bool pathOps) {
+ if (NULL != fDebugCanvas) {
+ fDebugCanvas->setAllowSimplifyClip(pathOps);
+ }
+ }
+
void setMegaViz(bool megaViz) {
if (NULL != fDebugCanvas) {
fDebugCanvas->setMegaVizMode(megaViz);
void getOverviewText(const SkTDArray<double>* typeTimes, double totTime,
SkString* overview, int numRuns);
+ void getClipStackText(SkString* clipStack);
+
private:
SkDebugCanvas* fDebugCanvas;
SkPicture* fPicture;
friend class SkDrawIter; // needs setupDrawForLayerDevice()
friend class AutoDrawLooper;
friend class SkLua; // needs top layer size and offset
+ friend class SkDebugCanvas; // needs experimental fAllowSimplifyClip
friend class SkDeferredDevice; // needs getTopDevice()
SkBaseDevice* createLayerDevice(const SkImageInfo&);
const SkClipStack::Element* element;
while ((element = iter.next())) {
SkClipStack::Element::Type type = element->getType();
- if (type == SkClipStack::Element::kEmpty_Type) {
- continue;
- }
SkPath operand;
- element->asPath(&operand);
+ if (type != SkClipStack::Element::kEmpty_Type) {
+ element->asPath(&operand);
+ }
SkRegion::Op elementOp = element->getOp();
if (elementOp == SkRegion::kReplace_Op) {
devPath = operand;
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++) {
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();
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;
+}
#include "SkCanvas.h"
#include "SkDrawCommand.h"
+#include "SkPathOps.h"
#include "SkPicture.h"
#include "SkTArray.h"
#include "SkString.h"
void setOutstandingSaveCount(int saveCount) { fOutstandingSaveCount = saveCount; }
int getOutstandingSaveCount() const { return fOutstandingSaveCount; }
+ bool getAllowSimplifyClip() const { return fAllowSimplifyClip; }
+
void setPicture(SkPicture* picture) { fPicture = picture; }
/**
fUserMatrix = matrix;
}
+ SkString clipStackData() const { return fClipStackData; }
+
////////////////////////////////////////////////////////////////////////////////
// Inherited from SkCanvas
////////////////////////////////////////////////////////////////////////////////
SkMatrix fMatrix;
SkIRect fClip;
+ SkString fClipStackData;
+ bool fCalledAddStackData;
+ SkPath fSaveDevPath;
+
bool fOverdrawViz;
SkDrawFilter* fOverdrawFilter;
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;
};