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
3807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::cubicTo(const SkPoint& pt1, const SkPoint& pt2, const SkPoint& pt3) {
3907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    lineTo();
40a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com    if (fEmpty && AlmostEqualUlps(fDefer[0], pt1) && AlmostEqualUlps(pt1, pt2)
41a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com            && AlmostEqualUlps(pt2, pt3)) {
42a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com        deferredLine(pt3);
43a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com        return;
44a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com    }
4507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    moveTo();
4607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fDefer[1] = pt3;
4707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    nudge();
4807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fDefer[0] = fDefer[1];
4907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_PATH_CONSTRUCTION
5007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkDebugf("path.cubicTo(%1.9g,%1.9g, %1.9g,%1.9g, %1.9g,%1.9g);\n",
5107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            pt1.fX, pt1.fY, pt2.fX, pt2.fY, fDefer[1].fX, fDefer[1].fY);
5207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
5307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fPathPtr->cubicTo(pt1.fX, pt1.fY, pt2.fX, pt2.fY, fDefer[1].fX, fDefer[1].fY);
5407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fEmpty = false;
5507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
5607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
5707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::deferredLine(const SkPoint& pt) {
5807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (pt == fDefer[1]) {
5907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return;
6007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
6107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (changedSlopes(pt)) {
6207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        lineTo();
6307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        fDefer[0] = fDefer[1];
6407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
6507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fDefer[1] = pt;
6607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
6707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
6807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::deferredMove(const SkPoint& pt) {
6907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fMoved = true;
7007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fHasMove = true;
7107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fEmpty = true;
7207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fDefer[0] = fDefer[1] = pt;
7307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
7407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
7507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::deferredMoveLine(const SkPoint& pt) {
7607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (!fHasMove) {
7707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        deferredMove(pt);
7807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
7907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    deferredLine(pt);
8007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
8107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
8207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.combool SkPathWriter::hasMove() const {
8307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return fHasMove;
8407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
8507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
8607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::init() {
8707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fEmpty = true;
8807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fHasMove = false;
8907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fMoved = false;
9007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
9107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
9207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.combool SkPathWriter::isClosed() const {
937eaa53d8f7e48fd17d02b5e3bd91f90e9c1899efcaryclark@google.com    return !fEmpty && SkDPoint::ApproximatelyEqual(fFirstPt, fDefer[1]);
9407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
9507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
9607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::lineTo() {
9707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (fDefer[0] == fDefer[1]) {
9807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return;
9907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
10007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    moveTo();
10107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    nudge();
10207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fEmpty = false;
10307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_PATH_CONSTRUCTION
10407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkDebugf("path.lineTo(%1.9g,%1.9g);\n", fDefer[1].fX, fDefer[1].fY);
10507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
10607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fPathPtr->lineTo(fDefer[1].fX, fDefer[1].fY);
10707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fDefer[0] = fDefer[1];
10807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
10907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
11007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comconst SkPath* SkPathWriter::nativePath() const {
11107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return fPathPtr;
11207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
11307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
11407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::nudge() {
11507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (fEmpty || !AlmostEqualUlps(fDefer[1].fX, fFirstPt.fX)
11607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            || !AlmostEqualUlps(fDefer[1].fY, fFirstPt.fY)) {
11707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return;
11807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
11907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fDefer[1] = fFirstPt;
12007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
12107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
12207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::quadTo(const SkPoint& pt1, const SkPoint& pt2) {
12307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    lineTo();
124a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com    if (fEmpty && AlmostEqualUlps(fDefer[0], pt1) && AlmostEqualUlps(pt1, pt2)) {
125a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com        deferredLine(pt2);
126a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com        return;
127a5e55925ea03e76885804bda77408a1d6f04c335caryclark@google.com    }
12807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    moveTo();
12907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fDefer[1] = pt2;
13007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    nudge();
13107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fDefer[0] = fDefer[1];
13207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_PATH_CONSTRUCTION
13307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkDebugf("path.quadTo(%1.9g,%1.9g, %1.9g,%1.9g);\n",
13407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com            pt1.fX, pt1.fY, fDefer[1].fX, fDefer[1].fY);
13507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
13607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fPathPtr->quadTo(pt1.fX, pt1.fY, fDefer[1].fX, fDefer[1].fY);
13707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fEmpty = false;
13807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
13907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
14007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.combool SkPathWriter::someAssemblyRequired() const {
14107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return fCloses < fMoves;
14207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
14307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
14407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.combool SkPathWriter::changedSlopes(const SkPoint& pt) const {
14507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (fDefer[0] == fDefer[1]) {
14607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return false;
14707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
14807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkScalar deferDx = fDefer[1].fX - fDefer[0].fX;
14907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkScalar deferDy = fDefer[1].fY - fDefer[0].fY;
15007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkScalar lineDx = pt.fX - fDefer[1].fX;
15107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkScalar lineDy = pt.fY - fDefer[1].fY;
15207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    return deferDx * lineDy != deferDy * lineDx;
15307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
15407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com
15507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.comvoid SkPathWriter::moveTo() {
15607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    if (!fMoved) {
15707393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com        return;
15807393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    }
15907393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fFirstPt = fDefer[0];
16007393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#if DEBUG_PATH_CONSTRUCTION
16107393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    SkDebugf("path.moveTo(%1.9g,%1.9g);\n", fDefer[0].fX, fDefer[0].fY);
16207393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com#endif
16307393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fPathPtr->moveTo(fDefer[0].fX, fDefer[0].fY);
16407393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fMoved = false;
16507393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com    fMoves++;
16607393cab57ce74a4aae89a31fae9aaa9780fc19dcaryclark@google.com}
167