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 12void 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 24void 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 33SkOpSpan* 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 45void SkOpContourBuilder::addConic(SkPoint pts[3], SkScalar weight) { 46 this->flush(); 47 fContour->addConic(pts, weight); 48} 49 50void SkOpContourBuilder::addCubic(SkPoint pts[4]) { 51 this->flush(); 52 fContour->addCubic(pts); 53} 54 55void 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 82void 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 96void SkOpContourBuilder::addQuad(SkPoint pts[3]) { 97 this->flush(); 98 fContour->addQuad(pts); 99} 100 101void 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