在Java 8中似乎在子像素坐标上的划痕已经破裂了。
我有三组案例,显示在屏幕截图上(列表示案例,行表示不同笔画宽度):
Java 7u51(400%规模)
Java 8u60(400%规模)
>在同一坐标上填充和笔画。按照预期工作,抚摸区域大于填充区域。
>行程收缩(按行程宽度)并居中(宽度的一半)位于填充区域的边界内。这部分在Java 8中为1像素笔画,其中绘画发生在子像素坐标(第一行)上; 3px笔画没有这个问题(第三行)。对于1px的笔画似乎是向上舍入的。
>填充矩形以相同的方式缩小为中心2.我需要这个图形,它支持子像素绘图,以便在细胞重叠时使不重叠的填充。在这里可以看到,填充操作向下舍入0.5到0,所以只是抚摸问题。
代码如下:
import static java.awt.BasicStroke.*;
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
public class TestCase
{
public static void main(String[] args)
{
JFrame frame = new JFrame("Test case");
frame.setSize(115, 115);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().add(new TestPanel());
frame.setVisible(true);
}
private static class TestPanel extends JPanel
{
TestPanel()
{
setOpaque(true);
}
@Override
protected void paintComponent(Graphics g)
{
Graphics2D g2 = (Graphics2D) g;
g2.setColor(Color.white);
g2.fill(getBounds());
Rectangle2D rect = new Rectangle2D.Double();
Color background = new Color(0, 255, 255);
Color border = new Color(255, 0, 0, 128);
Stroke STROKE_1PX = new BasicStroke(1, CAP_SQUARE, JOIN_MITER);
Stroke STROKE_2PX = new BasicStroke(2, CAP_SQUARE, JOIN_MITER);
Stroke STROKE_3PX = new BasicStroke(3, CAP_SQUARE, JOIN_MITER);
g2.translate(10, 10);
/**
* Filling and stroking by original coordinates
*/
rect.setRect(0, 0, 25, 25);
g2.setColor(background);
g2.fill(rect);
g2.setColor(border);
g2.setStroke(STROKE_1PX);
g2.draw(rect);
g2.translate(0, 35);
g2.setColor(background);
g2.fill(rect);
g2.setColor(border);
g2.setStroke(STROKE_2PX);
g2.draw(rect);
g2.translate(0, 35);
g2.setColor(background);
g2.fill(rect);
g2.setColor(border);
g2.setStroke(STROKE_3PX);
g2.draw(rect);
/**
* Stroking is shrunk to be inside the filling rect
*/
g2.translate(35, -70);
rect.setRect(0, 0, 25, 25);
g2.setColor(background);
g2.fill(rect);
rect.setRect(0.5, 0.5, 24, 24);
g2.setColor(border);
g2.setStroke(STROKE_1PX);
g2.draw(rect);
g2.translate(0, 35);
rect.setRect(0, 0, 25, 25);
g2.setColor(background);
g2.fill(rect);
rect.setRect(1, 1, 23, 23);
g2.setColor(border);
g2.setStroke(STROKE_2PX);
g2.draw(rect);
g2.translate(0, 35);
rect.setRect(0, 0, 25, 25);
g2.setColor(background);
g2.fill(rect);
rect.setRect(1.5, 1.5, 22, 22);
g2.setColor(border);
g2.setStroke(STROKE_3PX);
g2.draw(rect);
/**
* Filling rect is additionally shrunk and centered
*/
g2.translate(35, -70);
rect.setRect(0.5, 0.5, 24, 24);
g2.setColor(background);
g2.fill(rect);
g2.setColor(border);
g2.setStroke(STROKE_1PX);
g2.draw(rect);
g2.translate(0, 35);
rect.setRect(1, 1, 23, 23);
g2.setColor(background);
g2.fill(rect);
g2.setColor(border);
g2.setStroke(STROKE_2PX);
g2.draw(rect);
g2.translate(0, 35);
rect.setRect(1.5, 1.5, 22, 22);
g2.setColor(background);
g2.fill(rect);
g2.setColor(border);
g2.setStroke(STROKE_3PX);
g2.draw(rect);
}
}
}
当我测试,Java 7没有这个问题(尝试在7u51),Windows(8u77)和Mac(8u60)。在Ubuntu(8u60和8u77)和Linux Mint(8u60)在不同的机器上尝试过,并且这里的bug。
有没有人面临这样的问题?有没有一般的解决方法?
我不能简单地处理1px的情况在使用抚摸的地方。这是因为有很多地方,我正在使用不同的Graphics2D实现,似乎从我使用的问题只是在SunGraphics2D上再现。这意味着我需要在这些地方使用instanceOf来打破常见的逻辑。