OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 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 "SkMath.h" | 8 #include "SkMath.h" |
9 #include "SkMatrix.h" | 9 #include "SkMatrix.h" |
10 #include "SkMatrixUtils.h" | 10 #include "SkMatrixUtils.h" |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 } | 238 } |
239 if (min > d) { | 239 if (min > d) { |
240 min = d; | 240 min = d; |
241 } | 241 } |
242 } | 242 } |
243 REPORTER_ASSERT(reporter, SkScalarDiv(max, maxScale) >= gCloseScaleTol); | 243 REPORTER_ASSERT(reporter, SkScalarDiv(max, maxScale) >= gCloseScaleTol); |
244 REPORTER_ASSERT(reporter, SkScalarDiv(minScale, min) >= gCloseScaleTol); | 244 REPORTER_ASSERT(reporter, SkScalarDiv(minScale, min) >= gCloseScaleTol); |
245 } | 245 } |
246 } | 246 } |
247 | 247 |
248 static void test_matrix_is_similarity(skiatest::Reporter* reporter) { | 248 static void test_matrix_preserve_shape(skiatest::Reporter* reporter) { |
249 SkMatrix mat; | 249 SkMatrix mat; |
250 | 250 |
251 // identity | 251 // identity |
252 mat.setIdentity(); | 252 mat.setIdentity(); |
253 REPORTER_ASSERT(reporter, mat.isSimilarity()); | 253 REPORTER_ASSERT(reporter, mat.isSimilarity()); |
| 254 REPORTER_ASSERT(reporter, mat.preservesRightAngles()); |
254 | 255 |
255 // translation only | 256 // translation only |
256 mat.reset(); | 257 mat.reset(); |
257 mat.setTranslate(SkIntToScalar(100), SkIntToScalar(100)); | 258 mat.setTranslate(SkIntToScalar(100), SkIntToScalar(100)); |
258 REPORTER_ASSERT(reporter, mat.isSimilarity()); | 259 REPORTER_ASSERT(reporter, mat.isSimilarity()); |
| 260 REPORTER_ASSERT(reporter, mat.preservesRightAngles()); |
259 | 261 |
260 // scale with same size | 262 // scale with same size |
261 mat.reset(); | 263 mat.reset(); |
262 mat.setScale(SkIntToScalar(15), SkIntToScalar(15)); | 264 mat.setScale(SkIntToScalar(15), SkIntToScalar(15)); |
263 REPORTER_ASSERT(reporter, mat.isSimilarity()); | 265 REPORTER_ASSERT(reporter, mat.isSimilarity()); |
| 266 REPORTER_ASSERT(reporter, mat.preservesRightAngles()); |
264 | 267 |
265 // scale with one negative | 268 // scale with one negative |
266 mat.reset(); | 269 mat.reset(); |
267 mat.setScale(SkIntToScalar(-15), SkIntToScalar(15)); | 270 mat.setScale(SkIntToScalar(-15), SkIntToScalar(15)); |
268 REPORTER_ASSERT(reporter, mat.isSimilarity()); | 271 REPORTER_ASSERT(reporter, mat.isSimilarity()); |
| 272 REPORTER_ASSERT(reporter, mat.preservesRightAngles()); |
269 | 273 |
270 // scale with different size | 274 // scale with different size |
271 mat.reset(); | 275 mat.reset(); |
272 mat.setScale(SkIntToScalar(15), SkIntToScalar(20)); | 276 mat.setScale(SkIntToScalar(15), SkIntToScalar(20)); |
273 REPORTER_ASSERT(reporter, !mat.isSimilarity()); | 277 REPORTER_ASSERT(reporter, !mat.isSimilarity()); |
| 278 REPORTER_ASSERT(reporter, mat.preservesRightAngles()); |
274 | 279 |
275 // scale with same size at a pivot point | 280 // scale with same size at a pivot point |
276 mat.reset(); | 281 mat.reset(); |
277 mat.setScale(SkIntToScalar(15), SkIntToScalar(15), | 282 mat.setScale(SkIntToScalar(15), SkIntToScalar(15), |
278 SkIntToScalar(2), SkIntToScalar(2)); | 283 SkIntToScalar(2), SkIntToScalar(2)); |
279 REPORTER_ASSERT(reporter, mat.isSimilarity()); | 284 REPORTER_ASSERT(reporter, mat.isSimilarity()); |
| 285 REPORTER_ASSERT(reporter, mat.preservesRightAngles()); |
280 | 286 |
281 // scale with different size at a pivot point | 287 // scale with different size at a pivot point |
282 mat.reset(); | 288 mat.reset(); |
283 mat.setScale(SkIntToScalar(15), SkIntToScalar(20), | 289 mat.setScale(SkIntToScalar(15), SkIntToScalar(20), |
284 SkIntToScalar(2), SkIntToScalar(2)); | 290 SkIntToScalar(2), SkIntToScalar(2)); |
285 REPORTER_ASSERT(reporter, !mat.isSimilarity()); | 291 REPORTER_ASSERT(reporter, !mat.isSimilarity()); |
| 292 REPORTER_ASSERT(reporter, mat.preservesRightAngles()); |
286 | 293 |
287 // skew with same size | 294 // skew with same size |
288 mat.reset(); | 295 mat.reset(); |
289 mat.setSkew(SkIntToScalar(15), SkIntToScalar(15)); | 296 mat.setSkew(SkIntToScalar(15), SkIntToScalar(15)); |
290 REPORTER_ASSERT(reporter, !mat.isSimilarity()); | 297 REPORTER_ASSERT(reporter, !mat.isSimilarity()); |
| 298 REPORTER_ASSERT(reporter, !mat.preservesRightAngles()); |
291 | 299 |
292 // skew with different size | 300 // skew with different size |
293 mat.reset(); | 301 mat.reset(); |
294 mat.setSkew(SkIntToScalar(15), SkIntToScalar(20)); | 302 mat.setSkew(SkIntToScalar(15), SkIntToScalar(20)); |
295 REPORTER_ASSERT(reporter, !mat.isSimilarity()); | 303 REPORTER_ASSERT(reporter, !mat.isSimilarity()); |
| 304 REPORTER_ASSERT(reporter, !mat.preservesRightAngles()); |
296 | 305 |
297 // skew with same size at a pivot point | 306 // skew with same size at a pivot point |
298 mat.reset(); | 307 mat.reset(); |
299 mat.setSkew(SkIntToScalar(15), SkIntToScalar(15), | 308 mat.setSkew(SkIntToScalar(15), SkIntToScalar(15), |
300 SkIntToScalar(2), SkIntToScalar(2)); | 309 SkIntToScalar(2), SkIntToScalar(2)); |
301 REPORTER_ASSERT(reporter, !mat.isSimilarity()); | 310 REPORTER_ASSERT(reporter, !mat.isSimilarity()); |
| 311 REPORTER_ASSERT(reporter, !mat.preservesRightAngles()); |
302 | 312 |
303 // skew with different size at a pivot point | 313 // skew with different size at a pivot point |
304 mat.reset(); | 314 mat.reset(); |
305 mat.setSkew(SkIntToScalar(15), SkIntToScalar(20), | 315 mat.setSkew(SkIntToScalar(15), SkIntToScalar(20), |
306 SkIntToScalar(2), SkIntToScalar(2)); | 316 SkIntToScalar(2), SkIntToScalar(2)); |
307 REPORTER_ASSERT(reporter, !mat.isSimilarity()); | 317 REPORTER_ASSERT(reporter, !mat.isSimilarity()); |
| 318 REPORTER_ASSERT(reporter, !mat.preservesRightAngles()); |
308 | 319 |
309 // perspective x | 320 // perspective x |
310 mat.reset(); | 321 mat.reset(); |
311 mat.setPerspX(SkScalarToPersp(SK_Scalar1 / 2)); | 322 mat.setPerspX(SkScalarToPersp(SK_Scalar1 / 2)); |
312 REPORTER_ASSERT(reporter, !mat.isSimilarity()); | 323 REPORTER_ASSERT(reporter, !mat.isSimilarity()); |
| 324 REPORTER_ASSERT(reporter, !mat.preservesRightAngles()); |
313 | 325 |
314 // perspective y | 326 // perspective y |
315 mat.reset(); | 327 mat.reset(); |
316 mat.setPerspY(SkScalarToPersp(SK_Scalar1 / 2)); | 328 mat.setPerspY(SkScalarToPersp(SK_Scalar1 / 2)); |
317 REPORTER_ASSERT(reporter, !mat.isSimilarity()); | 329 REPORTER_ASSERT(reporter, !mat.isSimilarity()); |
| 330 REPORTER_ASSERT(reporter, !mat.preservesRightAngles()); |
318 | 331 |
319 // rotate | 332 // rotate |
320 for (int angle = 0; angle < 360; ++angle) { | 333 for (int angle = 0; angle < 360; ++angle) { |
321 mat.reset(); | 334 mat.reset(); |
322 mat.setRotate(SkIntToScalar(angle)); | 335 mat.setRotate(SkIntToScalar(angle)); |
323 #ifndef SK_CPU_ARM64 | |
324 REPORTER_ASSERT(reporter, mat.isSimilarity()); | 336 REPORTER_ASSERT(reporter, mat.isSimilarity()); |
325 #else | 337 REPORTER_ASSERT(reporter, mat.preservesRightAngles()); |
326 // 64-bit ARM devices built with -O2 and -ffp-contract=fast have a loss | |
327 // of precision and require that we have a higher tolerance | |
328 REPORTER_ASSERT(reporter, mat.isSimilarity(SK_ScalarNearlyZero + 0.00010
113f)); | |
329 #endif | |
330 } | 338 } |
331 | 339 |
332 // see if there are any accumulated precision issues | 340 // see if there are any accumulated precision issues |
333 mat.reset(); | 341 mat.reset(); |
334 for (int i = 1; i < 360; i++) { | 342 for (int i = 1; i < 360; i++) { |
335 mat.postRotate(SkIntToScalar(1)); | 343 mat.postRotate(SkIntToScalar(1)); |
336 } | 344 } |
337 REPORTER_ASSERT(reporter, mat.isSimilarity()); | 345 REPORTER_ASSERT(reporter, mat.isSimilarity()); |
| 346 REPORTER_ASSERT(reporter, mat.preservesRightAngles()); |
338 | 347 |
339 // rotate + translate | 348 // rotate + translate |
340 mat.reset(); | 349 mat.reset(); |
341 mat.setRotate(SkIntToScalar(30)); | 350 mat.setRotate(SkIntToScalar(30)); |
342 mat.postTranslate(SkIntToScalar(10), SkIntToScalar(20)); | 351 mat.postTranslate(SkIntToScalar(10), SkIntToScalar(20)); |
343 REPORTER_ASSERT(reporter, mat.isSimilarity()); | 352 REPORTER_ASSERT(reporter, mat.isSimilarity()); |
| 353 REPORTER_ASSERT(reporter, mat.preservesRightAngles()); |
344 | 354 |
345 // rotate + uniform scale | 355 // rotate + uniform scale |
346 mat.reset(); | 356 mat.reset(); |
347 mat.setRotate(SkIntToScalar(30)); | 357 mat.setRotate(SkIntToScalar(30)); |
348 mat.postScale(SkIntToScalar(2), SkIntToScalar(2)); | 358 mat.postScale(SkIntToScalar(2), SkIntToScalar(2)); |
349 REPORTER_ASSERT(reporter, mat.isSimilarity()); | 359 REPORTER_ASSERT(reporter, mat.isSimilarity()); |
| 360 REPORTER_ASSERT(reporter, mat.preservesRightAngles()); |
350 | 361 |
351 // rotate + non-uniform scale | 362 // rotate + non-uniform scale |
352 mat.reset(); | 363 mat.reset(); |
353 mat.setRotate(SkIntToScalar(30)); | 364 mat.setRotate(SkIntToScalar(30)); |
354 mat.postScale(SkIntToScalar(3), SkIntToScalar(2)); | 365 mat.postScale(SkIntToScalar(3), SkIntToScalar(2)); |
355 REPORTER_ASSERT(reporter, !mat.isSimilarity()); | 366 REPORTER_ASSERT(reporter, !mat.isSimilarity()); |
| 367 REPORTER_ASSERT(reporter, !mat.preservesRightAngles()); |
| 368 |
| 369 // non-uniform scale + rotate |
| 370 mat.reset(); |
| 371 mat.setScale(SkIntToScalar(3), SkIntToScalar(2)); |
| 372 mat.postRotate(SkIntToScalar(30)); |
| 373 REPORTER_ASSERT(reporter, !mat.isSimilarity()); |
| 374 REPORTER_ASSERT(reporter, mat.preservesRightAngles()); |
356 | 375 |
357 // all zero | 376 // all zero |
358 mat.setAll(0, 0, 0, 0, 0, 0, 0, 0, 0); | 377 mat.setAll(0, 0, 0, 0, 0, 0, 0, 0, 0); |
359 REPORTER_ASSERT(reporter, !mat.isSimilarity()); | 378 REPORTER_ASSERT(reporter, !mat.isSimilarity()); |
| 379 REPORTER_ASSERT(reporter, !mat.preservesRightAngles()); |
360 | 380 |
361 // all zero except perspective | 381 // all zero except perspective |
| 382 mat.reset(); |
362 mat.setAll(0, 0, 0, 0, 0, 0, 0, 0, SK_Scalar1); | 383 mat.setAll(0, 0, 0, 0, 0, 0, 0, 0, SK_Scalar1); |
363 REPORTER_ASSERT(reporter, !mat.isSimilarity()); | 384 REPORTER_ASSERT(reporter, !mat.isSimilarity()); |
| 385 REPORTER_ASSERT(reporter, !mat.preservesRightAngles()); |
364 | 386 |
365 // scales zero, only skews | 387 // scales zero, only skews (rotation) |
| 388 mat.setAll(0, SK_Scalar1, 0, |
| 389 -SK_Scalar1, 0, 0, |
| 390 0, 0, SkMatrix::I()[8]); |
| 391 REPORTER_ASSERT(reporter, mat.isSimilarity()); |
| 392 REPORTER_ASSERT(reporter, mat.preservesRightAngles()); |
| 393 |
| 394 // scales zero, only skews (reflection) |
366 mat.setAll(0, SK_Scalar1, 0, | 395 mat.setAll(0, SK_Scalar1, 0, |
367 SK_Scalar1, 0, 0, | 396 SK_Scalar1, 0, 0, |
368 0, 0, SkMatrix::I()[8]); | 397 0, 0, SkMatrix::I()[8]); |
369 REPORTER_ASSERT(reporter, mat.isSimilarity()); | 398 REPORTER_ASSERT(reporter, mat.isSimilarity()); |
| 399 REPORTER_ASSERT(reporter, mat.preservesRightAngles()); |
370 } | 400 } |
371 | 401 |
372 // For test_matrix_decomposition, below. | 402 // For test_matrix_decomposition, below. |
373 static bool scalar_nearly_equal_relative(SkScalar a, SkScalar b, | 403 static bool scalar_nearly_equal_relative(SkScalar a, SkScalar b, |
374 SkScalar tolerance = SK_ScalarNearlyZer
o) { | 404 SkScalar tolerance = SK_ScalarNearlyZer
o) { |
375 // from Bruce Dawson | 405 // from Bruce Dawson |
376 // absolute check | 406 // absolute check |
377 SkScalar diff = SkScalarAbs(a - b); | 407 SkScalar diff = SkScalarAbs(a - b); |
378 if (diff < tolerance) { | 408 if (diff < tolerance) { |
379 return true; | 409 return true; |
(...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
808 mat.set(SkMatrix::kMSkewX, -zero); | 838 mat.set(SkMatrix::kMSkewX, -zero); |
809 REPORTER_ASSERT(reporter, are_equal(reporter, mat, mat2)); | 839 REPORTER_ASSERT(reporter, are_equal(reporter, mat, mat2)); |
810 | 840 |
811 mat2.reset(); | 841 mat2.reset(); |
812 mat.reset(); | 842 mat.reset(); |
813 mat.set(SkMatrix::kMSkewX, SK_ScalarNaN); | 843 mat.set(SkMatrix::kMSkewX, SK_ScalarNaN); |
814 mat2.set(SkMatrix::kMSkewX, SK_ScalarNaN); | 844 mat2.set(SkMatrix::kMSkewX, SK_ScalarNaN); |
815 REPORTER_ASSERT(reporter, !are_equal(reporter, mat, mat2)); | 845 REPORTER_ASSERT(reporter, !are_equal(reporter, mat, mat2)); |
816 | 846 |
817 test_matrix_min_max_scale(reporter); | 847 test_matrix_min_max_scale(reporter); |
818 test_matrix_is_similarity(reporter); | 848 test_matrix_preserve_shape(reporter); |
819 test_matrix_recttorect(reporter); | 849 test_matrix_recttorect(reporter); |
820 test_matrix_decomposition(reporter); | 850 test_matrix_decomposition(reporter); |
821 test_matrix_homogeneous(reporter); | 851 test_matrix_homogeneous(reporter); |
822 } | 852 } |
823 | 853 |
824 DEF_TEST(Matrix_Concat, r) { | 854 DEF_TEST(Matrix_Concat, r) { |
825 SkMatrix a; | 855 SkMatrix a; |
826 a.setTranslate(10, 20); | 856 a.setTranslate(10, 20); |
827 | 857 |
828 SkMatrix b; | 858 SkMatrix b; |
829 b.setScale(3, 5); | 859 b.setScale(3, 5); |
830 | 860 |
831 SkMatrix expected; | 861 SkMatrix expected; |
832 expected.setConcat(a,b); | 862 expected.setConcat(a,b); |
833 | 863 |
834 REPORTER_ASSERT(r, expected == SkMatrix::Concat(a, b)); | 864 REPORTER_ASSERT(r, expected == SkMatrix::Concat(a, b)); |
835 } | 865 } |
OLD | NEW |