mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-18 19:08:19 +00:00
Added Support for DefineShape4 nonzero winding rule - display, svg (import, export), canvas export
Fixed Calculating fillBits, lineBits on SHAPE structure (storing morphshapes, fonts)
This commit is contained in:
@@ -1353,11 +1353,15 @@ public class SWFOutputStream extends OutputStream {
|
||||
/**
|
||||
* Writes SHAPE value to the stream
|
||||
*
|
||||
* @param fillStyleCount
|
||||
* @param lineStyleCount
|
||||
* @param value SHAPE value
|
||||
* @param shapeNum 1 in DefineShape, 2 in DefineShape2,...
|
||||
* @throws IOException
|
||||
*/
|
||||
public void writeSHAPE(SHAPE value, int shapeNum) throws IOException {
|
||||
public void writeSHAPE(int fillStyleCount, int lineStyleCount, SHAPE value, int shapeNum) throws IOException {
|
||||
value.numFillBits = getNeededBitsU(fillStyleCount);
|
||||
value.numLineBits = getNeededBitsU(lineStyleCount);
|
||||
writeUB(4, value.numFillBits);
|
||||
writeUB(4, value.numLineBits);
|
||||
writeSHAPERECORDS(value.shapeRecords, value.numFillBits, value.numLineBits, shapeNum);
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.jpexs.decompiler.flash.exporters.settings.FontExportSettings;
|
||||
import com.jpexs.decompiler.flash.exporters.shape.PathExporter;
|
||||
import com.jpexs.decompiler.flash.tags.Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.FontTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.Path;
|
||||
@@ -202,7 +203,7 @@ public class FontExporter {
|
||||
char c = t.glyphToChar(i);
|
||||
SHAPE s = shapes.get(i);
|
||||
final List<FPoint[]> contours = new ArrayList<>();
|
||||
PathExporter seb = new PathExporter(1, swf, s, null) {
|
||||
PathExporter seb = new PathExporter(ShapeTag.WIND_EVEN_ODD, 1, swf, s, null) {
|
||||
|
||||
private double transformX(double x) {
|
||||
return Math.ceil((double) (x / divider));
|
||||
|
||||
@@ -139,7 +139,7 @@ public class ShapeExporter {
|
||||
SHAPE shp = st.getShapes();
|
||||
int deltaX = -shp.getBounds(1).Xmin;
|
||||
int deltaY = -shp.getBounds(1).Ymin;
|
||||
CanvasShapeExporter cse = new CanvasShapeExporter(st.getShapeNum(), null, SWF.unitDivisor / settings.zoom, ((Tag) st).getSwf(), shp, new CXFORMWITHALPHA(), deltaX, deltaY);
|
||||
CanvasShapeExporter cse = new CanvasShapeExporter(st.getWindingRule(), st.getShapeNum(), null, SWF.unitDivisor / settings.zoom, ((Tag) st).getSwf(), shp, new CXFORMWITHALPHA(), deltaX, deltaY);
|
||||
cse.export();
|
||||
Set<Integer> needed = new HashSet<>();
|
||||
needed.add(st.getCharacterId());
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.jpexs.decompiler.flash.exporters.ImageTagBufferedImage;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.ExportRectangle;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.tags.base.ImageTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
|
||||
import com.jpexs.decompiler.flash.types.ColorTransform;
|
||||
import com.jpexs.decompiler.flash.types.FILLSTYLE;
|
||||
import com.jpexs.decompiler.flash.types.GRADIENT;
|
||||
@@ -74,7 +75,7 @@ public class BitmapExporter extends ShapeExporterBase {
|
||||
|
||||
private final SWF swf;
|
||||
|
||||
private final GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD); //For correct intersections display;
|
||||
private final GeneralPath path;
|
||||
|
||||
private Shape aliasedShape;
|
||||
|
||||
@@ -166,16 +167,17 @@ public class BitmapExporter extends ShapeExporterBase {
|
||||
}
|
||||
}
|
||||
|
||||
public static void export(int shapeNum, SWF swf, SHAPE shape, Color defaultColor, SerializableImage image, double unzoom, Matrix transformation, Matrix strokeTransformation, ColorTransform colorTransform, boolean scaleStrokes, boolean canUseSmoothing) {
|
||||
BitmapExporter exporter = new BitmapExporter(shapeNum, swf, shape, defaultColor, colorTransform);
|
||||
public static void export(int windingRule, int shapeNum, SWF swf, SHAPE shape, Color defaultColor, SerializableImage image, double unzoom, Matrix transformation, Matrix strokeTransformation, ColorTransform colorTransform, boolean scaleStrokes, boolean canUseSmoothing) {
|
||||
BitmapExporter exporter = new BitmapExporter(windingRule, shapeNum, swf, shape, defaultColor, colorTransform);
|
||||
exporter.setCanUseSmoothing(canUseSmoothing);
|
||||
exporter.exportTo(shapeNum, image, unzoom, transformation, strokeTransformation, scaleStrokes);
|
||||
}
|
||||
|
||||
private BitmapExporter(int shapeNum, SWF swf, SHAPE shape, Color defaultColor, ColorTransform colorTransform) {
|
||||
super(shapeNum, swf, shape, colorTransform);
|
||||
private BitmapExporter(int windingRule, int shapeNum, SWF swf, SHAPE shape, Color defaultColor, ColorTransform colorTransform) {
|
||||
super(windingRule, shapeNum, swf, shape, colorTransform);
|
||||
this.swf = swf;
|
||||
this.defaultColor = defaultColor;
|
||||
path = new GeneralPath(windingRule == ShapeTag.WIND_NONZERO ? GeneralPath.WIND_NON_ZERO : GeneralPath.WIND_EVEN_ODD);
|
||||
}
|
||||
|
||||
private void exportTo(int shapeNum, SerializableImage image, double unzoom, Matrix transformation, Matrix strokeTransformation, boolean scaleStrokes) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Point;
|
||||
import com.jpexs.decompiler.flash.tags.base.ImageTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
|
||||
import com.jpexs.decompiler.flash.types.ColorTransform;
|
||||
import com.jpexs.decompiler.flash.types.FILLSTYLE;
|
||||
import com.jpexs.decompiler.flash.types.GRADIENT;
|
||||
@@ -150,8 +151,8 @@ public class CanvasShapeExporter extends ShapeExporterBase {
|
||||
return shapeData.toString();
|
||||
}
|
||||
|
||||
public CanvasShapeExporter(int shapeNum, RGB basicFill, double unitDivisor, SWF swf, SHAPE shape, ColorTransform colorTransform, int deltaX, int deltaY) {
|
||||
super(shapeNum, swf, shape, colorTransform);
|
||||
public CanvasShapeExporter(int windingRule, int shapeNum, RGB basicFill, double unitDivisor, SWF swf, SHAPE shape, ColorTransform colorTransform, int deltaX, int deltaY) {
|
||||
super(windingRule, shapeNum, swf, shape, colorTransform);
|
||||
this.swf = swf;
|
||||
this.unitDivisor = unitDivisor;
|
||||
this.basicFill = basicFill;
|
||||
@@ -437,7 +438,7 @@ public class CanvasShapeExporter extends ShapeExporterBase {
|
||||
preLineFillData.append("\tlfctx.applyTransforms(ctx._matrix);\r\n");
|
||||
preLineFillData.append("\tctx = lfctx;");
|
||||
if (lineLastRadColor != null) {
|
||||
preLineFillData.append("\tctx.fillStyle=").append(lineLastRadColor).append(";\r\n\tctx.fill(\"evenodd\");\r\n");
|
||||
preLineFillData.append("\tctx.fillStyle=").append(lineLastRadColor).append(";\r\n\tctx.fill(\"").append(windingRule == ShapeTag.WIND_NONZERO ? "nonzero" : "evenodd").append("\");\r\n");
|
||||
}
|
||||
|
||||
if (lineFillMatrix != null) {
|
||||
@@ -474,7 +475,7 @@ public class CanvasShapeExporter extends ShapeExporterBase {
|
||||
if (fillMatrix != null) {
|
||||
pathData.append(drawFill);
|
||||
if (lastRadColor != null) {
|
||||
pathData.append("\tctx.fillStyle=").append(lastRadColor).append(";\r\n\tctx.fill(\"evenodd\");\r\n");
|
||||
pathData.append("\tctx.fillStyle=").append(lastRadColor).append(";\r\n\tctx.fill(\"").append(windingRule == ShapeTag.WIND_NONZERO ? "nonzero" : "evenodd").append("\");\r\n");
|
||||
}
|
||||
pathData.append("\tctx.save();\r\n");
|
||||
pathData.append("\tctx.clip();\r\n");
|
||||
@@ -497,7 +498,7 @@ public class CanvasShapeExporter extends ShapeExporterBase {
|
||||
shapeData.append(pathData);
|
||||
} else {
|
||||
if (fillData != null && fillData.length() > 0) {
|
||||
pathData.append(drawFill).append("\tctx.fill(\"evenodd\");\r\n");
|
||||
pathData.append(drawFill).append("\tctx.fill(\"").append(windingRule == ShapeTag.WIND_NONZERO ? "nonzero" : "evenodd").append("\");\r\n");
|
||||
}
|
||||
shapeData.append(fillData).append(pathData);
|
||||
}
|
||||
|
||||
@@ -41,8 +41,8 @@ public abstract class DefaultSVGShapeExporter extends ShapeExporterBase {
|
||||
|
||||
protected boolean aliasedFill;
|
||||
|
||||
public DefaultSVGShapeExporter(int shapeNum, SWF swf, SHAPE shape, ColorTransform colorTransform, double zoom) {
|
||||
super(shapeNum, swf, shape, colorTransform);
|
||||
public DefaultSVGShapeExporter(int windingRule, int shapeNum, SWF swf, SHAPE shape, ColorTransform colorTransform, double zoom) {
|
||||
super(windingRule, shapeNum, swf, shape, colorTransform);
|
||||
this.zoom = zoom;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,19 +43,19 @@ public class PathExporter extends ShapeExporterBase {
|
||||
|
||||
private GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD);
|
||||
|
||||
public static List<GeneralPath> export(int shapeNum, SWF swf, SHAPE shape) {
|
||||
return export(shapeNum, swf, shape, new ArrayList<>());
|
||||
public static List<GeneralPath> export(int windingRule, int shapeNum, SWF swf, SHAPE shape) {
|
||||
return export(windingRule, shapeNum, swf, shape, new ArrayList<>());
|
||||
}
|
||||
|
||||
public static List<GeneralPath> export(int shapeNum, SWF swf, SHAPE shape, List<GeneralPath> strokes) {
|
||||
PathExporter exporter = new PathExporter(shapeNum, swf, shape, null);
|
||||
public static List<GeneralPath> export(int windingRule, int shapeNum, SWF swf, SHAPE shape, List<GeneralPath> strokes) {
|
||||
PathExporter exporter = new PathExporter(windingRule, shapeNum, swf, shape, null);
|
||||
exporter.export();
|
||||
strokes.addAll(exporter.strokes);
|
||||
return exporter.paths;
|
||||
}
|
||||
|
||||
protected PathExporter(int shapeNum, SWF swf, SHAPE shape, ColorTransform colorTransform) {
|
||||
super(shapeNum, swf, shape, colorTransform);
|
||||
protected PathExporter(int windingRule, int shapeNum, SWF swf, SHAPE shape, ColorTransform colorTransform) {
|
||||
super(windingRule, shapeNum, swf, shape, colorTransform);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
|
||||
import com.jpexs.decompiler.flash.tags.base.ImageTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
|
||||
import com.jpexs.decompiler.flash.tags.enums.ImageFormat;
|
||||
import com.jpexs.decompiler.flash.types.ColorTransform;
|
||||
import com.jpexs.decompiler.flash.types.FILLSTYLE;
|
||||
@@ -52,8 +53,8 @@ public class SVGShapeExporter extends DefaultSVGShapeExporter {
|
||||
|
||||
private final SVGExporter exporter;
|
||||
|
||||
public SVGShapeExporter(int shapeNum, SWF swf, SHAPE shape, int id, SVGExporter exporter, Color defaultColor, ColorTransform colorTransform, double zoom) {
|
||||
super(shapeNum, swf, shape, colorTransform, zoom);
|
||||
public SVGShapeExporter(int windingRule, int shapeNum, SWF swf, SHAPE shape, int id, SVGExporter exporter, Color defaultColor, ColorTransform colorTransform, double zoom) {
|
||||
super(windingRule, shapeNum, swf, shape, colorTransform, zoom);
|
||||
this.swf = swf;
|
||||
this.id = id;
|
||||
this.defaultColor = defaultColor;
|
||||
@@ -73,7 +74,7 @@ public class SVGShapeExporter extends DefaultSVGShapeExporter {
|
||||
if (color != null) {
|
||||
path.setAttribute("fill", color.toHexRGB());
|
||||
}
|
||||
path.setAttribute("fill-rule", "evenodd");
|
||||
path.setAttribute("fill-rule", windingRule == ShapeTag.WIND_NONZERO ? "nonzero" : "evenodd");
|
||||
if (color instanceof RGBA) {
|
||||
RGBA colorA = (RGBA) color;
|
||||
if (colorA.alpha != 255) {
|
||||
|
||||
@@ -64,10 +64,15 @@ public abstract class ShapeExporterBase implements IShapeExporter {
|
||||
private final ColorTransform colorTransform;
|
||||
|
||||
private boolean canUseSmoothing = true;
|
||||
|
||||
protected int windingRule;
|
||||
|
||||
|
||||
|
||||
public ShapeExporterBase(int shapeNum, SWF swf, SHAPE shape, ColorTransform colorTransform) {
|
||||
public ShapeExporterBase(int windingRule, int shapeNum, SWF swf, SHAPE shape, ColorTransform colorTransform) {
|
||||
this.shape = shape;
|
||||
this.colorTransform = colorTransform;
|
||||
this.windingRule = windingRule;
|
||||
|
||||
Cache<SHAPE, ShapeExportData> cache = swf.getShapeExportDataCache();
|
||||
ShapeExportData cachedData = cache.get(shape);
|
||||
|
||||
@@ -104,6 +104,7 @@ public class SvgImporter {
|
||||
|
||||
if (st instanceof DefineShape4Tag) {
|
||||
DefineShape4Tag shape4 = (DefineShape4Tag) st;
|
||||
shape4.usesFillWindingRule = false;
|
||||
shape4.usesNonScalingStrokes = false;
|
||||
shape4.usesScalingStrokes = false;
|
||||
}
|
||||
@@ -371,6 +372,14 @@ public class SvgImporter {
|
||||
}
|
||||
|
||||
private void processCommands(int shapeNum, SHAPEWITHSTYLE shapes, List<PathCommand> commands, Matrix transform, SvgStyle style) {
|
||||
|
||||
if ("nonzero".equals(style.getFillRule())) {
|
||||
if (shapeTag instanceof DefineShape4Tag) {
|
||||
DefineShape4Tag shape4 = (DefineShape4Tag) shapeTag;
|
||||
shape4.usesFillWindingRule = true;
|
||||
}
|
||||
}
|
||||
|
||||
Matrix transform2 = transform.preConcatenate(Matrix.getScaleInstance(SWF.unitDivisor));
|
||||
Point prevPoint = new Point(0, 0);
|
||||
Point startPoint = prevPoint;
|
||||
@@ -1192,7 +1201,7 @@ public class SvgImporter {
|
||||
st = (DefineShape4Tag) (new SvgImporter().importSvg(st, svgDataS, false));
|
||||
swf.addTag(st);
|
||||
SerializableImage si = new SerializableImage(480, 360, BufferedImage.TYPE_4BYTE_ABGR);
|
||||
BitmapExporter.export(st.getShapeNum(), swf, st.shapes, Color.yellow, si, 1, new Matrix(), new Matrix(), null, true, true);
|
||||
BitmapExporter.export(st.getWindingRule(), st.getShapeNum(), swf, st.shapes, Color.yellow, si, 1, new Matrix(), new Matrix(), null, true, true);
|
||||
List<Tag> li = new ArrayList<>();
|
||||
li.add(st);
|
||||
ImageIO.write(si.getBufferedImage(), "PNG", new File(name + ".imported.png"));
|
||||
|
||||
@@ -168,6 +168,10 @@ class SvgStyle {
|
||||
public double getFillOpacity() {
|
||||
return getValue(element, "fill-opacity");
|
||||
}
|
||||
|
||||
public String getFillRule() {
|
||||
return getValue(element, "fill-rule");
|
||||
}
|
||||
|
||||
public SvgFill getStroke() {
|
||||
return getValue(element, "stroke");
|
||||
@@ -648,6 +652,9 @@ class SvgStyle {
|
||||
double opacity = Double.parseDouble(value);
|
||||
return opacity;
|
||||
}
|
||||
case "fill-rule": {
|
||||
return value;
|
||||
}
|
||||
case "stroke": {
|
||||
if ("currentColor".equals(value)) {
|
||||
return new SvgColor(style.getColor());
|
||||
|
||||
@@ -58,6 +58,7 @@ public class SvgStyleProperty {
|
||||
p.put("color", new SvgStyleProperty("color", true, Color.BLACK /* depends on user agent */));
|
||||
p.put("fill", new SvgStyleProperty("fill", true, new SvgColor(Color.BLACK)));
|
||||
p.put("fill-opacity", new SvgStyleProperty("fill-opacity", true, 1.0));
|
||||
p.put("fill-rule", new SvgStyleProperty("fill-rule", true, "nonzero"));
|
||||
p.put("stroke", new SvgStyleProperty("stroke", true, null));
|
||||
p.put("stroke-width", new SvgStyleProperty("stroke-width", true, 1.0));
|
||||
p.put("stroke-opacity", new SvgStyleProperty("stroke-opacity", true, 1.0));
|
||||
|
||||
@@ -209,7 +209,7 @@ public class DefineFont2Tag extends FontTag {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
sos3.writeSHAPE(glyphShapeTable.get(i), 1);
|
||||
sos3.writeSHAPE(1, 0, glyphShapeTable.get(i), 1);
|
||||
} catch (IOException ex) {
|
||||
//should not happen
|
||||
return;
|
||||
@@ -266,7 +266,7 @@ public class DefineFont2Tag extends FontTag {
|
||||
SWFOutputStream sos3 = new SWFOutputStream(baosGlyphShapes, getVersion(), getCharset());
|
||||
for (int i = 0; i < numGlyphs; i++) {
|
||||
offsetTable.add((glyphShapeTable.size() + 1/*CodeTableOffset*/) * (fontFlagsWideOffsets ? 4 : 2) + sos3.getPos());
|
||||
sos3.writeSHAPE(glyphShapeTable.get(i), 1);
|
||||
sos3.writeSHAPE(1, 0, glyphShapeTable.get(i), 1);
|
||||
}
|
||||
byte[] baGlyphShapes = baosGlyphShapes.toByteArray();
|
||||
for (Long offset : offsetTable) {
|
||||
|
||||
@@ -196,7 +196,7 @@ public class DefineFont3Tag extends FontTag {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
sos3.writeSHAPE(glyphShapeTable.get(i), 1);
|
||||
sos3.writeSHAPE(1, 0, glyphShapeTable.get(i), 1);
|
||||
} catch (IOException ex) {
|
||||
//should not happen
|
||||
return;
|
||||
@@ -239,7 +239,7 @@ public class DefineFont3Tag extends FontTag {
|
||||
int numGlyphs = glyphShapeTable.size();
|
||||
for (int i = 0; i < numGlyphs; i++) {
|
||||
offsetTable.add(sos3.getPos());
|
||||
sos3.writeSHAPE(glyphShapeTable.get(i), 1);
|
||||
sos3.writeSHAPE(1, 0, glyphShapeTable.get(i), 1);
|
||||
}
|
||||
byte[] baGlyphShapes = baosGlyphShapes.toByteArray();
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ public class DefineFontTag extends FontTag {
|
||||
SWFOutputStream sos2 = new SWFOutputStream(baos2, getVersion(), getCharset());
|
||||
for (SHAPE shape : glyphShapeTable) {
|
||||
offsetTable.add(glyphShapeTable.size() * 2 + (int) sos2.getPos());
|
||||
sos2.writeSHAPE(shape, 1);
|
||||
sos2.writeSHAPE(1, 0, shape, 1);
|
||||
}
|
||||
for (int offset : offsetTable) {
|
||||
sos.writeUI16(offset);
|
||||
@@ -323,7 +323,7 @@ public class DefineFontTag extends FontTag {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
sos2.writeSHAPE(shape, 1);
|
||||
sos2.writeSHAPE(1, 0, shape, 1);
|
||||
} catch (IOException ex) {
|
||||
//should not happen
|
||||
}
|
||||
|
||||
@@ -127,11 +127,11 @@ public class DefineMorphShape2Tag extends MorphShapeTag {
|
||||
SWFOutputStream sos2 = new SWFOutputStream(baos2, getVersion(), getCharset());
|
||||
sos2.writeMORPHFILLSTYLEARRAY(morphFillStyles, 2);
|
||||
sos2.writeMORPHLINESTYLEARRAY(morphLineStyles, 2);
|
||||
sos2.writeSHAPE(startEdges, 2);
|
||||
sos2.writeSHAPE(morphFillStyles.fillStyles.length, morphLineStyles.lineStyles2.length, startEdges, 2);
|
||||
byte[] ba2 = baos2.toByteArray();
|
||||
sos.writeUI32(ba2.length);
|
||||
sos.write(ba2);
|
||||
sos.writeSHAPE(endEdges, 2);
|
||||
sos.writeSHAPE(morphFillStyles.fillStyles.length, morphLineStyles.lineStyles2.length, endEdges, 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -99,11 +99,11 @@ public class DefineMorphShapeTag extends MorphShapeTag {
|
||||
SWFOutputStream sos2 = new SWFOutputStream(baos2, getVersion(), getCharset());
|
||||
sos2.writeMORPHFILLSTYLEARRAY(morphFillStyles, 1);
|
||||
sos2.writeMORPHLINESTYLEARRAY(morphLineStyles, 1);
|
||||
sos2.writeSHAPE(startEdges, 1);
|
||||
sos2.writeSHAPE(morphFillStyles.fillStyles.length, morphLineStyles.lineStyles.length, startEdges, 1);
|
||||
byte[] ba2 = baos2.toByteArray();
|
||||
sos.writeUI32(ba2.length);
|
||||
sos.write(ba2);
|
||||
sos.writeSHAPE(endEdges, 1);
|
||||
sos.writeSHAPE(morphFillStyles.fillStyles.length, morphLineStyles.lineStyles.length, endEdges, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -83,4 +83,9 @@ public class DefineShape2Tag extends ShapeTag {
|
||||
public int getShapeNum() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWindingRule() {
|
||||
return WIND_EVEN_ODD;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,4 +83,9 @@ public class DefineShape3Tag extends ShapeTag {
|
||||
public int getShapeNum() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWindingRule() {
|
||||
return WIND_EVEN_ODD;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,4 +117,11 @@ public class DefineShape4Tag extends ShapeTag {
|
||||
edgeBounds = SHAPERECORD.getBounds(shapes.shapeRecords, null, 4, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWindingRule() {
|
||||
if (usesFillWindingRule) {
|
||||
return WIND_NONZERO;
|
||||
}
|
||||
return WIND_EVEN_ODD;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,4 +83,9 @@ public class DefineShapeTag extends ShapeTag {
|
||||
public int getShapeNum() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWindingRule() {
|
||||
return WIND_EVEN_ODD;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -440,7 +440,7 @@ public abstract class FontTag extends DrawableTag implements AloneTag {
|
||||
|
||||
@Override
|
||||
public synchronized void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, SerializableImage fullImage, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, Matrix fullTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect, boolean scaleStrokes, int drawMode, int blendMode, boolean canUseSmoothing) {
|
||||
SHAPERECORD.shapeListToImage(1, swf, getGlyphShapeTable(), image, frame, Color.black, colorTransform);
|
||||
SHAPERECORD.shapeListToImage(ShapeTag.WIND_EVEN_ODD, 1, swf, getGlyphShapeTable(), image, frame, Color.black, colorTransform);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -457,7 +457,7 @@ public abstract class FontTag extends DrawableTag implements AloneTag {
|
||||
String cs = "" + c;
|
||||
cs = cs.replace("\\", "\\\\").replace("\"", "\\\"");
|
||||
result.append("\t\tcase \"").append(cs).append("\":\r\n");
|
||||
CanvasShapeExporter exporter = new CanvasShapeExporter(1, null, unitDivisor, swf, shapes.get(i), null, 0, 0);
|
||||
CanvasShapeExporter exporter = new CanvasShapeExporter(ShapeTag.WIND_EVEN_ODD, 1, null, unitDivisor, swf, shapes.get(i), null, 0, 0);
|
||||
exporter.export();
|
||||
result.append("\t\t").append(exporter.getShapeData().replaceAll("\r\n", "\r\n\t\t"));
|
||||
result.append("\tbreak;\r\n");
|
||||
|
||||
@@ -259,18 +259,18 @@ public abstract class ImageTag extends DrawableTag {
|
||||
|
||||
@Override
|
||||
public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, SerializableImage fullImage, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, Matrix fullTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect, boolean scaleStrokes, int drawMode, int blendMode, boolean canUseSmoothing) {
|
||||
BitmapExporter.export(1, swf, getShape(1), null, image, unzoom, transformation, strokeTransformation, colorTransform, true, canUseSmoothing);
|
||||
BitmapExporter.export(ShapeTag.WIND_EVEN_ODD, 1, swf, getShape(1), null, image, unzoom, transformation, strokeTransformation, colorTransform, true, canUseSmoothing);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) throws IOException {
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(1, swf, getShape(1), getCharacterId(), exporter, null, colorTransform, 1);
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(ShapeTag.WIND_EVEN_ODD, 1, swf, getShape(1), getCharacterId(), exporter, null, colorTransform, 1);
|
||||
shapeExporter.export();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toHtmlCanvas(StringBuilder result, double unitDivisor) {
|
||||
CanvasShapeExporter cse = new CanvasShapeExporter(1, null, unitDivisor, swf, getShape(1), null, 0, 0);
|
||||
CanvasShapeExporter cse = new CanvasShapeExporter(ShapeTag.WIND_EVEN_ODD, 1, null, unitDivisor, swf, getShape(1), null, 0, 0);
|
||||
cse.export();
|
||||
result.append(cse.getShapeData());
|
||||
}
|
||||
|
||||
@@ -323,7 +323,7 @@ public abstract class MorphShapeTag extends DrawableTag {
|
||||
// todo: Currently the generated image is not cached, because the cache
|
||||
// key contains the hashCode of the finalRecord object, and it is always
|
||||
// recreated
|
||||
BitmapExporter.export(getShapeNum() == 2 ? 4 : 1, swf, shape, null, image, unzoom, transformation, strokeTransformation, colorTransform, scaleStrokes, canUseSmoothing);
|
||||
BitmapExporter.export(ShapeTag.WIND_EVEN_ODD /*??? FIXME*/, getShapeNum() == 2 ? 4 : 1, swf, shape, null, image, unzoom, transformation, strokeTransformation, colorTransform, scaleStrokes, canUseSmoothing);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -335,7 +335,7 @@ public abstract class MorphShapeTag extends DrawableTag {
|
||||
shapeExporter.export();
|
||||
} else {
|
||||
SHAPEWITHSTYLE shapes = getShapeAtRatio(ratio);
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(getShapeNum() == 2 ? 4 : 1, swf, shapes, getCharacterId(), exporter, null, colorTransform, 1);
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(ShapeTag.WIND_EVEN_ODD /*??? FIXME*/, getShapeNum() == 2 ? 4 : 1, swf, shapes, getCharacterId(), exporter, null, colorTransform, 1);
|
||||
shapeExporter.export();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,10 @@ public abstract class ShapeTag extends DrawableTag implements LazyObject {
|
||||
protected ByteArrayRange shapeData;
|
||||
|
||||
private final int markerSize = 10;
|
||||
|
||||
public static final int WIND_EVEN_ODD = 0;
|
||||
|
||||
public static final int WIND_NONZERO = 1;
|
||||
|
||||
public ShapeTag(SWF swf, int id, String name, ByteArrayRange data) {
|
||||
super(swf, id, name, data);
|
||||
@@ -75,6 +79,8 @@ public abstract class ShapeTag extends DrawableTag implements LazyObject {
|
||||
public void load() {
|
||||
getShapes();
|
||||
}
|
||||
|
||||
public abstract int getWindingRule();
|
||||
|
||||
public abstract int getShapeNum();
|
||||
|
||||
@@ -189,9 +195,9 @@ public abstract class ShapeTag extends DrawableTag implements LazyObject {
|
||||
|
||||
@Override
|
||||
public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, SerializableImage fullImage, boolean isClip, Matrix transformation, Matrix strokeTransformation, Matrix absoluteTransformation, Matrix fullTransformation, ColorTransform colorTransform, double unzoom, boolean sameImage, ExportRectangle viewRect, boolean scaleStrokes, int drawMode, int blendMode, boolean canUseSmoothing) {
|
||||
BitmapExporter.export(getShapeNum(), swf, getShapes(), null, image, unzoom, transformation, strokeTransformation, colorTransform, scaleStrokes, canUseSmoothing);
|
||||
BitmapExporter.export(getWindingRule(), getShapeNum(), swf, getShapes(), null, image, unzoom, transformation, strokeTransformation, colorTransform, scaleStrokes, canUseSmoothing);
|
||||
if (Configuration._debugMode.get()) { // show control points
|
||||
List<GeneralPath> paths = PathExporter.export(getShapeNum(), swf, getShapes());
|
||||
List<GeneralPath> paths = PathExporter.export(getWindingRule(), getShapeNum(), swf, getShapes());
|
||||
double[] coords = new double[6];
|
||||
AffineTransform at = transformation.toTransform();
|
||||
at.preConcatenate(AffineTransform.getScaleInstance(1 / SWF.unitDivisor, 1 / SWF.unitDivisor));
|
||||
@@ -233,13 +239,13 @@ public abstract class ShapeTag extends DrawableTag implements LazyObject {
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level) throws IOException {
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(getShapeNum(), swf, getShapes(), getCharacterId(), exporter, null, colorTransform, 1);
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(getWindingRule(), getShapeNum(), swf, getShapes(), getCharacterId(), exporter, null, colorTransform, 1);
|
||||
shapeExporter.export();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toHtmlCanvas(StringBuilder result, double unitDivisor) {
|
||||
CanvasShapeExporter cse = new CanvasShapeExporter(getShapeNum(), null, unitDivisor, swf, getShapes(), null, 0, 0);
|
||||
CanvasShapeExporter cse = new CanvasShapeExporter(getWindingRule(), getShapeNum(), null, unitDivisor, swf, getShapes(), null, 0, 0);
|
||||
cse.export();
|
||||
result.append(cse.getShapeData());
|
||||
}
|
||||
|
||||
@@ -423,7 +423,7 @@ public abstract class TextTag extends DrawableTag {
|
||||
Graphics2D g = (Graphics2D) image.getGraphics();
|
||||
Matrix mat = transformation.clone();
|
||||
mat = mat.concatenate(new Matrix(textMatrix));
|
||||
BitmapExporter.export(1, swf, getBorderShape(borderColor, fillColor, rect), null, image, 1 /*FIXME??*/, mat, mat, colorTransform, true, false);
|
||||
BitmapExporter.export(ShapeTag.WIND_EVEN_ODD, 1, swf, getBorderShape(borderColor, fillColor, rect), null, image, 1 /*FIXME??*/, mat, mat, colorTransform, true, false);
|
||||
}
|
||||
|
||||
public static void drawBorderHtmlCanvas(SWF swf, StringBuilder result, RGB borderColor, RGB fillColor, RECT rect, MATRIX textMatrix, ColorTransform colorTransform, double unitDivisor) {
|
||||
@@ -431,7 +431,7 @@ public abstract class TextTag extends DrawableTag {
|
||||
result.append("\tctx.save();\r\n");
|
||||
result.append("\tctx.transform(").append(mat.scaleX).append(",").append(mat.rotateSkew0).append(",").append(mat.rotateSkew1).append(",").append(mat.scaleY).append(",").append(mat.translateX).append(",").append(mat.translateY).append(");\r\n");
|
||||
SHAPE shape = getBorderShape(borderColor, fillColor, rect);
|
||||
CanvasShapeExporter cse = new CanvasShapeExporter(1, null, unitDivisor, swf, shape, colorTransform, 0, 0);
|
||||
CanvasShapeExporter cse = new CanvasShapeExporter(ShapeTag.WIND_EVEN_ODD, 1, null, unitDivisor, swf, shape, colorTransform, 0, 0);
|
||||
cse.export();
|
||||
result.append(cse.getShapeData());
|
||||
result.append("\tctx.restore();\r\n");
|
||||
@@ -440,7 +440,7 @@ public abstract class TextTag extends DrawableTag {
|
||||
public static void drawBorderSVG(SWF swf, SVGExporter exporter, RGB borderColor, RGB fillColor, RECT rect, MATRIX textMatrix, ColorTransform colorTransform, double zoom) {
|
||||
exporter.createSubGroup(new Matrix(textMatrix), null);
|
||||
SHAPE shape = getBorderShape(borderColor, fillColor, rect);
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(1, swf, shape, 0, exporter, null, colorTransform, zoom);
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(ShapeTag.WIND_EVEN_ODD, 1, swf, shape, 0, exporter, null, colorTransform, zoom);
|
||||
shapeExporter.export();
|
||||
exporter.endGroup();
|
||||
}
|
||||
@@ -513,7 +513,7 @@ public abstract class TextTag extends DrawableTag {
|
||||
}
|
||||
|
||||
if (shape != null) {
|
||||
BitmapExporter.export(1, swf, shape, textColor2, image, 1 /*FIXME??*/, mat, mat, colorTransform, true, false);
|
||||
BitmapExporter.export(ShapeTag.WIND_EVEN_ODD, 1, swf, shape, textColor2, image, 1 /*FIXME??*/, mat, mat, colorTransform, true, false);
|
||||
if (SHAPERECORD.DRAW_BOUNDING_BOX) {
|
||||
RGB borderColor = new RGBA(Color.black);
|
||||
RGB fillColor = new RGBA(new Color(255, 255, 255, 0));
|
||||
@@ -761,7 +761,7 @@ public abstract class TextTag extends DrawableTag {
|
||||
if (charId == null) {
|
||||
charId = exporter.getUniqueId(Helper.getValidHtmlId("font_" + font.getFontNameIntag() + "_" + ch));
|
||||
exporter.createDefGroup(null, charId);
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(1, swf, shape, 0, exporter, null, colorTransform, zoom);
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(ShapeTag.WIND_EVEN_ODD, 1, swf, shape, 0, exporter, null, colorTransform, zoom);
|
||||
shapeExporter.export();
|
||||
if (!exporter.endGroup()) {
|
||||
charId = "";
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.jpexs.decompiler.flash.types;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.exporters.shape.PathExporter;
|
||||
import com.jpexs.decompiler.flash.tags.base.NeedsCharacters;
|
||||
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFArray;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.EndShapeRecord;
|
||||
@@ -108,7 +109,7 @@ public class SHAPE implements NeedsCharacters, Serializable {
|
||||
}
|
||||
|
||||
List<GeneralPath> strokes = new ArrayList<>();
|
||||
List<GeneralPath> paths = PathExporter.export(shapeNum, swf, this, strokes);
|
||||
List<GeneralPath> paths = PathExporter.export(ShapeTag.WIND_EVEN_ODD, shapeNum, swf, this, strokes);
|
||||
|
||||
boolean large = shapeRecords.size() > 500;
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.exporters.shape.BitmapExporter;
|
||||
import com.jpexs.decompiler.flash.helpers.FontHelper;
|
||||
import com.jpexs.decompiler.flash.tags.base.NeedsCharacters;
|
||||
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.TextTag;
|
||||
import com.jpexs.decompiler.flash.types.ColorTransform;
|
||||
import com.jpexs.decompiler.flash.types.LINESTYLE;
|
||||
@@ -197,7 +198,7 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters, Seriali
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static void shapeListToImage(int shapeNum, SWF swf, List<SHAPE> shapes, SerializableImage image, int frame, Color color, ColorTransform colorTransform) {
|
||||
public static void shapeListToImage(int windingRule, int shapeNum, SWF swf, List<SHAPE> shapes, SerializableImage image, int frame, Color color, ColorTransform colorTransform) {
|
||||
if (shapes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@@ -281,7 +282,7 @@ public abstract class SHAPERECORD implements Cloneable, NeedsCharacters, Seriali
|
||||
|
||||
Matrix transformation = Matrix.getTranslateInstance(px, py);
|
||||
transformation.scale(ratio);
|
||||
BitmapExporter.export(shapeNum, swf, shape, color, image, 1 /*FIXME??*/, transformation, transformation, colorTransform, true, true);
|
||||
BitmapExporter.export(windingRule, shapeNum, swf, shape, color, image, 1 /*FIXME??*/, transformation, transformation, colorTransform, true, true);
|
||||
|
||||
// draw bounding boxes
|
||||
if (DRAW_BOUNDING_BOX) {
|
||||
|
||||
Reference in New Issue
Block a user