Matrix_Delegate.java revision c2e9651bf386a1f7bf7fc706cf5424950570470c
1/* 2 * Copyright (C) 2010 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 17package android.graphics; 18 19 20import com.android.layoutlib.bridge.impl.DelegateManager; 21 22import android.graphics.Matrix.ScaleToFit; 23 24import java.awt.geom.AffineTransform; 25import java.awt.geom.NoninvertibleTransformException; 26 27/** 28 * Delegate implementing the native methods of android.graphics.Matrix 29 * 30 * Through the layoutlib_create tool, the original native methods of Matrix have been replaced 31 * by calls to methods of the same name in this delegate class. 32 * 33 * This class behaves like the original native implementation, but in Java, keeping previously 34 * native data into its own objects and mapping them to int that are sent back and forth between 35 * it and the original Matrix class. 36 * 37 * @see DelegateManager 38 * 39 */ 40public final class Matrix_Delegate { 41 42 private final static int MATRIX_SIZE = 9; 43 44 // ---- delegate manager ---- 45 private static final DelegateManager<Matrix_Delegate> sManager = 46 new DelegateManager<Matrix_Delegate>(); 47 48 // ---- delegate data ---- 49 private float mValues[] = new float[MATRIX_SIZE]; 50 51 // ---- Public Helper methods ---- 52 53 public static Matrix_Delegate getDelegate(int native_instance) { 54 return sManager.getDelegate(native_instance); 55 } 56 57 /** 58 * Returns an {@link AffineTransform} matching the given Matrix. 59 */ 60 public static AffineTransform getAffineTransform(Matrix m) { 61 Matrix_Delegate delegate = sManager.getDelegate(m.native_instance); 62 if (delegate == null) { 63 assert false; 64 return null; 65 } 66 67 return getAffineTransform(delegate); 68 } 69 70 public static boolean hasPerspective(Matrix m) { 71 Matrix_Delegate delegate = sManager.getDelegate(m.native_instance); 72 if (delegate == null) { 73 assert false; 74 return false; 75 } 76 77 return (delegate.mValues[6] != 0 || delegate.mValues[7] != 0 || delegate.mValues[8] != 1); 78 } 79 80 /** 81 * Sets the content of the matrix with the content of another matrix. 82 */ 83 public void set(Matrix_Delegate matrix) { 84 System.arraycopy(matrix.mValues, 0, mValues, 0, MATRIX_SIZE); 85 } 86 87 /** 88 * Resets the matrix to be the identity matrix. 89 */ 90 public void reset() { 91 reset(mValues); 92 } 93 94 /** 95 * Returns whether or not the matrix is identity. 96 */ 97 public boolean isIdentity() { 98 for (int i = 0, k = 0; i < 3; i++) { 99 for (int j = 0; j < 3; j++, k++) { 100 if (mValues[k] != ((i==j) ? 1 : 0)) { 101 return false; 102 } 103 } 104 } 105 106 return true; 107 } 108 109 110 // ---- native methods ---- 111 112 /*package*/ static int native_create(int native_src_or_zero) { 113 // create the delegate 114 Matrix_Delegate newDelegate = new Matrix_Delegate(); 115 116 // copy from values if needed. 117 if (native_src_or_zero > 0) { 118 Matrix_Delegate oldDelegate = sManager.getDelegate(native_src_or_zero); 119 if (oldDelegate != null) { 120 System.arraycopy( 121 oldDelegate.mValues, 0, 122 newDelegate.mValues, 0, 123 MATRIX_SIZE); 124 } 125 } 126 127 return sManager.addDelegate(newDelegate); 128 } 129 130 /*package*/ static boolean native_isIdentity(int native_object) { 131 Matrix_Delegate d = sManager.getDelegate(native_object); 132 if (d == null) { 133 assert false; 134 return false; 135 } 136 137 return d.isIdentity(); 138 } 139 140 /*package*/ static boolean native_rectStaysRect(int native_object) { 141 Matrix_Delegate d = sManager.getDelegate(native_object); 142 if (d == null) { 143 assert false; 144 return true; 145 } 146 147 return (d.computeTypeMask() & kRectStaysRect_Mask) != 0; 148 } 149 150 /*package*/ static void native_reset(int native_object) { 151 Matrix_Delegate d = sManager.getDelegate(native_object); 152 if (d == null) { 153 assert false; 154 return; 155 } 156 157 reset(d.mValues); 158 } 159 160 /*package*/ static void native_set(int native_object, int other) { 161 Matrix_Delegate d = sManager.getDelegate(native_object); 162 if (d == null) { 163 assert false; 164 return; 165 } 166 167 Matrix_Delegate src = sManager.getDelegate(other); 168 if (src == null) { 169 assert false; 170 return; 171 } 172 173 System.arraycopy(src.mValues, 0, d.mValues, 0, MATRIX_SIZE); 174 } 175 176 /*package*/ static void native_setTranslate(int native_object, float dx, float dy) { 177 Matrix_Delegate d = sManager.getDelegate(native_object); 178 if (d == null) { 179 assert false; 180 return; 181 } 182 183 setTranslate(d.mValues, dx, dy); 184 } 185 186 /*package*/ static void native_setScale(int native_object, float sx, float sy, float px, float py) { 187 Matrix_Delegate d = sManager.getDelegate(native_object); 188 if (d == null) { 189 assert false; 190 return; 191 } 192 193 d.mValues = getScale(sx, sy, px, py); 194 } 195 196 /*package*/ static void native_setScale(int native_object, float sx, float sy) { 197 Matrix_Delegate d = sManager.getDelegate(native_object); 198 if (d == null) { 199 assert false; 200 return; 201 } 202 203 d.mValues[0] = sx; 204 d.mValues[1] = 0; 205 d.mValues[2] = 0; 206 d.mValues[3] = 0; 207 d.mValues[4] = sy; 208 d.mValues[5] = 0; 209 d.mValues[6] = 0; 210 d.mValues[7] = 0; 211 d.mValues[8] = 1; 212 } 213 214 /*package*/ static void native_setRotate(int native_object, float degrees, float px, float py) { 215 Matrix_Delegate d = sManager.getDelegate(native_object); 216 if (d == null) { 217 assert false; 218 return; 219 } 220 221 d.mValues = getRotate(degrees, px, py); 222 } 223 224 /*package*/ static void native_setRotate(int native_object, float degrees) { 225 Matrix_Delegate d = sManager.getDelegate(native_object); 226 if (d == null) { 227 assert false; 228 return; 229 } 230 231 setRotate(d.mValues, degrees); 232 } 233 234 /*package*/ static void native_setSinCos(int native_object, float sinValue, float cosValue, 235 float px, float py) { 236 Matrix_Delegate d = sManager.getDelegate(native_object); 237 if (d == null) { 238 assert false; 239 return; 240 } 241 242 // TODO: do it in one pass 243 244 // translate so that the pivot is in 0,0 245 setTranslate(d.mValues, -px, -py); 246 247 // scale 248 d.postTransform(getRotate(sinValue, cosValue)); 249 // translate back the pivot 250 d.postTransform(getTranslate(px, py)); 251 } 252 253 /*package*/ static void native_setSinCos(int native_object, float sinValue, float cosValue) { 254 Matrix_Delegate d = sManager.getDelegate(native_object); 255 if (d == null) { 256 assert false; 257 return; 258 } 259 260 setRotate(d.mValues, sinValue, cosValue); 261 } 262 263 /*package*/ static void native_setSkew(int native_object, float kx, float ky, float px, float py) { 264 Matrix_Delegate d = sManager.getDelegate(native_object); 265 if (d == null) { 266 assert false; 267 return; 268 } 269 270 d.mValues = getSkew(kx, ky, px, py); 271 } 272 273 /*package*/ static void native_setSkew(int native_object, float kx, float ky) { 274 Matrix_Delegate d = sManager.getDelegate(native_object); 275 if (d == null) { 276 assert false; 277 return; 278 } 279 280 d.mValues[0] = 1; 281 d.mValues[1] = kx; 282 d.mValues[2] = -0; 283 d.mValues[3] = ky; 284 d.mValues[4] = 1; 285 d.mValues[5] = 0; 286 d.mValues[6] = 0; 287 d.mValues[7] = 0; 288 d.mValues[8] = 1; 289 } 290 291 /*package*/ static boolean native_setConcat(int native_object, int a, int b) { 292 if (a == native_object) { 293 return native_preConcat(native_object, b); 294 } else if (b == native_object) { 295 return native_postConcat(native_object, a); 296 } 297 298 Matrix_Delegate d = sManager.getDelegate(native_object); 299 if (d == null) { 300 assert false; 301 return false; 302 } 303 304 Matrix_Delegate a_mtx = sManager.getDelegate(a); 305 if (a_mtx == null) { 306 assert false; 307 return false; 308 } 309 310 Matrix_Delegate b_mtx = sManager.getDelegate(b); 311 if (b_mtx == null) { 312 assert false; 313 return false; 314 } 315 316 multiply(d.mValues, a_mtx.mValues, b_mtx.mValues); 317 318 return true; 319 } 320 321 /*package*/ static boolean native_preTranslate(int native_object, float dx, float dy) { 322 Matrix_Delegate d = sManager.getDelegate(native_object); 323 if (d == null) { 324 assert false; 325 return false; 326 } 327 328 d.preTransform(getTranslate(dx, dy)); 329 return true; 330 } 331 332 /*package*/ static boolean native_preScale(int native_object, float sx, float sy, 333 float px, float py) { 334 Matrix_Delegate d = sManager.getDelegate(native_object); 335 if (d == null) { 336 assert false; 337 return false; 338 } 339 340 d.preTransform(getScale(sx, sy, px, py)); 341 return true; 342 } 343 344 /*package*/ static boolean native_preScale(int native_object, float sx, float sy) { 345 Matrix_Delegate d = sManager.getDelegate(native_object); 346 if (d == null) { 347 assert false; 348 return false; 349 } 350 351 d.preTransform(getScale(sx, sy)); 352 return true; 353 } 354 355 /*package*/ static boolean native_preRotate(int native_object, float degrees, float px, float py) { 356 Matrix_Delegate d = sManager.getDelegate(native_object); 357 if (d == null) { 358 assert false; 359 return false; 360 } 361 362 d.preTransform(getRotate(degrees, px, py)); 363 return true; 364 } 365 366 /*package*/ static boolean native_preRotate(int native_object, float degrees) { 367 Matrix_Delegate d = sManager.getDelegate(native_object); 368 if (d == null) { 369 assert false; 370 return false; 371 } 372 373 double rad = Math.toRadians(degrees); 374 float sin = (float)Math.sin(rad); 375 float cos = (float)Math.cos(rad); 376 377 d.preTransform(getRotate(sin, cos)); 378 return true; 379 } 380 381 /*package*/ static boolean native_preSkew(int native_object, float kx, float ky, 382 float px, float py) { 383 Matrix_Delegate d = sManager.getDelegate(native_object); 384 if (d == null) { 385 assert false; 386 return false; 387 } 388 389 d.preTransform(getSkew(kx, ky, px, py)); 390 return true; 391 } 392 393 /*package*/ static boolean native_preSkew(int native_object, float kx, float ky) { 394 Matrix_Delegate d = sManager.getDelegate(native_object); 395 if (d == null) { 396 assert false; 397 return false; 398 } 399 400 d.preTransform(getSkew(kx, ky)); 401 return true; 402 } 403 404 /*package*/ static boolean native_preConcat(int native_object, int other_matrix) { 405 Matrix_Delegate d = sManager.getDelegate(native_object); 406 if (d == null) { 407 assert false; 408 return false; 409 } 410 411 Matrix_Delegate other = sManager.getDelegate(other_matrix); 412 if (d == null) { 413 assert false; 414 return false; 415 } 416 417 d.preTransform(other.mValues); 418 return true; 419 } 420 421 /*package*/ static boolean native_postTranslate(int native_object, float dx, float dy) { 422 Matrix_Delegate d = sManager.getDelegate(native_object); 423 if (d == null) { 424 assert false; 425 return false; 426 } 427 428 d.postTransform(getTranslate(dx, dy)); 429 return true; 430 } 431 432 /*package*/ static boolean native_postScale(int native_object, float sx, float sy, 433 float px, float py) { 434 Matrix_Delegate d = sManager.getDelegate(native_object); 435 if (d == null) { 436 assert false; 437 return false; 438 } 439 440 d.postTransform(getScale(sx, sy, px, py)); 441 return true; 442 } 443 444 /*package*/ static boolean native_postScale(int native_object, float sx, float sy) { 445 Matrix_Delegate d = sManager.getDelegate(native_object); 446 if (d == null) { 447 assert false; 448 return false; 449 } 450 451 d.postTransform(getScale(sx, sy)); 452 return true; 453 } 454 455 /*package*/ static boolean native_postRotate(int native_object, float degrees, float px, float py) { 456 Matrix_Delegate d = sManager.getDelegate(native_object); 457 if (d == null) { 458 assert false; 459 return false; 460 } 461 462 d.preTransform(getRotate(degrees, px, py)); 463 return true; 464 } 465 466 /*package*/ static boolean native_postRotate(int native_object, float degrees) { 467 Matrix_Delegate d = sManager.getDelegate(native_object); 468 if (d == null) { 469 assert false; 470 return false; 471 } 472 473 d.postTransform(getRotate(degrees)); 474 return true; 475 } 476 477 /*package*/ static boolean native_postSkew(int native_object, float kx, float ky, 478 float px, float py) { 479 Matrix_Delegate d = sManager.getDelegate(native_object); 480 if (d == null) { 481 assert false; 482 return false; 483 } 484 485 d.postTransform(getSkew(kx, ky, px, py)); 486 return true; 487 } 488 489 /*package*/ static boolean native_postSkew(int native_object, float kx, float ky) { 490 Matrix_Delegate d = sManager.getDelegate(native_object); 491 if (d == null) { 492 assert false; 493 return false; 494 } 495 496 d.postTransform(getSkew(kx, ky)); 497 return true; 498 } 499 500 /*package*/ static boolean native_postConcat(int native_object, int other_matrix) { 501 Matrix_Delegate d = sManager.getDelegate(native_object); 502 if (d == null) { 503 assert false; 504 return false; 505 } 506 507 Matrix_Delegate other = sManager.getDelegate(other_matrix); 508 if (d == null) { 509 assert false; 510 return false; 511 } 512 513 d.postTransform(other.mValues); 514 return true; 515 } 516 517 /*package*/ static boolean native_setRectToRect(int native_object, RectF src, RectF dst, int stf) { 518 Matrix_Delegate d = sManager.getDelegate(native_object); 519 if (d == null) { 520 assert false; 521 return false; 522 } 523 524 if (src.isEmpty()) { 525 reset(d.mValues); 526 return false; 527 } 528 529 if (dst.isEmpty()) { 530 d.mValues[0] = d.mValues[1] = d.mValues[2] = d.mValues[3] = d.mValues[4] = d.mValues[5] 531 = d.mValues[6] = d.mValues[7] = 0; 532 d.mValues[8] = 1; 533 } else { 534 float tx, sx = dst.width() / src.width(); 535 float ty, sy = dst.height() / src.height(); 536 boolean xLarger = false; 537 538 if (stf != ScaleToFit.FILL.nativeInt) { 539 if (sx > sy) { 540 xLarger = true; 541 sx = sy; 542 } else { 543 sy = sx; 544 } 545 } 546 547 tx = dst.left - src.left * sx; 548 ty = dst.top - src.top * sy; 549 if (stf == ScaleToFit.CENTER.nativeInt || stf == ScaleToFit.END.nativeInt) { 550 float diff; 551 552 if (xLarger) { 553 diff = dst.width() - src.width() * sy; 554 } else { 555 diff = dst.height() - src.height() * sy; 556 } 557 558 if (stf == ScaleToFit.CENTER.nativeInt) { 559 diff = diff / 2; 560 } 561 562 if (xLarger) { 563 tx += diff; 564 } else { 565 ty += diff; 566 } 567 } 568 569 d.mValues[0] = sx; 570 d.mValues[4] = sy; 571 d.mValues[2] = tx; 572 d.mValues[5] = ty; 573 d.mValues[1] = d.mValues[3] = d.mValues[6] = d.mValues[7] = 0; 574 575 } 576 // shared cleanup 577 d.mValues[8] = 1; 578 return true; 579 } 580 581 /*package*/ static boolean native_setPolyToPoly(int native_object, float[] src, int srcIndex, 582 float[] dst, int dstIndex, int pointCount) { 583 // FIXME 584 throw new UnsupportedOperationException("Native delegate needed: Matrix_Delegate.native_setPolyToPoly"); 585 } 586 587 /*package*/ static boolean native_invert(int native_object, int inverse) { 588 Matrix_Delegate d = sManager.getDelegate(native_object); 589 if (d == null) { 590 assert false; 591 return false; 592 } 593 594 Matrix_Delegate inv_mtx = sManager.getDelegate(inverse); 595 if (inv_mtx == null) { 596 assert false; 597 return false; 598 } 599 600 601 try { 602 AffineTransform affineTransform = getAffineTransform(d); 603 AffineTransform inverseTransform = affineTransform.createInverse(); 604 inv_mtx.mValues[0] = (float)inverseTransform.getScaleX(); 605 inv_mtx.mValues[1] = (float)inverseTransform.getShearX(); 606 inv_mtx.mValues[2] = (float)inverseTransform.getTranslateX(); 607 inv_mtx.mValues[3] = (float)inverseTransform.getScaleX(); 608 inv_mtx.mValues[4] = (float)inverseTransform.getShearY(); 609 inv_mtx.mValues[5] = (float)inverseTransform.getTranslateY(); 610 611 return true; 612 } catch (NoninvertibleTransformException e) { 613 return false; 614 } 615 } 616 617 /*package*/ static void native_mapPoints(int native_object, float[] dst, int dstIndex, 618 float[] src, int srcIndex, int ptCount, boolean isPts) { 619 Matrix_Delegate d = sManager.getDelegate(native_object); 620 if (d == null) { 621 assert false; 622 return; 623 } 624 625 if (isPts) { 626 d.mapPoints(dst, dstIndex, src, srcIndex, ptCount); 627 } else { 628 // src is vectors 629 // FIXME 630 throw new UnsupportedOperationException("Native delegate needed: Matrix_Delegate.native_mapPoints"); 631 } 632 } 633 634 /*package*/ static boolean native_mapRect(int native_object, RectF dst, RectF src) { 635 Matrix_Delegate d = sManager.getDelegate(native_object); 636 if (d == null) { 637 assert false; 638 return false; 639 } 640 641 // array with 4 corners 642 float[] corners = new float[] { 643 src.left, src.top, 644 src.right, src.top, 645 src.right, src.bottom, 646 src.left, src.bottom, 647 }; 648 649 // apply the transform to them. 650 d.mapPoints(corners); 651 652 // now put the result in the rect. We take the min/max of Xs and min/max of Ys 653 dst.left = Math.min(Math.min(corners[0], corners[2]), Math.min(corners[4], corners[6])); 654 dst.right = Math.max(Math.max(corners[0], corners[2]), Math.max(corners[4], corners[6])); 655 656 dst.top = Math.min(Math.min(corners[1], corners[3]), Math.min(corners[5], corners[7])); 657 dst.bottom = Math.max(Math.max(corners[1], corners[3]), Math.max(corners[5], corners[7])); 658 659 660 return (d.computeTypeMask() & kRectStaysRect_Mask) != 0; 661 } 662 663 /*package*/ static float native_mapRadius(int native_object, float radius) { 664 // FIXME 665 throw new UnsupportedOperationException("Native delegate needed: Matrix_Delegate.native_mapRadius"); 666 } 667 668 /*package*/ static void native_getValues(int native_object, float[] values) { 669 Matrix_Delegate d = sManager.getDelegate(native_object); 670 if (d == null) { 671 assert false; 672 return; 673 } 674 675 System.arraycopy(d.mValues, 0, d.mValues, 0, MATRIX_SIZE); 676 } 677 678 /*package*/ static void native_setValues(int native_object, float[] values) { 679 Matrix_Delegate d = sManager.getDelegate(native_object); 680 if (d == null) { 681 assert false; 682 return; 683 } 684 685 System.arraycopy(values, 0, d.mValues, 0, MATRIX_SIZE); 686 } 687 688 /*package*/ static boolean native_equals(int native_a, int native_b) { 689 Matrix_Delegate a = sManager.getDelegate(native_a); 690 if (a == null) { 691 assert false; 692 return false; 693 } 694 695 Matrix_Delegate b = sManager.getDelegate(native_b); 696 if (b == null) { 697 assert false; 698 return false; 699 } 700 701 for (int i = 0 ; i < MATRIX_SIZE ; i++) { 702 if (a.mValues[i] != b.mValues[i]) { 703 return false; 704 } 705 } 706 707 return true; 708 } 709 710 /*package*/ static void finalizer(int native_instance) { 711 sManager.removeDelegate(native_instance); 712 } 713 714 // ---- Private helper methods ---- 715 716 private static AffineTransform getAffineTransform(Matrix_Delegate d) { 717 return getAffineTransform(d.mValues); 718 } 719 720 /*package*/ static AffineTransform getAffineTransform(float[] matrix) { 721 // the AffineTransform constructor takes the value in a different order 722 // for a matrix [ 0 1 2 ] 723 // [ 3 4 5 ] 724 // the order is 0, 3, 1, 4, 2, 5... 725 return new AffineTransform( 726 matrix[0], matrix[3], matrix[1], 727 matrix[4], matrix[2], matrix[5]); 728 } 729 730 731 /** 732 * Reset a matrix to the identity 733 */ 734 private static void reset(float[] mtx) { 735 for (int i = 0, k = 0; i < 3; i++) { 736 for (int j = 0; j < 3; j++, k++) { 737 mtx[k] = ((i==j) ? 1 : 0); 738 } 739 } 740 } 741 742 @SuppressWarnings("unused") 743 private final static int kIdentity_Mask = 0; 744 private final static int kTranslate_Mask = 0x01; //!< set if the matrix has translation 745 private final static int kScale_Mask = 0x02; //!< set if the matrix has X or Y scale 746 private final static int kAffine_Mask = 0x04; //!< set if the matrix skews or rotates 747 private final static int kPerspective_Mask = 0x08; //!< set if the matrix is in perspective 748 private final static int kRectStaysRect_Mask = 0x10; 749 @SuppressWarnings("unused") 750 private final static int kUnknown_Mask = 0x80; 751 752 @SuppressWarnings("unused") 753 private final static int kAllMasks = kTranslate_Mask | 754 kScale_Mask | 755 kAffine_Mask | 756 kPerspective_Mask | 757 kRectStaysRect_Mask; 758 759 // these guys align with the masks, so we can compute a mask from a variable 0/1 760 @SuppressWarnings("unused") 761 private final static int kTranslate_Shift = 0; 762 @SuppressWarnings("unused") 763 private final static int kScale_Shift = 1; 764 @SuppressWarnings("unused") 765 private final static int kAffine_Shift = 2; 766 @SuppressWarnings("unused") 767 private final static int kPerspective_Shift = 3; 768 private final static int kRectStaysRect_Shift = 4; 769 770 private int computeTypeMask() { 771 int mask = 0; 772 773 if (mValues[6] != 0. || mValues[7] != 0. || mValues[8] != 1.) { 774 mask |= kPerspective_Mask; 775 } 776 777 if (mValues[2] != 0. || mValues[5] != 0.) { 778 mask |= kTranslate_Mask; 779 } 780 781 float m00 = mValues[0]; 782 float m01 = mValues[1]; 783 float m10 = mValues[3]; 784 float m11 = mValues[4]; 785 786 if (m01 != 0. || m10 != 0.) { 787 mask |= kAffine_Mask; 788 } 789 790 if (m00 != 1. || m11 != 1.) { 791 mask |= kScale_Mask; 792 } 793 794 if ((mask & kPerspective_Mask) == 0) { 795 // map non-zero to 1 796 int im00 = m00 != 0 ? 1 : 0; 797 int im01 = m01 != 0 ? 1 : 0; 798 int im10 = m10 != 0 ? 1 : 0; 799 int im11 = m11 != 0 ? 1 : 0; 800 801 // record if the (p)rimary and (s)econdary diagonals are all 0 or 802 // all non-zero (answer is 0 or 1) 803 int dp0 = (im00 | im11) ^ 1; // true if both are 0 804 int dp1 = im00 & im11; // true if both are 1 805 int ds0 = (im01 | im10) ^ 1; // true if both are 0 806 int ds1 = im01 & im10; // true if both are 1 807 808 // return 1 if primary is 1 and secondary is 0 or 809 // primary is 0 and secondary is 1 810 mask |= ((dp0 & ds1) | (dp1 & ds0)) << kRectStaysRect_Shift; 811 } 812 813 return mask; 814 } 815 816 /** 817 * Adds the given transformation to the current Matrix 818 * <p/>This in effect does this = this*matrix 819 * @param matrix 820 */ 821 private void postTransform(float[] matrix) { 822 float[] tmp = new float[9]; 823 multiply(tmp, mValues, matrix); 824 mValues = tmp; 825 } 826 827 /** 828 * Adds the given transformation to the current Matrix 829 * <p/>This in effect does this = matrix*this 830 * @param matrix 831 */ 832 private void preTransform(float[] matrix) { 833 float[] tmp = new float[9]; 834 multiply(tmp, matrix, mValues); 835 mValues = tmp; 836 } 837 838 /** 839 * Apply this matrix to the array of 2D points specified by src, and write 840 * the transformed points into the array of points specified by dst. The 841 * two arrays represent their "points" as pairs of floats [x, y]. 842 * 843 * @param dst The array of dst points (x,y pairs) 844 * @param dstIndex The index of the first [x,y] pair of dst floats 845 * @param src The array of src points (x,y pairs) 846 * @param srcIndex The index of the first [x,y] pair of src floats 847 * @param pointCount The number of points (x,y pairs) to transform 848 */ 849 850 private void mapPoints(float[] dst, int dstIndex, float[] src, int srcIndex, 851 int pointCount) { 852 //checkPointArrays(src, srcIndex, dst, dstIndex, pointCount); 853 854 float[] tmpDest = dst; 855 boolean inPlace = dst == src; 856 if (inPlace) { 857 tmpDest = new float[dstIndex + pointCount * 2]; 858 } 859 860 for (int i = 0 ; i < pointCount ; i++) { 861 // just in case we are doing in place, we better put this in temp vars 862 float x = mValues[0] * src[i + srcIndex] + 863 mValues[1] * src[i + srcIndex + 1] + 864 mValues[2]; 865 float y = mValues[3] * src[i + srcIndex] + 866 mValues[4] * src[i + srcIndex + 1] + 867 mValues[5]; 868 869 tmpDest[i + dstIndex] = x; 870 tmpDest[i + dstIndex + 1] = y; 871 } 872 873 if (inPlace) { 874 System.arraycopy(tmpDest, dstIndex, dst, dstIndex, pointCount * 2); 875 } 876 } 877 878 /** 879 * Apply this matrix to the array of 2D points, and write the transformed 880 * points back into the array 881 * 882 * @param pts The array [x0, y0, x1, y1, ...] of points to transform. 883 */ 884 885 private void mapPoints(float[] pts) { 886 mapPoints(pts, 0, pts, 0, pts.length >> 1); 887 } 888 889 /** 890 * multiply two matrices and store them in a 3rd. 891 * <p/>This in effect does dest = a*b 892 * dest cannot be the same as a or b. 893 */ 894 /*package*/ static void multiply(float dest[], float[] a, float[] b) { 895 // first row 896 dest[0] = b[0] * a[0] + b[1] * a[3] + b[2] * a[6]; 897 dest[1] = b[0] * a[1] + b[1] * a[4] + b[2] * a[7]; 898 dest[2] = b[0] * a[2] + b[1] * a[5] + b[2] * a[8]; 899 900 // 2nd row 901 dest[3] = b[3] * a[0] + b[4] * a[3] + b[5] * a[6]; 902 dest[4] = b[3] * a[1] + b[4] * a[4] + b[5] * a[7]; 903 dest[5] = b[3] * a[2] + b[4] * a[5] + b[5] * a[8]; 904 905 // 3rd row 906 dest[6] = b[6] * a[0] + b[7] * a[3] + b[8] * a[6]; 907 dest[7] = b[6] * a[1] + b[7] * a[4] + b[8] * a[7]; 908 dest[8] = b[6] * a[2] + b[7] * a[5] + b[8] * a[8]; 909 } 910 911 /** 912 * Returns a matrix that represents a given translate 913 * @param dx 914 * @param dy 915 * @return 916 */ 917 /*package*/ static float[] getTranslate(float dx, float dy) { 918 return setTranslate(new float[9], dx, dy); 919 } 920 921 /*package*/ static float[] setTranslate(float[] dest, float dx, float dy) { 922 dest[0] = 1; 923 dest[1] = 0; 924 dest[2] = dx; 925 dest[3] = 0; 926 dest[4] = 1; 927 dest[5] = dy; 928 dest[6] = 0; 929 dest[7] = 0; 930 dest[8] = 1; 931 return dest; 932 } 933 934 /*package*/ static float[] getScale(float sx, float sy) { 935 return new float[] { sx, 0, 0, 0, sy, 0, 0, 0, 1 }; 936 } 937 938 /** 939 * Returns a matrix that represents the given scale info. 940 * @param sx 941 * @param sy 942 * @param px 943 * @param py 944 */ 945 /*package*/ static float[] getScale(float sx, float sy, float px, float py) { 946 float[] tmp = new float[9]; 947 float[] tmp2 = new float[9]; 948 949 // TODO: do it in one pass 950 951 // translate tmp so that the pivot is in 0,0 952 setTranslate(tmp, -px, -py); 953 954 // scale into tmp2 955 multiply(tmp2, tmp, getScale(sx, sy)); 956 957 // translate back the pivot back into tmp 958 multiply(tmp, tmp2, getTranslate(px, py)); 959 960 return tmp; 961 } 962 963 964 /*package*/ static float[] getRotate(float degrees) { 965 double rad = Math.toRadians(degrees); 966 float sin = (float)Math.sin(rad); 967 float cos = (float)Math.cos(rad); 968 969 return getRotate(sin, cos); 970 } 971 972 /*package*/ static float[] getRotate(float sin, float cos) { 973 return setRotate(new float[9], sin, cos); 974 } 975 976 /*package*/ static float[] setRotate(float[] dest, float degrees) { 977 double rad = Math.toRadians(degrees); 978 float sin = (float)Math.sin(rad); 979 float cos = (float)Math.cos(rad); 980 981 return setRotate(dest, sin, cos); 982 } 983 984 /*package*/ static float[] setRotate(float[] dest, float sin, float cos) { 985 dest[0] = cos; 986 dest[1] = -sin; 987 dest[2] = 0; 988 dest[3] = sin; 989 dest[4] = cos; 990 dest[5] = 0; 991 dest[6] = 0; 992 dest[7] = 0; 993 dest[8] = 1; 994 return dest; 995 } 996 997 /*package*/ static float[] getRotate(float degrees, float px, float py) { 998 float[] tmp = new float[9]; 999 float[] tmp2 = new float[9]; 1000 1001 // TODO: do it in one pass 1002 1003 // translate so that the pivot is in 0,0 1004 setTranslate(tmp, -px, -py); 1005 1006 // rotate into tmp2 1007 double rad = Math.toRadians(degrees); 1008 float cos = (float)Math.cos(rad); 1009 float sin = (float)Math.sin(rad); 1010 multiply(tmp2, tmp, getRotate(sin, cos)); 1011 1012 // translate back the pivot back into tmp 1013 multiply(tmp, tmp2, getTranslate(px, py)); 1014 1015 return tmp; 1016 } 1017 1018 /*package*/ static float[] getSkew(float kx, float ky) { 1019 return new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 }; 1020 } 1021 1022 /*package*/ static float[] getSkew(float kx, float ky, float px, float py) { 1023 float[] tmp = new float[9]; 1024 float[] tmp2 = new float[9]; 1025 1026 // TODO: do it in one pass 1027 1028 // translate so that the pivot is in 0,0 1029 setTranslate(tmp, -px, -py); 1030 1031 // skew into tmp2 1032 multiply(tmp2, tmp, new float[] { 1, kx, 0, ky, 1, 0, 0, 0, 1 }); 1033 // translate back the pivot back into tmp 1034 multiply(tmp, tmp2, getTranslate(px, py)); 1035 1036 return tmp; 1037 } 1038 1039 1040} 1041