#369: SVG export fix

This commit is contained in:
Honfika
2014-01-22 23:59:40 +01:00
parent ae781b16bb
commit a6b031b1a8
12 changed files with 47 additions and 28 deletions
@@ -63,7 +63,7 @@ public class DefineShape2Tag extends CharacterTag implements BoundedTag, ShapeTa
@Override
public String toSVG() {
return shapes.toSVG(2, swf.tags);
return shapes.toSVG(2, swf.tags, shapeBounds);
}
@Override
@@ -68,7 +68,7 @@ public class DefineShape3Tag extends CharacterTag implements BoundedTag, ShapeTa
@Override
public String toSVG() {
return shapes.toSVG(3, swf.tags);
return shapes.toSVG(3, swf.tags, shapeBounds);
}
@Override
@@ -67,7 +67,7 @@ public class DefineShape4Tag extends CharacterTag implements BoundedTag, ShapeTa
@Override
public String toSVG() {
return shapes.toSVG(4, swf.tags);
return shapes.toSVG(4, swf.tags, shapeBounds);
}
@Override
@@ -76,7 +76,7 @@ public class DefineShapeTag extends CharacterTag implements BoundedTag, ShapeTag
@Override
public String toSVG() {
return shapes.toSVG(1, swf.tags);
return shapes.toSVG(1, swf.tags, shapeBounds);
}
@Override
@@ -51,7 +51,7 @@ public class SHAPE implements NeedsCharacters {
* @return String with XML representation of this shape (SVG)
*/
public String toSVG(int shapeNum, List<Tag> tags) {
return SHAPERECORD.shapeToSVG(tags, shapeNum, null, null, numFillBits, numLineBits, shapeRecords);
return SHAPERECORD.shapeToSVG(tags, shapeNum, null, null, numFillBits, numLineBits, shapeRecords, new RECT());
}
public BufferedImage toImage(int shapeNum, List<Tag> tags, Color defaultColor, boolean putToCache) {
@@ -50,10 +50,12 @@ public class SHAPEWITHSTYLE implements NeedsCharacters {
* Converts shape to SVG
*
* @param shapeNum Type of DefineShape
* @param tags
* @param bounds
* @return String with XML representation of this shape (SVG)
*/
public String toSVG(int shapeNum, List<Tag> tags) {
return SHAPERECORD.shapeToSVG(tags, shapeNum, fillStyles, lineStyles, numFillBits, numLineBits, shapeRecords);
public String toSVG(int shapeNum, List<Tag> tags, RECT bounds) {
return SHAPERECORD.shapeToSVG(tags, shapeNum, fillStyles, lineStyles, numFillBits, numLineBits, shapeRecords, bounds);
}
public BufferedImage toImage(int shapeNum, List<Tag> tags) {
@@ -39,8 +39,12 @@ public class CurvedEdgeRecord extends SHAPERECORD {
}
@Override
public String toSWG(int oldX, int oldY) {
return "Q " + SWF.twipToPixel(oldX + controlDeltaX) + " " + SWF.twipToPixel(oldY + controlDeltaY) + " " + SWF.twipToPixel(oldX + controlDeltaX + anchorDeltaX) + " " + SWF.twipToPixel(oldY + controlDeltaY + anchorDeltaY);
public String toSVG(int oldX, int oldY, SVGRenderingContext context) {
String result = "";
if (!context.wasMoveTo) {
result = "M " + SWF.twipToPixel(oldX) + " " + SWF.twipToPixel(oldY) + " ";
}
return result + "Q " + SWF.twipToPixel(oldX + controlDeltaX) + " " + SWF.twipToPixel(oldY + controlDeltaY) + " " + SWF.twipToPixel(oldX + controlDeltaX + anchorDeltaX) + " " + SWF.twipToPixel(oldY + controlDeltaY + anchorDeltaY);
}
@@ -31,7 +31,7 @@ public class EndShapeRecord extends SHAPERECORD {
}
@Override
public String toSWG(int oldX, int oldY) {
public String toSVG(int oldX, int oldY, SVGRenderingContext context) {
return "";
}
@@ -55,6 +55,7 @@ import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
@@ -101,7 +102,7 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters, Seriali
public Point start;
public Point end;
public void draw(int startX, int startY, Graphics2D g, int shapeNum) {
private void draw(int startX, int startY, Graphics2D g, int shapeNum) {
AffineTransform oldAf = g.getTransform();
AffineTransform trans20 = AffineTransform.getScaleInstance(1 / DESCALE, 1 / DESCALE);
boolean ok = false;
@@ -161,7 +162,7 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters, Seriali
g.setClip(null);
}
public void fill(List<Tag> tags, int startX, int startY, Graphics2D g, int shapeNum) {
private void fill(List<Tag> tags, int startX, int startY, Graphics2D g, int shapeNum) {
if (fillStyle0 == null) {
return;
}
@@ -480,8 +481,9 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters, Seriali
String points = "";
int x = 0;
int y = 0;
context.wasMoveTo = false;
for (SHAPERECORD r : edges) {
points += " " + r.toSWG(x, y);
points += " " + r.toSVG(x, y, context);
x = r.changeX(x);
y = r.changeY(y);
}
@@ -490,7 +492,7 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters, Seriali
}
}
public abstract String toSWG(int oldX, int oldY);
public abstract String toSVG(int oldX, int oldY, SVGRenderingContext context);
public abstract int changeX(int x);
@@ -849,22 +851,25 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters, Seriali
* @param records
* @return Shape converted to SVG
*/
public static String shapeToSVG(List<Tag> tags, int shapeNum, FILLSTYLEARRAY fillStyles, LINESTYLEARRAY lineStylesList, int numFillBits, int numLineBits, List<SHAPERECORD> records) {
public static String shapeToSVG(List<Tag> tags, int shapeNum, FILLSTYLEARRAY fillStyles, LINESTYLEARRAY lineStylesList, int numFillBits, int numLineBits, List<SHAPERECORD> records, RECT bounds) {
String ret = "";
RECT bounds = new RECT();
List<Path> paths = getPaths(bounds, shapeNum, fillStyles, lineStylesList, /*numFillBits, numLineBits,*/ records);
RECT rect = new RECT();
List<Path> paths = getPaths(rect, shapeNum, fillStyles, lineStylesList, /*numFillBits, numLineBits,*/ records);
ret = "";
SVGRenderingContext context = new SVGRenderingContext();
ret += "<g id=\"1\" transform=\"matrix(1, 0, 0, 1, "
+ SWF.twipToPixel(-bounds.Xmin) + ", " + SWF.twipToPixel(-bounds.Ymin) + ")\">\n";
for (Path p : paths) {
ret += p.toSVG(tags, shapeNum, context);
ret += p.toSVG(tags, shapeNum, context) + "\n";
}
ret += "</g>\n";
ret = "<?xml version='1.0' encoding='UTF-8' ?> \n"
+ "<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\" \"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\n"
+ "<svg width=\"" + (int) Math.ceil(SWF.twipToPixel(bounds.Xmax)) + "\"\n"
+ " height=\"" + (int) Math.ceil(SWF.twipToPixel(bounds.Ymax)) + "\"\n"
+ " viewBox=\"0 0 " + (int) Math.ceil(SWF.twipToPixel(bounds.Xmax)) + " " + (int) Math.ceil(SWF.twipToPixel(bounds.Ymax) + 50) + "\"\n"
+ "<svg width=\"" + (int) Math.ceil(SWF.twipToPixel(bounds.Xmax - bounds.Xmin)) + "\"\n"
+ " height=\"" + (int) Math.ceil(SWF.twipToPixel(bounds.Ymax - bounds.Ymin)) + "\"\n"
+ " viewBox=\"0 0 " + (int) Math.ceil(SWF.twipToPixel(bounds.Xmax - bounds.Xmin)) + " " + (int) Math.ceil(SWF.twipToPixel(bounds.Ymax - bounds.Ymin)) + "\"\n"
+ " xmlns=\"http://www.w3.org/2000/svg\"\n"
+ " xmlns:xlink=\"http://www.w3.org/1999/xlink\">" + ret + ""
+ " xmlns:xlink=\"http://www.w3.org/1999/xlink\">\n" + ret + ""
+ "</svg>";
return ret;
}
@@ -24,4 +24,5 @@ package com.jpexs.decompiler.flash.types.shaperecords;
public class SVGRenderingContext {
public int patternCount = 0;
public boolean wasMoveTo;
}
@@ -39,13 +39,17 @@ public class StraightEdgeRecord extends SHAPERECORD {
}
@Override
public String toSWG(int oldX, int oldY) {
public String toSVG(int oldX, int oldY, SVGRenderingContext context) {
String result = "";
if (!context.wasMoveTo) {
result = "M " + SWF.twipToPixel(oldX) + " " + SWF.twipToPixel(oldY) + " ";
}
if (generalLineFlag) {
return "L " + SWF.twipToPixel(oldX + deltaX) + " " + SWF.twipToPixel(oldY + deltaY);
return result + "L " + SWF.twipToPixel(oldX + deltaX) + " " + SWF.twipToPixel(oldY + deltaY);
} else if (vertLineFlag) {
return "V " + SWF.twipToPixel(oldY + deltaY);
return result + "V " + SWF.twipToPixel(oldY + deltaY);
} else {
return "H " + SWF.twipToPixel(oldX + deltaX);
return result + "H " + SWF.twipToPixel(oldX + deltaX);
}
}
@@ -64,9 +64,12 @@ public class StyleChangeRecord extends SHAPERECORD implements Cloneable {
}
@Override
public String toSWG(int oldX, int oldY) {
public String toSVG(int oldX, int oldY, SVGRenderingContext context) {
if (stateMoveTo) {
return "M " + SWF.twipToPixel(moveDeltaX) + " " + SWF.twipToPixel(moveDeltaY);
if ((!context.wasMoveTo) || ((moveDeltaX != oldX) || (moveDeltaY != oldY))) {
context.wasMoveTo = true;
return "M " + SWF.twipToPixel(moveDeltaX) + " " + SWF.twipToPixel(moveDeltaY);
}
}
return "";
}