diff -r fd16c54261b3 -r 90ce3da70b43 jdk/src/share/classes/java/awt/MediaTracker.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/share/classes/java/awt/MediaTracker.java Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,949 @@ +/* + * Copyright 1995-2007 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package java.awt; + +import java.awt.Component; +import java.awt.Image; +import java.awt.image.ImageObserver; + +/** + * The MediaTracker class is a utility class to track + * the status of a number of media objects. Media objects could + * include audio clips as well as images, though currently only + * images are supported. + *

+ * To use a media tracker, create an instance of + * MediaTracker and call its addImage + * method for each image to be tracked. In addition, each image can + * be assigned a unique identifier. This identifier controls the + * priority order in which the images are fetched. It can also be used + * to identify unique subsets of the images that can be waited on + * independently. Images with a lower ID are loaded in preference to + * those with a higher ID number. + * + *

+ * + * Tracking an animated image + * might not always be useful + * due to the multi-part nature of animated image + * loading and painting, + * but it is supported. + * MediaTracker treats an animated image + * as completely loaded + * when the first frame is completely loaded. + * At that point, the MediaTracker + * signals any waiters + * that the image is completely loaded. + * If no ImageObservers are observing the image + * when the first frame has finished loading, + * the image might flush itself + * to conserve resources + * (see {@link Image#flush()}). + * + *

+ * Here is an example of using MediaTracker: + *

+ *


+ * import java.applet.Applet;
+ * import java.awt.Color;
+ * import java.awt.Image;
+ * import java.awt.Graphics;
+ * import java.awt.MediaTracker;
+ *
+ * public class ImageBlaster extends Applet implements Runnable {
+ *      MediaTracker tracker;
+ *      Image bg;
+ *      Image anim[] = new Image[5];
+ *      int index;
+ *      Thread animator;
+ *
+ *      // Get the images for the background (id == 0)
+ *      // and the animation frames (id == 1)
+ *      // and add them to the MediaTracker
+ *      public void init() {
+ *          tracker = new MediaTracker(this);
+ *          bg = getImage(getDocumentBase(),
+ *                  "images/background.gif");
+ *          tracker.addImage(bg, 0);
+ *          for (int i = 0; i < 5; i++) {
+ *              anim[i] = getImage(getDocumentBase(),
+ *                      "images/anim"+i+".gif");
+ *              tracker.addImage(anim[i], 1);
+ *          }
+ *      }
+ *
+ *      // Start the animation thread.
+ *      public void start() {
+ *          animator = new Thread(this);
+ *          animator.start();
+ *      }
+ *
+ *      // Stop the animation thread.
+ *      public void stop() {
+ *          animator = null;
+ *      }
+ *
+ *      // Run the animation thread.
+ *      // First wait for the background image to fully load
+ *      // and paint.  Then wait for all of the animation
+ *      // frames to finish loading. Finally, loop and
+ *      // increment the animation frame index.
+ *      public void run() {
+ *          try {
+ *              tracker.waitForID(0);
+ *              tracker.waitForID(1);
+ *          } catch (InterruptedException e) {
+ *              return;
+ *          }
+ *          Thread me = Thread.currentThread();
+ *          while (animator == me) {
+ *              try {
+ *                  Thread.sleep(100);
+ *              } catch (InterruptedException e) {
+ *                  break;
+ *              }
+ *              synchronized (this) {
+ *                  index++;
+ *                  if (index >= anim.length) {
+ *                      index = 0;
+ *                  }
+ *              }
+ *              repaint();
+ *          }
+ *      }
+ *
+ *      // The background image fills the frame so we
+ *      // don't need to clear the applet on repaints.
+ *      // Just call the paint method.
+ *      public void update(Graphics g) {
+ *          paint(g);
+ *      }
+ *
+ *      // Paint a large red rectangle if there are any errors
+ *      // loading the images.  Otherwise always paint the
+ *      // background so that it appears incrementally as it
+ *      // is loading.  Finally, only paint the current animation
+ *      // frame if all of the frames (id == 1) are done loading,
+ *      // so that we don't get partial animations.
+ *      public void paint(Graphics g) {
+ *          if ((tracker.statusAll(false) & MediaTracker.ERRORED) != 0) {
+ *              g.setColor(Color.red);
+ *              g.fillRect(0, 0, size().width, size().height);
+ *              return;
+ *          }
+ *          g.drawImage(bg, 0, 0, this);
+ *          if (tracker.statusID(1, false) == MediaTracker.COMPLETE) {
+ *              g.drawImage(anim[index], 10, 10, this);
+ *          }
+ *      }
+ * }
+ * 

+ * + * @author Jim Graham + * @since JDK1.0 + */ +public class MediaTracker implements java.io.Serializable { + + /** + * A given Component that will be + * tracked by a media tracker where the image will + * eventually be drawn. + * + * @serial + * @see #MediaTracker(Component) + */ + Component target; + /** + * The head of the list of Images that is being + * tracked by the MediaTracker. + * + * @serial + * @see #addImage(Image, int) + * @see #removeImage(Image) + */ + MediaEntry head; + + /* + * JDK 1.1 serialVersionUID + */ + private static final long serialVersionUID = -483174189758638095L; + + /** + * Creates a media tracker to track images for a given component. + * @param comp the component on which the images + * will eventually be drawn + */ + public MediaTracker(Component comp) { + target = comp; + } + + /** + * Adds an image to the list of images being tracked by this media + * tracker. The image will eventually be rendered at its default + * (unscaled) size. + * @param image the image to be tracked + * @param id an identifier used to track this image + */ + public void addImage(Image image, int id) { + addImage(image, id, -1, -1); + } + + /** + * Adds a scaled image to the list of images being tracked + * by this media tracker. The image will eventually be + * rendered at the indicated width and height. + * + * @param image the image to be tracked + * @param id an identifier that can be used to track this image + * @param w the width at which the image is rendered + * @param h the height at which the image is rendered + */ + public synchronized void addImage(Image image, int id, int w, int h) { + head = MediaEntry.insert(head, + new ImageMediaEntry(this, image, id, w, h)); + } + + /** + * Flag indicating that media is currently being loaded. + * @see java.awt.MediaTracker#statusAll + * @see java.awt.MediaTracker#statusID + */ + public static final int LOADING = 1; + + /** + * Flag indicating that the downloading of media was aborted. + * @see java.awt.MediaTracker#statusAll + * @see java.awt.MediaTracker#statusID + */ + public static final int ABORTED = 2; + + /** + * Flag indicating that the downloading of media encountered + * an error. + * @see java.awt.MediaTracker#statusAll + * @see java.awt.MediaTracker#statusID + */ + public static final int ERRORED = 4; + + /** + * Flag indicating that the downloading of media was completed + * successfully. + * @see java.awt.MediaTracker#statusAll + * @see java.awt.MediaTracker#statusID + */ + public static final int COMPLETE = 8; + + static final int DONE = (ABORTED | ERRORED | COMPLETE); + + /** + * Checks to see if all images being tracked by this media tracker + * have finished loading. + *

+ * This method does not start loading the images if they are not + * already loading. + *

+ * If there is an error while loading or scaling an image, then that + * image is considered to have finished loading. Use the + * isErrorAny or isErrorID methods to + * check for errors. + * @return true if all images have finished loading, + * have been aborted, or have encountered + * an error; false otherwise + * @see java.awt.MediaTracker#checkAll(boolean) + * @see java.awt.MediaTracker#checkID + * @see java.awt.MediaTracker#isErrorAny + * @see java.awt.MediaTracker#isErrorID + */ + public boolean checkAll() { + return checkAll(false, true); + } + + /** + * Checks to see if all images being tracked by this media tracker + * have finished loading. + *

+ * If the value of the load flag is true, + * then this method starts loading any images that are not yet + * being loaded. + *

+ * If there is an error while loading or scaling an image, that + * image is considered to have finished loading. Use the + * isErrorAny and isErrorID methods to + * check for errors. + * @param load if true, start loading any + * images that are not yet being loaded + * @return true if all images have finished loading, + * have been aborted, or have encountered + * an error; false otherwise + * @see java.awt.MediaTracker#checkID + * @see java.awt.MediaTracker#checkAll() + * @see java.awt.MediaTracker#isErrorAny() + * @see java.awt.MediaTracker#isErrorID(int) + */ + public boolean checkAll(boolean load) { + return checkAll(load, true); + } + + private synchronized boolean checkAll(boolean load, boolean verify) { + MediaEntry cur = head; + boolean done = true; + while (cur != null) { + if ((cur.getStatus(load, verify) & DONE) == 0) { + done = false; + } + cur = cur.next; + } + return done; + } + + /** + * Checks the error status of all of the images. + * @return true if any of the images tracked + * by this media tracker had an error during + * loading; false otherwise + * @see java.awt.MediaTracker#isErrorID + * @see java.awt.MediaTracker#getErrorsAny + */ + public synchronized boolean isErrorAny() { + MediaEntry cur = head; + while (cur != null) { + if ((cur.getStatus(false, true) & ERRORED) != 0) { + return true; + } + cur = cur.next; + } + return false; + } + + /** + * Returns a list of all media that have encountered an error. + * @return an array of media objects tracked by this + * media tracker that have encountered + * an error, or null if + * there are none with errors + * @see java.awt.MediaTracker#isErrorAny + * @see java.awt.MediaTracker#getErrorsID + */ + public synchronized Object[] getErrorsAny() { + MediaEntry cur = head; + int numerrors = 0; + while (cur != null) { + if ((cur.getStatus(false, true) & ERRORED) != 0) { + numerrors++; + } + cur = cur.next; + } + if (numerrors == 0) { + return null; + } + Object errors[] = new Object[numerrors]; + cur = head; + numerrors = 0; + while (cur != null) { + if ((cur.getStatus(false, false) & ERRORED) != 0) { + errors[numerrors++] = cur.getMedia(); + } + cur = cur.next; + } + return errors; + } + + /** + * Starts loading all images tracked by this media tracker. This + * method waits until all the images being tracked have finished + * loading. + *

+ * If there is an error while loading or scaling an image, then that + * image is considered to have finished loading. Use the + * isErrorAny or isErrorID methods to + * check for errors. + * @see java.awt.MediaTracker#waitForID(int) + * @see java.awt.MediaTracker#waitForAll(long) + * @see java.awt.MediaTracker#isErrorAny + * @see java.awt.MediaTracker#isErrorID + * @exception InterruptedException if any thread has + * interrupted this thread + */ + public void waitForAll() throws InterruptedException { + waitForAll(0); + } + + /** + * Starts loading all images tracked by this media tracker. This + * method waits until all the images being tracked have finished + * loading, or until the length of time specified in milliseconds + * by the ms argument has passed. + *

+ * If there is an error while loading or scaling an image, then + * that image is considered to have finished loading. Use the + * isErrorAny or isErrorID methods to + * check for errors. + * @param ms the number of milliseconds to wait + * for the loading to complete + * @return true if all images were successfully + * loaded; false otherwise + * @see java.awt.MediaTracker#waitForID(int) + * @see java.awt.MediaTracker#waitForAll(long) + * @see java.awt.MediaTracker#isErrorAny + * @see java.awt.MediaTracker#isErrorID + * @exception InterruptedException if any thread has + * interrupted this thread. + */ + public synchronized boolean waitForAll(long ms) + throws InterruptedException + { + long end = System.currentTimeMillis() + ms; + boolean first = true; + while (true) { + int status = statusAll(first, first); + if ((status & LOADING) == 0) { + return (status == COMPLETE); + } + first = false; + long timeout; + if (ms == 0) { + timeout = 0; + } else { + timeout = end - System.currentTimeMillis(); + if (timeout <= 0) { + return false; + } + } + wait(timeout); + } + } + + /** + * Calculates and returns the bitwise inclusive OR of the + * status of all media that are tracked by this media tracker. + *

+ * Possible flags defined by the + * MediaTracker class are LOADING, + * ABORTED, ERRORED, and + * COMPLETE. An image that hasn't started + * loading has zero as its status. + *

+ * If the value of load is true, then + * this method starts loading any images that are not yet being loaded. + * + * @param load if true, start loading + * any images that are not yet being loaded + * @return the bitwise inclusive OR of the status of + * all of the media being tracked + * @see java.awt.MediaTracker#statusID(int, boolean) + * @see java.awt.MediaTracker#LOADING + * @see java.awt.MediaTracker#ABORTED + * @see java.awt.MediaTracker#ERRORED + * @see java.awt.MediaTracker#COMPLETE + */ + public int statusAll(boolean load) { + return statusAll(load, true); + } + + private synchronized int statusAll(boolean load, boolean verify) { + MediaEntry cur = head; + int status = 0; + while (cur != null) { + status = status | cur.getStatus(load, verify); + cur = cur.next; + } + return status; + } + + /** + * Checks to see if all images tracked by this media tracker that + * are tagged with the specified identifier have finished loading. + *

+ * This method does not start loading the images if they are not + * already loading. + *

+ * If there is an error while loading or scaling an image, then that + * image is considered to have finished loading. Use the + * isErrorAny or isErrorID methods to + * check for errors. + * @param id the identifier of the images to check + * @return true if all images have finished loading, + * have been aborted, or have encountered + * an error; false otherwise + * @see java.awt.MediaTracker#checkID(int, boolean) + * @see java.awt.MediaTracker#checkAll() + * @see java.awt.MediaTracker#isErrorAny() + * @see java.awt.MediaTracker#isErrorID(int) + */ + public boolean checkID(int id) { + return checkID(id, false, true); + } + + /** + * Checks to see if all images tracked by this media tracker that + * are tagged with the specified identifier have finished loading. + *

+ * If the value of the load flag is true, + * then this method starts loading any images that are not yet + * being loaded. + *

+ * If there is an error while loading or scaling an image, then that + * image is considered to have finished loading. Use the + * isErrorAny or isErrorID methods to + * check for errors. + * @param id the identifier of the images to check + * @param load if true, start loading any + * images that are not yet being loaded + * @return true if all images have finished loading, + * have been aborted, or have encountered + * an error; false otherwise + * @see java.awt.MediaTracker#checkID(int, boolean) + * @see java.awt.MediaTracker#checkAll() + * @see java.awt.MediaTracker#isErrorAny() + * @see java.awt.MediaTracker#isErrorID(int) + */ + public boolean checkID(int id, boolean load) { + return checkID(id, load, true); + } + + private synchronized boolean checkID(int id, boolean load, boolean verify) + { + MediaEntry cur = head; + boolean done = true; + while (cur != null) { + if (cur.getID() == id + && (cur.getStatus(load, verify) & DONE) == 0) + { + done = false; + } + cur = cur.next; + } + return done; + } + + /** + * Checks the error status of all of the images tracked by this + * media tracker with the specified identifier. + * @param id the identifier of the images to check + * @return true if any of the images with the + * specified identifier had an error during + * loading; false otherwise + * @see java.awt.MediaTracker#isErrorAny + * @see java.awt.MediaTracker#getErrorsID + */ + public synchronized boolean isErrorID(int id) { + MediaEntry cur = head; + while (cur != null) { + if (cur.getID() == id + && (cur.getStatus(false, true) & ERRORED) != 0) + { + return true; + } + cur = cur.next; + } + return false; + } + + /** + * Returns a list of media with the specified ID that + * have encountered an error. + * @param id the identifier of the images to check + * @return an array of media objects tracked by this media + * tracker with the specified identifier + * that have encountered an error, or + * null if there are none with errors + * @see java.awt.MediaTracker#isErrorID + * @see java.awt.MediaTracker#isErrorAny + * @see java.awt.MediaTracker#getErrorsAny + */ + public synchronized Object[] getErrorsID(int id) { + MediaEntry cur = head; + int numerrors = 0; + while (cur != null) { + if (cur.getID() == id + && (cur.getStatus(false, true) & ERRORED) != 0) + { + numerrors++; + } + cur = cur.next; + } + if (numerrors == 0) { + return null; + } + Object errors[] = new Object[numerrors]; + cur = head; + numerrors = 0; + while (cur != null) { + if (cur.getID() == id + && (cur.getStatus(false, false) & ERRORED) != 0) + { + errors[numerrors++] = cur.getMedia(); + } + cur = cur.next; + } + return errors; + } + + /** + * Starts loading all images tracked by this media tracker with the + * specified identifier. This method waits until all the images with + * the specified identifier have finished loading. + *

+ * If there is an error while loading or scaling an image, then that + * image is considered to have finished loading. Use the + * isErrorAny and isErrorID methods to + * check for errors. + * @param id the identifier of the images to check + * @see java.awt.MediaTracker#waitForAll + * @see java.awt.MediaTracker#isErrorAny() + * @see java.awt.MediaTracker#isErrorID(int) + * @exception InterruptedException if any thread has + * interrupted this thread. + */ + public void waitForID(int id) throws InterruptedException { + waitForID(id, 0); + } + + /** + * Starts loading all images tracked by this media tracker with the + * specified identifier. This method waits until all the images with + * the specified identifier have finished loading, or until the + * length of time specified in milliseconds by the ms + * argument has passed. + *

+ * If there is an error while loading or scaling an image, then that + * image is considered to have finished loading. Use the + * statusID, isErrorID, and + * isErrorAny methods to check for errors. + * @param id the identifier of the images to check + * @param ms the length of time, in milliseconds, to wait + * for the loading to complete + * @see java.awt.MediaTracker#waitForAll + * @see java.awt.MediaTracker#waitForID(int) + * @see java.awt.MediaTracker#statusID + * @see java.awt.MediaTracker#isErrorAny() + * @see java.awt.MediaTracker#isErrorID(int) + * @exception InterruptedException if any thread has + * interrupted this thread. + */ + public synchronized boolean waitForID(int id, long ms) + throws InterruptedException + { + long end = System.currentTimeMillis() + ms; + boolean first = true; + while (true) { + int status = statusID(id, first, first); + if ((status & LOADING) == 0) { + return (status == COMPLETE); + } + first = false; + long timeout; + if (ms == 0) { + timeout = 0; + } else { + timeout = end - System.currentTimeMillis(); + if (timeout <= 0) { + return false; + } + } + wait(timeout); + } + } + + /** + * Calculates and returns the bitwise inclusive OR of the + * status of all media with the specified identifier that are + * tracked by this media tracker. + *

+ * Possible flags defined by the + * MediaTracker class are LOADING, + * ABORTED, ERRORED, and + * COMPLETE. An image that hasn't started + * loading has zero as its status. + *

+ * If the value of load is true, then + * this method starts loading any images that are not yet being loaded. + * @param id the identifier of the images to check + * @param load if true, start loading + * any images that are not yet being loaded + * @return the bitwise inclusive OR of the status of + * all of the media with the specified + * identifier that are being tracked + * @see java.awt.MediaTracker#statusAll(boolean) + * @see java.awt.MediaTracker#LOADING + * @see java.awt.MediaTracker#ABORTED + * @see java.awt.MediaTracker#ERRORED + * @see java.awt.MediaTracker#COMPLETE + */ + public int statusID(int id, boolean load) { + return statusID(id, load, true); + } + + private synchronized int statusID(int id, boolean load, boolean verify) { + MediaEntry cur = head; + int status = 0; + while (cur != null) { + if (cur.getID() == id) { + status = status | cur.getStatus(load, verify); + } + cur = cur.next; + } + return status; + } + + /** + * Removes the specified image from this media tracker. + * All instances of the specified image are removed, + * regardless of scale or ID. + * @param image the image to be removed + * @see java.awt.MediaTracker#removeImage(java.awt.Image, int) + * @see java.awt.MediaTracker#removeImage(java.awt.Image, int, int, int) + * @since JDK1.1 + */ + public synchronized void removeImage(Image image) { + MediaEntry cur = head; + MediaEntry prev = null; + while (cur != null) { + MediaEntry next = cur.next; + if (cur.getMedia() == image) { + if (prev == null) { + head = next; + } else { + prev.next = next; + } + cur.cancel(); + } else { + prev = cur; + } + cur = next; + } + notifyAll(); // Notify in case remaining images are "done". + } + + /** + * Removes the specified image from the specified tracking + * ID of this media tracker. + * All instances of Image being tracked + * under the specified ID are removed regardless of scale. + * @param image the image to be removed + * @param id the tracking ID frrom which to remove the image + * @see java.awt.MediaTracker#removeImage(java.awt.Image) + * @see java.awt.MediaTracker#removeImage(java.awt.Image, int, int, int) + * @since JDK1.1 + */ + public synchronized void removeImage(Image image, int id) { + MediaEntry cur = head; + MediaEntry prev = null; + while (cur != null) { + MediaEntry next = cur.next; + if (cur.getID() == id && cur.getMedia() == image) { + if (prev == null) { + head = next; + } else { + prev.next = next; + } + cur.cancel(); + } else { + prev = cur; + } + cur = next; + } + notifyAll(); // Notify in case remaining images are "done". + } + + /** + * Removes the specified image with the specified + * width, height, and ID from this media tracker. + * Only the specified instance (with any duplicates) is removed. + * @param image the image to be removed + * @param id the tracking ID from which to remove the image + * @param width the width to remove (-1 for unscaled) + * @param height the height to remove (-1 for unscaled) + * @see java.awt.MediaTracker#removeImage(java.awt.Image) + * @see java.awt.MediaTracker#removeImage(java.awt.Image, int) + * @since JDK1.1 + */ + public synchronized void removeImage(Image image, int id, + int width, int height) { + MediaEntry cur = head; + MediaEntry prev = null; + while (cur != null) { + MediaEntry next = cur.next; + if (cur.getID() == id && cur instanceof ImageMediaEntry + && ((ImageMediaEntry) cur).matches(image, width, height)) + { + if (prev == null) { + head = next; + } else { + prev.next = next; + } + cur.cancel(); + } else { + prev = cur; + } + cur = next; + } + notifyAll(); // Notify in case remaining images are "done". + } + + synchronized void setDone() { + notifyAll(); + } +} + +abstract class MediaEntry { + MediaTracker tracker; + int ID; + MediaEntry next; + + int status; + boolean cancelled; + + MediaEntry(MediaTracker mt, int id) { + tracker = mt; + ID = id; + } + + abstract Object getMedia(); + + static MediaEntry insert(MediaEntry head, MediaEntry me) { + MediaEntry cur = head; + MediaEntry prev = null; + while (cur != null) { + if (cur.ID > me.ID) { + break; + } + prev = cur; + cur = cur.next; + } + me.next = cur; + if (prev == null) { + head = me; + } else { + prev.next = me; + } + return head; + } + + int getID() { + return ID; + } + + abstract void startLoad(); + + void cancel() { + cancelled = true; + } + + static final int LOADING = MediaTracker.LOADING; + static final int ABORTED = MediaTracker.ABORTED; + static final int ERRORED = MediaTracker.ERRORED; + static final int COMPLETE = MediaTracker.COMPLETE; + + static final int LOADSTARTED = (LOADING | ERRORED | COMPLETE); + static final int DONE = (ABORTED | ERRORED | COMPLETE); + + synchronized int getStatus(boolean doLoad, boolean doVerify) { + if (doLoad && ((status & LOADSTARTED) == 0)) { + status = (status & ~ABORTED) | LOADING; + startLoad(); + } + return status; + } + + void setStatus(int flag) { + synchronized (this) { + status = flag; + } + tracker.setDone(); + } +} + +class ImageMediaEntry extends MediaEntry implements ImageObserver, +java.io.Serializable { + Image image; + int width; + int height; + + /* + * JDK 1.1 serialVersionUID + */ + private static final long serialVersionUID = 4739377000350280650L; + + ImageMediaEntry(MediaTracker mt, Image img, int c, int w, int h) { + super(mt, c); + image = img; + width = w; + height = h; + } + + boolean matches(Image img, int w, int h) { + return (image == img && width == w && height == h); + } + + Object getMedia() { + return image; + } + + synchronized int getStatus(boolean doLoad, boolean doVerify) { + if (doVerify) { + int flags = tracker.target.checkImage(image, width, height, null); + int s = parseflags(flags); + if (s == 0) { + if ((status & (ERRORED | COMPLETE)) != 0) { + setStatus(ABORTED); + } + } else if (s != status) { + setStatus(s); + } + } + return super.getStatus(doLoad, doVerify); + } + + void startLoad() { + if (tracker.target.prepareImage(image, width, height, this)) { + setStatus(COMPLETE); + } + } + + int parseflags(int infoflags) { + if ((infoflags & ERROR) != 0) { + return ERRORED; + } else if ((infoflags & ABORT) != 0) { + return ABORTED; + } else if ((infoflags & (ALLBITS | FRAMEBITS)) != 0) { + return COMPLETE; + } + return 0; + } + + public boolean imageUpdate(Image img, int infoflags, + int x, int y, int w, int h) { + if (cancelled) { + return false; + } + int s = parseflags(infoflags); + if (s != 0 && s != status) { + setStatus(s); + } + return ((status & LOADING) != 0); + } +}