Chromium Code Reviews| Index: src/core/SkPatch.cpp |
| diff --git a/src/core/SkPatch.cpp b/src/core/SkPatch.cpp |
| index acd6cb9b57725aafcd999091fb1b40f57c2557fe..8f872fbcbceb3e1e406f589d26e500e1ad297bf3 100644 |
| --- a/src/core/SkPatch.cpp |
| +++ b/src/core/SkPatch.cpp |
| @@ -53,6 +53,21 @@ public: |
| this->restart(1); |
| } |
| + explicit FwDCubicEvaluator(SkPoint points[4]) { |
| + for (int i = 0; i< 4; i++) { |
| + fPoints[i] = points[i]; |
| + } |
| + |
| + SkScalar cx[4], cy[4]; |
| + SkGetCubicCoeff(fPoints, cx, cy); |
| + fCoefs[0].set(cx[0], cy[0]); |
| + fCoefs[1].set(cx[1], cy[1]); |
| + fCoefs[2].set(cx[2], cy[2]); |
| + fCoefs[3].set(cx[3], cy[3]); |
| + |
| + this->restart(1); |
| + } |
| + |
| /** |
| * Restarts the forward differences evaluator to the first value of t = 0. |
| */ |
| @@ -120,51 +135,47 @@ uint8_t bilinear(SkScalar tx, SkScalar ty, SkScalar c00, SkScalar c10, SkScalar |
| return uint8_t(a * (1.f - ty) + b * ty); |
| } |
| -bool SkPatch::getVertexData(SkPatch::VertexData* data, int divisions) { |
| +bool SkPatch::getVertexData(SkPatch::VertexData* data, int lodX, int lodY) const { |
| - if (divisions < 1) { |
| + if (lodX < 1 || lodY < 1) { |
| return false; |
| } |
| - int divX = divisions, divY = divisions; |
| - |
| - data->fVertexCount = (divX + 1) * (divY + 1); |
| - data->fIndexCount = divX * divY * 6; |
| + // number of indices is limited by size of uint16_t, so we clamp it to avoid overflow |
| + data->fVertexCount = (lodX + 1) * (lodY + 1); |
| + if (data->fVertexCount > 65536) { |
| + data->fVertexCount = 65536; |
| + lodX = lodY = 255; |
|
bsalomon
2014/07/31 17:39:06
lodX = SkMin(lodX, 255) and same for lodY?
dandov
2014/07/31 21:35:40
Done.
|
| + } |
| + data->fIndexCount = lodX * lodY * 6; |
| data->fPoints = SkNEW_ARRAY(SkPoint, data->fVertexCount); |
| data->fColors = SkNEW_ARRAY(uint32_t, data->fVertexCount); |
| data->fTexCoords = SkNEW_ARRAY(SkPoint, data->fVertexCount); |
| data->fIndices = SkNEW_ARRAY(uint16_t, data->fIndexCount); |
| - FwDCubicEvaluator fBottom(fCtrlPoints[kBottomP0_CubicCtrlPts], |
| - fCtrlPoints[kBottomP1_CubicCtrlPts], |
| - fCtrlPoints[kBottomP2_CubicCtrlPts], |
| - fCtrlPoints[kBottomP3_CubicCtrlPts]), |
| - fTop(fCtrlPoints[kTopP0_CubicCtrlPts], |
| - fCtrlPoints[kTopP1_CubicCtrlPts], |
| - fCtrlPoints[kTopP2_CubicCtrlPts], |
| - fCtrlPoints[kTopP2_CubicCtrlPts]), |
| - fLeft(fCtrlPoints[kLeftP0_CubicCtrlPts], |
| - fCtrlPoints[kLeftP1_CubicCtrlPts], |
| - fCtrlPoints[kLeftP2_CubicCtrlPts], |
| - fCtrlPoints[kLeftP3_CubicCtrlPts]), |
| - fRight(fCtrlPoints[kRightP0_CubicCtrlPts], |
| - fCtrlPoints[kRightP1_CubicCtrlPts], |
| - fCtrlPoints[kRightP2_CubicCtrlPts], |
| - fCtrlPoints[kRightP3_CubicCtrlPts]); |
| - |
| - fBottom.restart(divX); |
| - fTop.restart(divX); |
| + SkPoint pts[4]; |
| + this->getBottomPoints(pts); |
| + FwDCubicEvaluator fBottom(pts); |
| + this->getTopPoints(pts); |
| + FwDCubicEvaluator fTop(pts); |
| + this->getLeftPoints(pts); |
| + FwDCubicEvaluator fLeft(pts); |
| + this->getRightPoints(pts); |
| + FwDCubicEvaluator fRight(pts); |
| + |
| + fBottom.restart(lodX); |
| + fTop.restart(lodX); |
| SkScalar u = 0.0f; |
| - int stride = divY + 1; |
| - for (int x = 0; x <= divX; x++) { |
| + int stride = lodY + 1; |
| + for (int x = 0; x <= lodX; x++) { |
| SkPoint bottom = fBottom.next(), top = fTop.next(); |
| - fLeft.restart(divY); |
| - fRight.restart(divY); |
| + fLeft.restart(lodY); |
| + fRight.restart(lodY); |
| SkScalar v = 0.f; |
| - for (int y = 0; y <= divY; y++) { |
| - int dataIndex = x * (divX + 1) + y; |
| + for (int y = 0; y <= lodY; y++) { |
| + int dataIndex = x * (lodY + 1) + y; |
| SkPoint left = fLeft.next(), right = fRight.next(); |
| @@ -193,22 +204,26 @@ bool SkPatch::getVertexData(SkPatch::VertexData* data, int divisions) { |
| SkScalar(SkColorGetR(fCornerColors[1])), |
| SkScalar(SkColorGetR(fCornerColors[2])), |
| SkScalar(SkColorGetR(fCornerColors[3]))); |
| + // check in case there are some precision errors. |
| + r = r > a ? a : r; |
| uint8_t g = bilinear(u, v, |
| SkScalar(SkColorGetG(fCornerColors[0])), |
| SkScalar(SkColorGetG(fCornerColors[1])), |
| SkScalar(SkColorGetG(fCornerColors[2])), |
| SkScalar(SkColorGetG(fCornerColors[3]))); |
| + g = g > a ? a : g; |
| uint8_t b = bilinear(u, v, |
| SkScalar(SkColorGetB(fCornerColors[0])), |
| SkScalar(SkColorGetB(fCornerColors[1])), |
| SkScalar(SkColorGetB(fCornerColors[2])), |
| SkScalar(SkColorGetB(fCornerColors[3]))); |
| + b = b > a ? a : b; |
| data->fColors[dataIndex] = SkPackARGB32(a,r,g,b); |
| data->fTexCoords[dataIndex] = SkPoint::Make(u, v); |
| - if(x < divX && y < divY) { |
| - int i = 6 * (x * divY + y); |
| + if(x < lodX && y < lodY) { |
| + int i = 6 * (x * lodY + y); |
| data->fIndices[i] = x * stride + y; |
| data->fIndices[i + 1] = x * stride + 1 + y; |
| data->fIndices[i + 2] = (x + 1) * stride + 1 + y; |
| @@ -216,9 +231,9 @@ bool SkPatch::getVertexData(SkPatch::VertexData* data, int divisions) { |
| data->fIndices[i + 4] = data->fIndices[i + 2]; |
| data->fIndices[i + 5] = (x + 1) * stride + y; |
| } |
| - v += 1.f / divY; |
| + v += 1.f / lodY; |
| } |
| - u += 1.f / divX; |
| + u += 1.f / lodX; |
| } |
| return true; |
| } |