1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/pathops/SkPathWriter.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,166 @@ 1.4 +/* 1.5 + * Copyright 2012 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 +#include "SkPathOpsPoint.h" 1.11 +#include "SkPathWriter.h" 1.12 + 1.13 +// wrap path to keep track of whether the contour is initialized and non-empty 1.14 +SkPathWriter::SkPathWriter(SkPath& path) 1.15 + : fPathPtr(&path) 1.16 + , fCloses(0) 1.17 + , fMoves(0) 1.18 +{ 1.19 + init(); 1.20 +} 1.21 + 1.22 +void SkPathWriter::close() { 1.23 + if (!fHasMove) { 1.24 + return; 1.25 + } 1.26 + bool callClose = isClosed(); 1.27 + lineTo(); 1.28 + if (fEmpty) { 1.29 + return; 1.30 + } 1.31 + if (callClose) { 1.32 +#if DEBUG_PATH_CONSTRUCTION 1.33 + SkDebugf("path.close();\n"); 1.34 +#endif 1.35 + fPathPtr->close(); 1.36 + fCloses++; 1.37 + } 1.38 + init(); 1.39 +} 1.40 + 1.41 +void SkPathWriter::cubicTo(const SkPoint& pt1, const SkPoint& pt2, const SkPoint& pt3) { 1.42 + lineTo(); 1.43 + if (fEmpty && AlmostEqualUlps(fDefer[0], pt1) && AlmostEqualUlps(pt1, pt2) 1.44 + && AlmostEqualUlps(pt2, pt3)) { 1.45 + deferredLine(pt3); 1.46 + return; 1.47 + } 1.48 + moveTo(); 1.49 + fDefer[1] = pt3; 1.50 + nudge(); 1.51 + fDefer[0] = fDefer[1]; 1.52 +#if DEBUG_PATH_CONSTRUCTION 1.53 + SkDebugf("path.cubicTo(%1.9g,%1.9g, %1.9g,%1.9g, %1.9g,%1.9g);\n", 1.54 + pt1.fX, pt1.fY, pt2.fX, pt2.fY, fDefer[1].fX, fDefer[1].fY); 1.55 +#endif 1.56 + fPathPtr->cubicTo(pt1.fX, pt1.fY, pt2.fX, pt2.fY, fDefer[1].fX, fDefer[1].fY); 1.57 + fEmpty = false; 1.58 +} 1.59 + 1.60 +void SkPathWriter::deferredLine(const SkPoint& pt) { 1.61 + if (pt == fDefer[1]) { 1.62 + return; 1.63 + } 1.64 + if (changedSlopes(pt)) { 1.65 + lineTo(); 1.66 + fDefer[0] = fDefer[1]; 1.67 + } 1.68 + fDefer[1] = pt; 1.69 +} 1.70 + 1.71 +void SkPathWriter::deferredMove(const SkPoint& pt) { 1.72 + fMoved = true; 1.73 + fHasMove = true; 1.74 + fEmpty = true; 1.75 + fDefer[0] = fDefer[1] = pt; 1.76 +} 1.77 + 1.78 +void SkPathWriter::deferredMoveLine(const SkPoint& pt) { 1.79 + if (!fHasMove) { 1.80 + deferredMove(pt); 1.81 + } 1.82 + deferredLine(pt); 1.83 +} 1.84 + 1.85 +bool SkPathWriter::hasMove() const { 1.86 + return fHasMove; 1.87 +} 1.88 + 1.89 +void SkPathWriter::init() { 1.90 + fEmpty = true; 1.91 + fHasMove = false; 1.92 + fMoved = false; 1.93 +} 1.94 + 1.95 +bool SkPathWriter::isClosed() const { 1.96 + return !fEmpty && SkDPoint::ApproximatelyEqual(fFirstPt, fDefer[1]); 1.97 +} 1.98 + 1.99 +void SkPathWriter::lineTo() { 1.100 + if (fDefer[0] == fDefer[1]) { 1.101 + return; 1.102 + } 1.103 + moveTo(); 1.104 + nudge(); 1.105 + fEmpty = false; 1.106 +#if DEBUG_PATH_CONSTRUCTION 1.107 + SkDebugf("path.lineTo(%1.9g,%1.9g);\n", fDefer[1].fX, fDefer[1].fY); 1.108 +#endif 1.109 + fPathPtr->lineTo(fDefer[1].fX, fDefer[1].fY); 1.110 + fDefer[0] = fDefer[1]; 1.111 +} 1.112 + 1.113 +const SkPath* SkPathWriter::nativePath() const { 1.114 + return fPathPtr; 1.115 +} 1.116 + 1.117 +void SkPathWriter::nudge() { 1.118 + if (fEmpty || !AlmostEqualUlps(fDefer[1].fX, fFirstPt.fX) 1.119 + || !AlmostEqualUlps(fDefer[1].fY, fFirstPt.fY)) { 1.120 + return; 1.121 + } 1.122 + fDefer[1] = fFirstPt; 1.123 +} 1.124 + 1.125 +void SkPathWriter::quadTo(const SkPoint& pt1, const SkPoint& pt2) { 1.126 + lineTo(); 1.127 + if (fEmpty && AlmostEqualUlps(fDefer[0], pt1) && AlmostEqualUlps(pt1, pt2)) { 1.128 + deferredLine(pt2); 1.129 + return; 1.130 + } 1.131 + moveTo(); 1.132 + fDefer[1] = pt2; 1.133 + nudge(); 1.134 + fDefer[0] = fDefer[1]; 1.135 +#if DEBUG_PATH_CONSTRUCTION 1.136 + SkDebugf("path.quadTo(%1.9g,%1.9g, %1.9g,%1.9g);\n", 1.137 + pt1.fX, pt1.fY, fDefer[1].fX, fDefer[1].fY); 1.138 +#endif 1.139 + fPathPtr->quadTo(pt1.fX, pt1.fY, fDefer[1].fX, fDefer[1].fY); 1.140 + fEmpty = false; 1.141 +} 1.142 + 1.143 +bool SkPathWriter::someAssemblyRequired() const { 1.144 + return fCloses < fMoves; 1.145 +} 1.146 + 1.147 +bool SkPathWriter::changedSlopes(const SkPoint& pt) const { 1.148 + if (fDefer[0] == fDefer[1]) { 1.149 + return false; 1.150 + } 1.151 + SkScalar deferDx = fDefer[1].fX - fDefer[0].fX; 1.152 + SkScalar deferDy = fDefer[1].fY - fDefer[0].fY; 1.153 + SkScalar lineDx = pt.fX - fDefer[1].fX; 1.154 + SkScalar lineDy = pt.fY - fDefer[1].fY; 1.155 + return deferDx * lineDy != deferDy * lineDx; 1.156 +} 1.157 + 1.158 +void SkPathWriter::moveTo() { 1.159 + if (!fMoved) { 1.160 + return; 1.161 + } 1.162 + fFirstPt = fDefer[0]; 1.163 +#if DEBUG_PATH_CONSTRUCTION 1.164 + SkDebugf("path.moveTo(%1.9g,%1.9g);\n", fDefer[0].fX, fDefer[0].fY); 1.165 +#endif 1.166 + fPathPtr->moveTo(fDefer[0].fX, fDefer[0].fY); 1.167 + fMoved = false; 1.168 + fMoves++; 1.169 +}