SVG importer rounding problem fixed

This commit is contained in:
honfika@gmail.com
2017-04-01 17:25:49 +02:00
parent 276ea972f2
commit d2504e5e71
2 changed files with 50 additions and 32 deletions

View File

@@ -43,6 +43,12 @@ public final class Matrix implements Cloneable {
return mat;
}
public static Matrix getScaleInstance(double scaleX, double scaleY) {
Matrix mat = new Matrix();
mat.scale(scaleX, scaleY);
return mat;
}
public static Matrix getTranslateInstance(double x, double y) {
Matrix mat = new Matrix();
mat.translate(x, y);
@@ -200,6 +206,13 @@ public final class Matrix implements Cloneable {
rotateSkew1 *= factor;
}
public void scale(double factorX, double factorY) {
scaleX *= factorX;
scaleY *= factorY;
rotateSkew0 *= factorX;
rotateSkew1 *= factorY;
}
public Matrix concatenate(Matrix m) {
Matrix result = new Matrix();
result.scaleX = scaleX * m.scaleX + rotateSkew1 * m.rotateSkew0;

View File

@@ -100,6 +100,14 @@ public class SvgImporter {
shapes.lineStyles.lineStyles = new LINESTYLE[0];
int shapeNum = st.getShapeNum();
RECT rect = st.getRect();
int origXmin = rect.Xmin;
int origYmin = rect.Ymin;
rect.Xmin -= origXmin;
rect.Xmax -= origXmin;
rect.Ymin -= origYmin;
rect.Ymax -= origYmin;
shapes.shapeRecords = new ArrayList<>();
Rectangle2D.Double viewBox = null;
@@ -165,6 +173,18 @@ public class SvgImporter {
SvgStyle style = new SvgStyle(this, idMap, rootElement);
Matrix transform = new Matrix();
if (!fill) {
rect.Xmin = (int) Math.round(viewBox.x * SWF.unitDivisor);
rect.Ymin = (int) Math.round(viewBox.y * SWF.unitDivisor);
rect.Xmax = (int) Math.round((viewBox.x + viewBox.width) * SWF.unitDivisor);
rect.Ymax = (int) Math.round((viewBox.y + viewBox.height) * SWF.unitDivisor);
} else {
double ratioX = rect.getWidth() / width / SWF.unitDivisor;
double ratioY = rect.getHeight() / height / SWF.unitDivisor;
transform = Matrix.getScaleInstance(ratioX, ratioY);
}
processSvgObject(idMap, shapeNum, shapes, rootElement, transform, style);
} catch (SAXException | IOException | ParserConfigurationException ex) {
Logger.getLogger(ShapeImporter.class.getName()).log(Level.SEVERE, null, ex);
@@ -172,27 +192,6 @@ public class SvgImporter {
shapes.shapeRecords.add(new EndShapeRecord());
RECT rect = st.getRect();
int origXmin = rect.Xmin;
int origYmin = rect.Ymin;
rect.Xmin -= origXmin;
rect.Xmax -= origXmin;
rect.Ymin -= origYmin;
rect.Ymax -= origYmin;
if (!fill && viewBox != null) {
rect.Xmin = (int) Math.round(viewBox.x * SWF.unitDivisor);
rect.Ymin = (int) Math.round(viewBox.y * SWF.unitDivisor);
rect.Xmax = (int) Math.round((viewBox.x + viewBox.width) * SWF.unitDivisor);
rect.Ymax = (int) Math.round((viewBox.y + viewBox.height) * SWF.unitDivisor);
} else if (viewBox != null) {
double width = viewBox.width * SWF.unitDivisor;
double height = viewBox.height * SWF.unitDivisor;
double radioX = rect.getWidth() / width;
double radioY = rect.getHeight() / height;
shapes = shapes.resize(radioX, radioY);
}
st.shapes = shapes;
st.setModified(true);
@@ -279,7 +278,13 @@ public class SvgImporter {
double x = x0;
double y = y0;
Point p;
char cmd = Character.toUpperCase(command.command);
boolean isRelative = Character.isLowerCase(command.command);
if (isRelative) {
throw new Error("processCommands is called with relative command");
}
char cmd = command.command;
switch (cmd) {
case 'M':
StyleChangeRecord scr = new StyleChangeRecord();
@@ -298,18 +303,18 @@ public class SvgImporter {
p = transform2.transform(x, y);
scr.moveDeltaX = (int) Math.round(p.x);
scr.moveDeltaY = (int) Math.round(p.y);
prevPoint = p;
prevPoint = new Point(scr.moveDeltaX, scr.moveDeltaY);
scr.stateMoveTo = true;
newRecords.add(scr);
startPoint = p;
startPoint = prevPoint;
break;
case 'Z':
StraightEdgeRecord serz = new StraightEdgeRecord();
p = startPoint;
serz.deltaX = (int) Math.round(p.x - prevPoint.x);
serz.deltaY = (int) Math.round(p.y - prevPoint.y);
prevPoint = p;
prevPoint = new Point(prevPoint.x + serz.deltaX, prevPoint.y + serz.deltaY);
serz.generalLineFlag = true;
newRecords.add(serz);
if (lineStyle2Obj != null) {
@@ -324,7 +329,7 @@ public class SvgImporter {
p = transform2.transform(x, y);
serl.deltaX = (int) Math.round(p.x - prevPoint.x);
serl.deltaY = (int) Math.round(p.y - prevPoint.y);
prevPoint = p;
prevPoint = new Point(prevPoint.x + serl.deltaX, prevPoint.y + serl.deltaY);
serl.generalLineFlag = true;
serl.simplify();
newRecords.add(serl);
@@ -335,7 +340,7 @@ public class SvgImporter {
p = transform2.transform(x, y);
serh.deltaX = (int) Math.round(p.x - prevPoint.x);
prevPoint = p;
prevPoint = new Point(prevPoint.x + serh.deltaX, prevPoint.y/* + serh.deltaY*/);
newRecords.add(serh);
break;
case 'V':
@@ -344,7 +349,7 @@ public class SvgImporter {
p = transform2.transform(x, y);
serv.deltaY = (int) Math.round(p.y - prevPoint.y);
prevPoint = p;
prevPoint = new Point(prevPoint.x/* + serv.deltaX*/, prevPoint.y + serv.deltaY);
serv.vertLineFlag = true;
newRecords.add(serv);
break;
@@ -356,7 +361,7 @@ public class SvgImporter {
p = transform2.transform(x, y);
cer.controlDeltaX = (int) Math.round(p.x - prevPoint.x);
cer.controlDeltaY = (int) Math.round(p.y - prevPoint.y);
prevPoint = p;
prevPoint = new Point(prevPoint.x + cer.controlDeltaX, prevPoint.y + cer.controlDeltaY);
x = command.params[2];
y = command.params[3];
@@ -364,7 +369,7 @@ public class SvgImporter {
p = transform2.transform(x, y);
cer.anchorDeltaX = (int) Math.round(p.x - prevPoint.x);
cer.anchorDeltaY = (int) Math.round(p.y - prevPoint.y);
prevPoint = p;
prevPoint = new Point(prevPoint.x + cer.anchorDeltaX, prevPoint.y + cer.anchorDeltaY);
newRecords.add(cer);
break;
case 'C':
@@ -400,12 +405,12 @@ public class SvgImporter {
p = new Point(quadCoordinates.get(i++), quadCoordinates.get(i++));
cerc.controlDeltaX = (int) Math.round(p.x - prevPoint.x);
cerc.controlDeltaY = (int) Math.round(p.y - prevPoint.y);
prevPoint = p;
prevPoint = new Point(prevPoint.x + cerc.controlDeltaX, prevPoint.y + cerc.controlDeltaY);
p = new Point(quadCoordinates.get(i++), quadCoordinates.get(i++));
cerc.anchorDeltaX = (int) Math.round(p.x - prevPoint.x);
cerc.anchorDeltaY = (int) Math.round(p.y - prevPoint.y);
prevPoint = p;
prevPoint = new Point(prevPoint.x + cerc.anchorDeltaX, prevPoint.y + cerc.anchorDeltaY);
newRecords.add(cerc);
}