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

135 阅读3分钟

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

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

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

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

一. 前言

冬奥会开幕式昨日成功举办

首先庆祝首都成为第一个双奥城市. 也给我们的孩子们留下了很多知识点以后要记了.

XDM, 明天就要上班了

假期总是很短暂的, 如果你觉得难熬, 那说明你不是很快乐. 不管快乐不快乐, 要相信上班才是快乐的, 才是我们生活的一大部分. 才能够实现我们白吃白喝在外一年还能够剩下一些 money 回家. 所以兄弟们, 爱上工作吧.

二.正文.

继续详细学习下其他的事件

// 这是一个段落的事件实现类, 主要是做xia'hua'xian
class ParagraphPositions extends PdfPageEventHelper {

    // 这个是在段落渲染之前触发的事件方法
    public void onParagraph(PdfWriter writer, Document pdfDocument, float paragraphPosition) {
        drawLine(writer.getDirectContent(), pdfDocument.left(), pdfDocument.right(), paragraphPosition - 8);
    }
    
    // 这个是在段落渲染之后触发的事件方法
    public void onParagraphEnd(PdfWriter writer, Document pdfDocument, float paragraphPosition)
        drawLine(writer.getDirectContent(), pdfDocument.left(), pdfDocument.right(), paragraphPosition - 5);
    }
    
    // 用以画一条下划线, 
    public void drawLine(PdfContentByte cb, float x1, float x2, float y) {
        // 先移动至 x位置为x1, y位置为y的位置
        cb.moveTo(x1, y);
        // 然后从上边的位置开始划, 划到x位置为x2, y位置还是为y的位置.
        cb.lineTo(x2, y);
        // 完成这一笔
        cb.stroke();
    }
}

上边是我们比较常用到的段落事件的使用, 接下来我们继续学习章节的一些章节事件. 大家都知道当我们在使用Chapter 和 Section 时, 就会自动产生一个目录树, 使用Adobe pdf Reader时, 可以根据章节目录来定位查看相关章节内容. 这个目录树并不能打印, 我们可以使用这个事件扩展来形成可打印的目录树.

我们还是来解读书中的例子吧:

class ChapterSectionTOC extends PdfPageEventHelper {

    // 所有章节 标题
    List titles = new ArrayList<Paragraph>();
    
    // 在章节渲染之前触发
    public void onChapter(PdfWriter writer, Document document, float position, Paragraph title){
        // 添加标题段落内容到 titles
        titles.add( new Paragraph(title.getContent(), FONT[4]));
    }
    
    // 在章节渲染后触发
    public void onChapterEnd(PdfWriter writer, Document document, position) {
        // 画一条线
        drawLine(writer.getDirectContent(), document.left(), document.right(), position - 5);
    }
    
    // 在章节渲染之前触发
    public void onSection(PdfWriter writer, Document document,float position, int depth, Paragraph title) {
        // 添加节的内容
        title = new Paragraph(title.getContent(), FONT[4]);
        // 设置左缩进
        title.setIndentationLeft(18 * depth);
        titles.add(title);
    }
    
    // 在章节渲染之后触发
    public void onSectionEnd(PdfWriter writer, Document document, float position) {
        // 画一条线
        drawLine(writer.getDirectContent(),document.left(), document.right(), position - 3);
    }
    
    public void drawLine(PdfContentByte cb, float x1, float x2, float y) {
        cb.moveTo(x1, y);
        cb.lineTo(x2, y);
        cb.stroke();
    }
}

当我们已经拥有了这个titles以后, 也就是说我们已经将所有的内容添加到了Pdf中, 我们才能开始想办法渲染这些内容, 而页数 也需要处理. 下边是一个简单的处理方式, 其实可以有更好的处理方式, 后边我们再详细说.

// 获取一个新页
document.newPage();
// 获取总页数
int toc = writer.getPageNumber();
// 在新页里边添加所有的title, 当然如果写不完也会添加到一页
for (Paragraph p : event.titles) {
    document.add(p);
}
// 重新获取最后的页码
document.newPage();
// 并获取总页码数
// if (order == null)
//    return pages.size();
int total = writer.reorderPages(null);
// 组装页码数数组, 用以最后reorderPages的参数
int[] order = new int[total];
for (int i = 0; i < total; i++) {
    order[i] = i + toc;
    if (order[i] > total)
        order[i] = order[i] - total;
}
// 按照 i => order[i] 来重新排序页面, 即将后边的目录页都移至最前边
writer.reorderPages(order);
document.close();

这个reorderPages 很好用, 大家可以试下.