JDK-8040689 : Fonts antialiasing artifacts appear when using translucent composited images
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 7,8,9
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_7
  • Submitted: 2013-05-24
  • Updated: 2015-10-29
  • Resolved: 2015-10-29
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9Resolved
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
JDK 7u21

ADDITIONAL OS VERSION INFORMATION :
Windows 7 64bit

A DESCRIPTION OF THE PROBLEM :
When you draw a string onto a translucent buffered image and then blit the image onto a transparent window, the antialiasing of the fonts doesn't blend from the font color to the translucent background color. In our application, we need to write to an intermediate buffered image, because we need to animate the content of the window.

This works well with Java 6. And is therefore  a regression.

REGRESSION.  Last worked in version 6u45

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the provided code and put the transparent window over a dark background.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The antialiasing of the first line of the provided example should blend to the transparent background color.

ACTUAL -
The pixels blend from the opaque font color to the OPAQUE  background color of the even thoug the background color is translucent.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package misc;

import java.awt.*;
import javax.swing.*;
import static java.awt.GraphicsDevice.WindowTranslucency.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import sun.font.GlyphList;
import sun.java2d.SunGraphics2D;
import sun.java2d.loops.FontInfo;

public class TranslucentFontWindowDemo extends JFrame {

    public TranslucentFontWindowDemo() {
        super( " TranslucentFontWindowDemo " );
        setUndecorated(true);
        setBackground(new Color(0, 0, 0, 0));
        setSize(new Dimension(700, 300));
        setLocationRelativeTo(null);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        JPanel panel = new JPanel() {

            @Override
            protected void paintComponent(Graphics g) {
                int w = getWidth();
                int h = getHeight();
                if (g instanceof Graphics2D) {

                    BufferedImage bi = getGraphicsConfiguration().createCompatibleImage(w, h, Transparency.TRANSLUCENT);
                    Graphics2D big = (Graphics2D) bi.createGraphics();
                    big.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    big.setColor(new Color(255, 0, 0, 50));
                    big.fillRoundRect(0, 0, getWidth(), getHeight(), 30, 30);
                    big.setColor(Color.BLACK);
                    big.setStroke(new BasicStroke(1.5f));
                    big.drawLine(0, 0, w, h);
                    big.setStroke(new BasicStroke(1f));
                    Font font = getFont().deriveFont(40f);
                    big.setFont(font);
                    big.drawString( " paintComponent:image:drawString " , 10, 30);

                    big.setColor(Color.BLACK);
                    FontRenderContext frc = big.getFontRenderContext();
                    TextLayout textLayout = new TextLayout( " Outline " , font, frc);
//                    textLayout.draw(big, 10, 120);
                    Rectangle2D textBounds = textLayout.getBounds();

                    Shape shapeOutline = textLayout.getOutline(AffineTransform.getTranslateInstance(10 - textBounds.getX(), 120 - textBounds.getY()));
                    big.fill(shapeOutline);

                    SunGraphics2D sg = (SunGraphics2D) big;
                    FontInfo info = sg.getFontInfo();
                    GlyphList gl = GlyphList.getInstance();
                    if (gl.setFromString(info,  " String " , 10, 110)) {
                        // Native call
//                        sg.loops.drawGlyphListAALoop.DrawGlyphListAA(sg, sg.surfaceData, gl);
//                        sg.loops.drawGlyphListLoop.DrawGlyphList(sg, sg.surfaceData, gl);
//                        sg.loops.drawGlyphListLCDLoop.DrawGlyphListLCD(sg, sg.surfaceData, gl);
                        gl.dispose();
                    }

                    big.dispose();

                    Graphics2D g2d = (Graphics2D) g.create();
                    g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                    g2d.drawImage(bi, 0, 0, null);
                    g2d.setColor(Color.BLACK);
                    g2d.setFont(getFont().deriveFont(40f));
                    g2d.drawString( " paintComponent:drawString " , 10, 70);
                    g2d.dispose();
                    super.paintComponent(g);
                }
            }
        };

        panel.setLayout(new BorderLayout());
        panel.add(new JLabel( " hey " ), BorderLayout.CENTER);
        panel.setOpaque(false);
        setLayout(new BorderLayout());
        setContentPane(panel);

        MouseAdapter mouseAdapter = new MouseAdapter() {

            Point start = null;

            @Override
            public void mousePressed(MouseEvent e) {
                this.start = e.getLocationOnScreen();
            }

            @Override
            public void mouseDragged(MouseEvent e) {
                if (this.start != null) {
                    Point end = e.getLocationOnScreen();
                    if (!end.equals(this.start)) {
                        int deltaX = end.x - this.start.x;
                        int deltaY = end.y - this.start.y;
                        Point dialogLocation = getLocation();
                        Point newLocation = new Point(dialogLocation.x + deltaX, dialogLocation.y + deltaY);
                        setLocation(newLocation);
                        this.start = end;
                    }
                }
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                this.start = null;
            }
        };

        addMouseListener(mouseAdapter);
        addMouseMotionListener(mouseAdapter);
    }

    public static void main(String[] args) {
        ColorModel cm = ColorModel.getRGBdefault();
        switch (cm.getTransparency()) {
            case Transparency.BITMASK:
                System.err.println( " Color model supports: BITMASK " );
                break;
            case Transparency.OPAQUE:
                System.err.println( " Color model supports: OPAQUE " );
                break;
            case Transparency.TRANSLUCENT:
                System.err.println( " Color model supports: TRANSLUCENT " );
                break;
        }

        // Determine what the GraphicsDevice can support.
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        GraphicsDevice gd = ge.getDefaultScreenDevice();
        boolean isPerPixelTranslucencySupported = gd.isWindowTranslucencySupported(PERPIXEL_TRANSLUCENT);

        //If translucent windows aren't supported, exit.
        if (!isPerPixelTranslucencySupported) {
            System.out.println( " Per-pixel translucency is not supported " );
            System.exit(0);
        }

        // Create the GUI on the event-dispatching thread
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                TranslucentFontWindowDemo gtw = new TranslucentFontWindowDemo();

                // Display the window.
                gtw.setUndecorated(true);
                gtw.setVisible(true);
            }
        });
    }
}
---------- END SOURCE ----------
Comments
Duplicate of https://bugs.openjdk.java.net/browse/JDK-8013564
29-10-2015

http://cr.openjdk.java.net/~psadhukhan/8040689/webrev.00/ submiited. It works but performance degrades. Waiting for Phil's evaluation on this.
29-09-2015

not a regression for 8 and 9
12-12-2014

- this is an issue reported against 7(7u), - there are now affected version 9 filed for this issue - 7u issues are transferred to Sustaining Nevertheless if someone have a report against 9 - please reopen and add affectedVersion 9 or 7u specific escalations might be reopen to Sustaining
10-08-2014

- this is an issue reported against 7(7u), - there are now affected version 9 filed for this issue - 7u issues are transferred to Sustaining Nevertheless if someone have a report against 9 - please reopen and add affectedVersion 9 or 7u specific escalations might be reopen to Sustaining
10-08-2014

Per agreement with Victor sustaining takes all the bugs that formally reported against JDK7. We may return them back after the evaluation if some of them are reproducible on JDK8 or 9.
07-05-2014

Will need review for >= JDK 7 Moving to 7u80 and will review ASAP. Ping me directly with any concerns about this move.
22-04-2014

is it affecting 8 or 9?
17-04-2014