1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.graphics; 18 19 import android.compat.annotation.UnsupportedAppUsage; 20 21 import dalvik.annotation.optimization.CriticalNative; 22 import dalvik.annotation.optimization.FastNative; 23 24 import libcore.util.NativeAllocationRegistry; 25 26 import java.io.PrintWriter; 27 28 /** 29 * The Matrix class holds a 3x3 matrix for transforming coordinates. 30 */ 31 public class Matrix { 32 33 public static final int MSCALE_X = 0; //!< use with getValues/setValues 34 public static final int MSKEW_X = 1; //!< use with getValues/setValues 35 public static final int MTRANS_X = 2; //!< use with getValues/setValues 36 public static final int MSKEW_Y = 3; //!< use with getValues/setValues 37 public static final int MSCALE_Y = 4; //!< use with getValues/setValues 38 public static final int MTRANS_Y = 5; //!< use with getValues/setValues 39 public static final int MPERSP_0 = 6; //!< use with getValues/setValues 40 public static final int MPERSP_1 = 7; //!< use with getValues/setValues 41 public static final int MPERSP_2 = 8; //!< use with getValues/setValues 42 43 /** @hide */ 44 @UnsupportedAppUsage 45 public final static Matrix IDENTITY_MATRIX = new Matrix() { 46 void oops() { 47 throw new IllegalStateException("Matrix can not be modified"); 48 } 49 50 @Override 51 public void set(Matrix src) { 52 oops(); 53 } 54 55 @Override 56 public void reset() { 57 oops(); 58 } 59 60 @Override 61 public void setTranslate(float dx, float dy) { 62 oops(); 63 } 64 65 @Override 66 public void setScale(float sx, float sy, float px, float py) { 67 oops(); 68 } 69 70 @Override 71 public void setScale(float sx, float sy) { 72 oops(); 73 } 74 75 @Override 76 public void setRotate(float degrees, float px, float py) { 77 oops(); 78 } 79 80 @Override 81 public void setRotate(float degrees) { 82 oops(); 83 } 84 85 @Override 86 public void setSinCos(float sinValue, float cosValue, float px, float py) { 87 oops(); 88 } 89 90 @Override 91 public void setSinCos(float sinValue, float cosValue) { 92 oops(); 93 } 94 95 @Override 96 public void setSkew(float kx, float ky, float px, float py) { 97 oops(); 98 } 99 100 @Override 101 public void setSkew(float kx, float ky) { 102 oops(); 103 } 104 105 @Override 106 public boolean setConcat(Matrix a, Matrix b) { 107 oops(); 108 return false; 109 } 110 111 @Override 112 public boolean preTranslate(float dx, float dy) { 113 oops(); 114 return false; 115 } 116 117 @Override 118 public boolean preScale(float sx, float sy, float px, float py) { 119 oops(); 120 return false; 121 } 122 123 @Override 124 public boolean preScale(float sx, float sy) { 125 oops(); 126 return false; 127 } 128 129 @Override 130 public boolean preRotate(float degrees, float px, float py) { 131 oops(); 132 return false; 133 } 134 135 @Override 136 public boolean preRotate(float degrees) { 137 oops(); 138 return false; 139 } 140 141 @Override 142 public boolean preSkew(float kx, float ky, float px, float py) { 143 oops(); 144 return false; 145 } 146 147 @Override 148 public boolean preSkew(float kx, float ky) { 149 oops(); 150 return false; 151 } 152 153 @Override 154 public boolean preConcat(Matrix other) { 155 oops(); 156 return false; 157 } 158 159 @Override 160 public boolean postTranslate(float dx, float dy) { 161 oops(); 162 return false; 163 } 164 165 @Override 166 public boolean postScale(float sx, float sy, float px, float py) { 167 oops(); 168 return false; 169 } 170 171 @Override 172 public boolean postScale(float sx, float sy) { 173 oops(); 174 return false; 175 } 176 177 @Override 178 public boolean postRotate(float degrees, float px, float py) { 179 oops(); 180 return false; 181 } 182 183 @Override 184 public boolean postRotate(float degrees) { 185 oops(); 186 return false; 187 } 188 189 @Override 190 public boolean postSkew(float kx, float ky, float px, float py) { 191 oops(); 192 return false; 193 } 194 195 @Override 196 public boolean postSkew(float kx, float ky) { 197 oops(); 198 return false; 199 } 200 201 @Override 202 public boolean postConcat(Matrix other) { 203 oops(); 204 return false; 205 } 206 207 @Override 208 public boolean setRectToRect(RectF src, RectF dst, ScaleToFit stf) { 209 oops(); 210 return false; 211 } 212 213 @Override 214 public boolean setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, 215 int pointCount) { 216 oops(); 217 return false; 218 } 219 220 @Override 221 public void setValues(float[] values) { 222 oops(); 223 } 224 }; 225 226 private static class NoImagePreloadHolder { 227 public static final NativeAllocationRegistry sRegistry = 228 NativeAllocationRegistry.createMalloced( 229 Matrix.class.getClassLoader(), nGetNativeFinalizer()); 230 } 231 232 /** 233 * @hide 234 */ 235 @UnsupportedAppUsage 236 public final long native_instance; 237 238 /** 239 * Create an identity matrix 240 */ Matrix()241 public Matrix() { 242 native_instance = nCreate(0); 243 NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, native_instance); 244 } 245 246 /** 247 * Create a matrix that is a (deep) copy of src 248 * 249 * @param src The matrix to copy into this matrix 250 */ Matrix(Matrix src)251 public Matrix(Matrix src) { 252 native_instance = nCreate(src != null ? src.native_instance : 0); 253 NoImagePreloadHolder.sRegistry.registerNativeAllocation(this, native_instance); 254 } 255 256 /** 257 * Returns true if the matrix is identity. This maybe faster than testing if (getType() == 0) 258 */ isIdentity()259 public boolean isIdentity() { 260 return nIsIdentity(native_instance); 261 } 262 263 /** 264 * Gets whether this matrix is affine. An affine matrix preserves straight lines and has no 265 * perspective. 266 * 267 * @return Whether the matrix is affine. 268 */ isAffine()269 public boolean isAffine() { 270 return nIsAffine(native_instance); 271 } 272 273 /** 274 * Returns true if will map a rectangle to another rectangle. This can be true if the matrix is 275 * identity, scale-only, or rotates a multiple of 90 degrees. 276 */ rectStaysRect()277 public boolean rectStaysRect() { 278 return nRectStaysRect(native_instance); 279 } 280 281 /** 282 * (deep) copy the src matrix into this matrix. If src is null, reset this matrix to the 283 * identity matrix. 284 */ set(Matrix src)285 public void set(Matrix src) { 286 if (src == null) { 287 reset(); 288 } else { 289 nSet(native_instance, src.native_instance); 290 } 291 } 292 293 /** 294 * Returns true iff obj is a Matrix and its values equal our values. 295 */ 296 @Override equals(Object obj)297 public boolean equals(Object obj) { 298 // if (obj == this) return true; -- NaN value would mean matrix != itself 299 if (!(obj instanceof Matrix)) { 300 return false; 301 } 302 return nEquals(native_instance, ((Matrix) obj).native_instance); 303 } 304 305 @Override hashCode()306 public int hashCode() { 307 // This should generate the hash code by performing some arithmetic operation on all 308 // the matrix elements -- our equals() does an element-by-element comparison, and we 309 // need to ensure that the hash code for two equal objects is the same. We're not 310 // really using this at the moment, so we take the easy way out. 311 return 44; 312 } 313 314 /** Set the matrix to identity */ reset()315 public void reset() { 316 nReset(native_instance); 317 } 318 319 /** Set the matrix to translate by (dx, dy). */ setTranslate(float dx, float dy)320 public void setTranslate(float dx, float dy) { 321 nSetTranslate(native_instance, dx, dy); 322 } 323 324 /** 325 * Set the matrix to scale by sx and sy, with a pivot point at (px, py). The pivot point is the 326 * coordinate that should remain unchanged by the specified transformation. 327 */ setScale(float sx, float sy, float px, float py)328 public void setScale(float sx, float sy, float px, float py) { 329 nSetScale(native_instance, sx, sy, px, py); 330 } 331 332 /** Set the matrix to scale by sx and sy. */ setScale(float sx, float sy)333 public void setScale(float sx, float sy) { 334 nSetScale(native_instance, sx, sy); 335 } 336 337 /** 338 * Set the matrix to rotate by the specified number of degrees, with a pivot point at (px, py). 339 * The pivot point is the coordinate that should remain unchanged by the specified 340 * transformation. 341 */ setRotate(float degrees, float px, float py)342 public void setRotate(float degrees, float px, float py) { 343 nSetRotate(native_instance, degrees, px, py); 344 } 345 346 /** 347 * Set the matrix to rotate about (0,0) by the specified number of degrees. 348 */ setRotate(float degrees)349 public void setRotate(float degrees) { 350 nSetRotate(native_instance, degrees); 351 } 352 353 /** 354 * Set the matrix to rotate by the specified sine and cosine values, with a pivot point at (px, 355 * py). The pivot point is the coordinate that should remain unchanged by the specified 356 * transformation. 357 */ setSinCos(float sinValue, float cosValue, float px, float py)358 public void setSinCos(float sinValue, float cosValue, float px, float py) { 359 nSetSinCos(native_instance, sinValue, cosValue, px, py); 360 } 361 362 /** Set the matrix to rotate by the specified sine and cosine values. */ setSinCos(float sinValue, float cosValue)363 public void setSinCos(float sinValue, float cosValue) { 364 nSetSinCos(native_instance, sinValue, cosValue); 365 } 366 367 /** 368 * Set the matrix to skew by sx and sy, with a pivot point at (px, py). The pivot point is the 369 * coordinate that should remain unchanged by the specified transformation. 370 */ setSkew(float kx, float ky, float px, float py)371 public void setSkew(float kx, float ky, float px, float py) { 372 nSetSkew(native_instance, kx, ky, px, py); 373 } 374 375 /** Set the matrix to skew by sx and sy. */ setSkew(float kx, float ky)376 public void setSkew(float kx, float ky) { 377 nSetSkew(native_instance, kx, ky); 378 } 379 380 /** 381 * Set the matrix to the concatenation of the two specified matrices and return true. 382 * <p> 383 * Either of the two matrices may also be the target matrix, that is 384 * <code>matrixA.setConcat(matrixA, matrixB);</code> is valid. 385 * </p> 386 * <p class="note"> 387 * In {@link android.os.Build.VERSION_CODES#GINGERBREAD_MR1} and below, this function returns 388 * true only if the result can be represented. In 389 * {@link android.os.Build.VERSION_CODES#HONEYCOMB} and above, it always returns true. 390 * </p> 391 */ setConcat(Matrix a, Matrix b)392 public boolean setConcat(Matrix a, Matrix b) { 393 nSetConcat(native_instance, a.native_instance, b.native_instance); 394 return true; 395 } 396 397 /** 398 * Preconcats the matrix with the specified translation. M' = M * T(dx, dy) 399 */ preTranslate(float dx, float dy)400 public boolean preTranslate(float dx, float dy) { 401 nPreTranslate(native_instance, dx, dy); 402 return true; 403 } 404 405 /** 406 * Preconcats the matrix with the specified scale. M' = M * S(sx, sy, px, py) 407 */ preScale(float sx, float sy, float px, float py)408 public boolean preScale(float sx, float sy, float px, float py) { 409 nPreScale(native_instance, sx, sy, px, py); 410 return true; 411 } 412 413 /** 414 * Preconcats the matrix with the specified scale. M' = M * S(sx, sy) 415 */ preScale(float sx, float sy)416 public boolean preScale(float sx, float sy) { 417 nPreScale(native_instance, sx, sy); 418 return true; 419 } 420 421 /** 422 * Preconcats the matrix with the specified rotation. M' = M * R(degrees, px, py) 423 */ preRotate(float degrees, float px, float py)424 public boolean preRotate(float degrees, float px, float py) { 425 nPreRotate(native_instance, degrees, px, py); 426 return true; 427 } 428 429 /** 430 * Preconcats the matrix with the specified rotation. M' = M * R(degrees) 431 */ preRotate(float degrees)432 public boolean preRotate(float degrees) { 433 nPreRotate(native_instance, degrees); 434 return true; 435 } 436 437 /** 438 * Preconcats the matrix with the specified skew. M' = M * K(kx, ky, px, py) 439 */ preSkew(float kx, float ky, float px, float py)440 public boolean preSkew(float kx, float ky, float px, float py) { 441 nPreSkew(native_instance, kx, ky, px, py); 442 return true; 443 } 444 445 /** 446 * Preconcats the matrix with the specified skew. M' = M * K(kx, ky) 447 */ preSkew(float kx, float ky)448 public boolean preSkew(float kx, float ky) { 449 nPreSkew(native_instance, kx, ky); 450 return true; 451 } 452 453 /** 454 * Preconcats the matrix with the specified matrix. M' = M * other 455 */ preConcat(Matrix other)456 public boolean preConcat(Matrix other) { 457 nPreConcat(native_instance, other.native_instance); 458 return true; 459 } 460 461 /** 462 * Postconcats the matrix with the specified translation. M' = T(dx, dy) * M 463 */ postTranslate(float dx, float dy)464 public boolean postTranslate(float dx, float dy) { 465 nPostTranslate(native_instance, dx, dy); 466 return true; 467 } 468 469 /** 470 * Postconcats the matrix with the specified scale. M' = S(sx, sy, px, py) * M 471 */ postScale(float sx, float sy, float px, float py)472 public boolean postScale(float sx, float sy, float px, float py) { 473 nPostScale(native_instance, sx, sy, px, py); 474 return true; 475 } 476 477 /** 478 * Postconcats the matrix with the specified scale. M' = S(sx, sy) * M 479 */ postScale(float sx, float sy)480 public boolean postScale(float sx, float sy) { 481 nPostScale(native_instance, sx, sy); 482 return true; 483 } 484 485 /** 486 * Postconcats the matrix with the specified rotation. M' = R(degrees, px, py) * M 487 */ postRotate(float degrees, float px, float py)488 public boolean postRotate(float degrees, float px, float py) { 489 nPostRotate(native_instance, degrees, px, py); 490 return true; 491 } 492 493 /** 494 * Postconcats the matrix with the specified rotation. M' = R(degrees) * M 495 */ postRotate(float degrees)496 public boolean postRotate(float degrees) { 497 nPostRotate(native_instance, degrees); 498 return true; 499 } 500 501 /** 502 * Postconcats the matrix with the specified skew. M' = K(kx, ky, px, py) * M 503 */ postSkew(float kx, float ky, float px, float py)504 public boolean postSkew(float kx, float ky, float px, float py) { 505 nPostSkew(native_instance, kx, ky, px, py); 506 return true; 507 } 508 509 /** 510 * Postconcats the matrix with the specified skew. M' = K(kx, ky) * M 511 */ postSkew(float kx, float ky)512 public boolean postSkew(float kx, float ky) { 513 nPostSkew(native_instance, kx, ky); 514 return true; 515 } 516 517 /** 518 * Postconcats the matrix with the specified matrix. M' = other * M 519 */ postConcat(Matrix other)520 public boolean postConcat(Matrix other) { 521 nPostConcat(native_instance, other.native_instance); 522 return true; 523 } 524 525 /** 526 * Controlls how the src rect should align into the dst rect for setRectToRect(). 527 */ 528 public enum ScaleToFit { 529 /** 530 * Scale in X and Y independently, so that src matches dst exactly. This may change the 531 * aspect ratio of the src. 532 */ 533 FILL(0), 534 /** 535 * Compute a scale that will maintain the original src aspect ratio, but will also ensure 536 * that src fits entirely inside dst. At least one axis (X or Y) will fit exactly. START 537 * aligns the result to the left and top edges of dst. 538 */ 539 START(1), 540 /** 541 * Compute a scale that will maintain the original src aspect ratio, but will also ensure 542 * that src fits entirely inside dst. At least one axis (X or Y) will fit exactly. The 543 * result is centered inside dst. 544 */ 545 CENTER(2), 546 /** 547 * Compute a scale that will maintain the original src aspect ratio, but will also ensure 548 * that src fits entirely inside dst. At least one axis (X or Y) will fit exactly. END 549 * aligns the result to the right and bottom edges of dst. 550 */ 551 END(3); 552 553 // the native values must match those in SkMatrix.h ScaleToFit(int nativeInt)554 ScaleToFit(int nativeInt) { 555 this.nativeInt = nativeInt; 556 } 557 558 final int nativeInt; 559 } 560 561 /** 562 * Set the matrix to the scale and translate values that map the source rectangle to the 563 * destination rectangle, returning true if the the result can be represented. 564 * 565 * @param src the source rectangle to map from. 566 * @param dst the destination rectangle to map to. 567 * @param stf the ScaleToFit option 568 * @return true if the matrix can be represented by the rectangle mapping. 569 */ setRectToRect(RectF src, RectF dst, ScaleToFit stf)570 public boolean setRectToRect(RectF src, RectF dst, ScaleToFit stf) { 571 if (dst == null || src == null) { 572 throw new NullPointerException(); 573 } 574 return nSetRectToRect(native_instance, src, dst, stf.nativeInt); 575 } 576 577 // private helper to perform range checks on arrays of "points" checkPointArrays(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount)578 private static void checkPointArrays(float[] src, int srcIndex, 579 float[] dst, int dstIndex, 580 int pointCount) { 581 // check for too-small and too-big indices 582 int srcStop = srcIndex + (pointCount << 1); 583 int dstStop = dstIndex + (pointCount << 1); 584 if ((pointCount | srcIndex | dstIndex | srcStop | dstStop) < 0 || 585 srcStop > src.length || dstStop > dst.length) { 586 throw new ArrayIndexOutOfBoundsException(); 587 } 588 } 589 590 /** 591 * Set the matrix such that the specified src points would map to the specified dst points. The 592 * "points" are represented as an array of floats, order [x0, y0, x1, y1, ...], where each 593 * "point" is 2 float values. 594 * 595 * @param src The array of src [x,y] pairs (points) 596 * @param srcIndex Index of the first pair of src values 597 * @param dst The array of dst [x,y] pairs (points) 598 * @param dstIndex Index of the first pair of dst values 599 * @param pointCount The number of pairs/points to be used. Must be [0..4] 600 * @return true if the matrix was set to the specified transformation 601 */ setPolyToPoly(float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount)602 public boolean setPolyToPoly(float[] src, int srcIndex, 603 float[] dst, int dstIndex, 604 int pointCount) { 605 if (pointCount > 4) { 606 throw new IllegalArgumentException(); 607 } 608 checkPointArrays(src, srcIndex, dst, dstIndex, pointCount); 609 return nSetPolyToPoly(native_instance, src, srcIndex, 610 dst, dstIndex, pointCount); 611 } 612 613 /** 614 * If this matrix can be inverted, return true and if inverse is not null, set inverse to be the 615 * inverse of this matrix. If this matrix cannot be inverted, ignore inverse and return false. 616 */ invert(Matrix inverse)617 public boolean invert(Matrix inverse) { 618 return nInvert(native_instance, inverse.native_instance); 619 } 620 621 /** 622 * Apply this matrix to the array of 2D points specified by src, and write the transformed 623 * points into the array of points specified by dst. The two arrays represent their "points" as 624 * pairs of floats [x, y]. 625 * 626 * @param dst The array of dst points (x,y pairs) 627 * @param dstIndex The index of the first [x,y] pair of dst floats 628 * @param src The array of src points (x,y pairs) 629 * @param srcIndex The index of the first [x,y] pair of src floats 630 * @param pointCount The number of points (x,y pairs) to transform 631 */ mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex, int pointCount)632 public void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex, 633 int pointCount) { 634 checkPointArrays(src, srcIndex, dst, dstIndex, pointCount); 635 nMapPoints(native_instance, dst, dstIndex, src, srcIndex, 636 pointCount, true); 637 } 638 639 /** 640 * Apply this matrix to the array of 2D vectors specified by src, and write the transformed 641 * vectors into the array of vectors specified by dst. The two arrays represent their "vectors" 642 * as pairs of floats [x, y]. Note: this method does not apply the translation associated with 643 * the matrix. Use {@link Matrix#mapPoints(float[], int, float[], int, int)} if you want the 644 * translation to be applied. 645 * 646 * @param dst The array of dst vectors (x,y pairs) 647 * @param dstIndex The index of the first [x,y] pair of dst floats 648 * @param src The array of src vectors (x,y pairs) 649 * @param srcIndex The index of the first [x,y] pair of src floats 650 * @param vectorCount The number of vectors (x,y pairs) to transform 651 */ mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, int vectorCount)652 public void mapVectors(float[] dst, int dstIndex, float[] src, int srcIndex, 653 int vectorCount) { 654 checkPointArrays(src, srcIndex, dst, dstIndex, vectorCount); 655 nMapPoints(native_instance, dst, dstIndex, src, srcIndex, 656 vectorCount, false); 657 } 658 659 /** 660 * Apply this matrix to the array of 2D points specified by src, and write the transformed 661 * points into the array of points specified by dst. The two arrays represent their "points" as 662 * pairs of floats [x, y]. 663 * 664 * @param dst The array of dst points (x,y pairs) 665 * @param src The array of src points (x,y pairs) 666 */ mapPoints(float[] dst, float[] src)667 public void mapPoints(float[] dst, float[] src) { 668 if (dst.length != src.length) { 669 throw new ArrayIndexOutOfBoundsException(); 670 } 671 mapPoints(dst, 0, src, 0, dst.length >> 1); 672 } 673 674 /** 675 * Apply this matrix to the array of 2D vectors specified by src, and write the transformed 676 * vectors into the array of vectors specified by dst. The two arrays represent their "vectors" 677 * as pairs of floats [x, y]. Note: this method does not apply the translation associated with 678 * the matrix. Use {@link Matrix#mapPoints(float[], float[])} if you want the translation to be 679 * applied. 680 * 681 * @param dst The array of dst vectors (x,y pairs) 682 * @param src The array of src vectors (x,y pairs) 683 */ mapVectors(float[] dst, float[] src)684 public void mapVectors(float[] dst, float[] src) { 685 if (dst.length != src.length) { 686 throw new ArrayIndexOutOfBoundsException(); 687 } 688 mapVectors(dst, 0, src, 0, dst.length >> 1); 689 } 690 691 /** 692 * Apply this matrix to the array of 2D points, and write the transformed points back into the 693 * array 694 * 695 * @param pts The array [x0, y0, x1, y1, ...] of points to transform. 696 */ mapPoints(float[] pts)697 public void mapPoints(float[] pts) { 698 mapPoints(pts, 0, pts, 0, pts.length >> 1); 699 } 700 701 /** 702 * Apply this matrix to the array of 2D vectors, and write the transformed vectors back into the 703 * array. Note: this method does not apply the translation associated with the matrix. Use 704 * {@link Matrix#mapPoints(float[])} if you want the translation to be applied. 705 * 706 * @param vecs The array [x0, y0, x1, y1, ...] of vectors to transform. 707 */ mapVectors(float[] vecs)708 public void mapVectors(float[] vecs) { 709 mapVectors(vecs, 0, vecs, 0, vecs.length >> 1); 710 } 711 712 /** 713 * Apply this matrix to the src rectangle, and write the transformed rectangle into dst. This is 714 * accomplished by transforming the 4 corners of src, and then setting dst to the bounds of 715 * those points. 716 * 717 * @param dst Where the transformed rectangle is written. 718 * @param src The original rectangle to be transformed. 719 * @return the result of calling rectStaysRect() 720 */ mapRect(RectF dst, RectF src)721 public boolean mapRect(RectF dst, RectF src) { 722 if (dst == null || src == null) { 723 throw new NullPointerException(); 724 } 725 return nMapRect(native_instance, dst, src); 726 } 727 728 /** 729 * Apply this matrix to the rectangle, and write the transformed rectangle back into it. This is 730 * accomplished by transforming the 4 corners of rect, and then setting it to the bounds of 731 * those points 732 * 733 * @param rect The rectangle to transform. 734 * @return the result of calling rectStaysRect() 735 */ mapRect(RectF rect)736 public boolean mapRect(RectF rect) { 737 return mapRect(rect, rect); 738 } 739 740 /** 741 * Return the mean radius of a circle after it has been mapped by this matrix. NOTE: in 742 * perspective this value assumes the circle has its center at the origin. 743 */ mapRadius(float radius)744 public float mapRadius(float radius) { 745 return nMapRadius(native_instance, radius); 746 } 747 748 /** 749 * Copy 9 values from the matrix into the array. 750 */ getValues(float[] values)751 public void getValues(float[] values) { 752 if (values.length < 9) { 753 throw new ArrayIndexOutOfBoundsException(); 754 } 755 nGetValues(native_instance, values); 756 } 757 758 /** 759 * Copy 9 values from the array into the matrix. Depending on the implementation of Matrix, 760 * these may be transformed into 16.16 integers in the Matrix, such that a subsequent call to 761 * getValues() will not yield exactly the same values. 762 */ setValues(float[] values)763 public void setValues(float[] values) { 764 if (values.length < 9) { 765 throw new ArrayIndexOutOfBoundsException(); 766 } 767 nSetValues(native_instance, values); 768 } 769 770 @Override toString()771 public String toString() { 772 StringBuilder sb = new StringBuilder(64); 773 sb.append("Matrix{"); 774 toShortString(sb); 775 sb.append('}'); 776 return sb.toString(); 777 778 } 779 toShortString()780 public String toShortString() { 781 StringBuilder sb = new StringBuilder(64); 782 toShortString(sb); 783 return sb.toString(); 784 } 785 786 /** 787 * @hide 788 */ toShortString(StringBuilder sb)789 public void toShortString(StringBuilder sb) { 790 float[] values = new float[9]; 791 getValues(values); 792 sb.append('['); 793 sb.append(values[0]); 794 sb.append(", "); 795 sb.append(values[1]); 796 sb.append(", "); 797 sb.append(values[2]); 798 sb.append("]["); 799 sb.append(values[3]); 800 sb.append(", "); 801 sb.append(values[4]); 802 sb.append(", "); 803 sb.append(values[5]); 804 sb.append("]["); 805 sb.append(values[6]); 806 sb.append(", "); 807 sb.append(values[7]); 808 sb.append(", "); 809 sb.append(values[8]); 810 sb.append(']'); 811 } 812 813 /** 814 * Print short string, to optimize dumping. 815 * 816 * @hide 817 */ printShortString(PrintWriter pw)818 public void printShortString(PrintWriter pw) { 819 float[] values = new float[9]; 820 getValues(values); 821 pw.print('['); 822 pw.print(values[0]); 823 pw.print(", "); 824 pw.print(values[1]); 825 pw.print(", "); 826 pw.print(values[2]); 827 pw.print("]["); 828 pw.print(values[3]); 829 pw.print(", "); 830 pw.print(values[4]); 831 pw.print(", "); 832 pw.print(values[5]); 833 pw.print("]["); 834 pw.print(values[6]); 835 pw.print(", "); 836 pw.print(values[7]); 837 pw.print(", "); 838 pw.print(values[8]); 839 pw.print(']'); 840 841 } 842 843 /** @hide */ ni()844 public final long ni() { 845 return native_instance; 846 } 847 848 // ------------------ Regular JNI ------------------------ 849 nCreate(long nSrc_or_zero)850 private static native long nCreate(long nSrc_or_zero); nGetNativeFinalizer()851 private static native long nGetNativeFinalizer(); 852 853 854 // ------------------ Fast JNI ------------------------ 855 856 @FastNative nSetRectToRect(long nObject, RectF src, RectF dst, int stf)857 private static native boolean nSetRectToRect(long nObject, 858 RectF src, RectF dst, int stf); 859 @FastNative nSetPolyToPoly(long nObject, float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount)860 private static native boolean nSetPolyToPoly(long nObject, 861 float[] src, int srcIndex, float[] dst, int dstIndex, int pointCount); 862 @FastNative nMapPoints(long nObject, float[] dst, int dstIndex, float[] src, int srcIndex, int ptCount, boolean isPts)863 private static native void nMapPoints(long nObject, 864 float[] dst, int dstIndex, float[] src, int srcIndex, 865 int ptCount, boolean isPts); 866 @FastNative nMapRect(long nObject, RectF dst, RectF src)867 private static native boolean nMapRect(long nObject, RectF dst, RectF src); 868 @FastNative nGetValues(long nObject, float[] values)869 private static native void nGetValues(long nObject, float[] values); 870 @FastNative nSetValues(long nObject, float[] values)871 private static native void nSetValues(long nObject, float[] values); 872 873 874 // ------------------ Critical JNI ------------------------ 875 876 @CriticalNative nIsIdentity(long nObject)877 private static native boolean nIsIdentity(long nObject); 878 @CriticalNative nIsAffine(long nObject)879 private static native boolean nIsAffine(long nObject); 880 @CriticalNative nRectStaysRect(long nObject)881 private static native boolean nRectStaysRect(long nObject); 882 @CriticalNative nReset(long nObject)883 private static native void nReset(long nObject); 884 @CriticalNative nSet(long nObject, long nOther)885 private static native void nSet(long nObject, long nOther); 886 @CriticalNative nSetTranslate(long nObject, float dx, float dy)887 private static native void nSetTranslate(long nObject, float dx, float dy); 888 @CriticalNative nSetScale(long nObject, float sx, float sy, float px, float py)889 private static native void nSetScale(long nObject, float sx, float sy, float px, float py); 890 @CriticalNative nSetScale(long nObject, float sx, float sy)891 private static native void nSetScale(long nObject, float sx, float sy); 892 @CriticalNative nSetRotate(long nObject, float degrees, float px, float py)893 private static native void nSetRotate(long nObject, float degrees, float px, float py); 894 @CriticalNative nSetRotate(long nObject, float degrees)895 private static native void nSetRotate(long nObject, float degrees); 896 @CriticalNative nSetSinCos(long nObject, float sinValue, float cosValue, float px, float py)897 private static native void nSetSinCos(long nObject, float sinValue, float cosValue, 898 float px, float py); 899 @CriticalNative nSetSinCos(long nObject, float sinValue, float cosValue)900 private static native void nSetSinCos(long nObject, float sinValue, float cosValue); 901 @CriticalNative nSetSkew(long nObject, float kx, float ky, float px, float py)902 private static native void nSetSkew(long nObject, float kx, float ky, float px, float py); 903 @CriticalNative nSetSkew(long nObject, float kx, float ky)904 private static native void nSetSkew(long nObject, float kx, float ky); 905 @CriticalNative nSetConcat(long nObject, long nA, long nB)906 private static native void nSetConcat(long nObject, long nA, long nB); 907 @CriticalNative nPreTranslate(long nObject, float dx, float dy)908 private static native void nPreTranslate(long nObject, float dx, float dy); 909 @CriticalNative nPreScale(long nObject, float sx, float sy, float px, float py)910 private static native void nPreScale(long nObject, float sx, float sy, float px, float py); 911 @CriticalNative nPreScale(long nObject, float sx, float sy)912 private static native void nPreScale(long nObject, float sx, float sy); 913 @CriticalNative nPreRotate(long nObject, float degrees, float px, float py)914 private static native void nPreRotate(long nObject, float degrees, float px, float py); 915 @CriticalNative nPreRotate(long nObject, float degrees)916 private static native void nPreRotate(long nObject, float degrees); 917 @CriticalNative nPreSkew(long nObject, float kx, float ky, float px, float py)918 private static native void nPreSkew(long nObject, float kx, float ky, float px, float py); 919 @CriticalNative nPreSkew(long nObject, float kx, float ky)920 private static native void nPreSkew(long nObject, float kx, float ky); 921 @CriticalNative nPreConcat(long nObject, long nOther_matrix)922 private static native void nPreConcat(long nObject, long nOther_matrix); 923 @CriticalNative nPostTranslate(long nObject, float dx, float dy)924 private static native void nPostTranslate(long nObject, float dx, float dy); 925 @CriticalNative nPostScale(long nObject, float sx, float sy, float px, float py)926 private static native void nPostScale(long nObject, float sx, float sy, float px, float py); 927 @CriticalNative nPostScale(long nObject, float sx, float sy)928 private static native void nPostScale(long nObject, float sx, float sy); 929 @CriticalNative nPostRotate(long nObject, float degrees, float px, float py)930 private static native void nPostRotate(long nObject, float degrees, float px, float py); 931 @CriticalNative nPostRotate(long nObject, float degrees)932 private static native void nPostRotate(long nObject, float degrees); 933 @CriticalNative nPostSkew(long nObject, float kx, float ky, float px, float py)934 private static native void nPostSkew(long nObject, float kx, float ky, float px, float py); 935 @CriticalNative nPostSkew(long nObject, float kx, float ky)936 private static native void nPostSkew(long nObject, float kx, float ky); 937 @CriticalNative nPostConcat(long nObject, long nOther_matrix)938 private static native void nPostConcat(long nObject, long nOther_matrix); 939 @CriticalNative nInvert(long nObject, long nInverse)940 private static native boolean nInvert(long nObject, long nInverse); 941 @CriticalNative nMapRadius(long nObject, float radius)942 private static native float nMapRadius(long nObject, float radius); 943 @CriticalNative nEquals(long nA, long nB)944 private static native boolean nEquals(long nA, long nB); 945 } 946