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

Side by Side Diff: ui/gfx/transform_util.cc

Issue 23043011: cc: Use SkMScalar instead of doubles everywhere in cc (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: danakj review Created 7 years, 3 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 | Annotate | Revision Log
« no previous file with comments | « ui/gfx/transform_util.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/gfx/transform_util.h" 5 #include "ui/gfx/transform_util.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 8
9 #include "ui/gfx/point.h" 9 #include "ui/gfx/point.h"
10 10
11 namespace gfx { 11 namespace gfx {
12 12
13 namespace { 13 namespace {
14 14
15 double Length3(double v[3]) { 15 SkMScalar Length3(SkMScalar v[3]) {
16 return std::sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); 16 return std::sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
17 } 17 }
18 18
19 void Scale3(double v[3], double scale) { 19 void Scale3(SkMScalar v[3], SkMScalar scale) {
20 for (int i = 0; i < 3; ++i) 20 for (int i = 0; i < 3; ++i)
21 v[i] *= scale; 21 v[i] *= scale;
22 } 22 }
23 23
24 template <int n> 24 template <int n>
25 double Dot(const double* a, const double* b) { 25 SkMScalar Dot(const SkMScalar* a, const SkMScalar* b) {
26 double toReturn = 0; 26 SkMScalar toReturn = 0;
27 for (int i = 0; i < n; ++i) 27 for (int i = 0; i < n; ++i)
28 toReturn += a[i] * b[i]; 28 toReturn += a[i] * b[i];
29 return toReturn; 29 return toReturn;
30 } 30 }
31 31
32 template <int n> 32 template <int n>
33 void Combine(double* out, 33 void Combine(SkMScalar* out,
34 const double* a, 34 const SkMScalar* a,
35 const double* b, 35 const SkMScalar* b,
36 double scale_a, 36 SkMScalar scale_a,
37 double scale_b) { 37 SkMScalar scale_b) {
38 for (int i = 0; i < n; ++i) 38 for (int i = 0; i < n; ++i)
39 out[i] = a[i] * scale_a + b[i] * scale_b; 39 out[i] = a[i] * scale_a + b[i] * scale_b;
40 } 40 }
41 41
42 void Cross3(double out[3], double a[3], double b[3]) { 42 void Cross3(SkMScalar out[3], SkMScalar a[3], SkMScalar b[3]) {
43 double x = a[1] * b[2] - a[2] * b[1]; 43 SkMScalar x = a[1] * b[2] - a[2] * b[1];
44 double y = a[2] * b[0] - a[0] * b[2]; 44 SkMScalar y = a[2] * b[0] - a[0] * b[2];
45 double z = a[0] * b[1] - a[1] * b[0]; 45 SkMScalar z = a[0] * b[1] - a[1] * b[0];
46 out[0] = x; 46 out[0] = x;
47 out[1] = y; 47 out[1] = y;
48 out[2] = z; 48 out[2] = z;
49 } 49 }
50 50
51 // Taken from http://www.w3.org/TR/css3-transforms/. 51 // Taken from http://www.w3.org/TR/css3-transforms/.
52 bool Slerp(double out[4], 52 bool Slerp(SkMScalar out[4],
53 const double q1[4], 53 const SkMScalar q1[4],
54 const double q2[4], 54 const SkMScalar q2[4],
55 double progress) { 55 SkMScalar progress) {
56 double product = Dot<4>(q1, q2); 56 SkMScalar product = Dot<4>(q1, q2);
57 57
58 // Clamp product to -1.0 <= product <= 1.0. 58 // Clamp product to -1.0 <= product <= 1.0.
59 product = std::min(std::max(product, -1.0), 1.0); 59 product = std::min(std::max(product, -SK_MScalar1), SK_MScalar1);
60 60
61 // Interpolate angles along the shortest path. For example, to interpolate 61 // Interpolate angles along the shortest path. For example, to interpolate
62 // between a 175 degree angle and a 185 degree angle, interpolate along the 62 // between a 175 degree angle and a 185 degree angle, interpolate along the
63 // 10 degree path from 175 to 185, rather than along the 350 degree path in 63 // 10 degree path from 175 to 185, rather than along the 350 degree path in
64 // the opposite direction. This matches WebKit's implementation but not 64 // the opposite direction. This matches WebKit's implementation but not
65 // the current W3C spec. Fixing the spec to match this approach is discussed 65 // the current W3C spec. Fixing the spec to match this approach is discussed
66 // at: 66 // at:
67 // http://lists.w3.org/Archives/Public/www-style/2013May/0131.html 67 // http://lists.w3.org/Archives/Public/www-style/2013May/0131.html
68 double scale1 = 1.0; 68 SkMScalar scale1 = SK_MScalar1;
69 if (product < 0) { 69 if (product < 0) {
70 product = -product; 70 product = -product;
71 scale1 = -1.0; 71 scale1 = -SK_MScalar1;
72 } 72 }
73 73
74 const double epsilon = 1e-5; 74 const SkMScalar epsilon = 1e-5;
75 if (std::abs(product - 1.0) < epsilon) { 75 if (std::abs(product - SK_MScalar1) < epsilon) {
76 for (int i = 0; i < 4; ++i) 76 for (int i = 0; i < 4; ++i)
77 out[i] = q1[i]; 77 out[i] = q1[i];
78 return true; 78 return true;
79 } 79 }
80 80
81 double denom = std::sqrt(1 - product * product); 81 SkMScalar denom = std::sqrt(1 - product * product);
82 double theta = std::acos(product); 82 SkMScalar theta = std::acos(product);
83 double w = std::sin(progress * theta) * (1 / denom); 83 SkMScalar w = std::sin(progress * theta) * (1 / denom);
84 84
85 scale1 *= std::cos(progress * theta) - product * w; 85 scale1 *= std::cos(progress * theta) - product * w;
86 double scale2 = w; 86 SkMScalar scale2 = w;
87 Combine<4>(out, q1, q2, scale1, scale2); 87 Combine<4>(out, q1, q2, scale1, scale2);
88 88
89 return true; 89 return true;
90 } 90 }
91 91
92 // Returns false if the matrix cannot be normalized. 92 // Returns false if the matrix cannot be normalized.
93 bool Normalize(SkMatrix44& m) { 93 bool Normalize(SkMatrix44& m) {
94 if (m.getDouble(3, 3) == 0.0) 94 if (m.get(3, 3) == 0.0)
95 // Cannot normalize. 95 // Cannot normalize.
96 return false; 96 return false;
97 97
98 double scale = 1.0 / m.getDouble(3, 3); 98 SkMScalar scale = 1.0 / m.get(3, 3);
99 for (int i = 0; i < 4; i++) 99 for (int i = 0; i < 4; i++)
100 for (int j = 0; j < 4; j++) 100 for (int j = 0; j < 4; j++)
101 m.setDouble(i, j, m.getDouble(i, j) * scale); 101 m.set(i, j, m.get(i, j) * scale);
102 102
103 return true; 103 return true;
104 } 104 }
105 105
106 } // namespace 106 } // namespace
107 107
108 Transform GetScaleTransform(const Point& anchor, float scale) { 108 Transform GetScaleTransform(const Point& anchor, float scale) {
109 Transform transform; 109 Transform transform;
110 transform.Translate(anchor.x() * (1 - scale), 110 transform.Translate(anchor.x() * (1 - scale),
111 anchor.y() * (1 - scale)); 111 anchor.y() * (1 - scale));
112 transform.Scale(scale, scale); 112 transform.Scale(scale, scale);
113 return transform; 113 return transform;
114 } 114 }
115 115
116 DecomposedTransform::DecomposedTransform() { 116 DecomposedTransform::DecomposedTransform() {
117 translate[0] = translate[1] = translate[2] = 0.0; 117 translate[0] = translate[1] = translate[2] = 0.0;
118 scale[0] = scale[1] = scale[2] = 1.0; 118 scale[0] = scale[1] = scale[2] = 1.0;
119 skew[0] = skew[1] = skew[2] = 0.0; 119 skew[0] = skew[1] = skew[2] = 0.0;
120 perspective[0] = perspective[1] = perspective[2] = 0.0; 120 perspective[0] = perspective[1] = perspective[2] = 0.0;
121 quaternion[0] = quaternion[1] = quaternion[2] = 0.0; 121 quaternion[0] = quaternion[1] = quaternion[2] = 0.0;
122 perspective[3] = quaternion[3] = 1.0; 122 perspective[3] = quaternion[3] = 1.0;
123 } 123 }
124 124
125 bool BlendDecomposedTransforms(DecomposedTransform* out, 125 bool BlendDecomposedTransforms(DecomposedTransform* out,
126 const DecomposedTransform& to, 126 const DecomposedTransform& to,
127 const DecomposedTransform& from, 127 const DecomposedTransform& from,
128 double progress) { 128 SkMScalar progress) {
129 double scalea = progress; 129 SkMScalar scalea = progress;
130 double scaleb = 1.0 - progress; 130 SkMScalar scaleb = SK_MScalar1 - progress;
131 Combine<3>(out->translate, to.translate, from.translate, scalea, scaleb); 131 Combine<3>(out->translate, to.translate, from.translate, scalea, scaleb);
132 Combine<3>(out->scale, to.scale, from.scale, scalea, scaleb); 132 Combine<3>(out->scale, to.scale, from.scale, scalea, scaleb);
133 Combine<3>(out->skew, to.skew, from.skew, scalea, scaleb); 133 Combine<3>(out->skew, to.skew, from.skew, scalea, scaleb);
134 Combine<4>( 134 Combine<4>(
135 out->perspective, to.perspective, from.perspective, scalea, scaleb); 135 out->perspective, to.perspective, from.perspective, scalea, scaleb);
136 return Slerp(out->quaternion, from.quaternion, to.quaternion, progress); 136 return Slerp(out->quaternion, from.quaternion, to.quaternion, progress);
137 } 137 }
138 138
139 // Taken from http://www.w3.org/TR/css3-transforms/. 139 // Taken from http://www.w3.org/TR/css3-transforms/.
140 bool DecomposeTransform(DecomposedTransform* decomp, 140 bool DecomposeTransform(DecomposedTransform* decomp,
141 const Transform& transform) { 141 const Transform& transform) {
142 if (!decomp) 142 if (!decomp)
143 return false; 143 return false;
144 144
145 // We'll operate on a copy of the matrix. 145 // We'll operate on a copy of the matrix.
146 SkMatrix44 matrix = transform.matrix(); 146 SkMatrix44 matrix = transform.matrix();
147 147
148 // If we cannot normalize the matrix, then bail early as we cannot decompose. 148 // If we cannot normalize the matrix, then bail early as we cannot decompose.
149 if (!Normalize(matrix)) 149 if (!Normalize(matrix))
150 return false; 150 return false;
151 151
152 SkMatrix44 perspectiveMatrix = matrix; 152 SkMatrix44 perspectiveMatrix = matrix;
153 153
154 for (int i = 0; i < 3; ++i) 154 for (int i = 0; i < 3; ++i)
155 perspectiveMatrix.setDouble(3, i, 0.0); 155 perspectiveMatrix.set(3, i, 0.0);
156 156
157 perspectiveMatrix.setDouble(3, 3, 1.0); 157 perspectiveMatrix.set(3, 3, 1.0);
158 158
159 // If the perspective matrix is not invertible, we are also unable to 159 // If the perspective matrix is not invertible, we are also unable to
160 // decompose, so we'll bail early. Constant taken from SkMatrix44::invert. 160 // decompose, so we'll bail early. Constant taken from SkMatrix44::invert.
161 if (std::abs(perspectiveMatrix.determinant()) < 1e-8) 161 if (std::abs(perspectiveMatrix.determinant()) < 1e-8)
162 return false; 162 return false;
163 163
164 if (matrix.getDouble(3, 0) != 0.0 || 164 if (matrix.get(3, 0) != 0.0 || matrix.get(3, 1) != 0.0 ||
165 matrix.getDouble(3, 1) != 0.0 || 165 matrix.get(3, 2) != 0.0) {
166 matrix.getDouble(3, 2) != 0.0) {
167 // rhs is the right hand side of the equation. 166 // rhs is the right hand side of the equation.
168 SkMScalar rhs[4] = { 167 SkMScalar rhs[4] = {
169 matrix.get(3, 0), 168 matrix.get(3, 0),
170 matrix.get(3, 1), 169 matrix.get(3, 1),
171 matrix.get(3, 2), 170 matrix.get(3, 2),
172 matrix.get(3, 3) 171 matrix.get(3, 3)
173 }; 172 };
174 173
175 // Solve the equation by inverting perspectiveMatrix and multiplying 174 // Solve the equation by inverting perspectiveMatrix and multiplying
176 // rhs by the inverse. 175 // rhs by the inverse.
(...skipping 11 matching lines...) Expand all
188 decomp->perspective[i] = rhs[i]; 187 decomp->perspective[i] = rhs[i];
189 188
190 } else { 189 } else {
191 // No perspective. 190 // No perspective.
192 for (int i = 0; i < 3; ++i) 191 for (int i = 0; i < 3; ++i)
193 decomp->perspective[i] = 0.0; 192 decomp->perspective[i] = 0.0;
194 decomp->perspective[3] = 1.0; 193 decomp->perspective[3] = 1.0;
195 } 194 }
196 195
197 for (int i = 0; i < 3; i++) 196 for (int i = 0; i < 3; i++)
198 decomp->translate[i] = matrix.getDouble(i, 3); 197 decomp->translate[i] = matrix.get(i, 3);
199 198
200 double row[3][3]; 199 SkMScalar row[3][3];
201 for (int i = 0; i < 3; i++) 200 for (int i = 0; i < 3; i++)
202 for (int j = 0; j < 3; ++j) 201 for (int j = 0; j < 3; ++j)
203 row[i][j] = matrix.getDouble(j, i); 202 row[i][j] = matrix.get(j, i);
204 203
205 // Compute X scale factor and normalize first row. 204 // Compute X scale factor and normalize first row.
206 decomp->scale[0] = Length3(row[0]); 205 decomp->scale[0] = Length3(row[0]);
207 if (decomp->scale[0] != 0.0) 206 if (decomp->scale[0] != 0.0)
208 Scale3(row[0], 1.0 / decomp->scale[0]); 207 Scale3(row[0], 1.0 / decomp->scale[0]);
209 208
210 // Compute XY shear factor and make 2nd row orthogonal to 1st. 209 // Compute XY shear factor and make 2nd row orthogonal to 1st.
211 decomp->skew[0] = Dot<3>(row[0], row[1]); 210 decomp->skew[0] = Dot<3>(row[0], row[1]);
212 Combine<3>(row[1], row[1], row[0], 1.0, -decomp->skew[0]); 211 Combine<3>(row[1], row[1], row[0], 1.0, -decomp->skew[0]);
213 212
(...skipping 14 matching lines...) Expand all
228 decomp->scale[2] = Length3(row[2]); 227 decomp->scale[2] = Length3(row[2]);
229 if (decomp->scale[2] != 0.0) 228 if (decomp->scale[2] != 0.0)
230 Scale3(row[2], 1.0 / decomp->scale[2]); 229 Scale3(row[2], 1.0 / decomp->scale[2]);
231 230
232 decomp->skew[1] /= decomp->scale[2]; 231 decomp->skew[1] /= decomp->scale[2];
233 decomp->skew[2] /= decomp->scale[2]; 232 decomp->skew[2] /= decomp->scale[2];
234 233
235 // At this point, the matrix (in rows) is orthonormal. 234 // At this point, the matrix (in rows) is orthonormal.
236 // Check for a coordinate system flip. If the determinant 235 // Check for a coordinate system flip. If the determinant
237 // is -1, then negate the matrix and the scaling factors. 236 // is -1, then negate the matrix and the scaling factors.
238 double pdum3[3]; 237 SkMScalar pdum3[3];
239 Cross3(pdum3, row[1], row[2]); 238 Cross3(pdum3, row[1], row[2]);
240 if (Dot<3>(row[0], pdum3) < 0) { 239 if (Dot<3>(row[0], pdum3) < 0) {
241 for (int i = 0; i < 3; i++) { 240 for (int i = 0; i < 3; i++) {
242 decomp->scale[i] *= -1.0; 241 decomp->scale[i] *= -1.0;
243 for (int j = 0; j < 3; ++j) 242 for (int j = 0; j < 3; ++j)
244 row[i][j] *= -1.0; 243 row[i][j] *= -1.0;
245 } 244 }
246 } 245 }
247 246
248 decomp->quaternion[0] = 247 decomp->quaternion[0] =
(...skipping 12 matching lines...) Expand all
261 if (row[1][0] > row[0][1]) 260 if (row[1][0] > row[0][1])
262 decomp->quaternion[2] = -decomp->quaternion[2]; 261 decomp->quaternion[2] = -decomp->quaternion[2];
263 262
264 return true; 263 return true;
265 } 264 }
266 265
267 // Taken from http://www.w3.org/TR/css3-transforms/. 266 // Taken from http://www.w3.org/TR/css3-transforms/.
268 Transform ComposeTransform(const DecomposedTransform& decomp) { 267 Transform ComposeTransform(const DecomposedTransform& decomp) {
269 SkMatrix44 matrix(SkMatrix44::kIdentity_Constructor); 268 SkMatrix44 matrix(SkMatrix44::kIdentity_Constructor);
270 for (int i = 0; i < 4; i++) 269 for (int i = 0; i < 4; i++)
271 matrix.setDouble(3, i, decomp.perspective[i]); 270 matrix.set(3, i, decomp.perspective[i]);
272 271
273 matrix.preTranslate(SkDoubleToMScalar(decomp.translate[0]), 272 matrix.preTranslate(
274 SkDoubleToMScalar(decomp.translate[1]), 273 decomp.translate[0], decomp.translate[1], decomp.translate[2]);
275 SkDoubleToMScalar(decomp.translate[2]));
276 274
277 double x = decomp.quaternion[0]; 275 SkMScalar x = decomp.quaternion[0];
278 double y = decomp.quaternion[1]; 276 SkMScalar y = decomp.quaternion[1];
279 double z = decomp.quaternion[2]; 277 SkMScalar z = decomp.quaternion[2];
280 double w = decomp.quaternion[3]; 278 SkMScalar w = decomp.quaternion[3];
281 279
282 SkMatrix44 rotation_matrix(SkMatrix44::kUninitialized_Constructor); 280 SkMatrix44 rotation_matrix(SkMatrix44::kUninitialized_Constructor);
283 rotation_matrix.set3x3(1.0 - 2.0 * (y * y + z * z), 281 rotation_matrix.set3x3(1.0 - 2.0 * (y * y + z * z),
284 2.0 * (x * y + z * w), 282 2.0 * (x * y + z * w),
285 2.0 * (x * z - y * w), 283 2.0 * (x * z - y * w),
286 2.0 * (x * y - z * w), 284 2.0 * (x * y - z * w),
287 1.0 - 2.0 * (x * x + z * z), 285 1.0 - 2.0 * (x * x + z * z),
288 2.0 * (y * z + x * w), 286 2.0 * (y * z + x * w),
289 2.0 * (x * z + y * w), 287 2.0 * (x * z + y * w),
290 2.0 * (y * z - x * w), 288 2.0 * (y * z - x * w),
291 1.0 - 2.0 * (x * x + y * y)); 289 1.0 - 2.0 * (x * x + y * y));
292 290
293 matrix.preConcat(rotation_matrix); 291 matrix.preConcat(rotation_matrix);
294 292
295 SkMatrix44 temp(SkMatrix44::kIdentity_Constructor); 293 SkMatrix44 temp(SkMatrix44::kIdentity_Constructor);
296 if (decomp.skew[2]) { 294 if (decomp.skew[2]) {
297 temp.setDouble(1, 2, decomp.skew[2]); 295 temp.set(1, 2, decomp.skew[2]);
298 matrix.preConcat(temp); 296 matrix.preConcat(temp);
299 } 297 }
300 298
301 if (decomp.skew[1]) { 299 if (decomp.skew[1]) {
302 temp.setDouble(1, 2, 0); 300 temp.set(1, 2, 0);
303 temp.setDouble(0, 2, decomp.skew[1]); 301 temp.set(0, 2, decomp.skew[1]);
304 matrix.preConcat(temp); 302 matrix.preConcat(temp);
305 } 303 }
306 304
307 if (decomp.skew[0]) { 305 if (decomp.skew[0]) {
308 temp.setDouble(0, 2, 0); 306 temp.set(0, 2, 0);
309 temp.setDouble(0, 1, decomp.skew[0]); 307 temp.set(0, 1, decomp.skew[0]);
310 matrix.preConcat(temp); 308 matrix.preConcat(temp);
311 } 309 }
312 310
313 matrix.preScale(SkDoubleToMScalar(decomp.scale[0]), 311 matrix.preScale(decomp.scale[0], decomp.scale[1], decomp.scale[2]);
314 SkDoubleToMScalar(decomp.scale[1]),
315 SkDoubleToMScalar(decomp.scale[2]));
316 312
317 Transform to_return; 313 Transform to_return;
318 to_return.matrix() = matrix; 314 to_return.matrix() = matrix;
319 return to_return; 315 return to_return;
320 } 316 }
321 317
322 } // namespace ui 318 } // namespace ui
OLDNEW
« no previous file with comments | « ui/gfx/transform_util.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698