2

我正在尝试在 Graphics2D 渲染上创建 Punch Out 效果。

我有一个黑色的矩形。文本颜色为红色。我希望能够将颜色设置为 0x00FF0000 并让它从背景中“冲出”。

    Graphics2D newG = (Graphics2D)g.create();
    newG.setColor(new Color(0x00,0x00,0x00,0xFF)); //255 Alpha
    newG.fillRect(box.x, box.y, box.width, box.height);

    newG.setColor(new Color(0xFF,0x00,0x00,0x00)); //0 Alpha
    newG.drawString("Welcome", box.x ,box.y);

我看到的是文本在背景上完全透明,但没有打孔。

我所看到的:http://i.imgur.com/HYTe1.jpg

我期望看到的:http://i.imgur.com/YQwZk.jpg

如何使用 Graphics2D 实现“打孔”效果?

编辑:打孔效果就像使用前景设置为 0x00FF0000 和背景设置为 0xFF000000 的 JLabel。它从背景中“删除”/“打出”文本。我也不希望它总是打出来,只有当 alpha 为 0 时。

EDIT2:我尝试了下面的 sugested 代码,结果相同。

Rectangle stringBox = new Rectangle(x, y - fm.getHeight() + fm.getDescent(), fm.stringWidth(splitStr[i]), fm.getHeight());

TextLayout textLO = new TextLayout(splitStr[i], newG.getFont(), newG.getFontRenderContext());
 Shape sText = textLO.getOutline(newG.getTransform());      // The Shape of text
Path2D.Double shape = new Path2D.Double(stringBox);     // The rectangle
appendTextShape(shape, sText, newG.getTransform(), 0, 10);
newG.setColor(Color.black);
newG.fill(shape);
newG.setColor(new Color(0xFF, 0x00,0x00,0x00));
newG.drawString(splitStr[i], x, y);
4

3 回答 3

1

http://docs.oracle.com/javase/tutorial/2d/advanced/compositing.html

正确设置组合物是解决方案。SRC_IN 是我正在寻找的组合。

于 2013-01-17T22:29:26.797 回答
1

如果您的意思是:

在此处输入图像描述

您需要获取Shape文本的轮廓,然后使用Path2D创建组合Shape来渲染:

Graphics2D g2d = ...;
TextLayout text = new TextLayout("Welcome", g2d.getFont(), g2d.getFontRenderContext());
Shape sText = text.getOutline(g2d.getTransform());      // The Shape of text
Path2D shape = new Path2D.Double(new Rectangle(200, 100));      // The rectangle
appendTextShape(shape, sText, g2d.getTransform(), 0, 10);   // combine the shape
g2d.setColor(Color.BLACK);
g2d.fill(rect);

appendTextShape方法在这里:

public void appendTextShape (Path2D p, Shape s, AffineTransform t, int x, int y) {
    synchronized (s) {
        PathIterator pit = s.getPathIterator(t);
        float[] coords = new float[6];
        int c = 0;
        while (true) {
            pit.next();
            if (pit.isDone()) {
                break;
            }
            switch (pit.currentSegment(coords)) {
                case PathIterator.SEG_MOVETO:
                    p.moveTo(x + coords[0], y + coords[1]);
                    break;
                case PathIterator.SEG_LINETO:
                    if (c == 0) {
                        p.moveTo(x + coords[0], y + coords[1]);
                    } else {
                        p.lineTo(x + coords[0], y + coords[1]);
                    }
                    break;
                case PathIterator.SEG_QUADTO:
                    if (c == 0) {
                        p.moveTo(x + coords[0], y + coords[1]);
                    } else {
                        p.quadTo(x + coords[0], y + coords[1], x + coords[2], y + coords[3]);
                    }
                    break;
                case PathIterator.SEG_CUBICTO:
                    if (c == 0) {
                        p.moveTo(x + coords[0], y + coords[1]);
                    } else {
                        p.curveTo(x + coords[0], y + coords[1], x + coords[2], y + coords[3], x + coords[4], y + coords[5]);
                    }
                    break;
                case PathIterator.SEG_CLOSE:
                    p.closePath();
                    break;
            }
            c++;
        }
    }
}
于 2013-01-17T18:51:28.600 回答
0

你的appendTextShape方法奏效了。

但是,它已经在 的构造函数中实现Path2D,如下所示:

Path2D path = new Path2D.Double(shape, affineTransform);
于 2013-09-23T07:34:27.773 回答