blob: f5799474ec50b6197b02a6e9b2378582b7afba6d [file] [log] [blame]
caryclark@google.com07393ca2013-04-08 11:47:37 +00001/*
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*/
caryclark@google.com07393ca2013-04-08 11:47:37 +00007#include "SkOpContour.h"
8#include "SkPathWriter.h"
caryclark54359292015-03-26 07:52:43 -07009#include "SkReduceOrder.h"
commit-bot@chromium.orgb76d3b62013-04-22 19:55:19 +000010#include "SkTSort.h"
caryclark@google.com07393ca2013-04-08 11:47:37 +000011
caryclark@google.com07393ca2013-04-08 11:47:37 +000012void SkOpContour::toPath(SkPathWriter* path) const {
Cary Clark0eb6ed42016-12-16 16:31:11 -050013 if (!this->count()) {
14 return;
15 }
caryclark54359292015-03-26 07:52:43 -070016 const SkOpSegment* segment = &fHead;
17 do {
caryclarkef784fb2015-10-30 12:03:06 -070018 SkAssertResult(segment->addCurveTo(segment->head(), segment->tail(), path));
caryclark54359292015-03-26 07:52:43 -070019 } while ((segment = segment->next()));
caryclarkeed356d2016-09-14 07:18:20 -070020 path->finishContour();
21 path->assemble();
caryclark@google.com07393ca2013-04-08 11:47:37 +000022}
23
caryclark5b5ddd72015-05-18 05:12:56 -070024void SkOpContour::toReversePath(SkPathWriter* path) const {
caryclark5b5ddd72015-05-18 05:12:56 -070025 const SkOpSegment* segment = fTail;
26 do {
caryclarkef784fb2015-10-30 12:03:06 -070027 SkAssertResult(segment->addCurveTo(segment->tail(), segment->head(), path));
caryclark5b5ddd72015-05-18 05:12:56 -070028 } while ((segment = segment->prev()));
caryclarkeed356d2016-09-14 07:18:20 -070029 path->finishContour();
30 path->assemble();
caryclark5b5ddd72015-05-18 05:12:56 -070031}
32
Cary Clarkab2d73b2016-12-16 17:17:25 -050033SkOpSpan* SkOpContour::undoneSpan() {
34 SkOpSegment* testSegment = &fHead;
35 bool allDone = true;
caryclark54359292015-03-26 07:52:43 -070036 do {
Cary Clarkab2d73b2016-12-16 17:17:25 -050037 if (testSegment->done()) {
caryclark@google.com07393ca2013-04-08 11:47:37 +000038 continue;
39 }
Cary Clarkab2d73b2016-12-16 17:17:25 -050040 allDone = false;
41 return testSegment->undoneSpan();
42 } while ((testSegment = testSegment->next()));
43 if (allDone) {
44 fDone = true;
45 }
halcanary96fcdcc2015-08-27 07:41:13 -070046 return nullptr;
caryclark@google.com07393ca2013-04-08 11:47:37 +000047}
Cary Clarkff114282016-12-14 11:56:16 -050048
49void SkOpContourBuilder::addConic(SkPoint pts[3], SkScalar weight) {
50 this->flush();
51 fContour->addConic(pts, weight);
52}
53
54void SkOpContourBuilder::addCubic(SkPoint pts[4]) {
55 this->flush();
56 fContour->addCubic(pts);
57}
58
59void SkOpContourBuilder::addCurve(SkPath::Verb verb, const SkPoint pts[4], SkScalar weight) {
60 if (SkPath::kLine_Verb == verb) {
61 this->addLine(pts);
62 return;
63 }
Herb Derbyc3cc5fa2017-03-07 11:11:47 -050064 SkArenaAlloc* allocator = fContour->globalState()->allocator();
Cary Clarkff114282016-12-14 11:56:16 -050065 switch (verb) {
66 case SkPath::kQuad_Verb: {
Herb Derbyecc364c2017-04-19 15:09:48 -040067 SkPoint* ptStorage = allocator->makeArrayDefault<SkPoint>(3);
Cary Clarkff114282016-12-14 11:56:16 -050068 memcpy(ptStorage, pts, sizeof(SkPoint) * 3);
69 this->addQuad(ptStorage);
70 } break;
71 case SkPath::kConic_Verb: {
Herb Derbyecc364c2017-04-19 15:09:48 -040072 SkPoint* ptStorage = allocator->makeArrayDefault<SkPoint>(3);
Cary Clarkff114282016-12-14 11:56:16 -050073 memcpy(ptStorage, pts, sizeof(SkPoint) * 3);
74 this->addConic(ptStorage, weight);
75 } break;
76 case SkPath::kCubic_Verb: {
Herb Derbyecc364c2017-04-19 15:09:48 -040077 SkPoint* ptStorage = allocator->makeArrayDefault<SkPoint>(4);
Cary Clarkff114282016-12-14 11:56:16 -050078 memcpy(ptStorage, pts, sizeof(SkPoint) * 4);
79 this->addCubic(ptStorage);
80 } break;
81 default:
82 SkASSERT(0);
83 }
84}
85
86void SkOpContourBuilder::addLine(const SkPoint pts[2]) {
87 // if the previous line added is the exact opposite, eliminate both
88 if (fLastIsLine) {
89 if (fLastLine[0] == pts[1] && fLastLine[1] == pts[0]) {
90 fLastIsLine = false;
91 return;
92 } else {
93 flush();
94 }
95 }
96 memcpy(fLastLine, pts, sizeof(fLastLine));
97 fLastIsLine = true;
98}
99
100void SkOpContourBuilder::addQuad(SkPoint pts[3]) {
101 this->flush();
102 fContour->addQuad(pts);
103}
104
105void SkOpContourBuilder::flush() {
106 if (!fLastIsLine)
107 return;
Herb Derbyc3cc5fa2017-03-07 11:11:47 -0500108 SkArenaAlloc* allocator = fContour->globalState()->allocator();
Herb Derbyecc364c2017-04-19 15:09:48 -0400109 SkPoint* ptStorage = allocator->makeArrayDefault<SkPoint>(2);
Cary Clarkff114282016-12-14 11:56:16 -0500110 memcpy(ptStorage, fLastLine, sizeof(fLastLine));
111 (void) fContour->addLine(ptStorage);
112 fLastIsLine = false;
113}