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

javafx.scene.layout.BackgroundSize Maven / Gradle / Ivy

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

import com.sun.javafx.util.InterpolationUtils;
import javafx.animation.Interpolatable;
import javafx.beans.NamedArg;
import java.util.Objects;


/**
 * Defines the size of the area that a BackgroundImage should fill relative
 * to the Region it is styling. There are several properties whose values
 * take precedence over the others. In particular there are 4 key properties,
 * {@code width}, {@code height}, {@code contain}, and {@code cover}. Both width
 * and height are independent of each other, however both interact with
 * contain and cover.
 * 

* From the CSS Specification, {@code cover} is defined to: *

* Scale the image, while preserving its intrinsic aspect ratio (if any), to the smallest size such that both * its width and its height can completely cover the background positioning area. *
* {@code contain} is defined to: *
* Scale the image, while preserving its intrinsic aspect ratio (if any), to the largest size such that both its * width and its height can fit inside the background positioning area. *
* And width and height both specify (in absolute values or percentages) the size to use. These * two properties only apply if both cover and contain are false. If both cover and contain are true, * then {@code cover} will be used. *

* The width and height may also be set to {@code AUTO}, indicating that the area should be sized * so as to use the image's intrinsic size, or if it cannot be determined, 100%. * @since JavaFX 8.0 */ public final class BackgroundSize implements Interpolatable { /** * From the CSS Specification: *

* An "auto" value for one dimension is resolved by using the image's intrinsic ratio and the size of the other * dimension, or failing that, using the image's intrinsic size, or failing that, treating it as 100%. *

* If both values are "auto" then the intrinsic width and/or height of the image should be used, if any, * the missing dimension (if any) behaving as "auto" as described above. If the image has neither an intrinsic * width nor an intrinsic height, its size is determined as for "contain". *

* * When set to AUTO, the values for widthAsPercentage and heightAsPercentage are ignored. */ public static final double AUTO = -1; /** * The default BackgroundSize used by BackgroundImages when an explicit size is not defined. * By default, the BackgroundSize is AUTO, AUTO for the width and height, and is neither * cover nor contain. */ public static final BackgroundSize DEFAULT = new BackgroundSize(AUTO, AUTO, true, true, false, false); /** * The width of the area within the Region where the associated BackgroundImage should * render. If set to AUTO, then {@code widthAsPercentage} is ignored. This value has * no meaning if either {@code contain} or {@code cover} are specified. This value * cannot be negative, except when set to the value of AUTO. * * @return the width of the area within the Region where the associated * BackgroundImage should render * @interpolationType discrete * if {@link #isCover() cover} or {@link #isContain() contain} is set, if one value * is absolute and the other value is a {@link #isWidthAsPercentage() percentage}, * or if the width is {@link #AUTO}; otherwise * linear */ public final double getWidth() { return width; } private final double width; /** * The height of the area within the Region where the associated BackgroundImage should * render. If set to AUTO, then {@code heightAsPercentage} is ignored. This value has * no meaning if either {@code contain} or {@code cover} are specified. This value * cannot be negative, except when set to the value of AUTO. * * @return the height of the area within the Region where the associated * BackgroundImage should render * @interpolationType discrete * if {@link #isCover() cover} or {@link #isContain() contain} is set, if one value * is absolute and the other value is a {@link #isHeightAsPercentage() percentage}, * or if the height is {@link #AUTO}; otherwise * linear */ public final double getHeight() { return height; } private final double height; /** * Specifies whether the value contained in {@code width} should be interpreted * as a percentage or as a normal value. * * @return true if width should be interpreted as a percentage * @interpolationType discrete */ public final boolean isWidthAsPercentage() { return widthAsPercentage; } private final boolean widthAsPercentage; /** * Specifies whether the value contained in {@code height} should be interpreted * as a percentage or as a normal value. * * @return true if height should be interpreted as a percentage * @interpolationType discrete */ public final boolean isHeightAsPercentage() { return heightAsPercentage; } private final boolean heightAsPercentage; /** * If true, scale the image, while preserving its intrinsic aspect ratio (if any), to the * largest size such that both its width and its height can fit inside the background * positioning area. * * @return true if the image can fit inside the background positioning area * @interpolationType discrete */ public final boolean isContain() { return contain; } private final boolean contain; /** * If true, scale the image, while preserving its intrinsic aspect ratio (if any), to the * smallest size such that both its width and its height can completely cover the background * positioning area. * * @return true if image can completely cover the background positioning area * @interpolationType discrete */ public final boolean isCover() { return cover; } private final boolean cover; /** * A cached hash code value */ private final int hash; /** * Create a new BackgroundSize. * * @param width The width. Cannot be less than 0, except for the value of AUTO. * @param height The height. Cannot be less than 0, except for the value of AUTO. * @param widthAsPercentage Whether the width is to be interpreted as a percentage * @param heightAsPercentage Whether the height is to be interpreted as a percentage * @param contain Whether the image should be sized to fit within the Region maximally * @param cover Whether the image should be sized to "cover" the Region */ public BackgroundSize(@NamedArg("width") double width, @NamedArg("height") double height, @NamedArg("widthAsPercentage") boolean widthAsPercentage, @NamedArg("heightAsPercentage") boolean heightAsPercentage, @NamedArg("contain") boolean contain, @NamedArg("cover") boolean cover) { // TODO Should deal with NaN and Infinity values as well if (width < 0 && width != AUTO) throw new IllegalArgumentException("Width cannot be < 0, except when AUTO"); if (height < 0 && height != AUTO) throw new IllegalArgumentException("Height cannot be < 0, except when AUTO"); this.width = width; this.height = height; this.widthAsPercentage = widthAsPercentage; this.heightAsPercentage = heightAsPercentage; this.contain = contain; this.cover = cover; // Pre-compute the hash code. NOTE: all variables are prefixed with "this" so that we // do not accidentally compute the hash based on the constructor arguments rather than // based on the fields themselves! int result; long temp; result = (this.widthAsPercentage ? 1 : 0); result = 31 * result + (this.heightAsPercentage ? 1 : 0); temp = this.width != +0.0d ? Double.doubleToLongBits(this.width) : 0L; result = 31 * result + (int) (temp ^ (temp >>> 32)); temp = this.height != +0.0d ? Double.doubleToLongBits(this.height) : 0L; result = 31 * result + (int) (temp ^ (temp >>> 32)); result = 31 * result + (this.cover ? 1 : 0); result = 31 * result + (this.contain ? 1 : 0); hash = result; } /** * {@inheritDoc} * * @throws NullPointerException {@inheritDoc} * @since 24 */ @Override public BackgroundSize interpolate(BackgroundSize endValue, double t) { Objects.requireNonNull(endValue, "endValue cannot be null"); if (t <= 0) { return this; } if (t >= 1) { return endValue; } if (cover || contain || endValue.cover || endValue.contain) { return t < 0.5 ? this : endValue; } double newWidth = interpolate( this.width, endValue.width, this.widthAsPercentage, endValue.widthAsPercentage, t); double newHeight = interpolate( this.height, endValue.height, this.heightAsPercentage, endValue.heightAsPercentage, t); boolean newWidthAsPercentage, newHeightAsPercentage; if (t < 0.5) { newWidthAsPercentage = this.widthAsPercentage; newHeightAsPercentage = this.heightAsPercentage; } else { newWidthAsPercentage = endValue.widthAsPercentage; newHeightAsPercentage = endValue.heightAsPercentage; } if (isSame(newWidth, newHeight, newWidthAsPercentage, newHeightAsPercentage)) { return this; } if (endValue.isSame(newWidth, newHeight, newWidthAsPercentage, newHeightAsPercentage)) { return endValue; } return new BackgroundSize(newWidth, newHeight, newWidthAsPercentage, newHeightAsPercentage, false, false); } private boolean isSame(double width, double height, boolean widthAsPercentage, boolean heightAsPercentage) { return this.width == width && this.height == height && this.widthAsPercentage == widthAsPercentage && this.heightAsPercentage == heightAsPercentage; } private static double interpolate(double start, double end, boolean startIsPercentage, boolean endIsPercentage, double t) { return startIsPercentage == endIsPercentage && start != AUTO && end != AUTO ? InterpolationUtils.interpolate(start, end, t) : InterpolationUtils.interpolateDiscrete(start, end, t); } /** * {@inheritDoc} */ @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; BackgroundSize that = (BackgroundSize) o; // Because the hash is cached, this can be very fast if (this.hash != that.hash) return false; if (contain != that.contain) return false; if (cover != that.cover) return false; if (Double.compare(that.height, height) != 0) return false; if (heightAsPercentage != that.heightAsPercentage) return false; if (widthAsPercentage != that.widthAsPercentage) return false; if (Double.compare(that.width, width) != 0) return false; return true; } /** * {@inheritDoc} */ @Override public int hashCode() { return hash; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy