The getClip()/getClipBounds bug fix (http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=8004859) changed sun.java2d.SunGraphics2D.transformShape(AffineTransform tx, Shape clip) to use a Rectangle2D.Double instead of Float and this change causes the rounding (done by casting from double to float) to be lost. The lack of rounding causes a bug on my program when using the jre 1.7.0.40, which is not present on 1.7.0.25. Take a look at the test case ClippingTest.java (attached), it draws clippingOn40.png (attached) when running the JRE 1.7.0.40, and clippingOn25.png (attached) when running JRE 1.7.0.25. Notice that on 1.7.0.25 the drawing does not show the center darker line... the clipping regions do not overlap.
A fix to this new bug is to change:
----
return new Rectangle2D.Double(matrix[0], matrix[1],
matrix[2] - matrix[0],
matrix[3] - matrix[1]);
----
on line 1947 of sun.java2d.SunGraphics2D to:
----
new Rectangle2D.Float((float)matrix[0], (float)matrix[1],
(float)(matrix[2] - matrix[0]),
(float)(matrix[3] - matrix[1])
);
----
My application calculates the clipping regions on screen using doubles
and a procedure slightly different (but equivalent if we take away the
insignificant digits of the calculation) compared to the one used by
SunGraphics2D, so when SunGraphics2D transform them (calculates the
usrClip) there are small differences (due to insignificant digits) that
in some cases end up being magnified to a full pixel [as the clipRegion
is calculated using floor() and ceil() inside the getBounds() called by
SunGraphics2D.validateCompClip()] by the current implementation
(1.7.0.40) and were nicely cut off by the previous (1.7.0.25) when it
rounded the result using Rectangle2D.Float.
Please let me know if I can be of more help,
Nicolas
import java.awt.Color;
import java.awt.Dimension;
import java.awt.geom.Rectangle2D;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
class ClippingTest
extends JComponent {
public static void main(String[] args) {
JFrame frame=new JFrame("Clipping Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new ClippingTest());
frame.pack();
frame.setVisible(true);
}
{
setPreferredSize(new Dimension(120, 120));
}
@Override
public void paintComponent(Graphics graphics) {
Graphics2D g=(Graphics2D)graphics.create();
double delta=1e-12; // delta is small enough so that its effect is lost when casting to float but big enough to be in the double's mantissa.
// translate and scale so that SunGraphics2D.transformShape() enters the relevant code block
g.translate(delta, delta);
g.scale(1+delta, 1+delta);
Rectangle2D r=new Rectangle2D.Double(10, 10, 100, 100);
g.setColor(Color.white);
g.fill(r);
Rectangle2D clip1=new Rectangle2D.Double(10, 10, 50, 100);
g.setColor(new Color(128, 128, 128, 128));
g.setClip(clip1);
g.fill(r);
Rectangle2D clip2=new Rectangle2D.Double(60, 10, 50, 100);
g.setClip(clip2);
g.fill(r);
g.dispose();
}
}<<attachment: clippingOn25.png>>
<<attachment: clippingOn40.png>>
