--- /dev/null
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "gm.h"
+#include "SkCanvas.h"
+#include "SkPath.h"
+
+#define WIDTH 400
+#define HEIGHT 400
+
+namespace {
+// Test thin stroked rect (stroked "by hand", not by stroking).
+void draw_thin_stroked_rect(SkCanvas* canvas, const SkPaint& paint, SkScalar width) {
+ SkPath path;
+ path.moveTo(10 + width, 10 + width);
+ path.lineTo(40, 10 + width);
+ path.lineTo(40, 20);
+ path.lineTo(10 + width, 20);
+ path.moveTo(10, 10);
+ path.lineTo(10, 20 + width);
+ path.lineTo(40 + width, 20 + width);
+ path.lineTo(40 + width, 10);
+ canvas->drawPath(path, paint);
+}
+
+};
+
+class ThinConcavePathsGM : public skiagm::GM {
+public:
+ ThinConcavePathsGM() {}
+
+protected:
+ SkString onShortName() override {
+ return SkString("thinconcavepaths");
+ }
+
+ SkISize onISize() override {
+ return SkISize::Make(WIDTH, HEIGHT);
+ }
+
+ void onDraw(SkCanvas* canvas) override {
+ SkPaint paint;
+
+ paint.setAntiAlias(true);
+ paint.setStyle(SkPaint::kFill_Style);
+
+ canvas->save();
+ for (SkScalar width = 1.0; width < 2.05; width += 0.25) {
+ draw_thin_stroked_rect(canvas, paint, width);
+ canvas->translate(0, 25);
+ }
+ canvas->restore();
+ }
+
+private:
+ typedef skiagm::GM INHERITED;
+};
+
+DEF_GM( return new ThinConcavePathsGM; )
edge, &edge->fTop->fFirstEdgeBelow, &edge->fTop->fLastEdgeBelow);
}
-void erase_edge_if_zero_winding(Edge* edge, EdgeList* edges) {
- if (edge->fWinding != 0) {
- return;
- }
- LOG("erasing edge (%g -> %g)\n", edge->fTop->fID, edge->fBottom->fID);
+void disconnect(Edge* edge)
+{
remove_edge_above(edge);
remove_edge_below(edge);
+}
+
+void erase_edge(Edge* edge, EdgeList* edges) {
+ LOG("erasing edge (%g -> %g)\n", edge->fTop->fID, edge->fBottom->fID);
+ disconnect(edge);
if (edges && edges->contains(edge)) {
remove_edge(edge, edges);
}
edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
other->fWinding += edge->fWinding;
- erase_edge_if_zero_winding(other, activeEdges);
- edge->fWinding = 0;
- erase_edge_if_zero_winding(edge, activeEdges);
+ erase_edge(edge, activeEdges);
} else if (c.sweep_lt(edge->fTop->fPoint, other->fTop->fPoint)) {
other->fWinding += edge->fWinding;
- erase_edge_if_zero_winding(other, activeEdges);
set_bottom(edge, other->fTop, activeEdges, c);
} else {
edge->fWinding += other->fWinding;
- erase_edge_if_zero_winding(edge, activeEdges);
set_bottom(other, edge->fTop, activeEdges, c);
}
}
edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
other->fWinding += edge->fWinding;
- erase_edge_if_zero_winding(other, activeEdges);
- edge->fWinding = 0;
- erase_edge_if_zero_winding(edge, activeEdges);
+ erase_edge(edge, activeEdges);
} else if (c.sweep_lt(edge->fBottom->fPoint, other->fBottom->fPoint)) {
edge->fWinding += other->fWinding;
- erase_edge_if_zero_winding(edge, activeEdges);
set_top(other, edge->fBottom, activeEdges, c);
} else {
other->fWinding += edge->fWinding;
- erase_edge_if_zero_winding(other, activeEdges);
set_top(edge, other->fBottom, activeEdges, c);
}
}
for (Edge* e = v->fFirstEdgeBelow; e != nullptr;) {
Edge* next = e->fNextEdgeBelow;
if (!is_boundary_edge(e, fillType)) {
- remove_edge_above(e);
- remove_edge_below(e);
+ disconnect(e);
}
e = next;
}
down = true;
}
}
- remove_edge_above(e);
- remove_edge_below(e);
+ disconnect(e);
e = next;
}
}