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.paint;
027
028import com.sun.javafx.beans.event.AbstractNotifyListener;
029import com.sun.javafx.tk.Toolkit;
030import javafx.scene.image.Image;
031
032/**
033 * <p>The {@code ImagePattern} class fills a shape with an image pattern. The
034 * user may specify the anchor rectangle, which defines the position,
035 * width, and height of the image relative to the upper left corner of the
036 * shape. If the shape extends out of the anchor rectangle, the image is tiled.
037 * </p>
038 *
039 * <p>If the {@code proportional} variable is set to true (the default)
040 * then the anchor rectangle should be specified relative to the unit
041 * square (0.0->1.0) and will be stretched across the shape.
042 * If the {@code proportional} variable is set to false, then the anchor
043 * rectangle should be specified in the local coordinate system of the shape 
044 * and the image will be stretched to fit the anchor rectangle. The anchor 
045 * rectangle will not be stretched across the shape.</p>
046 *
047 * <p>The example below demonstrates the use of the {@code proportional}
048 * variable.  The shapes on the top row use proportional coordinates
049 * (the default) to specify the anchor rectangle.  The shapes on the
050 * bottom row use absolute coordinates.  The flower image is stretched
051 * to fill the entire triangle shape, while the dot pattern image is tiled
052 * within the circle shape.</p>
053 *
054<pre><code>
055import javafx.scene.Scene;
056import javafx.scene.image.Image;
057import javafx.scene.paint.ImagePattern;
058import javafx.scene.shape.Circle;
059import javafx.scene.shape.Polygon;
060import javafx.stage.Stage;
061
062public class HelloImagePattern extends Application {
063    
064    private static final String flowerURL = "file:flower.png";
065    private static final String dotsURL = "file:dots.png";
066    
067    &#64;Override public void start(Stage stage) {
068        stage.setTitle("Image Pattern");
069        Group root = new Group();
070        Scene scene = new Scene(root, 600, 450);
071        
072        Image dots = new Image(dotsURL);
073        Image flower = new Image(flowerURL);
074        
075        Polygon p = new Polygon();
076        
077        p.setLayoutX(10);
078        p.setLayoutY(10);
079        p.getPoints().add(50.0);
080        p.getPoints().add(0.0);
081        p.getPoints().add(100.0);
082        p.getPoints().add(100.0);
083        p.getPoints().add(0.0);
084        p.getPoints().add(100.0);
085        
086        p.setFill(new ImagePattern(flower, 0, 0, 1, 1, true));
087        
088        root.getChildren().add(p);
089        
090        Polygon p2 = new Polygon();
091        
092        p2.setLayoutX(10);
093        p2.setLayoutY(120);
094        p2.getPoints().add(50.0);
095        p2.getPoints().add(0.0);
096        p2.getPoints().add(100.0);
097        p2.getPoints().add(100.0);
098        p2.getPoints().add(0.0);
099        p2.getPoints().add(100.0);
100        
101        p2.setFill(new ImagePattern(flower, 0, 0, 100, 100, false));
102        
103        root.getChildren().add(p2);
104        
105        Circle circ = new Circle(50);
106        circ.setTranslateX(120);
107        circ.setTranslateY(10);
108        circ.setCenterX(50);
109        circ.setCenterY(50);
110        circ.setFill(new ImagePattern(dots, 0.2, 0.2, 0.4, 0.4, true));
111        
112        root.getChildren().add(circ);
113        
114        Circle circ2 = new Circle(50);
115        circ2.setTranslateX(120);
116        circ2.setTranslateY(10);
117        circ2.setCenterX(50);
118        circ2.setCenterY(50);
119        circ2.setFill(new ImagePattern(dots, 20, 20, 40, 40, false));
120        
121        root.getChildren().add(circ2);
122        stage.setScene(scene);
123        stage.show();
124    }
125</pre></code>
126 * <p>The code above produces the following:</p>
127 * <p><img src="doc-files/ImagePattern.png"/></p>
128 *
129 * @since 2.2
130 */
131public final class ImagePattern extends Paint {
132    
133    private Image image;
134
135    /**
136     * Gets the image to be used as a paint.
137     * 
138     * @return Image to be used as a paint.
139     */
140    public final Image getImage() {
141        return image;
142    }
143    
144    
145    private double x;
146    
147    /**
148     * Gets the x origin of the anchor rectangle.
149     *
150     * @defaultValue 0.0
151     * @return The x origin of the anchor rectangle.
152     */
153    public final double getX() {
154        return x;
155    }
156    
157    private double y;
158
159    /**
160     * Gets the y origin of the anchor rectangle.
161     *
162     * @defaultValue 0.0
163     * @return The y origin of the anchor rectangle.
164     */
165    public final double getY() {
166        return y;
167    }
168    
169    
170    private double width = 1f;
171    
172    /**
173     * Gets the width of the anchor rectangle.
174     *
175     * @defaultValue 1.0
176     * @return The width of the anchor rectangle.
177     */
178    public final double getWidth() {
179        return width;
180    }
181    
182    
183    private double height = 1f;
184    
185    /**
186     * Gets the height of the anchor rectangle.
187     *
188     * @defaultValue 1.0
189     * @return The height of the anchor rectangle.
190     */
191    public final double getHeight() {
192        return height;
193    }
194    
195
196    private boolean proportional = true;
197
198    /**
199     * Gets a boolean that indicates whether start and end locations are 
200     * proportional or absolute. If this flag is true, the two end points are 
201     * defined in a coordinate space where coordinates in the range 
202     * {@code [0..1]} are scaled to map onto the bounds of the shape that the 
203     * pattern fills. If this flag is false, then the coordinates are specified 
204     * in the local coordinate system of the node.
205     *
206     * @defaultValue true
207     * @return boolean that is true if this paint is proportional.
208     */
209    public final boolean isProportional() {
210        return proportional;
211    }
212
213    @Override public final boolean isOpaque() {
214        // RT-24827: isOpaque should return true if the image doesn't have an alpha.
215        // We haven't implemented this support yet, but should!
216        return false;
217    }
218
219    private Object platformPaint;
220
221    /**
222     * Creates a new instance of ImagePattern from the specified image. Default 
223     * values are used for all other parameters.
224     * 
225     * @param image the image to be used as the paint.
226     * @throws NullPointerException if the image is null.
227     * @throws IllegalArgumentException if image is not done loading, 
228     * that is if progress is < 1.
229     */
230    public ImagePattern(Image image) {
231        if (image == null) {
232            throw new NullPointerException("Image must be non-null.");
233        } else if (image.getProgress() < 1.0) {
234            throw new IllegalArgumentException("Image not yet loaded");
235        }
236        this.image = image;
237    }
238
239    /**
240     * Creates a new instance of ImagePattern.
241     * 
242     * @param image the image to be used as the paint.
243     * @param x the x origin of the anchor rectangle.
244     * @param y the y origin of the anchor rectangle.
245     * @param width the width of the anchor rectangle.
246     * @param height the height of the anchor rectangle.
247     * @param proportional whether the coordinates are proportional
248     * to the shape which ImagePattern fills
249     * @throws NullPointerException if the image is null.
250     * @throws IllegalArgumentException if image is not done loading, 
251     * that is if progress is < 1.
252     */
253    public ImagePattern(Image image, double x, double y, double width,
254            double height, boolean proportional) {
255
256        if (image == null) {
257            throw new NullPointerException("Image must be non-null.");
258        } else if (image.getProgress() < 1.0) {
259            throw new IllegalArgumentException("Image not yet loaded");
260        }
261        this.image = image;
262        this.x = x;
263        this.y = y;
264        this.width = width;
265        this.height = height;
266        this.proportional = proportional;
267    }
268
269    @Override
270    boolean acc_isMutable() {
271        return Toolkit.getImageAccessor().isAnimation(image);
272    }
273
274    @Override
275    void acc_addListener(AbstractNotifyListener platformChangeListener) {
276        Toolkit.getImageAccessor().getImageProperty(image)
277                .addListener(platformChangeListener);
278    }
279
280    @Override
281    void acc_removeListener(AbstractNotifyListener platformChangeListener) {
282        Toolkit.getImageAccessor().getImageProperty(image)
283                .removeListener(platformChangeListener);
284    }
285
286    @Override Object acc_getPlatformPaint() {
287        if (acc_isMutable() || platformPaint == null) {
288            platformPaint = Toolkit.getToolkit().getPaint(this);
289        }
290        return platformPaint;
291    }
292}