| /* |
| * |
| * 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.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 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); |
| } |
| } |
| } |
| } |