• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 #include "SkPathOpsPoint.h"
8 #include "SkPathWriter.h"
9 
10 // wrap path to keep track of whether the contour is initialized and non-empty
SkPathWriter(SkPath & path)11 SkPathWriter::SkPathWriter(SkPath& path)
12     : fPathPtr(&path)
13     , fCloses(0)
14     , fMoves(0)
15 {
16     init();
17 }
18 
close()19 void SkPathWriter::close() {
20     if (!fHasMove) {
21         return;
22     }
23     bool callClose = isClosed();
24     lineTo();
25     if (fEmpty) {
26         return;
27     }
28     if (callClose) {
29 #if DEBUG_PATH_CONSTRUCTION
30         SkDebugf("path.close();\n");
31 #endif
32         fPathPtr->close();
33         fCloses++;
34     }
35     init();
36 }
37 
cubicTo(const SkPoint & pt1,const SkPoint & pt2,const SkPoint & pt3)38 void SkPathWriter::cubicTo(const SkPoint& pt1, const SkPoint& pt2, const SkPoint& pt3) {
39     lineTo();
40     if (fEmpty && AlmostEqualUlps(fDefer[0], pt1) && AlmostEqualUlps(pt1, pt2)
41             && AlmostEqualUlps(pt2, pt3)) {
42         deferredLine(pt3);
43         return;
44     }
45     moveTo();
46     fDefer[1] = pt3;
47     nudge();
48     fDefer[0] = fDefer[1];
49 #if DEBUG_PATH_CONSTRUCTION
50     SkDebugf("path.cubicTo(%1.9g,%1.9g, %1.9g,%1.9g, %1.9g,%1.9g);\n",
51             pt1.fX, pt1.fY, pt2.fX, pt2.fY, fDefer[1].fX, fDefer[1].fY);
52 #endif
53     fPathPtr->cubicTo(pt1.fX, pt1.fY, pt2.fX, pt2.fY, fDefer[1].fX, fDefer[1].fY);
54     fEmpty = false;
55 }
56 
deferredLine(const SkPoint & pt)57 void SkPathWriter::deferredLine(const SkPoint& pt) {
58     if (pt == fDefer[1]) {
59         return;
60     }
61     if (changedSlopes(pt)) {
62         lineTo();
63         fDefer[0] = fDefer[1];
64     }
65     fDefer[1] = pt;
66 }
67 
deferredMove(const SkPoint & pt)68 void SkPathWriter::deferredMove(const SkPoint& pt) {
69     fMoved = true;
70     fHasMove = true;
71     fEmpty = true;
72     fDefer[0] = fDefer[1] = pt;
73 }
74 
deferredMoveLine(const SkPoint & pt)75 void SkPathWriter::deferredMoveLine(const SkPoint& pt) {
76     if (!fHasMove) {
77         deferredMove(pt);
78     }
79     deferredLine(pt);
80 }
81 
hasMove() const82 bool SkPathWriter::hasMove() const {
83     return fHasMove;
84 }
85 
init()86 void SkPathWriter::init() {
87     fEmpty = true;
88     fHasMove = false;
89     fMoved = false;
90 }
91 
isClosed() const92 bool SkPathWriter::isClosed() const {
93     return !fEmpty && SkDPoint::ApproximatelyEqual(fFirstPt, fDefer[1]);
94 }
95 
lineTo()96 void SkPathWriter::lineTo() {
97     if (fDefer[0] == fDefer[1]) {
98         return;
99     }
100     moveTo();
101     nudge();
102     fEmpty = false;
103 #if DEBUG_PATH_CONSTRUCTION
104     SkDebugf("path.lineTo(%1.9g,%1.9g);\n", fDefer[1].fX, fDefer[1].fY);
105 #endif
106     fPathPtr->lineTo(fDefer[1].fX, fDefer[1].fY);
107     fDefer[0] = fDefer[1];
108 }
109 
nativePath() const110 const SkPath* SkPathWriter::nativePath() const {
111     return fPathPtr;
112 }
113 
nudge()114 void SkPathWriter::nudge() {
115     if (fEmpty || !AlmostEqualUlps(fDefer[1].fX, fFirstPt.fX)
116             || !AlmostEqualUlps(fDefer[1].fY, fFirstPt.fY)) {
117         return;
118     }
119     fDefer[1] = fFirstPt;
120 }
121 
quadTo(const SkPoint & pt1,const SkPoint & pt2)122 void SkPathWriter::quadTo(const SkPoint& pt1, const SkPoint& pt2) {
123     lineTo();
124     if (fEmpty && AlmostEqualUlps(fDefer[0], pt1) && AlmostEqualUlps(pt1, pt2)) {
125         deferredLine(pt2);
126         return;
127     }
128     moveTo();
129     fDefer[1] = pt2;
130     nudge();
131     fDefer[0] = fDefer[1];
132 #if DEBUG_PATH_CONSTRUCTION
133     SkDebugf("path.quadTo(%1.9g,%1.9g, %1.9g,%1.9g);\n",
134             pt1.fX, pt1.fY, fDefer[1].fX, fDefer[1].fY);
135 #endif
136     fPathPtr->quadTo(pt1.fX, pt1.fY, fDefer[1].fX, fDefer[1].fY);
137     fEmpty = false;
138 }
139 
someAssemblyRequired() const140 bool SkPathWriter::someAssemblyRequired() const {
141     return fCloses < fMoves;
142 }
143 
changedSlopes(const SkPoint & pt) const144 bool SkPathWriter::changedSlopes(const SkPoint& pt) const {
145     if (fDefer[0] == fDefer[1]) {
146         return false;
147     }
148     SkScalar deferDx = fDefer[1].fX - fDefer[0].fX;
149     SkScalar deferDy = fDefer[1].fY - fDefer[0].fY;
150     SkScalar lineDx = pt.fX - fDefer[1].fX;
151     SkScalar lineDy = pt.fY - fDefer[1].fY;
152     return deferDx * lineDy != deferDy * lineDx;
153 }
154 
moveTo()155 void SkPathWriter::moveTo() {
156     if (!fMoved) {
157         return;
158     }
159     fFirstPt = fDefer[0];
160 #if DEBUG_PATH_CONSTRUCTION
161     SkDebugf("path.moveTo(%1.9g,%1.9g);\n", fDefer[0].fX, fDefer[0].fY);
162 #endif
163     fPathPtr->moveTo(fDefer[0].fX, fDefer[0].fY);
164     fMoved = false;
165     fMoves++;
166 }
167