JDK-8013564 : Font rendering anti-aliasing in translucent BufferedImages broken
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 7,7u7
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: solaris_10,windows_7
  • CPU: sparc
  • Submitted: 2013-03-20
  • Updated: 2016-03-15
  • Resolved: 2016-03-15
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 :  
Relates :  
Description
FULL PRODUCT VERSION :
java 1.7_7

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

A DESCRIPTION OF THE PROBLEM :
On Java 7, pixel translucency has regressed comparing to Java 6.

When you try to draw strings in a translucent BufferedImage, instead of using the alpha values of the background the anti-aliasing uses the opaque color value of the background. This makes anti-aliasing artifacts appear around the text.

This never occured with Java 6, which renders the properly the fonts when using intermediate buffered images and alpha compositing.



REGRESSION.  Last worked in version 6u31

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile the provided sample code and  put the window on dark background. You will see the labels:
* paintComponent:image:drawStringproperly rendered

This sample shows two different approaches, once in paint() and once in paintComponent():
1) write into a buffered image and blit it on the graphics context
2) write directly to the graphics context

The rendering changes by using Using  -Dsun.java2d.noddraw=true or false, which makes me think of a pipeline rendering issue. -Dsun.java2d.d3d also affects the rendering.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
There should be no  " white "  artifacts

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.image.BufferedImage;
import java.awt.image.ColorModel;

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,255,255,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.setFont(getFont().deriveFont(40f));
                    big.drawString( " paintComponent:image:drawString " , 10, 30);
                    big.dispose();

                    Graphics2D g2d = (Graphics2D) g;
                    super.paintComponent(g);
                    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);
                }
            }
        };

        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 ----------

CUSTOMER SUBMITTED WORKAROUND :
Use Java 6, but on Windows 7 x64 there are other issues with this JVM.
Comments
Close Remarks: 1. The issue is reproducible on JDK 9 & is duplicate of JDK-8015070 2. At the time of closing, JDK-8015070 is open and being actively inspected as well. 3. The fix has been identified and the same fix resolves the current bug. webrev for the changes will be initiated soon. 4. Hence closing this issue as duplicate.
15-03-2016

Quick Inferences from Inspection: 1. The issue is reproducible on JDK 9 2. Duplicate of JDK-8015070. Kindly refer to the link for more details on root cause & fix. Link: https://bugs.openjdk.java.net/browse/JDK-8015070
15-03-2016

RT NOTE: Client (bulk) The criteria for deferral bulk request bugs: - Not P2 - Not tck-red - Not critical to customer Approved.
11-10-2013

jdk8: SQE OK to defer
07-10-2013

Defer notes: not a regression in 8. Defer to 8-pool.
04-10-2013

isn't a regression from jdk8 pov
02-10-2013

is it jdk8 affected? what is introduced in release?
13-09-2013

solaris10-sparcv9/7u40b30(64bit) sun/java2d/DirectX/NonOpaqueDestLCDAATest/NonOpaqueDestLCDAATest.java It has same issue: The text strings below appear with smudges. refer to JDK-8015581
27-06-2013

I think this was introduced by the fix for https://jbs.oracle.com/bugs/browse/JDK-6263951 "Java does not use fast AA text loops when regular AA hint is set" If you create a JDK 6 verison of the above program (ie use com.sun.AWTUtilities) it works fine until you set the hint for the BI case to be big.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); when it behaves the same as JDK 7 without this change. In other words this was always a bug for the KEY_TEXT_ANTIALIASING case and now the JDK 7 optimisation means means KEY_ANTIALIASING is affected too. Probably we need to detect the non-opaque destination and in such case always use the 'general' AA loops rather than the optimised text AA loops.
01-05-2013