📄 actionblockwriter.java
字号:
/****************************************************************
* Copyright (c) 2003, David N. Main, All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the
* following conditions are met:
*
* 1. Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. The name of the author may not be used to endorse or
* promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
****************************************************************/
package com.anotherbigidea.flash.writers;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.anotherbigidea.flash.SWFActionCodes;
import com.anotherbigidea.flash.SWFConstants;
import com.anotherbigidea.flash.interfaces.SWFActionBlock;
import com.anotherbigidea.flash.interfaces.SWFActions;
import com.anotherbigidea.io.OutStream;
/**
* Implementation of SWFActionBlock that builds a byte array of the actions
* it is passed.
*
* @author nmain
*/
public class ActionBlockWriter implements SWFActionBlock, SWFActionCodes {
/** Base for different types of fix-ups. */
interface Fixer {
public void fix( byte[] actionData );
}
private class OffsetFixer implements Fixer {
private int mBaseOffset;
private int mOffsetAddr;
private String mTargetLabel;
OffsetFixer( int baseOffset, int offsetAddr, String targetLabel ) {
mBaseOffset = baseOffset;
mOffsetAddr = offsetAddr;
mTargetLabel = targetLabel;
}
public void fix( byte[] actionData ) {
LabelInfo info = (LabelInfo) mLabelToInfo.get( mTargetLabel );
int offset = info.offset - mBaseOffset;
actionData[ mOffsetAddr ] = (byte)(offset & 0xff);
actionData[ mOffsetAddr+1 ] = (byte)((offset >> 8) & 0xff);
}
}
private class SkipActionFixer implements Fixer {
private int mSkipCountAddr;
private int mBaseActionCount;
private String mTargetLabel;
SkipActionFixer( int baseActionCount, int skipCountAddr, String targetLabel ) {
mBaseActionCount = baseActionCount;
mSkipCountAddr = skipCountAddr;
mTargetLabel = targetLabel;
}
public void fix( byte[] actionData ) {
LabelInfo info = (LabelInfo) mLabelToInfo.get( mTargetLabel );
int actionsToSkip = info.actionNumber - mBaseActionCount;
actionData[ mSkipCountAddr ] = (byte) actionsToSkip;
}
}
private class BlockLengthFixer implements Fixer {
private int mBlockLengthAddr;
private int mBlockLength;
BlockLengthFixer( int blockLengthAddr ) {
mBlockLengthAddr = blockLengthAddr;
}
public void setBlockLength( int length ) {
mBlockLength = length;
}
public void fix( byte[] actionData ) {
actionData[ mBlockLengthAddr ] = (byte)(mBlockLength & 0xff);
actionData[ mBlockLengthAddr+1 ] = (byte)((mBlockLength >> 8) & 0xff);
}
}
private class TryFlagsFixer implements Fixer {
private int mFlagsAddr;
private int mFlags = 0;
TryFlagsFixer( int flagsAddr ) {
mFlagsAddr = flagsAddr;
}
public void hasCatchBlock() { mFlags |= SWFActionCodes.TRY_HAS_CATCH; }
public void hasFinallyBlock() { mFlags |= SWFActionCodes.TRY_HAS_FINALLY; }
public void catchInRegister() { mFlags |= SWFActionCodes.TRY_CATCH_IN_REGISTER; }
public void fix( byte[] actionData ) {
actionData[ mFlagsAddr ] = (byte)(mFlags & 0xff);
}
}
/** Info about a label. */
private static class LabelInfo {
public final String label;
public final int offset;
public final int actionNumber;
public LabelInfo( String label, int offset, int actionNumber ) {
this.label = label;
this.offset = offset;
this.actionNumber = actionNumber;
}
}
interface PushValue { public abstract void write( OutStream out ) throws IOException; }
class PushUndefined implements PushValue { public void write( OutStream out ) throws IOException { out.writeUI8( PUSHTYPE_UNDEFINED ); } }
class PushStringVal implements PushValue { public void write( OutStream out ) throws IOException { out.writeUI8( PUSHTYPE_STRING ); out.writeString( value, mStringEncoding ); } private String value; PushStringVal( String v ) { value = v; } }
class PushBooleanVal implements PushValue { public void write( OutStream out ) throws IOException { out.writeUI8( PUSHTYPE_BOOLEAN ); out.writeUI8( value ? 1 : 0 ); } private boolean value; PushBooleanVal( boolean v ) { value = v; } }
class PushIntegerVal implements PushValue { public void write( OutStream out ) throws IOException { out.writeUI8( PUSHTYPE_INTEGER ); out.writeSI32( value ); } private int value; PushIntegerVal( int v ) { value = v; } }
class PushLookup implements PushValue { public void write( OutStream out ) throws IOException { if( idx <=255 ) { out.writeUI8( PUSHTYPE_LOOKUP8 ); out.writeUI8( idx ); } else { out.writeUI8( PUSHTYPE_LOOKUP16 ); out.writeUI16( idx ); } } private int idx; PushLookup( int v ) { idx = v; } }
class PushRegister implements PushValue { public void write( OutStream out ) throws IOException { out.writeUI8( PUSHTYPE_REGISTER ); out.writeUI8( value ); } private int value; PushRegister( int v ) { value = v; } }
class PushFloatVal implements PushValue { public void write( OutStream out ) throws IOException { out.writeUI8( PUSHTYPE_FLOAT ); out.writeFloat( value ); } private float value; PushFloatVal( float v ) { value = v; } }
class PushDoubleVal implements PushValue { public void write( OutStream out ) throws IOException { out.writeUI8( PUSHTYPE_DOUBLE ); out.writeDouble( value ); } private double value; PushDoubleVal( double v ) { value = v; } }
class PushNull implements PushValue { public void write( OutStream out ) throws IOException { out.writeUI8( PUSHTYPE_NULL ); } }
protected static class SubBlockWriter extends ActionBlockWriter {
private BlockLengthFixer mLengthFixer;
private int mInitOffset;
SubBlockWriter( BlockLengthFixer fixer,
OutStream out,
ByteArrayOutputStream byteOut,
List fixers,
Map labelToInfo,
int[] actionCount,
int flashVersion ) {
super( out, byteOut, fixers, labelToInfo, actionCount, flashVersion );
mLengthFixer = fixer;
mInitOffset = out.getCount();
}
public void end() throws IOException {
int length = mOut.getCount() - mInitOffset;
mLengthFixer.setBlockLength( length );
}
}
protected OutStream mOut;
protected ByteArrayOutputStream mByteOut;
protected List mFixers;
protected Map mLabelToInfo;
protected int[] mActionCount;
protected List mPushValues = new ArrayList();
protected int mFlashVersion;
protected String mStringEncoding;
public ActionBlockWriter( int flashVersion ) {
mByteOut = new ByteArrayOutputStream();
mOut = new OutStream( mByteOut );
mFixers = new ArrayList();
mLabelToInfo = new HashMap();
mActionCount = new int[] {0};
setFlashVersion( flashVersion );
}
protected ActionBlockWriter( OutStream out,
ByteArrayOutputStream byteOut,
List fixers,
Map labelToInfo,
int[] actionCount,
int flashVersion ) {
mByteOut = byteOut;
mOut = out;
mFixers = fixers;
mLabelToInfo = labelToInfo;
mActionCount = actionCount;
setFlashVersion( flashVersion );
}
private void setFlashVersion( int flashVersion ) {
mFlashVersion = flashVersion;
mStringEncoding = ( flashVersion >= SWFConstants.FLASH_MX_VERSION ) ?
SWFConstants.STRING_ENCODING_MX :
SWFConstants.STRING_ENCODING_PRE_MX;
}
/** Close out the action data, fix up all labels and blocks and return the data. */
public byte[] getActionData() throws IOException {
mOut.flush();
mOut.close();
byte[] data = mByteOut.toByteArray();
for (Iterator i = mFixers.iterator(); i.hasNext();) {
Fixer fixer = (Fixer) i.next();
fixer.fix( data );
}
return data;
}
protected void writeCode( int code ) throws IOException {
if( mPushValues.size() > 0 && code != PUSH ) flushPushValues();
mOut.writeUI8( code );
mActionCount[0]++;
}
public void end() throws IOException {
writeCode( 0 );
}
/**
* Pass through a blob of actions
*/
public void blob( byte[] blob ) throws IOException
{
mOut.write( blob );
}
public void comment( String comment ) throws IOException
{
//ignore comments
}
public void unknown( int code, byte[] data ) throws IOException
{
writeCode( code );
int length = (data != null) ? data.length : 0;
if( code >= 0x80 || length > 0 )
{
mOut.writeUI16( length );
}
if( length > 0 ) mOut.write( data );
}
public void initArray() throws IOException
{
writeCode( INIT_ARRAY );
}
public void jumpLabel( String label ) throws IOException {
if( mPushValues.size() > 0 ) flushPushValues();
int offset = (int) mOut.getCount();
LabelInfo info = new LabelInfo( label, offset, mActionCount[0] );
mLabelToInfo.put( label, info );
}
public void gotoFrame( int frameNumber ) throws IOException
{
writeCode( GOTO_FRAME );
mOut.writeUI16( 2 );
mOut.writeUI16( frameNumber );
}
public void gotoFrame( String label ) throws IOException
{
writeCode( GOTO_LABEL );
mOut.writeUI16 ( OutStream.getStringLength( label ) );
mOut.writeString( label, mStringEncoding );
}
public void getURL( String url, String target ) throws IOException
{
writeCode( GET_URL );
mOut.writeUI16 ( OutStream.getStringLength(url) + OutStream.getStringLength(target) );
mOut.writeString( url, mStringEncoding );
mOut.writeString( target, mStringEncoding );
}
public void nextFrame() throws IOException
{
writeCode( NEXT_FRAME );
}
public void prevFrame() throws IOException
{
writeCode( PREVIOUS_FRAME );
}
public void play() throws IOException
{
writeCode( PLAY );
}
public void stop() throws IOException
{
writeCode( STOP );
}
public void toggleQuality() throws IOException
{
writeCode( TOGGLE_QUALITY );
}
public void stopSounds() throws IOException
{
writeCode( STOP_SOUNDS );
}
public void setTarget( String target ) throws IOException
{
writeCode( SET_TARGET );
mOut.writeUI16 ( OutStream.getStringLength( target ) );
mOut.writeString( target, mStringEncoding );
}
protected void writeJump( String label, int code ) throws IOException {
writeCode( code );
mOut.writeUI16( 2 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -