All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javafx.scene.effect.PerspectiveTransform Maven / Gradle / Ivy

There is a newer version: 24-ea+15
Show newest version
/*
 * Copyright (c) 2010, 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package javafx.scene.effect;

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.DoublePropertyBase;
import javafx.beans.property.ObjectProperty;
import javafx.scene.Node;

import com.sun.javafx.effect.EffectDirtyBits;
import com.sun.javafx.geom.BaseBounds;
import com.sun.javafx.geom.RectBounds;
import com.sun.javafx.geom.transform.BaseTransform;
import com.sun.javafx.scene.BoundsAccessor;


/**
 * An effect that provides non-affine transformation of the input content.
 * Most typically {@code PerspectiveTransform} is used to provide a "faux"
 * three-dimensional effect for otherwise two-dimensional content.
 * 

* A perspective transformation is capable of mapping an arbitrary * quadrilateral into another arbitrary quadrilateral, while preserving * the straightness of lines. Unlike an affine transformation, the * parallelism of lines in the source is not necessarily preserved in the * output. *

* Note that this effect does not adjust the coordinates of input events * or any methods that measure containment on a {@code Node}. * The results of mouse picking and the containment methods are undefined * when a {@code Node} has a {@code PerspectiveTransform} effect in place. * *

* Example: *

{@code
 * PerspectiveTransform perspectiveTrasform = new PerspectiveTransform();
 * perspectiveTrasform.setUlx(10.0);
 * perspectiveTrasform.setUly(10.0);
 * perspectiveTrasform.setUrx(310.0);
 * perspectiveTrasform.setUry(40.0);
 * perspectiveTrasform.setLrx(310.0);
 * perspectiveTrasform.setLry(60.0);
 * perspectiveTrasform.setLlx(10.0);
 * perspectiveTrasform.setLly(90.0);
 *
 * Group g = new Group();
 * g.setEffect(perspectiveTrasform);
 * g.setCache(true);
 *
 * Rectangle rect = new Rectangle();
 * rect.setX(10.0);
 * rect.setY(10.0);
 * rect.setWidth(280.0);
 * rect.setHeight(80.0);
 * rect.setFill(Color.web("0x3b596d"));
 *
 * Text text = new Text();
 * text.setX(20.0);
 * text.setY(65.0);
 * text.setText("Perspective");
 * text.setFill(Color.ALICEBLUE);
 * text.setFont(Font.font(null, FontWeight.BOLD, 36));
 *
 * g.getChildren().addAll(rect, text);
 * }
*

The code above produces the following:

*

* The visual effect of
 * PerspectiveTransform on text *

* @since JavaFX 2.0 */ public class PerspectiveTransform extends Effect { /** * Creates a new instance of PerspectiveTransform with default parameters. */ public PerspectiveTransform() {} /** * Creates a new instance of PerspectiveTransform with the specified ulx, * uly, urx, ury, lrx, lry, llx, and lly. * @param ulx the x coordinate of upper left corner * @param uly the y coordinate of upper left corner * @param urx the x coordinate of upper right corner * @param ury the y coordinate of upper right corner * @param lrx the x coordinate of lower right corner * @param lry the y coordinate of lower right corner * @param llx the x coordinate of lower left corner * @param lly the y coordinate of lower left corner * @since JavaFX 2.1 */ public PerspectiveTransform(double ulx, double uly, double urx, double ury, double lrx, double lry, double llx, double lly) { setUlx(ulx); setUly(uly); setUrx(urx); setUry(ury); setLlx(llx); setLly(lly); setLrx(lrx); setLry(lry); } private void updateXform() { ((com.sun.scenario.effect.PerspectiveTransform) getPeer()).setQuadMapping( (float)getUlx(), (float)getUly(), (float)getUrx(), (float)getUry(), (float)getLrx(), (float)getLry(), (float)getLlx(), (float)getLly()); } @Override com.sun.scenario.effect.PerspectiveTransform createPeer() { return new com.sun.scenario.effect.PerspectiveTransform(); } /** * The input for this {@code Effect}. * If set to {@code null}, or left unspecified, a graphical image of * the {@code Node} to which the {@code Effect} is attached will be * used as the input. * @defaultValue null */ private ObjectProperty input; public final void setInput(Effect value) { inputProperty().set(value); } public final Effect getInput() { return input == null ? null : input.get(); } public final ObjectProperty inputProperty() { if (input == null) { input = new EffectInputProperty("input"); } return input; } @Override boolean checkChainContains(Effect e) { Effect localInput = getInput(); if (localInput == null) return false; if (localInput == e) return true; return localInput.checkChainContains(e); } /** * The x coordinate of the output location onto which the upper left * corner of the source is mapped. * @defaultValue 0.0 */ private DoubleProperty ulx; public final void setUlx(double value) { ulxProperty().set(value); } public final double getUlx() { return ulx == null ? 0 : ulx.get(); } public final DoubleProperty ulxProperty() { if (ulx == null) { ulx = new DoublePropertyBase() { @Override public void invalidated() { markDirty(EffectDirtyBits.EFFECT_DIRTY); effectBoundsChanged(); } @Override public Object getBean() { return PerspectiveTransform.this; } @Override public String getName() { return "ulx"; } }; } return ulx; } /** * The y coordinate of the output location onto which the upper left * corner of the source is mapped. * @defaultValue 0.0 */ private DoubleProperty uly; public final void setUly(double value) { ulyProperty().set(value); } public final double getUly() { return uly == null ? 0 : uly.get(); } public final DoubleProperty ulyProperty() { if (uly == null) { uly = new DoublePropertyBase() { @Override public void invalidated() { markDirty(EffectDirtyBits.EFFECT_DIRTY); effectBoundsChanged(); } @Override public Object getBean() { return PerspectiveTransform.this; } @Override public String getName() { return "uly"; } }; } return uly; } /** * The x coordinate of the output location onto which the upper right * corner of the source is mapped. * @defaultValue 0.0 */ private DoubleProperty urx; public final void setUrx(double value) { urxProperty().set(value); } public final double getUrx() { return urx == null ? 0 : urx.get(); } public final DoubleProperty urxProperty() { if (urx == null) { urx = new DoublePropertyBase() { @Override public void invalidated() { markDirty(EffectDirtyBits.EFFECT_DIRTY); effectBoundsChanged(); } @Override public Object getBean() { return PerspectiveTransform.this; } @Override public String getName() { return "urx"; } }; } return urx; } /** * The y coordinate of the output location onto which the upper right * corner of the source is mapped. * @defaultValue 0.0 */ private DoubleProperty ury; public final void setUry(double value) { uryProperty().set(value); } public final double getUry() { return ury == null ? 0 : ury.get(); } public final DoubleProperty uryProperty() { if (ury == null) { ury = new DoublePropertyBase() { @Override public void invalidated() { markDirty(EffectDirtyBits.EFFECT_DIRTY); effectBoundsChanged(); } @Override public Object getBean() { return PerspectiveTransform.this; } @Override public String getName() { return "ury"; } }; } return ury; } /** * The x coordinate of the output location onto which the lower right * corner of the source is mapped. * @defaultValue 0.0 */ private DoubleProperty lrx; public final void setLrx(double value) { lrxProperty().set(value); } public final double getLrx() { return lrx == null ? 0 : lrx.get(); } public final DoubleProperty lrxProperty() { if (lrx == null) { lrx = new DoublePropertyBase() { @Override public void invalidated() { markDirty(EffectDirtyBits.EFFECT_DIRTY); effectBoundsChanged(); } @Override public Object getBean() { return PerspectiveTransform.this; } @Override public String getName() { return "lrx"; } }; } return lrx; } /** * The y coordinate of the output location onto which the lower right * corner of the source is mapped. * @defaultValue 0.0 */ private DoubleProperty lry; public final void setLry(double value) { lryProperty().set(value); } public final double getLry() { return lry == null ? 0 : lry.get(); } public final DoubleProperty lryProperty() { if (lry == null) { lry = new DoublePropertyBase() { @Override public void invalidated() { markDirty(EffectDirtyBits.EFFECT_DIRTY); effectBoundsChanged(); } @Override public Object getBean() { return PerspectiveTransform.this; } @Override public String getName() { return "lry"; } }; } return lry; } /** * The x coordinate of the output location onto which the lower left * corner of the source is mapped. * @defaultValue 0.0 */ private DoubleProperty llx; public final void setLlx(double value) { llxProperty().set(value); } public final double getLlx() { return llx == null ? 0 : llx.get(); } public final DoubleProperty llxProperty() { if (llx == null) { llx = new DoublePropertyBase() { @Override public void invalidated() { markDirty(EffectDirtyBits.EFFECT_DIRTY); effectBoundsChanged(); } @Override public Object getBean() { return PerspectiveTransform.this; } @Override public String getName() { return "llx"; } }; } return llx; } /** * The y coordinate of the output location onto which the lower left * corner of the source is mapped. * @defaultValue 0.0 */ private DoubleProperty lly; public final void setLly(double value) { llyProperty().set(value); } public final double getLly() { return lly == null ? 0 : lly.get(); } public final DoubleProperty llyProperty() { if (lly == null) { lly = new DoublePropertyBase() { @Override public void invalidated() { markDirty(EffectDirtyBits.EFFECT_DIRTY); effectBoundsChanged(); } @Override public Object getBean() { return PerspectiveTransform.this; } @Override public String getName() { return "lly"; } }; } return lly; } @Override void update() { Effect localInput = getInput(); if (localInput != null) { localInput.sync(); } ((com.sun.scenario.effect.PerspectiveTransform)getPeer()) .setInput(localInput == null ? null : localInput.getPeer()); updateXform(); } private float devcoords[] = new float[8]; @Override BaseBounds getBounds(BaseBounds bounds, BaseTransform tx, Node node, BoundsAccessor boundsAccessor) { setupDevCoords(tx); float minx, miny, maxx, maxy; minx = maxx = devcoords[0]; miny = maxy = devcoords[1]; for (int i = 2; i < devcoords.length; i += 2) { if (minx > devcoords[i]) minx = devcoords[i]; else if (maxx < devcoords[i]) maxx = devcoords[i]; if (miny > devcoords[i+1]) miny = devcoords[i+1]; else if (maxy < devcoords[i+1]) maxy = devcoords[i+1]; } return new RectBounds(minx, miny, maxx, maxy); } private void setupDevCoords(BaseTransform transform) { devcoords[0] = (float)getUlx(); devcoords[1] = (float)getUly(); devcoords[2] = (float)getUrx(); devcoords[3] = (float)getUry(); devcoords[4] = (float)getLrx(); devcoords[5] = (float)getLry(); devcoords[6] = (float)getLlx(); devcoords[7] = (float)getLly(); transform.transform(devcoords, 0, devcoords, 0, 4); } @Override Effect copy() { return new PerspectiveTransform(this.getUlx(), this.getUly(), this.getUrx(), this.getUry(), this.getLrx(), this.getLry(), this.getLlx(), this.getLly()); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy