[更文挑战]iText番盘-PDF神器-11

244 阅读3分钟

「这是我参与2022首次更文挑战的第11天,活动详情查看:2022首次更文挑战

PDF神器iText英文版翻译与学习

作者: 薛大郎.
英文原版:iText in Action 2nd Edition.pdf

坚持. 分享. 成长. 利他 !

一. 前言

人家的总结真是总结, 自己的总结也只是总结

刚看完小傅哥の总结我觉得我没必要总结了,因为人家的总结真的是总结. 但是我们自己的总结还是要做, 想想自己到底进步了吗, 想想我们是否应该怎样改变下, 才能不枉时光, 毕竟我们的征途是星辰大海, 即使你才刚出发, 坚信通往成功的路上就如考驾照的路上一样, 与年龄无关, 与背景无关, 只需要你努力了, 收获就有了. 而且有小傅哥这样的优秀博主在鼓励着大家.

二.正文.

5.2 Image和印章对象PdfTemplate

当想将同一个图片添加到同一个Pdf文件中时, 请使用同一个图片的实例. 因为在正常情况下,图像的位和字节存储在单独的存储空间中, 即PDF文件中的流对象。而包含此类图像的页面也就是此外部图像对象这样的对象也称为XObject。有很多种XObject, 其中我们用的最多的莫过于 Image和Form XObject, 比如当我们想建立一个PDF文件的模板, 只是向当中添加少量的文字的时候, 我们更多的实战方案不是需要使用iText编码所有的文字和内容, 而是使用iText复制现成的带有Form表单的Pdf文件模板, 然后将form表单的字段KEY-VALUE填充到Pdf的复制文件中, 并生成即可.

这里我们先讲一下Image XObject

    // 从自定义的资源中获取一个Image的实例
    Image img = Image.getInstance(RESOURCE);
    // 计算并设置图片的绝对位置 
    img.setAbsolutePosition((PageSize.POSTCARD.getWidth() - img.getScaledWidth()) / 2,
        (PageSize.POSTCARD.getHeight() - img.getScaledHeight()) / 2);
    // 获取的是DirectContentByte的实例, 即将图片添加到了所有内容的最顶层的layer中.
    writer.getDirectContent().addImage(img);
    // 添加一段文字
    Paragraph p = new Paragraph("Foobar Text", new Font(FontFamily.HELVETICA, 22));
    // 设置水平居中对齐
    p.setAlignment(Element.ALIGN_CENTER);
    // 添加到文档中
    document.add(p);

那么这样一来我们只会看到图片看不到Foobar Text文字了. 将Image的实例多次使用这个并不难. 主要今天的讲解是下边这个PdfTemplate

PdfTemplate是PdfContentByte的子类, 源码中注释为 Implements the form XObject.,即也是Form XObject的一种实现, 除了这种实现还有AcroFormXFA forms, 最常用的还是PdfTemplate和AcroForm.

这个最典型的例子还是iText in Action中电影胶卷的例子:

    // 还是获取的最上边的一层 来填充内容
    PdfContentByte canvas = writer.getDirectContent();
    // 创建一个 宽595, 高84.2的一个胶卷 PdfTemplate实例
    PdfTemplate celluloid = canvas.createTemplate(595, 84.2f);
    // 在胶卷中设置一个矩形, 起点x轴为8,起点y轴为8,宽度为579, 高度为68
    // 宽度为什么设置为 579, 是因为两边都留了8个单位的宽度,即 595 - (8 * 2) = 579;
    celluloid.rectangle(8, 8, 579, 68);
    for (float f = 8.25f; f < 581; f+= 6.5f) {
        // 添加胶片中的上下两个圆边小矩形.
        celluloid.roundRectangle(f, 8.5f, 6, 3, 1.5f);
        celluloid.roundRectangle(f, 72.5f, 6, 3, 1.5f);
    }
    // 填充颜色 0(黑色)和 1(白色)之间的值
    celluloid.setGrayFill(0.1f);
    // 填充路径,使用奇偶规则确定要填充的区域。 即1-2填充, 2-3不填充 就形成了胶卷图像.
    celluloid.eoFill();
    writer.releaseTemplate(celluloid);

    // 一页添加10个胶卷Template
    for (int i = 0; i < 10; i++) {
        canvas.addTemplate(celluloid, 0, i * 84.2f);
    }
    // 获取所有的电影.
    List movies = PojoFactory.getMovies(connection);
    Image img;
    float x = 11.5f;
    float y = 769.7f;
    // 从上至下, 从左到右开始添加每个电影的海报. 
    for (Movie movie : movies) {
        img = Image.getInstance(String.format(RESOURCE, movie.getImdb()));
        img.scaleToFit(1000, 60);
        img.setAbsolutePosition(x + (45 - img.getScaledWidth()) / 2, y);
        canvas.addImage(img);
        x += 48;
        if (x > 578) {
            x = 11.5f;
            y -= 84.2f;
        }
    }

效果图: 整个过程需要耐心的计算各个元素的x,y轴的起点和宽度才能使得最后的结果美观. 完全就是数学和iText实现的美工UI工作. 1643434736(1).png