JDK-6648996 : Frame.printAll() invoked on a non-opaque window prints black background
  • Type: Bug
  • Component: client-libs
  • Sub-Component: java.awt
  • Affected Version: 6u10
  • Priority: P2
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2008-01-10
  • Updated: 2011-01-19
  • Resolved: 2008-02-14
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 6
6u10 b12Fixed
Related Reports
Relates :  
Relates :  
Description
When using the API introduced with the feature described at the CR 6633275, and making a frame non-opaque (AWTUtilities.setWindowOpaque(frame, false)), the frame is displayed as a translucent top-level window on the screen. The background of the frame becomes invisible, and only the explitcitly painted pixels are visibles (like those belonging to the Swing components put onto the frame).

However, when the Frame.printAll() method is used to print the frame contents on the paper, the area occupied by the invisible background gets printed with black color on the paper which is not correct. 

Expected behavior: nothing should be printed at the areas occupied by the background of the frame if these areas are invisible on the screen because the frame is non-opaque.

Comments
SUGGESTED FIX --- old/src/windows/classes/sun/awt/windows/WCanvasPeer.java 2008-01-18 15:21:05.000000000 +0300 +++ new/src/windows/classes/sun/awt/windows/WCanvasPeer.java 2008-01-18 15:21:05.000000000 +0300 @@ -10,6 +10,7 @@ import java.awt.peer.*; import java.lang.ref.WeakReference; import java.lang.reflect.Method; +import sun.awt.AWTAccessor; import sun.awt.SunToolkit; import sun.awt.Win32GraphicsDevice; import sun.awt.PaintEventDispatcher; @@ -100,18 +101,22 @@ } public void print(Graphics g) { - Dimension d = ((Component)target).getSize(); - if (g instanceof Graphics2D || - g instanceof sun.awt.Graphics2Delegate) { - // background color is setup correctly, so just use clearRect - g.clearRect(0, 0, d.width, d.height); - } else { - // emulate clearRect - g.setColor(((Component)target).getBackground()); - g.fillRect(0, 0, d.width, d.height); - g.setColor(((Component)target).getForeground()); - } - super.print(g); + if (!(target instanceof Window) || + AWTAccessor.getWindowAccessor().isOpaque((Window)target)) + { + Dimension d = ((Component)target).getSize(); + if (g instanceof Graphics2D || + g instanceof sun.awt.Graphics2Delegate) { + // background color is setup correctly, so just use clearRect + g.clearRect(0, 0, d.width, d.height); + } else { + // emulate clearRect + g.setColor(((Component)target).getBackground()); + g.fillRect(0, 0, d.width, d.height); + g.setColor(((Component)target).getForeground()); + } + } + super.print(g); } public boolean shouldClearRectBeforePaint() { --- old/src/windows/classes/sun/awt/windows/WComponentPeer.java 2008-01-18 15:21:05.000000000 +0300 +++ new/src/windows/classes/sun/awt/windows/WComponentPeer.java 2008-01-18 15:21:05.000000000 +0300 @@ -253,7 +253,7 @@ int[] pix = createPrintedPixels(0, startY, totalW, h); if (pix != null) { BufferedImage bim = new BufferedImage(totalW, h, - BufferedImage.TYPE_INT_RGB); + BufferedImage.TYPE_INT_ARGB); bim.setRGB(0, 0, totalW, h, pix, 0, totalW); g.drawImage(bim, 0, startY, null); bim.flush(); --- old/src/windows/classes/sun/awt/windows/WFileDialogPeer.java 2008-01-18 15:21:05.000000000 +0300 +++ new/src/windows/classes/sun/awt/windows/WFileDialogPeer.java 2008-01-18 15:21:05.000000000 +0300 @@ -207,4 +207,10 @@ public boolean isRestackSupported() { return false; } + + // The effects are not supported for system dialogs. + public void applyShape(sun.java2d.pipe.Region shape) {} + public void setOpacity(float opacity) {} + public void setOpaque(boolean isOpaque) {} + public void updateWindow(java.awt.image.BufferedImage backBuffer) {} } --- old/src/windows/classes/sun/awt/windows/WPrintDialogPeer.java 2008-01-18 15:21:05.000000000 +0300 +++ new/src/windows/classes/sun/awt/windows/WPrintDialogPeer.java 2008-01-18 15:21:05.000000000 +0300 @@ -122,4 +122,10 @@ public boolean isRestackSupported() { return false; } + + // The effects are not supported for system dialogs. + public void applyShape(sun.java2d.pipe.Region shape) {} + public void setOpacity(float opacity) {} + public void setOpaque(boolean isOpaque) {} + public void updateWindow(java.awt.image.BufferedImage backBuffer) {} }
18-01-2008

EVALUATION Also we need not to clear the background when printing a translucent window. This is fixed in the WCanvasPeer.print() method (see the suggested fix).
18-01-2008

EVALUATION Actually the code for the translucency/shapes feature (6633275) has broken the system dialogs under MS Windows (FileDialog and PrintDialog). Using these dilogs causes throwing the NullPointerException("pData is null"). This happens because the implementation of the mentioned dialogs doesn't use native objects to represent the system dislogs: only the java-sized peers exist. While initializing a window (be it a regular java window, or a system dialog which is a window as well from the point of view of Java), the applyShape() method gets invoked (see java.awt.Window.addNotify()) to initialize any set shape for this window. The method at the end of the call-chain executes a static function at the native code (say, AwtComponent::SetRectangularShape()), which in turn tries to retrive the pointer to the native object (an instance of the AwtComponent class) which is the native part of the peer. As this native part doesn't exist for system dialogs, the exception gets generated. The fix for this CR fixes a couple of printing issue, and it's supposed to be integrated into the 6u10 asap as this is a bug in the newly introduced feature. So is the Print/FileDialog fix, and therefore it is reasonable to combine these fixes. Concerning the actual printing issue. The cause of the problem is the WComponentPeer.print() method which uses BufferedImage.TYPE_INT_RGB buffered images instead of the BufferedImage.TYPE_INT_ARGB. The first kind of images doesn't support the translucency, and so such images interpret the color value of zero (32 bits) as a black color, not taking into account the alpha component (the 4th byte) which is also null, and therefore represents a transparent color. Using an ARGB image fixes the problem.
18-01-2008

WORK AROUND While printing one may temporary make the frame being opaque.
10-01-2008