Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.scene.transform; 027 028import javafx.beans.property.DoubleProperty; 029import javafx.beans.property.DoublePropertyBase; 030 031import com.sun.javafx.geom.transform.Affine3D; 032import javafx.geometry.Point2D; 033import javafx.geometry.Point3D; 034 035 036/** 037 * This class represents an {@code Affine} object that shears coordinates 038 * by the specified multipliers. The matrix representing the shearing 039 * transformation is as follows: 040 * <pre> 041 * [ 1 x 0 -x*pivotY ] 042 * [ y 1 0 -y*pivotX ] 043 * [ 0 0 1 0 ] 044 * </pre> 045 * 046 * <p> 047 * For example: 048 * <pre><code> 049 * Text text = new Text("Using Shear for pseudo-italic font"); 050 * text.setX(20); 051 * text.setY(50); 052 * text.setFont(new Font(20)); 053 * 054 * text.getTransforms().add(new Shear(-0.35, 0)); 055 * </code></pre> 056 * </p> 057 */ 058public class Shear extends Transform { 059 060 /** 061 * Creates a default Shear (identity). 062 */ 063 public Shear() { 064 } 065 066 /** 067 * Creates a new instance of Shear. 068 * @param x the multiplier by which coordinates are shifted in the direction 069 * of the positive X axis as a factor of their Y coordinate 070 * @param y the multiplier by which coordinates are shifted in the direction 071 * of the positive Y axis as a factor of their X coordinate 072 */ 073 public Shear(double x, double y) { 074 setX(x); 075 setY(y); 076 } 077 078 /** 079 * Creates a new instance of Shear with pivot. 080 * @param x the multiplier by which coordinates are shifted in the direction 081 * of the positive X axis as a factor of their Y coordinate 082 * @param y the multiplier by which coordinates are shifted in the direction 083 * of the positive Y axis as a factor of their X coordinate 084 * @param pivotX the X coordinate of the shear pivot point 085 * @param pivotY the Y coordinate of the shear pivot point 086 */ 087 public Shear(double x, double y, double pivotX, double pivotY) { 088 setX(x); 089 setY(y); 090 setPivotX(pivotX); 091 setPivotY(pivotY); 092 } 093 094 /** 095 * Defines the multiplier by which coordinates are shifted in the direction 096 * of the positive X axis as a factor of their Y coordinate. Typical values 097 * are in the range -1 to 1, exclusive. 098 * 099 * @defaultValue 0.0 100 */ 101 private DoubleProperty x; 102 103 104 public final void setX(double value) { 105 xProperty().set(value); 106 } 107 108 public final double getX() { 109 return x == null ? 0.0 : x.get(); 110 } 111 112 public final DoubleProperty xProperty() { 113 if (x == null) { 114 x = new DoublePropertyBase() { 115 116 @Override 117 public void invalidated() { 118 transformChanged(); 119 } 120 121 @Override 122 public Object getBean() { 123 return Shear.this; 124 } 125 126 @Override 127 public String getName() { 128 return "x"; 129 } 130 }; 131 } 132 return x; 133 } 134 135 /** 136 * Defines the multiplier by which coordinates are shifted in the direction 137 * of the positive Y axis as a factor of their X coordinate. Typical values 138 * are in the range -1 to 1, exclusive. 139 * 140 * @defaultValue 0.0 141 */ 142 private DoubleProperty y; 143 144 145 public final void setY(double value) { 146 yProperty().set(value); 147 } 148 149 public final double getY() { 150 return y == null ? 0.0 : y.get(); 151 } 152 153 public final DoubleProperty yProperty() { 154 if (y == null) { 155 y = new DoublePropertyBase() { 156 157 @Override 158 public void invalidated() { 159 transformChanged(); 160 } 161 162 @Override 163 public Object getBean() { 164 return Shear.this; 165 } 166 167 @Override 168 public String getName() { 169 return "y"; 170 } 171 }; 172 } 173 return y; 174 } 175 176 /** 177 * Defines the X coordinate of the shear pivot point. 178 */ 179 private DoubleProperty pivotX; 180 181 182 public final void setPivotX(double value) { 183 pivotXProperty().set(value); 184 } 185 186 public final double getPivotX() { 187 return pivotX == null ? 0.0 : pivotX.get(); 188 } 189 190 public final DoubleProperty pivotXProperty() { 191 if (pivotX == null) { 192 pivotX = new DoublePropertyBase() { 193 194 @Override 195 public void invalidated() { 196 transformChanged(); 197 } 198 199 @Override 200 public Object getBean() { 201 return Shear.this; 202 } 203 204 @Override 205 public String getName() { 206 return "pivotX"; 207 } 208 }; 209 } 210 return pivotX; 211 } 212 213 /** 214 * Defines the Y coordinate of the shear pivot point. 215 */ 216 private DoubleProperty pivotY; 217 218 219 public final void setPivotY(double value) { 220 pivotYProperty().set(value); 221 } 222 223 public final double getPivotY() { 224 return pivotY == null ? 0.0 : pivotY.get(); 225 } 226 227 public final DoubleProperty pivotYProperty() { 228 if (pivotY == null) { 229 pivotY = new DoublePropertyBase() { 230 231 @Override 232 public void invalidated() { 233 transformChanged(); 234 } 235 236 @Override 237 public Object getBean() { 238 return Shear.this; 239 } 240 241 @Override 242 public String getName() { 243 return "pivotY"; 244 } 245 }; 246 } 247 return pivotY; 248 } 249 250 /* ************************************************************************* 251 * * 252 * Element getters * 253 * * 254 **************************************************************************/ 255 256 @Override 257 public double getMxy() { 258 return getX(); 259 } 260 261 @Override 262 public double getMyx() { 263 return getY(); 264 } 265 266 @Override 267 public double getTx() { 268 return -getX() * getPivotY(); 269 } 270 271 @Override 272 public double getTy() { 273 return -getY() * getPivotX(); 274 } 275 276 /* ************************************************************************* 277 * * 278 * State getters * 279 * * 280 **************************************************************************/ 281 282 @Override 283 boolean computeIs2D() { 284 return true; 285 } 286 287 @Override 288 boolean computeIsIdentity() { 289 return getX() == 0.0 && getY() == 0.0; 290 } 291 292 /* ************************************************************************* 293 * * 294 * Array getters * 295 * * 296 **************************************************************************/ 297 298 @Override 299 void fill2DArray(double[] array) { 300 final double sx = getX(); 301 final double sy = getY(); 302 303 array[0] = 1.0; 304 array[1] = sx; 305 array[2] = -sx * getPivotY(); 306 array[3] = sy; 307 array[4] = 1.0; 308 array[5] = -sy * getPivotX(); 309 } 310 311 @Override 312 void fill3DArray(double[] array) { 313 final double sx = getX(); 314 final double sy = getY(); 315 316 array[0] = 1.0; 317 array[1] = sx; 318 array[2] = 0.0; 319 array[3] = -sx * getPivotY(); 320 array[4] = sy; 321 array[5] = 1.0; 322 array[6] = 0.0; 323 array[7] = -sy * getPivotX(); 324 array[8] = 0.0; 325 array[9] = 0.0; 326 array[10] = 1.0; 327 array[11] = 0.0; 328 } 329 330 /* ************************************************************************* 331 * * 332 * Transform creators * 333 * * 334 **************************************************************************/ 335 336 @Override 337 public Transform createConcatenation(Transform transform) { 338 339 if (transform instanceof Affine) { 340 Affine a = (Affine) transform.clone(); 341 a.prepend(this); 342 return a; 343 } 344 345 final double sx = getX(); 346 final double sy = getY(); 347 348 final double txx = transform.getMxx(); 349 final double txy = transform.getMxy(); 350 final double txz = transform.getMxz(); 351 final double ttx = transform.getTx(); 352 final double tyx = transform.getMyx(); 353 final double tyy = transform.getMyy(); 354 final double tyz = transform.getMyz(); 355 final double tty = transform.getTy(); 356 return new Affine( 357 txx + sx * tyx, 358 txy + sx * tyy, 359 txz + sx * tyz, 360 ttx + sx * tty - sx * getPivotY(), 361 sy * txx + tyx, 362 sy * txy + tyy, 363 sy * txz + tyz, 364 sy * ttx + tty - sy * getPivotX(), 365 transform.getMzx(), 366 transform.getMzy(), 367 transform.getMzz(), 368 transform.getTz()); 369 } 370 371 @Override 372 public Transform createInverse() { 373 final double sx = getX(); 374 final double sy = getY(); 375 376 if (sy == 0.0) { 377 return new Shear(-sx, 0.0, 0.0, getPivotY()); 378 } 379 380 if (sx == 0.0) { 381 return new Shear(0.0, -sy, getPivotX(), 0.0); 382 } 383 384 final double px = getPivotX(); 385 final double py = getPivotY(); 386 final double coef = 1.0 / (1.0 - sx * sy); 387 388 return new Affine( 389 coef, -sx * coef, 0, sx * (py - sy * px) * coef, 390 -sy * coef, 1 + sx * sy * coef, 0, sy * px + sy * (sx * sy * px - sx * py) * coef, 391 0, 0, 1, 0); 392 } 393 394 @Override 395 public Shear clone() { 396 return new Shear(getX(), getY(), getPivotX(), getPivotY()); 397 } 398 399 /* ************************************************************************* 400 * * 401 * Transform, Inverse Transform * 402 * * 403 **************************************************************************/ 404 405 @Override 406 public Point2D transform(double x, double y) { 407 final double mxy = getX(); 408 final double myx = getY(); 409 410 return new Point2D( 411 x + mxy * y - mxy * getPivotY(), 412 myx * x + y - myx * getPivotX()); 413 } 414 415 @Override 416 public Point3D transform(double x, double y, double z) { 417 final double mxy = getX(); 418 final double myx = getY(); 419 420 return new Point3D( 421 x + mxy * y - mxy * getPivotY(), 422 myx * x + y - myx * getPivotX(), 423 z); 424 } 425 426 @Override 427 void transform2DPointsImpl(double[] srcPts, int srcOff, 428 double[] dstPts, int dstOff, int numPts) { 429 final double xy = getX(); 430 final double yx = getY(); 431 final double px = getPivotX(); 432 final double py = getPivotY(); 433 434 while (--numPts >= 0) { 435 final double x = srcPts[srcOff++]; 436 final double y = srcPts[srcOff++]; 437 438 dstPts[dstOff++] = x + xy * y - xy * py; 439 dstPts[dstOff++] = yx * x + y - yx * px; 440 } 441 } 442 443 @Override 444 void transform3DPointsImpl(double[] srcPts, int srcOff, 445 double[] dstPts, int dstOff, int numPts) { 446 final double xy = getX(); 447 final double yx = getY(); 448 final double px = getPivotX(); 449 final double py = getPivotY(); 450 451 while (--numPts >= 0) { 452 final double x = srcPts[srcOff++]; 453 final double y = srcPts[srcOff++]; 454 455 dstPts[dstOff++] = x + xy * y - xy * py; 456 dstPts[dstOff++] = yx * x + y - yx * px; 457 dstPts[dstOff++] = srcPts[srcOff++]; 458 } 459 } 460 461 @Override 462 public Point2D deltaTransform(double x, double y) { 463 464 return new Point2D( 465 x + getX() * y, 466 getY() * x + y); 467 } 468 469 @Override 470 public Point3D deltaTransform(double x, double y, double z) { 471 return new Point3D( 472 x + getX() * y, 473 getY() * x + y, 474 z); 475 } 476 477 478 @Override 479 public Point2D inverseTransform(double x, double y) 480 throws NonInvertibleTransformException { 481 final double sx = getX(); 482 final double sy = getY(); 483 484 if (sy == 0.0) { 485 final double mxy = -getX(); 486 487 return new Point2D( 488 x + mxy * y - mxy * getPivotY(), 489 y); 490 } 491 492 if (sx == 0.0) { 493 final double myx = -getY(); 494 495 return new Point2D( 496 x, 497 myx * x + y - myx * getPivotX()); 498 } 499 500 return super.inverseTransform(x, y); 501 } 502 503 @Override 504 public Point3D inverseTransform(double x, double y, double z) 505 throws NonInvertibleTransformException { 506 final double sx = getX(); 507 final double sy = getY(); 508 509 if (sy == 0.0) { 510 final double mxy = -getX(); 511 512 return new Point3D( 513 x + mxy * y - mxy * getPivotY(), 514 y, 515 z); 516 } 517 518 if (sx == 0.0) { 519 final double myx = -getY(); 520 521 return new Point3D( 522 x, 523 myx * x + y - myx * getPivotX(), 524 z); 525 } 526 527 return super.inverseTransform(x, y, z); 528 } 529 530 @Override 531 void inverseTransform2DPointsImpl(double[] srcPts, int srcOff, 532 double[] dstPts, int dstOff, int numPts) 533 throws NonInvertibleTransformException { 534 535 final double px = getPivotX(); 536 final double py = getPivotY(); 537 538 final double sx = getX(); 539 final double sy = getY(); 540 541 if (sy == 0.0) { 542 final double xy = -sx; 543 544 while (--numPts >= 0) { 545 final double x = srcPts[srcOff++]; 546 final double y = srcPts[srcOff++]; 547 548 dstPts[dstOff++] = x + xy * y - xy * py; 549 dstPts[dstOff++] = y; 550 } 551 return; 552 } 553 554 if (sx == 0.0) { 555 final double yx = -sy; 556 557 while (--numPts >= 0) { 558 final double x = srcPts[srcOff++]; 559 final double y = srcPts[srcOff++]; 560 561 dstPts[dstOff++] = x; 562 dstPts[dstOff++] = yx * x + y - yx * px; 563 } 564 return; 565 } 566 567 super.inverseTransform2DPointsImpl(srcPts, srcOff, dstPts, dstOff, numPts); 568 } 569 570 @Override 571 void inverseTransform3DPointsImpl(double[] srcPts, int srcOff, 572 double[] dstPts, int dstOff, int numPts) 573 throws NonInvertibleTransformException{ 574 575 final double px = getPivotX(); 576 final double py = getPivotY(); 577 578 final double sx = getX(); 579 final double sy = getY(); 580 581 if (sy == 0.0) { 582 final double xy = -sx; 583 584 while (--numPts >= 0) { 585 final double x = srcPts[srcOff++]; 586 final double y = srcPts[srcOff++]; 587 588 dstPts[dstOff++] = x + xy * y - xy * py; 589 dstPts[dstOff++] = y; 590 dstPts[dstOff++] = srcPts[srcOff++]; 591 } 592 return; 593 } 594 595 if (sx == 0.0) { 596 final double yx = -sy; 597 598 while (--numPts >= 0) { 599 final double x = srcPts[srcOff++]; 600 final double y = srcPts[srcOff++]; 601 602 dstPts[dstOff++] = x; 603 dstPts[dstOff++] = yx * x + y - yx * px; 604 dstPts[dstOff++] = srcPts[srcOff++]; 605 } 606 return; 607 } 608 609 super.inverseTransform3DPointsImpl(srcPts, srcOff, dstPts, dstOff, numPts); 610 } 611 612 @Override 613 public Point2D inverseDeltaTransform(double x, double y) 614 throws NonInvertibleTransformException { 615 final double sx = getX(); 616 final double sy = getY(); 617 618 if (sy == 0.0) { 619 return new Point2D( 620 x - getX() * y, 621 y); 622 } 623 624 if (sx == 0.0) { 625 return new Point2D( 626 x, 627 -getY() * x + y); 628 } 629 630 return super.inverseDeltaTransform(x, y); 631 } 632 633 @Override 634 public Point3D inverseDeltaTransform(double x, double y, double z) 635 throws NonInvertibleTransformException { 636 final double sx = getX(); 637 final double sy = getY(); 638 639 if (sy == 0.0) { 640 return new Point3D( 641 x - getX() * y, 642 y, 643 z); 644 } 645 646 if (sx == 0.0) { 647 return new Point3D( 648 x, 649 -getY() * x + y, 650 z); 651 } 652 653 return super.inverseDeltaTransform(x, y, z); 654 } 655 656 /* ************************************************************************* 657 * * 658 * Other API * 659 * * 660 **************************************************************************/ 661 662 /** 663 * Returns a string representation of this {@code Shear} object. 664 * @return a string representation of this {@code Shear} object. 665 */ 666 @Override 667 public String toString() { 668 final StringBuilder sb = new StringBuilder("Shear ["); 669 670 sb.append("x=").append(getX()); 671 sb.append(", y=").append(getY()); 672 sb.append(", pivotX=").append(getPivotX()); 673 sb.append(", pivotY=").append(getPivotY()); 674 675 return sb.append("]").toString(); 676 } 677 678 /* ************************************************************************* 679 * * 680 * Internal implementation stuff * 681 * * 682 **************************************************************************/ 683 684 /** 685 * @treatAsPrivate implementation detail 686 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 687 */ 688 @Deprecated 689 @Override 690 public void impl_apply(final Affine3D trans) { 691 if (getPivotX() != 0 || getPivotY() != 0) { 692 trans.translate(getPivotX(), getPivotY()); 693 trans.shear(getX(), getY()); 694 trans.translate(-getPivotX(), -getPivotY()); 695 } else { 696 trans.shear(getX(), getY()); 697 } 698 } 699 700 @Override 701 void validate() { 702 getX(); getPivotX(); 703 getY(); getPivotY(); 704 } 705 706 @Override 707 void appendTo(Affine a) { 708 a.appendShear(getX(), getY(), getPivotX(), getPivotY()); 709 } 710 711 @Override 712 void prependTo(Affine a) { 713 a.prependShear(getX(), getY(), getPivotX(), getPivotY()); 714 } 715}