1cc03adb90901d226e8b0252a187b19a68fabcc42dandov/* 2cc03adb90901d226e8b0252a187b19a68fabcc42dandov * Copyright 2014 Google Inc. 3cc03adb90901d226e8b0252a187b19a68fabcc42dandov * 4cc03adb90901d226e8b0252a187b19a68fabcc42dandov * Use of this source code is governed by a BSD-style license that can be 5cc03adb90901d226e8b0252a187b19a68fabcc42dandov * found in the LICENSE file. 6cc03adb90901d226e8b0252a187b19a68fabcc42dandov */ 7cc03adb90901d226e8b0252a187b19a68fabcc42dandov 8cc03adb90901d226e8b0252a187b19a68fabcc42dandov#include "SkPatchGrid.h" 9cc03adb90901d226e8b0252a187b19a68fabcc42dandov#include "SkPatchUtils.h" 10cc03adb90901d226e8b0252a187b19a68fabcc42dandov 11cc03adb90901d226e8b0252a187b19a68fabcc42dandovSkPatchGrid::SkPatchGrid(int rows, int cols, VertexType flags, SkXfermode* xfer) 12cc03adb90901d226e8b0252a187b19a68fabcc42dandov : fRows(0) 13cc03adb90901d226e8b0252a187b19a68fabcc42dandov , fCols(0) 14cc03adb90901d226e8b0252a187b19a68fabcc42dandov , fModeFlags(kNone_VertexType) 15cc03adb90901d226e8b0252a187b19a68fabcc42dandov , fCornerPts(NULL) 16cc03adb90901d226e8b0252a187b19a68fabcc42dandov , fCornerColors(NULL) 17cc03adb90901d226e8b0252a187b19a68fabcc42dandov , fTexCoords(NULL) 18cc03adb90901d226e8b0252a187b19a68fabcc42dandov , fHrzCtrlPts(NULL) 19cc03adb90901d226e8b0252a187b19a68fabcc42dandov , fVrtCtrlPts(NULL) 20cc03adb90901d226e8b0252a187b19a68fabcc42dandov , fXferMode(NULL) { 21cc03adb90901d226e8b0252a187b19a68fabcc42dandov this->reset(rows, cols, flags, xfer); 22cc03adb90901d226e8b0252a187b19a68fabcc42dandov} 23cc03adb90901d226e8b0252a187b19a68fabcc42dandov 24cc03adb90901d226e8b0252a187b19a68fabcc42dandovSkPatchGrid::~SkPatchGrid() { 25cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkDELETE_ARRAY(fCornerPts); 26cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkDELETE_ARRAY(fCornerColors); 27cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkDELETE_ARRAY(fTexCoords); 28cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkDELETE_ARRAY(fHrzCtrlPts); 29cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkDELETE_ARRAY(fVrtCtrlPts); 30cc03adb90901d226e8b0252a187b19a68fabcc42dandov} 31cc03adb90901d226e8b0252a187b19a68fabcc42dandov 32cc03adb90901d226e8b0252a187b19a68fabcc42dandovbool SkPatchGrid::setPatch(int x, int y, const SkPoint cubics[12], const SkColor colors[4], 33cc03adb90901d226e8b0252a187b19a68fabcc42dandov const SkPoint texCoords[4]) { 34cc03adb90901d226e8b0252a187b19a68fabcc42dandov // Check for the passed paramaters to be within the range of the grid dimensions and a valid 35cc03adb90901d226e8b0252a187b19a68fabcc42dandov // pointer for the cubics' control points. 36cc03adb90901d226e8b0252a187b19a68fabcc42dandov if (x < 0 || y < 0 || x > fCols - 1 || y > fRows - 1 || NULL == cubics) { 37cc03adb90901d226e8b0252a187b19a68fabcc42dandov return false; 38cc03adb90901d226e8b0252a187b19a68fabcc42dandov } 39cc03adb90901d226e8b0252a187b19a68fabcc42dandov 40cc03adb90901d226e8b0252a187b19a68fabcc42dandov // setup corners and colors 41cc03adb90901d226e8b0252a187b19a68fabcc42dandov int cornerPos = y * (fCols + 1) + x; 42cc03adb90901d226e8b0252a187b19a68fabcc42dandov fCornerPts[cornerPos] = cubics[SkPatchUtils::kTopP0_CubicCtrlPts]; 43cc03adb90901d226e8b0252a187b19a68fabcc42dandov fCornerPts[cornerPos + 1] = cubics[SkPatchUtils::kTopP3_CubicCtrlPts]; 44cc03adb90901d226e8b0252a187b19a68fabcc42dandov fCornerPts[cornerPos + (fCols + 1)] = cubics[SkPatchUtils::kBottomP0_CubicCtrlPts]; 45cc03adb90901d226e8b0252a187b19a68fabcc42dandov fCornerPts[cornerPos + (fCols + 1) + 1] = cubics[SkPatchUtils::kBottomP3_CubicCtrlPts]; 46cc03adb90901d226e8b0252a187b19a68fabcc42dandov 47cc03adb90901d226e8b0252a187b19a68fabcc42dandov // set horizontal control points 48cc03adb90901d226e8b0252a187b19a68fabcc42dandov int hrzPos = y * (fCols * 2) + (x * 2); 49cc03adb90901d226e8b0252a187b19a68fabcc42dandov fHrzCtrlPts[hrzPos] = cubics[SkPatchUtils::kTopP1_CubicCtrlPts]; 50cc03adb90901d226e8b0252a187b19a68fabcc42dandov fHrzCtrlPts[hrzPos + 1] = cubics[SkPatchUtils::kTopP2_CubicCtrlPts]; 51cc03adb90901d226e8b0252a187b19a68fabcc42dandov fHrzCtrlPts[hrzPos + (fCols * 2)] = cubics[SkPatchUtils::kBottomP1_CubicCtrlPts]; 52cc03adb90901d226e8b0252a187b19a68fabcc42dandov fHrzCtrlPts[hrzPos + (fCols * 2) + 1] = cubics[SkPatchUtils::kBottomP2_CubicCtrlPts]; 53cc03adb90901d226e8b0252a187b19a68fabcc42dandov 54cc03adb90901d226e8b0252a187b19a68fabcc42dandov // set vertical control points 55cc03adb90901d226e8b0252a187b19a68fabcc42dandov int vrtPos = (y*2) * (fCols + 1) + x; 56cc03adb90901d226e8b0252a187b19a68fabcc42dandov fVrtCtrlPts[vrtPos] = cubics[SkPatchUtils::kLeftP1_CubicCtrlPts]; 57cc03adb90901d226e8b0252a187b19a68fabcc42dandov fVrtCtrlPts[vrtPos + 1] = cubics[SkPatchUtils::kRightP1_CubicCtrlPts]; 58cc03adb90901d226e8b0252a187b19a68fabcc42dandov fVrtCtrlPts[vrtPos + (fCols + 1)] = cubics[SkPatchUtils::kLeftP2_CubicCtrlPts]; 59cc03adb90901d226e8b0252a187b19a68fabcc42dandov fVrtCtrlPts[vrtPos + (fCols + 1) + 1] = cubics[SkPatchUtils::kRightP2_CubicCtrlPts]; 60cc03adb90901d226e8b0252a187b19a68fabcc42dandov 61cc03adb90901d226e8b0252a187b19a68fabcc42dandov // set optional values (colors and texture coordinates) 6249f085dddff10473b6ebf832a974288300224e60bsalomon if ((fModeFlags & kColors_VertexType) && colors) { 63cc03adb90901d226e8b0252a187b19a68fabcc42dandov fCornerColors[cornerPos] = colors[0]; 64cc03adb90901d226e8b0252a187b19a68fabcc42dandov fCornerColors[cornerPos + 1] = colors[1]; 65cc03adb90901d226e8b0252a187b19a68fabcc42dandov fCornerColors[cornerPos + (fCols + 1)] = colors[3]; 66cc03adb90901d226e8b0252a187b19a68fabcc42dandov fCornerColors[cornerPos + (fCols + 1) + 1] = colors[2]; 67cc03adb90901d226e8b0252a187b19a68fabcc42dandov } 68cc03adb90901d226e8b0252a187b19a68fabcc42dandov 6949f085dddff10473b6ebf832a974288300224e60bsalomon if ((fModeFlags & kTexs_VertexType) && texCoords) { 70cc03adb90901d226e8b0252a187b19a68fabcc42dandov fTexCoords[cornerPos] = texCoords[0]; 71cc03adb90901d226e8b0252a187b19a68fabcc42dandov fTexCoords[cornerPos + 1] = texCoords[1]; 72cc03adb90901d226e8b0252a187b19a68fabcc42dandov fTexCoords[cornerPos + (fCols + 1)] = texCoords[3]; 73cc03adb90901d226e8b0252a187b19a68fabcc42dandov fTexCoords[cornerPos + (fCols + 1) + 1] = texCoords[2]; 74cc03adb90901d226e8b0252a187b19a68fabcc42dandov } 75cc03adb90901d226e8b0252a187b19a68fabcc42dandov 76cc03adb90901d226e8b0252a187b19a68fabcc42dandov return true; 77cc03adb90901d226e8b0252a187b19a68fabcc42dandov} 78cc03adb90901d226e8b0252a187b19a68fabcc42dandov 79cc03adb90901d226e8b0252a187b19a68fabcc42dandovbool SkPatchGrid::getPatch(int x, int y, SkPoint cubics[12], SkColor colors[4], 80cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkPoint texCoords[4]) const { 81cc03adb90901d226e8b0252a187b19a68fabcc42dandov 82cc03adb90901d226e8b0252a187b19a68fabcc42dandov if (x < 0 || y < 0 || x > fCols - 1 || y > fRows - 1 || NULL == cubics) { 83cc03adb90901d226e8b0252a187b19a68fabcc42dandov return false; 84cc03adb90901d226e8b0252a187b19a68fabcc42dandov } 85cc03adb90901d226e8b0252a187b19a68fabcc42dandov 86cc03adb90901d226e8b0252a187b19a68fabcc42dandov // set the patch by building the array of points and colors with the corresponding values. 87cc03adb90901d226e8b0252a187b19a68fabcc42dandov int cornerPos = y * (fCols + 1) + x; 88cc03adb90901d226e8b0252a187b19a68fabcc42dandov cubics[SkPatchUtils::kTopP0_CubicCtrlPts] = fCornerPts[cornerPos]; 89cc03adb90901d226e8b0252a187b19a68fabcc42dandov cubics[SkPatchUtils::kTopP3_CubicCtrlPts] = fCornerPts[cornerPos + 1]; 90cc03adb90901d226e8b0252a187b19a68fabcc42dandov cubics[SkPatchUtils::kBottomP0_CubicCtrlPts] = fCornerPts[cornerPos + (fCols + 1)]; 91cc03adb90901d226e8b0252a187b19a68fabcc42dandov cubics[SkPatchUtils::kBottomP3_CubicCtrlPts] = fCornerPts[cornerPos + (fCols + 1) + 1]; 92cc03adb90901d226e8b0252a187b19a68fabcc42dandov 93cc03adb90901d226e8b0252a187b19a68fabcc42dandov int hrzPos = y * (fCols * 2) + (x * 2); 94cc03adb90901d226e8b0252a187b19a68fabcc42dandov cubics[SkPatchUtils::kTopP1_CubicCtrlPts] = fHrzCtrlPts[hrzPos]; 95cc03adb90901d226e8b0252a187b19a68fabcc42dandov cubics[SkPatchUtils::kTopP2_CubicCtrlPts] = fHrzCtrlPts[hrzPos + 1]; 96cc03adb90901d226e8b0252a187b19a68fabcc42dandov cubics[SkPatchUtils::kBottomP1_CubicCtrlPts] = fHrzCtrlPts[hrzPos + (fCols * 2)]; 97cc03adb90901d226e8b0252a187b19a68fabcc42dandov cubics[SkPatchUtils::kBottomP2_CubicCtrlPts] = fHrzCtrlPts[hrzPos + (fCols * 2) + 1]; 98cc03adb90901d226e8b0252a187b19a68fabcc42dandov 99cc03adb90901d226e8b0252a187b19a68fabcc42dandov int vrtPos = (y*2) * (fCols + 1) + x; 100cc03adb90901d226e8b0252a187b19a68fabcc42dandov cubics[SkPatchUtils::kLeftP1_CubicCtrlPts] = fVrtCtrlPts[vrtPos]; 101cc03adb90901d226e8b0252a187b19a68fabcc42dandov cubics[SkPatchUtils::kRightP1_CubicCtrlPts] = fVrtCtrlPts[vrtPos + 1]; 102cc03adb90901d226e8b0252a187b19a68fabcc42dandov cubics[SkPatchUtils::kLeftP2_CubicCtrlPts] = fVrtCtrlPts[vrtPos + (fCols + 1)]; 103cc03adb90901d226e8b0252a187b19a68fabcc42dandov cubics[SkPatchUtils::kRightP2_CubicCtrlPts] = fVrtCtrlPts[vrtPos + (fCols + 1) + 1]; 104cc03adb90901d226e8b0252a187b19a68fabcc42dandov 10549f085dddff10473b6ebf832a974288300224e60bsalomon if ((fModeFlags & kColors_VertexType) && colors) { 106cc03adb90901d226e8b0252a187b19a68fabcc42dandov colors[0] = fCornerColors[cornerPos]; 107cc03adb90901d226e8b0252a187b19a68fabcc42dandov colors[1] = fCornerColors[cornerPos + 1]; 108cc03adb90901d226e8b0252a187b19a68fabcc42dandov colors[3] = fCornerColors[cornerPos + (fCols + 1)]; 109cc03adb90901d226e8b0252a187b19a68fabcc42dandov colors[2] = fCornerColors[cornerPos + (fCols + 1) + 1]; 110cc03adb90901d226e8b0252a187b19a68fabcc42dandov } 111cc03adb90901d226e8b0252a187b19a68fabcc42dandov 11249f085dddff10473b6ebf832a974288300224e60bsalomon if ((fModeFlags & kTexs_VertexType) && texCoords) { 113cc03adb90901d226e8b0252a187b19a68fabcc42dandov texCoords[0] = fTexCoords[cornerPos]; 114cc03adb90901d226e8b0252a187b19a68fabcc42dandov texCoords[1] = fTexCoords[cornerPos + 1]; 115cc03adb90901d226e8b0252a187b19a68fabcc42dandov texCoords[3] = fTexCoords[cornerPos + (fCols + 1)]; 116cc03adb90901d226e8b0252a187b19a68fabcc42dandov texCoords[2] = fTexCoords[cornerPos + (fCols + 1) + 1]; 117cc03adb90901d226e8b0252a187b19a68fabcc42dandov } 118cc03adb90901d226e8b0252a187b19a68fabcc42dandov 119cc03adb90901d226e8b0252a187b19a68fabcc42dandov return true; 120cc03adb90901d226e8b0252a187b19a68fabcc42dandov} 121cc03adb90901d226e8b0252a187b19a68fabcc42dandov 122cc03adb90901d226e8b0252a187b19a68fabcc42dandovvoid SkPatchGrid::reset(int rows, int cols, VertexType flags, SkXfermode* xMode) { 123cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkDELETE_ARRAY(fCornerPts); 124cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkDELETE_ARRAY(fCornerColors); 125cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkDELETE_ARRAY(fTexCoords); 126cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkDELETE_ARRAY(fHrzCtrlPts); 127cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkDELETE_ARRAY(fVrtCtrlPts); 128cc03adb90901d226e8b0252a187b19a68fabcc42dandov 129cc03adb90901d226e8b0252a187b19a68fabcc42dandov fCols = cols; 130cc03adb90901d226e8b0252a187b19a68fabcc42dandov fRows = rows; 131cc03adb90901d226e8b0252a187b19a68fabcc42dandov fModeFlags = flags; 132cc03adb90901d226e8b0252a187b19a68fabcc42dandov fXferMode = xMode; 133cc03adb90901d226e8b0252a187b19a68fabcc42dandov 134cc03adb90901d226e8b0252a187b19a68fabcc42dandov fCornerPts = SkNEW_ARRAY(SkPoint, (fRows + 1) * (fCols + 1)); 135cc03adb90901d226e8b0252a187b19a68fabcc42dandov fHrzCtrlPts = SkNEW_ARRAY(SkPoint, (fRows + 1) * fCols * 2); 136cc03adb90901d226e8b0252a187b19a68fabcc42dandov fVrtCtrlPts = SkNEW_ARRAY(SkPoint, fRows * 2 * (fCols + 1)); 137cc03adb90901d226e8b0252a187b19a68fabcc42dandov memset(fCornerPts, 0, (fRows + 1) * (fCols + 1) * sizeof(SkPoint)); 138cc03adb90901d226e8b0252a187b19a68fabcc42dandov memset(fHrzCtrlPts, 0, (fRows + 1) * fCols * 2 * sizeof(SkPoint)); 139cc03adb90901d226e8b0252a187b19a68fabcc42dandov memset(fVrtCtrlPts, 0, fRows * 2 * (fCols + 1) * sizeof(SkPoint)); 140cc03adb90901d226e8b0252a187b19a68fabcc42dandov 141cc03adb90901d226e8b0252a187b19a68fabcc42dandov if (fModeFlags & kColors_VertexType) { 142cc03adb90901d226e8b0252a187b19a68fabcc42dandov fCornerColors = SkNEW_ARRAY(SkColor, (fRows + 1) * (fCols + 1)); 143cc03adb90901d226e8b0252a187b19a68fabcc42dandov memset(fCornerColors, 0, (fRows + 1) * (fCols + 1) * sizeof(SkColor)); 144cc03adb90901d226e8b0252a187b19a68fabcc42dandov } 145cc03adb90901d226e8b0252a187b19a68fabcc42dandov 146cc03adb90901d226e8b0252a187b19a68fabcc42dandov if (fModeFlags & kTexs_VertexType) { 147cc03adb90901d226e8b0252a187b19a68fabcc42dandov fTexCoords = SkNEW_ARRAY(SkPoint, (fRows + 1) * (fCols + 1)); 148cc03adb90901d226e8b0252a187b19a68fabcc42dandov memset(fTexCoords, 0, (fRows + 1) * (fCols + 1) * sizeof(SkPoint)); 149cc03adb90901d226e8b0252a187b19a68fabcc42dandov } 150cc03adb90901d226e8b0252a187b19a68fabcc42dandov} 151cc03adb90901d226e8b0252a187b19a68fabcc42dandov 152cc03adb90901d226e8b0252a187b19a68fabcc42dandovvoid SkPatchGrid::draw(SkCanvas* canvas, SkPaint& paint) { 153cc03adb90901d226e8b0252a187b19a68fabcc42dandov int* maxCols = SkNEW_ARRAY(int, fCols); 154cc03adb90901d226e8b0252a187b19a68fabcc42dandov int* maxRows = SkNEW_ARRAY(int, fRows); 155cc03adb90901d226e8b0252a187b19a68fabcc42dandov memset(maxCols, 0, fCols * sizeof(int)); 156cc03adb90901d226e8b0252a187b19a68fabcc42dandov memset(maxRows, 0, fRows * sizeof(int)); 157cc03adb90901d226e8b0252a187b19a68fabcc42dandov 158cc03adb90901d226e8b0252a187b19a68fabcc42dandov // Get the maximum level of detail per axis for each row and column 159cc03adb90901d226e8b0252a187b19a68fabcc42dandov for (int y = 0; y < fRows; y++) { 160cc03adb90901d226e8b0252a187b19a68fabcc42dandov for (int x = 0; x < fCols; x++) { 161cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkPoint cubics[12]; 162cc03adb90901d226e8b0252a187b19a68fabcc42dandov this->getPatch(x, y, cubics, NULL, NULL); 163cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkMatrix matrix = canvas->getTotalMatrix(); 164cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkISize lod = SkPatchUtils::GetLevelOfDetail(cubics, &matrix); 165cc03adb90901d226e8b0252a187b19a68fabcc42dandov maxCols[x] = SkMax32(maxCols[x], lod.width()); 166cc03adb90901d226e8b0252a187b19a68fabcc42dandov maxRows[y] = SkMax32(maxRows[y], lod.height()); 167cc03adb90901d226e8b0252a187b19a68fabcc42dandov } 168cc03adb90901d226e8b0252a187b19a68fabcc42dandov } 169cc03adb90901d226e8b0252a187b19a68fabcc42dandov // Draw the patches by generating their geometry with the maximum level of detail per axis. 170cc03adb90901d226e8b0252a187b19a68fabcc42dandov for (int x = 0; x < fCols; x++) { 171cc03adb90901d226e8b0252a187b19a68fabcc42dandov for (int y = 0; y < fRows; y++) { 172cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkPoint cubics[12]; 173cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkPoint texCoords[4]; 174cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkColor colors[4]; 175cc03adb90901d226e8b0252a187b19a68fabcc42dandov this->getPatch(x, y, cubics, colors, texCoords); 176cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkPatchUtils::VertexData data; 1777e5598a004d0aceb630707053566bee523feea66dandov if (SkPatchUtils::getVertexData(&data, cubics, 1787e5598a004d0aceb630707053566bee523feea66dandov fModeFlags & kColors_VertexType ? colors : NULL, 1797e5598a004d0aceb630707053566bee523feea66dandov fModeFlags & kTexs_VertexType ? texCoords : NULL, 1807e5598a004d0aceb630707053566bee523feea66dandov maxCols[x], maxRows[y])) { 1817e5598a004d0aceb630707053566bee523feea66dandov canvas->drawVertices(SkCanvas::kTriangles_VertexMode, data.fVertexCount, 1827e5598a004d0aceb630707053566bee523feea66dandov data.fPoints, data.fTexCoords, data.fColors, fXferMode, 1837e5598a004d0aceb630707053566bee523feea66dandov data.fIndices, data.fIndexCount, paint); 1847e5598a004d0aceb630707053566bee523feea66dandov } 185cc03adb90901d226e8b0252a187b19a68fabcc42dandov } 186cc03adb90901d226e8b0252a187b19a68fabcc42dandov } 187cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkDELETE_ARRAY(maxCols); 188cc03adb90901d226e8b0252a187b19a68fabcc42dandov SkDELETE_ARRAY(maxRows); 189cc03adb90901d226e8b0252a187b19a68fabcc42dandov} 190