Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Public Types | Public Member Functions | List of all members
OpAsWinding Class Reference

Public Types

enum class  Edge { kInitial , kCompare }
 

Public Member Functions

 OpAsWinding (const SkPath &path)
 
void contourBounds (vector< Contour > *containers)
 
Contour::Direction getDirection (Contour &contour)
 
int nextEdge (Contour &contour, Edge edge)
 
bool containerContains (Contour &contour, Contour &test)
 
void inParent (Contour &contour, Contour &parent)
 
bool checkContainerChildren (Contour *parent, Contour *child)
 
bool markReverse (Contour *parent, Contour *child)
 
SkPath reverseMarkedContours (vector< Contour > &contours, SkPathFillType fillType)
 

Detailed Description

Definition at line 170 of file SkPathOpsAsWinding.cpp.

Member Enumeration Documentation

◆ Edge

enum class OpAsWinding::Edge
strong
Enumerator
kInitial 
kCompare 

Definition at line 172 of file SkPathOpsAsWinding.cpp.

172 {
173 kInitial,
174 kCompare,
175 };

Constructor & Destructor Documentation

◆ OpAsWinding()

OpAsWinding::OpAsWinding ( const SkPath path)
inline

Definition at line 177 of file SkPathOpsAsWinding.cpp.

178 : fPath(path) {
179 }

Member Function Documentation

◆ checkContainerChildren()

bool OpAsWinding::checkContainerChildren ( Contour parent,
Contour child 
)
inline

Definition at line 328 of file SkPathOpsAsWinding.cpp.

328 {
329 for (auto grandChild : child->fChildren) {
330 if (!checkContainerChildren(child, grandChild)) {
331 return false;
332 }
333 }
334 if (parent) {
335 if (!containerContains(*parent, *child)) {
336 return false;
337 }
338 }
339 return true;
340 }
bool containerContains(Contour &contour, Contour &test)
bool checkContainerChildren(Contour *parent, Contour *child)

◆ containerContains()

bool OpAsWinding::containerContains ( Contour contour,
Contour test 
)
inline

Definition at line 291 of file SkPathOpsAsWinding.cpp.

291 {
292 // find outside point on lesser contour
293 // arbitrarily, choose non-horizontal edge where point <= bounds left
294 // note that if leftmost point is control point, may need tight bounds
295 // to find edge with minimum-x
296 if (SK_ScalarMax == test.fMinXY.fX) {
297 this->nextEdge(test, Edge::kInitial);
298 }
299 // find all edges on greater equal or to the left of one on lesser
300 contour.fMinXY = test.fMinXY;
301 int winding = this->nextEdge(contour, Edge::kCompare);
302 // if edge is up, mark contour cw, otherwise, ccw
303 // sum of greater edges direction should be cw, 0, ccw
304 test.fContained = winding != 0;
305 return -1 <= winding && winding <= 1;
306 }
#define SK_ScalarMax
Definition SkScalar.h:24
int nextEdge(Contour &contour, Edge edge)

◆ contourBounds()

void OpAsWinding::contourBounds ( vector< Contour > *  containers)
inline

Definition at line 181 of file SkPathOpsAsWinding.cpp.

181 {
183 bounds.setEmpty();
184 int lastStart = 0;
185 int verbStart = 0;
186 for (auto [verb, pts, w] : SkPathPriv::Iterate(fPath)) {
187 if (SkPathVerb::kMove == verb) {
188 if (!bounds.isEmpty()) {
189 containers->emplace_back(bounds, lastStart, verbStart);
190 lastStart = verbStart;
191 }
193 }
194 if (SkPathVerb::kLine <= verb && verb <= SkPathVerb::kCubic) {
195 SkRect verbBounds;
196 verbBounds.setBounds(&pts[kPtIndex[(int)verb]], kPtCount[(int)verb]);
197 bounds.joinPossiblyEmptyRect(verbBounds);
198 }
199 ++verbStart;
200 }
201 if (!bounds.isEmpty()) {
202 containers->emplace_back(bounds, lastStart, ++verbStart);
203 }
204 }
static const int kPtIndex[]
static const int kPtCount[]
@ kCubic
SkPath::RawIter returns 4 points.
@ kMove
SkPath::RawIter returns 1 point.
@ kLine
SkPath::RawIter returns 2 points.
@ kMove_Verb
Definition SkPath.h:1458
Optional< SkRect > bounds
Definition SkRecords.h:189
SkScalar w
void setBounds(const SkPoint pts[], int count)
Definition SkRect.h:881

