improved exporter for SVG

This commit is contained in:
hneemann 2016-04-01 12:01:57 +02:00
parent 953c3b9edf
commit 9a98599da7
10 changed files with 154 additions and 16 deletions

View File

@ -19,7 +19,11 @@ public class GraphicSVG implements Graphic, Closeable {
}
public GraphicSVG(File file, Vector min, Vector max, File source, int svgScale) throws IOException {
w = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "utf-8"));
this(new FileOutputStream(file), min, max, source, svgScale);
}
public GraphicSVG(OutputStream out, Vector min, Vector max, File source, int svgScale) throws IOException {
w = new BufferedWriter(new OutputStreamWriter(out, "utf-8"));
w.write("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
"<!-- Created with Digital by H.Neemann -->\n");
w.write("<!-- created: " + new Date() + " -->\n");
@ -55,7 +59,7 @@ public class GraphicSVG implements Graphic, Closeable {
// addStrokeDash(w, style.getDashArray());
w.write(" />\n");
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@ -74,7 +78,7 @@ public class GraphicSVG implements Graphic, Closeable {
// addStrokeDash(w, style.getDashArray());
w.write(" stroke=\"" + getColor(style) + "\" stroke-width=\"" + getStrokeWidth(style) + "\" fill=\"none\"/>\n");
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@ -96,7 +100,7 @@ public class GraphicSVG implements Graphic, Closeable {
w.write(" />\n");
}
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@ -105,7 +109,7 @@ public class GraphicSVG implements Graphic, Closeable {
if (text == null || text.length() == 0) return;
try {
text = escapeXML(text);
text = formatText(text, style.getFontSize());
boolean rotateText = false;
if (p1.y == p2.y) { // 0 and 180 deg
@ -137,15 +141,19 @@ public class GraphicSVG implements Graphic, Closeable {
else
w.write("<text text-anchor=\"" + getAchor(orientation.getX()) + "\" x=\"" + p.x + "\" y=\"" + p.y + "\" fill=\"" + getColor(style) + "\" style=\"font-size:" + style.getFontSize() + "\">" + text + "</text>\n");
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
public String formatText(String text, int fontSize) {
return escapeXML(text);
}
public String getColor(Style style) {
return "#" + Integer.toHexString(style.getColor().getRGB()).substring(2);
}
private String escapeXML(String text) {
public String escapeXML(String text) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);

View File

@ -0,0 +1,56 @@
package de.neemann.digital.draw.graphics;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
/**
* @author hneemann
*/
public class GraphicSVGIndex extends GraphicSVG {
public GraphicSVGIndex(File file, Vector min, Vector max) throws IOException {
super(file, min, max);
}
public GraphicSVGIndex(OutputStream out, Vector min, Vector max, File source, int svgScale) throws IOException {
super(out, min, max, source, svgScale);
}
@Override
public String formatText(String text, int fontSize) {
return formatSVGIndex(escapeXML(formatIndex(text)));
}
public String formatIndex(String text) {
int p = text.lastIndexOf("_");
if (p > 0) {
text = text.substring(0, p) + "_{" + text.substring(p + 1) + "}";
}
return text;
}
private String formatSVGIndex(String text) {
int p1;
while ((p1 = text.indexOf("_{")) >= 0) {
int p2 = text.indexOf('}', p1);
if (p2 >= 0) {
String ind = text.substring(p1 + 2, p2);
if (ind.length() > 0)
ind = "<tspan style=\"font-size:80%;baseline-shift:sub\">" + ind + "</tspan>";
text = text.substring(0, p1) + ind + text.substring(p2 + 1);
}
}
while ((p1 = text.indexOf("^{")) >= 0) {
int p2 = text.indexOf('}', p1);
if (p2 >= 0) {
String ind = text.substring(p1 + 2, p2);
if (ind.length() > 0)
ind = "<tspan style=\"font-size:80%;baseline-shift:super\">" + ind + "</tspan>";
text = text.substring(0, p1) + ind + text.substring(p2 + 1);
}
}
return text;
}
}

View File

@ -2,6 +2,7 @@ package de.neemann.digital.draw.graphics;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
/**
* @author hneemann
@ -11,8 +12,13 @@ public class GraphicSVGLaTeX extends GraphicSVG {
super(file, min, max);
}
public GraphicSVGLaTeX(OutputStream out, Vector min, Vector max, File source, int svgScale) throws IOException {
super(out, min, max, source, svgScale);
}
@Override
public void drawText(Vector p1, Vector p2, String text, Orientation orientation, Style style) {
public String formatText(String text, int fontSize) {
text = formatIndex(text);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < text.length(); i++) {
char c = text.charAt(i);
@ -31,9 +37,21 @@ public class GraphicSVGLaTeX extends GraphicSVG {
sb.append(c);
}
}
super.drawText(p1, p2, sb.toString(), orientation, style);
text = sb.toString();
if (fontSize < Style.NORMAL.getFontSize())
text = "{\\scriptsize " + text + "}";
return escapeXML(text);
}
public String formatIndex(String text) {
int p = text.lastIndexOf("_");
if (p > 0) {
text = "$" + text.substring(0, p) + "_{" + text.substring(p + 1) + "}$";
}
return text;
}
@Override
public void drawCircle(Vector p1, Vector p2, Style style) {
if ((style != Style.WIRE && style != Style.WIRE_OUT) || Math.abs(p1.x - p2.x) > 2)

View File

@ -99,15 +99,15 @@ public class GenericShape implements Shape {
graphic.drawPolygon(new Polygon(true)
.add(1, -SIZE2)
.add(SIZE * width - 1, -SIZE2)
.add(SIZE * width - 1, height)
.add(SIZE * width - (invert ? 0 : 1), -SIZE2)
.add(SIZE * width - (invert ? 0 : 1), height)
.add(1, height), Style.NORMAL);
if (invert) {
int offs = symmetric ? inputs.length / 2 * SIZE : 0;
for (int i = 0; i < outputs.length; i++)
graphic.drawCircle(new Vector(SIZE * width, i * SIZE - SIZE2 + 1 + offs),
new Vector(SIZE * (width + 1) - 2, i * SIZE + SIZE2 - 1 + offs), Style.NORMAL);
graphic.drawCircle(new Vector(SIZE * width + 1, i * SIZE - SIZE2 + 1 + offs),
new Vector(SIZE * (width + 1) - 1, i * SIZE + SIZE2 - 1 + offs), Style.NORMAL);
}

View File

@ -51,7 +51,7 @@ public class LEDShape implements Shape {
fill = true;
}
Vector center = new Vector(2 + SIZE, 0);
Vector center = new Vector(1 + SIZE, 0);
graphic.drawCircle(center.sub(RADL), center.add(RADL), Style.FILLED);
if (fill)
graphic.drawCircle(center.sub(RAD), center.add(RAD), onStyle);

View File

@ -48,7 +48,7 @@ public class OutputShape implements Shape {
}
}
Vector center = new Vector(2 + SIZE, 0);
Vector center = new Vector(1 + SIZE, 0);
graphic.drawCircle(center.sub(RAD), center.add(RAD), style);
graphic.drawCircle(center.sub(RADL), center.add(RADL), Style.NORMAL);
Vector textPos = new Vector(SIZE * 3, 0);

View File

@ -160,7 +160,7 @@ public class Main extends JFrame implements ClosingWindowListener.ConfirmSave {
JMenu export = new JMenu(Lang.get("menu_export"));
export.add(new ExportAction(Lang.get("menu_exportSVG"), "svg", GraphicSVG::new));
export.add(new ExportAction(Lang.get("menu_exportSVG"), "svg", GraphicSVGIndex::new));
export.add(new ExportAction(Lang.get("menu_exportSVGLaTex"), "svg", GraphicSVGLaTeX::new));

View File

@ -0,0 +1,16 @@
package de.neemann.digital.draw.graphics;
import junit.framework.TestCase;
/**
* @author hneemann
*/
public class GraphicSVGIndexTest extends TestCase {
public void testFormatText() throws Exception {
GraphicSVGIndex gs = new GraphicSVGIndex(System.out, new Vector(0, 0), new Vector(30, 30), null, 30);
assertEquals("Z<tspan style=\"font-size:80%;baseline-shift:sub\">0</tspan>", gs.formatText("Z0", 0));
assertEquals("&lt;a&gt;", gs.formatText("<a>", 0));
}
}

View File

@ -0,0 +1,24 @@
package de.neemann.digital.draw.graphics;
import junit.framework.TestCase;
/**
* @author hneemann
*/
public class GraphicSVGLaTeXTest extends TestCase {
public void testFormatText() throws Exception {
GraphicSVGLaTeX gs = new GraphicSVGLaTeX(System.out, new Vector(0, 0), new Vector(30, 30), null, 30);
assertEquals("$Z_{0}$", gs.formatText("Z_0", Style.NORMAL.getFontSize()));
assertEquals("\\&amp;", gs.formatText("&", Style.NORMAL.getFontSize()));
assertEquals("$\\geq$1", gs.formatText("\u22651", Style.NORMAL.getFontSize()));
assertEquals("$\\neg$Q", gs.formatText("~Q", Style.NORMAL.getFontSize()));
assertEquals("&lt;a&gt;", gs.formatText("<a>", Style.NORMAL.getFontSize()));
assertEquals("Grün", gs.formatText("Grün", Style.NORMAL.getFontSize()));
assertEquals("{\\scriptsize Grün}", gs.formatText("Grün", Style.SHAPE_PIN.getFontSize()));
assertEquals("{\\scriptsize $Z_{0}$}", gs.formatText("Z_0", Style.SHAPE_PIN.getFontSize()));
}
}

View File

@ -0,0 +1,16 @@
package de.neemann.digital.draw.graphics;
import junit.framework.TestCase;
/**
* @author hneemann
*/
public class GraphicSVGTest extends TestCase {
public void testFormatText() throws Exception {
GraphicSVG gs = new GraphicSVG(System.out, new Vector(0, 0), new Vector(30, 30), null, 30);
assertEquals("Z0", gs.formatText("Z0", 0));
assertEquals("&lt;a&gt;", gs.formatText("<a>", 0));
}
}