xref: /aosp_15_r20/external/skia/src/pathops/SkOpContour.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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