/*
* 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 "SkOpContour.h"
#include "SkPathWriter.h"
#include "SkReduceOrder.h"
#include "SkTSort.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;
    bool allDone = true;
    do {
        if (testSegment->done()) {
            continue;
        }
        allDone = false;
        return testSegment->undoneSpan();
    } while ((testSegment = testSegment->next()));
    if (allDone) {
      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<SkPoint>(3);
            memcpy(ptStorage, pts, sizeof(SkPoint) * 3);
            this->addQuad(ptStorage);
        } break;
        case SkPath::kConic_Verb: {
            SkPoint* ptStorage = allocator->makeArrayDefault<SkPoint>(3);
            memcpy(ptStorage, pts, sizeof(SkPoint) * 3);
            this->addConic(ptStorage, weight);
        } break;
        case SkPath::kCubic_Verb: {
            SkPoint* ptStorage = allocator->makeArrayDefault<SkPoint>(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<SkPoint>(2);
    memcpy(ptStorage, fLastLine, sizeof(fLastLine));
    (void) fContour->addLine(ptStorage);
    fLastIsLine = false;
}
