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 "SkOpContour.h"
8 #include "SkPathWriter.h"
9 #include "SkReduceOrder.h"
10 #include "SkTSort.h"
11 
12 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 
24 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 
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 
45 void SkOpContourBuilder::addConic(SkPoint pts[3], SkScalar weight) {
46     this->flush();
47     fContour->addConic(pts, weight);
48 }
49 
50 void SkOpContourBuilder::addCubic(SkPoint pts[4]) {
51     this->flush();
52     fContour->addCubic(pts);
53 }
54 
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 
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 
96 void SkOpContourBuilder::addQuad(SkPoint pts[3]) {
97     this->flush();
98     fContour->addQuad(pts);
99 }
100 
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