1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci* Copyright 2013 Google Inc. 3cb93a386Sopenharmony_ci* 4cb93a386Sopenharmony_ci* Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci* found in the LICENSE file. 6cb93a386Sopenharmony_ci*/ 7cb93a386Sopenharmony_ci#include "src/pathops/SkOpContour.h" 8cb93a386Sopenharmony_ci#include "src/pathops/SkPathWriter.h" 9cb93a386Sopenharmony_ci#include "src/pathops/SkReduceOrder.h" 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_civoid SkOpContour::toPath(SkPathWriter* path) const { 12cb93a386Sopenharmony_ci if (!this->count()) { 13cb93a386Sopenharmony_ci return; 14cb93a386Sopenharmony_ci } 15cb93a386Sopenharmony_ci const SkOpSegment* segment = &fHead; 16cb93a386Sopenharmony_ci do { 17cb93a386Sopenharmony_ci SkAssertResult(segment->addCurveTo(segment->head(), segment->tail(), path)); 18cb93a386Sopenharmony_ci } while ((segment = segment->next())); 19cb93a386Sopenharmony_ci path->finishContour(); 20cb93a386Sopenharmony_ci path->assemble(); 21cb93a386Sopenharmony_ci} 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_civoid SkOpContour::toReversePath(SkPathWriter* path) const { 24cb93a386Sopenharmony_ci const SkOpSegment* segment = fTail; 25cb93a386Sopenharmony_ci do { 26cb93a386Sopenharmony_ci SkAssertResult(segment->addCurveTo(segment->tail(), segment->head(), path)); 27cb93a386Sopenharmony_ci } while ((segment = segment->prev())); 28cb93a386Sopenharmony_ci path->finishContour(); 29cb93a386Sopenharmony_ci path->assemble(); 30cb93a386Sopenharmony_ci} 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_ciSkOpSpan* SkOpContour::undoneSpan() { 33cb93a386Sopenharmony_ci SkOpSegment* testSegment = &fHead; 34cb93a386Sopenharmony_ci do { 35cb93a386Sopenharmony_ci if (testSegment->done()) { 36cb93a386Sopenharmony_ci continue; 37cb93a386Sopenharmony_ci } 38cb93a386Sopenharmony_ci return testSegment->undoneSpan(); 39cb93a386Sopenharmony_ci } while ((testSegment = testSegment->next())); 40cb93a386Sopenharmony_ci fDone = true; 41cb93a386Sopenharmony_ci return nullptr; 42cb93a386Sopenharmony_ci} 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_civoid SkOpContourBuilder::addConic(SkPoint pts[3], SkScalar weight) { 45cb93a386Sopenharmony_ci this->flush(); 46cb93a386Sopenharmony_ci fContour->addConic(pts, weight); 47cb93a386Sopenharmony_ci} 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_civoid SkOpContourBuilder::addCubic(SkPoint pts[4]) { 50cb93a386Sopenharmony_ci this->flush(); 51cb93a386Sopenharmony_ci fContour->addCubic(pts); 52cb93a386Sopenharmony_ci} 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_civoid SkOpContourBuilder::addCurve(SkPath::Verb verb, const SkPoint pts[4], SkScalar weight) { 55cb93a386Sopenharmony_ci if (SkPath::kLine_Verb == verb) { 56cb93a386Sopenharmony_ci this->addLine(pts); 57cb93a386Sopenharmony_ci return; 58cb93a386Sopenharmony_ci } 59cb93a386Sopenharmony_ci SkArenaAlloc* allocator = fContour->globalState()->allocator(); 60cb93a386Sopenharmony_ci switch (verb) { 61cb93a386Sopenharmony_ci case SkPath::kQuad_Verb: { 62cb93a386Sopenharmony_ci SkPoint* ptStorage = allocator->makeArrayDefault<SkPoint>(3); 63cb93a386Sopenharmony_ci memcpy(ptStorage, pts, sizeof(SkPoint) * 3); 64cb93a386Sopenharmony_ci this->addQuad(ptStorage); 65cb93a386Sopenharmony_ci } break; 66cb93a386Sopenharmony_ci case SkPath::kConic_Verb: { 67cb93a386Sopenharmony_ci SkPoint* ptStorage = allocator->makeArrayDefault<SkPoint>(3); 68cb93a386Sopenharmony_ci memcpy(ptStorage, pts, sizeof(SkPoint) * 3); 69cb93a386Sopenharmony_ci this->addConic(ptStorage, weight); 70cb93a386Sopenharmony_ci } break; 71cb93a386Sopenharmony_ci case SkPath::kCubic_Verb: { 72cb93a386Sopenharmony_ci SkPoint* ptStorage = allocator->makeArrayDefault<SkPoint>(4); 73cb93a386Sopenharmony_ci memcpy(ptStorage, pts, sizeof(SkPoint) * 4); 74cb93a386Sopenharmony_ci this->addCubic(ptStorage); 75cb93a386Sopenharmony_ci } break; 76cb93a386Sopenharmony_ci default: 77cb93a386Sopenharmony_ci SkASSERT(0); 78cb93a386Sopenharmony_ci } 79cb93a386Sopenharmony_ci} 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_civoid SkOpContourBuilder::addLine(const SkPoint pts[2]) { 82cb93a386Sopenharmony_ci // if the previous line added is the exact opposite, eliminate both 83cb93a386Sopenharmony_ci if (fLastIsLine) { 84cb93a386Sopenharmony_ci if (fLastLine[0] == pts[1] && fLastLine[1] == pts[0]) { 85cb93a386Sopenharmony_ci fLastIsLine = false; 86cb93a386Sopenharmony_ci return; 87cb93a386Sopenharmony_ci } else { 88cb93a386Sopenharmony_ci flush(); 89cb93a386Sopenharmony_ci } 90cb93a386Sopenharmony_ci } 91cb93a386Sopenharmony_ci memcpy(fLastLine, pts, sizeof(fLastLine)); 92cb93a386Sopenharmony_ci fLastIsLine = true; 93cb93a386Sopenharmony_ci} 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_civoid SkOpContourBuilder::addQuad(SkPoint pts[3]) { 96cb93a386Sopenharmony_ci this->flush(); 97cb93a386Sopenharmony_ci fContour->addQuad(pts); 98cb93a386Sopenharmony_ci} 99cb93a386Sopenharmony_ci 100cb93a386Sopenharmony_civoid SkOpContourBuilder::flush() { 101cb93a386Sopenharmony_ci if (!fLastIsLine) 102cb93a386Sopenharmony_ci return; 103cb93a386Sopenharmony_ci SkArenaAlloc* allocator = fContour->globalState()->allocator(); 104cb93a386Sopenharmony_ci SkPoint* ptStorage = allocator->makeArrayDefault<SkPoint>(2); 105cb93a386Sopenharmony_ci memcpy(ptStorage, fLastLine, sizeof(fLastLine)); 106cb93a386Sopenharmony_ci (void) fContour->addLine(ptStorage); 107cb93a386Sopenharmony_ci fLastIsLine = false; 108cb93a386Sopenharmony_ci} 109