uia.pdf.PDFMaker.java Source code

Java tutorial

Introduction

Here is the source code for uia.pdf.PDFMaker.java

Source

/*
 * Copyright 2015 uia.pdf
 *
 * Licensed 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 uia.pdf;

import java.io.File;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.ArrayList;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode;
import org.apache.pdfbox.pdmodel.font.PDFont;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.destination.PDPageFitDestination;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDDocumentOutline;
import org.apache.pdfbox.pdmodel.interactive.documentnavigation.outline.PDOutlineItem;

import uia.pdf.papers.A4Paper;
import uia.pdf.parsers.ValueParserFactory;

/**
 * PDF maker.
 *
 * @author Kan Lin
 *
 */
public class PDFMaker {

    private final PDDocument doc;

    private final ValueParserFactory factory;

    private final PDFont font;

    private PDDocumentOutline docOutline;

    private ArrayList<BookmarkPage> bookmarkPages;

    private ArrayDeque<PDOutlineItem> hierarchyOI;

    private PDOutlineItem lastOI;

    private ArrayList<PDOutlineItem> temp;

    /**
     * Constructor.
     * @param font Font.
     * @throws IOException
     */
    public PDFMaker(PDFont font) throws IOException {
        this.temp = new ArrayList<PDOutlineItem>();
        this.doc = new PDDocument();
        this.font = font;
        this.factory = new ValueParserFactory();

        this.docOutline = new PDDocumentOutline();
        this.doc.getDocumentCatalog().setDocumentOutline(this.docOutline);

        PDOutlineItem rootOI = new PDOutlineItem();
        rootOI.setTitle("All");
        this.docOutline.addLast(rootOI);

        this.hierarchyOI = new ArrayDeque<PDOutlineItem>();
        this.hierarchyOI.push(rootOI);

        this.bookmarkPages = new ArrayList<BookmarkPage>();
    }

    /**
     * Constructor.
     * @param fontFile TTF font file.
     * @throws IOException
     */
    public PDFMaker(File fontFile) throws IOException {
        this.temp = new ArrayList<PDOutlineItem>();
        this.doc = new PDDocument();
        this.font = PDType0Font.load(this.doc, fontFile);
        this.factory = new ValueParserFactory();

        this.docOutline = new PDDocumentOutline();
        this.doc.getDocumentCatalog().setDocumentOutline(this.docOutline);

        PDOutlineItem rootOI = new PDOutlineItem();
        rootOI.setTitle("All");
        this.docOutline.addLast(rootOI);

        this.hierarchyOI = new ArrayDeque<PDOutlineItem>();
        this.hierarchyOI.push(rootOI);

        this.bookmarkPages = new ArrayList<BookmarkPage>();
    }

    /**
     *
     * @return
     */
    public ValueParserFactory getValueParserFactory() {
        return this.factory;
    }

    /**
     * Save
     * @param file PDF file.
     * @throws IOException
     */
    public void save(File file) throws IOException {
        createIndex();
        this.docOutline.openNode();
        this.doc.save(file);
        this.doc.close();
    }

    /**
     * Get document.
     * @return PDF document.
     */
    public PDDocument getDocument() {
        return this.doc;
    }

    /**
     * Get font.
     * @return Font.
     */
    public PDFont getFont() {
        return this.font;
    }

    /**
     * Add bookmark.
     * @param page Page.
     * @param text bookmark text.
     * @throws IOException
     */
    public PDPage addBookmark(ContentView view, PDPage page, String text) throws IOException {
        text = text == null ? "" : text.trim();
        PDPageFitDestination dest = new PDPageFitDestination();
        dest.setPage(page);

        for (PDOutlineItem oi : this.temp) {
            oi.setDestination(dest);
        }

        if (text.trim().length() > 0) {
            this.lastOI = new PDOutlineItem();
            this.lastOI.setDestination(dest);
            this.lastOI.setTitle(text);
            this.hierarchyOI.peek().addLast(this.lastOI);
            this.bookmarkPages.add(new BookmarkPage(text, "" + this.doc.getNumberOfPages()));

            this.temp.add(this.lastOI);
        }

        page = view.drawBookmarks(page, this.temp);
        this.temp.clear();

        return page;
    }

    /**
     * Begin bookmark group.
     */
    public void beginBookmarkGroup() {
        if (this.hierarchyOI.peek() != this.lastOI) {
            this.hierarchyOI.push(this.lastOI);
        }
    }

    /**
     *
     * @param text
     */
    public void beginBookmarkGroup(String text) {
        text = text == null ? "" : text.trim();
        this.lastOI = new PDOutlineItem();
        this.lastOI.setTitle(text);
        this.hierarchyOI.peek().addLast(this.lastOI);
        this.bookmarkPages.add(new BookmarkPage(text, "" + (this.doc.getNumberOfPages() + 1)));
        this.temp.add(this.lastOI);

        this.hierarchyOI.push(this.lastOI);
    }

    /**
     * End bookmark group.
     */
    public void endBookmarkGroup() {
        if (this.hierarchyOI.size() > 1) {
            this.hierarchyOI.pop();
        }
    }

    private void createIndex() throws IOException {
        A4Paper a4 = new A4Paper();

        PDPage page = a4.createPage();
        if (this.doc.getPages().getCount() > 0) {
            this.doc.getPages().insertBefore(page, this.doc.getPage(0));
        } else {
            this.doc.addPage(page);
        }

        PDPageContentStream contentStream = new PDPageContentStream(this.doc, page, AppendMode.APPEND, false,
                false);

        contentStream.setFont(this.font, 16);
        int cw = PDFUtil.getContentWidth("INDEX", this.font, 11);
        contentStream.beginText();
        contentStream.newLineAtOffset(a4.getLeft() + (a4.getDrawableSize().width - cw) / 2, a4.getTop() - 12);
        contentStream.showText("INDEX");
        contentStream.endText();

        contentStream.setFont(this.font, 11);
        contentStream.setLineWidth(0.5f);
        int top = a4.getTop() - 20;
        for (BookmarkPage bp : this.bookmarkPages) {
            if (top <= a4.getBottom()) {
                contentStream.close();

                PDPage nextPage = a4.createPage();
                this.doc.getPages().insertAfter(nextPage, page);
                contentStream = new PDPageContentStream(this.doc, nextPage, AppendMode.APPEND, false, false);
                contentStream.setFont(this.font, 11);

                top = a4.getTop() - 20;
            }

            int cw1 = PDFUtil.getContentWidth(bp.text, this.font, 11);
            int cw2 = PDFUtil.getContentWidth(bp.pageNo, this.font, 11);

            int right = a4.getRight() - 18;
            int w = 4 * (int) Math.ceil((right - (a4.getLeft() + cw1 + 10)) / 4);
            contentStream.setLineDashPattern(new float[] { 1, 3 }, 0);
            contentStream.moveTo(right - w - 1, top - 10);
            contentStream.lineTo(right, top - 10);
            contentStream.stroke();

            contentStream.beginText();
            contentStream.newLineAtOffset(a4.getLeft(), top - 10);
            contentStream.showText(bp.text);
            contentStream.endText();

            contentStream.beginText();
            contentStream.newLineAtOffset(a4.getRight() - cw2, top - 10);
            contentStream.showText(bp.pageNo);
            contentStream.endText();

            top -= 15;
        }

        contentStream.close();
    }

    class BookmarkPage {

        final String text;

        final String pageNo;

        public BookmarkPage(String text, String pageNo) {
            this.text = text;
            this.pageNo = pageNo;
        }
    }
}