actionparser.java

来自「java和flash混合编程」· Java 代码 · 共 424 行 · 第 1/2 页

JAVA
424
字号
/****************************************************************
 * Copyright (c) 2001, 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.readers;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

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.InStream;

/**
 * Parse action bytes and drive a SWFActions interface
 */
public class ActionParser implements SWFActionCodes 
{
    protected SWFActionBlock mBlock;
    protected int            mFlashVersion;
    protected int            mStartOffset;
    
    public ActionParser( SWFActionBlock actions, int flashVersion )
    {
        mBlock = actions;
        mFlashVersion = flashVersion;
    }
    
    public synchronized void parse( byte[] bytes ) throws IOException
    {
        parse( new InStream(bytes) );
    }
    
    public synchronized void parse( InStream in ) throws IOException
    {
        mStartOffset = (int) in.getBytesRead();
        BlockParser parser = new BlockParser( mBlock, -1, in, mFlashVersion );
        parser.parse();
    }
        
    private static class WaitForFrameTarget {
        public int    actionsToSkip;
        public String targetLabel;
        public WaitForFrameTarget( int skip, String label ) {
            actionsToSkip = skip;
            targetLabel   = label;
        }
    }
    
    private class BlockParser implements SWFActionCodes {
        
        private SWFActionBlock mBlock;
        private int            mBlockSize;
        private InStream       mIn;
        private int            mInitBytesRead;
        private int            mFlashVersion;
        protected String mStringEncoding = SWFConstants.STRING_ENCODING_MX;
        private int            mWaitForFrameIndex = 0;
        private List           mWaitForFrameTargets;
              
        /** @return the target label for the Wait-for-frame action. */
        private String newWaitForFrameTarget( int actionsToSkip ) {
            if( mWaitForFrameTargets == null ) mWaitForFrameTargets = new ArrayList();
            WaitForFrameTarget target = new WaitForFrameTarget( actionsToSkip, "w" + (mWaitForFrameIndex++) );
            mWaitForFrameTargets.add( target );
            return target.targetLabel;
        }
        
        BlockParser( SWFActionBlock block, int blockSize, InStream in, int flashVersion ) {
            mBlock     = block;
            mBlockSize = blockSize;
            mIn        = in;
            mInitBytesRead = (int) in.getBytesRead();
            mFlashVersion = flashVersion;
            
            if( flashVersion < SWFConstants.FLASH_MX_VERSION ) {
                mStringEncoding = SWFConstants.STRING_ENCODING_PRE_MX;
            }
        }
        
        private String makeLabel( int offset ) {
        	String label = Integer.toString( offset + mInitBytesRead - mStartOffset );
        	if( label.length() < 4 ) label = "0000".substring(0,4-label.length()) + label;
        	return label;
        }
        
        private void applyWaitForFrameTargets() throws IOException {
            if( mWaitForFrameTargets == null || mWaitForFrameTargets.isEmpty() ) return;
            
            for (Iterator i = mWaitForFrameTargets.iterator(); i.hasNext();) {
                WaitForFrameTarget target = (WaitForFrameTarget) i.next();
                
                if( target.actionsToSkip == 0 ) {
                    mBlock.jumpLabel( target.targetLabel );
                    i.remove();
                    continue;
                }
            
                target.actionsToSkip--;
            }
        }
        
