OLD | NEW |
(Empty) | |
| 1 /* |
| 2 * Copyright 2014 Google Inc. |
| 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. |
| 6 */ |
| 7 |
| 8 #include "SkMeshGradient.h" |
| 9 #include "SkPatchUtils.h" |
| 10 |
| 11 SkMeshGradient::SkMeshGradient(int rows, int cols) |
| 12 : fRows(rows) |
| 13 , fCols(cols) |
| 14 , fCornerPts(NULL) |
| 15 , fCornerColors(NULL) |
| 16 , fHrzCtrlPts(NULL) |
| 17 , fVrtCtrlPts(NULL) { |
| 18 this->reset(fRows, fCols, NULL, NULL, NULL, NULL); |
| 19 } |
| 20 |
| 21 SkMeshGradient::SkMeshGradient(int rows, int cols, const SkPoint* corners, |
| 22 const SkPoint* hrzCtrlPts, const SkPoint* vrtCtrl
Pts, |
| 23 const SkColor* colors) |
| 24 : fRows(rows) |
| 25 , fCols(cols) |
| 26 , fCornerPts(NULL) |
| 27 , fCornerColors(NULL) |
| 28 , fHrzCtrlPts(NULL) |
| 29 , fVrtCtrlPts(NULL) { |
| 30 this->reset(fRows, fCols, corners, hrzCtrlPts, vrtCtrlPts, colors); |
| 31 } |
| 32 |
| 33 SkMeshGradient::~SkMeshGradient() { |
| 34 SkDELETE_ARRAY(fCornerPts); |
| 35 SkDELETE_ARRAY(fCornerColors); |
| 36 SkDELETE_ARRAY(fHrzCtrlPts); |
| 37 SkDELETE_ARRAY(fVrtCtrlPts); |
| 38 } |
| 39 |
| 40 bool SkMeshGradient::addPatch(int x, int y, const SkPoint ctrlPts[12], const SkC
olor colors[4]) { |
| 41 // Check for the passed paramaters to be within the range of the mesh gradie
nt dimensions. |
| 42 if (x < 0 || y < 0 || x > fCols - 1 || y > fRows - 1) { |
| 43 return false; |
| 44 } |
| 45 |
| 46 //setup corners and colors |
| 47 int cornerPos = y * (fCols + 1) + x; |
| 48 fCornerPts[cornerPos] = ctrlPts[SkPatch::kTopP0_CubicCtrlPts]; |
| 49 fCornerPts[cornerPos + 1] = ctrlPts[SkPatch::kTopP3_CubicCtrlPts]; |
| 50 fCornerPts[cornerPos + (fCols + 1)] = ctrlPts[SkPatch::kBottomP0_CubicCtrlPt
s]; |
| 51 fCornerPts[cornerPos + (fCols + 1) + 1] = ctrlPts[SkPatch::kBottomP3_CubicCt
rlPts]; |
| 52 |
| 53 fCornerColors[cornerPos] = colors[0]; |
| 54 fCornerColors[cornerPos + 1] = colors[1]; |
| 55 fCornerColors[cornerPos + (fCols + 1)] = colors[3]; |
| 56 fCornerColors[cornerPos + (fCols + 1) + 1] = colors[2]; |
| 57 |
| 58 // set horizontal control points |
| 59 int hrzPos = y * (fCols * 2) + (x * 2); |
| 60 fHrzCtrlPts[hrzPos] = ctrlPts[SkPatch::kTopP1_CubicCtrlPts]; |
| 61 fHrzCtrlPts[hrzPos + 1] = ctrlPts[SkPatch::kTopP2_CubicCtrlPts]; |
| 62 fHrzCtrlPts[hrzPos + (fCols * 2)] = ctrlPts[SkPatch::kBottomP1_CubicCtrlPts]
; |
| 63 fHrzCtrlPts[hrzPos + (fCols * 2) + 1] = ctrlPts[SkPatch::kBottomP2_CubicCtrl
Pts]; |
| 64 |
| 65 int vrtPos = (y*2) * (fCols + 1) + x; |
| 66 fVrtCtrlPts[vrtPos] = ctrlPts[SkPatch::kLeftP1_CubicCtrlPts]; |
| 67 fVrtCtrlPts[vrtPos + 1] = ctrlPts[SkPatch::kRightP1_CubicCtrlPts]; |
| 68 fVrtCtrlPts[vrtPos + (fCols + 1)] = ctrlPts[SkPatch::kLeftP2_CubicCtrlPts]; |
| 69 fVrtCtrlPts[vrtPos + (fCols + 1) + 1] = ctrlPts[SkPatch::kRightP2_CubicCtrlP
ts]; |
| 70 return true; |
| 71 } |
| 72 |
| 73 bool SkMeshGradient::addPatch(int x, int y, const SkPatch& patch) { |
| 74 return this->addPatch(x, y, patch.getControlPoints(), patch.getColors()); |
| 75 } |
| 76 |
| 77 void SkMeshGradient::getPatchAt(int x, int y, SkPatch* patch) const { |
| 78 |
| 79 if (x < 0 || y < 0 || x > fCols - 1 || y > fRows - 1) { |
| 80 return; |
| 81 } |
| 82 |
| 83 if (NULL != patch) { |
| 84 //set the patch by building the array of points and colors with the corr
esponding values. |
| 85 |
| 86 SkPoint ctrlPts[12]; |
| 87 SkColor colors[4]; |
| 88 |
| 89 int cornerPos = y * (fCols + 1) + x; |
| 90 ctrlPts[SkPatch::kTopP0_CubicCtrlPts] = fCornerPts[cornerPos]; |
| 91 ctrlPts[SkPatch::kTopP3_CubicCtrlPts] = fCornerPts[cornerPos + 1]; |
| 92 ctrlPts[SkPatch::kBottomP0_CubicCtrlPts] = fCornerPts[cornerPos + (fCols
+ 1)]; |
| 93 ctrlPts[SkPatch::kBottomP3_CubicCtrlPts] = fCornerPts[cornerPos + (fCols
+ 1) + 1]; |
| 94 |
| 95 colors[0] = fCornerColors[cornerPos]; |
| 96 colors[1] = fCornerColors[cornerPos + 1]; |
| 97 colors[3] = fCornerColors[cornerPos + (fCols + 1)]; |
| 98 colors[2] = fCornerColors[cornerPos + (fCols + 1) + 1]; |
| 99 |
| 100 int hrzPos = y * (fCols * 2) + (x * 2); |
| 101 ctrlPts[SkPatch::kTopP1_CubicCtrlPts] = fHrzCtrlPts[hrzPos]; |
| 102 ctrlPts[SkPatch::kTopP2_CubicCtrlPts] = fHrzCtrlPts[hrzPos + 1]; |
| 103 ctrlPts[SkPatch::kBottomP1_CubicCtrlPts] = fHrzCtrlPts[hrzPos + (fCols *
2)]; |
| 104 ctrlPts[SkPatch::kBottomP2_CubicCtrlPts] = fHrzCtrlPts[hrzPos + (fCols *
2) + 1]; |
| 105 |
| 106 int vrtPos = (y*2) * (fCols + 1) + x; |
| 107 ctrlPts[SkPatch::kLeftP1_CubicCtrlPts] = fVrtCtrlPts[vrtPos]; |
| 108 ctrlPts[SkPatch::kRightP1_CubicCtrlPts] = fVrtCtrlPts[vrtPos + 1]; |
| 109 ctrlPts[SkPatch::kLeftP2_CubicCtrlPts] = fVrtCtrlPts[vrtPos + (fCols + 1
)]; |
| 110 ctrlPts[SkPatch::kRightP2_CubicCtrlPts] = fVrtCtrlPts[vrtPos + (fCols +
1) + 1]; |
| 111 |
| 112 patch->reset(ctrlPts, colors); |
| 113 } |
| 114 } |
| 115 |
| 116 void SkMeshGradient::resize(int rows, int cols) { |
| 117 //save old values |
| 118 int oldCols = fCols; |
| 119 int oldRows = fRows; |
| 120 |
| 121 fCols = cols; |
| 122 fRows = rows; |
| 123 |
| 124 SkPoint* pts = fCornerPts; |
| 125 SkColor* colors = fCornerColors; |
| 126 SkPoint* hzrPts = fHrzCtrlPts; |
| 127 SkPoint* vrtPts = fVrtCtrlPts; |
| 128 |
| 129 fCornerPts = SkNEW_ARRAY(SkPoint, (fRows + 1) * (fCols + 1)); |
| 130 fCornerColors = SkNEW_ARRAY(SkColor, (fRows + 1) * (fCols + 1)); |
| 131 fHrzCtrlPts = SkNEW_ARRAY(SkPoint, (fRows + 1) * fCols * 2); |
| 132 fVrtCtrlPts = SkNEW_ARRAY(SkPoint, fRows * 2 * (fCols + 1)); |
| 133 |
| 134 //copy previous values that are still within the new range. |
| 135 for (int y = 0; y < fRows; y++) { |
| 136 for (int x = 0; x < fCols; x++) { |
| 137 if (x >= oldCols || y >= oldRows) { |
| 138 continue; |
| 139 } |
| 140 |
| 141 int cornerPos = y * (fCols + 1) + x; |
| 142 int oldCornerPos = y * (oldCols + 1) + x; |
| 143 fCornerPts[cornerPos] = pts[oldCornerPos]; |
| 144 fCornerPts[cornerPos + 1] = pts[oldCornerPos + 1]; |
| 145 fCornerPts[cornerPos + (fCols + 1)] = pts[oldCornerPos + (oldCols +
1)]; |
| 146 fCornerPts[cornerPos + (fCols + 1) + 1] = pts[oldCornerPos + (oldCol
s + 1) + 1]; |
| 147 fCornerColors[cornerPos] = colors[oldCornerPos]; |
| 148 fCornerColors[cornerPos + 1] = colors[oldCornerPos + 1]; |
| 149 fCornerColors[cornerPos + (fCols + 1)] = colors[oldCornerPos + (oldC
ols + 1)]; |
| 150 fCornerColors[cornerPos + (fCols + 1) + 1] = |
| 151 colors[oldCornerPos + (oldCo
ls + 1) + 1]; |
| 152 |
| 153 int hrzPos = y * (fCols * 2) + (x * 2); |
| 154 int oldHrzPos = y * (oldCols * 2) + (x * 2); |
| 155 fHrzCtrlPts[hrzPos] = hzrPts[oldHrzPos]; |
| 156 fHrzCtrlPts[hrzPos + 1] = hzrPts[oldHrzPos + 1]; |
| 157 fHrzCtrlPts[hrzPos + (fCols * 2)] = hzrPts[oldHrzPos + (oldCols * 2)
]; |
| 158 fHrzCtrlPts[hrzPos + (fCols * 2) + 1] = hzrPts[oldHrzPos + (oldCols
* 2) + 1]; |
| 159 |
| 160 int vrtPos = (y*2) * (fCols + 1) + x; |
| 161 int oldVrtPos = (y*2) * (oldCols + 1) + x; |
| 162 fVrtCtrlPts[vrtPos] = vrtPts[oldVrtPos]; |
| 163 fVrtCtrlPts[vrtPos + 1] = vrtPts[oldVrtPos + 1]; |
| 164 fVrtCtrlPts[vrtPos + (fCols + 1)] = vrtPts[oldVrtPos + (oldCols + 1)
]; |
| 165 fVrtCtrlPts[vrtPos + (fCols + 1) + 1] = vrtPts[oldVrtPos + (oldCols
+ 1) + 1]; |
| 166 } |
| 167 } |
| 168 |
| 169 //delete old copies. |
| 170 SkDELETE_ARRAY(pts); |
| 171 SkDELETE_ARRAY(colors); |
| 172 SkDELETE_ARRAY(hzrPts); |
| 173 SkDELETE_ARRAY(vrtPts); |
| 174 } |
| 175 |
| 176 void SkMeshGradient::reset(int rows, int cols, const SkPoint* corners, const SkP
oint* hrzCtrlPts, |
| 177 const SkPoint* vrtCtrlPts, const SkColor* colors) { |
| 178 SkDELETE_ARRAY(fCornerPts); |
| 179 SkDELETE_ARRAY(fCornerColors); |
| 180 SkDELETE_ARRAY(fHrzCtrlPts); |
| 181 SkDELETE_ARRAY(fVrtCtrlPts); |
| 182 |
| 183 fCols = cols; |
| 184 fRows = rows; |
| 185 |
| 186 fCornerPts = SkNEW_ARRAY(SkPoint, (fRows + 1) * (fCols + 1)); |
| 187 fCornerColors = SkNEW_ARRAY(SkColor, (fRows + 1) * (fCols + 1)); |
| 188 fHrzCtrlPts = SkNEW_ARRAY(SkPoint, (fRows + 1) * fCols * 2); |
| 189 fVrtCtrlPts = SkNEW_ARRAY(SkPoint, fRows * 2 * (fCols + 1)); |
| 190 |
| 191 if (NULL != corners) { |
| 192 memcpy(fCornerPts, corners, (fRows + 1) * (fCols + 1) * sizeof(SkPoint))
; |
| 193 } |
| 194 if (NULL != colors) { |
| 195 memcpy(fCornerColors, colors, (fRows + 1) * (fCols + 1) * sizeof(SkColor
)); |
| 196 } |
| 197 if (NULL != hrzCtrlPts) { |
| 198 memcpy(fHrzCtrlPts, hrzCtrlPts, (fRows + 1) * fCols * 2 * sizeof(SkPoint
)); |
| 199 } |
| 200 if (NULL != vrtCtrlPts) { |
| 201 memcpy(fVrtCtrlPts, vrtCtrlPts, fRows * 2 * (fCols + 1) * sizeof(SkPoint
)); |
| 202 } |
| 203 } |
| 204 |
| 205 void SkMeshGradient::draw(SkCanvas* canvas, SkPaint& paint) { |
| 206 int* maxCols = SkNEW_ARRAY(int, fCols); |
| 207 int* maxRows = SkNEW_ARRAY(int, fRows); |
| 208 memset(maxCols, 0, fCols*sizeof(int)); |
| 209 memset(maxRows, 0, fRows*sizeof(int)); |
| 210 |
| 211 // Get the maximum level of detail per axis for each row and column |
| 212 for (int y = 0; y < fRows; y++) { |
| 213 for (int x = 0; x < fCols; x++) { |
| 214 SkPatch patch; |
| 215 this->getPatchAt(x, y, &patch); |
| 216 SkMatrix matrix = canvas->getTotalMatrix(); |
| 217 SkISize lod = SkPatchUtils::GetLevelOfDetail(patch, &matrix); |
| 218 maxCols[x] = SkMax32(maxCols[x], lod.width()); |
| 219 maxRows[y] = SkMax32(maxRows[y], lod.height()); |
| 220 } |
| 221 } |
| 222 // Draw the patches by generating their mesh with the maximum level of detai
l per axis. |
| 223 for (int y = 0; y < fRows; y++) { |
| 224 for (int x = 0; x < fCols; x++) { |
| 225 SkPatch patch; |
| 226 this->getPatchAt(x, y, &patch); |
| 227 SkPatch::VertexData data; |
| 228 patch.getVertexData(&data, maxCols[x], maxRows[y]); |
| 229 canvas->drawVertices(SkCanvas::kTriangles_VertexMode, data.fVertexCo
unt, |
| 230 data.fPoints, data.fTexCoords, data.fColors, NU
LL, |
| 231 data.fIndices, data.fIndexCount, paint); |
| 232 } |
| 233 } |
| 234 SkDELETE_ARRAY(maxCols); |
| 235 SkDELETE_ARRAY(maxRows); |
| 236 } |
OLD | NEW |