
/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkPictureStateTree.h"
#include "SkCanvas.h"

SK_DEFINE_INST_COUNT(SkPictureStateTree)

SkPictureStateTree::SkPictureStateTree()
    : fAlloc(2048)
    , fRoot(NULL)
    , fStateStack(sizeof(Draw), 16) {
    SkMatrix* identity = static_cast<SkMatrix*>(fAlloc.allocThrow(sizeof(SkMatrix)));
    identity->reset();
    fRoot = static_cast<Node*>(fAlloc.allocThrow(sizeof(Node)));
    fRoot->fParent = NULL;
    fRoot->fMatrix = identity;
    fRoot->fFlags = Node::kSave_Flag;
    fRoot->fOffset = 0;
    fRoot->fLevel = 0;
    fCurrentState.fNode = fRoot;
    fCurrentState.fMatrix = identity;
    *static_cast<Draw*>(fStateStack.push_back()) = fCurrentState;
}

SkPictureStateTree::~SkPictureStateTree() {
}

SkPictureStateTree::Draw* SkPictureStateTree::appendDraw(uint32_t offset) {
    Draw* draw = static_cast<Draw*>(fAlloc.allocThrow(sizeof(Draw)));
    *draw = fCurrentState;
    draw->fOffset = offset;
    return draw;
}

void SkPictureStateTree::appendSave() {
    *static_cast<Draw*>(fStateStack.push_back()) = fCurrentState;
    fCurrentState.fNode->fFlags |= Node::kSave_Flag;
}

void SkPictureStateTree::appendSaveLayer(uint32_t offset) {
    *static_cast<Draw*>(fStateStack.push_back()) = fCurrentState;
    this->appendNode(offset);
    fCurrentState.fNode->fFlags |= Node::kSaveLayer_Flag;
}

void SkPictureStateTree::appendRestore() {
    fCurrentState = *static_cast<Draw*>(fStateStack.back());
    fStateStack.pop_back();
}

void SkPictureStateTree::appendTransform(const SkMatrix& trans) {
    SkMatrix* m = static_cast<SkMatrix*>(fAlloc.allocThrow(sizeof(SkMatrix)));
    *m = trans;
    fCurrentState.fMatrix = m;
}

void SkPictureStateTree::appendClip(uint32_t offset) {
    this->appendNode(offset);
}

SkPictureStateTree::Iterator SkPictureStateTree::getIterator(const SkTDArray<void*>& draws,
                                                             SkCanvas* canvas) {
    return Iterator(draws, canvas, fRoot);
}

void SkPictureStateTree::appendNode(uint32_t offset) {
    Node* n = static_cast<Node*>(fAlloc.allocThrow(sizeof(Node)));
    n->fOffset = offset;
    n->fFlags = 0;
    n->fParent = fCurrentState.fNode;
    n->fLevel = fCurrentState.fNode->fLevel + 1;
    n->fMatrix = fCurrentState.fMatrix;
    fCurrentState.fNode = n;
}

SkPictureStateTree::Iterator::Iterator(const SkTDArray<void*>& draws, SkCanvas* canvas, Node* root)
    : fDraws(&draws)
    , fCanvas(canvas)
    , fCurrentNode(root)
    , fPlaybackMatrix(canvas->getTotalMatrix())
    , fCurrentMatrix(NULL)
    , fPlaybackIndex(0)
    , fSave(false)
    , fValid(true) {
}

uint32_t SkPictureStateTree::Iterator::draw() {
    SkASSERT(this->isValid());
    if (fPlaybackIndex >= fDraws->count()) {
        // restore back to where we started
        if (fCurrentNode->fFlags & Node::kSaveLayer_Flag) { fCanvas->restore(); }
        fCurrentNode = fCurrentNode->fParent;
        while (NULL != fCurrentNode) {
            if (fCurrentNode->fFlags & Node::kSave_Flag) { fCanvas->restore(); }
            if (fCurrentNode->fFlags & Node::kSaveLayer_Flag) { fCanvas->restore(); }
            fCurrentNode = fCurrentNode->fParent;
        }
        fCanvas->setMatrix(fPlaybackMatrix);
        return kDrawComplete;
    }

    Draw* draw = static_cast<Draw*>((*fDraws)[fPlaybackIndex]);
    Node* targetNode = draw->fNode;

    if (fSave) {
        fCanvas->save(SkCanvas::kClip_SaveFlag);
        fSave = false;
    }

    if (fCurrentNode != targetNode) {
        // If we're not at the target and we don't have a list of nodes to get there, we need to
        // figure out the path from our current node, to the target
        if (fNodes.count() == 0) {
            // Trace back up to a common ancestor, restoring to get our current state to match that
            // of the ancestor, and saving a list of nodes whose state we need to apply to get to
            // the target (we can restore up to the ancestor immediately, but we'll need to return
            // an offset for each node on the way down to the target, to apply the desired clips and
            // saveLayers, so it may take several draw() calls before the next draw actually occurs)
            Node* tmp = fCurrentNode;
            Node* ancestor = targetNode;
            while (tmp != ancestor) {
                uint16_t currentLevel = tmp->fLevel;
                uint16_t targetLevel = ancestor->fLevel;
                if (currentLevel >= targetLevel) {
                    if (tmp != fCurrentNode && tmp->fFlags & Node::kSave_Flag) { fCanvas->restore(); }
                    if (tmp->fFlags & Node::kSaveLayer_Flag) { fCanvas->restore(); }
                    tmp = tmp->fParent;
                }
                if (currentLevel <= targetLevel) {
                    fNodes.push(ancestor);
                    ancestor = ancestor->fParent;
                }
            }

            if (ancestor->fFlags & Node::kSave_Flag) {
                if (fCurrentNode != ancestor) { fCanvas->restore(); }
                if (targetNode != ancestor) { fCanvas->save(SkCanvas::kClip_SaveFlag); }
            }
            fCurrentNode = ancestor;
        }

        // If we're not at the target node yet, we'll need to return an offset to make the caller
        // apply the next clip or saveLayer.
        if (fCurrentNode != targetNode) {
            if (fCurrentMatrix != fNodes.top()->fMatrix) {
                fCurrentMatrix = fNodes.top()->fMatrix;
                SkMatrix tmp = *fNodes.top()->fMatrix;
                tmp.postConcat(fPlaybackMatrix);
                fCanvas->setMatrix(tmp);
            }
            uint32_t offset = fNodes.top()->fOffset;
            fCurrentNode = fNodes.top();
            fSave = fCurrentNode != targetNode && fCurrentNode->fFlags & Node::kSave_Flag;
            fNodes.pop();
            return offset;
        }
    }

    // If we got this far, the clip/saveLayer state is all set, so we can proceed to set the matrix
    // for the draw, and return its offset.

    if (fCurrentMatrix != draw->fMatrix) {
        SkMatrix tmp = *draw->fMatrix;
        tmp.postConcat(fPlaybackMatrix);
        fCanvas->setMatrix(tmp);
        fCurrentMatrix = draw->fMatrix;
    }

    ++fPlaybackIndex;
    return draw->fOffset;
}
