17839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger/*
27839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * Copyright 2012 Google Inc.
37839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger *
47839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * Use of this source code is governed by a BSD-style license that can be
57839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger * found in the LICENSE file.
67839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger */
77839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkPathOpsPoint.h"
87839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#include "SkPathWriter.h"
97839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// wrap path to keep track of whether the contour is initialized and non-empty
117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek SollenbergerSkPathWriter::SkPathWriter(SkPath& path)
127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    : fPathPtr(&path)
137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    , fCloses(0)
147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    , fMoves(0)
157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger{
167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    init();
177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergervoid SkPathWriter::close() {
207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (!fHasMove) {
217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return;
227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    bool callClose = isClosed();
247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    lineTo();
257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (fEmpty) {
267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return;
277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (callClose) {
297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#if DEBUG_PATH_CONSTRUCTION
307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        SkDebugf("path.close();\n");
317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#endif
327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        fPathPtr->close();
337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        fCloses++;
347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    init();
367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergervoid SkPathWriter::cubicTo(const SkPoint& pt1, const SkPoint& pt2, const SkPoint& pt3) {
397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    lineTo();
407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (fEmpty && AlmostEqualUlps(fDefer[0], pt1) && AlmostEqualUlps(pt1, pt2)
417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            && AlmostEqualUlps(pt2, pt3)) {
427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        deferredLine(pt3);
437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return;
447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    moveTo();
467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fDefer[1] = pt3;
477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    nudge();
487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fDefer[0] = fDefer[1];
497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#if DEBUG_PATH_CONSTRUCTION
507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkDebugf("path.cubicTo(%1.9g,%1.9g, %1.9g,%1.9g, %1.9g,%1.9g);\n",
517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            pt1.fX, pt1.fY, pt2.fX, pt2.fY, fDefer[1].fX, fDefer[1].fY);
527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#endif
537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fPathPtr->cubicTo(pt1.fX, pt1.fY, pt2.fX, pt2.fY, fDefer[1].fX, fDefer[1].fY);
547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fEmpty = false;
557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergervoid SkPathWriter::deferredLine(const SkPoint& pt) {
587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (pt == fDefer[1]) {
597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return;
607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (changedSlopes(pt)) {
627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        lineTo();
637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        fDefer[0] = fDefer[1];
647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fDefer[1] = pt;
667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
687839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergervoid SkPathWriter::deferredMove(const SkPoint& pt) {
697839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fMoved = true;
707839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fHasMove = true;
717839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fEmpty = true;
727839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fDefer[0] = fDefer[1] = pt;
737839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
747839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
757839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergervoid SkPathWriter::deferredMoveLine(const SkPoint& pt) {
767839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (!fHasMove) {
777839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        deferredMove(pt);
787839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
797839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    deferredLine(pt);
807839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
817839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
827839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerbool SkPathWriter::hasMove() const {
837839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return fHasMove;
847839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
857839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
867839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergervoid SkPathWriter::init() {
877839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fEmpty = true;
887839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fHasMove = false;
897839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fMoved = false;
907839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
917839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
927839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerbool SkPathWriter::isClosed() const {
930a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    return !fEmpty && SkDPoint::ApproximatelyEqual(fFirstPt, fDefer[1]);
947839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
957839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
967839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergervoid SkPathWriter::lineTo() {
977839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (fDefer[0] == fDefer[1]) {
987839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return;
997839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1007839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    moveTo();
1017839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    nudge();
1027839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fEmpty = false;
1037839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#if DEBUG_PATH_CONSTRUCTION
1047839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkDebugf("path.lineTo(%1.9g,%1.9g);\n", fDefer[1].fX, fDefer[1].fY);
1057839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#endif
1067839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fPathPtr->lineTo(fDefer[1].fX, fDefer[1].fY);
1077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fDefer[0] = fDefer[1];
1087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
1097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerconst SkPath* SkPathWriter::nativePath() const {
1117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return fPathPtr;
1127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
1137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergervoid SkPathWriter::nudge() {
1157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (fEmpty || !AlmostEqualUlps(fDefer[1].fX, fFirstPt.fX)
1167839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            || !AlmostEqualUlps(fDefer[1].fY, fFirstPt.fY)) {
1177839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return;
1187839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1197839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fDefer[1] = fFirstPt;
1207839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
1217839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1227839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergervoid SkPathWriter::quadTo(const SkPoint& pt1, const SkPoint& pt2) {
1237839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    lineTo();
1247839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (fEmpty && AlmostEqualUlps(fDefer[0], pt1) && AlmostEqualUlps(pt1, pt2)) {
1257839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        deferredLine(pt2);
1267839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return;
1277839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1287839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    moveTo();
1297839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fDefer[1] = pt2;
1307839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    nudge();
1317839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fDefer[0] = fDefer[1];
1327839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#if DEBUG_PATH_CONSTRUCTION
1337839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkDebugf("path.quadTo(%1.9g,%1.9g, %1.9g,%1.9g);\n",
1347839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            pt1.fX, pt1.fY, fDefer[1].fX, fDefer[1].fY);
1357839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#endif
1367839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fPathPtr->quadTo(pt1.fX, pt1.fY, fDefer[1].fX, fDefer[1].fY);
1377839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fEmpty = false;
1387839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
1397839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1407839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerbool SkPathWriter::someAssemblyRequired() const {
1417839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return fCloses < fMoves;
1427839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
1437839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1447839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergerbool SkPathWriter::changedSlopes(const SkPoint& pt) const {
1457839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (fDefer[0] == fDefer[1]) {
1467839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return false;
1477839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1487839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkScalar deferDx = fDefer[1].fX - fDefer[0].fX;
1497839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkScalar deferDy = fDefer[1].fY - fDefer[0].fY;
1507839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkScalar lineDx = pt.fX - fDefer[1].fX;
1517839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkScalar lineDy = pt.fY - fDefer[1].fY;
1527839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    return deferDx * lineDy != deferDy * lineDx;
1537839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
1547839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
1557839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenbergervoid SkPathWriter::moveTo() {
1567839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (!fMoved) {
1577839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        return;
1587839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
1597839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fFirstPt = fDefer[0];
1607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#if DEBUG_PATH_CONSTRUCTION
1617839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    SkDebugf("path.moveTo(%1.9g,%1.9g);\n", fDefer[0].fX, fDefer[0].fY);
1627839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#endif
1637839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fPathPtr->moveTo(fDefer[0].fX, fDefer[0].fY);
1647839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fMoved = false;
1657839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    fMoves++;
1667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger}
167