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