001 /* ========================================================================
002 * JCommon : a free general purpose class library for the Java(tm) platform
003 * ========================================================================
004 *
005 * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
006 *
007 * Project Info: http://www.jfree.org/jcommon/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
022 * USA.
023 *
024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025 * in the United States and other countries.]
026 *
027 * -------------------------
028 * WaitingImageObserver.java
029 * -------------------------
030 * (C)opyright 2000-2004, by Thomas Morgner and Contributors.
031 *
032 * Original Author: Thomas Morgner
033 * Contributor(s): Stefan Prange;
034 *
035 * $Id: WaitingImageObserver.java,v 1.8 2008/09/10 09:24:41 mungady Exp $
036 *
037 * Changes (from 8-Feb-2002)
038 * -------------------------
039 * 15-Apr-2002 : first version used by ImageElement.
040 * 16-May-2002 : Line delimiters adjusted
041 * 04-Jun-2002 : Documentation and added a NullPointerCheck for the constructor.
042 * 14-Jul-2002 : BugFixed: WaitingImageObserver dead-locked (bugfix by Stefan
043 * Prange)
044 * 18-Mar-2003 : Updated header and made minor Javadoc changes (DG);
045 * 21-Sep-2003 : Moved from JFreeReport.
046 */
047
048 package org.jfree.util;
049
050 import java.awt.Graphics;
051 import java.awt.Image;
052 import java.awt.image.BufferedImage;
053 import java.awt.image.ImageObserver;
054 import java.io.Serializable;
055
056 /**
057 * This image observer blocks until the image is completely loaded. AWT
058 * defers the loading of images until they are painted on a graphic.
059 *
060 * While printing reports it is not very nice, not to know whether a image
061 * was completely loaded, so this observer forces the loading of the image
062 * until a final state (either ALLBITS, ABORT or ERROR) is reached.
063 *
064 * @author Thomas Morgner
065 */
066 public class WaitingImageObserver implements ImageObserver, Serializable,
067 Cloneable
068 {
069 /** For serialization. */
070 static final long serialVersionUID = -807204410581383550L;
071
072 /** The lock. */
073 private boolean lock;
074
075 /** The image. */
076 private Image image;
077
078 /** A flag that signals an error. */
079 private boolean error;
080
081 /**
082 * Creates a new <code>ImageObserver<code> for the given <code>Image<code>.
083 * The observer has to be started by an external thread.
084 *
085 * @param image the image to observe (<code>null</code> not permitted).
086 */
087 public WaitingImageObserver(final Image image) {
088 if (image == null) {
089 throw new NullPointerException();
090 }
091 this.image = image;
092 this.lock = true;
093 }
094
095 /**
096 * Callback function used by AWT to inform that more data is available. The
097 * observer waits until either all data is loaded or AWT signals that the
098 * image cannot be loaded.
099 *
100 * @param img the image being observed.
101 * @param infoflags the bitwise inclusive OR of the following
102 * flags: <code>WIDTH</code>, <code>HEIGHT</code>,
103 * <code>PROPERTIES</code>, <code>SOMEBITS</code>,
104 * <code>FRAMEBITS</code>, <code>ALLBITS</code>,
105 * <code>ERROR</code>, <code>ABORT</code>.
106 * @param x the <i>x</i> coordinate.
107 * @param y the <i>y</i> coordinate.
108 * @param width the width.
109 * @param height the height.
110 *
111 * @return <code>false</code> if the infoflags indicate that the
112 * image is completely loaded; <code>true</code> otherwise.
113 */
114 public synchronized boolean imageUpdate(
115 final Image img,
116 final int infoflags,
117 final int x,
118 final int y,
119 final int width,
120 final int height) {
121 if ((infoflags & ImageObserver.ALLBITS) == ImageObserver.ALLBITS) {
122 this.lock = false;
123 this.error = false;
124 notifyAll();
125 return false;
126 }
127 else if ((infoflags & ImageObserver.ABORT) == ImageObserver.ABORT
128 || (infoflags & ImageObserver.ERROR) == ImageObserver.ERROR) {
129 this.lock = false;
130 this.error = true;
131 notifyAll();
132 return false;
133 }
134 //notifyAll();
135 return true;
136 }
137
138 /**
139 * The workerthread. Simply draws the image to a BufferedImage's
140 * Graphics-Object and waits for the AWT to load the image.
141 */
142 public synchronized void waitImageLoaded() {
143
144 if (this.lock == false)
145 {
146 return;
147 }
148
149 final BufferedImage img = new BufferedImage(
150 1, 1, BufferedImage.TYPE_INT_RGB
151 );
152 final Graphics g = img.getGraphics();
153
154 while (this.lock) {
155 if (g.drawImage(this.image, 0, 0, img.getWidth(this),
156 img.getHeight(this), this)) {
157 return;
158 }
159
160 try {
161 wait(500);
162 }
163 catch (InterruptedException e) {
164 Log.info(
165 "WaitingImageObserver.waitImageLoaded(): InterruptedException thrown",
166 e
167 );
168 }
169 }
170 }
171
172 /**
173 * Clones this WaitingImageObserver.
174 *
175 * @return a clone.
176 *
177 * @throws CloneNotSupportedException this should never happen.
178 * @deprecated cloning may lock down the observer
179 */
180 public Object clone() throws CloneNotSupportedException {
181 return (WaitingImageObserver) super.clone();
182 }
183
184 /**
185 * Returns <code>true</code> if loading is complete, and <code>false</code>
186 * otherwise.
187 *
188 * @return A boolean.
189 */
190 public boolean isLoadingComplete() {
191 return this.lock == false;
192 }
193
194 /**
195 * Returns true if there is an error condition, and false otherwise.
196 *
197 * @return A boolean.
198 */
199 public boolean isError() {
200 return this.error;
201 }
202 }