107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com/*
207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Copyright 2012 Google Inc.
307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com *
407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * Use of this source code is governed by a BSD-style license that can be
507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com * found in the LICENSE file.
607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com */
7a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com#include "SkPathOpsPoint.h"
807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#include "SkPathWriter.h"
907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com// wrap path to keep track of whether the contour is initialized and non-empty
1107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comSkPathWriter::SkPathWriter(SkPath& path)
1207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    : fPathPtr(&path)
1307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    , fCloses(0)
1407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    , fMoves(0)
1507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com{
1607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    init();
1707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
1807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
1907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::close() {
2007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (!fHasMove) {
2107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return;
2207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
2307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    bool callClose = isClosed();
2407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    lineTo();
2507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (fEmpty) {
2607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return;
2707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
2807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (callClose) {
2907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_PATH_CONSTRUCTION
3007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        SkDebugf("path.close();\n");
3107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
3207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fPathPtr->close();
3307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fCloses++;
3407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
3507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    init();
3607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
3707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
381049f1246e7be4ccb68001361efceb8933e6f81ccaryclarkvoid SkPathWriter::conicTo(const SkPoint& pt1, const SkPoint& pt2, SkScalar weight) {
391049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    lineTo();
401049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    if (fEmpty && AlmostEqualUlps(fDefer[0], pt1) && AlmostEqualUlps(pt1, pt2)) {
411049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        deferredLine(pt2);
421049f1246e7be4ccb68001361efceb8933e6f81ccaryclark        return;
431049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    }
441049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    moveTo();
451049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    fDefer[1] = pt2;
461049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    nudge();
471049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    fDefer[0] = fDefer[1];
481049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#if DEBUG_PATH_CONSTRUCTION
491049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    SkDebugf("path.conicTo(%1.9g,%1.9g, %1.9g,%1.9g, %1.9g);\n",
501049f1246e7be4ccb68001361efceb8933e6f81ccaryclark            pt1.fX, pt1.fY, fDefer[1].fX, fDefer[1].fY, weight);
511049f1246e7be4ccb68001361efceb8933e6f81ccaryclark#endif
521049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    fPathPtr->conicTo(pt1.fX, pt1.fY, fDefer[1].fX, fDefer[1].fY, weight);
531049f1246e7be4ccb68001361efceb8933e6f81ccaryclark    fEmpty = false;
541049f1246e7be4ccb68001361efceb8933e6f81ccaryclark}
551049f1246e7be4ccb68001361efceb8933e6f81ccaryclark
5607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::cubicTo(const SkPoint& pt1, const SkPoint& pt2, const SkPoint& pt3) {
5707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    lineTo();
58a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com    if (fEmpty && AlmostEqualUlps(fDefer[0], pt1) && AlmostEqualUlps(pt1, pt2)
59a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com            && AlmostEqualUlps(pt2, pt3)) {
60a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com        deferredLine(pt3);
61a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com        return;
62a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com    }
6307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    moveTo();
6407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fDefer[1] = pt3;
6507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    nudge();
6607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fDefer[0] = fDefer[1];
6707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_PATH_CONSTRUCTION
6807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkDebugf("path.cubicTo(%1.9g,%1.9g, %1.9g,%1.9g, %1.9g,%1.9g);\n",
6907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            pt1.fX, pt1.fY, pt2.fX, pt2.fY, fDefer[1].fX, fDefer[1].fY);
7007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
7107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fPathPtr->cubicTo(pt1.fX, pt1.fY, pt2.fX, pt2.fY, fDefer[1].fX, fDefer[1].fY);
7207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fEmpty = false;
7307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
7407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
7507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::deferredLine(const SkPoint& pt) {
7607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (pt == fDefer[1]) {
7707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return;
7807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
7907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (changedSlopes(pt)) {
8007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        lineTo();
8107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fDefer[0] = fDefer[1];
8207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
8307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fDefer[1] = pt;
8407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
8507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
8607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::deferredMove(const SkPoint& pt) {
8707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fMoved = true;
8807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fHasMove = true;
8907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fEmpty = true;
9007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fDefer[0] = fDefer[1] = pt;
9107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
9207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
9307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::deferredMoveLine(const SkPoint& pt) {
9407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (!fHasMove) {
9507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        deferredMove(pt);
9607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
9707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    deferredLine(pt);
9807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
9907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
10007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.combool SkPathWriter::hasMove() const {
10107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return fHasMove;
10207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
10307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
10407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::init() {
10507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fEmpty = true;
10607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fHasMove = false;
10707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fMoved = false;
10807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
10907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
11007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.combool SkPathWriter::isClosed() const {
1117eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com    return !fEmpty && SkDPoint::ApproximatelyEqual(fFirstPt, fDefer[1]);
11207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
11307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
11407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::lineTo() {
11507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (fDefer[0] == fDefer[1]) {
11607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return;
11707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
11807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    moveTo();
11907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    nudge();
12007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fEmpty = false;
12107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_PATH_CONSTRUCTION
12207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkDebugf("path.lineTo(%1.9g,%1.9g);\n", fDefer[1].fX, fDefer[1].fY);
12307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
12407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fPathPtr->lineTo(fDefer[1].fX, fDefer[1].fY);
12507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fDefer[0] = fDefer[1];
12607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
12707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
12807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comconst SkPath* SkPathWriter::nativePath() const {
12907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return fPathPtr;
13007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
13107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
13207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::nudge() {
13307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (fEmpty || !AlmostEqualUlps(fDefer[1].fX, fFirstPt.fX)
13407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            || !AlmostEqualUlps(fDefer[1].fY, fFirstPt.fY)) {
13507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return;
13607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
13707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fDefer[1] = fFirstPt;
13807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
13907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
14007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::quadTo(const SkPoint& pt1, const SkPoint& pt2) {
14107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    lineTo();
142a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com    if (fEmpty && AlmostEqualUlps(fDefer[0], pt1) && AlmostEqualUlps(pt1, pt2)) {
143a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com        deferredLine(pt2);
144a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com        return;
145a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com    }
14607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    moveTo();
14707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fDefer[1] = pt2;
14807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    nudge();
14907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fDefer[0] = fDefer[1];
15007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_PATH_CONSTRUCTION
15107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkDebugf("path.quadTo(%1.9g,%1.9g, %1.9g,%1.9g);\n",
15207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            pt1.fX, pt1.fY, fDefer[1].fX, fDefer[1].fY);
15307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
15407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fPathPtr->quadTo(pt1.fX, pt1.fY, fDefer[1].fX, fDefer[1].fY);
15507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fEmpty = false;
15607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
15707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
15807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.combool SkPathWriter::someAssemblyRequired() const {
15907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return fCloses < fMoves;
16007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
16107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
16207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.combool SkPathWriter::changedSlopes(const SkPoint& pt) const {
16307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (fDefer[0] == fDefer[1]) {
16407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return false;
16507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
16607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkScalar deferDx = fDefer[1].fX - fDefer[0].fX;
16707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkScalar deferDy = fDefer[1].fY - fDefer[0].fY;
16807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkScalar lineDx = pt.fX - fDefer[1].fX;
16907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkScalar lineDy = pt.fY - fDefer[1].fY;
17007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return deferDx * lineDy != deferDy * lineDx;
17107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
17207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
17307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::moveTo() {
17407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (!fMoved) {
17507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return;
17607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
17707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fFirstPt = fDefer[0];
17807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_PATH_CONSTRUCTION
17907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkDebugf("path.moveTo(%1.9g,%1.9g);\n", fDefer[0].fX, fDefer[0].fY);
18007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
18107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fPathPtr->moveTo(fDefer[0].fX, fDefer[0].fY);
18207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fMoved = false;
18307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fMoves++;
18407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
185