Search code examples
printingjava-6

Java Printing with alpha color makes blank page


I am experiencing an issue where when I use a color with an alpha that is not at 100% the entire page will not print.

For example

  • I have two pages p1, p2.
  • I have a color with alpha set to 40% called c1.
  • I have the same color but at 100% alpha c2.
  • I have a rectangle r that may or may not be printed on the pages.
  • I also have some test text printed on both.

  • If p1 does not print r, p2 prints r using c2, p2 prints fine.

  • If p1 does not print r, p2 prints r using c1, p2 does not print.
  • If p1 prints r using c1, p2 prints r using c1, p2 prints fine.

Here is a sample application to demonstrate this:

import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.RoundRectangle2D;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;

import javax.swing.JButton;
import javax.swing.JFrame;

class Rectangle extends java.awt.Rectangle {
    public static final int SCREEN_RESOLUTION = 72;
    private static final int TWIP_CONVERT = 1440;

    Rectangle(int x, int y, int w, int h) {
        super(twip2pixel(x,1),twip2pixel(y,1),twip2pixel(w,1),twip2pixel(h,1));
    }

    static int twip2pixel(int twips, float zoom) {
         return Math.round(zoom * twips * SCREEN_RESOLUTION / TWIP_CONVERT);
     }
}

public class Test extends JFrame implements ActionListener{

    static Rectangle[] textRectangles1 = {
                new Rectangle(2590, 8075, 2325,265),
                new Rectangle(2480, 8480, 7595, 265),
                new Rectangle(1700, 8940, 8310, 265),
                new Rectangle(2445, 9385, 7615, 265),
                new Rectangle(2630, 9850, 7410, 265),
                new Rectangle(2015, 10320, 8005, 265),
                new Rectangle(2450, 10780, 7600, 265),
                new Rectangle(8210, 12240, 2170, 265),
    };

    static Rectangle[] textRectangles2 = {
                new Rectangle(1895, 5630, 6160, 265)
    };

    JButton btnPrint;
    JButton btnPrint2;
    JButton btnPrint3;

    public Test() {
        this.setLayout(new FlowLayout());

        btnPrint = new JButton("Print - 100% alpha - works");
        btnPrint.addActionListener(this);
        this.add(btnPrint);

        btnPrint2 = new JButton("Print2 - 40% alpha - doesn't work");
        btnPrint2.addActionListener(this);
        this.add(btnPrint2);

        btnPrint3 = new JButton("Print3 - both pages 40% alpha - works");
        btnPrint3.addActionListener(this);
        this.add(btnPrint3);

        this.pack();
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        Test test = new Test();
        test.setVisible(true);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        PrinterJob job = PrinterJob.getPrinterJob();

        Book book = new Book();
        if(e.getSource().equals(btnPrint)) {
            book.append(new MyPage(textRectangles1, 255, false), new PageFormat());
            book.append(new MyPage(textRectangles2, 255, true), new PageFormat());
        } else if(e.getSource().equals(btnPrint2)) {
            book.append(new MyPage(textRectangles1, 255, false), new PageFormat());
            book.append(new MyPage(textRectangles2, 100, true), new PageFormat());
        } else {
            book.append(new MyPage(textRectangles1, 100, true), new PageFormat());
            book.append(new MyPage(textRectangles2, 100, true), new PageFormat());
        }

        job.setPageable(book);
        boolean doPrint = job.printDialog();
        if (doPrint) {
            try {
                job.print();
            } catch (PrinterException ex) {
                // The job did not successfully
                // complete
            }
        }
    }

    static void drawText(Graphics2D g, Rectangle r) {
        g.setClip(r.x, r.y, r.width, r.height);
        AffineTransform oldTransform = g.getTransform();
        g.scale(1.0, 1.0);
        g.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
                   RenderingHints.VALUE_FRACTIONALMETRICS_ON);

        g.translate(r.x, r.y);
        g.setFont(new Font("Arial",0,10));

        g.setColor(Color.BLACK);

        float y = g.getFontMetrics().getAscent() + 1;
        g.drawString("TEST", 3, y);

        g.setTransform(oldTransform);
    }

    static void drawBox(Graphics2D g, Rectangle r, int alpha) {
        AffineTransform oldTransform = g.getTransform();
        float zoom = 1;
        g.scale(zoom, zoom);
        g.setClip(r);
        g.translate(r.x, r.y);

        Font boxFont = new Font("Arial", 1, 30);
        g.setFont(boxFont);

        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

        RoundRectangle2D rect = new RoundRectangle2D.Double(0.0,0.0,r.getWidth()-2,r.getHeight()-2,15 ,12);
        g.setColor(new Color(188, 238, 104, alpha));
        g.fill(rect);

        g.setTransform(oldTransform);
        g.setFont(new Font("Arial",0,10));
        g.setTransform(oldTransform);
    }
}

class MyPage implements Printable{
    int alpha = 255;
    boolean printRectangle = false;
    Rectangle[] textRectangles;

    MyPage(Rectangle[] textRectangles, int alpha, boolean printRectangle) {
        this.textRectangles = textRectangles;
        this.alpha = alpha;
        this.printRectangle = printRectangle;
    }

    @Override
    public int print(Graphics graphics, PageFormat pageFormat,
            int pageIndex) throws PrinterException {

        Graphics2D g2d = (Graphics2D) graphics;

        g2d.setPaint(Color.black);
        g2d.translate(10, 10);
        g2d.scale(0.96732026, 0.96732026);

        for(Rectangle r : textRectangles) {
            Test.drawText(g2d, r);
        }

        if(printRectangle) {
            Test.drawBox(g2d, new Rectangle(4156, 942, 3728, 1216), alpha);
        }

        return Printable.PAGE_EXISTS;
    }
}

Solution

  • This is caused by a java bug: https://bugs.java.com/bugdatabase/view_bug?bug_id=7146409

    A workaround is to print a rectangle on the first page with width and height set to 0 but with the graphics color set to a color with alpha less than 255.