Files
wisemapping-open-source/wise-webapp/src/main/java/com/wisemapping/xml/SvgToVMLConverter.java
2011-01-23 21:03:40 -03:00

443 lines
16 KiB
Java

/*
* Copyright [2011] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.xml;
import com.wisemapping.xml.svgmap.*;
import com.wisemapping.xml.svgmap.ObjectFactory;
import com.wisemapping.xml.vmlmap.*;
import com.wisemapping.xml.vmlmap.Line;
import com.wisemapping.xml.vmlmap.Polyline;
import com.wisemapping.xml.vmlmap.Rect;
import javax.xml.bind.JAXBException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.Marshaller;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
public class SvgToVMLConverter {
private ObjectFactory svgObjectFactory;
private static final int CORRECTION_HANDCODE = 5;
private Object svgRootElem;
public SvgToVMLConverter() {
this.svgObjectFactory = new ObjectFactory();
}
public void convert(final InputStream vmlDocument) throws JAXBException {
final JAXBContext vmlContext = JAXBContext.newInstance("com.wisemapping.xml.vmlmap");
final Unmarshaller umarshaller = vmlContext.createUnmarshaller();
final Group rootElem = (Group) umarshaller.unmarshal(vmlDocument);
this.svgRootElem = convert(rootElem);
}
private Svg convert(Group g) {
final Svg svgElement = svgObjectFactory.createSvg();
svgElement.setPreserveAspectRatio("none");
/*
<v:group style="WIDTH: 1270px; POSITION: absolute; HEIGHT: 705px" coordsize="889,493" coordorigin="-445,-247">
<svgElement preserveAspectRatio="none" viewBox="-445.9 -221.9 891.8 443.8" height="634" width="1274" id="workspace" focusable="true">
*/
final String coordorigin = g.getCoordorigin();
String coordSize = g.getCoordsize();
svgElement.setViewBox(coordorigin + ", " + coordSize);
final Style style = Style.parse(g.getStyle());
float width = style.getWidth();
svgElement.setWidth(String.valueOf(width));
float height = style.getHeight();
svgElement.setHeight(String.valueOf(height));
// Convert connection lines ...
final List<Polyline> polylines = g.getPolyline();
final List<com.wisemapping.xml.svgmap.Polyline> svgPolylines = svgElement.getPolyline();
for (Polyline vmlPolyline : polylines) {
final com.wisemapping.xml.svgmap.Polyline svgPolyline = convert(vmlPolyline);
svgPolylines.add(svgPolyline);
}
final List<Line> vmlLines = g.getLine();
final List<com.wisemapping.xml.svgmap.Line> svgLines = svgElement.getLine();
for (Line vmlLine : vmlLines) {
final com.wisemapping.xml.svgmap.Line svgPolyline = convert(vmlLine);
svgLines.add(svgPolyline);
}
// Convert Topics ...
final List<Group> vmlTopics = g.getGroup();
final List<G> svgTopics = svgElement.getG();
for (Group topic : vmlTopics) {
G svgTopic = convertTopicGroup(topic);
svgTopics.add(svgTopic);
}
// Convert connectors ...
g.getOval();
return svgElement;
}
private G convertTopicGroup(final Group vmlTopic) {
/**
* <v:group style="LEFT: 222px; WIDTH: 100px; CURSOR: move; POSITION: absolute; TOP: -53px; HEIGHT: 100px" coordsize="100,100">
* <g transform="translate(225, -52) scale(1, 1)" height="100" width="100" focusable="true" preserveAspectRatio="none">
*/
final G svgTopic = new G();
final String styleStr = vmlTopic.getStyle();
final Style style = Style.parse(styleStr);
String transform = "translate(" + style.getLeft() + ", " + style.getTop() + ") scale(1, 1)";
svgTopic.setTransform(transform);
float width = style.getWidth();
svgTopic.setWidth(String.valueOf(width));
float height = style.getHeight();
svgTopic.setHeight(String.valueOf(height));
svgTopic.setPreserveAspectRatio("none");
// Convert InnerShape ...
final List<Roundrect> roundrects = vmlTopic.getRoundrect();
float rectWidth = 0;
float rectHeight = 0;
for (Roundrect vmlRect : roundrects) {
// Skip outerShape figure...
final Fill vmlFill = vmlRect.getFill();
if (vmlFill == null || !"0".equals(vmlFill.getOpacity())) {
final com.wisemapping.xml.svgmap.Rect svgRect = convert(vmlRect);
svgTopic.setRect(svgRect);
final Style rectStyle = Style.parse(vmlRect.getStyle());
rectWidth = rectStyle.getWidth();
rectHeight = rectStyle.getHeight();
}
}
final List<Rect> vmlRects = vmlTopic.getRect();
for (Rect vmlRect : vmlRects) {
// Skip outerShape figure...
final Fill vmlFill = vmlRect.getFill();
if (vmlFill == null || !"0".equals(vmlFill.getOpacity())) {
final com.wisemapping.xml.svgmap.Rect svgRect = convert(vmlRect);
svgTopic.setRect(svgRect);
final Style rectStyle = Style.parse(vmlRect.getStyle());
rectWidth = rectStyle.getWidth();
rectHeight = rectStyle.getHeight();
}
}
final List<Line> vmlLines = vmlTopic.getLine();
for (final Line vmlLine : vmlLines) {
final String lineStyleStr = vmlLine.getStyle();
final Style lineStyle = Style.parse(lineStyleStr);
if (lineStyle.isVisible()) {
com.wisemapping.xml.svgmap.Line line = convert(vmlLine);
svgTopic.setLine(line);
} else {
// Shape is line...
final String from = vmlLine.getFrom();
String[] formPoints = from.split(",");
final String to = vmlLine.getTo();
String[] toPoints = to.split(",");
rectWidth = Float.parseFloat(formPoints[0]) - Float.parseFloat(toPoints[0]);
rectWidth = Math.abs(rectWidth);
rectHeight = Float.parseFloat(formPoints[1]);
}
}
// Convert connection ovals..
final List<Oval> vmlOvals = vmlTopic.getOval();
for (Oval vmlOval : vmlOvals) {
// Skip outerShape figure...
final Ellipse svgElipse = convert(vmlOval);
if (svgElipse != null) {
svgTopic.setEllipse(svgElipse);
}
}
// Convert Text ...
final List<Shape> vmlTextShape = vmlTopic.getShape();
final Text svgText = convertTextShape(vmlTextShape.get(0), rectWidth, rectHeight);
svgTopic.setText(svgText);
return svgTopic;
}
private com.wisemapping.xml.svgmap.Rect convert(Rect vmlRect) {
final com.wisemapping.xml.svgmap.Rect svgRect = new com.wisemapping.xml.svgmap.Rect();
final Style style = Style.parse(vmlRect.getStyle());
float width = style.getWidth();
svgRect.setWidth(String.valueOf(width));
float height = style.getHeight();
svgRect.setHeight(height);
String top = style.getTop();
svgRect.setY(Float.parseFloat(top));
String left = style.getLeft();
svgRect.setX(Float.parseFloat(left));
// Fill properties ...
final String fillColor = vmlRect.getFillcolor();
svgRect.setFill(fillColor);
// Stroke properties ...
final String strokeColor = vmlRect.getStrokecolor();
svgRect.setStroke(strokeColor);
svgRect.setStrokeWidth("0.5px");
return svgRect;
}
private Ellipse convert(final Oval vmlOval) {
/**
* <v:oval style="LEFT: 5px; VISIBILITY: hidden; WIDTH: 6px; POSITION: absolute; TOP: 5px; HEIGHT: 6px"
* coordsize="21600,21600" fillcolor="#e0e5ef" stroked="t" strokecolor="#023bb9" strokeweight="6762emu">
* <v:stroke dashstyle="solid"></v:stroke>
* <v:fill></v:fill>
* </v:oval>
*
*
* SVG:
* <ellipse stroke="#023BB9" visibility="hidden" fill="#E0E5EF" stroke-width="0.5px" cy="3" cx="3" ry="3" rx="3"
* height="6" width="6"></ellipse>
*/
final Style style = Style.parse(vmlOval.getStyle());
Ellipse svgElipse = null;
if (style.isVisible()) {
svgElipse = new Ellipse();
float width = style.getWidth();
svgElipse.setWidth(width);
svgElipse.setRx(width / 2);
float height = style.getHeight();
svgElipse.setHeight(height);
svgElipse.setRy(height / 2);
String top = style.getTop();
svgElipse.setCy(Float.parseFloat(top) + (width / 2));
String left = style.getLeft();
svgElipse.setCx(Float.parseFloat(left) + (height / 2));
// Fill properties ...
final String fillColor = vmlOval.getFillcolor();
svgElipse.setFill(fillColor);
// Stroke properties ...
final String strokeColor = vmlOval.getStrokecolor();
svgElipse.setStroke(strokeColor);
svgElipse.setStrokeWidth("0.5px");
}
return svgElipse;
}
private com.wisemapping.xml.svgmap.Line convert(final Line vmlLine) {
/**
* VML:
* <v:line style="POSITION: absolute" from="0,0" to="157,-150" fillcolor="white" stroked="t" strokecolor="#495879"
* strokeweight="1px">
* <:stroke dashstyle="solid"></v:stroke>
* </v:line>
*
* SVG:
* <line y2="14" x2="49" y1="14" x1="-1" visibility="hidden" style="cursor: move;" stroke="#495879"
stroke-width="1px"></line>
*/
com.wisemapping.xml.svgmap.Line svgLine = new com.wisemapping.xml.svgmap.Line();
final String from = vmlLine.getFrom();
final String[] fromPoints = from.split(",");
svgLine.setX1(Float.parseFloat(fromPoints[0]));
svgLine.setY1(Float.parseFloat(fromPoints[1]));
final String to = vmlLine.getTo();
final String[] toPoints = to.split(",");
svgLine.setX2(Float.parseFloat(toPoints[0]));
svgLine.setY2(Float.parseFloat(toPoints[1]));
String strokeweight = vmlLine.getStrokeweight();
svgLine.setStrokeWidth(strokeweight);
String stokeColor = vmlLine.getStrokecolor();
svgLine.setStroke(stokeColor);
return svgLine;
}
private Text convertTextShape(Shape vmlTextShape, float boxWidth, float boxHeigth) {
/**
* <v:shape
* style="Z-INDEX: 10; LEFT: 9px; WIDTH: 130px; CURSOR: default; POSITION: absolute; TOP: 9px; HEIGHT: 1px; antialias: true"
* coordsize="100,100">
* <v:textbox
* style="MARGIN-TOP: 0.187pt; LEFT: auto; FONT: bold 19px verdana; MARGIN-LEFT: 0.25pt; OVERFLOW: visible; WIDTH: 138.531pt; COLOR: #023bb9; POSITION: absolute; TOP: auto; HEIGHT: 0.343pt"
* xFontScale="1.4" xTextSize="100.1,16.0" inset="0,0,0,0">
* <SPAN style="WIDTH: 100%; HEIGHT: 100%">
* <SPAN>Central Topic</SPAN>
* </SPAN>
* </v:textbox>
* </v:shape>
* SVG:
* <text x="9" y="19" style="cursor: default;" fill="#023BB9" font-weight="bold" font-style="normal"
* font-size="13.4375" font-family="verdana" focusable="true">Central Topic
* </text>
*/
final Text svgText = new Text();
Textbox vmlTextBox = vmlTextShape.getTextbox();
final String textBoxStyleStr = vmlTextBox.getStyle();
final Style textBoxStyle = Style.parse(textBoxStyleStr);
// @todo: Take this hardcode from javascript ...
float fontSize = textBoxStyle.getFontSize();
float scale = vmlTextBox.getXFontScale();
float svgFontSize = fontSize / scale;
svgText.setFontSize(svgFontSize);
// Set text properties...
final String textValue = vmlTextBox.getSPAN().getSPAN();
svgText.setContent(textValue);
final String color = textBoxStyle.getColor();
svgText.setFill(color);
final String fontWidth = textBoxStyle.getFontWidth();
svgText.setFontWeight(fontWidth);
// Positionate font...
final String textSize = vmlTextBox.getXTextSize();
final String[] split = textSize.split(",");
float textWidth = Float.valueOf(split[0]);
float textHeight = Float.valueOf(split[1]);
svgText.setX(boxWidth - textWidth);
svgText.setY(boxHeigth - textHeight + CORRECTION_HANDCODE);
return svgText;
}
private com.wisemapping.xml.svgmap.Rect convert(Roundrect vmlRect) {
/*
* VML:
* <v:roundrect style="LEFT: 0px; WIDTH: 62px; CURSOR: move; POSITION: absolute; TOP: 0px; HEIGHT: 23px"
* arcsize="9830f" coordsize="21600,21600" fillcolor="#e0e5ef" stroked="t" strokecolor="#023bb9"
* strokeweight="6762emu">
* <v:stroke dashstyle="solid"></v:stroke>
* <v:fill></v:fill>
* </v:roundrect>
*
* SVG:
* <rect style="cursor: move;" fill="#E0E5EF" stroke="#023BB9" stroke-width="0.5px" y="0" x="0" ry="2.7" rx="2.7"
* height="18" width="68"></rect>
*
*/
final com.wisemapping.xml.svgmap.Rect svgRect = new com.wisemapping.xml.svgmap.Rect();
final Style style = Style.parse(vmlRect.getStyle());
svgRect.setRy(2.7F);
svgRect.setRx(2.7F);
float width = style.getWidth();
svgRect.setWidth(String.valueOf(width));
float height = style.getHeight();
svgRect.setHeight(height);
String top = style.getTop();
svgRect.setY(Float.parseFloat(top));
String left = style.getLeft();
svgRect.setX(Float.parseFloat(left));
// Fill properties ...
final String fillColor = vmlRect.getFillcolor();
svgRect.setFill(fillColor);
// Stroke properties ...
final String strokeColor = vmlRect.getStrokecolor();
svgRect.setStroke(strokeColor);
svgRect.setStrokeWidth("0.5px");
return svgRect;
}
private com.wisemapping.xml.svgmap.Polyline convert(Polyline vmlPolyline) {
/*
* <v:polyline style="POSITION: absolute" rPoints="167.1, 100.0 177.1, 100.0 177.1, 130.5 182.1, 135.5 230.6, 135.5"
* filled="f" strokecolor="#495879" strokeweight=".75pt">
* <v:stroke opacity="1" dashstyle="solid"></v:stroke>
* </v:polyline>
*
* <polyline points="173.5,100 183.5,100 183.5,129 188.5,134 240,134" stroke-opacity="1" stroke="#495879"
* stroke-width="1px" fill="none"></polyline>
*/
final com.wisemapping.xml.svgmap.Polyline svgPolyline = svgObjectFactory.createPolyline();
final String rPoints = vmlPolyline.getXPoints();
svgPolyline.setPoints(rPoints);
final String strokeColor = vmlPolyline.getStrokecolor();
svgPolyline.setStroke(strokeColor);
// @todo: Take from SVG.
svgPolyline.setFill("none");
svgPolyline.setStrokeWidth("1px");
svgPolyline.setStrokeOpacity("1");
return svgPolyline;
}
public void toXml(OutputStream os) throws JAXBException {
final JAXBContext svgContext = JAXBContext.newInstance("com.wisemapping.xml.svgmap");
Marshaller m = svgContext.createMarshaller();
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
m.marshal(svgRootElem, os);
}
}