| 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 |