mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-18 22:18:09 +00:00
Replacing morphshape from start/end shape.
Fixed Display of morphshape end shape to be exactly at 65535 ratio
This commit is contained in:
@@ -966,12 +966,7 @@ public final class Configuration {
|
||||
|
||||
@ConfigurationDefaultBoolean(true)
|
||||
@ConfigurationCategory("ui")
|
||||
public static ConfigurationItem<Boolean> displayAs3PCodePanel = null;
|
||||
|
||||
@ConfigurationDefaultBoolean(true)
|
||||
@ConfigurationName("warning.replace.morphshape")
|
||||
@ConfigurationCategory("ui")
|
||||
public static ConfigurationItem<Boolean> warningReplaceMorphShape = null;
|
||||
public static ConfigurationItem<Boolean> displayAs3PCodePanel = null;
|
||||
|
||||
private enum OSId {
|
||||
WINDOWS, OSX, UNIX
|
||||
|
||||
@@ -45,9 +45,19 @@ public class CurvedEdge extends StraightEdge implements IEdge {
|
||||
return new CurvedEdge(toX, toY, controlX, controlY, fromX, fromY, lineStyleIdx, newFillStyleIdx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IEdge sameWithNewFillStyle(int newFillStyleIdx) {
|
||||
return new CurvedEdge(fromX, fromY, controlX, controlY, toX, toY, lineStyleIdx, newFillStyleIdx);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "curved[" + fromX / 20f + "," + fromY / 20f + " -> " + toX / 20f + "," + toY / 20f + " control:" + controlX / 20f + "," + controlY / 20f + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public IEdge reverse() {
|
||||
return new CurvedEdge(toX, toY, controlX, controlY, fromX, fromY, lineStyleIdx, getFillStyleIdx());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,4 +35,8 @@ public interface IEdge {
|
||||
public int getFillStyleIdx();
|
||||
|
||||
public IEdge reverseWithNewFillStyle(int newFillStyleIdx);
|
||||
|
||||
public IEdge reverse();
|
||||
|
||||
public IEdge sameWithNewFillStyle(int newFillStyleIdx);
|
||||
}
|
||||
|
||||
@@ -64,10 +64,8 @@ public abstract class ShapeExporterBase implements IShapeExporter {
|
||||
private final ColorTransform colorTransform;
|
||||
|
||||
private boolean canUseSmoothing = true;
|
||||
|
||||
|
||||
protected int windingRule;
|
||||
|
||||
|
||||
|
||||
public ShapeExporterBase(int windingRule, int shapeNum, SWF swf, SHAPE shape, ColorTransform colorTransform) {
|
||||
this.shape = shape;
|
||||
|
||||
@@ -83,4 +83,15 @@ public class StraightEdge implements IEdge {
|
||||
return "straight[" + fromX / 20f + "," + fromY / 20f + " -> " + toX / 20f + "," + toY / 20f + "]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public IEdge sameWithNewFillStyle(int newFillStyleIdx) {
|
||||
return new StraightEdge(fromX, fromY, toX, toY, lineStyleIdx, newFillStyleIdx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IEdge reverse() {
|
||||
return new StraightEdge(toX, toY, fromX, fromY, lineStyleIdx, getFillStyleIdx());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,335 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2023 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.importers.morphshape;
|
||||
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.math.BezierEdge;
|
||||
import com.jpexs.decompiler.flash.tags.DefineMorphShape2Tag;
|
||||
import com.jpexs.decompiler.flash.tags.base.ShapeTag;
|
||||
import com.jpexs.decompiler.flash.types.FILLSTYLE;
|
||||
import com.jpexs.decompiler.flash.types.LINESTYLE2;
|
||||
import com.jpexs.decompiler.flash.types.MORPHFILLSTYLE;
|
||||
import com.jpexs.decompiler.flash.types.MORPHFILLSTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.MORPHLINESTYLE2;
|
||||
import com.jpexs.decompiler.flash.types.MORPHLINESTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.CurvedEdgeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.EndShapeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.SHAPERECORD;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.StraightEdgeRecord;
|
||||
import com.jpexs.decompiler.flash.types.shaperecords.StyleChangeRecord;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.Reference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class MorphShapeGenerator {
|
||||
|
||||
public void generate(DefineMorphShape2Tag morphShape, ShapeTag startShape, ShapeTag endShape) throws StyleMismatchException {
|
||||
ShapeForMorphExporter startExport = new ShapeForMorphExporter(startShape);
|
||||
startExport.export();
|
||||
ShapeForMorphExporter endExport = new ShapeForMorphExporter(endShape);
|
||||
endExport.export();
|
||||
|
||||
List<List<BezierEdge>> startBeziers = new ArrayList<>();
|
||||
List<List<BezierEdge>> endBeziers = new ArrayList<>();
|
||||
List<FILLSTYLE> startFillStyles = new ArrayList<>();
|
||||
List<Integer> startFillstyleIndices = new ArrayList<>();
|
||||
List<LINESTYLE2> startLineStyles = new ArrayList<>();
|
||||
List<Integer> startLineStyleIndices = new ArrayList<>();
|
||||
|
||||
List<FILLSTYLE> endFillStyles = new ArrayList<>();
|
||||
List<LINESTYLE2> endLineStyles = new ArrayList<>();
|
||||
|
||||
Set<Integer> usedBs = new HashSet<>();
|
||||
|
||||
List<Integer> startShapeIndices = new ArrayList<>();
|
||||
List<Integer> endShapeIndices = new ArrayList<>();
|
||||
|
||||
for (int a = 0; a < startExport.shapes.size(); a++) {
|
||||
double minDistance = Double.MAX_VALUE;
|
||||
double minDistanceNoUsed = Double.MAX_VALUE;
|
||||
int selectedB = -1;
|
||||
int selectedBNoUsed = -1;
|
||||
|
||||
int startFillStyleIndex = startExport.fillStyleIndices.get(a);
|
||||
FILLSTYLE startFillStyle = startFillStyleIndex == -1 ? null : startExport.fillStyles.get(startFillStyleIndex);
|
||||
int startLineStyleIndex = startExport.lineStyleIndices.get(a);
|
||||
LINESTYLE2 startLineStyle = startLineStyleIndex == -1 ? null : startExport.lineStyles.get(startLineStyleIndex);
|
||||
|
||||
for (int b = 0; b < endExport.shapes.size(); b++) {
|
||||
int endFillStyleIndex = endExport.fillStyleIndices.get(b);
|
||||
FILLSTYLE endFillStyle = endFillStyleIndex == -1 ? null : endExport.fillStyles.get(endFillStyleIndex);
|
||||
int endLineStyleIndex = endExport.lineStyleIndices.get(b);
|
||||
LINESTYLE2 endLineStyle = endLineStyleIndex == -1 ? null : endExport.lineStyles.get(endLineStyleIndex);
|
||||
|
||||
if (((endFillStyle == null && startFillStyle == null)
|
||||
|| (startFillStyle != null
|
||||
&& endFillStyle != null
|
||||
&& startFillStyle.isCompatibleFillStyle(endFillStyle)))
|
||||
&& ((endLineStyle == null && startLineStyle == null)
|
||||
|| (startLineStyle != null
|
||||
&& endLineStyle != null
|
||||
&& startLineStyle.isCompatibleLineStyle(endLineStyle)))) {
|
||||
double distance = startExport.centralPos.get(a).distance(endExport.centralPos.get(b));
|
||||
if (distance < minDistance) {
|
||||
minDistance = distance;
|
||||
selectedB = b;
|
||||
}
|
||||
|
||||
if (distance < minDistanceNoUsed && !usedBs.contains(b)) {
|
||||
minDistanceNoUsed = distance;
|
||||
selectedBNoUsed = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (selectedB == -1) {
|
||||
throw new StyleMismatchException();
|
||||
}
|
||||
if (selectedBNoUsed != -1) {
|
||||
selectedB = selectedBNoUsed;
|
||||
}
|
||||
startShapeIndices.add(a);
|
||||
endShapeIndices.add(selectedB);
|
||||
usedBs.add(selectedB);
|
||||
}
|
||||
|
||||
if (usedBs.size() < endExport.shapes.size()) {
|
||||
for (int b = 0; b < endExport.shapes.size(); b++) {
|
||||
if (!usedBs.contains(b)) {
|
||||
|
||||
double minDistance = Double.MAX_VALUE;
|
||||
int selectedA = -1;
|
||||
|
||||
int endFillStyleIndex = endExport.fillStyleIndices.get(b);
|
||||
FILLSTYLE endFillStyle = endFillStyleIndex == -1 ? null : endExport.fillStyles.get(endFillStyleIndex);
|
||||
int endLineStyleIndex = endExport.lineStyleIndices.get(b);
|
||||
LINESTYLE2 endLineStyle = endLineStyleIndex == -1 ? null : endExport.lineStyles.get(endLineStyleIndex);
|
||||
|
||||
for (int a = 0; a < startExport.shapes.size(); a++) {
|
||||
int startFillStyleIndex = startExport.fillStyleIndices.get(a);
|
||||
FILLSTYLE startFillStyle = startFillStyleIndex == -1 ? null : startExport.fillStyles.get(startFillStyleIndex);
|
||||
int startLineStyleIndex = startExport.lineStyleIndices.get(a);
|
||||
LINESTYLE2 startLineStyle = startLineStyleIndex == -1 ? null : startExport.lineStyles.get(startLineStyleIndex);
|
||||
|
||||
if (((endFillStyle == null && startFillStyle == null)
|
||||
|| (startFillStyle != null
|
||||
&& endFillStyle != null
|
||||
&& startFillStyle.isCompatibleFillStyle(endFillStyle)))
|
||||
&& ((endLineStyle == null && startLineStyle == null)
|
||||
|| (startLineStyle != null
|
||||
&& endLineStyle != null
|
||||
&& startLineStyle.isCompatibleLineStyle(endLineStyle)))) {
|
||||
double distance = startExport.centralPos.get(a).distance(endExport.centralPos.get(b));
|
||||
if (distance < minDistance) {
|
||||
minDistance = distance;
|
||||
selectedA = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (selectedA == -1) {
|
||||
throw new StyleMismatchException();
|
||||
}
|
||||
|
||||
startShapeIndices.add(selectedA);
|
||||
endShapeIndices.add(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < startShapeIndices.size(); i++) {
|
||||
int a = startShapeIndices.get(i);
|
||||
int b = endShapeIndices.get(i);
|
||||
|
||||
List<BezierEdge> shapeStart = Helper.deepCopy(startExport.shapes.get(a));
|
||||
split(shapeStart, startExport.pointsPosPercent.get(a), endExport.pointsPosPercent.get(b));
|
||||
List<BezierEdge> shapeEnd = Helper.deepCopy(endExport.shapes.get(b));
|
||||
split(shapeEnd, endExport.pointsPosPercent.get(b), startExport.pointsPosPercent.get(a));
|
||||
|
||||
startBeziers.add(shapeStart);
|
||||
endBeziers.add(shapeEnd);
|
||||
|
||||
if (startExport.fillStyleIndices.get(a) != -1) {
|
||||
startFillStyles.add(startExport.fillStyles.get(startExport.fillStyleIndices.get(a)));
|
||||
}
|
||||
startFillstyleIndices.add(startExport.fillStyleIndices.get(a));
|
||||
if (startExport.lineStyleIndices.get(a) != -1) {
|
||||
startLineStyles.add(startExport.lineStyles.get(startExport.lineStyleIndices.get(a)));
|
||||
}
|
||||
startLineStyleIndices.add(startExport.lineStyleIndices.get(a));
|
||||
|
||||
if (endExport.fillStyleIndices.get(b) != -1) {
|
||||
endFillStyles.add(endExport.fillStyles.get(endExport.fillStyleIndices.get(b)));
|
||||
}
|
||||
if (endExport.lineStyleIndices.get(b) != -1) {
|
||||
endLineStyles.add(endExport.lineStyles.get(endExport.lineStyleIndices.get(b)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
List<SHAPERECORD> startRecords = new ArrayList<>();
|
||||
List<SHAPERECORD> endRecords = new ArrayList<>();
|
||||
|
||||
MORPHFILLSTYLEARRAY morphFillStyleArray = new MORPHFILLSTYLEARRAY();
|
||||
morphFillStyleArray.fillStyles = new MORPHFILLSTYLE[startFillStyles.size()];
|
||||
|
||||
MORPHLINESTYLEARRAY morphLineStyleArray = new MORPHLINESTYLEARRAY();
|
||||
morphLineStyleArray.lineStyles2 = new MORPHLINESTYLE2[startLineStyles.size()];
|
||||
|
||||
for (int i = 0; i < startFillStyles.size(); i++) {
|
||||
FILLSTYLE fsStart = startFillStyles.get(i);
|
||||
FILLSTYLE fsEnd = endFillStyles.get(i);
|
||||
MORPHFILLSTYLE morphFillStyle = fsStart.toMorphStyle(fsEnd);
|
||||
if (morphFillStyle == null) {
|
||||
throw new StyleMismatchException();
|
||||
}
|
||||
morphFillStyleArray.fillStyles[i] = morphFillStyle;
|
||||
}
|
||||
|
||||
for (int i = 0; i < startLineStyles.size(); i++) {
|
||||
LINESTYLE2 lsStart = startLineStyles.get(i);
|
||||
LINESTYLE2 lsEnd = endLineStyles.get(i);
|
||||
MORPHLINESTYLE2 morphLineStyle = lsStart.toMorphLineStyle2(lsEnd);
|
||||
if (morphLineStyle == null) {
|
||||
throw new StyleMismatchException();
|
||||
}
|
||||
morphLineStyleArray.lineStyles2[i] = morphLineStyle;
|
||||
if (morphLineStyle.noHScaleFlag || morphLineStyle.noVScaleFlag) {
|
||||
morphShape.usesNonScalingStrokes = true;
|
||||
}
|
||||
if (!morphLineStyle.noHScaleFlag && !morphLineStyle.noVScaleFlag) {
|
||||
morphShape.usesScalingStrokes = true;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < startBeziers.size(); i++) {
|
||||
List<BezierEdge> beList = startBeziers.get(i);
|
||||
StyleChangeRecord scr = new StyleChangeRecord();
|
||||
scr.stateFillStyle0 = true;
|
||||
if (startFillstyleIndices.get(i) != -1) {
|
||||
scr.fillStyle0 = startFillstyleIndices.get(i) + 1;
|
||||
} else {
|
||||
scr.fillStyle0 = 0;
|
||||
}
|
||||
scr.stateLineStyle = true;
|
||||
if (startLineStyleIndices.get(i) != -1) {
|
||||
scr.lineStyle = startLineStyleIndices.get(i) + 1;
|
||||
} else {
|
||||
scr.lineStyle = 0;
|
||||
}
|
||||
startRecords.add(scr);
|
||||
|
||||
BezierEdge firstBe = beList.get(0);
|
||||
StyleChangeRecord scrMove = new StyleChangeRecord();
|
||||
scrMove.stateMoveTo = true;
|
||||
scrMove.moveDeltaX = (int) Math.round(firstBe.getBeginPoint().getX());
|
||||
scrMove.moveDeltaY = (int) Math.round(firstBe.getBeginPoint().getY());
|
||||
startRecords.add(scrMove);
|
||||
|
||||
for (BezierEdge be : beList) {
|
||||
SHAPERECORD rec = bezierToRecord(be);
|
||||
startRecords.add(rec);
|
||||
}
|
||||
}
|
||||
startRecords.add(new EndShapeRecord());
|
||||
|
||||
for (int i = 0; i < endBeziers.size(); i++) {
|
||||
List<BezierEdge> beList = endBeziers.get(i);
|
||||
BezierEdge firstBe = beList.get(0);
|
||||
StyleChangeRecord scrMove = new StyleChangeRecord();
|
||||
scrMove.stateMoveTo = true;
|
||||
scrMove.moveDeltaX = (int) Math.round(firstBe.getBeginPoint().getX());
|
||||
scrMove.moveDeltaY = (int) Math.round(firstBe.getBeginPoint().getY());
|
||||
endRecords.add(scrMove);
|
||||
for (BezierEdge be : beList) {
|
||||
SHAPERECORD rec = bezierToRecord(be);
|
||||
endRecords.add(rec);
|
||||
}
|
||||
}
|
||||
endRecords.add(new EndShapeRecord());
|
||||
|
||||
morphShape.morphFillStyles = morphFillStyleArray;
|
||||
morphShape.morphLineStyles = morphLineStyleArray;
|
||||
morphShape.startEdges = new SHAPE();
|
||||
morphShape.startEdges.shapeRecords = startRecords;
|
||||
morphShape.startEdges.numFillBits = SWFOutputStream.getNeededBitsU(morphFillStyleArray.fillStyles.length);
|
||||
morphShape.startEdges.numLineBits = SWFOutputStream.getNeededBitsU(morphLineStyleArray.lineStyles2.length);
|
||||
|
||||
morphShape.endEdges = new SHAPE();
|
||||
morphShape.endEdges.numFillBits = 0;
|
||||
morphShape.endEdges.numLineBits = 0;
|
||||
morphShape.endEdges.shapeRecords = endRecords;
|
||||
|
||||
morphShape.setModified(true);
|
||||
morphShape.updateBounds();
|
||||
}
|
||||
|
||||
private void split(List<BezierEdge> shape, List<Double> originalPointsPosPercent, List<Double> newPointPosPercent) {
|
||||
List<Double> pointPointsPercent = new ArrayList<>(originalPointsPosPercent);
|
||||
|
||||
int nppPos = 0;
|
||||
for (int i = 0; i < shape.size() && nppPos < newPointPosPercent.size(); i++) {
|
||||
BezierEdge be = shape.get(i);
|
||||
double pointPosPct = pointPointsPercent.get(i);
|
||||
double pointPosNextPct = pointPointsPercent.get(i + 1);
|
||||
|
||||
double pct = newPointPosPercent.get(nppPos);
|
||||
if (pct > pointPosPct && pct < pointPosNextPct) {
|
||||
double deltaPct = pointPosNextPct - pointPosPct;
|
||||
double newPct = pct - pointPosPct;
|
||||
double insidePct = newPct / deltaPct;
|
||||
Reference<BezierEdge> leftRef = new Reference<>(null);
|
||||
Reference<BezierEdge> rightRef = new Reference<>(null);
|
||||
be.split(insidePct, leftRef, rightRef);
|
||||
shape.remove(i);
|
||||
shape.add(i, leftRef.getVal());
|
||||
shape.add(i + 1, rightRef.getVal());
|
||||
pointPointsPercent.add(i + 1, pct);
|
||||
nppPos++;
|
||||
} else if (pct == pointPosPct) {
|
||||
nppPos++;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SHAPERECORD bezierToRecord(BezierEdge be) {
|
||||
if (be.points.size() == 2) {
|
||||
StraightEdgeRecord ser = new StraightEdgeRecord();
|
||||
ser.deltaX = (int) Math.round(be.points.get(1).getX() - be.points.get(0).getX());
|
||||
ser.deltaY = (int) Math.round(be.points.get(1).getY() - be.points.get(0).getY());
|
||||
ser.generalLineFlag = true;
|
||||
ser.simplify();
|
||||
return ser;
|
||||
}
|
||||
if (be.points.size() == 3) {
|
||||
CurvedEdgeRecord cer = new CurvedEdgeRecord();
|
||||
cer.controlDeltaX = (int) Math.round(be.points.get(1).getX() - be.points.get(0).getX());
|
||||
cer.controlDeltaY = (int) Math.round(be.points.get(1).getY() - be.points.get(0).getY());
|
||||
cer.anchorDeltaX = (int) Math.round(be.points.get(2).getX() - be.points.get(1).getX());
|
||||
cer.anchorDeltaY = (int) Math.round(be.points.get(2).getY() - be.points.get(1).getY());
|
||||
return cer;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,430 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2023 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.importers.morphshape;
|
||||
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.exporters.shape.ShapeExporterBase;
|
||||
import com.jpexs.decompiler.flash.math.BezierEdge;
|
||||
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.FOCALGRADIENT;
|
||||
import com.jpexs.decompiler.flash.types.GRADIENT;
|
||||
import com.jpexs.decompiler.flash.types.GRADRECORD;
|
||||
import com.jpexs.decompiler.flash.types.LINESTYLE2;
|
||||
import com.jpexs.decompiler.flash.types.RGB;
|
||||
import com.jpexs.decompiler.flash.types.RGBA;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import com.jpexs.helpers.Reference;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class ShapeForMorphExporter extends ShapeExporterBase {
|
||||
|
||||
public List<List<BezierEdge>> shapes = new ArrayList<>();
|
||||
public List<Integer> fillStyleIndices = new ArrayList<>();
|
||||
public List<Integer> lineStyleIndices = new ArrayList<>();
|
||||
public List<List<Double>> pointsPosPercent = new ArrayList<>();
|
||||
public List<Point2D.Double> centralPos = new ArrayList<>();
|
||||
private final List<Point2D.Double> pointsSum = new ArrayList<>();
|
||||
private final List<Integer> segmentCount = new ArrayList<>();
|
||||
private final List<List<Double>> bezierLengths = new ArrayList<>();
|
||||
|
||||
private List<BezierEdge> currentShape = new ArrayList<>();
|
||||
private List<Double> currentBezierLengths = new ArrayList<>();
|
||||
private Point2D.Double currentPointsSum = new Point2D.Double();
|
||||
private int currentSegmentCount = 0;
|
||||
private int currentLineStyle = -1;
|
||||
private int currentFillStyle = -1;
|
||||
|
||||
double currentShapeLen = 0;
|
||||
|
||||
public List<FILLSTYLE> fillStyles = new ArrayList<>();
|
||||
public List<LINESTYLE2> lineStyles = new ArrayList<>();
|
||||
|
||||
private double lastX = 0;
|
||||
private double lastY = 0;
|
||||
|
||||
public ShapeForMorphExporter(ShapeTag shape) {
|
||||
super(ShapeTag.WIND_EVEN_ODD, shape.getShapeNum(), shape.getSwf(), shape.shapes, new ColorTransform());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginShape() {
|
||||
shapes = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endShape() {
|
||||
endCurrent();
|
||||
|
||||
for (int i = 0; i < segmentCount.size(); i++) {
|
||||
Point2D.Double center = new Point2D.Double();
|
||||
center.x = pointsSum.get(i).x / (double) segmentCount.get(i);
|
||||
center.y = pointsSum.get(i).y / (double) segmentCount.get(i);
|
||||
centralPos.add(center);
|
||||
}
|
||||
|
||||
for (int i = 0; i < shapes.size(); i++) {
|
||||
List<BezierEdge> shape = shapes.get(i);
|
||||
List<Point2D> points = new ArrayList<>();
|
||||
BezierEdge be = null;
|
||||
for (int j = 0; j < shape.size(); j++) {
|
||||
be = shape.get(j);
|
||||
points.add(new Point2D.Double(
|
||||
be.getBeginPoint().getX() - centralPos.get(i).getX(),
|
||||
be.getBeginPoint().getY() - centralPos.get(i).getY()
|
||||
));
|
||||
}
|
||||
points.add(new Point2D.Double(
|
||||
be.getEndPoint().getX() - centralPos.get(i).getX(),
|
||||
be.getEndPoint().getY() - centralPos.get(i).getY()
|
||||
));
|
||||
|
||||
double w = 0;
|
||||
for (int j = 0; j < points.size(); j++) {
|
||||
int secondPoint = j + 1 == points.size() ? 0 : j + 1;
|
||||
double x = points.get(j).getX();
|
||||
double xp1 = points.get(secondPoint).getX();
|
||||
double y = points.get(j).getY();
|
||||
double yp1 = points.get(secondPoint).getY();
|
||||
|
||||
if (y * yp1 < 0) {
|
||||
double r = x + ((y * (xp1 - x)) / (y - yp1));
|
||||
if (r > 0) {
|
||||
if (y < 0) {
|
||||
w = w + 1;
|
||||
} else {
|
||||
w = w - 1;
|
||||
}
|
||||
}
|
||||
} else if ((y == 0) && (x > 0)) {
|
||||
if (yp1 > 0) {
|
||||
w = w + .5;
|
||||
} else {
|
||||
w = w - .5;
|
||||
}
|
||||
} else if ((yp1 == 0) && (xp1 > 0)) {
|
||||
if (y < 0) {
|
||||
w = w + .5;
|
||||
} else {
|
||||
w = w - .5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (w > 0) {
|
||||
//clockwise
|
||||
} else {
|
||||
//counter clock wise
|
||||
List<BezierEdge> newShape = new ArrayList<>();
|
||||
List<Double> newBeLength = new ArrayList<>();
|
||||
for (int j = shape.size() - 1; j >= 0; j--) {
|
||||
newShape.add(shape.get(j).reverse());
|
||||
newBeLength.add(bezierLengths.get(i).get(j));
|
||||
}
|
||||
shape.clear();
|
||||
shape.addAll(newShape);
|
||||
bezierLengths.get(i).clear();
|
||||
bezierLengths.get(i).addAll(newBeLength);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < shapes.size(); i++) {
|
||||
List<BezierEdge> shape = shapes.get(i);
|
||||
//closed shape
|
||||
if (shape.get(0).getBeginPoint().equals(shape.get(shape.size() - 1).getEndPoint())) {
|
||||
|
||||
//Find most top left point
|
||||
double minX = Double.MAX_VALUE;
|
||||
double minY = Double.MAX_VALUE;
|
||||
|
||||
for (int j = 0; j < shape.size(); j++) {
|
||||
if (shape.get(j).getBeginPoint().getX() < minX) {
|
||||
minX = shape.get(j).getBeginPoint().getX();
|
||||
}
|
||||
if (shape.get(j).getBeginPoint().getY() < minY) {
|
||||
minY = shape.get(j).getBeginPoint().getY();
|
||||
}
|
||||
}
|
||||
double minDist = Double.MAX_VALUE;
|
||||
int minPos = -1;
|
||||
for (int j = 0; j < shape.size(); j++) {
|
||||
double dist = shape.get(j).getBeginPoint().distance(minX, minY);
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
minPos = j;
|
||||
}
|
||||
}
|
||||
if (minPos > -1) {
|
||||
//Rearange shape to start with the top left point
|
||||
for (int j = 0; j < minPos; j++) {
|
||||
shape.add(shape.remove(0));
|
||||
bezierLengths.get(i).add(bezierLengths.get(i).remove(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (List<Double> pp : bezierLengths) {
|
||||
List<Double> ppPercent = new ArrayList<>();
|
||||
double len = 0.0;
|
||||
for (double bLength : pp) {
|
||||
len += bLength;
|
||||
}
|
||||
double pos = 0;
|
||||
for (double bLength : pp) {
|
||||
double pct = roundPct(pos / len);
|
||||
pos += bLength;
|
||||
ppPercent.add(pct);
|
||||
}
|
||||
ppPercent.add(1.0);
|
||||
pointsPosPercent.add(ppPercent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginAliasedFills() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginFills() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endFills() {
|
||||
endCurrent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginLines() {
|
||||
currentShape = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endLines(boolean close) {
|
||||
endCurrent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginFill(RGB color) {
|
||||
endCurrent();
|
||||
currentShape = new ArrayList<>();
|
||||
currentFillStyle = fillStyles.size();
|
||||
FILLSTYLE fillStyle = new FILLSTYLE();
|
||||
fillStyle.fillStyleType = FILLSTYLE.SOLID;
|
||||
fillStyle.color = color;
|
||||
fillStyles.add(fillStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginGradientFill(int type, GRADRECORD[] gradientRecords, Matrix matrix, int spreadMethod, int interpolationMethod, float focalPointRatio) {
|
||||
endCurrent();
|
||||
currentShape = new ArrayList<>();
|
||||
currentFillStyle = fillStyles.size();
|
||||
FILLSTYLE fillStyle = new FILLSTYLE();
|
||||
fillStyle.fillStyleType = type;
|
||||
fillStyle.gradient = focalPointRatio == 0 ? new FOCALGRADIENT() : new GRADIENT();
|
||||
fillStyle.gradient.gradientRecords = Helper.deepCopy(gradientRecords);
|
||||
fillStyle.gradientMatrix = matrix.toMATRIX();
|
||||
fillStyle.gradient.spreadMode = spreadMethod;
|
||||
fillStyle.gradient.interpolationMode = interpolationMethod;
|
||||
if (focalPointRatio != 0) {
|
||||
((FOCALGRADIENT) fillStyle.gradient).focalPoint = focalPointRatio;
|
||||
}
|
||||
fillStyles.add(fillStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginBitmapFill(int bitmapId, Matrix matrix, boolean repeat, boolean smooth, ColorTransform colorTransform) {
|
||||
endCurrent();
|
||||
currentShape = new ArrayList<>();
|
||||
currentFillStyle = fillStyles.size();
|
||||
FILLSTYLE fillStyle = new FILLSTYLE();
|
||||
if (repeat) {
|
||||
if (smooth) {
|
||||
fillStyle.fillStyleType = FILLSTYLE.REPEATING_BITMAP;
|
||||
} else {
|
||||
fillStyle.fillStyleType = FILLSTYLE.NON_SMOOTHED_REPEATING_BITMAP;
|
||||
}
|
||||
} else {
|
||||
if (smooth) {
|
||||
fillStyle.fillStyleType = FILLSTYLE.CLIPPED_BITMAP;
|
||||
} else {
|
||||
fillStyle.fillStyleType = FILLSTYLE.NON_SMOOTHED_CLIPPED_BITMAP;
|
||||
}
|
||||
}
|
||||
fillStyle.bitmapMatrix = matrix.toMATRIX();
|
||||
fillStyle.bitmapId = bitmapId;
|
||||
fillStyles.add(fillStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endFill() {
|
||||
endCurrent();
|
||||
}
|
||||
|
||||
private void endCurrent() {
|
||||
if (currentShape != null && !currentShape.isEmpty()) {
|
||||
shapes.add(currentShape);
|
||||
bezierLengths.add(currentBezierLengths);
|
||||
pointsSum.add(currentPointsSum);
|
||||
segmentCount.add(currentSegmentCount);
|
||||
fillStyleIndices.add(currentFillStyle);
|
||||
lineStyleIndices.add(currentLineStyle);
|
||||
}
|
||||
currentShapeLen = 0;
|
||||
currentShape = new ArrayList<>();
|
||||
currentBezierLengths = new ArrayList<>();
|
||||
currentPointsSum = new Point2D.Double();
|
||||
currentSegmentCount = 0;
|
||||
currentFillStyle = -1;
|
||||
currentLineStyle = -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lineStyle(double thickness, RGB color, boolean pixelHinting, String scaleMode, int startCaps, int endCaps, int joints, float miterLimit) {
|
||||
endCurrent();
|
||||
currentLineStyle = lineStyles.size();
|
||||
LINESTYLE2 lineStyle = new LINESTYLE2();
|
||||
lineStyle.width = (int) thickness;
|
||||
lineStyle.color = new RGBA(color);
|
||||
lineStyle.pixelHintingFlag = pixelHinting;
|
||||
switch (scaleMode) {
|
||||
case "NONE":
|
||||
lineStyle.noHScaleFlag = true;
|
||||
lineStyle.noVScaleFlag = true;
|
||||
break;
|
||||
case "VERTICAL":
|
||||
lineStyle.noHScaleFlag = true;
|
||||
break;
|
||||
case "HORIZONTAL":
|
||||
lineStyle.noVScaleFlag = true;
|
||||
break;
|
||||
}
|
||||
lineStyle.startCapStyle = startCaps;
|
||||
lineStyle.endCapStyle = endCaps;
|
||||
lineStyle.joinStyle = joints;
|
||||
lineStyle.miterLimitFactor = miterLimit;
|
||||
lineStyles.add(lineStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lineGradientStyle(int type, GRADRECORD[] gradientRecords, Matrix matrix, int spreadMethod, int interpolationMethod, float focalPointRatio) {
|
||||
LINESTYLE2 lineStyle = lineStyles.get(lineStyles.size() - 1);
|
||||
lineStyle.hasFillFlag = true;
|
||||
FILLSTYLE fillStyle = new FILLSTYLE();
|
||||
fillStyle.fillStyleType = type;
|
||||
fillStyle.gradient = focalPointRatio == 0 ? new FOCALGRADIENT() : new GRADIENT();
|
||||
fillStyle.gradient.gradientRecords = Helper.deepCopy(gradientRecords);
|
||||
fillStyle.gradientMatrix = matrix.toMATRIX();
|
||||
fillStyle.gradient.spreadMode = spreadMethod;
|
||||
fillStyle.gradient.interpolationMode = interpolationMethod;
|
||||
if (focalPointRatio != 0) {
|
||||
((FOCALGRADIENT) fillStyle.gradient).focalPoint = focalPointRatio;
|
||||
}
|
||||
lineStyle.fillType = fillStyle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lineBitmapStyle(int bitmapId, Matrix matrix, boolean repeat, boolean smooth, ColorTransform colorTransform) {
|
||||
LINESTYLE2 lineStyle = lineStyles.get(lineStyles.size() - 1);
|
||||
lineStyle.hasFillFlag = true;
|
||||
FILLSTYLE fillStyle = new FILLSTYLE();
|
||||
if (repeat) {
|
||||
if (smooth) {
|
||||
fillStyle.fillStyleType = FILLSTYLE.REPEATING_BITMAP;
|
||||
} else {
|
||||
fillStyle.fillStyleType = FILLSTYLE.NON_SMOOTHED_REPEATING_BITMAP;
|
||||
}
|
||||
} else {
|
||||
if (smooth) {
|
||||
fillStyle.fillStyleType = FILLSTYLE.CLIPPED_BITMAP;
|
||||
} else {
|
||||
fillStyle.fillStyleType = FILLSTYLE.NON_SMOOTHED_CLIPPED_BITMAP;
|
||||
}
|
||||
}
|
||||
fillStyle.bitmapMatrix = matrix.toMATRIX();
|
||||
fillStyle.bitmapId = bitmapId;
|
||||
lineStyle.fillType = fillStyle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void moveTo(double x, double y) {
|
||||
int backupFillStyle = currentFillStyle;
|
||||
int backupLineStyle = currentLineStyle;
|
||||
endCurrent();
|
||||
currentFillStyle = backupFillStyle;
|
||||
currentLineStyle = backupLineStyle;
|
||||
lastX = (int) x;
|
||||
lastY = (int) y;
|
||||
//currentPointsPos.add(0.0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void lineTo(double x, double y) {
|
||||
if (x == lastX && y == lastY) {
|
||||
return;
|
||||
}
|
||||
BezierEdge be = new BezierEdge(lastX, lastY, x, y);
|
||||
|
||||
currentPointsSum.x += x; // - lastX;
|
||||
currentPointsSum.y += y; // - lastY;
|
||||
|
||||
currentShape.add(be);
|
||||
lastX = x;
|
||||
lastY = y;
|
||||
currentBezierLengths.add(be.length());
|
||||
currentShapeLen += be.length();
|
||||
|
||||
currentSegmentCount++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void curveTo(double controlX, double controlY, double anchorX, double anchorY) {
|
||||
|
||||
if (anchorX == lastX && anchorY == lastY) {
|
||||
return;
|
||||
}
|
||||
|
||||
BezierEdge be = new BezierEdge(lastX, lastY, controlX, controlY, anchorX, anchorY);
|
||||
|
||||
currentShape.add(be);
|
||||
|
||||
currentPointsSum.x += anchorX; // - lastX;
|
||||
currentPointsSum.y += anchorY; // - lastY;
|
||||
|
||||
lastX = anchorX;
|
||||
lastY = anchorY;
|
||||
currentBezierLengths.add(be.length());
|
||||
currentShapeLen += be.length();
|
||||
|
||||
currentSegmentCount++;
|
||||
}
|
||||
|
||||
private double roundPct(double pct) {
|
||||
double precision = 1000000d;
|
||||
return Math.round(pct * precision) / precision;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2010-2023 JPEXS, All rights reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 3.0 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library.
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.importers.morphshape;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class StyleMismatchException extends Exception {
|
||||
|
||||
}
|
||||
@@ -226,6 +226,11 @@ public class SvgImporter {
|
||||
transform = Matrix.getScaleInstance(ratioX, ratioY);
|
||||
transform.translate(origXmin / SWF.unitDivisor / ratioX, origYmin / SWF.unitDivisor / ratioY);
|
||||
}
|
||||
|
||||
transform = transform.preConcatenate(Matrix.getTranslateInstance(-viewBox.x, -viewBox.y));
|
||||
if (viewBox.height != 0 && viewBox.width != 0) {
|
||||
transform = transform.preConcatenate(Matrix.getScaleInstance(width / viewBox.width, height / viewBox.height));
|
||||
}
|
||||
|
||||
processSvgObject(idMap, shapeNum, shapes, rootElement, transform, style, morphShape);
|
||||
} catch (SAXException | IOException | ParserConfigurationException ex) {
|
||||
|
||||
@@ -19,14 +19,16 @@ package com.jpexs.decompiler.flash.math;
|
||||
import com.jpexs.helpers.Reference;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author JPEXS
|
||||
*/
|
||||
public class BezierEdge {
|
||||
public class BezierEdge implements Serializable {
|
||||
|
||||
public List<Point2D> points = new ArrayList<>();
|
||||
|
||||
@@ -45,6 +47,14 @@ public class BezierEdge {
|
||||
points.add(new Point2D.Double(x1, y1));
|
||||
}
|
||||
|
||||
public Point2D getBeginPoint() {
|
||||
return points.get(0);
|
||||
}
|
||||
|
||||
public Point2D getEndPoint() {
|
||||
return points.get(points.size() - 1);
|
||||
}
|
||||
|
||||
public Point2D pointAt(double t) {
|
||||
if (points.size() == 2) {
|
||||
double x = (1 - t) * points.get(0).getX() + t * points.get(1).getX();
|
||||
@@ -189,6 +199,30 @@ public class BezierEdge {
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
public double length() {
|
||||
double distance = 0;
|
||||
double epsilon = 1;
|
||||
|
||||
Stack<BezierEdge> parts = new Stack<BezierEdge>();
|
||||
parts.push(this);
|
||||
|
||||
while (!parts.isEmpty()) {
|
||||
BezierEdge curve = parts.pop();
|
||||
double d = curve.points.get(0).distance(curve.points.get(curve.points.size() - 1));
|
||||
if (d < epsilon) {
|
||||
distance += d;
|
||||
} else {
|
||||
Reference<BezierEdge> leftRef = new Reference<>(null);
|
||||
Reference<BezierEdge> rightRef = new Reference<>(null);
|
||||
curve.split(0.5, leftRef, rightRef);
|
||||
parts.add(leftRef.getVal());
|
||||
parts.add(rightRef.getVal());
|
||||
}
|
||||
}
|
||||
return distance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@@ -207,6 +241,14 @@ public class BezierEdge {
|
||||
left.setVal(new BezierEdge(leftPoints));
|
||||
right.setVal(new BezierEdge(rightPoints));
|
||||
}
|
||||
|
||||
public BezierEdge reverse() {
|
||||
List<Point2D> revPoints = new ArrayList<>();
|
||||
for (int i = points.size() - 1; i >= 0; i--) {
|
||||
revPoints.add(points.get(i));
|
||||
}
|
||||
return new BezierEdge(revPoints);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
List<Double> t1 = new ArrayList<>();
|
||||
@@ -245,6 +287,10 @@ public class BezierEdge {
|
||||
);
|
||||
|
||||
System.out.println("Intersection point: " + c);
|
||||
|
||||
BezierEdge be = new BezierEdge(0, 0, 100, 50, 0, 100);
|
||||
|
||||
System.out.println("be5.dist: " + be.length());
|
||||
|
||||
//Rectangle2D out = new Rectangle2D.Double();
|
||||
//rectIntersection(new Rectangle2D.Double(0,0,50,50), new Rectangle2D.Double(0,50,50,50), out);
|
||||
|
||||
@@ -84,7 +84,7 @@ public abstract class ShapeTag extends DrawableTag implements LazyObject {
|
||||
|
||||
public abstract int getShapeNum();
|
||||
|
||||
public SHAPEWITHSTYLE getShapes() {
|
||||
public synchronized SHAPEWITHSTYLE getShapes() {
|
||||
if (shapes == null && shapeData != null) {
|
||||
try {
|
||||
SWFInputStream sis = new SWFInputStream(swf, shapeData.getArray(), 0, shapeData.getPos() + shapeData.getLength());
|
||||
|
||||
@@ -151,6 +151,30 @@ public class FILLSTYLE implements NeedsCharacters, FieldChangeObserver, Serializ
|
||||
gradient = g;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isCompatibleFillStyle(FILLSTYLE otherFillStyle) {
|
||||
if (fillStyleType != otherFillStyle.fillStyleType) {
|
||||
return false;
|
||||
}
|
||||
switch (fillStyleType) {
|
||||
case CLIPPED_BITMAP:
|
||||
case NON_SMOOTHED_CLIPPED_BITMAP:
|
||||
case NON_SMOOTHED_REPEATING_BITMAP:
|
||||
case REPEATING_BITMAP:
|
||||
if (bitmapId != otherFillStyle.bitmapId) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case LINEAR_GRADIENT:
|
||||
case RADIAL_GRADIENT:
|
||||
case FOCAL_RADIAL_GRADIENT:
|
||||
if (!gradient.isCompatibleGradient(otherFillStyle.gradient)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public MORPHFILLSTYLE toMorphStyle() {
|
||||
@@ -171,4 +195,30 @@ public class FILLSTYLE implements NeedsCharacters, FieldChangeObserver, Serializ
|
||||
|
||||
return morphFillStyle;
|
||||
}
|
||||
|
||||
public MORPHFILLSTYLE toMorphStyle(FILLSTYLE endFillStyle) {
|
||||
if (!isCompatibleFillStyle(endFillStyle)) {
|
||||
return null;
|
||||
}
|
||||
MORPHFILLSTYLE morphFillStyle = new MORPHFILLSTYLE();
|
||||
morphFillStyle.bitmapId = bitmapId;
|
||||
if (bitmapMatrix != null) {
|
||||
morphFillStyle.startBitmapMatrix = new MATRIX(bitmapMatrix);
|
||||
}
|
||||
if (endFillStyle.bitmapMatrix != null) {
|
||||
morphFillStyle.endBitmapMatrix = new MATRIX(endFillStyle.bitmapMatrix);
|
||||
}
|
||||
if (color != null) {
|
||||
morphFillStyle.startColor = new RGBA(color);
|
||||
}
|
||||
if (endFillStyle.color != null) {
|
||||
morphFillStyle.endColor = new RGBA(endFillStyle.color);
|
||||
}
|
||||
morphFillStyle.fillStyleType = fillStyleType;
|
||||
if (gradient != null) {
|
||||
morphFillStyle.gradient = gradient.toMorphGradient(endFillStyle.gradient);
|
||||
}
|
||||
|
||||
return morphFillStyle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,20 @@ public class GRADIENT implements Serializable {
|
||||
public static final int INTERPOLATION_RESERVED2 = 3;
|
||||
|
||||
@SWFArray(value = "record")
|
||||
public GRADRECORD[] gradientRecords = new GRADRECORD[0];
|
||||
public GRADRECORD[] gradientRecords = new GRADRECORD[0];
|
||||
|
||||
public boolean isCompatibleGradient(GRADIENT otherGradient) {
|
||||
if (interpolationMode != otherGradient.interpolationMode) {
|
||||
return false;
|
||||
}
|
||||
if (spreadMode != otherGradient.spreadMode) {
|
||||
return false;
|
||||
}
|
||||
if (gradientRecords.length != otherGradient.gradientRecords.length) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public MORPHGRADIENT toMorphGradient() {
|
||||
MORPHGRADIENT morphGradient = new MORPHGRADIENT();
|
||||
@@ -73,4 +86,18 @@ public class GRADIENT implements Serializable {
|
||||
}
|
||||
return morphGradient;
|
||||
}
|
||||
|
||||
public MORPHGRADIENT toMorphGradient(GRADIENT endGradient) {
|
||||
if (!isCompatibleGradient(endGradient)) {
|
||||
return null;
|
||||
}
|
||||
MORPHGRADIENT morphGradient = new MORPHGRADIENT();
|
||||
morphGradient.interPolationMode = interpolationMode;
|
||||
morphGradient.spreadMode = spreadMode;
|
||||
morphGradient.gradientRecords = new MORPHGRADRECORD[gradientRecords.length];
|
||||
for (int i = 0; i < gradientRecords.length; i++) {
|
||||
morphGradient.gradientRecords[i] = gradientRecords[i].toMorphGradRecord();
|
||||
}
|
||||
return morphGradient;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,4 +46,13 @@ public class GRADRECORD implements Serializable {
|
||||
morphGradRecord.endRatio = ratio;
|
||||
return morphGradRecord;
|
||||
}
|
||||
|
||||
public MORPHGRADRECORD toMorphGradRecord(GRADRECORD endGradRecord) {
|
||||
MORPHGRADRECORD morphGradRecord = new MORPHGRADRECORD();
|
||||
morphGradRecord.startColor = new RGBA(color);
|
||||
morphGradRecord.endColor = new RGBA(endGradRecord.color);
|
||||
morphGradRecord.startRatio = ratio;
|
||||
morphGradRecord.endRatio = endGradRecord.ratio;
|
||||
return morphGradRecord;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,6 +141,44 @@ public class LINESTYLE2 implements NeedsCharacters, Serializable, ILINESTYLE {
|
||||
@Override
|
||||
public void setWidth(int width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public boolean isCompatibleLineStyle(LINESTYLE2 otherLineStyle) {
|
||||
if (startCapStyle != otherLineStyle.startCapStyle) {
|
||||
return false;
|
||||
}
|
||||
if (endCapStyle != otherLineStyle.endCapStyle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (joinStyle != otherLineStyle.joinStyle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hasFillFlag != otherLineStyle.hasFillFlag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (noVScaleFlag != otherLineStyle.noVScaleFlag) {
|
||||
return false;
|
||||
}
|
||||
if (pixelHintingFlag != otherLineStyle.pixelHintingFlag) {
|
||||
return false;
|
||||
}
|
||||
if (noClose != otherLineStyle.noClose) {
|
||||
return false;
|
||||
}
|
||||
if (miterLimitFactor != otherLineStyle.miterLimitFactor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hasFillFlag) {
|
||||
if (!fillType.isCompatibleFillStyle(otherLineStyle.fillType)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public MORPHLINESTYLE2 toMorphLineStyle2() {
|
||||
@@ -165,4 +203,33 @@ public class LINESTYLE2 implements NeedsCharacters, Serializable, ILINESTYLE {
|
||||
}
|
||||
return morphLineStyle2;
|
||||
}
|
||||
|
||||
public MORPHLINESTYLE2 toMorphLineStyle2(LINESTYLE2 endLineStyle) {
|
||||
if (!isCompatibleLineStyle(endLineStyle)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
MORPHLINESTYLE2 morphLineStyle2 = new MORPHLINESTYLE2();
|
||||
morphLineStyle2.startWidth = width;
|
||||
morphLineStyle2.endWidth = endLineStyle.width;
|
||||
morphLineStyle2.startCapStyle = startCapStyle;
|
||||
morphLineStyle2.joinStyle = joinStyle;
|
||||
morphLineStyle2.hasFillFlag = hasFillFlag;
|
||||
morphLineStyle2.noHScaleFlag = noHScaleFlag;
|
||||
morphLineStyle2.noVScaleFlag = noVScaleFlag;
|
||||
morphLineStyle2.pixelHintingFlag = pixelHintingFlag;
|
||||
morphLineStyle2.noClose = noClose;
|
||||
morphLineStyle2.endCapStyle = endCapStyle;
|
||||
morphLineStyle2.miterLimitFactor = miterLimitFactor;
|
||||
if (color != null) {
|
||||
morphLineStyle2.startColor = new RGBA(color);
|
||||
}
|
||||
if (endLineStyle.color != null) {
|
||||
morphLineStyle2.endColor = new RGBA(endLineStyle.color);
|
||||
}
|
||||
if (hasFillFlag) {
|
||||
morphLineStyle2.fillType = fillType.toMorphStyle(endLineStyle.fillType);
|
||||
}
|
||||
return morphLineStyle2;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user