You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ti...@apache.org on 2022/05/31 14:11:12 UTC

svn commit: r1901455 - /pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/printing/OpaquePDFRenderer.java

Author: tilman
Date: Tue May 31 14:11:12 2022
New Revision: 1901455

URL: http://svn.apache.org/viewvc?rev=1901455&view=rev
Log:
PDFBOX-5450: add Opaque PDFRenderer example, based on discussion with Tres Finocchiaro on the mailing list

Added:
    pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/printing/OpaquePDFRenderer.java   (with props)

Added: pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/printing/OpaquePDFRenderer.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/printing/OpaquePDFRenderer.java?rev=1901455&view=auto
==============================================================================
--- pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/printing/OpaquePDFRenderer.java (added)
+++ pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/printing/OpaquePDFRenderer.java Tue May 31 14:11:12 2022
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.pdfbox.examples.printing;
+
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.List;
+import javax.print.PrintServiceLookup;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.pdfbox.Loader;
+import org.apache.pdfbox.contentstream.operator.MissingOperandException;
+import org.apache.pdfbox.contentstream.operator.Operator;
+import org.apache.pdfbox.contentstream.operator.OperatorName;
+import org.apache.pdfbox.contentstream.operator.graphics.GraphicsOperatorProcessor;
+import org.apache.pdfbox.cos.COSBase;
+import org.apache.pdfbox.cos.COSName;
+import org.apache.pdfbox.pdmodel.MissingResourceException;
+import org.apache.pdfbox.pdmodel.PDDocument;
+import org.apache.pdfbox.pdmodel.graphics.PDXObject;
+import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;
+import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
+import org.apache.pdfbox.printing.PDFPrintable;
+import org.apache.pdfbox.printing.Scaling;
+import org.apache.pdfbox.rendering.PDFRenderer;
+import org.apache.pdfbox.rendering.PageDrawer;
+import org.apache.pdfbox.rendering.PageDrawerParameters;
+
+/**
+ * PDF documents with transparency groups are sometimes printed slowly and in poor quality, see
+ * <a href="https://issues.apache.org/jira/browse/PDFBOX-4123">PDFBOX-4123</a>. If the transparency
+ * groups aren't really needed (e.g. for most labels), we can use a custom PDFRenderer / PageDrawer
+ * that uses a custom DrawObject class which doesn't call showTransparencyGroup() but only
+ * showForm().
+ * <p>
+ * This OpaquePDFRenderer class object can be passed to the "long" constructor of
+ * {@link PDFPrintable#PDFPrintable(org.apache.pdfbox.pdmodel.PDDocument, org.apache.pdfbox.printing.Scaling, boolean, float, boolean, org.apache.pdfbox.rendering.PDFRenderer)}.
+ *
+ * @author Tilman Hausherr
+ */
+public class OpaquePDFRenderer extends PDFRenderer
+{
+
+    public static void main(String[] args) throws IOException, PrinterException
+    {
+        // PDF from the QZ Tray project, who reported this problem.
+        try (InputStream is = new URL("https://github.com/qzind/tray/files/1749977/test.pdf").openStream();
+             PDDocument doc = Loader.loadPDF(is))
+        {
+            PDFRenderer renderer = new OpaquePDFRenderer(doc);
+            Printable printable = new PDFPrintable(doc, Scaling.SCALE_TO_FIT, false, 0, true, renderer);
+            PrinterJob job = PrinterJob.getPrinterJob();
+            job.setPrintService(PrintServiceLookup.lookupDefaultPrintService());
+            job.setPrintable(printable);
+            if (job.printDialog())
+            {
+                job.print();
+            }
+        }
+    }
+
+    public OpaquePDFRenderer(PDDocument document)
+    {
+        super(document);
+    }
+
+    @Override
+    protected PageDrawer createPageDrawer(PageDrawerParameters parameters) throws IOException
+    {
+        return new OpaquePageDrawer(parameters);
+    }
+
+    private class OpaquePageDrawer extends PageDrawer
+    {
+
+        public OpaquePageDrawer(PageDrawerParameters parameters) throws IOException
+        {
+            super(parameters);
+            addOperator(new OpaqueDrawObject());
+        }
+    }
+
+    // copied from org.apache.pdfbox.contentstream.operator.graphics.DrawObject()
+    // but doesn't call showTransparencyGroup
+    private class OpaqueDrawObject extends GraphicsOperatorProcessor
+    {
+
+        private final Log LOG = LogFactory.getLog(OpaqueDrawObject.class);
+
+        @Override
+        public void process(Operator operator, List<COSBase> operands) throws IOException
+        {
+            if (operands.isEmpty())
+            {
+                throw new MissingOperandException(operator, operands);
+            }
+            COSBase base0 = operands.get(0);
+            if (!(base0 instanceof COSName))
+            {
+                return;
+            }
+            COSName objectName = (COSName) base0;
+            PDXObject xobject = context.getResources().getXObject(objectName);
+
+            if (xobject == null)
+            {
+                throw new MissingResourceException("Missing XObject: " + objectName.getName());
+            }
+            else if (xobject instanceof PDImageXObject)
+            {
+                PDImageXObject image = (PDImageXObject) xobject;
+                context.drawImage(image);
+            }
+            else if (xobject instanceof PDFormXObject)
+            {
+                try
+                {
+                    context.increaseLevel();
+                    if (context.getLevel() > 50)
+                    {
+                        LOG.error("recursion is too deep, skipping form XObject");
+                        return;
+                    }
+                    context.showForm((PDFormXObject) xobject);
+                }
+                finally
+                {
+                    context.decreaseLevel();
+                }
+            }
+        }
+
+        @Override
+        public String getName()
+        {
+            return OperatorName.DRAW_OBJECT;
+        }
+    }
+}

Propchange: pdfbox/trunk/examples/src/main/java/org/apache/pdfbox/examples/printing/OpaquePDFRenderer.java
------------------------------------------------------------------------------
    svn:eol-style = native