Java AWT自定义CompositeContext&;抗锯齿:在客户端区域之外绘制时出现RasterFormatException

Java AWT自定义CompositeContext&;抗锯齿:在客户端区域之外绘制时出现RasterFormatException,java,awt,composite,xor,antialiasing,Java,Awt,Composite,Xor,Antialiasing,我正在尝试为AWT实现类似SWT的xor模式绘图。使用内置不是一个选项,因为它没有实现SWT中的xor模式绘图 SWT xor模式图形通过二进制异或组合源颜色和目标颜色。AWT(可通过g2d.setXORMode(Color))使用恒定的异或颜色,该颜色通过二进制异或与源颜色组合,即目标颜色不影响结果颜色 因此,我考虑的唯一选择是编写自己的实现,将源和目标适当地结合起来 经过一些阅读,我提出了这个简单的实现:(是的,我知道getPixel(…)、setPixel(…)开销。我希望它在优化之前能够

我正在尝试为AWT实现类似SWT的xor模式绘图。使用内置不是一个选项,因为它没有实现SWT中的xor模式绘图

SWT xor模式图形通过二进制异或组合源颜色和目标颜色。AWT(可通过
g2d.setXORMode(Color)
)使用恒定的异或颜色,该颜色通过二进制异或与源颜色组合,即目标颜色不影响结果颜色

因此,我考虑的唯一选择是编写自己的实现,将源和目标适当地结合起来

经过一些阅读,我提出了这个简单的实现:(是的,我知道getPixel(…)、setPixel(…)开销。我希望它在优化之前能够正常工作。)

值得注意的是,我的Composite/CompositeContext不会引发异常,但AWT内部在尝试创建要传递给我的CompositeContext的光栅对象时会引发异常

不幸的是,PixelToParallelogramConverter仅在启用抗锯齿时用于自定义合成。例如,内置XORComposite使用本机方法进行绘制。我假设是AWT错误,但我不确定

非常感谢您的帮助:)

更新:

正如Durandal所建议的,我使用java-6-sun和java-1.6.0-openjdk测试了代码。我发现OpenJDK抛出异常,而Sun JDK没有。因此,我在OpenJDK bug跟踪器上报告了错误

问题解决后,我将更新此问题。请访问相应的OpenJDK bug以了解当前进度的信息

问候,, 马蒂亚斯

下面是一个示例程序,您可以在本地对其进行测试:

/*******************************************************************************
 * Copyright (c) 2013 itemis AG and others.
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Matthias Wienand (itemis AG) - initial API and implementation
 * 
 *******************************************************************************/
package org.eclipse.gef4.graphics.examples;

import java.awt.Color;

public class AwtXorTest extends JApplet {

    private static final long serialVersionUID = 1L;

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setTitle("AWT XorMode Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JApplet applet = new AwtXorTest();
        applet.init();
        frame.getContentPane().add(applet);
        frame.pack();
        frame.setVisible(true);
    }

    @Override
    public void init() {
        JPanel panel = new AwtXorTestPanel();
        getContentPane().add(panel);
    }

}

class AwtXorTestPanel extends JPanel {

    private static class XorComposite implements Composite {

        public static XorComposite INSTANCE = new XorComposite();

        private XorContext context = new XorContext();

        @Override
        public CompositeContext createContext(ColorModel srcColorModel,
                ColorModel dstColorModel, RenderingHints hints) {
            return context;
        }

    }

    private static class XorContext implements CompositeContext {

        public XorContext() {
        }

        @Override
        public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
            int w = Math.min(src.getWidth(), dstIn.getWidth());
            int h = Math.min(src.getHeight(), dstIn.getHeight());

            int[] srcRgba = new int[4];
            int[] dstRgba = new int[4];

            for (int x = 0; x < w; x++) {
                for (int y = 0; y < h; y++) {
                    src.getPixel(x, y, srcRgba);
                    dstIn.getPixel(x, y, dstRgba);
                    for (int i = 0; i < 3; i++) {
                        dstRgba[i] ^= srcRgba[i];
                    }
                    dstOut.setPixel(x, y, dstRgba);
                }
            }
        }

