-
Bug
-
Resolution: Fixed
-
P4
-
7, 8, 9, 10, 11, 12, 13, 14, 15
-
b19
-
x86_64
-
windows_10
-
Verified
ADDITIONAL SYSTEM INFORMATION :
Windows 10, Java 8, 9, 10, 11, 12 and 13.
A DESCRIPTION OF THE PROBLEM :
When printing an opaque image (i.e. TYPE_INT_RGB) using a custom Composite and with no other graphic elements, the custom composite is ignored.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
- Create a class that implements Composite.
- Create a class that implements Printable
- Create main() method that starts a print job with the Printable class and starts it.
- In the print() method of the Printable class, set the custom composite with Graphics2D.setComposite() and draw the image.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The custom Composite class should be called when the image is drawn to implement the custom compositing.
ACTUAL -
The custom Composite class does not get called.
---------- BEGIN SOURCE ----------
package test;
import java.awt.Composite;
import java.awt.CompositeContext;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
public class TestComposite implements Printable, Composite, CompositeContext
{
private BufferedImage mTestImage;
public TestComposite(BufferedImage testImage)
{
mTestImage = testImage;
}
public static void main(String [] args) throws Exception
{
// Create opaque image
BufferedImage opaqueImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
// Print the image
PrinterJob pjob = PrinterJob.getPrinterJob();
pjob.setPrintable(new TestComposite(opaqueImage));
pjob.print();
}
@Override
public int print(Graphics graphics, PageFormat pf, int pageIndex) throws PrinterException
{
if (pageIndex == 0)
{
Graphics2D g2 = (Graphics2D)graphics;
g2.setComposite(this);
g2.drawImage(mTestImage, 0, 0, null);
//g2.drawLine(0, 0, 10, 10);
return PAGE_EXISTS;
}
else
{
return NO_SUCH_PAGE;
}
}
@Override
public CompositeContext createContext(ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints)
{
return this;
}
@Override
public void compose(Raster src, Raster dstIn, WritableRaster dstOut)
{
System.out.println("compose()");
int [] srcSamples = new int[src.getWidth() * src.getHeight() * src.getNumBands()];
src.getPixels(0, 0, src.getWidth(), src.getHeight(), srcSamples);
dstOut.setPixels(0, 0, dstOut.getWidth(), dstOut.getHeight(), srcSamples);
}
@Override
public void dispose()
{
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
If any other elements are drawn on the page when the custom Composite is active, then when the image is drawn, the custom composite class will get called, i.e. it will work correctly. So, just add a drawLine() call and the
The problem happens in the implementation of PeekGraphics and PeekMetrics. PeekMetrics is used to keep track of whether custom composites have been used, and if so, the PrinterJob will use a different Graphics2D object on subsequent printing.
PeekMetrics has methods to register the drawing of shapes, text and images. The methods for shapes and text check if the current Composite is a custom Composite, and sets a flag accordingly. The method to register images do not check this, so PeekGraphics thinks custom Composite objects were never used.
The fix is simple, in the drawImage() methods in PeekMetrics, a call should be added to checkAlpha() also in PeekMetrics with the current Composite object.
FREQUENCY : always
Windows 10, Java 8, 9, 10, 11, 12 and 13.
A DESCRIPTION OF THE PROBLEM :
When printing an opaque image (i.e. TYPE_INT_RGB) using a custom Composite and with no other graphic elements, the custom composite is ignored.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
- Create a class that implements Composite.
- Create a class that implements Printable
- Create main() method that starts a print job with the Printable class and starts it.
- In the print() method of the Printable class, set the custom composite with Graphics2D.setComposite() and draw the image.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The custom Composite class should be called when the image is drawn to implement the custom compositing.
ACTUAL -
The custom Composite class does not get called.
---------- BEGIN SOURCE ----------
package test;
import java.awt.Composite;
import java.awt.CompositeContext;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
public class TestComposite implements Printable, Composite, CompositeContext
{
private BufferedImage mTestImage;
public TestComposite(BufferedImage testImage)
{
mTestImage = testImage;
}
public static void main(String [] args) throws Exception
{
// Create opaque image
BufferedImage opaqueImage = new BufferedImage(100, 100, BufferedImage.TYPE_INT_RGB);
// Print the image
PrinterJob pjob = PrinterJob.getPrinterJob();
pjob.setPrintable(new TestComposite(opaqueImage));
pjob.print();
}
@Override
public int print(Graphics graphics, PageFormat pf, int pageIndex) throws PrinterException
{
if (pageIndex == 0)
{
Graphics2D g2 = (Graphics2D)graphics;
g2.setComposite(this);
g2.drawImage(mTestImage, 0, 0, null);
//g2.drawLine(0, 0, 10, 10);
return PAGE_EXISTS;
}
else
{
return NO_SUCH_PAGE;
}
}
@Override
public CompositeContext createContext(ColorModel srcColorModel, ColorModel dstColorModel, RenderingHints hints)
{
return this;
}
@Override
public void compose(Raster src, Raster dstIn, WritableRaster dstOut)
{
System.out.println("compose()");
int [] srcSamples = new int[src.getWidth() * src.getHeight() * src.getNumBands()];
src.getPixels(0, 0, src.getWidth(), src.getHeight(), srcSamples);
dstOut.setPixels(0, 0, dstOut.getWidth(), dstOut.getHeight(), srcSamples);
}
@Override
public void dispose()
{
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
If any other elements are drawn on the page when the custom Composite is active, then when the image is drawn, the custom composite class will get called, i.e. it will work correctly. So, just add a drawLine() call and the
The problem happens in the implementation of PeekGraphics and PeekMetrics. PeekMetrics is used to keep track of whether custom composites have been used, and if so, the PrinterJob will use a different Graphics2D object on subsequent printing.
PeekMetrics has methods to register the drawing of shapes, text and images. The methods for shapes and text check if the current Composite is a custom Composite, and sets a flag accordingly. The method to register images do not check this, so PeekGraphics thinks custom Composite objects were never used.
The fix is simple, in the drawImage() methods in PeekMetrics, a call should be added to checkAlpha() also in PeekMetrics with the current Composite object.
FREQUENCY : always