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