1 /* 2 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.javafx.scene.transform; 27 28 import com.sun.javafx.geom.transform.Affine2D; 29 import com.sun.javafx.geom.transform.Affine3D; 30 import com.sun.javafx.geom.transform.BaseTransform; 31 import javafx.geometry.Point2D; 32 import javafx.geometry.Point3D; 33 import javafx.scene.transform.NonInvertibleTransformException; 34 import javafx.scene.transform.Transform; 35 import javafx.scene.transform.Affine; 36 37 /** 38 * Internal utilities for transformations 39 */ 40 public class TransformUtils { 41 42 /** 43 * Creates an immutable arbitrary transformation. 44 * This method is not intended for public use, users should use the Affine 45 * class. 46 */ 47 public static Transform immutableTransform( 48 double mxx, double mxy, double mxz, double tx, 49 double myx, double myy, double myz, double ty, 50 double mzx, double mzy, double mzz, double tz) { 51 return new ImmutableTransform( 52 mxx, mxy, mxz, tx, 53 myx, myy, myz, ty, 54 mzx, mzy, mzz, tz); 55 } 56 57 /** 58 * Creates an immutable transformation filled with current values 59 * from the given transformation. 60 * This method is not intended for public use, users should use the Affine 61 * class. 62 */ 63 public static Transform immutableTransform(Transform t) { 64 return new ImmutableTransform( 65 t.getMxx(), t.getMxy(), t.getMxz(), t.getTx(), 66 t.getMyx(), t.getMyy(), t.getMyz(), t.getTy(), 67 t.getMzx(), t.getMzy(), t.getMzz(), t.getTz()); 68 } 69 70 /** 71 * Creates an immutable arbitrary transformation. 72 * If the given instance is not null, it is reused. 73 * This method is not intended for public use, users should use the Affine 74 * class. 75 * @throws ClassCastException if the given transform to be reused 76 * is not instance of ImmutableTransform 77 */ 78 public static Transform immutableTransform(Transform reuse, 79 double mxx, double mxy, double mxz, double tx, 80 double myx, double myy, double myz, double ty, 81 double mzx, double mzy, double mzz, double tz) { 82 83 if (reuse == null) { 84 return new ImmutableTransform( 85 mxx, mxy, mxz, tx, 86 myx, myy, myz, ty, 87 mzx, mzy, mzz, tz); 88 } 89 90 ((ImmutableTransform) reuse).setToTransform( 91 mxx, mxy, mxz, tx, 92 myx, myy, myz, ty, 93 mzx, mzy, mzz, tz); 94 return reuse; 95 } 96 97 /** 98 * Creates an immutable transformation filled with current values 99 * from the given transformation. 100 * If the given instance is not null, it is reused. 101 * This method is not intended for public use, users should use the Affine 102 * class. 103 * @throws ClassCastException if the given transform to be reused 104 * is not instance of ImmutableTransform 105 */ 106 public static Transform immutableTransform(Transform reuse, 107 Transform t) { 108 return immutableTransform((ImmutableTransform) reuse, 109 t.getMxx(), t.getMxy(), t.getMxz(), t.getTx(), 110 t.getMyx(), t.getMyy(), t.getMyz(), t.getTy(), 111 t.getMzx(), t.getMzy(), t.getMzz(), t.getTz()); 112 } 113 114 /** 115 * Creates an immutable transformation filled with concatenation 116 * of the given transformations. 117 * If the given instance is not null, it is reused. 118 * This method is not intended for public use, users should use the Affine 119 * class. 120 * @throws ClassCastException if one of the given transforms 121 * is not instance of ImmutableTransform 122 */ 123 public static Transform immutableTransform(Transform reuse, 124 Transform left, Transform right) { 125 126 if (reuse == null) { 127 reuse = new ImmutableTransform(); 128 } 129 130 ((ImmutableTransform) reuse).setToConcatenation( 131 (ImmutableTransform) left, ((ImmutableTransform) right)); 132 133 return reuse; 134 } 135 136 /** 137 * Immutable transformation with performance optimizations based on Affine. 138 * 139 * From user's perspective, this transform is immutable. However, we can 140 * modify it internally. This allows for reusing instances that were 141 * not handed to users. The caller is responsible for not modifying 142 * user-visible instances. 143 * 144 * Note: can't override Transform's package private methods so they cannot 145 * be optimized. Currently not a big deal. 146 */ 147 static class ImmutableTransform extends Transform { 148 149 private static final int APPLY_IDENTITY = 0; 150 private static final int APPLY_TRANSLATE = 1; 151 private static final int APPLY_SCALE = 2; 152 private static final int APPLY_SHEAR = 4; 153 private static final int APPLY_NON_3D = 0; 154 private static final int APPLY_3D_COMPLEX = 4; 155 private transient int state2d; 156 private transient int state3d; 157 158 private double xx; 159 private double xy; 160 private double xz; 161 private double yx; 162 private double yy; 163 private double yz; 164 private double zx; 165 private double zy; 166 private double zz; 167 private double xt; 168 private double yt; 169 private double zt; 170 171 public ImmutableTransform() { 172 xx = yy = zz = 1.0; 173 } 174 175 public ImmutableTransform(Transform transform) { 176 this(transform.getMxx(), transform.getMxy(), transform.getMxz(), 177 transform.getTx(), 178 transform.getMyx(), transform.getMyy(), transform.getMyz(), 179 transform.getTy(), 180 transform.getMzx(), transform.getMzy(), transform.getMzz(), 181 transform.getTz()); 182 } 183 184 public ImmutableTransform(double mxx, double mxy, double mxz, double tx, 185 double myx, double myy, double myz, double ty, 186 double mzx, double mzy, double mzz, double tz) { 187 xx = mxx; 188 xy = mxy; 189 xz = mxz; 190 xt = tx; 191 192 yx = myx; 193 yy = myy; 194 yz = myz; 195 yt = ty; 196 197 zx = mzx; 198 zy = mzy; 199 zz = mzz; 200 zt = tz; 201 202 updateState(); 203 } 204 205 // Beware: this is modifying immutable transform! 206 // It is private and it is there just for the purpose of reusing 207 // instances not given to users 208 private void setToTransform(double mxx, double mxy, double mxz, double tx, 209 double myx, double myy, double myz, double ty, 210 double mzx, double mzy, double mzz, double tz) 211 { 212 xx = mxx; 213 xy = mxy; 214 xz = mxz; 215 xt = tx; 216 yx = myx; 217 yy = myy; 218 yz = myz; 219 yt = ty; 220 zx = mzx; 221 zy = mzy; 222 zz = mzz; 223 zt = tz; 224 updateState(); 225 } 226 227 // Beware: this is modifying immutable transform! 228 // It is private and it is there just for the purpose of reusing 229 // instances not given to users 230 private void setToConcatenation(ImmutableTransform left, ImmutableTransform right) { 231 if (left.state3d == APPLY_NON_3D && right.state3d == APPLY_NON_3D) { 232 xx = left.xx * right.xx + left.xy * right.yx; 233 xy = left.xx * right.xy + left.xy * right.yy; 234 xt = left.xx * right.xt + left.xy * right.yt + left.xt; 235 yx = left.yx * right.xx + left.yy * right.yx; 236 yy = left.yx * right.xy + left.yy * right.yy; 237 yt = left.yx * right.xt + left.yy * right.yt + left.yt; 238 if (state3d != APPLY_NON_3D) { 239 xz = yz = zx = zy = zt = 0.0; 240 zz = 1.0; 241 state3d = APPLY_NON_3D; 242 } 243 updateState2D(); 244 } else { 245 xx = left.xx * right.xx + left.xy * right.yx + left.xz * right.zx; 246 xy = left.xx * right.xy + left.xy * right.yy + left.xz * right.zy; 247 xz = left.xx * right.xz + left.xy * right.yz + left.xz * right.zz; 248 xt = left.xx * right.xt + left.xy * right.yt + left.xz * right.zt + left.xt; 249 yx = left.yx * right.xx + left.yy * right.yx + left.yz * right.zx; 250 yy = left.yx * right.xy + left.yy * right.yy + left.yz * right.zy; 251 yz = left.yx * right.xz + left.yy * right.yz + left.yz * right.zz; 252 yt = left.yx * right.xt + left.yy * right.yt + left.yz * right.zt + left.yt; 253 zx = left.zx * right.xx + left.zy * right.yx + left.zz * right.zx; 254 zy = left.zx * right.xy + left.zy * right.yy + left.zz * right.zy; 255 zz = left.zx * right.xz + left.zy * right.yz + left.zz * right.zz; 256 zt = left.zx * right.xt + left.zy * right.yt + left.zz * right.zt + left.zt; 257 updateState(); 258 } 259 // could be further optimized using the states, but that would 260 // require a lot of code (see Affine and all its append* methods) 261 } 262 263 @Override 264 public double getMxx() { 265 return xx; 266 } 267 268 @Override 269 public double getMxy() { 270 return xy; 271 } 272 273 @Override 274 public double getMxz() { 275 return xz; 276 } 277 278 @Override 279 public double getTx() { 280 return xt; 281 } 282 283 @Override 284 public double getMyx() { 285 return yx; 286 } 287 288 @Override 289 public double getMyy() { 290 return yy; 291 } 292 293 @Override 294 public double getMyz() { 295 return yz; 296 } 297 298 @Override 299 public double getTy() { 300 return yt; 301 } 302 303 @Override 304 public double getMzx() { 305 return zx; 306 } 307 308 @Override 309 public double getMzy() { 310 return zy; 311 } 312 313 @Override 314 public double getMzz() { 315 return zz; 316 } 317 318 @Override 319 public double getTz() { 320 return zt; 321 } 322 323 /* ************************************************************************* 324 * * 325 * State getters * 326 * * 327 **************************************************************************/ 328 329 @Override 330 public double determinant() { 331 switch(state3d) { 332 default: 333 stateError(); 334 // cannot reach 335 case APPLY_NON_3D: 336 switch (state2d) { 337 default: 338 stateError(); 339 // cannot reach 340 case APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE: 341 case APPLY_SHEAR | APPLY_SCALE: 342 return xx * yy - xy * yx; 343 case APPLY_SHEAR | APPLY_TRANSLATE: 344 case APPLY_SHEAR: 345 return -(xy* yx); 346 case APPLY_SCALE | APPLY_TRANSLATE: 347 case APPLY_SCALE: 348 return xx * yy; 349 case APPLY_TRANSLATE: 350 case APPLY_IDENTITY: 351 return 1.0; 352 } 353 case APPLY_TRANSLATE: 354 return 1.0; 355 case APPLY_SCALE: 356 case APPLY_SCALE | APPLY_TRANSLATE: 357 return xx * yy * zz; 358 case APPLY_3D_COMPLEX: 359 return (xx* (yy * zz - zy * yz) + 360 xy* (yz * zx - zz * yx) + 361 xz* (yx * zy - zx * yy)); 362 } 363 } 364 365 @Override 366 public Transform createConcatenation(Transform transform) { 367 javafx.scene.transform.Affine a = new Affine(this); 368 a.append(transform); 369 return a; 370 } 371 372 @Override 373 public javafx.scene.transform.Affine createInverse() throws NonInvertibleTransformException { 374 javafx.scene.transform.Affine t = new Affine(this); 375 t.invert(); 376 return t; 377 } 378 379 @Override 380 public Transform clone() { 381 return new ImmutableTransform(this); 382 } 383 384 /* ************************************************************************* 385 * * 386 * Transform, Inverse Transform * 387 * * 388 **************************************************************************/ 389 390 @Override 391 public Point2D transform(double x, double y) { 392 ensureCanTransform2DPoint(); 393 394 switch (state2d) { 395 default: 396 stateError(); 397 // cannot reach 398 case APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE: 399 return new Point2D( 400 xx * x + xy * y + xt, 401 yx * x + yy * y + yt); 402 case APPLY_SHEAR | APPLY_SCALE: 403 return new Point2D( 404 xx * x + xy * y, 405 yx * x + yy * y); 406 case APPLY_SHEAR | APPLY_TRANSLATE: 407 return new Point2D( 408 xy * y + xt, 409 yx * x + yt); 410 case APPLY_SHEAR: 411 return new Point2D(xy * y, yx * x); 412 case APPLY_SCALE | APPLY_TRANSLATE: 413 return new Point2D( 414 xx * x + xt, 415 yy * y + yt); 416 case APPLY_SCALE: 417 return new Point2D(xx * x, yy * y); 418 case APPLY_TRANSLATE: 419 return new Point2D(x + xt, y + yt); 420 case APPLY_IDENTITY: 421 return new Point2D(x, y); 422 } 423 } 424 425 @Override 426 public Point3D transform(double x, double y, double z) { 427 switch (state3d) { 428 default: 429 stateError(); 430 // cannot reach 431 case APPLY_NON_3D: 432 switch (state2d) { 433 default: 434 stateError(); 435 // cannot reach 436 case APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE: 437 return new Point3D( 438 xx * x + xy * y + xt, 439 yx * x + yy * y + yt, z); 440 case APPLY_SHEAR | APPLY_SCALE: 441 return new Point3D( 442 xx * x + xy * y, 443 yx * x + yy * y, z); 444 case APPLY_SHEAR | APPLY_TRANSLATE: 445 return new Point3D( 446 xy * y + xt, yx * x + yt, 447 z); 448 case APPLY_SHEAR: 449 return new Point3D(xy * y, yx * x, z); 450 case APPLY_SCALE | APPLY_TRANSLATE: 451 return new Point3D( 452 xx * x + xt, yy * y + yt, 453 z); 454 case APPLY_SCALE: 455 return new Point3D(xx * x, yy * y, z); 456 case APPLY_TRANSLATE: 457 return new Point3D(x + xt, y + yt, z); 458 case APPLY_IDENTITY: 459 return new Point3D(x, y, z); 460 } 461 case APPLY_TRANSLATE: 462 return new Point3D(x + xt, y + yt, z + zt); 463 case APPLY_SCALE: 464 return new Point3D(xx * x, yy * y, zz * z); 465 case APPLY_SCALE | APPLY_TRANSLATE: 466 return new Point3D( 467 xx * x + xt, 468 yy * y + yt, 469 zz * z + zt); 470 case APPLY_3D_COMPLEX: 471 return new Point3D( 472 xx * x + xy * y + xz * z + xt, 473 yx * x + yy * y + yz * z + yt, 474 zx * x + zy * y + zz * z + zt); 475 } 476 } 477 478 @Override 479 public Point2D deltaTransform(double x, double y) { 480 ensureCanTransform2DPoint(); 481 482 switch (state2d) { 483 default: 484 stateError(); 485 // cannot reach 486 case APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE: 487 case APPLY_SHEAR | APPLY_SCALE: 488 return new Point2D( 489 xx * x + xy * y, 490 yx * x + yy * y); 491 case APPLY_SHEAR | APPLY_TRANSLATE: 492 case APPLY_SHEAR: 493 return new Point2D(xy * y, yx * x); 494 case APPLY_SCALE | APPLY_TRANSLATE: 495 case APPLY_SCALE: 496 return new Point2D(xx * x, yy * y); 497 case APPLY_TRANSLATE: 498 case APPLY_IDENTITY: 499 return new Point2D(x, y); 500 } 501 } 502 503 @Override 504 public Point3D deltaTransform(double x, double y, double z) { 505 switch (state3d) { 506 default: 507 stateError(); 508 // cannot reach 509 case APPLY_NON_3D: 510 switch (state2d) { 511 default: 512 stateError(); 513 // cannot reach 514 case APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE: 515 case APPLY_SHEAR | APPLY_SCALE: 516 return new Point3D( 517 xx * x + xy * y, 518 yx * x + yy * y, z); 519 case APPLY_SHEAR | APPLY_TRANSLATE: 520 case APPLY_SHEAR: 521 return new Point3D(xy * y, yx * x, z); 522 case APPLY_SCALE | APPLY_TRANSLATE: 523 case APPLY_SCALE: 524 return new Point3D(xx * x, yy * y, z); 525 case APPLY_TRANSLATE: 526 case APPLY_IDENTITY: 527 return new Point3D(x, y, z); 528 } 529 case APPLY_TRANSLATE: 530 return new Point3D(x, y, z); 531 case APPLY_SCALE: 532 case APPLY_SCALE | APPLY_TRANSLATE: 533 return new Point3D(xx * x, yy * y, zz * z); 534 case APPLY_3D_COMPLEX: 535 return new Point3D( 536 xx * x + xy * y + xz * z, 537 yx * x + yy * y + yz * z, 538 zx * x + zy * y + zz * z); 539 } 540 } 541 542 @Override 543 public Point2D inverseTransform(double x, double y) 544 throws NonInvertibleTransformException { 545 ensureCanTransform2DPoint(); 546 547 switch (state2d) { 548 default: 549 return super.inverseTransform(x, y); 550 case APPLY_SHEAR | APPLY_TRANSLATE: 551 if (xy == 0.0 || yx == 0.0) { 552 throw new NonInvertibleTransformException("Determinant is 0"); 553 } 554 return new Point2D( 555 (1.0 / yx) * y - yt / yx, 556 (1.0 / xy) * x - xt / xy); 557 case APPLY_SHEAR: 558 if (xy == 0.0 || yx == 0.0) { 559 throw new NonInvertibleTransformException("Determinant is 0"); 560 } 561 return new Point2D((1.0 / yx) * y, (1.0 / xy) * x); 562 case APPLY_SCALE | APPLY_TRANSLATE: 563 if (xx == 0.0 || yy == 0.0) { 564 throw new NonInvertibleTransformException("Determinant is 0"); 565 } 566 return new Point2D( 567 (1.0 / xx) * x - xt / xx, 568 (1.0 / yy) * y - yt / yy); 569 case APPLY_SCALE: 570 if (xx == 0.0 || yy == 0.0) { 571 throw new NonInvertibleTransformException("Determinant is 0"); 572 } 573 return new Point2D((1.0 / xx) * x, (1.0 / yy) * y); 574 case APPLY_TRANSLATE: 575 return new Point2D(x - xt, y - yt); 576 case APPLY_IDENTITY: 577 return new Point2D(x, y); 578 } 579 } 580 581 @Override 582 public Point3D inverseTransform(double x, double y, double z) 583 throws NonInvertibleTransformException { 584 switch(state3d) { 585 default: 586 stateError(); 587 // cannot reach 588 case APPLY_NON_3D: 589 switch (state2d) { 590 default: 591 return super.inverseTransform(x, y, z); 592 case APPLY_SHEAR | APPLY_TRANSLATE: 593 if (xy == 0.0 || yx == 0.0) { 594 throw new NonInvertibleTransformException( 595 "Determinant is 0"); 596 } 597 return new Point3D( 598 (1.0 / yx) * y - yt / yx, 599 (1.0 / xy) * x - xt / xy, z); 600 case APPLY_SHEAR: 601 if (xy == 0.0 || yx == 0.0) { 602 throw new NonInvertibleTransformException( 603 "Determinant is 0"); 604 } 605 return new Point3D( 606 (1.0 / yx) * y, 607 (1.0 / xy) * x, z); 608 case APPLY_SCALE | APPLY_TRANSLATE: 609 if (xx == 0.0 || yy == 0.0) { 610 throw new NonInvertibleTransformException( 611 "Determinant is 0"); 612 } 613 return new Point3D( 614 (1.0 / xx) * x - xt / xx, 615 (1.0 / yy) * y - yt / yy, z); 616 case APPLY_SCALE: 617 if (xx == 0.0 || yy == 0.0) { 618 throw new NonInvertibleTransformException( 619 "Determinant is 0"); 620 } 621 return new Point3D((1.0 / xx) * x, (1.0 / yy) * y, z); 622 case APPLY_TRANSLATE: 623 return new Point3D(x - xt, y - yt, z); 624 case APPLY_IDENTITY: 625 return new Point3D(x, y, z); 626 } 627 case APPLY_TRANSLATE: 628 return new Point3D(x - xt, y - yt, z - zt); 629 case APPLY_SCALE: 630 if (xx == 0.0 || yy == 0.0 || zz == 0.0) { 631 throw new NonInvertibleTransformException("Determinant is 0"); 632 } 633 return new Point3D( 634 (1.0 / xx) * x, 635 (1.0 / yy) * y, 636 (1.0 / zz) * z); 637 case APPLY_SCALE | APPLY_TRANSLATE: 638 if (xx == 0.0 || yy == 0.0 || zz == 0.0) { 639 throw new NonInvertibleTransformException("Determinant is 0"); 640 } 641 return new Point3D( 642 (1.0 / xx) * x - xt / xx, 643 (1.0 / yy) * y - yt / yy, 644 (1.0 / zz) * z - zt / zz); 645 case APPLY_3D_COMPLEX: 646 return super.inverseTransform(x, y, z); 647 } 648 } 649 650 @Override 651 public Point2D inverseDeltaTransform(double x, double y) 652 throws NonInvertibleTransformException { 653 ensureCanTransform2DPoint(); 654 655 switch (state2d) { 656 default: 657 return super.inverseDeltaTransform(x, y); 658 case APPLY_SHEAR | APPLY_TRANSLATE: 659 case APPLY_SHEAR: 660 if (xy == 0.0 || yx == 0.0) { 661 throw new NonInvertibleTransformException("Determinant is 0"); 662 } 663 return new Point2D((1.0 / yx) * y, (1.0 / xy) * x); 664 case APPLY_SCALE | APPLY_TRANSLATE: 665 case APPLY_SCALE: 666 if (xx == 0.0 || yy == 0.0) { 667 throw new NonInvertibleTransformException("Determinant is 0"); 668 } 669 return new Point2D((1.0 / xx) * x, (1.0 / yy) * y); 670 case APPLY_TRANSLATE: 671 case APPLY_IDENTITY: 672 return new Point2D(x, y); 673 } 674 } 675 676 @Override 677 public Point3D inverseDeltaTransform(double x, double y, double z) 678 throws NonInvertibleTransformException { 679 switch(state3d) { 680 default: 681 stateError(); 682 // cannot reach 683 case APPLY_NON_3D: 684 switch (state2d) { 685 default: 686 return super.inverseDeltaTransform(x, y, z); 687 case APPLY_SHEAR | APPLY_TRANSLATE: 688 case APPLY_SHEAR: 689 if (xy == 0.0 || yx == 0.0) { 690 throw new NonInvertibleTransformException( 691 "Determinant is 0"); 692 } 693 return new Point3D( 694 (1.0 / yx) * y, 695 (1.0 / xy) * x, z); 696 case APPLY_SCALE | APPLY_TRANSLATE: 697 case APPLY_SCALE: 698 if (xx == 0.0 || yy == 0.0) { 699 throw new NonInvertibleTransformException( 700 "Determinant is 0"); 701 } 702 return new Point3D( 703 (1.0 / xx) * x, 704 (1.0 / yy) * y, z); 705 case APPLY_TRANSLATE: 706 case APPLY_IDENTITY: 707 return new Point3D(x, y, z); 708 } 709 710 case APPLY_TRANSLATE: 711 return new Point3D(x, y, z); 712 case APPLY_SCALE | APPLY_TRANSLATE: 713 case APPLY_SCALE: 714 if (xx == 0.0 || yy == 0.0 || zz == 0.0) { 715 throw new NonInvertibleTransformException("Determinant is 0"); 716 } 717 return new Point3D( 718 (1.0 / xx) * x, 719 (1.0 / yy) * y, 720 (1.0 / zz) * z); 721 case APPLY_3D_COMPLEX: 722 return super.inverseDeltaTransform(x, y, z); 723 } 724 } 725 726 /* ************************************************************************* 727 * * 728 * Other API * 729 * * 730 **************************************************************************/ 731 732 @Override 733 public String toString() { 734 final StringBuilder sb = new StringBuilder("Transform [\n"); 735 736 sb.append("\t").append(xx); 737 sb.append(", ").append(xy); 738 sb.append(", ").append(xz); 739 sb.append(", ").append(xt); 740 sb.append('\n'); 741 sb.append("\t").append(yx); 742 sb.append(", ").append(yy); 743 sb.append(", ").append(yz); 744 sb.append(", ").append(yt); 745 sb.append('\n'); 746 sb.append("\t").append(zx); 747 sb.append(", ").append(zy); 748 sb.append(", ").append(zz); 749 sb.append(", ").append(zt); 750 751 return sb.append("\n]").toString(); 752 } 753 754 /* ************************************************************************* 755 * * 756 * Internal implementation stuff * 757 * * 758 **************************************************************************/ 759 760 private void updateState() { 761 updateState2D(); 762 763 state3d = APPLY_NON_3D; 764 765 if (xz != 0.0 || 766 yz != 0.0 || 767 zx != 0.0 || 768 zy != 0.0) 769 { 770 state3d = APPLY_3D_COMPLEX; 771 } else { 772 if ((state2d & APPLY_SHEAR) == 0) { 773 if (zt != 0.0) { 774 state3d |= APPLY_TRANSLATE; 775 } 776 if (zz != 1.0) { 777 state3d |= APPLY_SCALE; 778 } 779 if (state3d != APPLY_NON_3D) { 780 state3d |= (state2d & (APPLY_SCALE | APPLY_TRANSLATE)); 781 } 782 } else { 783 if (zz != 1.0 || zt != 0.0) { 784 state3d = APPLY_3D_COMPLEX; 785 } 786 } 787 } 788 } 789 790 private void updateState2D() { 791 if (xy == 0.0 && yx == 0.0) { 792 if (xx == 1.0 && yy == 1.0) { 793 if (xt == 0.0 && yt == 0.0) { 794 state2d = APPLY_IDENTITY; 795 } else { 796 state2d = APPLY_TRANSLATE; 797 } 798 } else { 799 if (xt == 0.0 && yt == 0.0) { 800 state2d = APPLY_SCALE; 801 } else { 802 state2d = (APPLY_SCALE | APPLY_TRANSLATE); 803 } 804 } 805 } else { 806 if (xx == 0.0 && yy == 0.0) { 807 if (xt == 0.0 && yt == 0.0) { 808 state2d = APPLY_SHEAR; 809 } else { 810 state2d = (APPLY_SHEAR | APPLY_TRANSLATE); 811 } 812 } else { 813 if (xt == 0.0 && yt == 0.0) { 814 state2d = (APPLY_SHEAR | APPLY_SCALE); 815 } else { 816 state2d = (APPLY_SHEAR | APPLY_SCALE | APPLY_TRANSLATE); 817 } 818 } 819 } 820 } 821 822 void ensureCanTransform2DPoint() throws IllegalStateException { 823 if (state3d != APPLY_NON_3D) { 824 throw new IllegalStateException("Cannot transform 2D point " 825 + "with a 3D transform"); 826 } 827 } 828 829 private static void stateError() { 830 throw new InternalError("missing case in a switch"); 831 } 832 833 /** 834 * @treatAsPrivate implementation detail 835 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 836 */ 837 @Deprecated 838 @Override 839 public void impl_apply(final Affine3D trans) { 840 trans.concatenate(xx, xy, xz, xt, 841 yx, yy, yz, yt, 842 zx, zy, zz, zt); 843 } 844 845 /** 846 * @treatAsPrivate implementation detail 847 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 848 */ 849 @Deprecated 850 @Override 851 public BaseTransform impl_derive(final BaseTransform trans) { 852 return trans.deriveWithConcatenation(xx, xy, xz, xt, 853 yx, yy, yz, yt, 854 zx, zy, zz, zt); 855 } 856 857 /** 858 * Used only by tests to check the 2d matrix state 859 */ 860 int getState2d() { 861 return state2d; 862 } 863 864 /** 865 * Used only by tests to check the 3d matrix state 866 */ 867 int getState3d() { 868 return state3d; 869 } 870 871 } 872 } 873 | 1 /* 2 * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package com.sun.javafx.scene.transform; 27 28 import javafx.scene.transform.Transform; 29 30 /** 31 * Internal utilities for transformations 32 */ 33 public class TransformUtils { 34 35 /** 36 * Creates an immutable arbitrary transformation. 37 * This method is not intended for public use, users should use the Affine 38 * class. 39 */ 40 public static Transform immutableTransform( 41 double mxx, double mxy, double mxz, double tx, 42 double myx, double myy, double myz, double ty, 43 double mzx, double mzy, double mzz, double tz) { 44 return TransformHelper.createImmutableTransform( 45 mxx, mxy, mxz, tx, 46 myx, myy, myz, ty, 47 mzx, mzy, mzz, tz); 48 } 49 50 /** 51 * Creates an immutable transformation filled with current values 52 * from the given transformation. 53 * This method is not intended for public use, users should use the Affine 54 * class. 55 */ 56 public static Transform immutableTransform(Transform t) { 57 return TransformHelper.createImmutableTransform( 58 t.getMxx(), t.getMxy(), t.getMxz(), t.getTx(), 59 t.getMyx(), t.getMyy(), t.getMyz(), t.getTy(), 60 t.getMzx(), t.getMzy(), t.getMzz(), t.getTz()); 61 } 62 63 /** 64 * Creates an immutable arbitrary transformation. 65 * If the given instance is not null, it is reused. 66 * This method is not intended for public use, users should use the Affine 67 * class. 68 * @throws ClassCastException if the given transform to be reused 69 * is not instance of ImmutableTransform 70 */ 71 public static Transform immutableTransform(Transform reuse, 72 double mxx, double mxy, double mxz, double tx, 73 double myx, double myy, double myz, double ty, 74 double mzx, double mzy, double mzz, double tz) { 75 76 return TransformHelper.createImmutableTransform(reuse, 77 mxx, mxy, mxz, tx, 78 myx, myy, myz, ty, 79 mzx, mzy, mzz, tz); 80 } 81 82 /** 83 * Creates an immutable transformation filled with current values 84 * from the given transformation. 85 * If the given instance is not null, it is reused. 86 * This method is not intended for public use, users should use the Affine 87 * class. 88 * @throws ClassCastException if the given transform to be reused 89 * is not instance of ImmutableTransform 90 */ 91 public static Transform immutableTransform(Transform reuse, 92 Transform t) { 93 return TransformHelper.createImmutableTransform(reuse, 94 t.getMxx(), t.getMxy(), t.getMxz(), t.getTx(), 95 t.getMyx(), t.getMyy(), t.getMyz(), t.getTy(), 96 t.getMzx(), t.getMzy(), t.getMzz(), t.getTz()); 97 } 98 99 /** 100 * Creates an immutable transformation filled with concatenation 101 * of the given transformations. 102 * If the given instance is not null, it is reused. 103 * This method is not intended for public use, users should use the Affine 104 * class. 105 * @throws ClassCastException if one of the given transforms 106 * is not instance of ImmutableTransform 107 */ 108 public static Transform immutableTransform(Transform reuse, 109 Transform left, Transform right) { 110 111 return TransformHelper.createImmutableTransform(reuse, left, right); 112 } 113 114 } |