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