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