Package flash.swf.tools

Source Code of flash.swf.tools.SwfxParser

/*
*
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You under the Apache License, Version 2.0
*  (the "License"); you may not use this file except in compliance with
*  the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*
*/

package flash.swf.tools;

import flash.util.Base64;
import flash.util.SwfImageUtils;
import flash.swf.Dictionary;
import flash.swf.Header;
import flash.swf.TagEncoder;
import flash.swf.TagHandler;
import flash.swf.TagValues;
import flash.swf.tags.DebugID;
import flash.swf.tags.DefineBits;
import flash.swf.tags.DefineShape;
import flash.swf.tags.DefineSprite;
import flash.swf.tags.DefineTag;
import flash.swf.tags.DoAction;
import flash.swf.tags.DoInitAction;
import flash.swf.tags.EnableDebugger;
import flash.swf.tags.ExportAssets;
import flash.swf.tags.FrameLabel;
import flash.swf.tags.GenericTag;
import flash.swf.tags.ImportAssets;
import flash.swf.tags.PlaceObject;
import flash.swf.tags.ProductInfo;
import flash.swf.tags.ScriptLimits;
import flash.swf.tags.SetBackgroundColor;
import flash.swf.tags.ShowFrame;
import flash.swf.tags.FileAttributes;
import flash.swf.tags.EnableTelemetry;
import flash.swf.types.CXForm;
import flash.swf.types.CurvedEdgeRecord;
import flash.swf.types.FillStyle;
import flash.swf.types.FlashUUID;
import flash.swf.types.GradRecord;
import flash.swf.types.ImportRecord;
import flash.swf.types.LineStyle;
import flash.swf.types.Matrix;
import flash.swf.types.Rect;
import flash.swf.types.ShapeWithStyle;
import flash.swf.types.StraightEdgeRecord;
import flash.swf.types.StyleChangeRecord;
import flash.swf.types.Gradient;
import flash.util.FileUtils;
import flash.util.StringUtils;
import flash.util.Trace;

import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Stack;

