    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
    048package org.jfree.util;
    049
    050import java.awt.Graphics;
    051import java.awt.Image;
    052import java.awt.image.BufferedImage;
    053import java.awt.image.ImageObserver;
    054import 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 */
    066public 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}