【问题标题】:PDF Renderer Causing Divide By ZeroPDF 渲染器导致除以零
【发布时间】:2013-12-12 15:07:40
【问题描述】:

我正在尝试使用 java.awt.print 包打印 PDF 文档。为此,我创建了一个 Printable 对象,该对象对文件进行了简短的转换(该技术源自前一段时间的不同主题)。

private static void printDocument(File finalFile, PrintService printer, String name) throws PrinterException {

    System.out.println(String.format("Starting %s document", name));

    FileInputStream fileInputStream = null;
    try {

        fileInputStream = new FileInputStream(finalFile);
        byte[] pdfContent = new byte[fileInputStream.available()];
        fileInputStream.read(pdfContent, 0, fileInputStream.available());
        ByteBuffer buffer = ByteBuffer.wrap(pdfContent);
        final PDFFile pdfFile = new PDFFile(buffer);

        //Create Printable object in preparation for printing
        Printable printable = new Printable() {

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

                int pagenum = pageIndex + 1;
                if ((pagenum >= 1) && (pagenum <= pdfFile.getNumPages())) {

                    Graphics2D graphics2D = (Graphics2D) graphics;
                    PDFPage page = pdfFile.getPage(pagenum);

                    Rectangle imageArea = new Rectangle((int) pageFormat.getImageableX(), (int) pageFormat.getImageableY(),
                            (int) pageFormat.getImageableWidth(), (int) pageFormat.getImageableHeight());

                    graphics2D.translate(0, 0);
                    PDFRenderer pdfRenderer = new PDFRenderer(page, graphics2D, imageArea, null, null);

                    try {
                        page.waitForFinish();
                        pdfRenderer.run();
                    }
                    catch (InterruptedException e) {
                        e.printStackTrace();
                        throw new PrinterException("Oh noes!");
                    }
                    return PAGE_EXISTS;
                }
                else {
                    return NO_SUCH_PAGE;
                }
            }
        };

        PrinterJob printJob = PrinterJob.getPrinterJob();

        printJob.setPrintService(printer);

        PageFormat pageFormat = printJob.defaultPage();
        Book book = new Book();
        book.append(printable, pageFormat, pdfFile.getNumPages());
        printJob.setPageable(book);

        Paper paper = new Paper();
        paper.setImageableArea(0, 0, paper.getWidth(), paper.getHeight());
        pageFormat.setPaper(paper);


        PrintRequestAttributeSet pset = new HashPrintRequestAttributeSet();
        printJob.setJobName(finalFile.getName() +
                "|" + String.valueOf(1) + 
                "|" + ("T"));

        printJob.print(pset);
    }

    catch (Exception e) {
        e.printStackTrace();
        throw new PrinterException();
    }
    finally {
        if (fileInputStream != null) {
            try {
                fileInputStream.close();
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    System.out.println(String.format("Finished %s document", name));
}

PDF 文件的某些特定案例对这个转换过程反应不佳,在 pdfRenderer.run(); 行失败此堆栈跟踪:

java.lang.ArithmeticException: / by zero
    at com.sun.pdfview.pattern.PatternType1$Type1PaintContext.getRaster(PatternType1.java:354)
    at sun.java2d.pipe.AlphaPaintPipe.renderPathTile(AlphaPaintPipe.java:106)
    at sun.java2d.pipe.DuctusShapeRenderer.renderTiles(DuctusShapeRenderer.java:147)
    at sun.java2d.pipe.DuctusShapeRenderer.renderPath(DuctusShapeRenderer.java:100)
    at sun.java2d.pipe.DuctusShapeRenderer.fill(DuctusShapeRenderer.java:50)
    at sun.java2d.pipe.PixelToParallelogramConverter.fill(PixelToParallelogramConverter.java:146)
    at sun.java2d.pipe.ValidatePipe.fill(ValidatePipe.java:142)
    at sun.java2d.SunGraphics2D.fill(SunGraphics2D.java:2376)
    at sun.print.ProxyGraphics2D.fill(ProxyGraphics2D.java:1381)
    at com.sun.pdfview.pattern.PatternType1$TilingPatternPaint.fill(PatternType1.java:278)
    at com.sun.pdfview.PDFRenderer.fill(PDFRenderer.java:261)
    at com.sun.pdfview.PDFShapeCmd.execute(PDFShapeCmd.java:77)
    at com.sun.pdfview.PDFRenderer.iterate(PDFRenderer.java:570)
    at com.sun.pdfview.BaseWatchable.run(BaseWatchable.java:101)
    at **MYFILEHERE**

这会导致文件中途失败,并导致文件只打印到一半,甚至在文本行的中心停止。

这个错误的原因是什么?它发生在渲染过程中的低级别,处理单个形状操作,我不得不相信它超出了我的控制范围和。 有没有办法让我的进程绕过它可能正在努力处理的损坏数据并继续完整呈现文档?

【问题讨论】:

  • 这里发生了什么? PatternType1.java:278PDFRenderer.java:261
  • 获取更多数据的建议:在代码中捕获异常。从 catch 块中,将缓冲区的内容转储到磁盘文件,然后在 pdf 阅读程序中打开它。另外,您确定您一直在读取整个输入文件吗?
  • @Brian 我想我不知道。那是 com.sun 代码。
  • 很难说。它可能在您的代码中的某个地方,但您没有向我们展示代码中堆栈异常会显示的行。
  • @Brian 哇,实际上,你是对的! PDFRenderer 不是来自核心 Sun 的 Java 包,而是取自这里的一个项目:java.net/projects/pdf-renderer/sources/svn/show/trunk/src/com/…。这改变了一切!谢谢。

标签: java pdf printing awt


【解决方案1】:

事实证明,正在执行的代码不是 Sun 的 Java 官方代码的一部分,正如 com.sun 包名称所暗示的那样,而是一个单独的项目强>位于here。代码是开源的,我可以查看它,修改this文件,并轻松地为自己构建一个新的jar。如果可能的话,我也会尝试为项目贡献我的修复。

解决方法只是添加一个检查以防止上述被零除错误。

原码:

xloc %= useXStep;
yloc %= useYStep;

固定代码:

if (xstep != 0)
    xloc %= useXStep;
if (ystep != 0)
    yloc %= useYStep;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-17
    • 1970-01-01
    • 2016-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多