flash on 2011-5-12
Use as3swf Library
Use MinimalComps Library
Use FontLoader Class
Other
/**
* Copyright fujista ( http://wonderfl.net/user/fujista )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/ajSX
*/
package {
// Use as3swf Library
import com.codeazur.as3swf.SWFData;
import com.codeazur.as3swf.data.SWFRawTag;
import com.codeazur.as3swf.data.SWFRecordHeader;
import com.codeazur.as3swf.data.SWFRectangle;
import com.codeazur.as3swf.factories.SWFTagFactory;
import com.codeazur.as3swf.tags.IDefinitionTag;
import com.codeazur.as3swf.tags.IDisplayListTag;
import com.codeazur.as3swf.tags.ITag;
import com.codeazur.as3swf.tags.TagDefineSprite;
import com.codeazur.as3swf.tags.TagEnd;
import com.codeazur.as3swf.tags.TagImportAssets;
import com.codeazur.as3swf.tags.TagImportAssets2;
import com.codeazur.as3swf.tags.TagPlaceObject;
import com.codeazur.as3swf.tags.TagPlaceObject2;
import com.codeazur.as3swf.tags.TagPlaceObject3;
import com.codeazur.as3swf.tags.TagRemoveObject;
import com.codeazur.as3swf.tags.TagRemoveObject2;
import com.codeazur.as3swf.tags.TagShowFrame;
// Use MinimalComps Library
import com.bit101.components.Label;
import com.bit101.components.ProgressBar;
import com.bit101.components.PushButton;
import com.bit101.components.Style;
import com.bit101.components.Text;
import com.bit101.components.TextArea;
// Use FontLoader Class
import net.wonderfl.utils.FontLoader;
// Other
import flash.display.Sprite;
import flash.errors.IOError;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.MouseEvent;
import flash.events.ProgressEvent;
import flash.net.FileReference;
import flash.utils.ByteArray;
import flash.utils.Dictionary;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.text.TextFormatAlign;
public class MovieClipTranscoder extends Sprite {
// swf headers
public var version:uint;
public var fileLength:uint;
public var frameSize:SWFRectangle;
public var frameRate:Number;
public var frameCount:uint;
public var compressed:Boolean;
// minimalcomps
protected var browse:PushButton;
protected var filename:Text;
protected var log:TextArea;
protected var progress1:ProgressBar;
protected var progress2:ProgressBar;
protected var status:Label;
protected var step:Label;
protected var _file:FileReference;
protected var _maxCharacterId:uint = 0;
protected var _dictionary:Dictionary;
protected var _spriteList:Dictionary;
protected var _processList:Dictionary;
protected var _steps:uint = 5;
protected var _parentMessage:String;
public function MovieClipTranscoder() {
_dictionary = new Dictionary();
_spriteList = new Dictionary();
_processList = new Dictionary();
initFileReference();
initFontLoad();
}
public function transcode(ba:ByteArray):void {
var source:SWFData = new SWFData();
ba.readBytes(source);
ba.clear();
try {
parse(source);
// build(source);
} catch (e:Error) {
}
// save.enabled = true;
}
protected function parse(data:SWFData):void {
try {
updateStatus("Checking...", false);
parseHeader(data);
updateStatus("done.");
setProgressMaximum(fileLength, "Parsing...");
parseTimeline(data, frameCount);
updateStatus("done.");
} catch (e:Error) {
updateStatus(e.toString());
}
}
protected function parseHeader(data:SWFData):void {
var header:Dictionary = new Dictionary();
var signature:Array = [data.readUI8(), data.readUI8(), data.readUI8()];
if ((signature[0] != 0x43 && signature[0] != 0x46) || signature[1] != 0x57 || signature[2] != 0x53) {
throw( new Error("File is not swf.") );
}
this.version = data.readUI8();
this.fileLength = data.readUI32();
this.compressed = (signature[0] == 0x43) ? true : false;
if (this.compressed) {
updateStatus("Uncompressing...", false);
data.swfUncompress();
if (this.fileLength != data.length) {
throw( new Error("File uncompress error") );
}
}
this.frameSize = data.readRECT();
this.frameRate = data.readFIXED8();
this.frameCount = data.readUI16();
}
protected function parseTimeline(data:SWFData, frameCount:uint, parentCharacterId:uint = 0):void {
var pos:uint;
var raw:SWFRawTag;
var tag:ITag;
var currentFrame:uint = 1;
var display:Dictionary;
var displayList:Dictionary = new Dictionary();
do {
pos = parentCharacterId ? data.position + _dictionary[parentCharacterId] : data.position;
raw = data.readRawTag();
data.position += raw.header.contentLength;
tag = parseTag(raw.bytes, pos);
switch (tag.type) {
// Except
case TagPlaceObject.TYPE:
case TagImportAssets.TYPE:
case TagImportAssets2.TYPE:
throw( new Error(tag.name + " not support.") );
case TagShowFrame.TYPE:
for (var key:String in displayList) {
displayList[key]["count"]++;
}
currentFrame++;
break;
case TagPlaceObject2.TYPE:
case TagPlaceObject3.TYPE:
var placeObject:TagPlaceObject = tag as TagPlaceObject;
if (placeObject.hasMove && displayList[placeObject.depth]) {
if (placeObject.hasCharacter) {
display = displayList[placeObject.depth];
_processList[display["id"]] = Math.max(display["count"], _processList[display["id"]]);
} else {
//
}
}
if (placeObject.hasCharacter && _spriteList[placeObject.characterId]) {
display = new Dictionary();
display["id"] = placeObject.characterId;
display["count"] = 0;
display["depth"] = placeObject.depth;
display["offset"] = currentFrame;
displayList[placeObject.depth] = display;
if (parentCharacterId > 0 && !_spriteList[parentCharacterId]) {
_spriteList[parentCharacterId] = true;
_processList[parentCharacterId] = 0;
}
}
break;
case TagRemoveObject.TYPE:
case TagRemoveObject2.TYPE:
var removeObject:TagRemoveObject = tag as TagRemoveObject;
if (displayList[removeObject.depth]) {
display = displayList[removeObject.depth];
_processList[display["id"]] = Math.max(display["count"], _processList[display["id"]]);
delete displayList[removeObject.depth];
}
break;
}
setProgressValue(pos + raw.header.contentLength);
} while (tag.type != TagEnd.TYPE);
}
protected function parseTag(data:SWFData, pos:uint):ITag {
var header:SWFRecordHeader = data.readTagHeader();
var tag:ITag = SWFTagFactory.create(header.type, null);
updateStatus(tag.name);
if (tag is IDefinitionTag) {
var characterId:uint = data.readUI16();
_dictionary[characterId] = pos;
_maxCharacterId = Math.max(_maxCharacterId, characterId);
if (tag is TagDefineSprite) {
var frameCount:uint = data.readUI16();
if (frameCount > 1) {
_spriteList[characterId] = true;
_processList[characterId] = 0;
}
parseTimeline(data, frameCount, characterId);
}
} else if (tag is IDisplayListTag) {
tag.parse(data, header.contentLength, this.version);
}
return tag;
}
protected function build(data:SWFData):void {
buildHeader(data);
}
protected function buildHeader(data:SWFData):void {
data.writeUI8(this.compressed ? 0x43 : 0x46);
data.writeUI8(0x57);
data.writeUI8(0x53);
data.writeUI8(this.version);
data.writeUI32(this.fileLength);
data.writeRECT(this.frameSize);
data.writeFIXED8(this.frameRate);
data.writeUI16(this.frameCount);
}
protected function buildTimeline(source:SWFData, data:SWFData):void {
}
protected function buildTag():void {
}
protected function buildSprite():void {
}
protected function test(characterId:uint, frame:uint):void {
var truncate:Dictionary;
var display:Dictionary;
do {
} while (true);
}
protected function setProgressMaximum(value:uint, message:String = null):void {
progress2.maximum = value;
progress1.value++;
if (message) {
updateStatus(message, false);
step.text = Math.floor( value / progress2.maximum * 100 ) + "%";
}
}
protected function setProgressValue(value:uint, append:Boolean = false):void {
value += append ? progress2.value : 0;
progress2.value = value;
step.text = Math.floor( value / progress2.maximum * 100 ) + "%";
}
protected function updateStatus(text:String, append:Boolean = true, override:Boolean = true):void {
_parentMessage = (!append && override) ? text : _parentMessage;
status.text = append ? _parentMessage + " " + text : text;
log.text += status.text + "\n";
}
protected function initFileReference():void {
_file = new FileReference();
_file.addEventListener(Event.SELECT, function(e:Event):void{
setProgressMaximum(e.target.size, "Loading...");
filename.text = e.target.name;
browse.enabled = false;
e.target.load();
});
_file.addEventListener(Event.COMPLETE, function(e:Event):void{
setProgressValue(e.target.data.length);
updateStatus("done.");
transcode(e.target.data);
});
_file.addEventListener(ProgressEvent.PROGRESS, function(e:ProgressEvent):void{
setProgressValue(e.bytesLoaded);
});
_file.addEventListener(IOErrorEvent.IO_ERROR, function(e:IOError):void{
updateStatus(e.toString());
});
}
protected function initFontLoad():void {
var font:FontLoader = new FontLoader();
font.addEventListener(Event.COMPLETE, function(e:Event):void {
initMinimalComps();
progress1.maximum = 5;
updateStatus("Please push \"Browse\" button and select target file.", false);
});
font.load("IPAGP");
}
protected function initMinimalComps():void {
var format:TextFormat;
Style.fontSize = 12;
Style.fontName = "IPAGP";
new Label(this, 5, 5, "File:");
browse = new PushButton(this, 360, 25, "Browse", function(e:MouseEvent):void{
_file.browse();
});
filename = new Text(this, 5, 25, null);
filename.width = 350;
filename.height = 20;
filename.editable = false;
new Label(this, 5, 55, "Progress:");
progress1 = new ProgressBar(this, 5, 75);
progress1.width = 455;
progress2 = new ProgressBar(this, 5, 86);
progress2.width = 455;
new Label(this, 5, 100, ">>");
status = new Label(this, 25, 100);
status.width = 400;
status.autoSize = false;
step = new Label(this, 410, 100);
step.width = 50;
step.autoSize = false;
format = step.textField.defaultTextFormat;
format.align = TextFormatAlign.RIGHT;
step.textField.defaultTextFormat = format;
//new PushButton(this, 180, 180, "SAVE");
new Label(this, 5, 280, "Information:");
log = new TextArea(this, 5, 300, null);
log.width = 455;
log.height = 160;
log.editable = false;
}
}
}