001/* ===================================================
002 * JFreeSVG : an SVG library for the Java(tm) platform
003 * ===================================================
004 * 
005 * (C)opyright 2013-2021, by Object Refinery Limited.  All rights reserved.
006 *
007 * Project Info:  http://www.jfree.org/jfreesvg/index.html
008 * 
009 * This program is free software: you can redistribute it and/or modify
010 * it under the terms of the GNU General Public License as published by
011 * the Free Software Foundation, either version 3 of the License, or
012 * (at your option) any later version.
013 *
014 * This program is distributed in the hope that it will be useful,
015 * but WITHOUT ANY WARRANTY; without even the implied warranty of
016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
017 * GNU General Public License for more details.
018 *
019 * You should have received a copy of the GNU General Public License
020 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
021 * 
022 * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. 
023 * Other names may be trademarks of their respective owners.]
024 * 
025 * If you do not wish to be bound by the terms of the GPL, an alternative
026 * commercial license can be purchased.  For details, please see visit the
027 * JFreeSVG home page:
028 * 
029 * http://www.jfree.org/jfreesvg
030 * 
031 */
032
033package org.jfree.graphics2d;
034
035import java.awt.Polygon;
036import java.awt.Shape;
037import java.awt.geom.Arc2D;
038import java.awt.geom.Ellipse2D;
039import java.awt.geom.GeneralPath;
040import java.awt.geom.Line2D;
041import java.awt.geom.Path2D;
042import java.awt.geom.Rectangle2D;
043import java.awt.geom.RoundRectangle2D;
044import java.awt.image.BufferedImage;
045import java.awt.image.ColorModel;
046import java.awt.image.RenderedImage;
047import java.awt.image.WritableRaster;
048import java.util.Hashtable;
049
050/**
051 * A collection of static utility methods for shapes and images.
052 */
053public final class GraphicsUtils {
054    
055    private GraphicsUtils() {
056        // no need to instantiate this
057    }
058    
059    /**
060     * Returns a shape that is (more or less) equivalent to the supplied shape.
061     * For some known shape implementations ({@code Line2D}, 
062     * {@code Rectangle2D}, {@code RoundRectangle2D}, {@code Arc2D}, 
063     * {@code Ellipse2D}, and {@code Polygon}) the copy will be an instance of 
064     * that class.  For other shapes, a {@code Path2D} containing the outline 
065     * of the shape is returned.
066     * 
067     * @param shape  the shape ({@code null} not permitted).
068     * 
069     * @return A copy of the shape or shape outline (never {@code null}). 
070     */
071    public static Shape copyOf(Shape shape) {
072       Args.nullNotPermitted(shape, "shape");
073       if (shape instanceof Line2D) {
074           Line2D l = (Line2D) shape;
075           return new Line2D.Double(l.getX1(), l.getY1(), l.getX2(), l.getY2());
076       }
077       if (shape instanceof Rectangle2D) {
078           Rectangle2D r = (Rectangle2D) shape;
079           return new Rectangle2D.Double(r.getX(), r.getY(), r.getWidth(), 
080                   r.getHeight());
081       }
082       if (shape instanceof RoundRectangle2D) {
083           RoundRectangle2D rr = (RoundRectangle2D) shape;
084           return new RoundRectangle2D.Double(rr.getX(), rr.getY(), 
085                   rr.getWidth(), rr.getHeight(), rr.getArcWidth(), 
086                   rr.getArcHeight());
087       }
088       if (shape instanceof Arc2D) {
089           Arc2D arc = (Arc2D) shape;
090           return new Arc2D.Double(arc.getX(), arc.getY(), arc.getWidth(),
091                   arc.getHeight(), arc.getAngleStart(), arc.getAngleExtent(),
092                   arc.getArcType());
093       }
094       if (shape instanceof Ellipse2D) {
095           Ellipse2D ell = (Ellipse2D) shape;
096           return new Ellipse2D.Double(ell.getX(), ell.getY(), ell.getWidth(),
097                   ell.getHeight());
098       }
099       if (shape instanceof Polygon) {
100           Polygon p = (Polygon) shape;
101           return new Polygon(p.xpoints, p.ypoints, p.npoints);
102       }
103       return new Path2D.Double(shape);
104    }
105
106    /**
107     * Creates a polygon from the specified {@code x} and {@code y} coordinate 
108     * arrays.
109     * 
110     * @param xPoints  the x-points.
111     * @param yPoints  the y-points.
112     * @param nPoints  the number of points to use for the polyline.
113     * @param close  closed?
114     * 
115     * @return A polygon.
116     */
117    public static GeneralPath createPolygon(int[] xPoints, int[] yPoints, 
118            int nPoints, boolean close) {
119        GeneralPath p = new GeneralPath();
120        p.moveTo(xPoints[0], yPoints[0]);
121        for (int i = 1; i < nPoints; i++) {
122            p.lineTo(xPoints[i], yPoints[i]);
123        }
124        if (close) {
125            p.closePath();
126        }
127        return p;
128    }
129
130    /**
131     * Converts a rendered image to a {@code BufferedImage}.  This utility
132     * method has come from a forum post by Jim Moore at:
133     * <p>
134     * <a href="http://www.jguru.com/faq/view.jsp?EID=114602">
135     * http://www.jguru.com/faq/view.jsp?EID=114602</a>
136     * 
137     * @param img  the rendered image.
138     * 
139     * @return A buffered image. 
140     */
141    public static BufferedImage convertRenderedImage(RenderedImage img) {
142        if (img instanceof BufferedImage) {
143            return (BufferedImage) img; 
144        }
145        ColorModel cm = img.getColorModel();
146        int width = img.getWidth();
147        int height = img.getHeight();
148        WritableRaster raster = cm.createCompatibleWritableRaster(width, height);
149        boolean isAlphaPremultiplied = cm.isAlphaPremultiplied();
150        Hashtable properties = new Hashtable();
151        String[] keys = img.getPropertyNames();
152        if (keys != null) {
153            for (int i = 0; i < keys.length; i++) {
154                properties.put(keys[i], img.getProperty(keys[i]));
155            }
156        }
157        BufferedImage result = new BufferedImage(cm, raster, 
158                isAlphaPremultiplied, properties);
159        img.copyData(raster);
160        return result;
161    }
162}