001/* ===============
002 * SkijaGraphics2D
003 * ===============
004 *
005 * (C)opyright 2021, by David Gilbert.
006 *
007 * The SkijaGraphics2D class has been developed by David Gilbert for
008 * use with Orson Charts (http://www.object-refinery.com/orsoncharts) and
009 * JFreeChart (http://www.jfree.org/jfreechart).  It may be useful for other
010 * code that uses the Graphics2D API provided by Java2D.
011 *
012 * Redistribution and use in source and binary forms, with or without
013 * modification, are permitted provided that the following conditions are met:
014 *   - Redistributions of source code must retain the above copyright
015 *     notice, this list of conditions and the following disclaimer.
016 *   - Redistributions in binary form must reproduce the above copyright
017 *     notice, this list of conditions and the following disclaimer in the
018 *     documentation and/or other materials provided with the distribution.
019 *   - Neither the name of the Object Refinery Limited nor the
020 *     names of its contributors may be used to endorse or promote products
021 *     derived from this software without specific prior written permission.
022 *
023 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
024 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
025 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
026 * ARE DISCLAIMED. IN NO EVENT SHALL OBJECT REFINERY LIMITED BE LIABLE FOR ANY
027 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
028 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
029 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
030 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
031 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
032 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
033 *
034 */
035
036package org.jfree.skija;
037
038import java.awt.*;
039import java.awt.geom.AffineTransform;
040import java.awt.image.BufferedImage;
041import java.awt.image.ColorModel;
042import java.awt.image.DirectColorModel;
043import java.awt.image.VolatileImage;
044
045/**
046 * A graphics configuration for the {@link SkijaGraphics2D} class.
047 */
048public class SkijaGraphicsConfiguration extends GraphicsConfiguration {
049
050    private GraphicsDevice device;
051
052    private final int width, height;
053
054    /**
055     * Creates a new instance.
056     *
057     * @param width  the width of the bounds.
058     * @param height  the height of the bounds.
059     */
060    public SkijaGraphicsConfiguration(int width, int height) {
061        super();
062        this.width = width;
063        this.height = height;
064    }
065
066    /**
067     * Returns the graphics device that this configuration is associated with.
068     *
069     * @return The graphics device (never {@code null}).
070     */
071    @Override
072    public GraphicsDevice getDevice() {
073        if (this.device == null) {
074            this.device = new SkijaGraphicsDevice("SkijaGraphicsDevice", this);
075        }
076        return this.device;
077    }
078
079    /**
080     * Returns the color model for this configuration.
081     *
082     * @return The color model.
083     */
084    @Override
085    public ColorModel getColorModel() {
086        return getColorModel(Transparency.TRANSLUCENT);
087    }
088
089    /**
090     * Returns the color model for the specified transparency type, or
091     * {@code null}.
092     *
093     * @param transparency  the transparency type.
094     *
095     * @return A color model (possibly {@code null}).
096     */
097    @Override
098    public ColorModel getColorModel(int transparency) {
099        if (transparency == Transparency.TRANSLUCENT) {
100            return ColorModel.getRGBdefault();
101        } else if (transparency == Transparency.OPAQUE) {
102            return new DirectColorModel(32, 0x00ff0000, 0x0000ff00, 0x000000ff);
103        } else {
104            return null;
105        }
106    }
107
108    /**
109     * Returns the default transform.
110     *
111     * @return The default transform.
112     */
113    @Override
114    public AffineTransform getDefaultTransform() {
115        return new AffineTransform();
116    }
117
118    /**
119     * Returns the normalizing transform.
120     *
121     * @return The normalizing transform.
122     */
123    @Override
124    public AffineTransform getNormalizingTransform() {
125        return new AffineTransform();
126    }
127
128    /**
129     * Returns the bounds for this configuration.
130     *
131     * @return The bounds.
132     */
133    @Override
134    public Rectangle getBounds() {
135        return new Rectangle(this.width, this.height);
136    }
137
138    private BufferedImage img;
139    private GraphicsConfiguration gc;
140
141    /**
142     * Returns a volatile image.  This method is a workaround for a
143     * ClassCastException that occurs on MacOSX when exporting a Swing UI
144     * that uses the Nimbus Look and Feel.
145     *
146     * @param width  the image width.
147     * @param height  the image height.
148     * @param caps  the image capabilities.
149     * @param transparency  the transparency.
150     *
151     * @return The volatile image.
152     *
153     * @throws AWTException if there is a problem creating the image.
154     */
155    @Override
156    public VolatileImage createCompatibleVolatileImage(int width, int height,
157                                                       ImageCapabilities caps, int transparency) throws AWTException {
158        if (img == null) {
159            img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
160            gc = img.createGraphics().getDeviceConfiguration();
161        }
162        return gc.createCompatibleVolatileImage(width, height, caps,
163                transparency);
164    }
165
166}