]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.export.core/src/org/simantics/export/core/pdf/PageNumbering.java
Merge branch 'feature/funcwrite'
[simantics/platform.git] / bundles / org.simantics.export.core / src / org / simantics / export / core / pdf / PageNumbering.java
1 /*******************************************************************************
2  * Copyright (c) 2017 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     Semantum Oy - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.export.core.pdf;
13
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;
19
20 import org.eclipse.core.runtime.IProgressMonitor;
21 import org.eclipse.core.runtime.SubMonitor;
22
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;
36
37 /**
38  * PDF page numbering related post-processing utilities using iText.
39  * 
40  * @author Tuukka Lehtonen
41  * @since 1.28.0
42  */
43 public class PageNumbering {
44
45         public static enum NumberingFormat {
46                 PAGE_SLASH_TOTAL_PAGES
47         }
48
49         public static enum Position {
50                 BOTTOM_LEFT,
51                 BOTTOM_RIGHT,
52                 TOP_LEFT,
53                 TOP_RIGHT,
54         }
55
56         private static int pageNumberAlignment(Position positioning) {
57                 switch (positioning) {
58                 case BOTTOM_LEFT:
59                 case TOP_LEFT:  return Element.ALIGN_LEFT;
60
61                 case BOTTOM_RIGHT:
62                 case TOP_RIGHT:
63                 default: return Element.ALIGN_RIGHT;
64                 }
65         }
66
67         private static Point2D.Float pageNumberPosition(Position positioning, Rectangle pageSize, Font font) {
68                 switch (positioning) {
69                 case TOP_LEFT:
70                         return new Point2D.Float(12, pageSize.getHeight() - 12 - font.getCalculatedSize()*0.8f);
71                 case TOP_RIGHT:
72                         return new Point2D.Float(pageSize.getWidth() - 12, pageSize.getHeight() - 12 - font.getCalculatedSize()*0.8f);
73                 case BOTTOM_LEFT:
74                         return new Point2D.Float(12, 12);
75                 case BOTTOM_RIGHT: 
76                 default:
77                         return new Point2D.Float(pageSize.getWidth() - 12, 12);
78                 }
79         }
80
81         public static String formatPageNumber(NumberingFormat format, int pageNumber, int totalPages) {
82                 switch (format) {
83                 case PAGE_SLASH_TOTAL_PAGES: return String.format("%d / %d", pageNumber, totalPages);
84                 default:
85                         throw new UnsupportedOperationException("Unsupported numbering format: " + format);
86                 }
87         }
88
89         public static void addPageNumber(
90                         PdfCopy pdfCopy,
91                         PdfReader sourceReader,
92                         int sourcePageNumber,
93                         int currentPageNumber,
94                         int totalPages,
95                         Font font,
96                         Position positioning,
97                         NumberingFormat format)
98                                         throws IOException, BadPdfFormatException
99         {
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);
108                 ps.alterContents();
109                 pdfCopy.addPage(imp);
110         }
111
112         public static void addPageNumbers(
113                         IProgressMonitor monitor,
114                         Path inputFile,
115                         Path outputFile,
116                         Position positioning,
117                         NumberingFormat format,
118                         Font pageNumberFont)
119                                         throws IOException, DocumentException
120         {
121                 PdfReader reader = null;
122                 try {
123                         reader = new PdfReader(inputFile.toString());
124                         int totalPages = reader.getNumberOfPages();
125                         int currentPage = 1;
126
127                         SubMonitor mon = SubMonitor.convert(monitor, totalPages);
128
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);
133                                 document.open();
134                                 try {
135                                         for (int i = 1; i <= totalPages; ++i) {
136                                                 mon.subTask(i + "/" + totalPages);
137                                                 PageNumbering.addPageNumber(pdfCopy, reader, i,
138                                                                 currentPage++, totalPages,
139                                                                 pageNumberFont,
140                                                                 positioning,
141                                                                 format);
142                                         }
143                                 } finally {
144                                         if (document != null && document.isOpen())
145                                                 document.close();
146                                         if (pdfCopy != null)
147                                                 pdfCopy.close();
148                                 }
149                         }
150                 } finally {
151                         if (reader != null)
152                                 reader.close();
153                 }
154
155         }
156
157         public static void addPageNumbers(
158                         IProgressMonitor monitor,
159                         Path inputFile,
160                         Path outputFile,
161                         Position positioning,
162                         NumberingFormat format)
163                                         throws IOException, DocumentException
164         {
165                 addPageNumbers(monitor, inputFile, outputFile, positioning, format, new Font(Font.HELVETICA, 8));
166         }
167
168 }