X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.diagram.svg%2Fsrc%2Forg%2Fsimantics%2Fdiagram%2Fsvg%2Fexport%2FSVGBuilder.java;h=457a05dcbaca6b9ead06f538b8d4574d0620b616;hp=86bdbcd8e9327f7673a4909b0de0111c2421ac22;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hpb=24e2b34260f219f0d1644ca7a138894980e25b14 diff --git a/bundles/org.simantics.diagram.svg/src/org/simantics/diagram/svg/export/SVGBuilder.java b/bundles/org.simantics.diagram.svg/src/org/simantics/diagram/svg/export/SVGBuilder.java index 86bdbcd8e..457a05dcb 100644 --- a/bundles/org.simantics.diagram.svg/src/org/simantics/diagram/svg/export/SVGBuilder.java +++ b/bundles/org.simantics.diagram.svg/src/org/simantics/diagram/svg/export/SVGBuilder.java @@ -1,188 +1,188 @@ -package org.simantics.diagram.svg.export; - -import java.awt.Graphics2D; -import java.awt.Point; -import java.awt.RenderingHints; -import java.awt.geom.AffineTransform; -import java.awt.geom.Rectangle2D; -import java.io.StringWriter; -import java.util.UUID; - -import org.apache.batik.dom.GenericDOMImplementation; -import org.apache.batik.svggen.SVGGraphics2D; -import org.simantics.g2d.canvas.ICanvasContext; -import org.simantics.g2d.diagram.DiagramHints; -import org.simantics.g2d.diagram.DiagramUtils; -import org.simantics.g2d.diagram.IDiagram; -import org.simantics.g2d.participant.TransformUtil; -import org.simantics.scenegraph.g2d.G2DRenderingHints; -import org.simantics.scenegraph.utils.QualityHints; -import org.simantics.utils.page.MarginUtils; -import org.simantics.utils.page.MarginUtils.Margins; -import org.w3c.dom.DOMImplementation; -import org.w3c.dom.Document; -import org.w3c.dom.Element; - - -/** - * org.simantics.diagram.export.ImageBuilder with SVG support - * - * @author Marko Luukkainen - * - */ -public class SVGBuilder { - Double dpi; - Point size; - double margin; - Margins margins; - - /** - * - * @param file File to write the image (optional) - * @param dpi Dots Per Inch - * @param size Image size in pixels - * @param margin percentage of image width for margins. 0.05 is 5%. - */ - public SVGBuilder(Double dpi, Point size, double margin) { - this.dpi = dpi; - this.size = size; - this.margin = Math.max(margin,0.0); - this.margins = null; - } - - /** - * - * @param file File to write the image (optional) - * @param dpi Dots Per Inch - * @param size Image size in pixels - * @param margins Margins - */ - public SVGBuilder(Double dpi, Point size, Margins margins) { - this.dpi = dpi; - this.size = size; - this.margin = 0.0; - this.margins = margins; - } - - public static SVGGraphics2D defaultSVGGenerator() { - DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation(); - - // Create an instance of org.w3c.dom.Document. - String svgNS = "http://www.w3.org/2000/svg"; - Document document = domImpl.createDocument(svgNS, "svg", null); - - // Create an instance of the SVG Generator. - SVGGraphics2D svgGenerator = new SVGGraphics2D(document); - svgGenerator.getGeneratorContext().setIDGenerator(new UniqueIDGenerator(UUID.randomUUID().toString())); - return svgGenerator; - } - - /** - * @param canvasContext - * the canvas context to paint - * @param writeResults - * true to actually write the resulting Image to the file. - */ - public String paint(ICanvasContext canvasContext) throws Exception { - return paint(canvasContext, defaultSVGGenerator()); - } - - /** - * @param canvasContext - * the canvas context to paint - * svgGenerator - * the svg generator to use - * @param writeResults - * true to actually write the resulting Image to the file. - */ - public String paint(ICanvasContext canvasContext, SVGGraphics2D svgGenerator) throws Exception { - - Graphics2D g2 = svgGenerator; - - IDiagram diagram = canvasContext.getDefaultHintContext().getHint(DiagramHints.KEY_DIAGRAM); - Rectangle2D diagramRect = DiagramUtils.getContentRect(diagram); - - if (diagramRect == null) - diagramRect = new Rectangle2D.Double(0, 0, 100, 100); - - // add margins to content. - double off = Math.max(diagramRect.getWidth(), diagramRect.getHeight()) * margin*0.5; - diagramRect = new Rectangle2D.Double(diagramRect.getX() - off, diagramRect.getY() - off, diagramRect.getWidth() + off * 2.0, diagramRect.getHeight() + off * 2.0); - - if (margins != null) { - diagramRect = org.simantics.scenegraph.utils.GeometryUtils.expandRectangle(diagramRect, - margins.top.diagramAbsolute, - margins.bottom.diagramAbsolute, - margins.left.diagramAbsolute, - margins.right.diagramAbsolute - ); - } - - // Make sure the transformation is reset. - AffineTransform tr = new AffineTransform(); - - Rectangle2D controlArea; - if (dpi != null) { - double mmToInch = 1.0 / 25.4; - controlArea = new Rectangle2D.Double(0, 0, diagramRect.getWidth() * mmToInch * dpi, diagramRect.getHeight() * mmToInch * dpi); - - if (margins != null) { - double w = controlArea.getWidth(); - double h = controlArea.getHeight(); - controlArea = org.simantics.scenegraph.utils.GeometryUtils.expandRectangle(controlArea, - margins.top.controlAbsolute + margins.top.controlRelative * h, - margins.bottom.controlAbsolute + margins.bottom.controlRelative * h, - margins.left.controlAbsolute + margins.left.controlRelative * w, - margins.right.controlAbsolute + margins.right.controlRelative * w - ); - } - } else { - controlArea = new Rectangle2D.Double(0, 0, size.getX(), size.getY()); - if (margins != null) { - double w = controlArea.getWidth(); - double h = controlArea.getHeight(); - controlArea = org.simantics.scenegraph.utils.GeometryUtils.expandRectangle(controlArea, - -(margins.top.controlAbsolute + margins.top.controlRelative * h), - -(margins.bottom.controlAbsolute + margins.bottom.controlRelative * h), - -(margins.left.controlAbsolute + margins.left.controlRelative * w), - -(margins.right.controlAbsolute + margins.right.controlRelative * w) - ); - } - } - - canvasContext.getSingleItem(TransformUtil.class).fitArea(controlArea, diagramRect, MarginUtils.NO_MARGINS); - - float width = (float)controlArea.getWidth(); - float height = (float)controlArea.getHeight(); - - - QualityHints.HIGH_QUALITY_HINTS.setQuality(g2); - g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); - - - g2.setTransform(tr); - g2.setClip(new Rectangle2D.Double(0, 0, controlArea.getWidth(), controlArea.getHeight())); - - g2.setRenderingHint(G2DRenderingHints.KEY_CONTROL_BOUNDS, new Rectangle2D.Double(0, 0, controlArea.getWidth(), controlArea.getHeight())); - - if (canvasContext.isLocked()) - throw new IllegalStateException("cannot render image, canvas context is locked: " + canvasContext); - - canvasContext.getSceneGraph().render(g2); - - - - Element root = svgGenerator.getRoot(); - root.setAttributeNS(null, "viewBox", "0 0 " + width + " " + height); - root.setAttributeNS(null, "height", Float.toString(height)); - root.setAttributeNS(null, "width", Float.toString(width)); - - // Finally, stream out SVG to the standard output using - // UTF-8 encoding. - boolean useCSS = false; // we want to use CSS style attributes - StringWriter writer = new StringWriter(); - //svgGenerator.stream(writer, useCSS); - svgGenerator.stream(root,writer, useCSS, false); - return writer.toString(); - } -} +package org.simantics.diagram.svg.export; + +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.RenderingHints; +import java.awt.geom.AffineTransform; +import java.awt.geom.Rectangle2D; +import java.io.StringWriter; +import java.util.UUID; + +import org.apache.batik.dom.GenericDOMImplementation; +import org.apache.batik.svggen.SVGGraphics2D; +import org.simantics.g2d.canvas.ICanvasContext; +import org.simantics.g2d.diagram.DiagramHints; +import org.simantics.g2d.diagram.DiagramUtils; +import org.simantics.g2d.diagram.IDiagram; +import org.simantics.g2d.participant.TransformUtil; +import org.simantics.scenegraph.g2d.G2DRenderingHints; +import org.simantics.scenegraph.utils.QualityHints; +import org.simantics.utils.page.MarginUtils; +import org.simantics.utils.page.MarginUtils.Margins; +import org.w3c.dom.DOMImplementation; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + + +/** + * org.simantics.diagram.export.ImageBuilder with SVG support + * + * @author Marko Luukkainen + * + */ +public class SVGBuilder { + Double dpi; + Point size; + double margin; + Margins margins; + + /** + * + * @param file File to write the image (optional) + * @param dpi Dots Per Inch + * @param size Image size in pixels + * @param margin percentage of image width for margins. 0.05 is 5%. + */ + public SVGBuilder(Double dpi, Point size, double margin) { + this.dpi = dpi; + this.size = size; + this.margin = Math.max(margin,0.0); + this.margins = null; + } + + /** + * + * @param file File to write the image (optional) + * @param dpi Dots Per Inch + * @param size Image size in pixels + * @param margins Margins + */ + public SVGBuilder(Double dpi, Point size, Margins margins) { + this.dpi = dpi; + this.size = size; + this.margin = 0.0; + this.margins = margins; + } + + public static SVGGraphics2D defaultSVGGenerator() { + DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation(); + + // Create an instance of org.w3c.dom.Document. + String svgNS = "http://www.w3.org/2000/svg"; + Document document = domImpl.createDocument(svgNS, "svg", null); + + // Create an instance of the SVG Generator. + SVGGraphics2D svgGenerator = new SVGGraphics2D(document); + svgGenerator.getGeneratorContext().setIDGenerator(new UniqueIDGenerator(UUID.randomUUID().toString())); + return svgGenerator; + } + + /** + * @param canvasContext + * the canvas context to paint + * @param writeResults + * true to actually write the resulting Image to the file. + */ + public String paint(ICanvasContext canvasContext) throws Exception { + return paint(canvasContext, defaultSVGGenerator()); + } + + /** + * @param canvasContext + * the canvas context to paint + * svgGenerator + * the svg generator to use + * @param writeResults + * true to actually write the resulting Image to the file. + */ + public String paint(ICanvasContext canvasContext, SVGGraphics2D svgGenerator) throws Exception { + + Graphics2D g2 = svgGenerator; + + IDiagram diagram = canvasContext.getDefaultHintContext().getHint(DiagramHints.KEY_DIAGRAM); + Rectangle2D diagramRect = DiagramUtils.getContentRect(diagram); + + if (diagramRect == null) + diagramRect = new Rectangle2D.Double(0, 0, 100, 100); + + // add margins to content. + double off = Math.max(diagramRect.getWidth(), diagramRect.getHeight()) * margin*0.5; + diagramRect = new Rectangle2D.Double(diagramRect.getX() - off, diagramRect.getY() - off, diagramRect.getWidth() + off * 2.0, diagramRect.getHeight() + off * 2.0); + + if (margins != null) { + diagramRect = org.simantics.scenegraph.utils.GeometryUtils.expandRectangle(diagramRect, + margins.top.diagramAbsolute, + margins.bottom.diagramAbsolute, + margins.left.diagramAbsolute, + margins.right.diagramAbsolute + ); + } + + // Make sure the transformation is reset. + AffineTransform tr = new AffineTransform(); + + Rectangle2D controlArea; + if (dpi != null) { + double mmToInch = 1.0 / 25.4; + controlArea = new Rectangle2D.Double(0, 0, diagramRect.getWidth() * mmToInch * dpi, diagramRect.getHeight() * mmToInch * dpi); + + if (margins != null) { + double w = controlArea.getWidth(); + double h = controlArea.getHeight(); + controlArea = org.simantics.scenegraph.utils.GeometryUtils.expandRectangle(controlArea, + margins.top.controlAbsolute + margins.top.controlRelative * h, + margins.bottom.controlAbsolute + margins.bottom.controlRelative * h, + margins.left.controlAbsolute + margins.left.controlRelative * w, + margins.right.controlAbsolute + margins.right.controlRelative * w + ); + } + } else { + controlArea = new Rectangle2D.Double(0, 0, size.getX(), size.getY()); + if (margins != null) { + double w = controlArea.getWidth(); + double h = controlArea.getHeight(); + controlArea = org.simantics.scenegraph.utils.GeometryUtils.expandRectangle(controlArea, + -(margins.top.controlAbsolute + margins.top.controlRelative * h), + -(margins.bottom.controlAbsolute + margins.bottom.controlRelative * h), + -(margins.left.controlAbsolute + margins.left.controlRelative * w), + -(margins.right.controlAbsolute + margins.right.controlRelative * w) + ); + } + } + + canvasContext.getSingleItem(TransformUtil.class).fitArea(controlArea, diagramRect, MarginUtils.NO_MARGINS); + + float width = (float)controlArea.getWidth(); + float height = (float)controlArea.getHeight(); + + + QualityHints.HIGH_QUALITY_HINTS.setQuality(g2); + g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); + + + g2.setTransform(tr); + g2.setClip(new Rectangle2D.Double(0, 0, controlArea.getWidth(), controlArea.getHeight())); + + g2.setRenderingHint(G2DRenderingHints.KEY_CONTROL_BOUNDS, new Rectangle2D.Double(0, 0, controlArea.getWidth(), controlArea.getHeight())); + + if (canvasContext.isLocked()) + throw new IllegalStateException("cannot render image, canvas context is locked: " + canvasContext); + + canvasContext.getSceneGraph().render(g2); + + + + Element root = svgGenerator.getRoot(); + root.setAttributeNS(null, "viewBox", "0 0 " + width + " " + height); + root.setAttributeNS(null, "height", Float.toString(height)); + root.setAttributeNS(null, "width", Float.toString(width)); + + // Finally, stream out SVG to the standard output using + // UTF-8 encoding. + boolean useCSS = false; // we want to use CSS style attributes + StringWriter writer = new StringWriter(); + //svgGenerator.stream(writer, useCSS); + svgGenerator.stream(root,writer, useCSS, false); + return writer.toString(); + } +}