// This can come on any thread. If we are in the process of reloading
  // the image and determining our state (loading == true) we don't fire
  // preference changed, or repaint, we just reset the fWidth/fHeight as
  // necessary and return. This is ok as we know when loading finishes
  // it will pick up the new height/width, if necessary.
  public boolean imageUpdate(Image img, int flags, int x, int y, int width, int height) {
    if (fImage == null || fImage != img) return false;

    // Bail out if there was an error:
    if ((flags & (ABORT | ERROR)) != 0) {
      fImage = null;
      repaint(0);
      return false;
    }

    // Resize image if necessary:
    short changed = 0;
    if ((flags & ImageObserver.HEIGHT) != 0)
      if (!getElement().getAttributes().isDefined(HTML.Attribute.HEIGHT)) {
        changed |= 1;
      }
    if ((flags & ImageObserver.WIDTH) != 0)
      if (!getElement().getAttributes().isDefined(HTML.Attribute.WIDTH)) {
        changed |= 2;
      }
    synchronized (this) {
      if ((changed & 1) == 1) {
        fWidth = width;
      }
      if ((changed & 2) == 2) {
        fHeight = height;
      }
      if (loading) {
        // No need to resize or repaint, still in the process of
        // loading.
        return true;
      }
    }
    if (changed != 0) {
      // May need to resize myself, asynchronously:
      if (DEBUG) System.out.println("ImageView: resized to " + fWidth + "x" + fHeight);

      Document doc = getDocument();
      try {
        if (doc instanceof AbstractDocument) {
          ((AbstractDocument) doc).readLock();
        }
        preferenceChanged(this, true, true);
      } finally {
        if (doc instanceof AbstractDocument) {
          ((AbstractDocument) doc).readUnlock();
        }
      }

      return true;
    }

    // Repaint when done or when new pixels arrive:
    if ((flags & (FRAMEBITS | ALLBITS)) != 0) repaint(0);
    else if ((flags & SOMEBITS) != 0) if (sIsInc) repaint(sIncRate);

    return ((flags & ALLBITS) == 0);
  }