◆ getDirection()

Contour::Direction OpAsWinding::getDirection ( Contour contour)
inline

Definition at line 206 of file SkPathOpsAsWinding.cpp.

206 {
207 SkPath::Iter iter(fPath, true);
208 int verbCount = -1;
209 SkPath::Verb verb;
210 SkPoint pts[4];
211
212 SkScalar total_signed_area = 0;
213 do {
214 verb = iter.next(pts);
215 if (++verbCount < contour.fVerbStart) {
216 continue;
217 }
218 if (verbCount >= contour.fVerbEnd) {
219 continue;
220 }
221 if (SkPath::kLine_Verb > verb || verb > SkPath::kCubic_Verb) {
222 continue;
223 }
224
225 switch (verb)
226 {
228 total_signed_area += (pts[0].fY - pts[1].fY) * (pts[0].fX + pts[1].fX);
229 break;
232 total_signed_area += (pts[0].fY - pts[2].fY) * (pts[0].fX + pts[2].fX);
233 break;
235 total_signed_area += (pts[0].fY - pts[3].fY) * (pts[0].fX + pts[3].fX);
236 break;
237 default:
238 break;
239 }
240 } while (SkPath::kDone_Verb != verb);
241
242 return total_signed_area < 0 ? Contour::Direction::kCCW: Contour::Direction::kCW;
243 }
@ kConic_Verb
Definition SkPath.h:1461
@ kDone_Verb
Definition SkPath.h:1464
@ kCubic_Verb
Definition SkPath.h:1462
@ kQuad_Verb
Definition SkPath.h:1460
@ kLine_Verb
Definition SkPath.h:1459
float SkScalar
Definition extension.cpp:12
float fY
y-axis value

◆ inParent()

void OpAsWinding::inParent ( Contour contour,
Contour parent 
)
inline

Definition at line 308 of file SkPathOpsAsWinding.cpp.

308 {
309 // move contour into sibling list contained by parent
310 for (auto test : parent.fChildren) {
311 if (test->fBounds.contains(contour.fBounds)) {
313 return;
314 }
315 }
316 // move parent's children into contour's children if contained by contour
317 for (auto iter = parent.fChildren.begin(); iter != parent.fChildren.end(); ) {
318 if (contour.fBounds.contains((*iter)->fBounds)) {
319 contour.fChildren.push_back(*iter);
320 iter = parent.fChildren.erase(iter);
321 continue;
322 }
323 ++iter;
324 }
325 parent.fChildren.push_back(&contour);
326 }
void inParent(Contour &contour, Contour &parent)
vector< Contour * > fChildren

◆ markReverse()

bool OpAsWinding::markReverse ( Contour parent,
Contour child 
)
inline

Definition at line 342 of file SkPathOpsAsWinding.cpp.

342 {
343 bool reversed = false;
344 for (auto grandChild : child->fChildren) {
345 reversed |= markReverse(grandChild->fContained ? child : parent, grandChild);
346 }
347
348 child->fDirection = getDirection(*child);
349 if (parent && parent->fDirection == child->fDirection) {
350 child->fReverse = true;
351 child->fDirection = (Contour::Direction) -(int) child->fDirection;
352 return true;
353 }
354 return reversed;
355 }
Contour::Direction getDirection(Contour &contour)
bool markReverse(Contour *parent, Contour *child)
Direction fDirection

◆ nextEdge()

int OpAsWinding::nextEdge ( Contour contour,
Edge  edge 
)
inline

Definition at line 245 of file SkPathOpsAsWinding.cpp.

