mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-18 21:18:09 +00:00
common code from DefineMorphShapeX tags moved to base class
This commit is contained in:
@@ -19,42 +19,20 @@ package com.jpexs.decompiler.flash.tags;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.morphshape.CanvasMorphShapeExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.morphshape.SVGMorphShapeExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.shape.BitmapExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.shape.SVGShapeExporter;
|
||||
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.MorphShapeTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.RenderContext;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.ColorTransform;
|
||||
import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.LINESTYLEARRAY;
|
||||
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.RECT;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE;
|
||||
import com.jpexs.decompiler.flash.types.annotations.Reserved;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
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.ByteArrayRange;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import java.awt.Shape;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -63,13 +41,6 @@ import java.util.Set;
|
||||
*/
|
||||
public class DefineMorphShape2Tag extends MorphShapeTag {
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int characterId;
|
||||
|
||||
public RECT startBounds;
|
||||
|
||||
public RECT endBounds;
|
||||
|
||||
public RECT startEdgeBounds;
|
||||
|
||||
public RECT endEdgeBounds;
|
||||
@@ -82,64 +53,8 @@ public class DefineMorphShape2Tag extends MorphShapeTag {
|
||||
|
||||
public boolean usesScalingStrokes;
|
||||
|
||||
public MORPHFILLSTYLEARRAY morphFillStyles;
|
||||
|
||||
public MORPHLINESTYLEARRAY morphLineStyles;
|
||||
|
||||
public SHAPE startEdges;
|
||||
|
||||
public SHAPE endEdges;
|
||||
|
||||
public static final int ID = 84;
|
||||
|
||||
public static final int MAX_RATIO = 65535;
|
||||
|
||||
@Override
|
||||
public void getNeededCharacters(Set<Integer> needed) {
|
||||
morphFillStyles.getNeededCharacters(needed);
|
||||
startEdges.getNeededCharacters(needed);
|
||||
endEdges.getNeededCharacters(needed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
|
||||
boolean modified = false;
|
||||
modified |= morphFillStyles.replaceCharacter(oldCharacterId, newCharacterId);
|
||||
modified |= startEdges.replaceCharacter(oldCharacterId, newCharacterId);
|
||||
modified |= endEdges.replaceCharacter(oldCharacterId, newCharacterId);
|
||||
if (modified) {
|
||||
setModified(true);
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeCharacter(int characterId) {
|
||||
boolean modified = false;
|
||||
modified |= morphFillStyles.removeCharacter(characterId);
|
||||
modified |= startEdges.removeCharacter(characterId);
|
||||
modified |= endEdges.removeCharacter(characterId);
|
||||
if (modified) {
|
||||
setModified(true);
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RECT getRect(Set<BoundedTag> added) {
|
||||
RECT rect = new RECT();
|
||||
rect.Xmin = Math.min(startBounds.Xmin, endBounds.Xmin);
|
||||
rect.Ymin = Math.min(startBounds.Ymin, endBounds.Ymin);
|
||||
rect.Xmax = Math.max(startBounds.Xmax, endBounds.Xmax);
|
||||
rect.Ymax = Math.max(startBounds.Ymax, endBounds.Ymax);
|
||||
return rect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCharacterId() {
|
||||
return characterId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
@@ -216,221 +131,15 @@ public class DefineMorphShape2Tag extends MorphShapeTag {
|
||||
reserved = (int) sis.readUB(6, "reserved");
|
||||
usesNonScalingStrokes = sis.readUB(1, "usesNonScalingStrokes") == 1;
|
||||
usesScalingStrokes = sis.readUB(1, "usesScalingStrokes") == 1;
|
||||
long offset = sis.readUI32("offset");
|
||||
long offset = sis.readUI32("offset"); // ignore
|
||||
morphFillStyles = sis.readMORPHFILLSTYLEARRAY("morphFillStyles");
|
||||
morphLineStyles = sis.readMORPHLINESTYLEARRAY(2, "morphLineStyles");
|
||||
startEdges = sis.readSHAPE(2, true, "startEdges");
|
||||
endEdges = sis.readSHAPE(2, true, "endEdges");
|
||||
}
|
||||
|
||||
@Override
|
||||
public RECT getStartBounds() {
|
||||
return startBounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RECT getEndBounds() {
|
||||
return endBounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MORPHFILLSTYLEARRAY getFillStyles() {
|
||||
return morphFillStyles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MORPHLINESTYLEARRAY getLineStyles() {
|
||||
return morphLineStyles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SHAPE getStartEdges() {
|
||||
return startEdges;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SHAPE getEndEdges() {
|
||||
return endEdges;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getShapeNum() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SHAPEWITHSTYLE getShapeAtRatio(int ratio) {
|
||||
List<SHAPERECORD> finalRecords = new ArrayList<>();
|
||||
FILLSTYLEARRAY fillStyles = morphFillStyles.getFillStylesAt(ratio);
|
||||
LINESTYLEARRAY lineStyles = morphLineStyles.getLineStylesAt(getShapeNum(), ratio);
|
||||
|
||||
int startPosX = 0, startPosY = 0;
|
||||
int endPosX = 0, endPosY = 0;
|
||||
int posX = 0, posY = 0;
|
||||
|
||||
for (int startIndex = 0, endIndex = 0;
|
||||
startIndex < startEdges.shapeRecords.size()
|
||||
&& endIndex < endEdges.shapeRecords.size(); startIndex++, endIndex++) {
|
||||
|
||||
SHAPERECORD edge1 = startEdges.shapeRecords.get(startIndex);
|
||||
SHAPERECORD edge2 = endEdges.shapeRecords.get(endIndex);
|
||||
if (edge1 instanceof StyleChangeRecord || edge2 instanceof StyleChangeRecord) {
|
||||
StyleChangeRecord scr1;
|
||||
if (edge1 instanceof StyleChangeRecord) {
|
||||
scr1 = (StyleChangeRecord) edge1;
|
||||
if (scr1.stateMoveTo) {
|
||||
startPosX = scr1.moveDeltaX;
|
||||
startPosY = scr1.moveDeltaY;
|
||||
}
|
||||
} else {
|
||||
scr1 = new StyleChangeRecord();
|
||||
startIndex--;
|
||||
}
|
||||
StyleChangeRecord scr2;
|
||||
if (edge2 instanceof StyleChangeRecord) {
|
||||
scr2 = (StyleChangeRecord) edge2;
|
||||
if (scr2.stateMoveTo) {
|
||||
endPosX = scr2.moveDeltaX;
|
||||
endPosY = scr2.moveDeltaY;
|
||||
}
|
||||
} else {
|
||||
scr2 = new StyleChangeRecord();
|
||||
endIndex--;
|
||||
}
|
||||
StyleChangeRecord scr = scr1.clone();
|
||||
if (scr1.stateMoveTo || scr2.stateMoveTo) {
|
||||
scr.moveDeltaX = startPosX + (endPosX - startPosX) * ratio / 65535;
|
||||
scr.moveDeltaY = startPosY + (endPosY - startPosY) * ratio / 65535;
|
||||
scr.stateMoveTo = scr.moveDeltaX != posX || scr.moveDeltaY != posY;
|
||||
}
|
||||
finalRecords.add(scr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (edge1 instanceof EndShapeRecord) {
|
||||
finalRecords.add(edge1);
|
||||
break;
|
||||
}
|
||||
if (edge2 instanceof EndShapeRecord) {
|
||||
finalRecords.add(edge2);
|
||||
break;
|
||||
}
|
||||
|
||||
if (edge1 instanceof CurvedEdgeRecord || edge2 instanceof CurvedEdgeRecord) {
|
||||
CurvedEdgeRecord cer1 = null;
|
||||
if (edge1 instanceof CurvedEdgeRecord) {
|
||||
cer1 = (CurvedEdgeRecord) edge1;
|
||||
} else if (edge1 instanceof StraightEdgeRecord) {
|
||||
cer1 = SHAPERECORD.straightToCurve((StraightEdgeRecord) edge1);
|
||||
}
|
||||
CurvedEdgeRecord cer2 = null;
|
||||
if (edge2 instanceof CurvedEdgeRecord) {
|
||||
cer2 = (CurvedEdgeRecord) edge2;
|
||||
} else if (edge2 instanceof StraightEdgeRecord) {
|
||||
cer2 = SHAPERECORD.straightToCurve((StraightEdgeRecord) edge2);
|
||||
}
|
||||
if ((cer2 == null) || (cer1 == null)) {
|
||||
continue;
|
||||
}
|
||||
CurvedEdgeRecord cer = new CurvedEdgeRecord();
|
||||
cer.controlDeltaX = cer1.controlDeltaX + (cer2.controlDeltaX - cer1.controlDeltaX) * ratio / 65535;
|
||||
cer.controlDeltaY = cer1.controlDeltaY + (cer2.controlDeltaY - cer1.controlDeltaY) * ratio / 65535;
|
||||
cer.anchorDeltaX = cer1.anchorDeltaX + (cer2.anchorDeltaX - cer1.anchorDeltaX) * ratio / 65535;
|
||||
cer.anchorDeltaY = cer1.anchorDeltaY + (cer2.anchorDeltaY - cer1.anchorDeltaY) * ratio / 65535;
|
||||
startPosX += cer1.controlDeltaX + cer1.anchorDeltaX;
|
||||
startPosY += cer1.controlDeltaY + cer1.anchorDeltaY;
|
||||
endPosX += cer2.controlDeltaX + cer2.anchorDeltaX;
|
||||
endPosY += cer2.controlDeltaY + cer2.anchorDeltaY;
|
||||
posX += cer.controlDeltaX + cer.anchorDeltaX;
|
||||
posY += cer.controlDeltaY + cer.anchorDeltaY;
|
||||
finalRecords.add(cer);
|
||||
} else {
|
||||
StraightEdgeRecord ser1 = null;
|
||||
if (edge1 instanceof StraightEdgeRecord) {
|
||||
ser1 = (StraightEdgeRecord) edge1;
|
||||
}
|
||||
StraightEdgeRecord ser2 = null;
|
||||
if (edge2 instanceof StraightEdgeRecord) {
|
||||
ser2 = (StraightEdgeRecord) edge2;
|
||||
}
|
||||
if ((ser2 == null) || (ser1 == null)) {
|
||||
continue;
|
||||
}
|
||||
StraightEdgeRecord ser = new StraightEdgeRecord();
|
||||
ser.generalLineFlag = true;
|
||||
ser.vertLineFlag = false;
|
||||
ser.deltaX = ser1.deltaX + (ser2.deltaX - ser1.deltaX) * ratio / 65535;
|
||||
ser.deltaY = ser1.deltaY + (ser2.deltaY - ser1.deltaY) * ratio / 65535;
|
||||
startPosX += ser1.deltaX;
|
||||
startPosY += ser1.deltaY;
|
||||
endPosX += ser2.deltaX;
|
||||
endPosY += ser2.deltaY;
|
||||
posX += ser.deltaX;
|
||||
posY += ser.deltaX;
|
||||
finalRecords.add(ser);
|
||||
}
|
||||
}
|
||||
SHAPEWITHSTYLE shape = new SHAPEWITHSTYLE();
|
||||
shape.fillStyles = fillStyles;
|
||||
shape.lineStyles = lineStyles;
|
||||
shape.shapeRecords = finalRecords;
|
||||
return shape;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUsedParameters() {
|
||||
return PARAMETER_RATIO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, Matrix transformation, ColorTransform colorTransform) {
|
||||
SHAPEWITHSTYLE shape = getShapeAtRatio(ratio);
|
||||
// shapeNum: 4
|
||||
// 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(swf, shape, null, image, transformation, colorTransform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, double zoom) {
|
||||
if (ratio == -2) {
|
||||
SHAPEWITHSTYLE beginShapes = getShapeAtRatio(0);
|
||||
SHAPEWITHSTYLE endShapes = getShapeAtRatio(65535);
|
||||
SVGMorphShapeExporter shapeExporter = new SVGMorphShapeExporter(swf, beginShapes, endShapes, exporter, null, colorTransform, zoom);
|
||||
shapeExporter.export();
|
||||
} else {
|
||||
SHAPEWITHSTYLE shapes = getShapeAtRatio(ratio);
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(swf, shapes, exporter, null, colorTransform, zoom);
|
||||
shapeExporter.export();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumFrames() {
|
||||
return 65536;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleFrame() {
|
||||
// Morpshape is a single frame specified with the ratio
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getOutline(int frame, int time, int ratio, RenderContext renderContext, Matrix transformation) {
|
||||
return transformation.toTransform().createTransformedShape(getShapeAtRatio(ratio).getOutline());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toHtmlCanvas(double unitDivisor) {
|
||||
CanvasMorphShapeExporter cmse = new CanvasMorphShapeExporter(swf, getShapeAtRatio(0), getShapeAtRatio(MAX_RATIO), new ColorTransform(), unitDivisor, 0, 0);
|
||||
cmse.export();
|
||||
return cmse.getShapeData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterId(int characterId) {
|
||||
this.characterId = characterId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,41 +19,17 @@ package com.jpexs.decompiler.flash.tags;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.SWFOutputStream;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.Matrix;
|
||||
import com.jpexs.decompiler.flash.exporters.commonshape.SVGExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.morphshape.CanvasMorphShapeExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.morphshape.SVGMorphShapeExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.shape.BitmapExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.shape.SVGShapeExporter;
|
||||
import com.jpexs.decompiler.flash.tags.base.BoundedTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.MorphShapeTag;
|
||||
import com.jpexs.decompiler.flash.tags.base.RenderContext;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.ColorTransform;
|
||||
import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.LINESTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.MORPHFILLSTYLE;
|
||||
import com.jpexs.decompiler.flash.types.MORPHFILLSTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.MORPHLINESTYLE;
|
||||
import com.jpexs.decompiler.flash.types.MORPHLINESTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.RECT;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
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.ByteArrayRange;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import java.awt.Shape;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -62,61 +38,8 @@ import java.util.Set;
|
||||
*/
|
||||
public class DefineMorphShapeTag extends MorphShapeTag {
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int characterId;
|
||||
|
||||
public RECT startBounds;
|
||||
|
||||
public RECT endBounds;
|
||||
|
||||
public MORPHFILLSTYLEARRAY morphFillStyles;
|
||||
|
||||
public MORPHLINESTYLEARRAY morphLineStyles;
|
||||
|
||||
public SHAPE startEdges;
|
||||
|
||||
public SHAPE endEdges;
|
||||
|
||||
public static final int ID = 46;
|
||||
|
||||
public static final int MAX_RATIO = 65535;
|
||||
|
||||
@Override
|
||||
public void getNeededCharacters(Set<Integer> needed) {
|
||||
morphFillStyles.getNeededCharacters(needed);
|
||||
startEdges.getNeededCharacters(needed);
|
||||
endEdges.getNeededCharacters(needed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
|
||||
boolean modified = false;
|
||||
modified |= morphFillStyles.replaceCharacter(oldCharacterId, newCharacterId);
|
||||
modified |= startEdges.replaceCharacter(oldCharacterId, newCharacterId);
|
||||
modified |= endEdges.replaceCharacter(oldCharacterId, newCharacterId);
|
||||
if (modified) {
|
||||
setModified(true);
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeCharacter(int characterId) {
|
||||
boolean modified = false;
|
||||
modified |= morphFillStyles.removeCharacter(characterId);
|
||||
modified |= startEdges.removeCharacter(characterId);
|
||||
modified |= endEdges.removeCharacter(characterId);
|
||||
if (modified) {
|
||||
setModified(true);
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCharacterId() {
|
||||
return characterId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets data bytes
|
||||
*
|
||||
@@ -136,11 +59,10 @@ public class DefineMorphShapeTag extends MorphShapeTag {
|
||||
sos2.writeMORPHFILLSTYLEARRAY(morphFillStyles, 1);
|
||||
sos2.writeMORPHLINESTYLEARRAY(morphLineStyles, 1);
|
||||
sos2.writeSHAPE(startEdges, 1);
|
||||
byte[] d = baos2.toByteArray();
|
||||
sos.writeUI32(d.length);
|
||||
sos.write(d);
|
||||
byte[] ba2 = baos2.toByteArray();
|
||||
sos.writeUI32(ba2.length);
|
||||
sos.write(ba2);
|
||||
sos.writeSHAPE(endEdges, 1);
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new Error("This should never happen.", e);
|
||||
}
|
||||
@@ -189,224 +111,8 @@ public class DefineMorphShapeTag extends MorphShapeTag {
|
||||
endEdges = sis.readSHAPE(1, true, "endEdges");
|
||||
}
|
||||
|
||||
@Override
|
||||
public RECT getRect(Set<BoundedTag> added) {
|
||||
RECT rect = new RECT();
|
||||
rect.Xmin = Math.min(startBounds.Xmin, endBounds.Xmin);
|
||||
rect.Ymin = Math.min(startBounds.Ymin, endBounds.Ymin);
|
||||
rect.Xmax = Math.max(startBounds.Xmax, endBounds.Xmax);
|
||||
rect.Ymax = Math.max(startBounds.Ymax, endBounds.Ymax);
|
||||
return rect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RECT getStartBounds() {
|
||||
return startBounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RECT getEndBounds() {
|
||||
return endBounds;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MORPHFILLSTYLEARRAY getFillStyles() {
|
||||
return morphFillStyles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MORPHLINESTYLEARRAY getLineStyles() {
|
||||
return morphLineStyles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SHAPE getStartEdges() {
|
||||
return startEdges;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SHAPE getEndEdges() {
|
||||
return endEdges;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getShapeNum() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SHAPEWITHSTYLE getShapeAtRatio(int ratio) {
|
||||
List<SHAPERECORD> finalRecords = new ArrayList<>();
|
||||
FILLSTYLEARRAY fillStyles = morphFillStyles.getFillStylesAt(ratio);
|
||||
LINESTYLEARRAY lineStyles = morphLineStyles.getLineStylesAt(getShapeNum(), ratio);
|
||||
|
||||
int startPosX = 0, startPosY = 0;
|
||||
int endPosX = 0, endPosY = 0;
|
||||
int posX = 0, posY = 0;
|
||||
|
||||
for (int startIndex = 0, endIndex = 0;
|
||||
startIndex < startEdges.shapeRecords.size()
|
||||
&& endIndex < endEdges.shapeRecords.size(); startIndex++, endIndex++) {
|
||||
|
||||
SHAPERECORD edge1 = startEdges.shapeRecords.get(startIndex);
|
||||
SHAPERECORD edge2 = endEdges.shapeRecords.get(endIndex);
|
||||
if (edge1 instanceof StyleChangeRecord || edge2 instanceof StyleChangeRecord) {
|
||||
StyleChangeRecord scr1;
|
||||
if (edge1 instanceof StyleChangeRecord) {
|
||||
scr1 = (StyleChangeRecord) edge1;
|
||||
if (scr1.stateMoveTo) {
|
||||
startPosX = scr1.moveDeltaX;
|
||||
startPosY = scr1.moveDeltaY;
|
||||
}
|
||||
} else {
|
||||
scr1 = new StyleChangeRecord();
|
||||
startIndex--;
|
||||
}
|
||||
StyleChangeRecord scr2;
|
||||
if (edge2 instanceof StyleChangeRecord) {
|
||||
scr2 = (StyleChangeRecord) edge2;
|
||||
if (scr2.stateMoveTo) {
|
||||
endPosX = scr2.moveDeltaX;
|
||||
endPosY = scr2.moveDeltaY;
|
||||
}
|
||||
} else {
|
||||
scr2 = new StyleChangeRecord();
|
||||
endIndex--;
|
||||
}
|
||||
StyleChangeRecord scr = scr1.clone();
|
||||
if (scr1.stateMoveTo || scr2.stateMoveTo) {
|
||||
scr.moveDeltaX = startPosX + (endPosX - startPosX) * ratio / MAX_RATIO;
|
||||
scr.moveDeltaY = startPosY + (endPosY - startPosY) * ratio / MAX_RATIO;
|
||||
scr.stateMoveTo = scr.moveDeltaX != posX || scr.moveDeltaY != posY;
|
||||
}
|
||||
finalRecords.add(scr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (edge1 instanceof EndShapeRecord) {
|
||||
finalRecords.add(edge1);
|
||||
break;
|
||||
}
|
||||
if (edge2 instanceof EndShapeRecord) {
|
||||
finalRecords.add(edge2);
|
||||
break;
|
||||
}
|
||||
|
||||
if (edge1 instanceof CurvedEdgeRecord || edge2 instanceof CurvedEdgeRecord) {
|
||||
CurvedEdgeRecord cer1 = null;
|
||||
if (edge1 instanceof CurvedEdgeRecord) {
|
||||
cer1 = (CurvedEdgeRecord) edge1;
|
||||
} else if (edge1 instanceof StraightEdgeRecord) {
|
||||
cer1 = SHAPERECORD.straightToCurve((StraightEdgeRecord) edge1);
|
||||
}
|
||||
CurvedEdgeRecord cer2 = null;
|
||||
if (edge2 instanceof CurvedEdgeRecord) {
|
||||
cer2 = (CurvedEdgeRecord) edge2;
|
||||
} else if (edge2 instanceof StraightEdgeRecord) {
|
||||
cer2 = SHAPERECORD.straightToCurve((StraightEdgeRecord) edge2);
|
||||
}
|
||||
if ((cer2 == null) || (cer1 == null)) {
|
||||
continue;
|
||||
}
|
||||
CurvedEdgeRecord cer = new CurvedEdgeRecord();
|
||||
cer.controlDeltaX = cer1.controlDeltaX + (cer2.controlDeltaX - cer1.controlDeltaX) * ratio / MAX_RATIO;
|
||||
cer.controlDeltaY = cer1.controlDeltaY + (cer2.controlDeltaY - cer1.controlDeltaY) * ratio / MAX_RATIO;
|
||||
cer.anchorDeltaX = cer1.anchorDeltaX + (cer2.anchorDeltaX - cer1.anchorDeltaX) * ratio / MAX_RATIO;
|
||||
cer.anchorDeltaY = cer1.anchorDeltaY + (cer2.anchorDeltaY - cer1.anchorDeltaY) * ratio / MAX_RATIO;
|
||||
startPosX += cer1.controlDeltaX + cer1.anchorDeltaX;
|
||||
startPosY += cer1.controlDeltaY + cer1.anchorDeltaY;
|
||||
endPosX += cer2.controlDeltaX + cer2.anchorDeltaX;
|
||||
endPosY += cer2.controlDeltaY + cer2.anchorDeltaY;
|
||||
posX += cer.controlDeltaX + cer.anchorDeltaX;
|
||||
posY += cer.controlDeltaY + cer.anchorDeltaY;
|
||||
finalRecords.add(cer);
|
||||
} else {
|
||||
StraightEdgeRecord ser1 = null;
|
||||
if (edge1 instanceof StraightEdgeRecord) {
|
||||
ser1 = (StraightEdgeRecord) edge1;
|
||||
}
|
||||
StraightEdgeRecord ser2 = null;
|
||||
if (edge2 instanceof StraightEdgeRecord) {
|
||||
ser2 = (StraightEdgeRecord) edge2;
|
||||
}
|
||||
if ((ser2 == null) || (ser1 == null)) {
|
||||
continue;
|
||||
}
|
||||
StraightEdgeRecord ser = new StraightEdgeRecord();
|
||||
ser.generalLineFlag = true;
|
||||
ser.vertLineFlag = false;
|
||||
ser.deltaX = ser1.deltaX + (ser2.deltaX - ser1.deltaX) * ratio / MAX_RATIO;
|
||||
ser.deltaY = ser1.deltaY + (ser2.deltaY - ser1.deltaY) * ratio / MAX_RATIO;
|
||||
startPosX += ser1.deltaX;
|
||||
startPosY += ser1.deltaY;
|
||||
endPosX += ser2.deltaX;
|
||||
endPosY += ser2.deltaY;
|
||||
posX += ser.deltaX;
|
||||
posY += ser.deltaX;
|
||||
finalRecords.add(ser);
|
||||
}
|
||||
}
|
||||
SHAPEWITHSTYLE shape = new SHAPEWITHSTYLE();
|
||||
shape.fillStyles = fillStyles;
|
||||
shape.lineStyles = lineStyles;
|
||||
shape.shapeRecords = finalRecords;
|
||||
return shape;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUsedParameters() {
|
||||
return PARAMETER_RATIO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, Matrix transformation, ColorTransform colorTransform) {
|
||||
SHAPEWITHSTYLE shape = getShapeAtRatio(ratio);
|
||||
// shapeNum: 3
|
||||
// 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(swf, shape, null, image, transformation, colorTransform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, double zoom) {
|
||||
if (ratio == -2) {
|
||||
SHAPEWITHSTYLE beginShapes = getShapeAtRatio(0);
|
||||
SHAPEWITHSTYLE endShapes = getShapeAtRatio(65535);
|
||||
SVGMorphShapeExporter shapeExporter = new SVGMorphShapeExporter(swf, beginShapes, endShapes, exporter, null, colorTransform, zoom);
|
||||
shapeExporter.export();
|
||||
} else {
|
||||
SHAPEWITHSTYLE shapes = getShapeAtRatio(ratio);
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(swf, shapes, exporter, null, colorTransform, zoom);
|
||||
shapeExporter.export();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumFrames() {
|
||||
return 65536;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleFrame() {
|
||||
// Morpshape is a single frame specified with the ratio
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getOutline(int frame, int time, int ratio, RenderContext renderContext, Matrix transformation) {
|
||||
return transformation.toTransform().createTransformedShape(getShapeAtRatio(ratio).getOutline());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toHtmlCanvas(double unitDivisor) {
|
||||
CanvasMorphShapeExporter cmse = new CanvasMorphShapeExporter(swf, getShapeAtRatio(0), getShapeAtRatio(MAX_RATIO), new ColorTransform(), unitDivisor, 0, 0);
|
||||
cmse.export();
|
||||
return cmse.getShapeData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterId(int characterId) {
|
||||
this.characterId = characterId;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,9 +21,11 @@ import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
import com.jpexs.decompiler.flash.tags.base.StaticTextTag;
|
||||
import com.jpexs.decompiler.flash.types.MATRIX;
|
||||
import com.jpexs.decompiler.flash.types.RECT;
|
||||
import com.jpexs.decompiler.flash.types.TEXTRECORD;
|
||||
import com.jpexs.helpers.ByteArrayRange;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -49,6 +51,16 @@ public class DefineTextTag extends StaticTextTag {
|
||||
advanceBits = 0;
|
||||
}
|
||||
|
||||
public DefineTextTag(SWF swf, int characterID, RECT textBounds, MATRIX textMatrix, List<TEXTRECORD> textRecords) {
|
||||
super(swf, ID, "DefineText", null);
|
||||
this.characterID = characterID;
|
||||
this.textBounds = textBounds;
|
||||
this.textMatrix = textMatrix;
|
||||
this.textRecords = textRecords;
|
||||
this.glyphBits = 0;
|
||||
this.advanceBits = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
|
||||
@@ -17,13 +17,35 @@
|
||||
package com.jpexs.decompiler.flash.tags.base;
|
||||
|
||||
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.exporters.morphshape.CanvasMorphShapeExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.morphshape.SVGMorphShapeExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.shape.BitmapExporter;
|
||||
import com.jpexs.decompiler.flash.exporters.shape.SVGShapeExporter;
|
||||
import static com.jpexs.decompiler.flash.tags.base.DrawableTag.PARAMETER_RATIO;
|
||||
import com.jpexs.decompiler.flash.types.BasicType;
|
||||
import com.jpexs.decompiler.flash.types.ColorTransform;
|
||||
import com.jpexs.decompiler.flash.types.FILLSTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.LINESTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.MORPHFILLSTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.MORPHLINESTYLEARRAY;
|
||||
import com.jpexs.decompiler.flash.types.RECT;
|
||||
import com.jpexs.decompiler.flash.types.SHAPE;
|
||||
import com.jpexs.decompiler.flash.types.SHAPEWITHSTYLE;
|
||||
import com.jpexs.decompiler.flash.types.annotations.SWFType;
|
||||
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.ByteArrayRange;
|
||||
import com.jpexs.helpers.SerializableImage;
|
||||
import java.awt.Shape;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -31,28 +53,276 @@ import java.util.HashSet;
|
||||
*/
|
||||
public abstract class MorphShapeTag extends CharacterTag implements DrawableTag {
|
||||
|
||||
public static final int MAX_RATIO = 65535;
|
||||
|
||||
@SWFType(BasicType.UI16)
|
||||
public int characterId;
|
||||
|
||||
public RECT startBounds;
|
||||
|
||||
public RECT endBounds;
|
||||
|
||||
public MORPHFILLSTYLEARRAY morphFillStyles;
|
||||
|
||||
public MORPHLINESTYLEARRAY morphLineStyles;
|
||||
|
||||
public SHAPE startEdges;
|
||||
|
||||
public SHAPE endEdges;
|
||||
|
||||
public MorphShapeTag(SWF swf, int id, String name, ByteArrayRange data) {
|
||||
super(swf, id, name, data);
|
||||
}
|
||||
|
||||
public abstract RECT getStartBounds();
|
||||
|
||||
public abstract RECT getEndBounds();
|
||||
|
||||
public abstract MORPHFILLSTYLEARRAY getFillStyles();
|
||||
|
||||
public abstract MORPHLINESTYLEARRAY getLineStyles();
|
||||
|
||||
public abstract SHAPE getStartEdges();
|
||||
|
||||
public abstract SHAPE getEndEdges();
|
||||
|
||||
public abstract int getShapeNum();
|
||||
|
||||
public abstract SHAPEWITHSTYLE getShapeAtRatio(int ratio);
|
||||
|
||||
@Override
|
||||
public RECT getRect() {
|
||||
return getRect(new HashSet<BoundedTag>());
|
||||
return getRect(new HashSet<>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getNeededCharacters(Set<Integer> needed) {
|
||||
morphFillStyles.getNeededCharacters(needed);
|
||||
startEdges.getNeededCharacters(needed);
|
||||
endEdges.getNeededCharacters(needed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean replaceCharacter(int oldCharacterId, int newCharacterId) {
|
||||
boolean modified = false;
|
||||
modified |= morphFillStyles.replaceCharacter(oldCharacterId, newCharacterId);
|
||||
modified |= startEdges.replaceCharacter(oldCharacterId, newCharacterId);
|
||||
modified |= endEdges.replaceCharacter(oldCharacterId, newCharacterId);
|
||||
if (modified) {
|
||||
setModified(true);
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeCharacter(int characterId) {
|
||||
boolean modified = false;
|
||||
modified |= morphFillStyles.removeCharacter(characterId);
|
||||
modified |= startEdges.removeCharacter(characterId);
|
||||
modified |= endEdges.removeCharacter(characterId);
|
||||
if (modified) {
|
||||
setModified(true);
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCharacterId() {
|
||||
return characterId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RECT getRect(Set<BoundedTag> added) {
|
||||
RECT rect = new RECT();
|
||||
rect.Xmin = Math.min(startBounds.Xmin, endBounds.Xmin);
|
||||
rect.Ymin = Math.min(startBounds.Ymin, endBounds.Ymin);
|
||||
rect.Xmax = Math.max(startBounds.Xmax, endBounds.Xmax);
|
||||
rect.Ymax = Math.max(startBounds.Ymax, endBounds.Ymax);
|
||||
return rect;
|
||||
}
|
||||
|
||||
public RECT getStartBounds() {
|
||||
return startBounds;
|
||||
}
|
||||
|
||||
public RECT getEndBounds() {
|
||||
return endBounds;
|
||||
}
|
||||
|
||||
public MORPHFILLSTYLEARRAY getFillStyles() {
|
||||
return morphFillStyles;
|
||||
}
|
||||
|
||||
public MORPHLINESTYLEARRAY getLineStyles() {
|
||||
return morphLineStyles;
|
||||
}
|
||||
|
||||
public SHAPE getStartEdges() {
|
||||
return startEdges;
|
||||
}
|
||||
|
||||
public SHAPE getEndEdges() {
|
||||
return endEdges;
|
||||
}
|
||||
|
||||
public SHAPEWITHSTYLE getShapeAtRatio(int ratio) {
|
||||
List<SHAPERECORD> finalRecords = new ArrayList<>();
|
||||
FILLSTYLEARRAY fillStyles = morphFillStyles.getFillStylesAt(ratio);
|
||||
LINESTYLEARRAY lineStyles = morphLineStyles.getLineStylesAt(getShapeNum(), ratio);
|
||||
|
||||
int startPosX = 0, startPosY = 0;
|
||||
int endPosX = 0, endPosY = 0;
|
||||
int posX = 0, posY = 0;
|
||||
|
||||
for (int startIndex = 0, endIndex = 0;
|
||||
startIndex < startEdges.shapeRecords.size()
|
||||
&& endIndex < endEdges.shapeRecords.size(); startIndex++, endIndex++) {
|
||||
|
||||
SHAPERECORD edge1 = startEdges.shapeRecords.get(startIndex);
|
||||
SHAPERECORD edge2 = endEdges.shapeRecords.get(endIndex);
|
||||
if (edge1 instanceof StyleChangeRecord || edge2 instanceof StyleChangeRecord) {
|
||||
StyleChangeRecord scr1;
|
||||
if (edge1 instanceof StyleChangeRecord) {
|
||||
scr1 = (StyleChangeRecord) edge1;
|
||||
if (scr1.stateMoveTo) {
|
||||
startPosX = scr1.moveDeltaX;
|
||||
startPosY = scr1.moveDeltaY;
|
||||
}
|
||||
} else {
|
||||
scr1 = new StyleChangeRecord();
|
||||
startIndex--;
|
||||
}
|
||||
StyleChangeRecord scr2;
|
||||
if (edge2 instanceof StyleChangeRecord) {
|
||||
scr2 = (StyleChangeRecord) edge2;
|
||||
if (scr2.stateMoveTo) {
|
||||
endPosX = scr2.moveDeltaX;
|
||||
endPosY = scr2.moveDeltaY;
|
||||
}
|
||||
} else {
|
||||
scr2 = new StyleChangeRecord();
|
||||
endIndex--;
|
||||
}
|
||||
StyleChangeRecord scr = scr1.clone();
|
||||
if (scr1.stateMoveTo || scr2.stateMoveTo) {
|
||||
scr.moveDeltaX = startPosX + (endPosX - startPosX) * ratio / MAX_RATIO;
|
||||
scr.moveDeltaY = startPosY + (endPosY - startPosY) * ratio / MAX_RATIO;
|
||||
scr.stateMoveTo = scr.moveDeltaX != posX || scr.moveDeltaY != posY;
|
||||
}
|
||||
finalRecords.add(scr);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (edge1 instanceof EndShapeRecord) {
|
||||
finalRecords.add(edge1);
|
||||
break;
|
||||
}
|
||||
if (edge2 instanceof EndShapeRecord) {
|
||||
finalRecords.add(edge2);
|
||||
break;
|
||||
}
|
||||
|
||||
if (edge1 instanceof CurvedEdgeRecord || edge2 instanceof CurvedEdgeRecord) {
|
||||
CurvedEdgeRecord cer1 = null;
|
||||
if (edge1 instanceof CurvedEdgeRecord) {
|
||||
cer1 = (CurvedEdgeRecord) edge1;
|
||||
} else if (edge1 instanceof StraightEdgeRecord) {
|
||||
cer1 = SHAPERECORD.straightToCurve((StraightEdgeRecord) edge1);
|
||||
}
|
||||
CurvedEdgeRecord cer2 = null;
|
||||
if (edge2 instanceof CurvedEdgeRecord) {
|
||||
cer2 = (CurvedEdgeRecord) edge2;
|
||||
} else if (edge2 instanceof StraightEdgeRecord) {
|
||||
cer2 = SHAPERECORD.straightToCurve((StraightEdgeRecord) edge2);
|
||||
}
|
||||
if ((cer2 == null) || (cer1 == null)) {
|
||||
continue;
|
||||
}
|
||||
CurvedEdgeRecord cer = new CurvedEdgeRecord();
|
||||
cer.controlDeltaX = cer1.controlDeltaX + (cer2.controlDeltaX - cer1.controlDeltaX) * ratio / MAX_RATIO;
|
||||
cer.controlDeltaY = cer1.controlDeltaY + (cer2.controlDeltaY - cer1.controlDeltaY) * ratio / MAX_RATIO;
|
||||
cer.anchorDeltaX = cer1.anchorDeltaX + (cer2.anchorDeltaX - cer1.anchorDeltaX) * ratio / MAX_RATIO;
|
||||
cer.anchorDeltaY = cer1.anchorDeltaY + (cer2.anchorDeltaY - cer1.anchorDeltaY) * ratio / MAX_RATIO;
|
||||
startPosX += cer1.controlDeltaX + cer1.anchorDeltaX;
|
||||
startPosY += cer1.controlDeltaY + cer1.anchorDeltaY;
|
||||
endPosX += cer2.controlDeltaX + cer2.anchorDeltaX;
|
||||
endPosY += cer2.controlDeltaY + cer2.anchorDeltaY;
|
||||
posX += cer.controlDeltaX + cer.anchorDeltaX;
|
||||
posY += cer.controlDeltaY + cer.anchorDeltaY;
|
||||
finalRecords.add(cer);
|
||||
} else {
|
||||
StraightEdgeRecord ser1 = null;
|
||||
if (edge1 instanceof StraightEdgeRecord) {
|
||||
ser1 = (StraightEdgeRecord) edge1;
|
||||
}
|
||||
StraightEdgeRecord ser2 = null;
|
||||
if (edge2 instanceof StraightEdgeRecord) {
|
||||
ser2 = (StraightEdgeRecord) edge2;
|
||||
}
|
||||
if ((ser2 == null) || (ser1 == null)) {
|
||||
continue;
|
||||
}
|
||||
StraightEdgeRecord ser = new StraightEdgeRecord();
|
||||
ser.generalLineFlag = true;
|
||||
ser.vertLineFlag = false;
|
||||
ser.deltaX = ser1.deltaX + (ser2.deltaX - ser1.deltaX) * ratio / MAX_RATIO;
|
||||
ser.deltaY = ser1.deltaY + (ser2.deltaY - ser1.deltaY) * ratio / MAX_RATIO;
|
||||
startPosX += ser1.deltaX;
|
||||
startPosY += ser1.deltaY;
|
||||
endPosX += ser2.deltaX;
|
||||
endPosY += ser2.deltaY;
|
||||
posX += ser.deltaX;
|
||||
posY += ser.deltaX;
|
||||
finalRecords.add(ser);
|
||||
}
|
||||
}
|
||||
SHAPEWITHSTYLE shape = new SHAPEWITHSTYLE();
|
||||
shape.fillStyles = fillStyles;
|
||||
shape.lineStyles = lineStyles;
|
||||
shape.shapeRecords = finalRecords;
|
||||
return shape;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUsedParameters() {
|
||||
return PARAMETER_RATIO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toImage(int frame, int time, int ratio, RenderContext renderContext, SerializableImage image, Matrix transformation, ColorTransform colorTransform) {
|
||||
SHAPEWITHSTYLE shape = getShapeAtRatio(ratio);
|
||||
// morphShape using shapeNum=3, morphShape2 using shapeNum=4
|
||||
// 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(swf, shape, null, image, transformation, colorTransform);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toSVG(SVGExporter exporter, int ratio, ColorTransform colorTransform, int level, double zoom) {
|
||||
if (ratio == -2) {
|
||||
SHAPEWITHSTYLE beginShapes = getShapeAtRatio(0);
|
||||
SHAPEWITHSTYLE endShapes = getShapeAtRatio(65535);
|
||||
SVGMorphShapeExporter shapeExporter = new SVGMorphShapeExporter(swf, beginShapes, endShapes, exporter, null, colorTransform, zoom);
|
||||
shapeExporter.export();
|
||||
} else {
|
||||
SHAPEWITHSTYLE shapes = getShapeAtRatio(ratio);
|
||||
SVGShapeExporter shapeExporter = new SVGShapeExporter(swf, shapes, exporter, null, colorTransform, zoom);
|
||||
shapeExporter.export();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumFrames() {
|
||||
return 65536;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSingleFrame() {
|
||||
// Morpshape is a single frame specified with the ratio
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Shape getOutline(int frame, int time, int ratio, RenderContext renderContext, Matrix transformation) {
|
||||
return transformation.toTransform().createTransformedShape(getShapeAtRatio(ratio).getOutline());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toHtmlCanvas(double unitDivisor) {
|
||||
CanvasMorphShapeExporter cmse = new CanvasMorphShapeExporter(swf, getShapeAtRatio(0), getShapeAtRatio(MAX_RATIO), new ColorTransform(), unitDivisor, 0, 0);
|
||||
cmse.export();
|
||||
return cmse.getShapeData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCharacterId(int characterId) {
|
||||
this.characterId = characterId;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user