From 7c2311ed308123477c7f85e51ebffe030dca0223 Mon Sep 17 00:00:00 2001 From: Honfika Date: Mon, 27 Jan 2014 22:11:16 +0100 Subject: [PATCH] image rendering fixes --- .../flash/exporters/BitmapExporter.java | 18 +++++++++-- .../flash/exporters/SVGShapeExporter.java | 8 +++++ .../flash/exporters/ShapeExporterBase.java | 32 ++++++++++++------- .../flash/types/shaperecords/SHAPERECORD.java | 19 +++++++++++ 4 files changed, 63 insertions(+), 14 deletions(-) diff --git a/trunk/src/com/jpexs/decompiler/flash/exporters/BitmapExporter.java b/trunk/src/com/jpexs/decompiler/flash/exporters/BitmapExporter.java index 2eb771552..878e7d768 100644 --- a/trunk/src/com/jpexs/decompiler/flash/exporters/BitmapExporter.java +++ b/trunk/src/com/jpexs/decompiler/flash/exporters/BitmapExporter.java @@ -22,10 +22,12 @@ import com.jpexs.decompiler.flash.tags.base.ImageTag; import com.jpexs.decompiler.flash.types.FILLSTYLE; import com.jpexs.decompiler.flash.types.GRADIENT; import com.jpexs.decompiler.flash.types.GRADRECORD; +import com.jpexs.decompiler.flash.types.LINESTYLE; import com.jpexs.decompiler.flash.types.LINESTYLE2; import com.jpexs.decompiler.flash.types.RECT; import com.jpexs.decompiler.flash.types.RGB; import com.jpexs.decompiler.flash.types.SHAPE; +import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE; import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD; import com.jpexs.helpers.Cache; import java.awt.BasicStroke; @@ -101,10 +103,20 @@ public class BitmapExporter extends ShapeExporterBase implements IShapeExporter return; } RECT bounds = SHAPERECORD.getBounds(records); - xMin = bounds.Xmin / unitDivisor - 1; - yMin = bounds.Ymin / unitDivisor - 1; + int maxLineWidthTwips = 0; + if (shape instanceof SHAPEWITHSTYLE) { + SHAPEWITHSTYLE shapeWithStyle = (SHAPEWITHSTYLE) shape; + for (LINESTYLE lineStyle : shapeWithStyle.lineStyles.lineStyles) { + if (lineStyle.width > maxLineWidthTwips) { + maxLineWidthTwips = lineStyle.width; + } + } + } + double maxLineWidth = maxLineWidthTwips / unitDivisor / 2; + xMin = bounds.Xmin / unitDivisor - maxLineWidth; + yMin = bounds.Ymin / unitDivisor - maxLineWidth; image = new BufferedImage( - (int) (bounds.getWidth() / unitDivisor + 3), (int) (bounds.getHeight() / unitDivisor + 3), BufferedImage.TYPE_INT_ARGB); + (int) (bounds.getWidth() / unitDivisor + 2 + maxLineWidth), (int) (bounds.getHeight() / unitDivisor + 2 + maxLineWidth), BufferedImage.TYPE_INT_ARGB); graphics = (Graphics2D) image.getGraphics(); graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR); graphics.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); diff --git a/trunk/src/com/jpexs/decompiler/flash/exporters/SVGShapeExporter.java b/trunk/src/com/jpexs/decompiler/flash/exporters/SVGShapeExporter.java index 433819853..b26dcadf7 100644 --- a/trunk/src/com/jpexs/decompiler/flash/exporters/SVGShapeExporter.java +++ b/trunk/src/com/jpexs/decompiler/flash/exporters/SVGShapeExporter.java @@ -69,6 +69,7 @@ public class SVGShapeExporter extends DefaultSVGShapeExporter { protected List gradients; protected int lastPatternId; private final SWF swf; + private double maxLineWidth; public SVGShapeExporter(SWF swf, SHAPE shape) { super(shape); @@ -114,6 +115,10 @@ public class SVGShapeExporter extends DefaultSVGShapeExporter { @Override public void endShape(double xMin, double yMin, double xMax, double yMax) { + xMin -= maxLineWidth; + xMax += maxLineWidth; + yMin -= maxLineWidth; + yMax += maxLineWidth; _svgG.setAttribute("transform", "matrix(1, 0, 0, 1, " + roundPixels20(-xMin) + ", " + roundPixels20(-yMin) + ")"); } @@ -215,6 +220,9 @@ public class SVGShapeExporter extends DefaultSVGShapeExporter { @Override public void lineStyle(double thickness, RGB color, boolean pixelHinting, String scaleMode, int startCaps, int endCaps, int joints, int miterLimit) { finalizePath(); + if (thickness > maxLineWidth) { + maxLineWidth = thickness; + } path.setAttribute("fill", "none"); path.setAttribute("stroke", color.toHexRGB()); path.setAttribute("stroke-width", Double.toString(thickness == 0 ? 1 : thickness)); diff --git a/trunk/src/com/jpexs/decompiler/flash/exporters/ShapeExporterBase.java b/trunk/src/com/jpexs/decompiler/flash/exporters/ShapeExporterBase.java index 4d86e32d2..5751e7dc4 100644 --- a/trunk/src/com/jpexs/decompiler/flash/exporters/ShapeExporterBase.java +++ b/trunk/src/com/jpexs/decompiler/flash/exporters/ShapeExporterBase.java @@ -230,20 +230,30 @@ public abstract class ShapeExporterBase implements IShapeExporter { private void calculateBound(IEdge edge) { Point from = edge.getFrom(); Point to = edge.getTo(); - if (from.x < bounds.xMin) { - bounds.xMin = from.x; - } - if (from.x > bounds.xMax) { - bounds.xMax = from.x; - } - if (to.y < bounds.yMin) { - bounds.yMin = to.y; - } - if (to.y > bounds.yMax) { - bounds.yMax = to.y; + calculateBound(from); + calculateBound(to); + if (edge instanceof CurvedEdge) { + CurvedEdge curvedEdge = (CurvedEdge) edge; + Point control = curvedEdge.getControl(); + calculateBound(control); } } + private void calculateBound(Point point) { + if (point.x < bounds.xMin) { + bounds.xMin = point.x; + } + if (point.x > bounds.xMax) { + bounds.xMax = point.x; + } + if (point.y < bounds.yMin) { + bounds.yMin = point.y; + } + if (point.y > bounds.yMax) { + bounds.yMax = point.y; + } + } + protected void exportFillPath(int groupIndex) { List path = createPathFromEdgeMap(fillEdgeMaps.get(groupIndex)); Point pos = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE); diff --git a/trunk/src/com/jpexs/decompiler/flash/types/shaperecords/SHAPERECORD.java b/trunk/src/com/jpexs/decompiler/flash/types/shaperecords/SHAPERECORD.java index 56e162463..a9ec33757 100644 --- a/trunk/src/com/jpexs/decompiler/flash/types/shaperecords/SHAPERECORD.java +++ b/trunk/src/com/jpexs/decompiler/flash/types/shaperecords/SHAPERECORD.java @@ -87,6 +87,25 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters, Seriali min_x = x; } } + if (r instanceof CurvedEdgeRecord) { + CurvedEdgeRecord curverEdge = (CurvedEdgeRecord) r; + int x2 = x + curverEdge.controlDeltaX; + int y2 = y + curverEdge.controlDeltaY; + if (x2 > max_x) { + max_x = x2; + } + if (y2 > max_y) { + max_y = y2; + } + if (started) { + if (y2 < min_y) { + min_y = y2; + } + if (x2 < min_x) { + min_x = x2; + } + } + } } return new RECT(min_x, max_x, min_y, max_y); }