Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2010, 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.effect; 027 028import javafx.beans.property.DoubleProperty; 029import javafx.beans.property.DoublePropertyBase; 030import javafx.beans.property.ObjectProperty; 031import javafx.scene.Node; 032 033import com.sun.javafx.effect.EffectDirtyBits; 034import com.sun.javafx.geom.BaseBounds; 035import com.sun.javafx.geom.RectBounds; 036import com.sun.javafx.geom.transform.BaseTransform; 037import com.sun.javafx.scene.BoundsAccessor; 038 039 040/** 041 * An effect that provides non-affine transformation of the input content. 042 * Most typically {@code PerspectiveTransform} is used to provide a "faux" 043 * three-dimensional effect for otherwise two-dimensional content. 044 * <p> 045 * A perspective transformation is capable of mapping an arbitrary 046 * quadrilateral into another arbitrary quadrilateral, while preserving 047 * the straightness of lines. Unlike an affine transformation, the 048 * parallelism of lines in the source is not necessarily preserved in the 049 * output. 050 * <p> 051 * Note that this effect does not adjust the coordinates of input events 052 * or any methods that measure containment on a {@code Node}. 053 * The results of mouse picking and the containment methods are undefined 054 * when a {@code Node} has a {@code PerspectiveTransform} effect in place. 055 * 056 * <p> 057 * Example: 058 * <pre><code> 059 * PerspectiveTransform perspectiveTrasform = new PerspectiveTransform(); 060 * perspectiveTrasform.setUlx(10.0); 061 * perspectiveTrasform.setUly(10.0); 062 * perspectiveTrasform.setUrx(310.0); 063 * perspectiveTrasform.setUry(40.0); 064 * perspectiveTrasform.setLrx(310.0); 065 * perspectiveTrasform.setLry(60.0); 066 * perspectiveTrasform.setLlx(10.0); 067 * perspectiveTrasform.setLly(90.0); 068 * 069 * Group g = new Group(); 070 * g.setEffect(perspectiveTrasform); 071 * g.setCache(true); 072 * 073 * Rectangle rect = new Rectangle(); 074 * rect.setX(10.0); 075 * rect.setY(10.0); 076 * rect.setWidth(280.0); 077 * rect.setHeight(80.0); 078 * rect.setFill(Color.web("0x3b596d")); 079 * 080 * Text text = new Text(); 081 * text.setX(20.0); 082 * text.setY(65.0); 083 * text.setText("Perspective"); 084 * text.setFill(Color.ALICEBLUE); 085 * text.setFont(Font.font(null, FontWeight.BOLD, 36)); 086 * 087 * g.getChildren().addAll(rect, text); 088 * </pre></code> 089 * <p> The code above produces the following: </p> 090 * <p> 091 * <img src="doc-files/perspectivetransform.png"/> 092 * </p> 093 */ 094public class PerspectiveTransform extends Effect { 095 /** 096 * Creates a new instance of PerspectiveTransform with default parameters. 097 */ 098 public PerspectiveTransform() {} 099 100 /** 101 * Creates a new instance of PerspectiveTransform with the specified ulx, 102 * uly, urx, ury, lrx, lry, llx, and lly. 103 * @param ulx the x coordinate of upper left corner 104 * @param uly the y coordinate of upper left corner 105 * @param urx the x coordinate of upper right corner 106 * @param ury the y coordinate of upper right corner 107 * @param lrx the x coordinate of lower right corner 108 * @param lry the y coordinate of lower right corner 109 * @param llx the x coordinate of lower left corner 110 * @param lly the y coordinate of lower left corner 111 */ 112 public PerspectiveTransform(double ulx, double uly, 113 double urx, double ury, 114 double lrx, double lry, 115 double llx, double lly) { 116 setUlx(ulx); setUly(uly); 117 setUrx(urx); setUry(ury); 118 setLlx(llx); setLly(lly); 119 setLrx(lrx); setLry(lry); 120 } 121 122 private void updateXform() { 123 ((com.sun.scenario.effect.PerspectiveTransform)impl_getImpl()).setQuadMapping( 124 (float)getUlx(), (float)getUly(), 125 (float)getUrx(), (float)getUry(), 126 (float)getLrx(), (float)getLry(), 127 (float)getLlx(), (float)getLly()); 128 } 129 130 @Override 131 com.sun.scenario.effect.PerspectiveTransform impl_createImpl() { 132 return new com.sun.scenario.effect.PerspectiveTransform(); 133 }; 134 /** 135 * The input for this {@code Effect}. 136 * If set to {@code null}, or left unspecified, a graphical image of 137 * the {@code Node} to which the {@code Effect} is attached will be 138 * used as the input. 139 * @defaultValue null 140 */ 141 private ObjectProperty<Effect> input; 142 143 144 public final void setInput(Effect value) { 145 inputProperty().set(value); 146 } 147 148 public final Effect getInput() { 149 return input == null ? null : input.get(); 150 } 151 152 public final ObjectProperty<Effect> inputProperty() { 153 if (input == null) { 154 input = new EffectInputProperty("input"); 155 } 156 return input; 157 } 158 159 @Override 160 boolean impl_checkChainContains(Effect e) { 161 Effect localInput = getInput(); 162 if (localInput == null) 163 return false; 164 if (localInput == e) 165 return true; 166 return localInput.impl_checkChainContains(e); 167 } 168 169 /** 170 * The x coordinate of the output location onto which the upper left 171 * corner of the source is mapped. 172 * @defaultValue 0.0 173 */ 174 private DoubleProperty ulx; 175 176 177 public final void setUlx(double value) { 178 ulxProperty().set(value); 179 } 180 181 public final double getUlx() { 182 return ulx == null ? 0 : ulx.get(); 183 } 184 185 public final DoubleProperty ulxProperty() { 186 if (ulx == null) { 187 ulx = new DoublePropertyBase() { 188 189 @Override 190 public void invalidated() { 191 markDirty(EffectDirtyBits.EFFECT_DIRTY); 192 effectBoundsChanged(); 193 } 194 195 @Override 196 public Object getBean() { 197 return PerspectiveTransform.this; 198 } 199 200 @Override 201 public String getName() { 202 return "ulx"; 203 } 204 }; 205 } 206 return ulx; 207 } 208 209 /** 210 * The y coordinate of the output location onto which the upper left 211 * corner of the source is mapped. 212 * @defaultValue 0.0 213 */ 214 private DoubleProperty uly; 215 216 217 public final void setUly(double value) { 218 ulyProperty().set(value); 219 } 220 221 public final double getUly() { 222 return uly == null ? 0 : uly.get(); 223 } 224 225 public final DoubleProperty ulyProperty() { 226 if (uly == null) { 227 uly = new DoublePropertyBase() { 228 229 @Override 230 public void invalidated() { 231 markDirty(EffectDirtyBits.EFFECT_DIRTY); 232 effectBoundsChanged(); 233 } 234 235 @Override 236 public Object getBean() { 237 return PerspectiveTransform.this; 238 } 239 240 @Override 241 public String getName() { 242 return "uly"; 243 } 244 }; 245 } 246 return uly; 247 } 248 249 /** 250 * The x coordinate of the output location onto which the upper right 251 * corner of the source is mapped. 252 * @defaultValue 0.0 253 */ 254 private DoubleProperty urx; 255 256 257 public final void setUrx(double value) { 258 urxProperty().set(value); 259 } 260 261 public final double getUrx() { 262 return urx == null ? 0 : urx.get(); 263 } 264 265 public final DoubleProperty urxProperty() { 266 if (urx == null) { 267 urx = new DoublePropertyBase() { 268 269 @Override 270 public void invalidated() { 271 markDirty(EffectDirtyBits.EFFECT_DIRTY); 272 effectBoundsChanged(); 273 } 274 275 @Override 276 public Object getBean() { 277 return PerspectiveTransform.this; 278 } 279 280 @Override 281 public String getName() { 282 return "urx"; 283 } 284 }; 285 } 286 return urx; 287 } 288 289 /** 290 * The y coordinate of the output location onto which the upper right 291 * corner of the source is mapped. 292 * @defaultValue 0.0 293 */ 294 private DoubleProperty ury; 295 296 297 public final void setUry(double value) { 298 uryProperty().set(value); 299 } 300 301 public final double getUry() { 302 return ury == null ? 0 : ury.get(); 303 } 304 305 public final DoubleProperty uryProperty() { 306 if (ury == null) { 307 ury = new DoublePropertyBase() { 308 309 @Override 310 public void invalidated() { 311 markDirty(EffectDirtyBits.EFFECT_DIRTY); 312 effectBoundsChanged(); 313 } 314 315 @Override 316 public Object getBean() { 317 return PerspectiveTransform.this; 318 } 319 320 @Override 321 public String getName() { 322 return "ury"; 323 } 324 }; 325 } 326 return ury; 327 } 328 329 /** 330 * The x coordinate of the output location onto which the lower right 331 * corner of the source is mapped. 332 * @defaultValue 0.0 333 */ 334 private DoubleProperty lrx; 335 336 337 public final void setLrx(double value) { 338 lrxProperty().set(value); 339 } 340 341 public final double getLrx() { 342 return lrx == null ? 0 : lrx.get(); 343 } 344 345 public final DoubleProperty lrxProperty() { 346 if (lrx == null) { 347 lrx = new DoublePropertyBase() { 348 349 @Override 350 public void invalidated() { 351 markDirty(EffectDirtyBits.EFFECT_DIRTY); 352 effectBoundsChanged(); 353 } 354 355 @Override 356 public Object getBean() { 357 return PerspectiveTransform.this; 358 } 359 360 @Override 361 public String getName() { 362 return "lrx"; 363 } 364 }; 365 } 366 return lrx; 367 } 368 369 /** 370 * The y coordinate of the output location onto which the lower right 371 * corner of the source is mapped. 372 * @defaultValue 0.0 373 */ 374 private DoubleProperty lry; 375 376 377 public final void setLry(double value) { 378 lryProperty().set(value); 379 } 380 381 public final double getLry() { 382 return lry == null ? 0 : lry.get(); 383 } 384 385 public final DoubleProperty lryProperty() { 386 if (lry == null) { 387 lry = new DoublePropertyBase() { 388 389 @Override 390 public void invalidated() { 391 markDirty(EffectDirtyBits.EFFECT_DIRTY); 392 effectBoundsChanged(); 393 } 394 395 @Override 396 public Object getBean() { 397 return PerspectiveTransform.this; 398 } 399 400 @Override 401 public String getName() { 402 return "lry"; 403 } 404 }; 405 } 406 return lry; 407 } 408 409 /** 410 * The x coordinate of the output location onto which the lower left 411 * corner of the source is mapped. 412 * @defaultValue 0.0 413 */ 414 private DoubleProperty llx; 415 416 417 public final void setLlx(double value) { 418 llxProperty().set(value); 419 } 420 421 public final double getLlx() { 422 return llx == null ? 0 : llx.get(); 423 } 424 425 public final DoubleProperty llxProperty() { 426 if (llx == null) { 427 llx = new DoublePropertyBase() { 428 429 @Override 430 public void invalidated() { 431 markDirty(EffectDirtyBits.EFFECT_DIRTY); 432 effectBoundsChanged(); 433 } 434 435 @Override 436 public Object getBean() { 437 return PerspectiveTransform.this; 438 } 439 440 @Override 441 public String getName() { 442 return "llx"; 443 } 444 }; 445 } 446 return llx; 447 } 448 449 /** 450 * The y coordinate of the output location onto which the lower left 451 * corner of the source is mapped. 452 * @defaultValue 0.0 453 */ 454 private DoubleProperty lly; 455 456 457 public final void setLly(double value) { 458 llyProperty().set(value); 459 } 460 461 public final double getLly() { 462 return lly == null ? 0 : lly.get(); 463 } 464 465 public final DoubleProperty llyProperty() { 466 if (lly == null) { 467 lly = new DoublePropertyBase() { 468 469 @Override 470 public void invalidated() { 471 markDirty(EffectDirtyBits.EFFECT_DIRTY); 472 effectBoundsChanged(); 473 } 474 475 @Override 476 public Object getBean() { 477 return PerspectiveTransform.this; 478 } 479 480 @Override 481 public String getName() { 482 return "lly"; 483 } 484 }; 485 } 486 return lly; 487 } 488 489 @Override 490 void impl_update() { 491 Effect localInput = getInput(); 492 if (localInput != null) { 493 localInput.impl_sync(); 494 } 495 496 ((com.sun.scenario.effect.PerspectiveTransform)impl_getImpl()) 497 .setInput(localInput == null ? null : localInput.impl_getImpl()); 498 updateXform(); 499 } 500 501 private float devcoords[] = new float[8]; 502 503 /** 504 * @treatAsPrivate implementation detail 505 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 506 */ 507 @Deprecated 508 @Override 509 public BaseBounds impl_getBounds(BaseBounds bounds, 510 BaseTransform tx, 511 Node node, 512 BoundsAccessor boundsAccessor) { 513 setupDevCoords(tx); 514 515 float minx, miny, maxx, maxy; 516 minx = maxx = devcoords[0]; 517 miny = maxy = devcoords[1]; 518 for (int i = 2; i < devcoords.length; i += 2) { 519 if (minx > devcoords[i]) minx = devcoords[i]; 520 else if (maxx < devcoords[i]) maxx = devcoords[i]; 521 if (miny > devcoords[i+1]) miny = devcoords[i+1]; 522 else if (maxy < devcoords[i+1]) maxy = devcoords[i+1]; 523 } 524 525 return new RectBounds(minx, miny, maxx, maxy); 526 } 527 528 private void setupDevCoords(BaseTransform transform) { 529 devcoords[0] = (float)getUlx(); 530 devcoords[1] = (float)getUly(); 531 devcoords[2] = (float)getUrx(); 532 devcoords[3] = (float)getUry(); 533 devcoords[4] = (float)getLrx(); 534 devcoords[5] = (float)getLry(); 535 devcoords[6] = (float)getLlx(); 536 devcoords[7] = (float)getLly(); 537 transform.transform(devcoords, 0, devcoords, 0, 4); 538 } 539 540 /** 541 * 542 * @treatAsPrivate implementation detail 543 * @deprecated This is an internal API that is not intended for use and will be removed in the next version 544 */ 545 @Deprecated 546 @Override 547 public Effect impl_copy() { 548 return new PerspectiveTransform(this.getUlx(), this.getUly(), 549 this.getUrx(), this.getUry(), this.getLrx(), this.getLry(), 550 this.getLlx(), this.getLly()); 551 } 552}