]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/PDFPainter.java
Merge branch 'feature/funcwrite'
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / pdf / PDFPainter.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 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  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *     Semantum Oy - (#7084) refactoring
12  *******************************************************************************/
13 package org.simantics.modeling.ui.pdf;
14
15 import java.util.concurrent.Semaphore;
16
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;
39
40 import com.lowagie.text.Rectangle;
41 import com.lowagie.text.pdf.FontMapper;
42 import com.lowagie.text.pdf.PdfWriter;
43
44 /**
45  * Rasterizes diagram into a PDF document using the com.lowagie.text plug-in.
46  * 
47  * @author Tuukka Lehtonen
48  */
49 public class PDFPainter {
50
51     public static void render(
52             final IThreadWorkQueue thread,
53             PDFExportPlan exportModel,
54             final Node node,
55             final PdfWriter writer,
56             final FontMapper mapper,
57             final Rectangle pageSize,
58             final PageDesc pageDesc,
59             final boolean fitDiagramContentsToPageMargins,
60             long timeout)
61                     throws InterruptedException, DatabaseException
62     {
63         DatabaseException[] exception = { null };
64         ICanvasSceneGraphProvider[] sgProvider = { null };
65
66         CanvasContext ctx = new CanvasContext(thread);
67
68         try {
69             final Semaphore done = new Semaphore(0);
70             // IMPORTANT: Load diagram in a different thread than the canvas context thread!
71             ThreadUtils.getBlockingWorkExecutor().execute(() -> {
72                 try {
73                     Session s = exportModel.sessionContext.getSession();
74
75                     Pair<Resource, String> modelAndRVI = s.syncRequest( modelAndRVI(node) );
76                     Boolean isSymbol = s.syncRequest( isSymbol(node) ); 
77
78                     ICanvasSceneGraphProvider provider = DiagramNodeUtil.loadSceneGraphProvider(
79                             ctx,
80                             modelAndRVI.first,
81                             node.getDiagramResource(),
82                             modelAndRVI.second,
83                             5000);
84                     sgProvider[0] = provider;
85                     ctx.getDefaultHintContext().setHint(Hints.KEY_PAGE_DESC, pageDesc);
86
87 //                    System.err.println(NodeUtil.printTreeNodes(ctx.getCanvasNode(), new StringBuilder()).toString());
88
89                     ThreadUtils.asyncExec(thread, () -> {
90                         try {
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);
95                         } finally {
96                             done.release();
97                         }
98                     });
99                 } catch (DatabaseException e) {
100                     done.release();
101                     exception[0] = e;
102                 } catch (Throwable e) {
103                     done.release();
104                     exception[0] = new DatabaseException(e);
105                 } finally {
106                     done.release();
107                 }
108             });
109
110             done.acquire(2);
111             if (exception[0] != null)
112                 throw exception[0];
113         } finally {
114             if (sgProvider[0] != null)
115                 sgProvider[0].dispose();
116             ctx.dispose();
117         }
118     }
119
120     private static Read<Pair<Resource, String>> modelAndRVI(Node node) {
121         return new UniqueRead<Pair<Resource, String>>() {
122             @Override
123             public Pair<Resource, String> perform(ReadGraph graph) throws DatabaseException {
124                 return Pair.make( resolveModel(graph, node), resolveRVI(graph, node) );
125             }
126         };
127     }
128
129     private static Read<Boolean> isSymbol(Node node) {
130         return new UniqueRead<Boolean>() {
131             @Override
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);
137             }
138         };
139     }
140
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));
144         if (model == null)
145             throw new ValidationException("no model found for composite " + NameUtils.getSafeName(graph, composite));
146         return model;
147     }
148
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;
156     }
157
158 }