Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8244422

graphics clipping ignored when printing to a PDF/XPS file

XMLWordPrintable

    • 2d
    • x86_64
    • windows_10

      ADDITIONAL SYSTEM INFORMATION :
      Windows 10.0.18363.778

      java version "14.0.1" 2020-04-14
      Java(TM) SE Runtime Environment (build 14.0.1+7)
      Java HotSpot(TM) 64-Bit Server VM (build 14.0.1+7, mixed mode, sharing)

      also:

      openjdk version "1.8.0_252"
      OpenJDK Runtime Environment Corretto-8.252.09.2 (build 1.8.0_252-b09)
      OpenJDK 64-Bit Server VM Corretto-8.252.09.2 (build 25.252-b09, mixed mode)

      A DESCRIPTION OF THE PROBLEM :
      When the graphics device has an empty clipping path, this is ignored when printing. Doing the same when rendering in a BufferedImage works as expected. "Empty clipping" path means that "graphics.getClip().getPathIterator(null).isDone()" is true.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      run the program
      in the dialogbox, choose PDF or XPS
      choose the filename

      (it also reproduces with a real printer, but you may want to save toner / ink / paper)

      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      the PDF / XPS file should be blank
      ACTUAL -
      the PDF / XPS file is red

      ---------- BEGIN SOURCE ----------
      package pdfbox4822clip;

      import java.awt.Color;
      import java.awt.Graphics;
      import java.awt.Graphics2D;
      import java.awt.Rectangle;
      import java.awt.geom.Area;
      import java.awt.geom.Rectangle2D;
      import java.awt.image.BufferedImage;
      import java.awt.print.PageFormat;
      import java.awt.print.Printable;
      import java.awt.print.PrinterException;
      import java.awt.print.PrinterJob;
      import java.io.File;
      import java.io.IOException;
      import javax.imageio.ImageIO;
      import javax.print.PrintServiceLookup;

      public class PDFBox4822Clip implements Printable
      {

          public static void main(String[] args) throws PrinterException, IOException
          {
              PDFBox4822Clip main = new PDFBox4822Clip();
              main.paintToImage(); // produces transparent image
              main.paintToPrint(); // produces red page, but should produce
          }

          public PDFBox4822Clip()
          {
              System.out.println("Empty Area path empty? " + new Area().getPathIterator(null).isDone());
              System.out.println("Empty Rect path empty? " + new Rectangle().getPathIterator(null).isDone());
          }
          
          public void paintToPrint() throws PrinterException
          {
              PrinterJob job = PrinterJob.getPrinterJob();
              job.setPrintService(PrintServiceLookup.lookupDefaultPrintService());
              job.setPrintable(this);
              if (job.printDialog()) // Choose PDF or XPS
              {
                  job.print();
              }
          }

          public void paintToImage() throws IOException
          {
              BufferedImage bim = new BufferedImage(596, 842, BufferedImage.TYPE_INT_ARGB);
              Graphics g2d = (Graphics2D) bim.getGraphics();
              
              paint(g2d);
              
              g2d.dispose();
              ImageIO.write(bim, "png", new File("PDFBox4822Clip.png"));
          }

          @Override
          public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException
          {
              if (pageIndex == 0)
              {
                  paint(graphics);

                  return PAGE_EXISTS;
              }
              return NO_SUCH_PAGE;
          }

          private void paint(Graphics g2d)
          {
              Rectangle2D r1 = new Rectangle(11, 74, 540, 750);
              Rectangle2D r2 = new Rectangle(374, 22, 8, 16);
              Area area = new Area(r1);
              area.intersect(new Area(r2));
              g2d.setClip(area); // area is empty
              System.out.println("g2d: " + g2d);
              System.out.println("clip empty? " + g2d.getClip().getPathIterator(null).isDone());
              System.out.println("clip bounds: " + g2d.getClip().getBounds2D());
              g2d.setColor(Color.red);
              g2d.fillRect(0, 0, 1000, 1000);
          }
      }

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      before doing a graphics operation like fill(), do something like this:

      if (graphics.getClip() != null && graphics.getClip().getPathIterator(null).isDone())
      {
          graphics.setClip(new Rectangle());
      }

      This works because "new Rectangle()" does not have an empty path, unlike "new Area()".

      FREQUENCY : always


            prr Philip Race
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated: