< prev index next >

modules/graphics/src/main/java/com/sun/javafx/scene/transform/TransformUtils.java

Print this page


   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 }

< prev index next >