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

javafx.scene.paint.ImagePattern Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2010, 2024, 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.paint;

import javafx.beans.NamedArg;
import javafx.scene.image.Image;
import com.sun.javafx.beans.event.AbstractNotifyListener;
import com.sun.javafx.tk.Toolkit;
import com.sun.javafx.util.InterpolationUtils;
import java.util.Objects;

/**
 * 

The {@code ImagePattern} class fills a shape with an image pattern. The * user may specify the anchor rectangle, which defines the position, * width, and height of the image relative to the upper left corner of the * shape. If the shape extends out of the anchor rectangle, the image is tiled. *

* *

If the {@code proportional} variable is set to true (the default) * then the anchor rectangle should be specified relative to the unit * square (0.0->1.0) and will be stretched across the shape. * If the {@code proportional} variable is set to false, then the anchor * rectangle should be specified in the local coordinate system of the shape * and the image will be stretched to fit the anchor rectangle. The anchor * rectangle will not be stretched across the shape.

* *

The example below demonstrates the use of the {@code proportional} * variable. The shapes on the top row use proportional coordinates * (the default) to specify the anchor rectangle. The shapes on the * bottom row use absolute coordinates. The flower image is stretched * to fill the entire triangle shape, while the dot pattern image is tiled * within the circle shape.

*

import javafx.scene.Scene;
import javafx.scene.image.Image;
import javafx.scene.paint.ImagePattern;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Polygon;
import javafx.stage.Stage;

public class HelloImagePattern extends Application {

    private static final String flowerURL = "file:flower.png";
    private static final String dotsURL = "file:dots.png";

    {@literal @Override public void start(Stage stage)} {
        stage.setTitle("Image Pattern");
        Group root = new Group();
        Scene scene = new Scene(root, 600, 450);

        Image dots = new Image(dotsURL);
        Image flower = new Image(flowerURL);

        Polygon p = new Polygon();

        p.setLayoutX(10);
        p.setLayoutY(10);
        p.getPoints().add(50.0);
        p.getPoints().add(0.0);
        p.getPoints().add(100.0);
        p.getPoints().add(100.0);
        p.getPoints().add(0.0);
        p.getPoints().add(100.0);

        p.setFill(new ImagePattern(flower, 0, 0, 1, 1, true));

        root.getChildren().add(p);

        Polygon p2 = new Polygon();

        p2.setLayoutX(10);
        p2.setLayoutY(120);
        p2.getPoints().add(50.0);
        p2.getPoints().add(0.0);
        p2.getPoints().add(100.0);
        p2.getPoints().add(100.0);
        p2.getPoints().add(0.0);
        p2.getPoints().add(100.0);

        p2.setFill(new ImagePattern(flower, 0, 0, 100, 100, false));

        root.getChildren().add(p2);

        Circle circ = new Circle(50);
        circ.setTranslateX(120);
        circ.setTranslateY(10);
        circ.setCenterX(50);
        circ.setCenterY(50);
        circ.setFill(new ImagePattern(dots, 0.2, 0.2, 0.4, 0.4, true));

        root.getChildren().add(circ);

        Circle circ2 = new Circle(50);
        circ2.setTranslateX(120);
        circ2.setTranslateY(10);
        circ2.setCenterX(50);
        circ2.setCenterY(50);
        circ2.setFill(new ImagePattern(dots, 20, 20, 40, 40, false));

        root.getChildren().add(circ2);
        stage.setScene(scene);
        stage.show();
    }
*

The code above produces the following:

*

A visual rendering of the
 * HelloImagePattern example

* * @since JavaFX 2.2 */ public final class ImagePattern extends Paint { private Image image; /** * Gets the image to be used as a paint. * * @interpolationType discrete * @return Image to be used as a paint. */ public final Image getImage() { return image; } private double x; /** * Gets the x origin of the anchor rectangle. * * @defaultValue 0.0 * @interpolationType linear * if both values are absolute or both values are {@link #isProportional() proportional}, * discrete otherwise * @return The x origin of the anchor rectangle. */ public final double getX() { return x; } private double y; /** * Gets the y origin of the anchor rectangle. * * @defaultValue 0.0 * @interpolationType linear * if both values are absolute or both values are {@link #isProportional() proportional}, * discrete otherwise * @return The y origin of the anchor rectangle. */ public final double getY() { return y; } private double width = 1f; /** * Gets the width of the anchor rectangle. * * @defaultValue 1.0 * @interpolationType linear * if both values are absolute or both values are {@link #isProportional() proportional}, * discrete otherwise * @return The width of the anchor rectangle. */ public final double getWidth() { return width; } private double height = 1f; /** * Gets the height of the anchor rectangle. * * @defaultValue 1.0 * @interpolationType linear * if both values are absolute or both values are {@link #isProportional() proportional}, * discrete otherwise * @return The height of the anchor rectangle. */ public final double getHeight() { return height; } private boolean proportional = true; /** * Gets a boolean that indicates whether start and end locations are * proportional or absolute. If this flag is true, the two end points are * defined in a coordinate space where coordinates in the range * {@code [0..1]} are scaled to map onto the bounds of the shape that the * pattern fills. If this flag is false, then the coordinates are specified * in the local coordinate system of the node. * * @defaultValue true * @interpolationType discrete * @return boolean that is true if this paint is proportional. */ public final boolean isProportional() { return proportional; } @Override public final boolean isOpaque() { // We only ever have Prism as our painting system these days, so we can just // cast this platformPaint to a prism paint type and check for isOpaque. // It would be better to change the type on platformPaint accordingly and // ditch the cast. return ((com.sun.prism.paint.ImagePattern)acc_getPlatformPaint()).isOpaque(); } private Object platformPaint; private int hash; /** * Creates a new instance of ImagePattern from the specified image. Default * values are used for all other parameters. * * @param image the image to be used as the paint. * @throws NullPointerException if the image is null. * @throws IllegalArgumentException if image is not done loading, * that is if progress is < 1. */ public ImagePattern(@NamedArg("image") Image image) { if (image == null) { throw new NullPointerException("Image must be non-null."); } else if (image.getProgress() < 1.0) { throw new IllegalArgumentException("Image not yet loaded"); } this.image = image; } /** * Creates a new instance of ImagePattern. * * @param image the image to be used as the paint. * @param x the x origin of the anchor rectangle. * @param y the y origin of the anchor rectangle. * @param width the width of the anchor rectangle. * @param height the height of the anchor rectangle. * @param proportional whether the coordinates are proportional * to the shape which ImagePattern fills * @throws NullPointerException if the image is null. * @throws IllegalArgumentException if image is not done loading, * that is if progress is < 1. */ public ImagePattern(@NamedArg("image") Image image, @NamedArg("x") double x, @NamedArg("y") double y, @NamedArg("width") double width, @NamedArg("height") double height, @NamedArg("proportional") boolean proportional) { if (image == null) { throw new NullPointerException("Image must be non-null."); } else if (image.getProgress() < 1.0) { throw new IllegalArgumentException("Image not yet loaded"); } this.image = image; this.x = x; this.y = y; this.width = width; this.height = height; this.proportional = proportional; } /** * Returns an intermediate value between the value of this {@code ImagePattern} and the specified * {@code endValue} using the linear interpolation factor {@code t}, ranging from 0 (inclusive) * to 1 (inclusive). * * @param endValue the target value * @param t the interpolation factor * @throws NullPointerException if {@code endValue} is {@code null} * @return the intermediate value * @since 24 */ public ImagePattern interpolate(ImagePattern endValue, double t) { Objects.requireNonNull(endValue, "endValue cannot be null"); if (t <= 0 || equals(endValue)) { return this; } if (t >= 1) { return endValue; } if (proportional != endValue.proportional) { return InterpolationUtils.interpolateDiscrete(this, endValue, t); } return new ImagePattern( InterpolationUtils.interpolateDiscrete(image, endValue.image, t), InterpolationUtils.interpolate(x, endValue.x, t), InterpolationUtils.interpolate(y, endValue.y, t), InterpolationUtils.interpolate(width, endValue.width, t), InterpolationUtils.interpolate(height, endValue.height, t), proportional); } /** * {@inheritDoc} * * @throws NullPointerException {@inheritDoc} * @since 24 */ @Override public Paint interpolate(Paint endValue, double t) { return InterpolationUtils.interpolatePaint(this, endValue, t); } @Override public boolean equals(Object obj) { if (obj instanceof ImagePattern other) { return proportional == other.proportional && x == other.x && y == other.y && width == other.width && height == other.height && image.equals(other.image); } return false; } @Override public int hashCode() { if (hash == 0) { long bits = 17L; bits = 37L * bits + Double.doubleToLongBits(x); bits = 37L * bits + Double.doubleToLongBits(y); bits = 37L * bits + Double.doubleToLongBits(width); bits = 37L * bits + Double.doubleToLongBits(height); bits = 37L * bits + ((proportional) ? 1231L : 1237L); bits = 37L * bits + image.hashCode(); hash = (int) (bits ^ (bits >> 32)); } return hash; } @Override boolean acc_isMutable() { return Toolkit.getImageAccessor().isAnimation(image); } @Override void acc_addListener(AbstractNotifyListener platformChangeListener) { Toolkit.getImageAccessor().getImageProperty(image) .addListener(platformChangeListener); } @Override void acc_removeListener(AbstractNotifyListener platformChangeListener) { Toolkit.getImageAccessor().getImageProperty(image) .removeListener(platformChangeListener); } @Override Object acc_getPlatformPaint() { if (acc_isMutable() || platformPaint == null) { platformPaint = Toolkit.getToolkit().getPaint(this); assert platformPaint != null; } return platformPaint; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy