/* * Copyright 2013 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "src/core/SkTSort.h" #include "src/pathops/SkOpContour.h" #include "src/pathops/SkPathWriter.h" #include "src/pathops/SkReduceOrder.h" void SkOpContour::toPath(SkPathWriter* path) const { if (!this->count()) { return; } const SkOpSegment* segment = &fHead; do { SkAssertResult(segment->addCurveTo(segment->head(), segment->tail(), path)); } while ((segment = segment->next())); path->finishContour(); path->assemble(); } void SkOpContour::toReversePath(SkPathWriter* path) const { const SkOpSegment* segment = fTail; do { SkAssertResult(segment->addCurveTo(segment->tail(), segment->head(), path)); } while ((segment = segment->prev())); path->finishContour(); path->assemble(); } SkOpSpan* SkOpContour::undoneSpan() { SkOpSegment* testSegment = &fHead; do { if (testSegment->done()) { continue; } return testSegment->undoneSpan(); } while ((testSegment = testSegment->next())); fDone = true; return nullptr; } void SkOpContourBuilder::addConic(SkPoint pts[3], SkScalar weight) { this->flush(); fContour->addConic(pts, weight); } void SkOpContourBuilder::addCubic(SkPoint pts[4]) { this->flush(); fContour->addCubic(pts); } void SkOpContourBuilder::addCurve(SkPath::Verb verb, const SkPoint pts[4], SkScalar weight) { if (SkPath::kLine_Verb == verb) { this->addLine(pts); return; } SkArenaAlloc* allocator = fContour->globalState()->allocator(); switch (verb) { case SkPath::kQuad_Verb: { SkPoint* ptStorage = allocator->makeArrayDefault(3); memcpy(ptStorage, pts, sizeof(SkPoint) * 3); this->addQuad(ptStorage); } break; case SkPath::kConic_Verb: { SkPoint* ptStorage = allocator->makeArrayDefault(3); memcpy(ptStorage, pts, sizeof(SkPoint) * 3); this->addConic(ptStorage, weight); } break; case SkPath::kCubic_Verb: { SkPoint* ptStorage = allocator->makeArrayDefault(4); memcpy(ptStorage, pts, sizeof(SkPoint) * 4); this->addCubic(ptStorage); } break; default: SkASSERT(0); } } void SkOpContourBuilder::addLine(const SkPoint pts[2]) { // if the previous line added is the exact opposite, eliminate both if (fLastIsLine) { if (fLastLine[0] == pts[1] && fLastLine[1] == pts[0]) { fLastIsLine = false; return; } else { flush(); } } memcpy(fLastLine, pts, sizeof(fLastLine)); fLastIsLine = true; } void SkOpContourBuilder::addQuad(SkPoint pts[3]) { this->flush(); fContour->addQuad(pts); } void SkOpContourBuilder::flush() { if (!fLastIsLine) return; SkArenaAlloc* allocator = fContour->globalState()->allocator(); SkPoint* ptStorage = allocator->makeArrayDefault(2); memcpy(ptStorage, fLastLine, sizeof(fLastLine)); (void) fContour->addLine(ptStorage); fLastIsLine = false; }