1 /*******************************************************************************
2 * Copyright (c) 2017 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Semantum Oy - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.export.core.pdf;
14 import java.awt.geom.Point2D;
15 import java.io.IOException;
16 import java.io.OutputStream;
17 import java.nio.file.Files;
18 import java.nio.file.Path;
20 import org.eclipse.core.runtime.IProgressMonitor;
21 import org.eclipse.core.runtime.SubMonitor;
23 import com.lowagie.text.Document;
24 import com.lowagie.text.DocumentException;
25 import com.lowagie.text.Element;
26 import com.lowagie.text.Font;
27 import com.lowagie.text.Phrase;
28 import com.lowagie.text.Rectangle;
29 import com.lowagie.text.pdf.BadPdfFormatException;
30 import com.lowagie.text.pdf.ColumnText;
31 import com.lowagie.text.pdf.PdfContentByte;
32 import com.lowagie.text.pdf.PdfCopy;
33 import com.lowagie.text.pdf.PdfImportedPage;
34 import com.lowagie.text.pdf.PdfReader;
35 import com.lowagie.text.pdf.PdfWriter;
38 * PDF page numbering related post-processing utilities using iText.
40 * @author Tuukka Lehtonen
43 public class PageNumbering {
45 public static enum NumberingFormat {
46 PAGE_SLASH_TOTAL_PAGES
49 public static enum Position {
56 private static int pageNumberAlignment(Position positioning) {
57 switch (positioning) {
59 case TOP_LEFT: return Element.ALIGN_LEFT;
63 default: return Element.ALIGN_RIGHT;
67 private static Point2D.Float pageNumberPosition(Position positioning, Rectangle pageSize, Font font) {
68 switch (positioning) {
70 return new Point2D.Float(12, pageSize.getHeight() - 12 - font.getCalculatedSize()*0.8f);
72 return new Point2D.Float(pageSize.getWidth() - 12, pageSize.getHeight() - 12 - font.getCalculatedSize()*0.8f);
74 return new Point2D.Float(12, 12);
77 return new Point2D.Float(pageSize.getWidth() - 12, 12);
81 public static String formatPageNumber(NumberingFormat format, int pageNumber, int totalPages) {
83 case PAGE_SLASH_TOTAL_PAGES: return String.format("%d / %d", pageNumber, totalPages);
85 throw new UnsupportedOperationException("Unsupported numbering format: " + format);
89 public static void addPageNumber(
91 PdfReader sourceReader,
93 int currentPageNumber,
97 NumberingFormat format)
98 throws IOException, BadPdfFormatException
100 Rectangle pageSize = sourceReader.getPageSizeWithRotation(sourcePageNumber);
101 PdfImportedPage imp = pdfCopy.getImportedPage(sourceReader, sourcePageNumber);
102 PdfCopy.PageStamp ps = pdfCopy.createPageStamp(imp);
103 PdfContentByte over = ps.getOverContent();
104 String text = formatPageNumber(format, currentPageNumber, totalPages);
105 Point2D.Float pos = pageNumberPosition(positioning, pageSize, font);
106 int alignment = pageNumberAlignment(positioning);
107 ColumnText.showTextAligned(over, alignment, new Phrase(text, font), pos.x, pos.y, 0);
109 pdfCopy.addPage(imp);
112 public static void addPageNumbers(
113 IProgressMonitor monitor,
116 Position positioning,
117 NumberingFormat format,
119 throws IOException, DocumentException
121 PdfReader reader = null;
123 reader = new PdfReader(inputFile.toString());
124 int totalPages = reader.getNumberOfPages();
127 SubMonitor mon = SubMonitor.convert(monitor, totalPages);
129 try (OutputStream fos = Files.newOutputStream(outputFile)) {
130 Document document = new Document();
131 PdfCopy pdfCopy = new PdfCopy(document, fos);
132 pdfCopy.setPdfVersion(PdfWriter.PDF_VERSION_1_7);
135 for (int i = 1; i <= totalPages; ++i) {
136 mon.subTask(i + "/" + totalPages);
137 PageNumbering.addPageNumber(pdfCopy, reader, i,
138 currentPage++, totalPages,
144 if (document != null && document.isOpen())
157 public static void addPageNumbers(
158 IProgressMonitor monitor,
161 Position positioning,
162 NumberingFormat format)
163 throws IOException, DocumentException
165 addPageNumbers(monitor, inputFile, outputFile, positioning, format, new Font(Font.HELVETICA, 8));