X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.modeling.ui%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Fui%2Fpdf%2FPDFPainter.java;h=0b7cd63e4c55eed107eb552c9707a382beffc974;hb=HEAD;hp=6e725c693b7a2364c83614ba4d585b11c3057353;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/PDFPainter.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/PDFPainter.java index 6e725c693..0b7cd63e4 100644 --- a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/PDFPainter.java +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/pdf/PDFPainter.java @@ -1,163 +1,167 @@ -/******************************************************************************* - * 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.util.concurrent.Semaphore; -import java.util.concurrent.atomic.AtomicReference; - -import org.simantics.db.ReadGraph; -import org.simantics.db.Resource; -import org.simantics.db.common.request.PossibleIndexRoot; -import org.simantics.db.common.request.UniqueRead; -import org.simantics.db.common.utils.NameUtils; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.exception.ValidationException; -import org.simantics.db.layer0.variable.Variable; -import org.simantics.db.layer0.variable.Variables; -import org.simantics.db.management.ISessionContext; -import org.simantics.diagram.elements.DiagramNodeUtil; -import org.simantics.diagram.stubs.DiagramResource; -import org.simantics.g2d.canvas.Hints; -import org.simantics.g2d.canvas.impl.CanvasContext; -import org.simantics.g2d.scenegraph.ICanvasSceneGraphProvider; -import org.simantics.modeling.requests.Node; -import org.simantics.structural.stubs.StructuralResource2; -import org.simantics.utils.DataContainer; -import org.simantics.utils.datastructures.Pair; -import org.simantics.utils.page.PageDesc; -import org.simantics.utils.threads.IThreadWorkQueue; -import org.simantics.utils.threads.ThreadUtils; - -import com.lowagie.text.Rectangle; -import com.lowagie.text.pdf.FontMapper; -import com.lowagie.text.pdf.PdfWriter; - -/** - * Rasterizes diagram into a PDF document using the com.lowagie.text plug-in. - * - * @author Tuukka Lehtonen - */ -public class PDFPainter { - - public static boolean render( - final IThreadWorkQueue thread, - final ISessionContext sessionContext, - PDFExportPlan exportModel, - final Node node, - final PdfWriter writer, - final FontMapper mapper, - final Rectangle pageSize, - final PageDesc pageDesc, - final boolean fitDiagramContentsToPageMargins, - long timeout) - throws InterruptedException, DatabaseException - { - final DataContainer result = new DataContainer(false); - final DataContainer exception = new DataContainer(); - - final CanvasContext ctx = new CanvasContext(thread); - final AtomicReference sgProvider = new AtomicReference(); - - try { - final Semaphore done = new Semaphore(0); - // IMPORTANT: Load diagram in a different thread than the canvas context thread! - ThreadUtils.getBlockingWorkExecutor().execute(new Runnable() { - @Override - public void run() { - try { - Pair modelAndRVI = sessionContext.getSession().syncRequest(new UniqueRead>() { - @Override - public Pair perform(ReadGraph graph) throws DatabaseException { - return new Pair( resolveModel(graph, node), resolveRVI(graph, node) ); - } - }); - - final Boolean isSymbol = sessionContext.getSession().syncRequest(new UniqueRead() { - @Override - public Boolean perform(ReadGraph graph) throws DatabaseException { - StructuralResource2 STR = StructuralResource2.getInstance(graph); - DiagramResource DIA = DiagramResource.getInstance(graph); - Resource possibleSymbol = graph.getPossibleObject(node.getDiagramResource(), STR.Defines); - return possibleSymbol != null && graph.isInstanceOf(possibleSymbol, DIA.ElementClass); - } - }); - - ICanvasSceneGraphProvider provider = DiagramNodeUtil.loadSceneGraphProvider(ctx, modelAndRVI.first, node.getDiagramResource(), modelAndRVI.second, 5000); - sgProvider.set( provider ); - ctx.getDefaultHintContext().setHint(Hints.KEY_PAGE_DESC, pageDesc); - -// StringBuilder b = new StringBuilder(); -// NodeUtil.printTreeNodes(ctx.getCanvasNode(), b); -// System.err.println(b.toString()); - - ThreadUtils.asyncExec(thread, new Runnable() { - @Override - public void run() { - try { - PDFBuilder chassis = new PDFBuilder(writer, mapper, pageSize, pageDesc, fitDiagramContentsToPageMargins || isSymbol); - - chassis.paint(ctx, true); - } finally { - done.release(); - } - } - }); - } catch (DatabaseException e) { - done.release(); - exception.set(e); - } catch (Throwable e) { - done.release(); - exception.set(new DatabaseException(e)); - } finally { - done.release(); - } - } - }); - - done.acquire(2); - if (exception.get() != null) - throw exception.get(); - return result.get(); - } finally { - if (sgProvider.get() != null) - sgProvider.get().dispose(); - ctx.dispose(); - } - } - - private static Resource resolveModel(ReadGraph graph, Node node) throws DatabaseException { - Resource composite = node.getDefiningResources().head(); - Resource model = graph.syncRequest(new PossibleIndexRoot(composite)); -// Resource model = StructuralVariables.getModel(graph, composite); - if (model == null) - throw new ValidationException("no model found for composite " + NameUtils.getSafeName(graph, composite)); - return model; - } - -// private static String resolveModelURI(ReadGraph graph, final Node node) throws DatabaseException { -// return graph.getURI(resolveModel(graph, node)); -// } - - private static String resolveRVI(ReadGraph graph, final Node node) throws DatabaseException { - String RVI = node.getRVI(); - if(RVI != null) return RVI; - Resource composite = node.getDefiningResources().head(); - Variable var = Variables.getVariable(graph, composite); - org.simantics.db.layer0.variable.RVI rvi = var.getPossibleRVI(graph); - if(rvi == null) return null; - return rvi.toString(); -// final ResourceArray compositePath = StructuralVariables.getCompositeArray(graph, composite); -// final ResourceArray variablePath = compositePath.removeFromBeginning(1); -// return StructuralVariables.getRVI(graph, variablePath); - } - -} +/******************************************************************************* + * 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 + *******************************************************************************/ +package org.simantics.modeling.ui.pdf; + +import java.util.concurrent.Semaphore; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.common.request.PossibleIndexRoot; +import org.simantics.db.common.request.UniqueRead; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.exception.ValidationException; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.layer0.variable.Variables; +import org.simantics.db.request.Read; +import org.simantics.diagram.elements.DiagramNodeUtil; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.g2d.canvas.Hints; +import org.simantics.g2d.canvas.impl.CanvasContext; +import org.simantics.g2d.scenegraph.ICanvasSceneGraphProvider; +import org.simantics.modeling.requests.Node; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.utils.datastructures.Pair; +import org.simantics.utils.page.PageDesc; +import org.simantics.utils.threads.IThreadWorkQueue; +import org.simantics.utils.threads.ThreadUtils; + +import com.lowagie.text.Rectangle; +import com.lowagie.text.pdf.FontMapper; +import com.lowagie.text.pdf.PdfWriter; + +/** + * Rasterizes diagram into a PDF document using the com.lowagie.text plug-in. + * + * @author Tuukka Lehtonen + */ +public class PDFPainter { + + public static void render( + final IThreadWorkQueue thread, + PDFExportPlan exportModel, + final Node node, + final PdfWriter writer, + final FontMapper mapper, + final Rectangle pageSize, + final PageDesc pageDesc, + final boolean fitDiagramContentsToPageMargins, + long timeout) + throws InterruptedException, DatabaseException + { + DatabaseException[] exception = { null }; + ICanvasSceneGraphProvider[] sgProvider = { null }; + + CanvasContext ctx = new CanvasContext(thread); + ctx.getDefaultHintContext().setHint(Hints.KEY_DISABLE_GRAPH_MODIFICATIONS, Boolean.TRUE); + + try { + final Semaphore done = new Semaphore(0); + // IMPORTANT: Load diagram in a different thread than the canvas context thread! + ThreadUtils.getBlockingWorkExecutor().execute(() -> { + try { + Session s = exportModel.sessionContext.getSession(); + + Pair modelAndRVI = s.syncRequest( modelAndRVI(node) ); + Boolean isSymbol = s.syncRequest( isSymbol(node) ); + + ICanvasSceneGraphProvider provider = DiagramNodeUtil.loadSceneGraphProvider( + ctx, + modelAndRVI.first, + node.getDiagramResource(), + modelAndRVI.second, + 5000); + sgProvider[0] = provider; + ctx.getDefaultHintContext().setHint(Hints.KEY_PAGE_DESC, pageDesc); + +// System.err.println(NodeUtil.printTreeNodes(ctx.getCanvasNode(), new StringBuilder()).toString()); + + ThreadUtils.asyncExec(thread, () -> { + try { + boolean fitToContent = fitDiagramContentsToPageMargins || isSymbol; + if (!fitToContent) { + // Prevent PDF printing from drawing page borders if the + // print area is fitted directly to the page size. + // This avoids unwanted black half-visible edges. + ctx.getDefaultHintContext().setHint(Hints.KEY_DISPLAY_PAGE, false); + } + + PDFBuilder chassis = new PDFBuilder(writer, mapper, pageSize, pageDesc, fitToContent); + chassis.paint(ctx, true); + } catch (Throwable e) { + exception[0] = new DatabaseException(e); + } finally { + done.release(); + } + }); + } catch (DatabaseException e) { + done.release(); + exception[0] = e; + } catch (Throwable e) { + done.release(); + exception[0] = new DatabaseException(e); + } finally { + done.release(); + } + }); + + done.acquire(2); + if (exception[0] != null) + throw exception[0]; + } finally { + if (sgProvider[0] != null) + sgProvider[0].dispose(); + ctx.dispose(); + } + } + + private static Read> modelAndRVI(Node node) { + return new UniqueRead>() { + @Override + public Pair perform(ReadGraph graph) throws DatabaseException { + return Pair.make( resolveModel(graph, node), resolveRVI(graph, node) ); + } + }; + } + + private static Read isSymbol(Node node) { + return new UniqueRead() { + @Override + public Boolean perform(ReadGraph graph) throws DatabaseException { + StructuralResource2 STR = StructuralResource2.getInstance(graph); + DiagramResource DIA = DiagramResource.getInstance(graph); + Resource possibleSymbol = graph.getPossibleObject(node.getDiagramResource(), STR.Defines); + return possibleSymbol != null && graph.isInstanceOf(possibleSymbol, DIA.ElementClass); + } + }; + } + + private static Resource resolveModel(ReadGraph graph, Node node) throws DatabaseException { + Resource composite = node.getDefiningResources().head(); + Resource model = graph.syncRequest(new PossibleIndexRoot(composite)); + if (model == null) + throw new ValidationException("no model found for composite " + NameUtils.getSafeName(graph, composite)); + return model; + } + + private static String resolveRVI(ReadGraph graph, final Node node) throws DatabaseException { + String RVI = node.getRVI(); + if (RVI != null) return RVI; + Resource composite = node.getDefiningResources().head(); + Variable var = Variables.getVariable(graph, composite); + org.simantics.db.layer0.variable.RVI rvi = var.getPossibleRVI(graph); + return rvi != null ? rvi.toString() : null; + } + +} \ No newline at end of file