Index: src/pathops/SkPathWriter.cpp |
=================================================================== |
--- src/pathops/SkPathWriter.cpp (revision 0) |
+++ src/pathops/SkPathWriter.cpp (revision 0) |
@@ -0,0 +1,157 @@ |
+/* |
+ * Copyright 2012 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+#include "SkPathOpsTypes.h" |
+#include "SkPathWriter.h" |
+ |
+// wrap path to keep track of whether the contour is initialized and non-empty |
+SkPathWriter::SkPathWriter(SkPath& path) |
+ : fPathPtr(&path) |
+ , fCloses(0) |
+ , fMoves(0) |
+{ |
+ init(); |
+} |
+ |
+void SkPathWriter::close() { |
+ if (!fHasMove) { |
+ return; |
+ } |
+ bool callClose = isClosed(); |
+ lineTo(); |
+ if (fEmpty) { |
+ return; |
+ } |
+ if (callClose) { |
+#if DEBUG_PATH_CONSTRUCTION |
+ SkDebugf("path.close();\n"); |
+#endif |
+ fPathPtr->close(); |
+ fCloses++; |
+ } |
+ init(); |
+} |
+ |
+void SkPathWriter::cubicTo(const SkPoint& pt1, const SkPoint& pt2, const SkPoint& pt3) { |
+ lineTo(); |
+ moveTo(); |
+ fDefer[1] = pt3; |
+ nudge(); |
+ fDefer[0] = fDefer[1]; |
+#if DEBUG_PATH_CONSTRUCTION |
+ SkDebugf("path.cubicTo(%1.9g,%1.9g, %1.9g,%1.9g, %1.9g,%1.9g);\n", |
+ pt1.fX, pt1.fY, pt2.fX, pt2.fY, fDefer[1].fX, fDefer[1].fY); |
+#endif |
+ fPathPtr->cubicTo(pt1.fX, pt1.fY, pt2.fX, pt2.fY, fDefer[1].fX, fDefer[1].fY); |
+ fEmpty = false; |
+} |
+ |
+void SkPathWriter::deferredLine(const SkPoint& pt) { |
+ if (pt == fDefer[1]) { |
+ return; |
+ } |
+ if (changedSlopes(pt)) { |
+ lineTo(); |
+ fDefer[0] = fDefer[1]; |
+ } |
+ fDefer[1] = pt; |
+} |
+ |
+void SkPathWriter::deferredMove(const SkPoint& pt) { |
+ fMoved = true; |
+ fHasMove = true; |
+ fEmpty = true; |
+ fDefer[0] = fDefer[1] = pt; |
+} |
+ |
+void SkPathWriter::deferredMoveLine(const SkPoint& pt) { |
+ if (!fHasMove) { |
+ deferredMove(pt); |
+ } |
+ deferredLine(pt); |
+} |
+ |
+bool SkPathWriter::hasMove() const { |
+ return fHasMove; |
+} |
+ |
+void SkPathWriter::init() { |
+ fEmpty = true; |
+ fHasMove = false; |
+ fMoved = false; |
+} |
+ |
+bool SkPathWriter::isClosed() const { |
+ return !fEmpty && fFirstPt == fDefer[1]; |
+} |
+ |
+void SkPathWriter::lineTo() { |
+ if (fDefer[0] == fDefer[1]) { |
+ return; |
+ } |
+ moveTo(); |
+ nudge(); |
+ fEmpty = false; |
+#if DEBUG_PATH_CONSTRUCTION |
+ SkDebugf("path.lineTo(%1.9g,%1.9g);\n", fDefer[1].fX, fDefer[1].fY); |
+#endif |
+ fPathPtr->lineTo(fDefer[1].fX, fDefer[1].fY); |
+ fDefer[0] = fDefer[1]; |
+} |
+ |
+const SkPath* SkPathWriter::nativePath() const { |
+ return fPathPtr; |
+} |
+ |
+void SkPathWriter::nudge() { |
+ if (fEmpty || !AlmostEqualUlps(fDefer[1].fX, fFirstPt.fX) |
+ || !AlmostEqualUlps(fDefer[1].fY, fFirstPt.fY)) { |
+ return; |
+ } |
+ fDefer[1] = fFirstPt; |
+} |
+ |
+void SkPathWriter::quadTo(const SkPoint& pt1, const SkPoint& pt2) { |
+ lineTo(); |
+ moveTo(); |
+ fDefer[1] = pt2; |
+ nudge(); |
+ fDefer[0] = fDefer[1]; |
+#if DEBUG_PATH_CONSTRUCTION |
+ SkDebugf("path.quadTo(%1.9g,%1.9g, %1.9g,%1.9g);\n", |
+ pt1.fX, pt1.fY, fDefer[1].fX, fDefer[1].fY); |
+#endif |
+ fPathPtr->quadTo(pt1.fX, pt1.fY, fDefer[1].fX, fDefer[1].fY); |
+ fEmpty = false; |
+} |
+ |
+bool SkPathWriter::someAssemblyRequired() const { |
+ return fCloses < fMoves; |
+} |
+ |
+bool SkPathWriter::changedSlopes(const SkPoint& pt) const { |
+ if (fDefer[0] == fDefer[1]) { |
+ return false; |
+ } |
+ SkScalar deferDx = fDefer[1].fX - fDefer[0].fX; |
+ SkScalar deferDy = fDefer[1].fY - fDefer[0].fY; |
+ SkScalar lineDx = pt.fX - fDefer[1].fX; |
+ SkScalar lineDy = pt.fY - fDefer[1].fY; |
+ return deferDx * lineDy != deferDy * lineDx; |
+} |
+ |
+void SkPathWriter::moveTo() { |
+ if (!fMoved) { |
+ return; |
+ } |
+ fFirstPt = fDefer[0]; |
+#if DEBUG_PATH_CONSTRUCTION |
+ SkDebugf("path.moveTo(%1.9g,%1.9g);\n", fDefer[0].fX, fDefer[0].fY); |
+#endif |
+ fPathPtr->moveTo(fDefer[0].fX, fDefer[0].fY); |
+ fMoved = false; |
+ fMoves++; |
+} |