/**
* This class supports reading in the SWFX format and turning it back
* into a SWF.  SWFX format can be created by hand or it also can be
* generated by the swfdump utility.
*
* @author Edwin Smith
* @see SwfxPrinter#main
*/
public class SwfxParser extends DefaultHandler
        implements TagValues
{
    private TagHandler tagHandler;
    private DefineSprite sprite;
    private Locator locator;
    private StringBuilder text;
    private Header header;
    private Stack stack;
    private ArrayList fillstyles;
    private ArrayList linestyles;
    private String docPath;
    private Dictionary dict;
    private String[] aspath;
    private String topLevel;
    private GenericTag jpegTables;
    private int startLineNumber;

    private TagHandler currentHandler()
    {
        return sprite != null ? sprite.tagList : tagHandler;
    }

    public SwfxParser(TagHandler handler, String[] aspath)
    {
        this.tagHandler = handler;
        this.aspath = aspath;
        try
        {
            this.topLevel = FileUtils.readFile(aspath[0] + File.separator + "toplevel.as", null);
        }
        catch (IOException ex)
        {
            this.topLevel = null;
        }

        stack = new Stack();
        dict = new Dictionary();
    }

    public void startElement(String uri, String localName,
                             String qName, Attributes attributes)
            throws SAXException
    {
        try
        {
            Method method = getClass().getMethod(qName, new Class[]{Attributes.class});
            method.invoke(this, new Object[]{attributes});
        }
        catch (NoSuchMethodException e)
        {
            warning(new SAXParseException("no start handler for " + qName, locator));
        }
        catch (IllegalAccessException e)
        {
            fatalError(new SAXParseException(e.getMessage(), locator, e));
        }
        catch (InvocationTargetException e)
        {
            Throwable t = e.getTargetException();
            if (t instanceof SAXException)
            {
                throw (SAXException)t;
            }
            else
            {
                fatalError(new SAXParseException(e.getMessage(), locator, e));
            }
        }
    }

    public void characters(char ch[], int start, int length)
            throws SAXException
    {
        if (text != null)
            text.append(ch, start, length);
    }

    public void curve(Attributes attributes) throws SAXParseException
    {
        CurvedEdgeRecord curvedEdge = new CurvedEdgeRecord();

        curvedEdge.controlDeltaX = parseInt(getAttribute(attributes, "cdx"));
        curvedEdge.controlDeltaY = parseInt(getAttribute(attributes, "cdy"));
        curvedEdge.anchorDeltaX = parseInt(getAttribute(attributes, "dx"));
        curvedEdge.anchorDeltaY = parseInt(getAttribute(attributes, "dy"));

        DefineShape defineShape = (DefineShape)stack.peek();
        defineShape.shapeWithStyle.shapeRecords.add(curvedEdge);
    }

    public void curve()
    {}

    public void DebugID(Attributes attributes) throws SAXParseException
    {
        DebugID debugId = new DebugID(parseUUID(getAttribute(attributes, "uuid")));
        tagHandler.debugID(debugId);
    }

    public void DebugID()
    {
    }

    private FlashUUID parseUUID(String s)
    {
        byte[] b = new byte[s.length() / 2];
        for (int i = 0; i < b.length; i++)
        {
            b[i] = (byte)((Character.digit(s.charAt(2 * i), 16) << 4) |
                    (Character.digit(s.charAt(2 * i + 1), 16) << 0));
        }
        return new FlashUUID(b);
    }

    /**
     * Add an id to the dictionary of characters, tracking what the player
     * would do anyway.  The player will ignore the new definition if another
     * one with the same ID already exists.
     *
     * @param id
     * @param tag
     * @throws SAXParseException
     */
    private void createCharacter(int id, DefineTag tag) throws SAXParseException
    {
        try
        {
            dict.add(id, tag);
        }
        catch (IllegalArgumentException e)
        {
            // player will ignore dups, so print a warning
            error(new SAXParseException(e.getMessage(), locator, e));
        }
    }

    private SwfImageUtils.JPEG loadJPEG(Attributes attributes) throws SAXException
    {
        if (hasAttribute(attributes, "encoding"))
        {
            if (!getAttribute(attributes, "encoding").equals("base64"))
                fatalError(new SAXParseException("unknown encoding "
                        + getAttribute(attributes, "encoding"),
                        locator));
            if (hasAttribute(attributes, "src"))
                fatalError(new SAXParseException("can only specify one of src or encoding attributes", locator));

            text = new StringBuilder();
        }
        else
        {
            text = null;
            if (!hasAttribute(attributes, "src"))
                fatalError(new SAXParseException("must provide either src or encoding attribute", locator));
            try
            {
                File src = new File(getAttribute(attributes, "src"));
                FileInputStream input = new FileInputStream(getAttribute(attributes, "src"));
                byte[] image = new byte[(int)src.length()];
                input.read(image);
                input.close();
                SwfImageUtils.JPEG jpeg = new SwfImageUtils.JPEG(image, true);
                if (!jpeg.validate())
                    fatalError(new SAXParseException("Invalid JPEG data in " + src.getName(), locator));
                return jpeg;
            }
            catch (IOException e)
            {
                throw new SAXParseException(e.getMessage(), locator);
            }
        }
        return null;
    }

    public void DefineBits(Attributes attributes) throws SAXException
    {
        if (jpegTables == null)
            fatalError(new SAXParseException("DefineBits must follow JPEGTables", locator));

        DefineBits db = new DefineBits(stagDefineBits);
        int id = parseInt(getAttribute(attributes, "id"));
        createCharacter(id, db);

        SwfImageUtils.JPEG jpeg = loadJPEG(attributes);

        if (jpeg != null)
        {
            if (!Arrays.equals(jpeg.table, jpegTables.data))
            {
                fatalError(new SAXParseException("JPEGTables data does not match, use DefineBitsJPEG2", locator));
            }
            db.data = jpeg.data;
        }
        stack.push(db);
    }

    public void DefineBits()
    {
        DefineBits db = (DefineBits)stack.pop();
        if (text != null)
        {
            // text is allocated for the base64 encoding

            Base64.Decoder dec = new Base64.Decoder();

            dec.decode(text.toString());

            db.data = dec.flush();
            db.jpegTables = jpegTables;


        }

        currentHandler().defineBits(db);

    }

    public void DefineBitsJPEG2(Attributes attributes) throws SAXException
    {
        DefineBits db = new DefineBits(stagDefineBitsJPEG2);
        int id = parseInt(getAttribute(attributes, "id"));
        createCharacter(id, db);
        if (hasAttribute(attributes, "encoding"))
        {
            if (!getAttribute(attributes, "encoding").equals("base64"))
                fatalError(new SAXParseException("unknown encoding "
                        + getAttribute(attributes, "encoding"),
                        locator));
            if (hasAttribute(attributes, "src"))
                fatalError(new SAXParseException("can only specify one of src or encoding attributes", locator));

            text = new StringBuilder();
        }
        else
        {
            if (!hasAttribute(attributes, "src"))
                fatalError(new SAXParseException("must provide either src or encoding attribute", locator));

            File src = new File(getAttribute(attributes, "src"));

            try
            {
                FileInputStream input = new FileInputStream(getAttribute(attributes, "src"));
                db.data = new byte[(int)src.length()];
                input.read(db.data);
            }
            catch (IOException e)
            {
                fatalError(new SAXParseException("Unable to load DefineBitsJPEG2 src " + src.getName() + ":" + e.getMessage(), locator));
            }
        }
        stack.push(db);
    }

    public void DefineBitsJPEG2()
    {
        DefineBits db = (DefineBits)stack.pop();
        if (text != null)
        {
            // text is allocated for the base64 encoding

            Base64.Decoder dec = new Base64.Decoder();

            dec.decode(text.toString());

            db.data = dec.flush();
            db.jpegTables = null;
        }

        currentHandler().defineBits(db);

    }

    public void DefineShape(Attributes attributes) throws SAXException
    {
        DefineShape tag = new DefineShape(stagDefineShape);
        int id = parseInt(getAttribute(attributes, "id"));
        createCharacter(id, tag);
        tag.bounds = parseRect(getAttribute(attributes, "bounds"));
        tag.shapeWithStyle = new ShapeWithStyle();
        tag.shapeWithStyle.fillstyles = new ArrayList();
        tag.shapeWithStyle.linestyles = new ArrayList();
        tag.shapeWithStyle.shapeRecords = new ArrayList();

        stack.push(tag);
        fillstyles = tag.shapeWithStyle.fillstyles;
        linestyles = tag.shapeWithStyle.linestyles;
    }

    public void DefineShape()
    {
        DefineShape tag = (DefineShape)stack.pop();
        fillstyles = null;
        linestyles = null;
        tagHandler.defineShape(tag);
    }

    public void DefineShape3(Attributes attributes) throws SAXException
    {
        DefineShape tag = new DefineShape(TagValues.stagDefineShape3);
        int id = parseInt(getAttribute(attributes, "id"));
        createCharacter(id, tag);
        tag.bounds = parseRect(getAttribute(attributes, "bounds"));
        tag.shapeWithStyle = new ShapeWithStyle();
        tag.shapeWithStyle.fillstyles = new ArrayList();
        tag.shapeWithStyle.linestyles = new ArrayList();
        tag.shapeWithStyle.shapeRecords = new ArrayList();

        stack.push(tag);
        fillstyles = tag.shapeWithStyle.fillstyles;
        linestyles = tag.shapeWithStyle.linestyles;
    }

    public void DefineShape3()
    {
        DefineShape tag = (DefineShape)stack.pop();
        fillstyles = null;
        linestyles = null;
        tagHandler.defineShape3(tag);
    }

    public void DefineSprite(Attributes attributes) throws SAXParseException
    {
        DefineSprite sprite = new DefineSprite();
        int id = parseInt(getAttribute(attributes, "id"));
        createCharacter(id, sprite);
        stack.push(sprite);
        this.sprite = sprite;
    }

    public void DefineSprite()
    {
        DefineSprite sprite = (DefineSprite)stack.pop();
        this.sprite = null;
        tagHandler.defineSprite(sprite);
    }

    public void DoAction(Attributes attributes)
    {
        text = new StringBuilder();
        startLineNumber = locator.getLineNumber();
    }

    public void DoAction() throws SAXException
    {
        //try
        //{
            //String code = text.toString();
            text = null;

            /*
            AsActionsContainerInfo info = new AsActionsContainerInfo();
            ActionScriptCompiler compiler = packageManager.createCompiler(info, ActionType.kFrameActions,
                    CompileFlags.kCompileString,
                    startLineNumber);
            compiler.setFileName(docPath);
            compiler.compile(code, true);
            if (compiler.errorsExist())
            {
                throw new SAXParseException("compile failed", locator);
            }
            byte[] bytecode = compiler.getAsBytes();
            */
            DoAction doAction = new DoAction();

            //SwfDecoder r = new SwfDecoder(bytecode, header.version);
            //doAction.actionList = new ActionDecoder(r).decode(bytecode.length);

            currentHandler().doAction(doAction);
        //}
        //catch (IOException e)
        //{
        //    fatalError(new SAXParseException(e.getMessage(), locator, e));
        //}
    }

    public void ProductInfo(Attributes attributes) throws SAXException
    {
        int product = parseInt(getAttribute(attributes, "product"));
        int edition = parseInt(getAttribute(attributes, "edition"));
        byte majorVersion = Byte.parseByte(getAttribute(attributes, "majorVersion"));
        byte minorVersion = Byte.parseByte(getAttribute(attributes, "majorVersion"));
        long build = Long.parseLong(getAttribute(attributes, "build"));
        long compileDate = Long.parseLong(getAttribute(attributes, "compileDate"));

        stack.push(new ProductInfo(product, edition, majorVersion, minorVersion, build, compileDate));
    }

    public void FileAttributes()
    {
        tagHandler.fileAttributes((FileAttributes)stack.pop());
    }

    public void FileAttributes(Attributes attributes) throws SAXException
    {
        FileAttributes tag = new FileAttributes();
        tag.useDirectBlit = parseBoolean(getAttribute(attributes, "useDirectBlit"));
        tag.useGPU = parseBoolean(getAttribute(attributes, "useGPU"));
        tag.hasMetadata = parseBoolean(getAttribute(attributes, "hasMetadata"));
        tag.actionScript3 = parseBoolean(getAttribute(attributes, "actionScript3"));
        tag.suppressCrossDomainCaching = parseBoolean(getAttribute(attributes, "suppressCrossDomainCaching"));
        tag.swfRelativeUrls = parseBoolean(getAttribute(attributes, "swfRelativeUrls"));
        tag.useNetwork = parseBoolean(getAttribute(attributes, "useNetwork"));
        stack.push(tag);
    }
   
    public void EnableTelemetry()
    {
        tagHandler.enableTelemetry((EnableTelemetry)stack.pop());
    }

    public void EnableTelemetry(Attributes attributes) throws SAXException
    {
      EnableTelemetry tag = new EnableTelemetry();
        tag.enabled = parseBoolean(getAttribute(attributes, "advancedTelemetry"));
        stack.push(tag);
    }

    public void ProductInfo()
    {
        tagHandler.productInfo((ProductInfo)stack.pop());
    }

    private DefineTag findCharacter(int idref) throws SAXParseException
    {
        try
        {
            return dict.getTag(idref);
        }
        catch (IllegalArgumentException e)
        {
            //return null;
            throw new SAXParseException(e.getMessage(), locator, e);
        }
    }

    public void Package(Attributes attributes) throws SAXParseException
    {
        text = new StringBuilder();
        DefineSprite pkg = new DefineSprite();
        DoInitAction initAction = new DoInitAction(pkg);
        // get id for this package
        int id = parseInt(getAttribute(attributes, "id"));
        createCharacter(id, pkg);
        currentHandler().defineSprite(pkg);
        startLineNumber = locator.getLineNumber();
        stack.push(initAction);
    }

    public void Package() throws SAXException
    {
        //try
        //{
        //    String code = text.toString();
            text = null;
            DoInitAction initAction = (DoInitAction)stack.pop();

            /*
            AsActionsContainerInfo info = new AsActionsContainerInfo();
            info.setModuleName(docPath);
            ActionScriptCompiler compiler = packageManager.createCompiler(info, ActionType.kPackageActions,
                    CompileFlags.kCompileString,
                    startLineNumber);
            // don't set the filename here because it makes AS2 compilain about the filename
            //compiler.setFileName(docPath);
            compiler.compile(code, true);
            if (compiler.errorsExist())
            {
                throw new SAXParseException("compile failed", locator);
            }
            byte[] bytecode = compiler.getAsBytes();
            */
            //ActionDecoder actionDecoder = new ActionDecoder(new SwfDecoder(bytecode, header.version));
            //initAction.actionList = actionDecoder.decode(bytecode.length);

            currentHandler().doInitAction(initAction);
        //}
        //catch (IOException e)
        //{
        //    fatalError(new SAXParseException(e.getMessage(), locator, e));
        //}
    }

    public void DoInitAction(Attributes attributes) throws SAXParseException
    {
        text = new StringBuilder();
        DoInitAction initAction = new DoInitAction();
        // get id of previous DefineSprite
        int idref = parseInt(getAttribute(attributes, "idref"));
        initAction.sprite = (DefineSprite)findCharacter(idref);
        startLineNumber = locator.getLineNumber();
        stack.push(initAction);
    }

    public void DoInitAction() throws SAXException
    {
        //try
        //{
            //String code = text.toString();
            text = null;
            DoInitAction initAction = (DoInitAction)stack.pop();

            /*
            AsActionsContainerInfo info = new AsActionsContainerInfo();
            ActionScriptCompiler compiler = packageManager.createCompiler(info, ActionType.kUndefinedActions,
                    CompileFlags.kCompileString,
                    startLineNumber);
            compiler.setFileName(docPath);
            compiler.compile(code, true);
            if (compiler.errorsExist())
            {
                throw new SAXParseException("compile failed", locator);
            }
            byte[] bytecode = compiler.getAsBytes();
            ActionDecoder actionDecoder = new ActionDecoder(new SwfDecoder(bytecode, header.version));
            initAction.actionList = actionDecoder.decode(bytecode.length);
            */

            currentHandler().doInitAction(initAction);
        //}
        //catch (IOException e)
        //{
        //    fatalError(new SAXParseException(e.getMessage(), locator, e));
        //}
    }

    public void EnableDebugger2(Attributes attributes) throws SAXParseException
    {
        EnableDebugger enableDebugger2 = new EnableDebugger(stagEnableDebugger2);
        enableDebugger2.password = getAttribute(attributes, "password");
        tagHandler.enableDebugger2(enableDebugger2);
    }

    public void EnableDebugger2()
    {}

    public void ExportAssets(Attributes attributes)
    {
        ExportAssets tag = new ExportAssets();
        stack.push(tag);
    }

    public void ExportAssets()
    {
        ExportAssets tag = (ExportAssets)stack.pop();
        tagHandler.exportAssets(tag);
    }

    public void Export(Attributes attributes) throws SAXParseException
    {
        ExportAssets tag = (ExportAssets)stack.peek();
        int idref = parseInt(getAttribute(attributes, "idref"));
        String name = getAttribute(attributes, "name");
        DefineTag ref = findCharacter(idref);
        ref.name = name;
        tag.exports.add(ref);
    }

    public void Export()
    {
    }

    public void fillstyle(Attributes attributes) throws SAXParseException
    {
        DefineShape defineShape = (DefineShape)stack.peek();
        boolean hasAlpha = (defineShape.code == stagDefineShape3);
        FillStyle fillstyle = new FillStyle();
        if (hasAttribute(attributes, "color"))
        {
            fillstyle.setType(FillStyle.FILL_SOLID);
            fillstyle.color = hasAlpha ? parseRGBA(getAttribute(attributes, "color")) :
                    parseRGB(getAttribute(attributes, "color"));
        }
        if (hasAttribute(attributes, "gradient"))
        {
            // todo support radial gradients
            fillstyle.setType(FillStyle.FILL_LINEAR_GRADIENT);
            fillstyle.gradient = parseGradient(getAttribute(attributes, "gradient"), hasAlpha);
            fillstyle.matrix = parseMatrix(getAttribute(attributes, "matrix"));
        }
        if (hasAttribute(attributes, "idref"))
        {
            // todo support clipped bitmaps
            fillstyle.setType(FillStyle.FILL_BITS); // tiled
            int idref = parseInt(getAttribute(attributes, "idref"));
            // todo check to make sure bitmapId points to a bitmap
            fillstyle.bitmap = findCharacter(idref);
            fillstyle.matrix = parseMatrix(getAttribute(attributes, "matrix"));
        }

        defineShape.shapeWithStyle.fillstyles.add(fillstyle);
    }

    public void fillstyle()
    {}

    public void FrameLabel(Attributes attributes) throws SAXParseException
    {
        FrameLabel frameLabel = new FrameLabel();
        frameLabel.label = getAttribute(attributes, "label");
        frameLabel.anchor = parseBoolean(getAttribute(attributes, "anchor"));
        tagHandler.frameLabel(frameLabel);
    }

    public void FrameLabel()
    {}

    public void Import(Attributes attributes) throws SAXParseException
    {
        ImportRecord record = new ImportRecord();
        int id = parseInt(getAttribute(attributes, "id"));
        record.name = getAttribute(attributes, "name");

        ImportAssets importAssets = (ImportAssets)stack.peek();
        importAssets.importRecords.add(record);

        // todo find the actual tag imported
        createCharacter(id, record);
    }

    public void Import()
    {}

    public void ImportAssets(Attributes attributes) throws SAXParseException
    {
        ImportAssets importAssets = new ImportAssets(stagImportAssets);
        importAssets.url = getAttribute(attributes, "url");
        importAssets.importRecords = new ArrayList();
        stack.push(importAssets);
    }

    public void ImportAssets()
    {
        ImportAssets importAssets = (ImportAssets)stack.pop();
        tagHandler.importAssets(importAssets);
    }

    public void line(Attributes attributes) throws SAXParseException
    {
        StraightEdgeRecord straightEdge = new StraightEdgeRecord();
        if (hasAttribute(attributes, "dx"))
        {
            straightEdge.deltaX = parseInt(getAttribute(attributes, "dx"));
        }
        if (hasAttribute(attributes, "dy"))
        {
            straightEdge.deltaY = parseInt(getAttribute(attributes, "dy"));
        }

        DefineShape defineShape = (DefineShape)stack.peek();
        defineShape.shapeWithStyle.shapeRecords.add(straightEdge);
    }

    public void line()
    {}

    public void linestyle(Attributes attributes) throws SAXParseException
    {
        DefineShape defineShape = (DefineShape)stack.peek();
        LineStyle linestyle = new LineStyle();
        if (defineShape.code == stagDefineShape3)
        {
            linestyle.color = parseRGBA(getAttribute(attributes, "color"));
        }
        else
        {
            linestyle.color = parseRGB(getAttribute(attributes, "color"));
        }
        linestyle.width = parseInt(getAttribute(attributes, "width"));
        linestyles.add(linestyle);
    }

    public void linestyle()
    {}

    public void swf(Attributes attributes) throws SAXException
    {
        Header h = new Header();
        h.version = parseInt(getAttribute(attributes, "version"));
        h.compressed = parseBoolean(getAttribute(attributes, "compressed"));
        h.rate = parseInt(getAttribute(attributes, "framerate"));
        h.size = parseRect(getAttribute(attributes, "size"));
        this.header = h;
        tagHandler.header(h);

        /*
        this.packageManager = new CompilerPackageManager(h.version, topLevel, 0);

        // register an asclassloader for the given aspath
        ASClassLoader asLoader = new ASClassLoader(aspath, false, null);
        asLoader.pm = packageManager;
        asLoader.debug = false;
        packageManager.addLoader(asLoader);
        packageManager.findType("String");

        MessageHandler.setThreadLocalMessageHandler(outputHandler);
        */
    }

    public void swf()
    {
    }

    public void JPEGTables(Attributes attributes) throws SAXParseException
    {
        text = new StringBuilder();
        if (hasAttribute(attributes, "encoding"))
        {
            if (!getAttribute(attributes, "encoding").equals("base64"))
                fatalError(new SAXParseException("unknown encoding "
                        + getAttribute(attributes, "encoding"),
                        locator));
        }
    }

    public void JPEGTables()
    {
        if (text != null)
        {
            String encoded = text.toString();
            text = null;

            Base64.Decoder dec = new Base64.Decoder();

            dec.decode(encoded);

            jpegTables = new GenericTag(stagJPEGTables);
            jpegTables.data = dec.flush();
            currentHandler().jpegTables(jpegTables);

        }
    }

    public void ShowFrame(Attributes attributes)
    {
        currentHandler().showFrame(new ShowFrame());

        if (sprite != null)
        {
            sprite.framecount++;
        }
        else
        {
            header.framecount++;
        }
    }

    public void ShowFrame()
    {
    }

    public void styleChange(Attributes attributes) throws SAXParseException
    {
        StyleChangeRecord styleChange = new StyleChangeRecord();
        if (hasAttribute(attributes, "dx") || hasAttribute(attributes, "dy"))
        {
            styleChange.stateMoveTo = true;
            styleChange.moveDeltaX = parseInt(getAttribute(attributes, "dx"));
            styleChange.moveDeltaY = parseInt(getAttribute(attributes, "dy"));
        }
        if (hasAttribute(attributes, "fillStyle0"))
        {
            styleChange.stateFillStyle0 = true;
            styleChange.fillstyle0 = parseInt(getAttribute(attributes, "fillStyle0"));
        }
        if (hasAttribute(attributes, "fillStyle1"))
        {
            styleChange.stateFillStyle1 = true;
            styleChange.fillstyle1 = parseInt(getAttribute(attributes, "fillStyle1"));
        }
        if (hasAttribute(attributes, "lineStyle"))
        {
            styleChange.stateLineStyle = true;
            styleChange.linestyle = parseInt(getAttribute(attributes, "lineStyle"));
        }
        styleChange.fillstyles = new ArrayList();
        styleChange.linestyles = new ArrayList();
        fillstyles = styleChange.fillstyles;
        linestyles = styleChange.linestyles;
        stack.push(styleChange);
    }

    public void styleChange()
    {
        StyleChangeRecord styleChange = (StyleChangeRecord)stack.pop();
        if (fillstyles.size() != 0)
        {
            styleChange.stateNewStyles = true;
        }

        DefineShape defineShape = (DefineShape)stack.peek();
        defineShape.shapeWithStyle.shapeRecords.add(styleChange);
        fillstyles = defineShape.shapeWithStyle.fillstyles;
        linestyles = defineShape.shapeWithStyle.linestyles;
    }

    public void PlaceObject2(Attributes attributes) throws SAXParseException
    {
        PlaceObject tag = new PlaceObject(stagPlaceObject2);
        tag.depth = parseInt(getAttribute(attributes, "depth"));
        if (hasAttribute(attributes, "className"))
        {
            tag.setClassName(getAttribute(attributes, "className"));
        }
        if (hasAttribute(attributes, "hasImage"))
        {
            tag.setHasImage(getAttribute(attributes, "hasImage").equals("true"));
        }
        if (hasAttribute(attributes, "idref"))
        {
            int idref = parseInt(getAttribute(attributes, "idref"));
            tag.setRef(findCharacter(idref));
        }
        if (hasAttribute(attributes, "name"))
        {
            tag.setName(getAttribute(attributes, "name"));
        }
        if (hasAttribute(attributes, "clipDepth"))
        {
            tag.setClipDepth(parseInt(getAttribute(attributes, "clipDepth")));
        }
        if (hasAttribute(attributes, "ratio"))
        {
            tag.setRatio(parseInt(getAttribute(attributes, "ratio")));
        }
        if (hasAttribute(attributes, "cxform"))
        {
            tag.setCxform(parseCXForm(getAttribute(attributes, "cxform")));
        }
        if (hasAttribute(attributes, "matrix"))
        {
            tag.setMatrix(parseMatrix(getAttribute(attributes, "matrix")));
        }

        stack.push(tag);
        text = new StringBuilder();
    }

    public void PlaceObject2() throws SAXException
    {
        PlaceObject tag = (PlaceObject)stack.pop();
        //try
        //{
            //String code = text.toString();
            text = null;

            /*
            if (code.length() > 0)
            {
                AsActionsContainerInfo info = new AsActionsContainerInfo();
                ActionScriptCompiler compiler = packageManager.createCompiler(info, ActionType.kSpriteActions,
                        CompileFlags.kCompileString,
                        locator.getLineNumber());
                compiler.setFileName(docPath);
                compiler.compile(code, true);
                if (compiler.errorsExist())
                {
                    throw new SAXParseException("compile failed", locator);
                }
                byte[] bytecode = compiler.getAsBytes();

                ActionDecoder decoder = new ActionDecoder(new SwfDecoder(bytecode, header.version));
                tag.setClipActions(decoder.decodeClipActions(bytecode.length));
            }
            */

            currentHandler().placeObject2(tag);
        //}
        //catch (IOException e)
        //{
        //    fatalError(new SAXParseException(e.getMessage(), locator, e));
        //}
    }

    public void SetBackgroundColor(Attributes attributes) throws SAXParseException
    {
        SetBackgroundColor tag = new SetBackgroundColor(parseRGB(getAttribute(attributes, "color")));
        currentHandler().setBackgroundColor(tag);
    }

    public void SetBackgroundColor()
    {
    }

    public void ScriptLimits(Attributes attributes) throws SAXParseException
    {
        ScriptLimits tag = new ScriptLimits(parseInt(getAttribute(attributes, "maxRecursionLimit")),
                parseInt(getAttribute(attributes, "scriptTimeLimit")));
        currentHandler().scriptLimits(tag);
    }

    public void ScriptLimits()
    {
    }

    private Matrix parseMatrix(String s)
    {
        Matrix matrix = new Matrix();
        for (int i = 0; i < s.length(); i++)
        {
            char c = s.charAt(i);
            switch (c)
            {
                case 'r':
                    i++;
                    String[] parts = StringUtils.split(s.substring(i), "[, ]", 3);
                    matrix.setRotate(Double.parseDouble(parts[0]), Double.parseDouble(parts[1]));
                    break;
                case 's':
                    i++;
                    parts = StringUtils.split(s.substring(i), "[, ]", 3);
                    matrix.setScale(Double.parseDouble(parts[0]), Double.parseDouble(parts[1]));
                    break;
                case 't':
                    i++;
                    parts = StringUtils.split(s.substring(i), "[, ]", 3);
                    matrix.translateX = Integer.parseInt(parts[0]);
                    matrix.translateY = Integer.parseInt(parts[1]);
                    break;
            }
        }
        return matrix;
    }

    private Gradient parseGradient(String s, boolean hasAlpha)
    {
        Gradient gradient = new Gradient(); // todo - support focal

        // todo add error checking
        //    count must be 1..8
        //    number of parts must be even
        //    ratio must be 0..255
        String[] parts = StringUtils.split(s, " ");
        int count = parts.length / 2;
        gradient.records = new GradRecord[count];
        for (int i = 0; i < count; i++)
        {
            GradRecord record = gradient.records[i] = new GradRecord();
            record.ratio = Integer.parseInt(parts[2 * i]);
            record.color = hasAlpha ? parseRGBA(parts[2 * i + 1]) : parseRGB(parts[2 * i + 1]);
        }
        return gradient;
    }

    private CXForm parseCXForm(String s)
    {
        // todo add error checking
        //    must be six parts
        //    each term must be -32768..32767
        String[] parts = StringUtils.split(s, "([rgb]\\+?| )");
        CXForm cxform = new CXForm();
        cxform.redAddTerm = Integer.parseInt(parts[0]);
        cxform.redMultTerm = Integer.parseInt(parts[1]);
        cxform.greenAddTerm = Integer.parseInt(parts[2]);
        cxform.greenMultTerm = Integer.parseInt(parts[3]);
        cxform.blueAddTerm = Integer.parseInt(parts[4]);
        cxform.blueMultTerm = Integer.parseInt(parts[5]);
        return cxform;
    }

    private boolean parseBoolean(String attribute)
    {
        return Boolean.valueOf(attribute).booleanValue();
    }

    /**
     * @param s
     * @return 0x00RRGGBB
     */
    private int parseRGB(String s)
    {
        int rgb = parseColor(s);
        int color = ((rgb >> 16) & 255) << 16; // red
        color |= ((rgb >> 8) & 255) << 8; // green
        color |= ((rgb >> 0) & 255); // blue
        return color;
    }

    /**
     * @param s
     * @return 0xAARRGGBB
     */
    private int parseRGBA(String s)
    {
        int rgb = parseColor(s);
        int color = ((rgb >> 24) & 255) << 16; // red
        color |= ((rgb >> 16) & 255) << 8; // green
        color |= ((rgb >> 8) & 255); // blue
        color |= ((rgb >> 0) & 255) << 24; // alpha
        return color;
    }

    public static int parseColor(String string)
    {
        if (string.length() > 0)
        {
            if (string.charAt(0) == '#')
            {
                return (int)Long.parseLong(string.substring(1), 16);
            }
            else if (string.startsWith("0x") || string.startsWith("0X"))
            {
                return Integer.parseInt(string.substring(2), 16);
            }
            else
            {
                return Integer.parseInt(string);
            }
        }
        else
        {
            return 0;
        }
    }

    private boolean hasAttribute(Attributes attributes, String qName)
    {
        return attributes.getValue(qName) != null;
    }

    private String getAttribute(Attributes attributes, String qName) throws SAXParseException
    {
        String value = attributes.getValue(qName);
        if (value == null)
        {
            error(new SAXParseException("attribute not found: " + qName, locator));
        }
        return value;
    }

    private Rect parseRect(String s)
    {
        String[] parts = StringUtils.split(s, "x");
        return new Rect(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]));
    }

    private int parseInt(String s)
    {
        return Integer.parseInt(s);
    }

    public void endElement(String uri, String localName, String qName)
            throws SAXException
    {
        try
        {
            Method method = getClass().getMethod(qName, new Class[]{});
            method.invoke(this, new Object[]{});
        }
        catch (NoSuchMethodException e)
        {
            warning(new SAXParseException("no end handler for " + qName, locator));
        }
        catch (IllegalAccessException e)
        {
            fatalError(new SAXParseException(e.getMessage(), locator, e));
        }
        catch (InvocationTargetException e)
        {
            Throwable t = e.getTargetException();
            if (t instanceof SAXException)
            {
                throw (SAXException)t;
            }
            else if (t instanceof Error)
            {
                throw (Error)t;
            }
            else
            {
                fatalError(new SAXParseException(t.getMessage(), locator));
            }
        }
    }

    public void endDocument()
            throws SAXException
    {
        tagHandler.finish();
    }

    public void warning(SAXParseException e)
            throws SAXParseException
    {
        //outputHandler.warning(0, e.getLineNumber(), docPath, e.getMessage());
    }

    public void error(SAXParseException e)
            throws SAXParseException
    {
        //outputHandler.error(0, e.getLineNumber(), docPath, e.getMessage());
    }

    public void fatalError(SAXParseException e)
            throws SAXParseException
    {
        //outputHandler.error(0, e.getLineNumber(), docPath, e.getMessage());
        throw e;
    }

    public void setDocumentLocator(Locator locator)
    {
        this.locator = locator;
    }


    public boolean parse(String path) throws IOException//, OutputHandler handler) throws IOException
    {
        // parser property names
        final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
        final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";

        final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";

        this.docPath = path;
        //this.outputHandler = handler;

        InputStream in = new BufferedInputStream(new FileInputStream(path));
        SAXParser parser;
        try
        {
            SAXParserFactory factory = SAXParserFactory.newInstance();
            factory.setValidating(true);
            factory.setNamespaceAware(true);
            try
            {
                parser = factory.newSAXParser();
                parser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
                parser.setProperty(JAXP_SCHEMA_SOURCE,
                        new InputSource(getClass().getResource("swfx.xsd").toExternalForm()));
            }
            catch (Exception e)
            {
                if (e instanceof SAXNotRecognizedException)
                {
                    // schema validation not supported... ignore
                    factory.setValidating(false);
                    factory.setNamespaceAware(true);
                    parser = factory.newSAXParser();
                }
                else if (e instanceof IOException)
                {
                    throw (IOException)e;
                }
                else if (e instanceof SAXException)
                {
                    throw (SAXException)e;
                }
                else
                {
                    e.printStackTrace();
                    parser = null;
                }
            }
            parser.parse(in, this);
            return true;
        }
        catch (SAXException e)
        {
            // errors will have been reported already
            //e.printStackTrace();
            return false;
        }
        catch (Exception e)
        {
            if (e instanceof ParserConfigurationException)
            {
                if (Trace.error)
                    e.printStackTrace();

                return false;
            }
            else if (e instanceof IOException)
            {
                throw (IOException)e;
            }
            else
            {
                e.printStackTrace();
                return true;
            }
        }
        finally
        {
            in.close();
        }
    }

    public static void main(String[] args) throws IOException
    {
        String aspath = null;
        for (int i = 0; i < args.length; i++)
        {
            if (args[i].equals("-aspath"))
            {
                aspath = args[++i];
                continue;
            }
            TagEncoder encoder = new TagEncoder();
            //ConsoleOutputHandler tagHandler = new ConsoleOutputHandler(null, null);
            SwfxParser swfxParser = new SwfxParser(encoder, StringUtils.splitPath(aspath));
            boolean success = swfxParser.parse(args[i]);//, tagHandler);
            if (success)
            {
                String swfFileName = args[i].substring(0, args[i].lastIndexOf('.')) + ".swf";
                OutputStream out = new BufferedOutputStream(new FileOutputStream(swfFileName));
                try
                {
                    encoder.writeTo(out);
                }
                finally
                {
                    out.close();
                }
            }
            else
            {
                System.exit(1);
            }
        }
    }
}
TOP

Related Classes of flash.swf.tools.SwfxParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.