1 /*******************************************************************************
2 * Copyright (c) 2007, 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 * VTT Technical Research Centre of Finland - initial API and implementation
11 * Semantum Oy - (#7084) refactoring
12 *******************************************************************************/
13 package org.simantics.modeling.ui.pdf;
15 import java.util.concurrent.Semaphore;
17 import org.simantics.db.ReadGraph;
18 import org.simantics.db.Resource;
19 import org.simantics.db.Session;
20 import org.simantics.db.common.request.PossibleIndexRoot;
21 import org.simantics.db.common.request.UniqueRead;
22 import org.simantics.db.common.utils.NameUtils;
23 import org.simantics.db.exception.DatabaseException;
24 import org.simantics.db.exception.ValidationException;
25 import org.simantics.db.layer0.variable.Variable;
26 import org.simantics.db.layer0.variable.Variables;
27 import org.simantics.db.request.Read;
28 import org.simantics.diagram.elements.DiagramNodeUtil;
29 import org.simantics.diagram.stubs.DiagramResource;
30 import org.simantics.g2d.canvas.Hints;
31 import org.simantics.g2d.canvas.impl.CanvasContext;
32 import org.simantics.g2d.scenegraph.ICanvasSceneGraphProvider;
33 import org.simantics.modeling.requests.Node;
34 import org.simantics.structural.stubs.StructuralResource2;
35 import org.simantics.utils.datastructures.Pair;
36 import org.simantics.utils.page.PageDesc;
37 import org.simantics.utils.threads.IThreadWorkQueue;
38 import org.simantics.utils.threads.ThreadUtils;
40 import com.lowagie.text.Rectangle;
41 import com.lowagie.text.pdf.FontMapper;
42 import com.lowagie.text.pdf.PdfWriter;
45 * Rasterizes diagram into a PDF document using the com.lowagie.text plug-in.
47 * @author Tuukka Lehtonen
49 public class PDFPainter {
51 public static void render(
52 final IThreadWorkQueue thread,
53 PDFExportPlan exportModel,
55 final PdfWriter writer,
56 final FontMapper mapper,
57 final Rectangle pageSize,
58 final PageDesc pageDesc,
59 final boolean fitDiagramContentsToPageMargins,
61 throws InterruptedException, DatabaseException
63 DatabaseException[] exception = { null };
64 ICanvasSceneGraphProvider[] sgProvider = { null };
66 CanvasContext ctx = new CanvasContext(thread);
69 final Semaphore done = new Semaphore(0);
70 // IMPORTANT: Load diagram in a different thread than the canvas context thread!
71 ThreadUtils.getBlockingWorkExecutor().execute(() -> {
73 Session s = exportModel.sessionContext.getSession();
75 Pair<Resource, String> modelAndRVI = s.syncRequest( modelAndRVI(node) );
76 Boolean isSymbol = s.syncRequest( isSymbol(node) );
78 ICanvasSceneGraphProvider provider = DiagramNodeUtil.loadSceneGraphProvider(
81 node.getDiagramResource(),
84 sgProvider[0] = provider;
85 ctx.getDefaultHintContext().setHint(Hints.KEY_PAGE_DESC, pageDesc);
87 // System.err.println(NodeUtil.printTreeNodes(ctx.getCanvasNode(), new StringBuilder()).toString());
89 ThreadUtils.asyncExec(thread, () -> {
91 PDFBuilder chassis = new PDFBuilder(writer, mapper, pageSize, pageDesc, fitDiagramContentsToPageMargins || isSymbol);
92 chassis.paint(ctx, true);
93 } catch (Throwable e) {
94 exception[0] = new DatabaseException(e);
99 } catch (DatabaseException e) {
102 } catch (Throwable e) {
104 exception[0] = new DatabaseException(e);
111 if (exception[0] != null)
114 if (sgProvider[0] != null)
115 sgProvider[0].dispose();
120 private static Read<Pair<Resource, String>> modelAndRVI(Node node) {
121 return new UniqueRead<Pair<Resource, String>>() {
123 public Pair<Resource, String> perform(ReadGraph graph) throws DatabaseException {
124 return Pair.make( resolveModel(graph, node), resolveRVI(graph, node) );
129 private static Read<Boolean> isSymbol(Node node) {
130 return new UniqueRead<Boolean>() {
132 public Boolean perform(ReadGraph graph) throws DatabaseException {
133 StructuralResource2 STR = StructuralResource2.getInstance(graph);
134 DiagramResource DIA = DiagramResource.getInstance(graph);
135 Resource possibleSymbol = graph.getPossibleObject(node.getDiagramResource(), STR.Defines);
136 return possibleSymbol != null && graph.isInstanceOf(possibleSymbol, DIA.ElementClass);
141 private static Resource resolveModel(ReadGraph graph, Node node) throws DatabaseException {
142 Resource composite = node.getDefiningResources().head();
143 Resource model = graph.syncRequest(new PossibleIndexRoot(composite));
145 throw new ValidationException("no model found for composite " + NameUtils.getSafeName(graph, composite));
149 private static String resolveRVI(ReadGraph graph, final Node node) throws DatabaseException {
150 String RVI = node.getRVI();
151 if (RVI != null) return RVI;
152 Resource composite = node.getDefiningResources().head();
153 Variable var = Variables.getVariable(graph, composite);
154 org.simantics.db.layer0.variable.RVI rvi = var.getPossibleRVI(graph);
155 return rvi != null ? rvi.toString() : null;