/*
 * 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 "GrAndroidPathRenderer.h"
#include "AndroidPathRenderer.h"
#include "Vertex.h"

GrAndroidPathRenderer::GrAndroidPathRenderer() {
}

bool GrAndroidPathRenderer::canDrawPath(const SkPath& path,
                                        const SkStrokeRec& stroke,
                                        const GrDrawTarget* target,
                                        bool antiAlias) const {
    return ((stroke.isFillStyle() || stroke.getStyle() == SkStrokeRec::kStroke_Style)
             && !path.isInverseFillType() && path.isConvex());
}

struct ColorVertex {
    SkPoint pos;
    GrColor color;
};

bool GrAndroidPathRenderer::onDrawPath(const SkPath& origPath,
                                       const SkStrokeRec& stroke,
                                       GrDrawTarget* target,
                                       bool antiAlias) {

    // generate verts using Android algorithm
    android::uirenderer::VertexBuffer vertices;
    android::uirenderer::PathRenderer::ConvexPathVertices(origPath, stroke, antiAlias, NULL,
                                                          &vertices);

    // set vertex attributes depending on anti-alias
    GrDrawState* drawState = target->drawState();
    if (antiAlias) {
        // position + coverage
        GrVertexAttrib attribs[] = {
            GrVertexAttrib(kVec2f_GrVertexAttribType, 0),
            GrVertexAttrib(kVec4ub_GrVertexAttribType, sizeof(GrPoint))
        };
        drawState->setVertexAttribs(attribs, SK_ARRAY_COUNT(attribs));
        drawState->setAttribIndex(GrDrawState::kPosition_AttribIndex, 0);
        drawState->setAttribIndex(GrDrawState::kCoverage_AttribIndex, 1);
        drawState->setAttribBindings(GrDrawState::kCoverage_AttribBindingsBit);
    } else {
        drawState->setDefaultVertexAttribs();
    }

    // allocate our vert buffer
    int vertCount = vertices.getSize();
    GrDrawTarget::AutoReleaseGeometry geo(target, vertCount, 0);
    if (!geo.succeeded()) {
        GrPrintf("Failed to get space for vertices!\n");
        return false;
    }

    // copy android verts to our vertex buffer
    if (antiAlias) {
        SkASSERT(sizeof(ColorVertex) == drawState->getVertexSize());
        ColorVertex* outVert = reinterpret_cast<ColorVertex*>(geo.vertices());
        android::uirenderer::AlphaVertex* inVert =
            reinterpret_cast<android::uirenderer::AlphaVertex*>(vertices.getBuffer());

        for (int i = 0; i < vertCount; ++i) {
            // copy vertex position
            outVert->pos.set(inVert->position[0], inVert->position[1]);
            // copy alpha
            int coverage = static_cast<int>(inVert->alpha * 0xff);
            outVert->color = GrColorPackRGBA(coverage, coverage, coverage, coverage);
            ++outVert;
            ++inVert;
        }
    } else {
       size_t vsize = drawState->getVertexSize();
       size_t copySize = vsize*vertCount;
       memcpy(geo.vertices(), vertices.getBuffer(), copySize);
    }

    // render it
    target->drawNonIndexed(kTriangleStrip_GrPrimitiveType, 0, vertCount);

    return true;
}