        void parse() throws IOException {
            int offset = 0;
            boolean foundEndAction = false;
            
            end: while( ( offset = ((int) mIn.getBytesRead()) - mInitBytesRead ) < mBlockSize 
            		  || mBlockSize < 0 //denotes termination by end rather than size
					  ) {
                int code = mIn.readUI8();                
                int dataLength = (code >= 0x80) ? mIn.readUI16() : 0;                
                
                applyWaitForFrameTargets();
                mBlock.jumpLabel( makeLabel(offset) );
                                
                switch( code )
                {
	                case 0: mBlock.end(); foundEndAction = true; break end;
	                
	                //--Flash 3
	                case GOTO_FRAME    : mBlock.gotoFrame( mIn.readUI16() ); break;
	                case GET_URL       : mBlock.getURL( mIn.readString(mStringEncoding), mIn.readString(mStringEncoding) ); break;
	                case NEXT_FRAME    : mBlock.nextFrame(); break;
	                case PREVIOUS_FRAME: mBlock.prevFrame(); break;
	                case PLAY          : mBlock.play(); break;
	                case STOP          : mBlock.stop(); break;
	                case TOGGLE_QUALITY: mBlock.toggleQuality(); break;
	                case STOP_SOUNDS   : mBlock.stopSounds(); break;
	                case WAIT_FOR_FRAME: mBlock.waitForFrame( mIn.readUI16(), newWaitForFrameTarget( mIn.readUI8() ) ); break; 
	                case SET_TARGET    : mBlock.setTarget( mIn.readString(mStringEncoding) ); break;
	                case GOTO_LABEL    : mBlock.gotoFrame( mIn.readString(mStringEncoding) ); break;
	                
	                //--Flash 4
	                case IF              : mBlock.ifJump( makeLabel( offset + 5 + mIn.readSI16() ) ); break;
	                case JUMP            : mBlock.jump( makeLabel( offset + 5 + mIn.readSI16() ) ); break;
	                case WAIT_FOR_FRAME_2: mBlock.waitForFrame( newWaitForFrameTarget( mIn.readUI8() )); break;
	                case POP             : mBlock.pop(); break;
	                case PUSH            : parsePush( dataLength, mIn ); break;
	                case ADD             : mBlock.add(); break;
	                case SUBTRACT        : mBlock.substract(); break;
	                case MULTIPLY        : mBlock.multiply(); break;
	                case DIVIDE          : mBlock.divide(); break;
	                
	                case EQUALS          : mBlock.equals(); break;
	                case LESS            : mBlock.lessThan(); break;
	                case AND             : mBlock.and(); break;
	                case OR              : mBlock.or(); break;
	                case NOT             : mBlock.not(); break;
	                
	                case STRING_EQUALS     : mBlock.stringEquals(); break;
	                case STRING_LENGTH     : mBlock.stringLength(); break;
	                case STRING_ADD        : mBlock.concat(); break;
	                case STRING_EXTRACT    : mBlock.substring(); break;
	                case STRING_LESS       : mBlock.stringLessThan(); break;                                                        
	                case MB_STRING_EXTRACT : mBlock.substringMB(); break;
	                case MB_STRING_LENGTH  : mBlock.stringLengthMB(); break;
	
	                case TO_INTEGER       : mBlock.toInteger(); break;
	                case CHAR_TO_ASCII    : mBlock.charToAscii(); break;
	                case ASCII_TO_CHAR    : mBlock.asciiToChar(); break;
	                case MB_CHAR_TO_ASCII : mBlock.charMBToAscii(); break;
	                case MB_ASCII_TO_CHAR : mBlock.asciiToCharMB(); break;
	                
	                case CALL             : mBlock.call(); break;
	                case GET_VARIABLE     : mBlock.getVariable(); break;
	                case SET_VARIABLE     : mBlock.setVariable(); break;
	                
	                case GET_URL_2        : parseGetURL2( mIn.readUI8() ); break;
	                
	                case GOTO_FRAME_2  : mBlock.gotoFrame( mIn.readUI8() != 0 ); break;
	                case SET_TARGET_2  : mBlock.setTarget(); break;
	                case GET_PROPERTY  : mBlock.getProperty(); break;
	                case SET_PROPERTY  : mBlock.setProperty(); break;
	                case CLONE_SPRITE  : mBlock.cloneSprite(); break;
	                case REMOVE_SPRITE : mBlock.removeSprite(); break;
	                case START_DRAG    : mBlock.startDrag(); break;
	                case END_DRAG      : mBlock.endDrag(); break;
	                case TRACE         : mBlock.trace(); break;
	                case GET_TIME      : mBlock.getTime(); break;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?