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    }