245 {
246 SkPath::Iter iter(fPath, true);
247 SkPoint pts[4];
248 SkPath::Verb verb;
249 int verbCount = -1;
250 int winding = 0;
251 do {
252 verb = iter.next(pts);
253 if (++verbCount < contour.fVerbStart) {
254 continue;
255 }
256 if (verbCount >= contour.fVerbEnd) {
257 continue;
258 }
259 if (SkPath::kLine_Verb > verb || verb > SkPath::kCubic_Verb) {
260 continue;
261 }
262 bool horizontal = true;
263 for (int index = 1; index <= kPtCount[verb]; ++index) {
264 if (pts[0].fY != pts[index].fY) {
265 horizontal = false;
266 break;
267 }
268 }
269 if (horizontal) {
270 continue;
271 }
272 if (edge == Edge::kCompare) {
273 winding += contains_edge(pts, verb, conic_weight(iter, verb), contour.fMinXY);
274 continue;
275 }
276 SkASSERT(edge == Edge::kInitial);
277 SkPoint minXY = left_edge(pts, verb, conic_weight(iter, verb));
278 if (minXY.fX > contour.fMinXY.fX) {
279 continue;
280 }
281 if (minXY.fX == contour.fMinXY.fX) {
282 if (minXY.fY != contour.fMinXY.fY) {
283 continue;
284 }
285 }
286 contour.fMinXY = minXY;
287 } while (SkPath::kDone_Verb != verb);
288 return winding;
289 }
#define SkASSERT(cond)
Definition SkAssert.h:116
static SkPoint left_edge(SkPoint pts[4], SkPath::Verb verb, SkScalar weight)
static SkScalar conic_weight(const SkPath::Iter &iter, SkPath::Verb verb)
static int contains_edge(SkPoint pts[4], SkPath::Verb verb, SkScalar weight, const SkPoint &edge)
float fX
x-axis value

◆ reverseMarkedContours()

SkPath OpAsWinding::reverseMarkedContours ( vector< Contour > &  contours,
SkPathFillType  fillType 
)
inline

Definition at line 357 of file SkPathOpsAsWinding.cpp.

357 {
358 SkPathPriv::Iterate iterate(fPath);
359 auto iter = iterate.begin();
360 int verbCount = 0;
361
363 result.setFillType(fillType);
364 for (const Contour& contour : contours) {
366 SkPathBuilder* temp = contour.fReverse ? &reverse : &result;
367 for (; iter != iterate.end() && verbCount < contour.fVerbEnd; ++iter, ++verbCount) {
368 auto [verb, pts, w] = *iter;
369 switch (verb) {
371 temp->moveTo(pts[0]);
372 break;
374 temp->lineTo(pts[1]);
375 break;
377 temp->quadTo(pts[1], pts[2]);
378 break;
380 temp->conicTo(pts[1], pts[2], *w);
381 break;
383 temp->cubicTo(pts[1], pts[2], pts[3]);
384 break;
386 temp->close();
387 break;
388 }
389 }
390 if (contour.fReverse) {
391 SkASSERT(temp == &reverse);
393 }
394 }
395 return result.detach();
396 }
@ kClose
SkPath::RawIter returns 0 points.
@ kConic
SkPath::RawIter returns 3 points + 1 weight.
@ kQuad
SkPath::RawIter returns 3 points.
SkPathBuilder & conicTo(SkPoint pt1, SkPoint pt2, SkScalar w)
SkPathBuilder & close()
SkPathBuilder & lineTo(SkPoint pt)
SkPathBuilder & setFillType(SkPathFillType ft)
SkPathBuilder & cubicTo(SkPoint pt1, SkPoint pt2, SkPoint pt3)
SkPathBuilder & moveTo(SkPoint pt)
SkPathBuilder & quadTo(SkPoint pt1, SkPoint pt2)
static void ReverseAddPath(SkPathBuilder *builder, const SkPath &reverseMe)
Definition SkPathPriv.h:421
GAsyncResult * result

The documentation for this class was generated from the following file: