Name: atR10191 Date: 03/22/2002
Precision in methods using floating point calculations is unspecified.
It makes impossible to create tests for them.
Let's consider drawing functions of class Graphics2D.
Such as drawImage, drawString, draw, and fill.
They are using Composite. It specifies how new pixels are to be combined with
the existing pixels on the graphics device during the rendering
process.
See for example excerpt from the specification for field
public static final int SRC_OVER of class AlphaComposite:
" public static final int SRC_OVER
Porter-Duff Source Over Destination rule. The source is composited over the destination.
Fs = 1 and Fd = (1-As), thus:
Cd = Cs + Cd*(1-As)
Ad = As + Ad*(1-As)
"
Usually it's possible to achive the same result using diferent
approaches. When floating point calculations are involved, the 'same'
result could be not the same in fact.
For the above equations we can write this:
float alpha = composite.getAlpha();
float[] rgbaSrc = cs.getRGBComponents(null);
float[] rgbaDst = cd.getRGBComponents(null);
float alphasource = rgbaSrc[3] * alpha;
float alphadest = rgbaDst[3];
float r = rgbaSrc[0]*alphasource + rgbaDst[0]*alphadest*(1-alphasource);
float g = rgbaSrc[1]*alphasource + rgbaDst[1]*alphadest*(1-alphasource);
float b = rgbaSrc[2]*alphasource + rgbaDst[2]*alphadest*(1-alphasource);
float a = alphasource + alphadest*(1-alphasource);
Color resultColor = new Color(r, g, b, a);
or this:
float alpha = composite.getAlpha();
float alphasource = (cs.getAlpha()/255.0f) * alpha;
float alphadest = (cd.getAlpha()/255.0f);
int r = (int) ( cs.getRed()*alphasource + cd.getRed()*alphadest*(1-alphasource));
int g = (int) ( cs.getGreen()*alphasource + cd.getGreen()*alphadest*(1-alphasource));
int b = (int) ( cs.getBlue()*alphasource + cd.getBlue()*alphadest*(1-alphasource));
float a = alphasource + (cd.getAlpha()/255.0f)*(1-alphasource);
int alpha1= (int)(a*255);
Color resultColor = new Color(r, g, b, alpha1);
They will produce different results.
So for such methods should be specified exact algoritm for calculations,
or acceptable fault.
If specification had defined permissible fault in floating point
calculations, e.g. 1 percent (or 0.5 percent) it would be possible to
test assertions such as above.
Here by "fault" I meant acceptable deviation from precise mathematics
value.
Here is sample program demonstrating the problem:
============ Test115x.java ==============================================
import java.awt.*;
import java.awt.image.*;
public class Test115x {
public static void main(String[] args) {
new Test115x().testRun();
}
void testRun() {
GraphicsEnvironment lge = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsConfiguration gc = lge.getDefaultScreenDevice().getDefaultConfiguration();
BufferedImage bi = gc.createCompatibleImage(200, 200);
final Graphics2D g2 = bi.createGraphics();
Color colors[] = {
new Color(Integer.MIN_VALUE + 1, true),
new Color(Integer.MAX_VALUE - 1, true),
new Color(Integer.MAX_VALUE, true),
new Color(0.9f, 0.9f, 0.0f),
new Color(0.5f, 0.1f, 0.6f, 0.5f)};
g2.setComposite(AlphaComposite.SrcOver);
for (int i = 0 ; i < colors.length; i++) {
g2.setColor(colors[i]);
g2.fill3DRect(1, 0, 100, 50, true);
Color c_after = new Color(bi.getRGB(50, 25), true);
System.out.println("Returned color: "+c_after);
}
System.exit(0);
}
}
======== end of Test115x.java ==========================================
======== output under personal basis profile b30 ====================
Returned color: java.awt.Color[r=0,g=0,b=0]
Returned color: java.awt.Color[r=127,g=127,b=126]
Returned color: java.awt.Color[r=190,g=190,b=190]
Returned color: java.awt.Color[r=229,g=229,b=0]
Returned color: java.awt.Color[r=178,g=127,b=76]
======== end of output under personal basis profile b30 =============
======== output under jdk 1.4 ====================
Returned color: java.awt.Color[r=0,g=0,b=1]
Returned color: java.awt.Color[r=127,g=127,b=128]
Returned color: java.awt.Color[r=191,g=191,b=191]
Returned color: java.awt.Color[r=230,g=230,b=0]
Returned color: java.awt.Color[r=179,g=128,b=77]
======== end of output under jdk 1.4 =============
Now we do not have a criterion do decide if output under pbp is valid.
======================================================================