001/* =========================================================== 002 * Orson Charts : a 3D chart library for the Java(tm) platform 003 * =========================================================== 004 * 005 * (C)opyright 2013-2022, by David Gilbert. All rights reserved. 006 * 007 * https://github.com/jfree/orson-charts 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 * Orson Charts home page: 028 * 029 * http://www.object-refinery.com/orsoncharts/index.html 030 * 031 */ 032 033package org.jfree.chart3d.table; 034 035import java.awt.Dimension; 036import java.awt.Image; 037import java.awt.Graphics2D; 038import java.awt.Paint; 039import java.awt.geom.Rectangle2D; 040import java.io.Serializable; 041import java.io.IOException; 042import java.io.ObjectInputStream; 043import java.io.ObjectOutputStream; 044 045import org.jfree.chart3d.graphics2d.Anchor2D; 046import org.jfree.chart3d.graphics2d.Fit2D; 047import org.jfree.chart3d.graphics2d.Scale2D; 048import org.jfree.chart3d.internal.Args; 049import org.jfree.chart3d.internal.ObjectUtils; 050import org.jfree.chart3d.internal.SerialUtils; 051 052 053/** 054 * A {@link RectanglePainter} that fills the rectangle with a 055 * color or image. Instances of this class are immutable. 056 * <br><br> 057 * Note that it is possible to use gradient paint with this painter, but it is 058 * usually better to use {@link GradientRectanglePainter} since it provides 059 * options to transform the gradient to fit the chart background size. 060 * <br><br> 061 * NOTE: This class is serializable, but the serialization format is subject 062 * to change in future releases and should not be relied upon for persisting 063 * instances of this class. 064 */ 065@SuppressWarnings("serial") 066public class StandardRectanglePainter implements RectanglePainter, 067 Serializable { 068 069 /** The paint (never {@code null}). */ 070 private transient Paint paint; 071 072 /** A background image for the chart, if any. */ 073 private transient Image image; 074 075 private Fit2D imageFit; 076 077 /** 078 * Creates a new painter that will fill a rectangle with the specified 079 * paint. 080 * 081 * @param paint the fill paint ({@code null} not permitted). 082 */ 083 public StandardRectanglePainter(Paint paint) { 084 this(paint, null, null); 085 } 086 087 /** 088 * Creates a new painter that will draw an image within the specified 089 * rectangle. 090 * 091 * @param paint the background paint ({@code null} not permitted). 092 * @param image the image ({@code null} permitted). 093 * @param imageFit the fit ({@code null} permitted). 094 */ 095 public StandardRectanglePainter(Paint paint, Image image, Fit2D imageFit) { 096 Args.nullNotPermitted(paint, "paint"); 097 this.paint = paint; 098 this.image = image; 099 this.imageFit = new Fit2D(Anchor2D.TOP_CENTER, Scale2D.SCALE_BOTH); 100 if (imageFit != null) { 101 this.imageFit = imageFit; 102 } 103 } 104 105 /** 106 * Returns the paint that will be used to fill rectangles. 107 * 108 * @return The paint (never {@code null}). 109 */ 110 public Paint getPaint() { 111 return this.paint; 112 } 113 114 /** 115 * Returns the image. 116 * 117 * @return The image (possibly {@code null}). 118 */ 119 public Image getImage() { 120 return this.image; 121 } 122 123 /** 124 * Returns the image fit specification. 125 * 126 * @return The image fit specification. 127 */ 128 public Fit2D getImageFit() { 129 return this.imageFit; 130 } 131 132 /** 133 * Fills the rectangle with the paint specified in the constructor. 134 * 135 * @param g2 the graphics target ({@code null} not permitted). 136 * @param bounds the rectangle ({@code null} not permitted). 137 */ 138 @Override 139 public void fill(Graphics2D g2, Rectangle2D bounds) { 140 Paint saved = g2.getPaint(); 141 g2.setPaint(this.paint); 142 g2.fill(bounds); 143 if (this.image != null) { 144 int w = this.image.getWidth(null); 145 int h = this.image.getHeight(null); 146 Rectangle2D imageBounds = this.imageFit.fit(new Dimension(w, h), 147 bounds); 148 g2.drawImage(this.image, (int) imageBounds.getX(), 149 (int) imageBounds.getY(), (int) imageBounds.getWidth(), 150 (int) imageBounds.getHeight(), null); 151 } 152 g2.setPaint(saved); 153 } 154 155 /** 156 * Tests this painter for equality with an arbitrary object. 157 * 158 * @param obj the object ({@code null} permitted). 159 * 160 * @return A boolean. 161 */ 162 @Override 163 public boolean equals(Object obj) { 164 if (obj == this) { 165 return true; 166 } 167 if (!(obj instanceof StandardRectanglePainter)) { 168 return false; 169 } 170 StandardRectanglePainter that = (StandardRectanglePainter) obj; 171 if (!ObjectUtils.equalsPaint(this.paint, that.paint)) { 172 return false; 173 } 174 return true; 175 } 176 177 /** 178 * Provides serialization support. 179 * 180 * @param stream the output stream. 181 * 182 * @throws IOException if there is an I/O error. 183 */ 184 private void writeObject(ObjectOutputStream stream) throws IOException { 185 stream.defaultWriteObject(); 186 SerialUtils.writePaint(this.paint, stream); 187 // TODO : serialize the image 188 } 189 190 /** 191 * Provides serialization support. 192 * 193 * @param stream the input stream. 194 * 195 * @throws IOException if there is an I/O error. 196 * @throws ClassNotFoundException if there is a classpath problem. 197 */ 198 private void readObject(ObjectInputStream stream) 199 throws IOException, ClassNotFoundException { 200 stream.defaultReadObject(); 201 this.paint = SerialUtils.readPaint(stream); 202 // deserialize the image 203 } 204}