-
Bug
-
Resolution: Unresolved
-
P4
-
None
-
1.2.0
-
generic
-
generic
Name: wl91122 Date: 08/04/99
java.awt.Component.imageUpdate does not use the coordinates of the updated image.
Instead, it uses the coordinates of the Component when a repaint is needed.
This causes the whole Component to be redrawn.
If several images are present within 1 component (e.g. a Canvas) the effects multiply.
In 1.2.2 the imageUpdate() method of java/awt/Component still calls for a redraw
of the *whole* canvas that the image is on. This can easily be seen on line 2062 of
java/awt/Component.java in JDK 1.2.2.
The JDK API documentation has an incomplete description of imageUpdate.
It states that 'The interpretation of the x, y, width, and height
arguments depends on the value of the infoflags argument.' but it fails to
give the exact meaning. The documentation issues are solved in 1.2.2.
java/awt/image/ImageObserver.java now gives a good explanation
of the parameters of the imageUpdate() method.
(I hope this is new documentation, otherwise I missed it the first time)
The JDK API documentation has a slightly wrong description for imageUpdate.
In the text the variables 'width', 'height' and 'infoflags' are mentionned.
Yet only 'w', 'h' and 'flags' exist.
In 1.2.2 according to the documentation of SOMEBITS in
java/awt/image/ImageObserver.java:
"The bounding box of the new pixels can be taken from the x, y, width, and
height arguments to the imageUpdate callback method"
The x and y coordinates returned are given relative to the image topleft
corner. This makes it impossible for any developer to overload imageUpdate()
and do a better job, since that would need the coordinates relative to the
CANVAS (or whatever type of ImageObserver used). [Please note that the
implementation of line 2026 in java/awt/Component.java could simply have
been "repaint(rate, x, y, w, h);".
In 1.2.2, the reception of the flag ALLBITS in imageUpdate() in
java/awt/image/ImageObserver.java leads to the same repaint
code (of the whole canvas). This is OK for the non-incremental case, since the
image will then be drawn for the first time. For the incremental case the image
has already been drawn piece by piece, so a repaint is not needed here and
leads to unneccesary flashing. (The 'rate' parameter usually prevents this by
the way) The documentation for ALLBITS says that:
"The x, y, width, and height arguments to the imageUpdate callback method
should be ignored." This makes it impossible for the existing (or overloaded)
code to do a better job.
The output of this program shows a trace of the paint, repaint and
imageUpdate functions with their parameters.
An annotated trace listing is in the file o.txt.
// Example program for review ID 53864
// 'Close' the window to start the show
import java.awt.*;
import java.awt.event.*;
class CanvasDebug extends Canvas
{
Image img = null;
void makeimage()
{
// Any 503x376 pixel image will do
img = getToolkit().getImage("x.gif");
repaint(40, 40, 503, 376);
}
public void paint(Graphics g)
{
// Tell the world what area we are asked to repaint
System.out.println("paint(clip="+g.getClipBounds()+")");
if(img != null) g.drawImage(img, 40, 40, this);
}
// imageUpdate is overloaded, but only to add tracing options
public boolean imageUpdate(Image img, int flags,
int x, int y, int w, int h) {
// Tell the world what information we have to work with
// Note that x and y are relative to the image
// There is no information about the position of the image itself
System.out.println("imageUpdate(f="+flags+","+x+","+y+","+w+","+h+")");
// The following code is a copy of the original code in java.awt.Component
// except that isInc(=true) and incRate(=100) are fixed
int rate = -1;
if ((flags & (FRAMEBITS|ALLBITS)) != 0) {
rate = 0;
} else if ((flags & SOMEBITS) != 0) {
if (true) {
try {
rate = 100;
if (rate < 0)
rate = 0;
} catch (Exception e) {
rate = 100;
}
}
}
if (rate >= 0) {
// Tell the world what area we are invalidating
// The original code uses 'width' and 'height' (not to be confused with 'w' and 'h'!)
// These are the instance variables containing the witdh and height of the Component
System.out.println("repaint("+rate+","+0+","+0+","+getWidth()+","+getHeight()+")");
repaint(rate, 0, 0, getWidth(), getHeight());
}
return (flags & (ALLBITS|ABORT)) == 0;
}
}
class p53864
{
public static void main(String args[])
{
// Create a basic window containing a Canvas
// The canvas is subclassed to add some debugging
Frame f = new Frame("p53864");
final CanvasDebug x = new CanvasDebug();
// 'Close' the window to load the image
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) { x.makeimage(); }});
f.add(x);
f.setSize(503 + 2 * 40, 376 + 2 * 40);
f.show();
}
}
// End
(Review ID: 53864)
======================================================================
java.awt.Component.imageUpdate does not use the coordinates of the updated image.
Instead, it uses the coordinates of the Component when a repaint is needed.
This causes the whole Component to be redrawn.
If several images are present within 1 component (e.g. a Canvas) the effects multiply.
In 1.2.2 the imageUpdate() method of java/awt/Component still calls for a redraw
of the *whole* canvas that the image is on. This can easily be seen on line 2062 of
java/awt/Component.java in JDK 1.2.2.
The JDK API documentation has an incomplete description of imageUpdate.
It states that 'The interpretation of the x, y, width, and height
arguments depends on the value of the infoflags argument.' but it fails to
give the exact meaning. The documentation issues are solved in 1.2.2.
java/awt/image/ImageObserver.java now gives a good explanation
of the parameters of the imageUpdate() method.
(I hope this is new documentation, otherwise I missed it the first time)
The JDK API documentation has a slightly wrong description for imageUpdate.
In the text the variables 'width', 'height' and 'infoflags' are mentionned.
Yet only 'w', 'h' and 'flags' exist.
In 1.2.2 according to the documentation of SOMEBITS in
java/awt/image/ImageObserver.java:
"The bounding box of the new pixels can be taken from the x, y, width, and
height arguments to the imageUpdate callback method"
The x and y coordinates returned are given relative to the image topleft
corner. This makes it impossible for any developer to overload imageUpdate()
and do a better job, since that would need the coordinates relative to the
CANVAS (or whatever type of ImageObserver used). [Please note that the
implementation of line 2026 in java/awt/Component.java could simply have
been "repaint(rate, x, y, w, h);".
In 1.2.2, the reception of the flag ALLBITS in imageUpdate() in
java/awt/image/ImageObserver.java leads to the same repaint
code (of the whole canvas). This is OK for the non-incremental case, since the
image will then be drawn for the first time. For the incremental case the image
has already been drawn piece by piece, so a repaint is not needed here and
leads to unneccesary flashing. (The 'rate' parameter usually prevents this by
the way) The documentation for ALLBITS says that:
"The x, y, width, and height arguments to the imageUpdate callback method
should be ignored." This makes it impossible for the existing (or overloaded)
code to do a better job.
The output of this program shows a trace of the paint, repaint and
imageUpdate functions with their parameters.
An annotated trace listing is in the file o.txt.
// Example program for review ID 53864
// 'Close' the window to start the show
import java.awt.*;
import java.awt.event.*;
class CanvasDebug extends Canvas
{
Image img = null;
void makeimage()
{
// Any 503x376 pixel image will do
img = getToolkit().getImage("x.gif");
repaint(40, 40, 503, 376);
}
public void paint(Graphics g)
{
// Tell the world what area we are asked to repaint
System.out.println("paint(clip="+g.getClipBounds()+")");
if(img != null) g.drawImage(img, 40, 40, this);
}
// imageUpdate is overloaded, but only to add tracing options
public boolean imageUpdate(Image img, int flags,
int x, int y, int w, int h) {
// Tell the world what information we have to work with
// Note that x and y are relative to the image
// There is no information about the position of the image itself
System.out.println("imageUpdate(f="+flags+","+x+","+y+","+w+","+h+")");
// The following code is a copy of the original code in java.awt.Component
// except that isInc(=true) and incRate(=100) are fixed
int rate = -1;
if ((flags & (FRAMEBITS|ALLBITS)) != 0) {
rate = 0;
} else if ((flags & SOMEBITS) != 0) {
if (true) {
try {
rate = 100;
if (rate < 0)
rate = 0;
} catch (Exception e) {
rate = 100;
}
}
}
if (rate >= 0) {
// Tell the world what area we are invalidating
// The original code uses 'width' and 'height' (not to be confused with 'w' and 'h'!)
// These are the instance variables containing the witdh and height of the Component
System.out.println("repaint("+rate+","+0+","+0+","+getWidth()+","+getHeight()+")");
repaint(rate, 0, 0, getWidth(), getHeight());
}
return (flags & (ALLBITS|ABORT)) == 0;
}
}
class p53864
{
public static void main(String args[])
{
// Create a basic window containing a Canvas
// The canvas is subclassed to add some debugging
Frame f = new Frame("p53864");
final CanvasDebug x = new CanvasDebug();
// 'Close' the window to load the image
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) { x.makeimage(); }});
f.add(x);
f.setSize(503 + 2 * 40, 376 + 2 * 40);
f.show();
}
}
// End
(Review ID: 53864)
======================================================================