

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.io.File;
import java.io.FileOutputStream;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import com.itextpdf.text.Document;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.DefaultFontMapper;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfWriter;

/**
 * This class demonstrates issue with transparent fills in iText PDF library.<br/>
 * 
 * 
 * On startup, it will write the PDF file using drawGraphics() method, and then show the frame with the same graphics
 * painted on the panel.<br/>
 * 
 * We will expect to see the same text printed in PDF and on the screen, but the second text is invisible in PDF. <br/>
 * 
 * The sequence of drawing:
 * <OL>
 * <LI>setColor to transparent white</LI>
 * <LI>fillRect()</LI>
 * <LI>createGraphics()</LI>
 * <LI>setClip() to same rectangle</LI>
 * <LI>setColor() to Blue</LI>
 * <LI>draw text within rectangle</LI>
 * </OL>
 * The text is visible in JPanel and not visible in PDF.
 * 
 * */
public class TransparencyItextPdf
{
    private static final int WIDTH = 200;

    private static final int HEIGHT = 250;

    private static final int HALF_HEIGHT = HEIGHT / 2;

    public static void main(String[] args) throws Exception
    {
        File file = File.createTempFile("transparency", ".pdf");
        writePdf(file);
        System.out.println("file:" + file);
        createFrame().setVisible(true);
        openPdfViewerInWindowsEnvironment(file);
    }

    private static void drawGraphics(Graphics graphics)
    {
        Graphics2D g = (Graphics2D)graphics;

        // this text will be visible on screen and in PDF
        g.setColor(Color.BLUE);
        g.drawString("Visible on screen and in PDF", 0, HALF_HEIGHT);

        // fill rectangle with transparent white color
        g.setColor(new Color(255, 255, 255, 0));
        g.fillRect(0, 0, WIDTH, HALF_HEIGHT);

        // the create() and setClip() is important
        Graphics2D g2 = (Graphics2D)graphics.create();
        g2.setClip(0, 0, WIDTH, HALF_HEIGHT);

        // Here is the problem, this text not appear in PDF
        g2.setColor(Color.BLUE);
        g2.drawString("Visible on screen only", 0, 40);
    }


    private static void openPdfViewerInWindowsEnvironment(File file)
    {
        JOptionPane.showMessageDialog(null, "File is created:" + file.getAbsolutePath());
        try
        {
            Runtime.getRuntime().exec("cmd.exe /c start " + file.getAbsolutePath());
        }
        catch (Exception e)
        {
        }
    }

    private static void writePdf(File file) throws Exception
    {
        FileOutputStream fos = new FileOutputStream(file);
        Document document = new Document(new Rectangle(WIDTH, HEIGHT));
        PdfWriter writer = PdfWriter.getInstance(document, fos);
        document.open();
        PdfContentByte content = writer.getDirectContent();
        content.saveState();
        Graphics2D g2 = content.createGraphics(WIDTH, HEIGHT, new DefaultFontMapper());
        drawGraphics(g2);
        content.restoreState();

        g2.dispose();
        document.close();
        fos.flush();
        fos.close();
    }

    @SuppressWarnings("serial")
    private static JFrame createFrame()
    {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(WIDTH, HEIGHT);
        frame.setLocation(Toolkit.getDefaultToolkit().getScreenSize().width / 4, Toolkit.getDefaultToolkit()
                .getScreenSize().height / 4);

        final JPanel panel = new JPanel()
        {
            protected void paintComponent(Graphics graphics)
            {
                drawGraphics(graphics);
            }

        };
        frame.add(panel);
        return frame;
    }

}
