- /*
 - * @(#)MediaTracker.java 1.34 00/07/14
 - *
 - * Copyright 1995-2000 Sun Microsystems, Inc. All Rights Reserved.
 - *
 - * This software is the proprietary information of Sun Microsystems, Inc.
 - * Use is subject to license terms.
 - *
 - */
 - package java.awt;
 - import java.awt.Component;
 - import java.awt.Image;
 - import java.awt.Graphics;
 - import java.awt.image.ImageObserver;
 - /**
 - * The <code>MediaTracker</code> 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.
 - * <p>
 - * To use a media tracker, create an instance of
 - * <code>MediaTracker</code> and call its <code>addImage</code>
 - * 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.
 - * <p>
 - * Here is an example:
 - * <p>
 - * <hr><blockquote><pre>
 - * 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);
 - * }
 - * }
 - * }
 - * </pre></blockquote><hr>
 - * <p>
 - * @version 1.34, 07/14/00
 - * @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 target;
 - /**
 - * The head of the list of Images that is being
 - * tracked by the MediaTracker.
 - *
 - * @serial
 - * @see addImage()
 - * @see removeImage()
 - */
 - 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 some 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 some 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 some 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.
 - * <p>
 - * This method does not start loading the images if they are not
 - * already loading.
 - * <p>
 - * If there is an error while loading or scaling an image, then that
 - * image is considered to have finished loading. Use the
 - * <code>isErrorAny</code> or <code>isErrorID</code> methods to
 - * check for errors.
 - * @return <code>true</code> if all images have finished loading,
 - * have been aborted, or have encountered
 - * an error; <code>false</code> 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.
 - * <p>
 - * If the value of the <code>load</code> flag is <code>true</code>,
 - * then this method starts loading any images that are not yet
 - * being loaded.
 - * <p>
 - * If there is an error while loading or scaling an image, that
 - * image is considered to have finished loading. Use the
 - * <code>isErrorAny</code> and <code>isErrorID</code> methods to
 - * check for errors.
 - * @param load if <code>true</code>, start loading any
 - * images that are not yet being loaded.
 - * @return <code>true</code> if all images have finished loading,
 - * have been aborted, or have encountered
 - * an error; <code>false</code> 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 <code>true</code> if any of the images tracked
 - * by this media tracker had an error during
 - * loading; <code>false</code> 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 <code>null</code> 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.
 - * <p>
 - * If there is an error while loading or scaling an image, then that
 - * image is considered to have finished loading. Use the
 - * <code>isErrorAny</code> or <code>isErrorID</code> 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 another 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 <code>ms</code> argument has passed.
 - * <p>
 - * If there is an error while loading or scaling an image, then
 - * that image is considered to have finished loading. Use the
 - * <code>isErrorAny</code> or <code>isErrorID</code> methods to
 - * check for errors.
 - * @param ms the number of milliseconds to wait
 - * for the loading to complete.
 - * @return <code>true</code> if all images were successfully
 - * loaded; <code>false</code> 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 another 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 <b>OR</b> of the
 - * status of all media that are tracked by this media tracker.
 - * <p>
 - * Possible flags defined by the
 - * <code>MediaTracker</code> class are <code>LOADING</code>,
 - * <code>ABORTED</code>, <code>ERRORED</code>, and
 - * <code>COMPLETE</code>. An image that hasn't started
 - * loading has zero as its status.
 - * <p>
 - * If the value of <code>load</code> is <code>true</code>, then
 - * this method starts loading any images that are not yet being loaded.
 - * @param load if <code>true</code>, start loading
 - * any images that are not yet being loaded.
 - * @return the bitwise inclusive <b>OR</b> 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.
 - * <p>
 - * This method does not start loading the images if they are not
 - * already loading.
 - * <p>
 - * If there is an error while loading or scaling an image, then that
 - * image is considered to have finished loading. Use the
 - * <code>isErrorAny</code> or <code>isErrorID</code> methods to
 - * check for errors.
 - * @param id the identifier of the images to check.
 - * @return <code>true</code> if all images have finished loading,
 - * have been aborted, or have encountered
 - * an error; <code>false</code> 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.
 - * <p>
 - * If the value of the <code>load</code> flag is <code>true</code>,
 - * then this method starts loading any images that are not yet
 - * being loaded.
 - * <p>
 - * If there is an error while loading or scaling an image, then that
 - * image is considered to have finished loading. Use the
 - * <code>isErrorAny</code> or <code>isErrorID</code> methods to
 - * check for errors.
 - * @param id the identifier of the images to check.
 - * @param load if <code>true</code>, start loading any
 - * images that are not yet being loaded.
 - * @return <code>true</code> if all images have finished loading,
 - * have been aborted, or have encountered
 - * an error; <code>false</code> 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 <code>true</code> if any of the images with the
 - * specified identifier had an error during
 - * loading; <code>false</code> 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
 - * <code>null</code> 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.
 - * <p>
 - * If there is an error while loading or scaling an image, then that
 - * image is considered to have finished loading. Use the
 - * <code>isErrorAny</code> and <code>isErrorID</code> 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 another 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 <code>ms</code>
 - * argument has passed.
 - * <p>
 - * If there is an error while loading or scaling an image, then that
 - * image is considered to have finished loading. Use the
 - * <code>statusID</code>, <code>isErrorID</code>, and
 - * <code>isErrorAny</code> 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 another 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 <b>OR</b> of the
 - * status of all media with the specified identifier that are
 - * tracked by this media tracker.
 - * <p>
 - * Possible flags defined by the
 - * <code>MediaTracker</code> class are <code>LOADING</code>,
 - * <code>ABORTED</code>, <code>ERRORED</code>, and
 - * <code>COMPLETE</code>. An image that hasn't started
 - * loading has zero as its status.
 - * <p>
 - * If the value of <code>load</code> is <code>true</code>, 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 <code>true</code>, start loading
 - * any images that are not yet being loaded.
 - * @return the bitwise inclusive <b>OR</b> 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;
 - }
 - /**
 - * Remove 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".
 - }
 - /**
 - * Remove the specified image from the specified tracking
 - * ID of this media tracker.
 - * All instances of <code>Image</code> 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".
 - }
 - /**
 - * Remove 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;
 - /*
 - * JDK 1.1 serialVersionUID
 - */
 - private static final long serialVersionUID = -2924957284304726459L;
 - 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;
 - 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;
 - }
 - 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);
 - }
 - }