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