blob: 5fe17311afa169377a7a0c7840479e050cd1d084 [file] [log] [blame]
/*
*
* 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);
}
}
}
}