📄 swfmerger.java
字号:
package org.javaswf.tools.merger;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Properties;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import com.anotherbigidea.flash.SWFConstants;
import com.anotherbigidea.flash.interfaces.SWFActionBlock;
import com.anotherbigidea.flash.interfaces.SWFActions;
import com.anotherbigidea.flash.interfaces.SWFShape;
import com.anotherbigidea.flash.interfaces.SWFTagTypes;
import com.anotherbigidea.flash.interfaces.SWFTags;
import com.anotherbigidea.flash.movie.ImageUtil;
import com.anotherbigidea.flash.readers.SWFReader;
import com.anotherbigidea.flash.readers.TagParser;
import com.anotherbigidea.flash.structs.Color;
import com.anotherbigidea.flash.structs.Matrix;
import com.anotherbigidea.flash.structs.Rect;
import com.anotherbigidea.flash.writers.SWFTagTypesImpl;
import com.anotherbigidea.flash.writers.SWFWriter;
import com.anotherbigidea.flash.writers.TagWriter;
/**
* A utility for merging assets from several SWF files into a single SWF.
*
* @author nmain
*/
public class SWFMerger {
private SWFTagTypes swf;
private int nextSymbolId = 1;
private int nextDepth = 1;
/**
* A Merger for writing to a SWF file.
* Assumes that the header has already been written and that no symbols
* have been defined (that it is OK to start assigning symbol ids from 1).
*
* The merger does not write an end tag - that is an external concern.
* It is possible to process more than one merge specification file - each
* one will add successive frames to the SWF.
*
* @param writer the swf file to write to.
*/
public SWFMerger( SWFWriter writer ) {
swf = new TagWriter( writer );
}
/**
* Parse and process a merge specification.
*
* @param xmlFile the spec file
*/
public void processMergeSpec( File xmlFile ) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse( xmlFile );
processMergeSpec( doc );
}
/**
* Process a merge specification.
*
* <merge>
<frame label="frame1">
<import name="" file="" depth="" />
<actions file="" frame="" />
</frame>
<frames count="23" />
</merge>
*
* @param doc the XML DOM of the specification.
*/
public void processMergeSpec( Document doc ) throws Exception {
Element root = doc.getDocumentElement();
NodeList children = root.getChildNodes();
for( int i = 0; i < children.getLength(); i++ ) {
Node node = children.item( i );
if( !(node instanceof Element)) continue;
Element child = (Element) node;
String tag = child.getTagName();
if( tag.equals( "frames" )) {
int count = getIntAttr( child, "count" );
while( count-- > 0 ) swf.tagShowFrame();
continue;
}
if( tag.equals( "frame" ) ) {
String name = child.getAttribute( "name" );
Properties vars = new Properties();
//--handle actions and imports
NodeList imports = child.getChildNodes();
for (int j = 0; j < imports.getLength(); j++) {
node = imports.item(j);
if( !(node instanceof Element)) continue;
Element elem = (Element) node;
tag = elem.getTagName();
if ( tag.equals( "actions" ) ) importActions( elem, vars );
else if( tag.equals( "import" ) ) importAsset ( elem );
else if( tag.equals( "variable" ) ) {
vars.setProperty( getAttr( elem, "name" ), getAttr( elem, "value" ));
}
}
//--set variable values
if( vars.size() > 0 ) setVars( vars );
//--end the frame
if( name.length() > 0 ) swf.tagFrameLabel( name );
swf.tagShowFrame();
continue;
}
}
}
/** Set a bunch of actionscript vars */
private void setVars( Properties vars ) throws IOException {
SWFActions actions = swf.tagDoAction();
SWFActionBlock acts = actions.start(0);
for(Enumeration e = vars.keys(); e.hasMoreElements();) {
String varName = (String) e.nextElement();
String value = vars.getProperty( varName );
acts.push( varName );
acts.push( value );
acts.setVariable();
}
acts.end();
actions.done();
}
/** Import actions into a frame */
private void importActions( Element elem, Properties vars ) throws Exception {
if( vars.size() > 0 ) setVars( vars );
vars.clear();
String filename = getAttr( elem, "file" );
String frame = getAttr( elem, "frame" );
ActionExtractor extractor = new ActionExtractor( frame );
byte[] actions = extractor.getActions( filename );
if( actions == null ) throw new Exception( "Failed to find actions in "
+ filename + " in frame " + frame );
swf.tag( SWFConstants.TAG_DOACTION, true, actions );
}
/** Import an asset or a jpeg */
private void importAsset( Element elem ) throws Exception {
String filename = getAttr( elem, "file" );
String name = getAttr( elem, "name" );
String alias = elem.getAttribute( "alias" );
int depth = getIntAttr( elem, "depth", nextDepth );
if( depth >= nextDepth ) nextDepth = depth + 1;
if( filename.toLowerCase().endsWith( ".jpg" )
|| filename.toLowerCase().endsWith( ".jpeg" )) {
importImage( filename, name, depth );
return;
}
}
/** Import a jpeg as a sprite instance. */
private void importImage( String filename, String instanceName, int depth )
throws IOException {
FileInputStream in = new FileInputStream( filename );
int[] size = new int[2];
byte[] imgData = ImageUtil.normalizeJPEG( in, size );
in.close();
int width = size[0] * SWFConstants.TWIPS;
int height = size[1] * SWFConstants.TWIPS;
int imageId = nextSymbolId++;
int shapeId = nextSymbolId++;
int spriteId = nextSymbolId++;
Rect outline = new Rect( 0, 0, width, height );
//make image symbol
swf.tagDefineBitsJPEG2( imageId, imgData );
//make shape with image fill
SWFShape s = swf.tagDefineShape2( shapeId, outline );
Matrix matrix = new Matrix( SWFConstants.TWIPS,
SWFConstants.TWIPS,
0.0, 0.0, 0.0, 0.0 );
s.defineFillStyle( imageId, matrix, true );
s.setFillStyle1(1); //use image fill
s.setLineStyle(0);
s.line(width,0);
s.line(0,height);
s.line(-width,0);
s.line(0,-height);
s.done();
//define sprite
SWFTagTypes sprite = swf.tagDefineSprite( spriteId );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -