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

#include "SkPatchGrid.h"
#include "SkPatchUtils.h"

SkPatchGrid::SkPatchGrid(int rows, int cols, VertexType flags, SkXfermode* xfer)
    : fRows(0)
    , fCols(0)
    , fModeFlags(kNone_VertexType)
    , fCornerPts(NULL)
    , fCornerColors(NULL)
    , fTexCoords(NULL)
    , fHrzCtrlPts(NULL)
    , fVrtCtrlPts(NULL)
    , fXferMode(NULL) {
        this->reset(rows, cols, flags, xfer);
}

SkPatchGrid::~SkPatchGrid() {
    SkDELETE_ARRAY(fCornerPts);
    SkDELETE_ARRAY(fCornerColors);
    SkDELETE_ARRAY(fTexCoords);
    SkDELETE_ARRAY(fHrzCtrlPts);
    SkDELETE_ARRAY(fVrtCtrlPts);
}

bool SkPatchGrid::setPatch(int x, int y, const SkPoint cubics[12], const SkColor colors[4],
                           const SkPoint texCoords[4]) {
    // Check for the passed paramaters to be within the range of the grid dimensions and a valid
    // pointer for the cubics' control points.
    if (x < 0 || y < 0 || x > fCols - 1 || y > fRows - 1 || NULL == cubics) {
        return false;
    }
    
    // setup corners and colors
    int cornerPos = y * (fCols + 1) + x;
    fCornerPts[cornerPos] = cubics[SkPatchUtils::kTopP0_CubicCtrlPts];
    fCornerPts[cornerPos + 1] = cubics[SkPatchUtils::kTopP3_CubicCtrlPts];
    fCornerPts[cornerPos + (fCols + 1)] = cubics[SkPatchUtils::kBottomP0_CubicCtrlPts];
    fCornerPts[cornerPos + (fCols + 1) + 1] = cubics[SkPatchUtils::kBottomP3_CubicCtrlPts];
    
    // set horizontal control points
    int hrzPos = y * (fCols * 2) + (x * 2);
    fHrzCtrlPts[hrzPos] = cubics[SkPatchUtils::kTopP1_CubicCtrlPts];
    fHrzCtrlPts[hrzPos + 1] = cubics[SkPatchUtils::kTopP2_CubicCtrlPts];
    fHrzCtrlPts[hrzPos + (fCols * 2)] = cubics[SkPatchUtils::kBottomP1_CubicCtrlPts];
    fHrzCtrlPts[hrzPos + (fCols * 2) + 1] = cubics[SkPatchUtils::kBottomP2_CubicCtrlPts];
    
    // set vertical control points
    int vrtPos = (y*2) * (fCols + 1) + x;
    fVrtCtrlPts[vrtPos] = cubics[SkPatchUtils::kLeftP1_CubicCtrlPts];
    fVrtCtrlPts[vrtPos + 1] = cubics[SkPatchUtils::kRightP1_CubicCtrlPts];
    fVrtCtrlPts[vrtPos + (fCols + 1)] = cubics[SkPatchUtils::kLeftP2_CubicCtrlPts];
    fVrtCtrlPts[vrtPos + (fCols + 1) + 1] = cubics[SkPatchUtils::kRightP2_CubicCtrlPts];
    
    // set optional values (colors and texture coordinates)
    if ((fModeFlags & kColors_VertexType)  && colors) {
        fCornerColors[cornerPos] = colors[0];
        fCornerColors[cornerPos + 1] = colors[1];
        fCornerColors[cornerPos + (fCols + 1)] = colors[3];
        fCornerColors[cornerPos + (fCols + 1) + 1] = colors[2];
    }
    
    if ((fModeFlags & kTexs_VertexType) && texCoords) {
        fTexCoords[cornerPos] = texCoords[0];
        fTexCoords[cornerPos + 1] = texCoords[1];
        fTexCoords[cornerPos + (fCols + 1)] = texCoords[3];
        fTexCoords[cornerPos + (fCols + 1) + 1] = texCoords[2];
    }
    
    return true;
}

bool SkPatchGrid::getPatch(int x, int y, SkPoint cubics[12], SkColor colors[4],
                           SkPoint texCoords[4]) const {
    
    if (x < 0 || y < 0 || x > fCols - 1 || y > fRows - 1 || NULL == cubics) {
        return false;
    }
    
    // set the patch by building the array of points and colors with the corresponding values.
    int cornerPos = y * (fCols + 1) + x;
    cubics[SkPatchUtils::kTopP0_CubicCtrlPts] = fCornerPts[cornerPos];
    cubics[SkPatchUtils::kTopP3_CubicCtrlPts] = fCornerPts[cornerPos + 1];
    cubics[SkPatchUtils::kBottomP0_CubicCtrlPts] = fCornerPts[cornerPos + (fCols + 1)];
    cubics[SkPatchUtils::kBottomP3_CubicCtrlPts] = fCornerPts[cornerPos + (fCols + 1) + 1];
    
    int hrzPos = y * (fCols * 2) + (x * 2);
    cubics[SkPatchUtils::kTopP1_CubicCtrlPts] = fHrzCtrlPts[hrzPos];
    cubics[SkPatchUtils::kTopP2_CubicCtrlPts] = fHrzCtrlPts[hrzPos + 1];
    cubics[SkPatchUtils::kBottomP1_CubicCtrlPts] = fHrzCtrlPts[hrzPos + (fCols * 2)];
    cubics[SkPatchUtils::kBottomP2_CubicCtrlPts] = fHrzCtrlPts[hrzPos + (fCols * 2) + 1];
    
    int vrtPos = (y*2) * (fCols + 1) + x;
    cubics[SkPatchUtils::kLeftP1_CubicCtrlPts] = fVrtCtrlPts[vrtPos];
    cubics[SkPatchUtils::kRightP1_CubicCtrlPts] = fVrtCtrlPts[vrtPos + 1];
    cubics[SkPatchUtils::kLeftP2_CubicCtrlPts] = fVrtCtrlPts[vrtPos + (fCols + 1)];
    cubics[SkPatchUtils::kRightP2_CubicCtrlPts] = fVrtCtrlPts[vrtPos + (fCols + 1) + 1];
    
    if ((fModeFlags & kColors_VertexType)  && colors) {
        colors[0] = fCornerColors[cornerPos];
        colors[1] = fCornerColors[cornerPos + 1];
        colors[3] = fCornerColors[cornerPos + (fCols + 1)];
        colors[2] = fCornerColors[cornerPos + (fCols + 1) + 1];
    }
    
    if ((fModeFlags & kTexs_VertexType)  && texCoords) {
        texCoords[0] = fTexCoords[cornerPos];
        texCoords[1] = fTexCoords[cornerPos + 1];
        texCoords[3] = fTexCoords[cornerPos + (fCols + 1)];
        texCoords[2] = fTexCoords[cornerPos + (fCols + 1) + 1];
    }
    
    return true;
}

void SkPatchGrid::reset(int rows, int cols, VertexType flags, SkXfermode* xMode) {
    SkDELETE_ARRAY(fCornerPts);
    SkDELETE_ARRAY(fCornerColors);
    SkDELETE_ARRAY(fTexCoords);
    SkDELETE_ARRAY(fHrzCtrlPts);
    SkDELETE_ARRAY(fVrtCtrlPts);
    
    fCols = cols;
    fRows = rows;
    fModeFlags = flags;
    fXferMode = xMode;
    
    fCornerPts = SkNEW_ARRAY(SkPoint, (fRows + 1) * (fCols + 1));
    fHrzCtrlPts = SkNEW_ARRAY(SkPoint, (fRows + 1) * fCols * 2);
    fVrtCtrlPts = SkNEW_ARRAY(SkPoint, fRows * 2 * (fCols + 1));
    memset(fCornerPts, 0, (fRows + 1) * (fCols + 1) * sizeof(SkPoint));
    memset(fHrzCtrlPts, 0, (fRows + 1) * fCols * 2 * sizeof(SkPoint));
    memset(fVrtCtrlPts, 0, fRows * 2 * (fCols + 1) * sizeof(SkPoint));
    
    if (fModeFlags & kColors_VertexType) {
        fCornerColors = SkNEW_ARRAY(SkColor, (fRows + 1) * (fCols + 1));
        memset(fCornerColors, 0, (fRows + 1) * (fCols + 1) * sizeof(SkColor));
    }
    
    if (fModeFlags & kTexs_VertexType) {
        fTexCoords = SkNEW_ARRAY(SkPoint, (fRows + 1) * (fCols + 1));
        memset(fTexCoords, 0, (fRows + 1) * (fCols + 1) * sizeof(SkPoint));
    }
}

void SkPatchGrid::draw(SkCanvas* canvas, SkPaint& paint) {
    int* maxCols = SkNEW_ARRAY(int, fCols);
    int* maxRows = SkNEW_ARRAY(int, fRows);
    memset(maxCols, 0, fCols * sizeof(int));
    memset(maxRows, 0, fRows * sizeof(int));
    
    // Get the maximum level of detail per axis for each row and column
    for (int y = 0; y < fRows; y++) {
        for (int x = 0; x < fCols; x++) {
            SkPoint cubics[12];
            this->getPatch(x, y, cubics, NULL, NULL);
            SkMatrix matrix = canvas->getTotalMatrix();
            SkISize lod = SkPatchUtils::GetLevelOfDetail(cubics, &matrix);
            maxCols[x] = SkMax32(maxCols[x], lod.width());
            maxRows[y] = SkMax32(maxRows[y], lod.height());
        }
    }
    // Draw the patches by generating their geometry with the maximum level of detail per axis.
    for (int x = 0; x < fCols; x++) {
        for (int y = 0; y < fRows; y++) {
            SkPoint cubics[12];
            SkPoint texCoords[4];
            SkColor colors[4];
            this->getPatch(x, y, cubics, colors, texCoords);
            SkPatchUtils::VertexData data;
            if (SkPatchUtils::getVertexData(&data, cubics,
                                            fModeFlags & kColors_VertexType ? colors : NULL,
                                            fModeFlags & kTexs_VertexType ? texCoords : NULL,
                                            maxCols[x], maxRows[y])) {
                canvas->drawVertices(SkCanvas::kTriangles_VertexMode, data.fVertexCount,
                                     data.fPoints, data.fTexCoords, data.fColors, fXferMode,
                                     data.fIndices, data.fIndexCount, paint);
            }
        }
    }
    SkDELETE_ARRAY(maxCols);
    SkDELETE_ARRAY(maxRows);
}
