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

Side by Side 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2014 Google Inc. 2 * Copyright 2014 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkPatchUtils.h" 8 #include "SkPatchUtils.h"
9 9
10 #include "SkColorPriv.h"
11
10 // size in pixels of each partition per axis, adjust this knob 12 // size in pixels of each partition per axis, adjust this knob
11 static const int kPartitionSize = 15; 13 static const int kPartitionSize = 15;
12 14
13 /** 15 /**
14 * Calculate the approximate arc length given a bezier curve's control points. 16 * Calculate the approximate arc length given a bezier curve's control points.
15 */ 17 */
16 static SkScalar approx_arc_length(SkPoint* points, int count) { 18 static SkScalar approx_arc_length(SkPoint* points, int count) {
17 if (count < 2) { 19 if (count < 2) {
18 return 0; 20 return 0;
19 } 21 }
20 SkScalar arcLength = 0; 22 SkScalar arcLength = 0;
21 for (int i = 0; i < count - 1; i++) { 23 for (int i = 0; i < count - 1; i++) {
22 arcLength += SkPoint::Distance(points[i], points[i + 1]); 24 arcLength += SkPoint::Distance(points[i], points[i + 1]);
23 } 25 }
24 return arcLength; 26 return arcLength;
25 } 27 }
26 28
27 SkISize SkPatchUtils::GetLevelOfDetail(const SkPatch& patch, const SkMatrix* mat rix) { 29 static SkScalar bilerp(SkScalar tx, SkScalar ty, SkScalar c00, SkScalar c10, SkS calar c01,
28 30 SkScalar c11) {
29 SkPoint mapPts[12]; 31 SkScalar a = c00 * (1.f - tx) + c10 * tx;
30 matrix->mapPoints(mapPts, patch.getControlPoints(), 12); 32 SkScalar b = c01 * (1.f - tx) + c11 * tx;
33 return a * (1.f - ty) + b * ty;
34 }
35
36 SkISize SkPatchUtils::GetLevelOfDetail(const SkPoint cubics[12], const SkMatrix* matrix) {
31 37
32 // Approximate length of each cubic. 38 // Approximate length of each cubic.
33 SkPoint pts[4]; 39 SkPoint pts[4];
34 patch.getTopPoints(pts); 40 SkPatchUtils::getTopCubic(cubics, pts);
35 matrix->mapPoints(pts, 4); 41 matrix->mapPoints(pts, 4);
36 SkScalar topLength = approx_arc_length(pts, 4); 42 SkScalar topLength = approx_arc_length(pts, 4);
37 43
38 patch.getBottomPoints(pts); 44 SkPatchUtils::getBottomCubic(cubics, pts);
39 matrix->mapPoints(pts, 4); 45 matrix->mapPoints(pts, 4);
40 SkScalar bottomLength = approx_arc_length(pts, 4); 46 SkScalar bottomLength = approx_arc_length(pts, 4);
41 47
42 patch.getLeftPoints(pts); 48 SkPatchUtils::getLeftCubic(cubics, pts);
43 matrix->mapPoints(pts, 4); 49 matrix->mapPoints(pts, 4);
44 SkScalar leftLength = approx_arc_length(pts, 4); 50 SkScalar leftLength = approx_arc_length(pts, 4);
45 51
46 patch.getRightPoints(pts); 52 SkPatchUtils::getRightCubic(cubics, pts);
47 matrix->mapPoints(pts, 4); 53 matrix->mapPoints(pts, 4);
48 SkScalar rightLength = approx_arc_length(pts, 4); 54 SkScalar rightLength = approx_arc_length(pts, 4);
49 55
50 // Level of detail per axis, based on the larger side between top and bottom or left and right 56 // Level of detail per axis, based on the larger side between top and bottom or left and right
51 int lodX = static_cast<int>(SkMaxScalar(topLength, bottomLength) / kPartitio nSize); 57 int lodX = static_cast<int>(SkMaxScalar(topLength, bottomLength) / kPartitio nSize);
52 int lodY = static_cast<int>(SkMaxScalar(leftLength, rightLength) / kPartitio nSize); 58 int lodY = static_cast<int>(SkMaxScalar(leftLength, rightLength) / kPartitio nSize);
53 59
54 return SkISize::Make(SkMax32(4, lodX), SkMax32(4, lodY)); 60 return SkISize::Make(SkMax32(4, lodX), SkMax32(4, lodY));
55 } 61 }
62
63 void SkPatchUtils::getTopCubic(const SkPoint cubics[12], SkPoint points[4]) {
64 if (NULL == points) {
65 return;
66 }
67 points[0] = cubics[SkPatch::kTopP0_CubicCtrlPts];
68 points[1] = cubics[SkPatch::kTopP1_CubicCtrlPts];
69 points[2] = cubics[SkPatch::kTopP2_CubicCtrlPts];
70 points[3] = cubics[SkPatch::kTopP3_CubicCtrlPts];
71 }
72
73 void SkPatchUtils::getBottomCubic(const SkPoint cubics[12], SkPoint points[4]) {
74 if (NULL == points) {
75 return;
76 }
77 points[0] = cubics[SkPatch::kBottomP0_CubicCtrlPts];
78 points[1] = cubics[SkPatch::kBottomP1_CubicCtrlPts];
79 points[2] = cubics[SkPatch::kBottomP2_CubicCtrlPts];
80 points[3] = cubics[SkPatch::kBottomP3_CubicCtrlPts];
81 }
82
83 void SkPatchUtils::getLeftCubic(const SkPoint cubics[12], SkPoint points[4]) {
84 if (NULL == points) {
85 return;
86 }
87 points[0] = cubics[SkPatch::kLeftP0_CubicCtrlPts];
88 points[1] = cubics[SkPatch::kLeftP1_CubicCtrlPts];
89 points[2] = cubics[SkPatch::kLeftP2_CubicCtrlPts];
90 points[3] = cubics[SkPatch::kLeftP3_CubicCtrlPts];
91 }
92
93 void SkPatchUtils::getRightCubic(const SkPoint cubics[12], SkPoint points[4]) {
94 if (NULL == points) {
95 return;
96 }
97 points[0] = cubics[SkPatch::kRightP0_CubicCtrlPts];
98 points[1] = cubics[SkPatch::kRightP1_CubicCtrlPts];
99 points[2] = cubics[SkPatch::kRightP2_CubicCtrlPts];
100 points[3] = cubics[SkPatch::kRightP3_CubicCtrlPts];
101 }
102
103 bool SkPatchUtils::getVertexData(SkPatch::VertexData* data, const SkPoint cubics [12],
104 const SkColor colors[4], const SkPoint texCoords[4], int lodX , int lodY) {
105 if (lodX < 1 || lodY < 1 || NULL == cubics || NULL == data) {
106 return false;
107 }
108
109 // number of indices is limited by size of uint16_t, so we clamp it to avoid overflow
110 data->fVertexCount = SkMin32((lodX + 1) * (lodY + 1), 65536);
111 lodX = SkMin32(lodX, 255);
112 lodY = SkMin32(lodY, 255);
113 data->fIndexCount = lodX * lodY * 6;
114
115 data->fPoints = SkNEW_ARRAY(SkPoint, data->fVertexCount);
116 data->fIndices = SkNEW_ARRAY(uint16_t, data->fIndexCount);
117
118 // if colors is not null then create array for colors
119 SkPMColor colorsPM[SkPatch::kNumCorners];
120 if (NULL != colors) {
121 // premultiply colors to avoid color bleeding.
122 for (int i = 0; i < SkPatch::kNumCorners; i++) {
123 colorsPM[i] = SkPreMultiplyColor(colors[i]);
124 }
125 data->fColors = SkNEW_ARRAY(uint32_t, data->fVertexCount);
126 }
127
128 // if texture coordinates are not null then create array for them
129 if (NULL != texCoords) {
130 data->fTexCoords = SkNEW_ARRAY(SkPoint, data->fVertexCount);
131 }
132
133 SkPoint pts[SkPatch::kNumPtsCubic];
134 SkPatchUtils::getBottomCubic(cubics, pts);
135 FwDCubicEvaluator fBottom(pts);
136 SkPatchUtils::getTopCubic(cubics, pts);
137 FwDCubicEvaluator fTop(pts);
138 SkPatchUtils::getLeftCubic(cubics, pts);
139 FwDCubicEvaluator fLeft(pts);
140 SkPatchUtils::getRightCubic(cubics, pts);
141 FwDCubicEvaluator fRight(pts);
142
143 fBottom.restart(lodX);
144 fTop.restart(lodX);
145
146 SkScalar u = 0.0f;
147 int stride = lodY + 1;
148 for (int x = 0; x <= lodX; x++) {
149 SkPoint bottom = fBottom.next(), top = fTop.next();
150 fLeft.restart(lodY);
151 fRight.restart(lodY);
152 SkScalar v = 0.f;
153 for (int y = 0; y <= lodY; y++) {
154 int dataIndex = x * (lodY + 1) + y;
155
156 SkPoint left = fLeft.next(), right = fRight.next();
157
158 SkPoint s0 = SkPoint::Make((1.0f - v) * top.x() + v * bottom.x(),
159 (1.0f - v) * top.y() + v * bottom.y());
160 SkPoint s1 = SkPoint::Make((1.0f - u) * left.x() + u * right.x(),
161 (1.0f - u) * left.y() + u * right.y());
162 SkPoint s2 = SkPoint::Make(
163 (1.0f - v) * ((1.0f - u) * fTop.getCtrlPo ints()[0].x()
164 + u * fTop.getCtrlPoints()[ 3].x())
165 + v * ((1.0f - u) * fBottom.getCtrlPoints ()[0].x()
166 + u * fBottom.getCtrlPoints()[3].x ()),
167 (1.0f - v) * ((1.0f - u) * fTop.getCtrlPo ints()[0].y()
168 + u * fTop.getCtrlPoints()[ 3].y())
169 + v * ((1.0f - u) * fBottom.getCtrlPoints ()[0].y()
170 + u * fBottom.getCtrlPoints()[3].y ()));
171 data->fPoints[dataIndex] = s0 + s1 - s2;
172
173 if (NULL != colors) {
174 uint8_t a = uint8_t(bilerp(u, v,
175 SkScalar(SkColorGetA(colorsPM[SkPatch::kTopLe ft_Corner])),
176 SkScalar(SkColorGetA(colorsPM[SkPatch::kTopRi ght_Corner])),
177 SkScalar(SkColorGetA(colorsPM[SkPatch::kBotto mLeft_Corner])),
178 SkScalar(SkColorGetA(colorsPM[SkPatch::kBotto mRight_Corner]))));
179 uint8_t r = uint8_t(bilerp(u, v,
180 SkScalar(SkColorGetR(colorsPM[SkPatch::kTopLe ft_Corner])),
181 SkScalar(SkColorGetR(colorsPM[SkPatch::kTopRi ght_Corner])),
182 SkScalar(SkColorGetR(colorsPM[SkPatch::kBotto mLeft_Corner])),
183 SkScalar(SkColorGetR(colorsPM[SkPatch::kBotto mRight_Corner]))));
184 uint8_t g = uint8_t(bilerp(u, v,
185 SkScalar(SkColorGetG(colorsPM[SkPatch::kTopLe ft_Corner])),
186 SkScalar(SkColorGetG(colorsPM[SkPatch::kTopRi ght_Corner])),
187 SkScalar(SkColorGetG(colorsPM[SkPatch::kBotto mLeft_Corner])),
188 SkScalar(SkColorGetG(colorsPM[SkPatch::kBotto mRight_Corner]))));
189 uint8_t b = uint8_t(bilerp(u, v,
190 SkScalar(SkColorGetB(colorsPM[SkPatch::kTopLe ft_Corner])),
191 SkScalar(SkColorGetB(colorsPM[SkPatch::kTopRi ght_Corner])),
192 SkScalar(SkColorGetB(colorsPM[SkPatch::kBotto mLeft_Corner])),
193 SkScalar(SkColorGetB(colorsPM[SkPatch::kBotto mRight_Corner]))));
194 data->fColors[dataIndex] = SkPackARGB32(a,r,g,b);
195 }
196
197 if (NULL != texCoords) {
198 data->fTexCoords[dataIndex] = SkPoint::Make(
199 bilerp(u, v, texCoords[SkPatch::kTop Left_Corner].x(),
200 texCoords[SkPatch::kTopRight_ Corner].x(),
201 texCoords[SkPatch::kBottomLef t_Corner].x(),
202 texCoords[SkPatch::kBottomRig ht_Corner].x()),
203 bilerp(u, v, texCoords[SkPatch::kTop Left_Corner].y(),
204 texCoords[SkPatch::kTopRight_ Corner].y(),
205 texCoords[SkPatch::kBottomLef t_Corner].y(),
206 texCoords[SkPatch::kBottomRig ht_Corner].y()));
207
208 }
209
210 if(x < lodX && y < lodY) {
211 int i = 6 * (x * lodY + y);
212 data->fIndices[i] = x * stride + y;
213 data->fIndices[i + 1] = x * stride + 1 + y;
214 data->fIndices[i + 2] = (x + 1) * stride + 1 + y;
215 data->fIndices[i + 3] = data->fIndices[i];
216 data->fIndices[i + 4] = data->fIndices[i + 2];
217 data->fIndices[i + 5] = (x + 1) * stride + y;
218 }
219 v = SkScalarClampMax(v + 1.f / lodY, 1);
220 }
221 u = SkScalarClampMax(u + 1.f / lodX, 1);
222 }
223 return true;
224
225 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698