-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.modeling.ui.pdf;\r
-\r
-import java.io.FileNotFoundException;\r
-import java.io.FileOutputStream;\r
-import java.security.Security;\r
-import java.util.Collection;\r
-import java.util.concurrent.atomic.AtomicBoolean;\r
-\r
-import org.eclipse.core.runtime.IProduct;\r
-import org.eclipse.core.runtime.IProgressMonitor;\r
-import org.eclipse.core.runtime.OperationCanceledException;\r
-import org.eclipse.core.runtime.Platform;\r
-import org.eclipse.core.runtime.SubMonitor;\r
-import org.simantics.db.RequestProcessor;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.Session;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.layer0.util.SessionGarbageCollection;\r
-import org.simantics.db.management.ISessionContext;\r
-import org.simantics.document.DocumentSettings;\r
-import org.simantics.document.DocumentUtils;\r
-import org.simantics.export.core.pdf.ServiceBasedPdfExportPageEvent;\r
-import org.simantics.modeling.requests.CollectionRequest;\r
-import org.simantics.modeling.requests.CollectionResult;\r
-import org.simantics.modeling.requests.Node;\r
-import org.simantics.modeling.ui.preferences.DiagramPreferenceUtil;\r
-import org.simantics.ui.jobs.SessionGarbageCollectorJob;\r
-import org.simantics.utils.page.PageDesc;\r
-import org.simantics.utils.page.PageOrientation;\r
-import org.simantics.utils.threads.WorkerThread;\r
-\r
-import com.kitfox.svg.SVGCache;\r
-import com.lowagie.text.Document;\r
-import com.lowagie.text.DocumentException;\r
-import com.lowagie.text.FontFactory;\r
-import com.lowagie.text.PageSize;\r
-import com.lowagie.text.Rectangle;\r
-import com.lowagie.text.pdf.DefaultFontMapper;\r
-import com.lowagie.text.pdf.PdfBoolean;\r
-import com.lowagie.text.pdf.PdfContentByte;\r
-import com.lowagie.text.pdf.PdfName;\r
-import com.lowagie.text.pdf.PdfTemplate;\r
-import com.lowagie.text.pdf.PdfWriter;\r
-\r
-public class DiagramPrinter {\r
-\r
- public static CollectionResult browse(IProgressMonitor monitor, RequestProcessor processor, Resource[] input) throws DatabaseException {\r
- final CollectionResult result = processor.syncRequest(new CollectionRequest(monitor, DiagramPreferenceUtil.getDefaultPreferences().getCompletePageDesc(), input));\r
- return result;\r
- }\r
-\r
- private static final AtomicBoolean fontFactoryInitialized = new AtomicBoolean();\r
-\r
- /**\r
- * @param monitor the progress monitor to use for reporting progress to the\r
- * user. It is the caller's responsibility to call done() on the\r
- * given monitor. Accepts <code>null</code>, indicating that no\r
- * progress should be reported and that the operation cannot be\r
- * cancelled.\r
- * \r
- * @param exportPath\r
- * @param flattenedNodes\r
- * @param sessionContext\r
- * @throws DocumentException\r
- * @throws FileNotFoundException\r
- */\r
- public static void printToPdf(\r
- IProgressMonitor monitor, \r
- PDFExportPlan exportPlan, \r
- String exportPath, \r
- Collection<Node> flattenedNodes,\r
- ISessionContext sessionContext) \r
- throws PdfException {\r
- Collection<Node> flattened = flattenedNodes;\r
-\r
- SubMonitor progress = SubMonitor.convert(monitor, "Export to PDF", flattened.size() * 2);\r
-\r
- WorkerThread workerThread = new WorkerThread("Diagram PDF Painter");\r
- workerThread.start();\r
-\r
- PdfWriter writer = null;\r
- Document document = null;\r
-\r
- try {\r
- progress.subTask("Loading system fonts");\r
- DefaultFontMapper mapper = new DefaultFontMapper();\r
- if (fontFactoryInitialized.compareAndSet(false, true)) {\r
- // Only register directories once.\r
- FontFactory.registerDirectories();\r
- }\r
-\r
- SessionGarbageCollectorJob.getInstance().setEnabled(false);\r
-\r
-\r
- boolean first = true; \r
- int i = 0;\r
- for (Node d : flattened) {\r
- ++i;\r
- \r
- //System.out.println("PAGE DESC: " + d.getPageDesc());\r
- //System.out.println("PAGE SIZE: " + pageSize);\r
-\r
- Rectangle pageSize = toPageSize(d.getPageDesc());\r
- if (writer == null) {\r
- document = new Document(pageSize);\r
- writer = PdfWriter.getInstance(document, new FileOutputStream(exportPath));\r
- writer.setPdfVersion(PdfWriter.PDF_VERSION_1_7);\r
- writer.setPageEvent(new ServiceBasedPdfExportPageEvent());\r
- if ( exportPlan.attachTG ) {\r
- writer.addViewerPreference(PdfName.USEATTACHMENTS, PdfBoolean.PDFTRUE);\r
- }\r
- \r
- String creator = getCreator();\r
- document.addCreator(creator);\r
-\r
- /*\r
- File keystoreFile = new File("c:\\0009278.p12");\r
- String password = "ka7GfzI9Oq";\r
-\r
- try {\r
- KeyStore ks = KeyStore.getInstance("pkcs12");\r
- ks.load(new FileInputStream(keystoreFile), password.toCharArray());\r
- List<String> aliases = Collections.list(ks.aliases());\r
- String alias = aliases.get(0);\r
- PrivateKey key = (PrivateKey)ks.getKey(alias, password.toCharArray());\r
- Certificate[] chain = ks.getCertificateChain(alias);\r
- int permission = PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING|PdfWriter.ALLOW_COPY|PdfWriter.ALLOW_ASSEMBLY;\r
- \r
- PdfEncryption crypto = new PdfEncryption();\r
- //for (Certificate c : chain) crypto.addRecipient(c, permission);\r
- //crypto.addRecipient(chain[2], permission);\r
- crypto.setCryptoMode(PdfWriter.ENCRYPTION_AES_128, 0);\r
- crypto.setupByEncryptionKey(key.getEncoded(), key.getEncoded().length*8);\r
- crypto.getEncryptionDictionary();\r
- \r
- \r
- } catch (Exception e) {\r
- e.printStackTrace();\r
- }*/\r
- \r
- /*\r
- writer.setEncryption(\r
- new Certificate[] {}, \r
- new int[] {PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING}, \r
- PdfWriter.STANDARD_ENCRYPTION_128);\r
- */\r
- //writer.setEncryption(PdfWriter.STANDARD_ENCRYPTION_128, "", "password", PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING|PdfWriter.ALLOW_COPY|PdfWriter.ALLOW_ASSEMBLY);\r
- \r
- \r
-// PdfName companyName = new PdfName("SMTC"); \r
-// PdfDeveloperExtension ext = new PdfDeveloperExtension(companyName, PdfWriter.PDF_VERSION_1_7, 3);\r
-// writer.addDeveloperExtension( ext );\r
- \r
- document.open();\r
- }\r
-\r
- if (!first) {\r
- document.setPageSize(pageSize);\r
- document.newPage();\r
- }\r
-\r
- /*\r
- /// ATTACHMENTS - TG ///\r
- byte[] attachment = null;\r
- if ( exportPlan.attachTG && !d.getDefiningResources().isEmpty() ) \r
- try {\r
- PdfDictionary fileParameter = new PdfDictionary();\r
-\r
- {\r
- final Resource composite = d.getDefiningResources().iterator().next(); \r
- final Session session = exportPlan.sessionContext.getSession();\r
- \r
- SimanticsClipboard clipboard = session.syncRequest(new Read<SimanticsClipboard>() {\r
- @Override\r
- public SimanticsClipboard perform(ReadGraph graph) throws DatabaseException {\r
- CopyHandler ch = graph.adapt(composite, CopyHandler.class);\r
- SimanticsClipboardImpl clipboard = new SimanticsClipboardImpl();\r
- ch.copyToClipboard(graph, clipboard);\r
- return clipboard;\r
- }\r
- });\r
- for (Set<Representation> object : clipboard.getContents()) {\r
- TransferableGraph1 tg = ClipboardUtils.accept(object, SimanticsKeys.KEY_TRANSFERABLE_GRAPH);\r
- String filename = d.getName()+".diagram";\r
- try {\r
- byte[] data = DataContainers.writeFile( \r
- new DataContainer("aprosDiagram", 1, new Variant(TransferableGraph1.BINDING, tg))\r
- );\r
- PdfFileSpecification fs = PdfFileSpecification.fileEmbedded(\r
- writer, \r
- "/Diagram", filename, data, true, "application/simantics/diagram", \r
- fileParameter);\r
- writer.addFileAttachment(d.getName()+".diagram", fs);\r
- } catch ( NullPointerException npe ) {\r
- throw new PdfException("Experiment must be activated to export attachments"+npe.getMessage(), npe);\r
- }\r
- }\r
- }\r
-\r
- } catch (DatabaseException e) {\r
- e.printStackTrace();\r
- } catch (IOException e) {\r
- e.printStackTrace();\r
- }\r
- */\r
- //////////////////////////\r
- \r
- String diagramName = formDiagramName(d, true);\r
- String subTask = "Page (" + i + "/" + flattened.size() + "): " + diagramName;\r
-\r
- Resource diagram = d.getDiagramResource();\r
- if (diagram == null) {\r
- // No diagram, skip page.\r
- subTask += " skipped, no diagram.";\r
- System.out.println(subTask);\r
- continue;\r
- }\r
-\r
- System.out.println(subTask);\r
- progress.subTask(subTask);\r
-\r
- try {\r
- PDFPainter.render(workerThread, sessionContext, exportPlan, d, writer, mapper,\r
- pageSize, d.getPageDesc(), exportPlan.fitContentToPageMargins, 10000);\r
- } catch (InterruptedException e) {\r
- e.printStackTrace();\r
- } catch (DatabaseException e) {\r
- e.printStackTrace();\r
- }\r
-\r
- // Paint diagram path/name on the page\r
- // TODO: remove this hard coded diagram name printing and\r
- // replace it with a page templates that is loaded along with\r
- // the rest of the diagram\r
-\r
- int w = (int) pageSize.getWidth();\r
- int h = (int) pageSize.getHeight();\r
-\r
- // Write Page Number\r
- PdfContentByte cb = writer.getDirectContent();\r
-\r
-// PdfTemplate tp = cb.createTemplate(w, h);\r
-// Graphics2D g2d = tp.createGraphics(w, h, mapper);\r
-// g2d.setColor(Color.black);\r
-// java.awt.Font thisFont = new java.awt.Font("Arial", java.awt.Font.ITALIC, 10);\r
-// g2d.setFont(thisFont);\r
-// FontMetrics metrics = g2d.getFontMetrics();\r
-// int width = metrics.stringWidth(diagramName);\r
-// g2d.drawString(diagramName, (w - width) / 2, document.getPageSize().getHeight() - PageDesc.toPoints(5));\r
-// g2d.dispose();\r
-// cb.addTemplate(tp, 0, 0);\r
-\r
- /// ATTACHMENTS - Write WIKI ///\r
- if ( exportPlan.attachWiki && !d.getDefiningResources().isEmpty() ) {\r
- final Session session = exportPlan.sessionContext.getSession();\r
- Resource composite = d.getDefiningResources().iterator().next();\r
- DocumentUtils du = new DocumentUtils();\r
- StringBuilder wiki = new StringBuilder();\r
- StringBuilder css = new StringBuilder();\r
- du.getDocumentWikiTextRecursive(session, composite, wiki, css);\r
- DocumentSettings settings = du.getDocumentSettings(session, composite);\r
- PdfTemplate tp_ = cb.createTemplate(w, h);\r
- if ( wiki.length()>0 ) {\r
- String wikiText = wiki.toString();\r
- String cssText = css.toString();\r
- du.print(session, composite, wikiText, cssText, settings, tp_.getPdfWriter(), document);\r
- }\r
- cb.addTemplate(tp_, 0, 0);\r
- }\r
- //////////////////////////\r
-\r
- progress.worked(1);\r
- first = false;\r
-\r
- if (progress.isCanceled())\r
- throw new OperationCanceledException();\r
-\r
- System.out.println("GC");\r
- SVGCache.getSVGUniverse().clearUnreferenced();\r
- SessionGarbageCollection.gc(null, sessionContext.getSession(), true, null);\r
- System.gc();\r
- System.out.println("GC finished");\r
- progress.worked(1);\r
- }\r
- } catch (DatabaseException e) {\r
- throw new PdfException(e);\r
- } catch (FileNotFoundException e) {\r
- throw new PdfException(e);\r
- } catch (DocumentException e) {\r
- throw new PdfException(e);\r
- } finally {\r
- workerThread.stopDispatchingEvents(true);\r
- System.out.println("closing document");\r
- try {\r
- if ( document!=null ) document.close();\r
- if ( writer!=null ) writer.close();\r
- } catch(RuntimeException e) {\r
- e.printStackTrace();\r
- }\r
- System.out.println("document closed");\r
- SessionGarbageCollectorJob.getInstance().setEnabled(true).scheduleAfterQuietTime();\r
- }\r
- }\r
-\r
- public static Rectangle toPageSize(PageDesc pageDesc) {\r
- String arg = PageDesc.toPoints(pageDesc.getWidth()) + " " + PageDesc.toPoints(pageDesc.getHeight());\r
- Rectangle r = PageSize.getRectangle(arg);\r
-\r
- if (PageOrientation.Landscape == pageDesc.getOrientation())\r
- r = r.rotate();\r
-\r
- // Disable inherent borders from the PDF writer.\r
- r.setBorder(0);\r
-\r
- return r;\r
- }\r
-\r
- public static String formDiagramName(Node node, boolean parents) {\r
- Node d = node;\r
- String ret = d.getName();\r
- if (parents) {\r
- while (d.getParent() != null) {\r
- d = d.getParent();\r
- ret = d.getName() + " / " + ret;\r
- }\r
- }\r
-// String[] pg = node.getPartOfGroups();\r
-// if (pg.length > 0)\r
-// ret += " [" + EString.implode(pg, " / ") + " / " + node.getName() + "]";\r
- return ret;\r
- }\r
-\r
- public static String getCreator() {\r
- String creator = null;\r
- IProduct product = Platform.getProduct();\r
- if (product != null) {\r
- creator = product.getDescription();\r
- if (creator == null) {\r
- creator = product.getName();\r
- }\r
- }\r
- if (creator == null) {\r
- creator = "Simantics";\r
- }\r
- return creator;\r
- }\r
-\r
- static {\r
- Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());\r
- }\r
-\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2017 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ * Semantum Oy - (#7084) refactoring, page numbering support
+ *******************************************************************************/
+package org.simantics.modeling.ui.pdf;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.Security;
+import java.util.Collection;
+
+import org.eclipse.core.runtime.IProduct;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.SubMonitor;
+import org.simantics.db.RequestProcessor;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.util.SessionGarbageCollection;
+import org.simantics.document.DocumentSettings;
+import org.simantics.document.DocumentUtils;
+import org.simantics.export.core.pdf.FontMapping;
+import org.simantics.export.core.pdf.PageNumbering;
+import org.simantics.export.core.pdf.ServiceBasedPdfExportPageEvent;
+import org.simantics.modeling.requests.CollectionRequest;
+import org.simantics.modeling.requests.CollectionResult;
+import org.simantics.modeling.requests.Node;
+import org.simantics.modeling.ui.preferences.DiagramPreferenceUtil;
+import org.simantics.ui.jobs.SessionGarbageCollectorJob;
+import org.simantics.utils.page.PageDesc;
+import org.simantics.utils.page.PageOrientation;
+import org.simantics.utils.threads.WorkerThread;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.kitfox.svg.SVGCache;
+import com.lowagie.text.Document;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.ExceptionConverter;
+import com.lowagie.text.PageSize;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.pdf.FontMapper;
+import com.lowagie.text.pdf.PdfBoolean;
+import com.lowagie.text.pdf.PdfContentByte;
+import com.lowagie.text.pdf.PdfName;
+import com.lowagie.text.pdf.PdfTemplate;
+import com.lowagie.text.pdf.PdfWriter;
+
+/**
+ * @author Tuukka Lehtonen
+ */
+public class DiagramPrinter {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DiagramPrinter.class);
+
+ public static CollectionResult browse(IProgressMonitor monitor, RequestProcessor processor, Resource[] input) throws DatabaseException {
+ final CollectionResult result = processor.syncRequest(new CollectionRequest(monitor, DiagramPreferenceUtil.getDefaultPreferences().getCompletePageDesc(), input));
+ return result;
+ }
+
+ /**
+ * @param monitor the progress monitor to use for reporting progress to the
+ * user. It is the caller's responsibility to call done() on the
+ * given monitor. Accepts <code>null</code>, indicating that no
+ * progress should be reported and that the operation cannot be
+ * cancelled.
+ *
+ * @param exportPath
+ * @param flattenedNodes
+ * @param sessionContext
+ * @throws DocumentException
+ * @throws FileNotFoundException
+ */
+ public static void printToPdf(
+ IProgressMonitor monitor,
+ PDFExportPlan exportPlan,
+ String exportPath,
+ Collection<Node> flattenedNodes)
+ throws PdfException
+ {
+ if (!exportPlan.addPageNumbers) {
+ printToPdfWithoutPageNumbers(monitor, exportPlan, exportPath, flattenedNodes);
+ } else {
+ SubMonitor mon = SubMonitor.convert(monitor, "Export to PDF", flattenedNodes.size() * 3);
+
+ Path tempOutput = Paths.get(exportPath + ".tmp");
+ Path finalOutput = Paths.get(exportPath);
+
+ int exportedPages = printToPdfWithoutPageNumbers(
+ mon.newChild(flattenedNodes.size() * 2, SubMonitor.SUPPRESS_NONE),
+ exportPlan,
+ tempOutput.toString(),
+ flattenedNodes);
+
+ if (mon.isCanceled()) {
+ tempOutput.toFile().delete();
+ throw new OperationCanceledException();
+ }
+
+ try {
+ mon.setWorkRemaining(exportedPages);
+ mon.setTaskName("Numbering output pages");
+ mon.subTask("");
+ PageNumbering.addPageNumbers(
+ mon.newChild(flattenedNodes.size()),
+ tempOutput, finalOutput,
+ exportPlan.pageNumberPosition,
+ exportPlan.pageNumberFormat);
+ } catch (IOException | DocumentException | ExceptionConverter e) {
+ throw new PdfException(e);
+ } finally {
+ tempOutput.toFile().delete();
+ }
+ }
+ }
+
+ /**
+ * @param monitor the progress monitor to use for reporting progress to the
+ * user. It is the caller's responsibility to call done() on the
+ * given monitor. Accepts <code>null</code>, indicating that no
+ * progress should be reported and that the operation cannot be
+ * cancelled.
+ *
+ * @param exportPath
+ * @param flattenedNodes
+ * @return number of pages printed
+ * @throws PdfException
+ * @since 1.28.0
+ */
+ public static int printToPdfWithoutPageNumbers(
+ IProgressMonitor monitor,
+ PDFExportPlan exportPlan,
+ String exportPath,
+ Collection<Node> flattenedNodes)
+ throws PdfException
+ {
+ SubMonitor progress = SubMonitor.convert(monitor, "Export to PDF", flattenedNodes.size() * 2);
+
+ WorkerThread workerThread = new WorkerThread("Diagram PDF Painter");
+ workerThread.start();
+
+ PdfWriter writer = null;
+ Document document = null;
+ int exportedPages = 0;
+
+ try {
+ progress.subTask("Loading system fonts");
+ FontMapper mapper = FontMapping.defaultFontMapper();
+
+ SessionGarbageCollectorJob.getInstance().setEnabled(false);
+
+ boolean first = true;
+ int i = 0;
+ for (Node d : flattenedNodes) {
+ ++i;
+
+ //System.out.println("PAGE DESC: " + d.getPageDesc());
+ //System.out.println("PAGE SIZE: " + pageSize);
+
+ Rectangle pageSize = toPageSize(d.getPageDesc());
+ if (writer == null) {
+ document = new Document(pageSize);
+ writer = PdfWriter.getInstance(document, new FileOutputStream(exportPath));
+ writer.setPdfVersion(PdfWriter.PDF_VERSION_1_7);
+ writer.setPageEvent(new ServiceBasedPdfExportPageEvent());
+ if ( exportPlan.attachTG ) {
+ writer.addViewerPreference(PdfName.USEATTACHMENTS, PdfBoolean.PDFTRUE);
+ }
+
+ String creator = getCreator();
+ document.addCreator(creator);
+
+ /*
+ File keystoreFile = new File("c:\\0009278.p12");
+ String password = "ka7GfzI9Oq";
+
+ try {
+ KeyStore ks = KeyStore.getInstance("pkcs12");
+ ks.load(new FileInputStream(keystoreFile), password.toCharArray());
+ List<String> aliases = Collections.list(ks.aliases());
+ String alias = aliases.get(0);
+ PrivateKey key = (PrivateKey)ks.getKey(alias, password.toCharArray());
+ Certificate[] chain = ks.getCertificateChain(alias);
+ int permission = PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING|PdfWriter.ALLOW_COPY|PdfWriter.ALLOW_ASSEMBLY;
+
+ PdfEncryption crypto = new PdfEncryption();
+ //for (Certificate c : chain) crypto.addRecipient(c, permission);
+ //crypto.addRecipient(chain[2], permission);
+ crypto.setCryptoMode(PdfWriter.ENCRYPTION_AES_128, 0);
+ crypto.setupByEncryptionKey(key.getEncoded(), key.getEncoded().length*8);
+ crypto.getEncryptionDictionary();
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }*/
+
+ /*
+ writer.setEncryption(
+ new Certificate[] {},
+ new int[] {PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING},
+ PdfWriter.STANDARD_ENCRYPTION_128);
+ */
+ //writer.setEncryption(PdfWriter.STANDARD_ENCRYPTION_128, "", "password", PdfWriter.ALLOW_FILL_IN|PdfWriter.ALLOW_PRINTING|PdfWriter.ALLOW_COPY|PdfWriter.ALLOW_ASSEMBLY);
+
+// PdfName companyName = new PdfName("SMTC");
+// PdfDeveloperExtension ext = new PdfDeveloperExtension(companyName, PdfWriter.PDF_VERSION_1_7, 3);
+// writer.addDeveloperExtension( ext );
+
+ document.open();
+ }
+
+ if (!first) {
+ document.setPageSize(pageSize);
+ document.newPage();
+ }
+
+ /*
+ /// ATTACHMENTS - TG ///
+ byte[] attachment = null;
+ if ( exportPlan.attachTG && !d.getDefiningResources().isEmpty() )
+ try {
+ PdfDictionary fileParameter = new PdfDictionary();
+
+ {
+ final Resource composite = d.getDefiningResources().iterator().next();
+ final Session session = exportPlan.sessionContext.getSession();
+
+ SimanticsClipboard clipboard = session.syncRequest(new Read<SimanticsClipboard>() {
+ @Override
+ public SimanticsClipboard perform(ReadGraph graph) throws DatabaseException {
+ CopyHandler ch = graph.adapt(composite, CopyHandler.class);
+ SimanticsClipboardImpl clipboard = new SimanticsClipboardImpl();
+ ch.copyToClipboard(graph, clipboard);
+ return clipboard;
+ }
+ });
+ for (Set<Representation> object : clipboard.getContents()) {
+ TransferableGraph1 tg = ClipboardUtils.accept(object, SimanticsKeys.KEY_TRANSFERABLE_GRAPH);
+ String filename = d.getName()+".diagram";
+ try {
+ byte[] data = DataContainers.writeFile(
+ new DataContainer("aprosDiagram", 1, new Variant(TransferableGraph1.BINDING, tg))
+ );
+ PdfFileSpecification fs = PdfFileSpecification.fileEmbedded(
+ writer,
+ "/Diagram", filename, data, true, "application/simantics/diagram",
+ fileParameter);
+ writer.addFileAttachment(d.getName()+".diagram", fs);
+ } catch ( NullPointerException npe ) {
+ throw new PdfException("Experiment must be activated to export attachments"+npe.getMessage(), npe);
+ }
+ }
+ }
+
+ } catch (DatabaseException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ */
+ //////////////////////////
+
+ String diagramName = formDiagramName(d, true);
+ String subTask = "Page (" + i + "/" + flattenedNodes.size() + "): " + diagramName;
+
+ Resource diagram = d.getDiagramResource();
+ if (diagram == null) {
+ // No diagram, skip page.
+ subTask += " skipped, no diagram.";
+ LOGGER.info(subTask);
+ continue;
+ }
+
+ LOGGER.info(subTask);
+ progress.subTask(subTask);
+
+ try {
+ PDFPainter.render(workerThread, exportPlan, d, writer, mapper,
+ pageSize, d.getPageDesc(), exportPlan.fitContentToPageMargins, 10000);
+ ++exportedPages;
+ } catch (DatabaseException | InterruptedException e) {
+ LOGGER.error("PDF rendering failed.", e);
+ }
+
+ /// ATTACHMENTS - Write WIKI ///
+ if ( exportPlan.attachWiki && !d.getDefiningResources().isEmpty() ) {
+ int w = (int) pageSize.getWidth();
+ int h = (int) pageSize.getHeight();
+ PdfContentByte cb = writer.getDirectContent();
+ Session session = exportPlan.sessionContext.getSession();
+ Resource composite = d.getDefiningResources().iterator().next();
+ DocumentUtils du = new DocumentUtils();
+ StringBuilder wiki = new StringBuilder();
+ StringBuilder css = new StringBuilder();
+ du.getDocumentWikiTextRecursive(session, composite, wiki, css);
+ DocumentSettings settings = du.getDocumentSettings(session, composite);
+ PdfTemplate tp_ = cb.createTemplate(w, h);
+ if ( wiki.length()>0 ) {
+ String wikiText = wiki.toString();
+ String cssText = css.toString();
+ try {
+ exportedPages += du.print(session, composite, wikiText, cssText, settings, tp_.getPdfWriter(), document);
+ } catch (DatabaseException | DocumentException e) {
+ LOGGER.error("Wiki documentation to PDF rendering failed.", e);
+ }
+ }
+ cb.addTemplate(tp_, 0, 0);
+ }
+ //////////////////////////
+
+ progress.worked(1);
+ first = false;
+
+ if (progress.isCanceled())
+ throw new OperationCanceledException();
+
+ LOGGER.trace("GC");
+ SVGCache.getSVGUniverse().clearUnreferenced();
+ SessionGarbageCollection.gc(null, exportPlan.sessionContext.getSession(), true, null);
+ System.gc();
+ LOGGER.trace("GC finished");
+ progress.worked(1);
+ }
+
+ return exportedPages;
+ } catch (DatabaseException | FileNotFoundException | DocumentException | ExceptionConverter e) {
+ throw new PdfException(e);
+ } finally {
+ workerThread.stopDispatchingEvents(true);
+ LOGGER.trace("closing document");
+ try {
+ if ( document != null ) document.close();
+ if ( writer != null ) writer.close();
+ LOGGER.trace("document closed");
+ } catch (RuntimeException e) {
+ LOGGER.error("Error closing PDF document writer", e);
+ }
+ SessionGarbageCollectorJob.getInstance().setEnabled(true).scheduleAfterQuietTime();
+ }
+ }
+
+ public static Rectangle toPageSize(PageDesc pageDesc) {
+ String arg = PageDesc.toPoints(pageDesc.getWidth()) + " " + PageDesc.toPoints(pageDesc.getHeight());
+ Rectangle r = PageSize.getRectangle(arg);
+
+ if (PageOrientation.Landscape == pageDesc.getOrientation())
+ r = r.rotate();
+
+ // Disable inherent borders from the PDF writer.
+ r.setBorder(0);
+
+ return r;
+ }
+
+ public static String formDiagramName(Node node, boolean parents) {
+ Node d = node;
+ String ret = d.getName();
+ if (parents) {
+ while (d.getParent() != null) {
+ d = d.getParent();
+ ret = d.getName() + " / " + ret;
+ }
+ }
+// String[] pg = node.getPartOfGroups();
+// if (pg.length > 0)
+// ret += " [" + EString.implode(pg, " / ") + " / " + node.getName() + "]";
+ return ret;
+ }
+
+ public static String getCreator() {
+ String creator = null;
+ IProduct product = Platform.getProduct();
+ if (product != null) {
+ creator = product.getDescription();
+ if (creator == null) {
+ creator = product.getName();
+ }
+ }
+ if (creator == null) {
+ creator = "Simantics";
+ }
+ return creator;
+ }
+
+ static {
+ Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
+ }
+