diff -r 000000000000 -r 6474c204b198 gfx/skia/trunk/src/pathops/SkPathWriter.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/gfx/skia/trunk/src/pathops/SkPathWriter.cpp Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,166 @@ +/* + * 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 "SkPathOpsPoint.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(); + if (fEmpty && AlmostEqualUlps(fDefer[0], pt1) && AlmostEqualUlps(pt1, pt2) + && AlmostEqualUlps(pt2, pt3)) { + deferredLine(pt3); + return; + } + 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 && SkDPoint::ApproximatelyEqual(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(); + if (fEmpty && AlmostEqualUlps(fDefer[0], pt1) && AlmostEqualUlps(pt1, pt2)) { + deferredLine(pt2); + return; + } + 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++; +}