Index: lams_common/src/java/org/lamsfoundation/lams/learningdesign/service/ExportToolContentService.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/learningdesign/service/ExportToolContentService.java,v diff -u -r1.106 -r1.107 --- lams_common/src/java/org/lamsfoundation/lams/learningdesign/service/ExportToolContentService.java 3 Sep 2010 13:45:06 -0000 1.106 +++ lams_common/src/java/org/lamsfoundation/lams/learningdesign/service/ExportToolContentService.java 13 Sep 2010 18:05:39 -0000 1.107 @@ -25,7 +25,6 @@ package org.lamsfoundation.lams.learningdesign.service; import java.io.BufferedReader; -import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -61,12 +60,11 @@ import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; +import org.apache.batik.transcoder.TranscoderException; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.log4j.Logger; -import org.apache.xml.serialize.OutputFormat; -import org.apache.xml.serialize.XMLSerializer; import org.jdom.Attribute; import org.jdom.Document; import org.jdom.Element; @@ -188,6 +186,8 @@ public static final String TOOL_FAILED_FILE_NAME = "export_failed.xml"; public static final String SVG_IMAGE_FILE_NAME = "learning_design.svg"; + + public static final String PNG_IMAGE_FILE_NAME = "learning_design.png"; private static final String ERROR_TOOL_NOT_FOUND = "error.import.matching.tool.not.found"; @@ -665,17 +665,16 @@ //generate SVG image if (format != ExportToolContentService.PACKAGE_FORMAT_IMS) { - String svgFileName = FileUtil.getFullPath(contentDir, ExportToolContentService.SVG_IMAGE_FILE_NAME); - Writer svgFile = new OutputStreamWriter(new FileOutputStream(svgFileName), "UTF-8"); SVGGenerator svgGenerator = new SVGGenerator(); - svgGenerator.generateSvg(ldDto); - OutputFormat outputFormat = new OutputFormat(svgGenerator.getSVGDocument()); - outputFormat.setLineWidth(65); - outputFormat.setIndenting(true); - outputFormat.setIndent(2); - XMLSerializer serializer = new XMLSerializer(svgFile, outputFormat); - serializer.serialize(svgGenerator.getSVGDocument()); - svgFile.close(); + svgGenerator.generateSvgDom(ldDto); + + String svgFileName = FileUtil.getFullPath(contentDir, ExportToolContentService.SVG_IMAGE_FILE_NAME); + FileOutputStream svgOutputStream = new FileOutputStream(svgFileName); + svgGenerator.streamOutDocument(svgOutputStream, SVGGenerator.OUTPUT_FORMAT_SVG); + + String pngFileName = FileUtil.getFullPath(contentDir, ExportToolContentService.PNG_IMAGE_FILE_NAME); + FileOutputStream pngOutputStream = new FileOutputStream(pngFileName); + svgGenerator.streamOutDocument(pngOutputStream, SVGGenerator.OUTPUT_FORMAT_PNG); } log.debug("Learning design xml export success"); @@ -724,7 +723,10 @@ } catch (JDOMException e) { log.error("JDOMException:", e); throw new ExportToolContentException(e); - } + } catch (TranscoderException e) { + log.error("TranscoderException:", e); + throw new ExportToolContentException(e); + } } /** Index: lams_common/src/java/org/lamsfoundation/lams/util/svg/ActivityTreeNodeComparator.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/util/svg/ActivityTreeNodeComparator.java,v diff -u -r1.1 -r1.2 --- lams_common/src/java/org/lamsfoundation/lams/util/svg/ActivityTreeNodeComparator.java 6 Sep 2010 11:05:41 -0000 1.1 +++ lams_common/src/java/org/lamsfoundation/lams/util/svg/ActivityTreeNodeComparator.java 13 Sep 2010 18:05:39 -0000 1.2 @@ -23,7 +23,6 @@ /* $Id$ */ package org.lamsfoundation.lams.util.svg; -import java.io.Serializable; import java.util.Comparator; import org.lamsfoundation.lams.learningdesign.dto.AuthoringActivityDTO; Index: lams_common/src/java/org/lamsfoundation/lams/util/svg/SVGConstants.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/util/svg/SVGConstants.java,v diff -u -r1.4 -r1.5 --- lams_common/src/java/org/lamsfoundation/lams/util/svg/SVGConstants.java 3 Sep 2010 17:35:37 -0000 1.4 +++ lams_common/src/java/org/lamsfoundation/lams/util/svg/SVGConstants.java 13 Sep 2010 18:05:39 -0000 1.5 @@ -32,8 +32,8 @@ public static final String ROOT_ELEMENT_ID = "rootElement"; // canvas dimensions - public static final String CANVAS_DEFAULT_WIDTH = "100%"; - public static final String CANVAS_DEFAULT_HEIGHT = "100%"; + public static final int CANVAS_DEFAULT_WIDTH = 1024; + public static final int CANVAS_DEFAULT_HEIGHT = 768; // gate dimensions public static final int GATE_WIDTH = 30; Index: lams_common/src/java/org/lamsfoundation/lams/util/svg/SVGGenerator.java =================================================================== RCS file: /usr/local/cvsroot/lams_common/src/java/org/lamsfoundation/lams/util/svg/SVGGenerator.java,v diff -u -r1.7 -r1.8 --- lams_common/src/java/org/lamsfoundation/lams/util/svg/SVGGenerator.java 6 Sep 2010 11:05:41 -0000 1.7 +++ lams_common/src/java/org/lamsfoundation/lams/util/svg/SVGGenerator.java 13 Sep 2010 18:05:39 -0000 1.8 @@ -26,16 +26,25 @@ import java.awt.Dimension; import java.awt.geom.Point2D; import java.io.IOException; +import java.io.OutputStream; +import java.io.StringWriter; +import java.io.Writer; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.TreeSet; import org.apache.batik.dom.svg.SVGDOMImplementation; +import org.apache.batik.transcoder.TranscoderException; +import org.apache.batik.transcoder.TranscoderInput; +import org.apache.batik.transcoder.TranscoderOutput; +import org.apache.batik.transcoder.image.PNGTranscoder; import org.apache.commons.lang.StringUtils; +import org.apache.xml.serialize.OutputFormat; +import org.apache.xml.serialize.XMLSerializer; import org.jdom.JDOMException; import org.lamsfoundation.lams.learningdesign.Activity; -import org.lamsfoundation.lams.learningdesign.ActivityDTOOrderComparator; import org.lamsfoundation.lams.learningdesign.dto.AuthoringActivityDTO; import org.lamsfoundation.lams.learningdesign.dto.LearningDesignDTO; import org.lamsfoundation.lams.learningdesign.dto.TransitionDTO; @@ -48,40 +57,29 @@ /** * Generates SVG document based on exported learning design's xml file. * - * To be able to see resulted SVG image in swing component use the following lines. - JSVGCanvas canvas = new JSVGCanvas(); - JFrame f = new JFrame(); - f.getContentPane().add(canvas); - canvas.setSVGDocument(svgGenerator.getSVGDocument()); - f.pack(); - f.setSize(CANVAS_DEFAULT_WIDTH, CANVAS_DEFAULT_HEIGHT); - f.setVisible(true); - * * @author Andrey Balan */ public class SVGGenerator extends SVGConstants{ + public final static int OUTPUT_FORMAT_SVG = 1; + public final static int OUTPUT_FORMAT_PNG = 2; + public final static int OUTPUT_FORMAT_SYSTEM_OUT = 3; + private SVGDocument doc; - private String width = null; - private String height = null; - private Double scale = null; + private Integer adjustedDocumentWidth = null; /** * Sets up Svg root and defs. */ private void initializeSvgDocument() { - String canvasWidth = (width == null) ? CANVAS_DEFAULT_WIDTH : width; - String canvasHeigth = (height == null) ? CANVAS_DEFAULT_HEIGHT : height; - Double scale = (this.scale == null) ? 1 : this.scale; + // Create an SVG document. DOMImplementation impl = SVGDOMImplementation.getDOMImplementation(); doc = (SVGDocument) impl.createDocument(SVG_NAMESPACE, "svg", null); // Get the root element (the 'svg' element). Element svgRoot = doc.getDocumentElement(); // Set the width and height attributes on the root 'svg' element. - svgRoot.setAttributeNS(null, "width", canvasWidth); - svgRoot.setAttributeNS(null, "height", canvasHeigth); svgRoot.setAttributeNS(null, "xmlns", SVG_NAMESPACE); svgRoot.setAttributeNS(null, "xmlns:xlink", SVG_NAMESPACE_XLINK); @@ -105,29 +103,21 @@ // Create root g element Element g = doc.createElementNS(SVG_NAMESPACE, "g"); g.setAttributeNS(null, "id", ROOT_ELEMENT_ID); - g.setAttributeNS(null, "transform", "scale(" + scale + " ," + scale + ")"); svgRoot.appendChild(g); - } - public void setSVGDocumentParameters(String width, String height, Double scale) { - this.width = width; - this.height = height; - this.scale = scale; + public void adjustDocumentWidth(Integer width) { + this.adjustedDocumentWidth = width; } - public SVGDocument getSVGDocument() { - return doc; - } - /** * Generates SVG image based on learning design provided. * * @param learningDesign * @throws JDOMException * @throws IOException */ - public void generateSvg(LearningDesignDTO learningDesign) throws JDOMException, IOException { + public void generateSvgDom(LearningDesignDTO learningDesign) throws JDOMException, IOException { initializeSvgDocument(); //initialize all tree nodes @@ -200,6 +190,8 @@ //**************** Draw activities ******************************************************** //tree traverse treeTraverse(root); + + setUpDocumentWidthHeight(allNodes.values()); } /** @@ -514,6 +506,128 @@ } + /** + * Returns estimated width and height of the whole SVG document. + * + * @param nodes + * @param x + * @param y + * @param g + * @return + */ + private void setUpDocumentWidthHeight(Collection nodes) { + int maxX = 0; + int maxY = 0; + for (ActivityTreeNode node : nodes) { + Dimension dimension = node.getActivityDimension(); + + int rightestActivityPoint = node.getActivityCoordinates().x + dimension.width; + if (rightestActivityPoint > maxX) { + maxX = rightestActivityPoint; + } + int bottomActivityPoint = node.getActivityCoordinates().y + dimension.height; + if (bottomActivityPoint > maxY) { + maxY = bottomActivityPoint; + } + } + + int minX = Integer.MAX_VALUE; + int minY = Integer.MAX_VALUE; + for (ActivityTreeNode node : nodes) { + AuthoringActivityDTO activity = node.getActivity(); + if (activity.getParentActivityID() == null) { + int leftActivityPoint = activity.getxCoord().intValue(); + if (leftActivityPoint < minX) { + minX = leftActivityPoint; + } + int topActivityPoint = activity.getyCoord().intValue(); + if (topActivityPoint < minY) { + minY = topActivityPoint; + } + } + } + + Element svg = doc.getDocumentElement(); + + //Removes padding of the SVG image. + minX--; + minY--; + int width = maxX - minX +5; + int height = maxY - minY +5; + svg.setAttributeNS(null, "viewBox", minX + " " + minY + " " + Integer.toString(width) + " " + Integer.toString(height)); + + // adjust width and height to adjustedDocumentWidth + if ((adjustedDocumentWidth != null) && adjustedDocumentWidth < width) { + double scale = (double) adjustedDocumentWidth / (double) width; + width = adjustedDocumentWidth; + height *= scale; + } + + //Sets the width and height + svg.setAttributeNS(null, "width", Integer.toString(width)); + svg.setAttributeNS(null, "height", Integer.toString(height)); + } + + /** + * Stream out SVG document into specified outputStream. + * + * @param outputStream stream where we put resulted data. It can be null in case of RESULT_TYPE_DISPLAY + * @param resultType one of SVGGenerator's constants: either RESULT_TYPE_SVG or RESULT_TYPE_PNG or RESULT_TYPE_DISPLAY + * + * @throws TranscoderException + * @throws IOException + */ + public void streamOutDocument(OutputStream outputStream, int resultType) throws TranscoderException, IOException { + + switch (resultType) { + case OUTPUT_FORMAT_SVG: + OutputFormat format = new OutputFormat(doc); + format.setLineWidth(65); + format.setIndenting(true); + format.setIndent(2); + + XMLSerializer serializer = new XMLSerializer(outputStream, format); + serializer.serialize(doc); + outputStream.flush(); + outputStream.close(); + break; + + case OUTPUT_FORMAT_PNG: + PNGTranscoder transcoder = new PNGTranscoder(); + // Set the transcoder input and output. + TranscoderInput input = new TranscoderInput(doc); + TranscoderOutput output = new TranscoderOutput(outputStream); + + // Perform the transcoding. + transcoder.transcode(input, output); + outputStream.flush(); + outputStream.close(); + break; + +// // to see resulted SVG image in swing component +// case OUTPUT_FORMAT_DISPLAY: +// JSVGCanvas canvas = new JSVGCanvas(); +// JFrame f = new JFrame(); +// f.getContentPane().add(canvas); +// canvas.setSVGDocument(doc); +// f.pack(); +// f.setSize(CANVAS_DEFAULT_WIDTH, CANVAS_DEFAULT_HEIGHT); +// f.setVisible(true); +// break; + + default: + OutputFormat format2 = new OutputFormat(doc); + format2.setLineWidth(65); + format2.setIndenting(true); + format2.setIndent(2); + Writer out = new StringWriter(); + XMLSerializer serializer2 = new XMLSerializer(out, format2); + serializer2.serialize(doc); + System.out.println(out.toString()); + } + + } + //**************** Auxiliary methods for creating svg components ******************************************************** private void createRectangle(ActivityTreeNode node, double x, double y, Element g) {