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