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