Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(671)

Unified Diff: src/utils/SkPatchUtils.cpp

Issue 463493002: SkCanvas::drawPatch param SkPoint[12] (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/utils/SkPatchUtils.cpp
diff --git a/src/utils/SkPatchUtils.cpp b/src/utils/SkPatchUtils.cpp
index ab15290a346c7e046fdd4e6b64b888a628c73d3c..fe5a19405c2d5e4123f96acd93f2d5abca338239 100644
--- a/src/utils/SkPatchUtils.cpp
+++ b/src/utils/SkPatchUtils.cpp
@@ -7,6 +7,8 @@
#include "SkPatchUtils.h"
+#include "SkColorPriv.h"
+
// size in pixels of each partition per axis, adjust this knob
static const int kPartitionSize = 15;
@@ -24,26 +26,30 @@ static SkScalar approx_arc_length(SkPoint* points, int count) {
return arcLength;
}
-SkISize SkPatchUtils::GetLevelOfDetail(const SkPatch& patch, const SkMatrix* matrix) {
-
- SkPoint mapPts[12];
- matrix->mapPoints(mapPts, patch.getControlPoints(), 12);
+static SkScalar bilerp(SkScalar tx, SkScalar ty, SkScalar c00, SkScalar c10, SkScalar c01,
+ SkScalar c11) {
+ SkScalar a = c00 * (1.f - tx) + c10 * tx;
+ SkScalar b = c01 * (1.f - tx) + c11 * tx;
+ return a * (1.f - ty) + b * ty;
+}
+
+SkISize SkPatchUtils::GetLevelOfDetail(const SkPoint cubics[12], const SkMatrix* matrix) {
// Approximate length of each cubic.
SkPoint pts[4];
- patch.getTopPoints(pts);
+ SkPatchUtils::getTopCubic(cubics, pts);
matrix->mapPoints(pts, 4);
SkScalar topLength = approx_arc_length(pts, 4);
- patch.getBottomPoints(pts);
+ SkPatchUtils::getBottomCubic(cubics, pts);
matrix->mapPoints(pts, 4);
SkScalar bottomLength = approx_arc_length(pts, 4);
- patch.getLeftPoints(pts);
+ SkPatchUtils::getLeftCubic(cubics, pts);
matrix->mapPoints(pts, 4);
SkScalar leftLength = approx_arc_length(pts, 4);
- patch.getRightPoints(pts);
+ SkPatchUtils::getRightCubic(cubics, pts);
matrix->mapPoints(pts, 4);
SkScalar rightLength = approx_arc_length(pts, 4);
@@ -53,3 +59,167 @@ SkISize SkPatchUtils::GetLevelOfDetail(const SkPatch& patch, const SkMatrix* mat
return SkISize::Make(SkMax32(4, lodX), SkMax32(4, lodY));
}
+
+void SkPatchUtils::getTopCubic(const SkPoint cubics[12], SkPoint points[4]) {
+ if (NULL == points) {
+ return;
+ }
+ points[0] = cubics[SkPatch::kTopP0_CubicCtrlPts];
+ points[1] = cubics[SkPatch::kTopP1_CubicCtrlPts];
+ points[2] = cubics[SkPatch::kTopP2_CubicCtrlPts];
+ points[3] = cubics[SkPatch::kTopP3_CubicCtrlPts];
+}
+
+void SkPatchUtils::getBottomCubic(const SkPoint cubics[12], SkPoint points[4]) {
+ if (NULL == points) {
+ return;
+ }
+ points[0] = cubics[SkPatch::kBottomP0_CubicCtrlPts];
+ points[1] = cubics[SkPatch::kBottomP1_CubicCtrlPts];
+ points[2] = cubics[SkPatch::kBottomP2_CubicCtrlPts];
+ points[3] = cubics[SkPatch::kBottomP3_CubicCtrlPts];
+}
+
+void SkPatchUtils::getLeftCubic(const SkPoint cubics[12], SkPoint points[4]) {
+ if (NULL == points) {
+ return;
+ }
+ points[0] = cubics[SkPatch::kLeftP0_CubicCtrlPts];
+ points[1] = cubics[SkPatch::kLeftP1_CubicCtrlPts];
+ points[2] = cubics[SkPatch::kLeftP2_CubicCtrlPts];
+ points[3] = cubics[SkPatch::kLeftP3_CubicCtrlPts];
+}
+
+void SkPatchUtils::getRightCubic(const SkPoint cubics[12], SkPoint points[4]) {
+ if (NULL == points) {
+ return;
+ }
+ points[0] = cubics[SkPatch::kRightP0_CubicCtrlPts];
+ points[1] = cubics[SkPatch::kRightP1_CubicCtrlPts];
+ points[2] = cubics[SkPatch::kRightP2_CubicCtrlPts];
+ points[3] = cubics[SkPatch::kRightP3_CubicCtrlPts];
+}
+
+bool SkPatchUtils::getVertexData(SkPatch::VertexData* data, const SkPoint cubics[12],
+ const SkColor colors[4], const SkPoint texCoords[4], int lodX, int lodY) {
+ if (lodX < 1 || lodY < 1 || NULL == cubics || NULL == data) {
+ return false;
+ }
+
+ // number of indices is limited by size of uint16_t, so we clamp it to avoid overflow
+ data->fVertexCount = SkMin32((lodX + 1) * (lodY + 1), 65536);
+ lodX = SkMin32(lodX, 255);
+ lodY = SkMin32(lodY, 255);
+ data->fIndexCount = lodX * lodY * 6;
+
+ data->fPoints = SkNEW_ARRAY(SkPoint, data->fVertexCount);
+ data->fIndices = SkNEW_ARRAY(uint16_t, data->fIndexCount);
+
+ // if colors is not null then create array for colors
+ SkPMColor colorsPM[SkPatch::kNumCorners];
+ if (NULL != colors) {
+ // premultiply colors to avoid color bleeding.
+ for (int i = 0; i < SkPatch::kNumCorners; i++) {
+ colorsPM[i] = SkPreMultiplyColor(colors[i]);
+ }
+ data->fColors = SkNEW_ARRAY(uint32_t, data->fVertexCount);
+ }
+
+ // if texture coordinates are not null then create array for them
+ if (NULL != texCoords) {
+ data->fTexCoords = SkNEW_ARRAY(SkPoint, data->fVertexCount);
+ }
+
+ SkPoint pts[SkPatch::kNumPtsCubic];
+ SkPatchUtils::getBottomCubic(cubics, pts);
+ FwDCubicEvaluator fBottom(pts);
+ SkPatchUtils::getTopCubic(cubics, pts);
+ FwDCubicEvaluator fTop(pts);
+ SkPatchUtils::getLeftCubic(cubics, pts);
+ FwDCubicEvaluator fLeft(pts);
+ SkPatchUtils::getRightCubic(cubics, pts);
+ FwDCubicEvaluator fRight(pts);
+
+ fBottom.restart(lodX);
+ fTop.restart(lodX);
+
+ SkScalar u = 0.0f;
+ int stride = lodY + 1;
+ for (int x = 0; x <= lodX; x++) {
+ SkPoint bottom = fBottom.next(), top = fTop.next();
+ fLeft.restart(lodY);
+ fRight.restart(lodY);
+ SkScalar v = 0.f;
+ for (int y = 0; y <= lodY; y++) {
+ int dataIndex = x * (lodY + 1) + y;
+
+ SkPoint left = fLeft.next(), right = fRight.next();
+
+ SkPoint s0 = SkPoint::Make((1.0f - v) * top.x() + v * bottom.x(),
+ (1.0f - v) * top.y() + v * bottom.y());
+ SkPoint s1 = SkPoint::Make((1.0f - u) * left.x() + u * right.x(),
+ (1.0f - u) * left.y() + u * right.y());
+ SkPoint s2 = SkPoint::Make(
+ (1.0f - v) * ((1.0f - u) * fTop.getCtrlPoints()[0].x()
+ + u * fTop.getCtrlPoints()[3].x())
+ + v * ((1.0f - u) * fBottom.getCtrlPoints()[0].x()
+ + u * fBottom.getCtrlPoints()[3].x()),
+ (1.0f - v) * ((1.0f - u) * fTop.getCtrlPoints()[0].y()
+ + u * fTop.getCtrlPoints()[3].y())
+ + v * ((1.0f - u) * fBottom.getCtrlPoints()[0].y()
+ + u * fBottom.getCtrlPoints()[3].y()));
+ data->fPoints[dataIndex] = s0 + s1 - s2;
+
+ if (NULL != colors) {
+ uint8_t a = uint8_t(bilerp(u, v,
+ SkScalar(SkColorGetA(colorsPM[SkPatch::kTopLeft_Corner])),
+ SkScalar(SkColorGetA(colorsPM[SkPatch::kTopRight_Corner])),
+ SkScalar(SkColorGetA(colorsPM[SkPatch::kBottomLeft_Corner])),
+ SkScalar(SkColorGetA(colorsPM[SkPatch::kBottomRight_Corner]))));
+ uint8_t r = uint8_t(bilerp(u, v,
+ SkScalar(SkColorGetR(colorsPM[SkPatch::kTopLeft_Corner])),
+ SkScalar(SkColorGetR(colorsPM[SkPatch::kTopRight_Corner])),
+ SkScalar(SkColorGetR(colorsPM[SkPatch::kBottomLeft_Corner])),
+ SkScalar(SkColorGetR(colorsPM[SkPatch::kBottomRight_Corner]))));
+ uint8_t g = uint8_t(bilerp(u, v,
+ SkScalar(SkColorGetG(colorsPM[SkPatch::kTopLeft_Corner])),
+ SkScalar(SkColorGetG(colorsPM[SkPatch::kTopRight_Corner])),
+ SkScalar(SkColorGetG(colorsPM[SkPatch::kBottomLeft_Corner])),
+ SkScalar(SkColorGetG(colorsPM[SkPatch::kBottomRight_Corner]))));
+ uint8_t b = uint8_t(bilerp(u, v,
+ SkScalar(SkColorGetB(colorsPM[SkPatch::kTopLeft_Corner])),
+ SkScalar(SkColorGetB(colorsPM[SkPatch::kTopRight_Corner])),
+ SkScalar(SkColorGetB(colorsPM[SkPatch::kBottomLeft_Corner])),
+ SkScalar(SkColorGetB(colorsPM[SkPatch::kBottomRight_Corner]))));
+ data->fColors[dataIndex] = SkPackARGB32(a,r,g,b);
+ }
+
+ if (NULL != texCoords) {
+ data->fTexCoords[dataIndex] = SkPoint::Make(
+ bilerp(u, v, texCoords[SkPatch::kTopLeft_Corner].x(),
+ texCoords[SkPatch::kTopRight_Corner].x(),
+ texCoords[SkPatch::kBottomLeft_Corner].x(),
+ texCoords[SkPatch::kBottomRight_Corner].x()),
+ bilerp(u, v, texCoords[SkPatch::kTopLeft_Corner].y(),
+ texCoords[SkPatch::kTopRight_Corner].y(),
+ texCoords[SkPatch::kBottomLeft_Corner].y(),
+ texCoords[SkPatch::kBottomRight_Corner].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;
+ data->fIndices[i + 3] = data->fIndices[i];
+ data->fIndices[i + 4] = data->fIndices[i + 2];
+ data->fIndices[i + 5] = (x + 1) * stride + y;
+ }
+ v = SkScalarClampMax(v + 1.f / lodY, 1);
+ }
+ u = SkScalarClampMax(u + 1.f / lodX, 1);
+ }
+ return true;
+
+}

Powered by Google App Engine
This is Rietveld 408576698