1 /*
2 * Copyright 2013 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 "src/core/SkTSort.h"
8 #include "src/pathops/SkOpContour.h"
9 #include "src/pathops/SkPathWriter.h"
10 #include "src/pathops/SkReduceOrder.h"
11
toPath(SkPathWriter * path) const12 void SkOpContour::toPath(SkPathWriter* path) const {
13 if (!this->count()) {
14 return;
15 }
16 const SkOpSegment* segment = &fHead;
17 do {
18 SkAssertResult(segment->addCurveTo(segment->head(), segment->tail(), path));
19 } while ((segment = segment->next()));
20 path->finishContour();
21 path->assemble();
22 }
23
toReversePath(SkPathWriter * path) const24 void SkOpContour::toReversePath(SkPathWriter* path) const {
25 const SkOpSegment* segment = fTail;
26 do {
27 SkAssertResult(segment->addCurveTo(segment->tail(), segment->head(), path));
28 } while ((segment = segment->prev()));
29 path->finishContour();
30 path->assemble();
31 }
32
undoneSpan()33 SkOpSpan* SkOpContour::undoneSpan() {
34 SkOpSegment* testSegment = &fHead;
35 do {
36 if (testSegment->done()) {
37 continue;
38 }
39 return testSegment->undoneSpan();
40 } while ((testSegment = testSegment->next()));
41 fDone = true;
42 return nullptr;
43 }
44
addConic(SkPoint pts[3],SkScalar weight)45 void SkOpContourBuilder::addConic(SkPoint pts[3], SkScalar weight) {
46 this->flush();
47 fContour->addConic(pts, weight);
48 }
49
addCubic(SkPoint pts[4])50 void SkOpContourBuilder::addCubic(SkPoint pts[4]) {
51 this->flush();
52 fContour->addCubic(pts);
53 }
54
addCurve(SkPath::Verb verb,const SkPoint pts[4],SkScalar weight)55 void SkOpContourBuilder::addCurve(SkPath::Verb verb, const SkPoint pts[4], SkScalar weight) {
56 if (SkPath::kLine_Verb == verb) {
57 this->addLine(pts);
58 return;
59 }
60 SkArenaAlloc* allocator = fContour->globalState()->allocator();
61 switch (verb) {
62 case SkPath::kQuad_Verb: {
63 SkPoint* ptStorage = allocator->makeArrayDefault<SkPoint>(3);
64 memcpy(ptStorage, pts, sizeof(SkPoint) * 3);
65 this->addQuad(ptStorage);
66 } break;
67 case SkPath::kConic_Verb: {
68 SkPoint* ptStorage = allocator->makeArrayDefault<SkPoint>(3);
69 memcpy(ptStorage, pts, sizeof(SkPoint) * 3);
70 this->addConic(ptStorage, weight);
71 } break;
72 case SkPath::kCubic_Verb: {
73 SkPoint* ptStorage = allocator->makeArrayDefault<SkPoint>(4);
74 memcpy(ptStorage, pts, sizeof(SkPoint) * 4);
75 this->addCubic(ptStorage);
76 } break;
77 default:
78 SkASSERT(0);
79 }
80 }
81
addLine(const SkPoint pts[2])82 void SkOpContourBuilder::addLine(const SkPoint pts[2]) {
83 // if the previous line added is the exact opposite, eliminate both
84 if (fLastIsLine) {
85 if (fLastLine[0] == pts[1] && fLastLine[1] == pts[0]) {
86 fLastIsLine = false;
87 return;
88 } else {
89 flush();
90 }
91 }
92 memcpy(fLastLine, pts, sizeof(fLastLine));
93 fLastIsLine = true;
94 }
95
addQuad(SkPoint pts[3])96 void SkOpContourBuilder::addQuad(SkPoint pts[3]) {
97 this->flush();
98 fContour->addQuad(pts);
99 }
100
flush()101 void SkOpContourBuilder::flush() {
102 if (!fLastIsLine)
103 return;
104 SkArenaAlloc* allocator = fContour->globalState()->allocator();
105 SkPoint* ptStorage = allocator->makeArrayDefault<SkPoint>(2);
106 memcpy(ptStorage, fLastLine, sizeof(fLastLine));
107 (void) fContour->addLine(ptStorage);
108 fLastIsLine = false;
109 }
110