X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.modeling.ui%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Fui%2Fpdf%2FDiagramPrinter.java;fp=bundles%2Forg.simantics.modeling.ui%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Fui%2Fpdf%2FDiagramPrinter.java;h=ccdf57fbe89f8ec655bef4fb1dd3b5b5f7ed8986;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/DiagramPrinter.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/DiagramPrinter.java new file mode 100644 index 000000000..ccdf57fbe --- /dev/null +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/DiagramPrinter.java @@ -0,0 +1,361 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 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 + *******************************************************************************/ +package org.simantics.modeling.ui.pdf; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.security.Security; +import java.util.Collection; +import java.util.concurrent.atomic.AtomicBoolean; + +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.db.management.ISessionContext; +import org.simantics.document.DocumentSettings; +import org.simantics.document.DocumentUtils; +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 com.kitfox.svg.SVGCache; +import com.lowagie.text.Document; +import com.lowagie.text.DocumentException; +import com.lowagie.text.FontFactory; +import com.lowagie.text.PageSize; +import com.lowagie.text.Rectangle; +import com.lowagie.text.pdf.DefaultFontMapper; +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; + +public class DiagramPrinter { + + 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; + } + + private static final AtomicBoolean fontFactoryInitialized = new AtomicBoolean(); + + /** + * @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 null, 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 flattenedNodes, + ISessionContext sessionContext) + throws PdfException { + Collection flattened = flattenedNodes; + + SubMonitor progress = SubMonitor.convert(monitor, "Export to PDF", flattened.size() * 2); + + WorkerThread workerThread = new WorkerThread("Diagram PDF Painter"); + workerThread.start(); + + PdfWriter writer = null; + Document document = null; + + try { + progress.subTask("Loading system fonts"); + DefaultFontMapper mapper = new DefaultFontMapper(); + if (fontFactoryInitialized.compareAndSet(false, true)) { + // Only register directories once. + FontFactory.registerDirectories(); + } + + SessionGarbageCollectorJob.getInstance().setEnabled(false); + + + boolean first = true; + int i = 0; + for (Node d : flattened) { + ++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); + 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 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() { + @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 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 + "/" + flattened.size() + "): " + diagramName; + + Resource diagram = d.getDiagramResource(); + if (diagram == null) { + // No diagram, skip page. + subTask += " skipped, no diagram."; + System.out.println(subTask); + continue; + } + + System.out.println(subTask); + progress.subTask(subTask); + + try { + PDFPainter.render(workerThread, sessionContext, exportPlan, d, writer, mapper, + pageSize, d.getPageDesc(), exportPlan.fitContentToPageMargins, 10000); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (DatabaseException e) { + e.printStackTrace(); + } + + // Paint diagram path/name on the page + // TODO: remove this hard coded diagram name printing and + // replace it with a page templates that is loaded along with + // the rest of the diagram + + int w = (int) pageSize.getWidth(); + int h = (int) pageSize.getHeight(); + + // Write Page Number + PdfContentByte cb = writer.getDirectContent(); + +// PdfTemplate tp = cb.createTemplate(w, h); +// Graphics2D g2d = tp.createGraphics(w, h, mapper); +// g2d.setColor(Color.black); +// java.awt.Font thisFont = new java.awt.Font("Arial", java.awt.Font.ITALIC, 10); +// g2d.setFont(thisFont); +// FontMetrics metrics = g2d.getFontMetrics(); +// int width = metrics.stringWidth(diagramName); +// g2d.drawString(diagramName, (w - width) / 2, document.getPageSize().getHeight() - PageDesc.toPoints(5)); +// g2d.dispose(); +// cb.addTemplate(tp, 0, 0); + + /// ATTACHMENTS - Write WIKI /// + if ( exportPlan.attachWiki && !d.getDefiningResources().isEmpty() ) { + final 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(); + du.print(session, composite, wikiText, cssText, settings, tp_.getPdfWriter(), document); + } + cb.addTemplate(tp_, 0, 0); + } + ////////////////////////// + + progress.worked(1); + first = false; + + if (progress.isCanceled()) + throw new OperationCanceledException(); + + System.out.println("GC"); + SVGCache.getSVGUniverse().clearUnreferenced(); + SessionGarbageCollection.gc(null, sessionContext.getSession(), true, null); + System.gc(); + System.out.println("GC finished"); + progress.worked(1); + } + } catch (DatabaseException e) { + throw new PdfException(e); + } catch (FileNotFoundException e) { + throw new PdfException(e); + } catch (DocumentException e) { + throw new PdfException(e); + } finally { + workerThread.stopDispatchingEvents(true); + System.out.println("closing document"); + try { + if ( document!=null ) document.close(); + if ( writer!=null ) writer.close(); + } catch(RuntimeException e) { + e.printStackTrace(); + } + System.out.println("document closed"); + 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()); + } + +} \ No newline at end of file