blob: ab1a37b09a95f68716a76eec5a81d9d0391c9827 [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"
caryclark54359292015-03-26 07:52:43 -07008#include "SkOpTAllocator.h"
caryclark@google.com07393ca2013-04-08 11:47:37 +00009#include "SkPathWriter.h"
caryclark54359292015-03-26 07:52:43 -070010#include "SkReduceOrder.h"
commit-bot@chromium.orgb76d3b62013-04-22 19:55:19 +000011#include "SkTSort.h"
caryclark@google.com07393ca2013-04-08 11:47:37 +000012
caryclark54359292015-03-26 07:52:43 -070013void SkOpContour::addCurve(SkPath::Verb verb, const SkPoint pts[4], SkChunkAlloc* allocator) {
14 switch (verb) {
15 case SkPath::kLine_Verb: {
16 SkPoint* ptStorage = SkOpTAllocator<SkPoint>::AllocateArray(allocator, 2);
17 memcpy(ptStorage, pts, sizeof(SkPoint) * 2);
18 appendSegment(allocator).addLine(ptStorage, this);
19 } break;
20 case SkPath::kQuad_Verb: {
21 SkPoint* ptStorage = SkOpTAllocator<SkPoint>::AllocateArray(allocator, 3);
22 memcpy(ptStorage, pts, sizeof(SkPoint) * 3);
23 appendSegment(allocator).addQuad(ptStorage, this);
24 } break;
caryclark1049f122015-04-20 08:31:59 -070025 case SkPath::kConic_Verb: {
26 SkASSERT(0); // the original curve is a cubic, which will never reduce to a conic
27 } break;
caryclark54359292015-03-26 07:52:43 -070028 case SkPath::kCubic_Verb: {
29 SkPoint* ptStorage = SkOpTAllocator<SkPoint>::AllocateArray(allocator, 4);
30 memcpy(ptStorage, pts, sizeof(SkPoint) * 4);
31 appendSegment(allocator).addCubic(ptStorage, this);
32 } break;
33 default:
34 SkASSERT(0);
caryclark@google.com7eaa53d2013-10-02 14:49:34 +000035 }
caryclark@google.com07393ca2013-04-08 11:47:37 +000036}
37
caryclark54359292015-03-26 07:52:43 -070038SkOpSegment* SkOpContour::nonVerticalSegment(SkOpSpanBase** start, SkOpSpanBase** end) {
caryclark@google.com07393ca2013-04-08 11:47:37 +000039 int segmentCount = fSortedSegments.count();
40 SkASSERT(segmentCount > 0);
41 for (int sortedIndex = fFirstSorted; sortedIndex < segmentCount; ++sortedIndex) {
42 SkOpSegment* testSegment = fSortedSegments[sortedIndex];
43 if (testSegment->done()) {
44 continue;
45 }
caryclark54359292015-03-26 07:52:43 -070046 SkOpSpanBase* span = testSegment->head();
47 SkOpSpanBase* testS, * testE;
48 while (SkOpSegment::NextCandidate(span, &testS, &testE)) {
49 if (!testSegment->isVertical(testS, testE)) {
50 *start = testS;
51 *end = testE;
caryclark@google.com07393ca2013-04-08 11:47:37 +000052 return testSegment;
53 }
caryclark54359292015-03-26 07:52:43 -070054 span = span->upCast()->next();
caryclark@google.com07393ca2013-04-08 11:47:37 +000055 }
56 }
57 return NULL;
58}
59
caryclark@google.com07393ca2013-04-08 11:47:37 +000060void SkOpContour::toPath(SkPathWriter* path) const {
caryclark54359292015-03-26 07:52:43 -070061 const SkPoint& pt = fHead.pts()[0];
caryclark@google.com07393ca2013-04-08 11:47:37 +000062 path->deferredMove(pt);
caryclark54359292015-03-26 07:52:43 -070063 const SkOpSegment* segment = &fHead;
64 do {
65 segment->addCurveTo(segment->head(), segment->tail(), path, true);
66 } while ((segment = segment->next()));
caryclark@google.com07393ca2013-04-08 11:47:37 +000067 path->close();
68}
69
70void SkOpContour::topSortableSegment(const SkPoint& topLeft, SkPoint* bestXY,
71 SkOpSegment** topStart) {
72 int segmentCount = fSortedSegments.count();
73 SkASSERT(segmentCount > 0);
74 int sortedIndex = fFirstSorted;
75 fDone = true; // may be cleared below
76 for ( ; sortedIndex < segmentCount; ++sortedIndex) {
77 SkOpSegment* testSegment = fSortedSegments[sortedIndex];
78 if (testSegment->done()) {
79 if (sortedIndex == fFirstSorted) {
80 ++fFirstSorted;
81 }
82 continue;
83 }
84 fDone = false;
commit-bot@chromium.org8cb1daa2014-04-25 12:59:11 +000085 SkPoint testXY = testSegment->activeLeftTop(NULL);
caryclark@google.com07393ca2013-04-08 11:47:37 +000086 if (*topStart) {
87 if (testXY.fY < topLeft.fY) {
88 continue;
89 }
90 if (testXY.fY == topLeft.fY && testXY.fX < topLeft.fX) {
91 continue;
92 }
93 if (bestXY->fY < testXY.fY) {
94 continue;
95 }
96 if (bestXY->fY == testXY.fY && bestXY->fX < testXY.fX) {
97 continue;
98 }
99 }
100 *topStart = testSegment;
101 *bestXY = testXY;
102 }
103}
104
caryclark54359292015-03-26 07:52:43 -0700105SkOpSegment* SkOpContour::undoneSegment(SkOpSpanBase** startPtr, SkOpSpanBase** endPtr) {
106 SkOpSegment* segment = &fHead;
107 do {
108 if (segment->done()) {
caryclark@google.com07393ca2013-04-08 11:47:37 +0000109 continue;
110 }
caryclark54359292015-03-26 07:52:43 -0700111 segment->undoneSpan(startPtr, endPtr);
112 return segment;
113 } while ((segment = segment->next()));
caryclark@google.com07393ca2013-04-08 11:47:37 +0000114 return NULL;
115}