        @Override
        public void dispose() {
        }

    }

    private static final long serialVersionUID = 1L;

    public AwtXorTestPanel() {
        setPreferredSize(new Dimension(640, 480));
    }

    @Override
    public void paint(Graphics graphics) {
        Graphics2D g2d = (Graphics2D) graphics;

        // comment out to see it working:
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        g2d.setComposite(XorComposite.INSTANCE);
        g2d.setColor(new Color(0, 255, 255)); // resulting color should be red
        g2d.fill(new Rectangle(100, 100, 500, 500));
    }

}
/*******************************************************************************
*版权所有(c)2013 itemis AG和其他公司。
* 
*版权所有。本计划及随附材料
*根据Eclipse公共许可证v1.0的条款提供
*随本发行版发行,可在
* http://www.eclipse.org/legal/epl-v10.html
* 
*贡献者:
*Matthias Wienad(itemis AG)-初始API和实现
* 
*******************************************************************************/
包org.eclipse.gef4.graphics.examples;
导入java.awt.Color;
公共类AwtXorTest扩展了JApplet{
私有静态最终长serialVersionUID=1L;
公共静态void main(字符串[]args){
JFrame=新JFrame();
帧。设置标题(“AWT XorMode测试”);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JApplet applet=新的AwtXorTest();
applet.init();
frame.getContentPane().add(小程序);
frame.pack();
frame.setVisible(true);
}
@凌驾
公共void init(){
JPanel panel=新的AwtXorTestPanel();
getContentPane().add(面板);
}
}
类AwtXorTestPanel扩展了JPanel{
私有静态类XorComposite实现复合{
公共静态XorComposite实例=新XorComposite();
私有XorContext上下文=新XorContext();
@凌驾
公共CompositeContext createContext(ColorModel srcColorModel,
ColorModel(颜色模型、渲染提示){
返回上下文;
}
}
私有静态类XorContext实现CompositeContext{
公共XorContext(){
}
@凌驾
公共void组合(光栅src、光栅dstIn、可写光栅dstOut){
int w=Math.min(src.getWidth(),dstIn.getWidth());
inth=Math.min(src.getHeight(),dstIn.getHeight());
int[]srcRgba=新int[4];
int[]dstRgba=新int[4];
对于(int x=0;x
g2d剪辑区域有多个框,并将引发RasterFormatException,因为它的全尺寸光栅参考将替换为抗锯齿框的光栅。

警告:我已经有一段时间没有接触光栅了

看起来您可能正在访问光栅外的像素

光栅有一个
minX
minY
,因此您的循环需要如下所示:

int srcMinX = src.getMinX();
int srcMinY = src.getMinY();
int dstInMinX = dstIn.getMinX();
int dstInMinY = dstIn.getMinY();
int dstOutMinX = dstOut.getMinX();
int dstOutMinY = dstOut.getMinY();

for (int x = 0; x < w; x++) {
    for (int y = 0; y < h; y++) {
        src.getPixel(x+srcMinX, y+srcMinY, srcRgba);
        dstIn.getPixel(x+dstInMinX, y+dstInMinY, dstRgba);
        for (int i = 0; i < 3; i++) {
            dstRgba[i] ^= srcRgba[i];
        }
        dstOut.setPixel(x+dstOutMinX, y+dstOutMinY, dstRgba);
    }
}
int srcMinX=src.getMinX();
int srcMinY=src.getMinY();
int-dstInMinX=dstIn.getMinX();
int-dstInMinY=dstIn.getMinY();
int-dstOutMinX=dstOut.getMinX();
int-dstOutMinY=dstOut.getMinY();
对于(int x=0;x
我没有从您的示例(WinXP、Orac)中得到任何异常
/*******************************************************************************
 * Copyright (c) 2013 itemis AG and others.
 * 
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Matthias Wienand (itemis AG) - initial API and implementation
 * 
 *******************************************************************************/
package org.eclipse.gef4.graphics.examples;

import java.awt.Color;

public class AwtXorTest extends JApplet {

    private static final long serialVersionUID = 1L;

    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setTitle("AWT XorMode Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JApplet applet = new AwtXorTest();
        applet.init();
        frame.getContentPane().add(applet);
        frame.pack();
        frame.setVisible(true);
    }

    @Override
    public void init() {
        JPanel panel = new AwtXorTestPanel();
        getContentPane().add(panel);
    }

}

class AwtXorTestPanel extends JPanel {

    private static class XorComposite implements Composite {

        public static XorComposite INSTANCE = new XorComposite();

        private XorContext context = new XorContext();

        @Override
        public CompositeContext createContext(ColorModel srcColorModel,
                ColorModel dstColorModel, RenderingHints hints) {
            return context;
        }

    }

    private static class XorContext implements CompositeContext {

        public XorContext() {
        }

        @Override
        public void compose(Raster src, Raster dstIn, WritableRaster dstOut) {
            int w = Math.min(src.getWidth(), dstIn.getWidth());
            int h = Math.min(src.getHeight(), dstIn.getHeight());

            int[] srcRgba = new int[4];
            int[] dstRgba = new int[4];

            for (int x = 0; x < w; x++) {
                for (int y = 0; y < h; y++) {
                    src.getPixel(x, y, srcRgba);
                    dstIn.getPixel(x, y, dstRgba);
                    for (int i = 0; i < 3; i++) {
                        dstRgba[i] ^= srcRgba[i];
                    }
                    dstOut.setPixel(x, y, dstRgba);
                }
            }
        }

        @Override
        public void dispose() {
        }

    }

    private static final long serialVersionUID = 1L;

    public AwtXorTestPanel() {
        setPreferredSize(new Dimension(640, 480));
    }

    @Override
    public void paint(Graphics graphics) {
        Graphics2D g2d = (Graphics2D) graphics;

        // comment out to see it working:
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);

        g2d.setComposite(XorComposite.INSTANCE);
        g2d.setColor(new Color(0, 255, 255)); // resulting color should be red
        g2d.fill(new Rectangle(100, 100, 500, 500));
    }

}
int srcMinX = src.getMinX();
int srcMinY = src.getMinY();
int dstInMinX = dstIn.getMinX();
int dstInMinY = dstIn.getMinY();
int dstOutMinX = dstOut.getMinX();
int dstOutMinY = dstOut.getMinY();

for (int x = 0; x < w; x++) {
    for (int y = 0; y < h; y++) {
        src.getPixel(x+srcMinX, y+srcMinY, srcRgba);
        dstIn.getPixel(x+dstInMinX, y+dstInMinY, dstRgba);
        for (int i = 0; i < 3; i++) {
            dstRgba[i] ^= srcRgba[i];
        }
        dstOut.setPixel(x+dstOutMinX, y+dstOutMinY, dstRgba);
    }
}