Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Added lot of bug fixes and improvements, new tags, Google's Closure C…

…ompiler and some Rake tasks

Signed-off-by: Tobias Schneider <schneider@tobias-schneiders-macbook-pro.local>
  • Loading branch information...
commit 00353e802c7e6cb9b104662d5b0adf5e814860b0 1 parent 5896327
Tobias Schneider authored
View
2  .gitignore
@@ -0,0 +1,2 @@
+dist/
+
View
6 README
@@ -1,6 +0,0 @@
-Gordon: An open source Flash™ runtime written in pure JavaScript
-
-Copyright (c) 2010 Tobias Schneider
-Gordon is freely distributable under the terms of the MIT license.
-
-...
View
6 README.md
@@ -0,0 +1,6 @@
+Gordon
+======
+
+#### An open source Flash™ runtime written in pure JavaScript ####
+
+Visit the GitHub Wiki for more information: http://wiki.github.com/tobeytailor/gordon/
View
30 Rakefile
@@ -0,0 +1,30 @@
+src_dir = 'src'
+dist_dir = 'dist'
+build_dir = 'build'
+base_names = [ 'base', 'movie', 'parser', 'stream', 'svg_renderer', 'vendor' ]
+base_files = base_names.map { |file| File.join(src_dir, file + '.js') }
+intro = File.join(src_dir, 'intro.js')
+outro = File.join(src_dir, 'outro.js')
+output_file = File.join(dist_dir, 'gordon.js')
+output_file_min = File.join(dist_dir, 'gordon.min.js')
+compiler = File.join(build_dir, 'compiler.jar')
+
+task :default => :min
+
+task :gordon do
+ sh 'cat vendor/* > ' + File.join(src_dir, 'vendor.js')
+ sh 'mkdir -p ' + dist_dir
+ sh 'cat ' + intro + ' > ' + output_file
+ sh 'for file in ' + base_files.join(' ') + "; do echo | cat $file - | sed 's/^/\t/' >> " + output_file + '; done'
+ sh 'cat ' + outro + ' >> ' + output_file
+end
+
+task :min => :gordon do
+ sh 'head -6 ' + output_file + ' > ' + output_file_min
+ sh 'java -jar ' + compiler + ' --warning_level QUIET --js=' + output_file + ' >> ' + output_file_min
+end
+
+task :clean do
+ sh 'rm -rf ' + dist_dir
+ sh 'rm src/vendor.js'
+end
View
BIN  build/compiler.jar
Binary file not shown
View
11 demos/blue.html
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>Gordon: An open source Flash™ runtime written in pure JavaScript</title>
- <script type="text/javascript" src="../gordon.js"></script>
- </head>
- <body onload="new Gordon.Movie('blue.swf', {id: 'stage', width: 500, height: 400})">
- <div id="stage"></div>
- </body>
-</html>
View
BIN  demos/blue.swf
Binary file not shown
View
11 demos/tiger.html
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>Gordon: An open source Flash™ runtime written in pure JavaScript</title>
- <script type="text/javascript" src="../gordon.js"></script>
- </head>
- <body onload="new Gordon.Movie('tiger.swf', {id: 'stage', width: 500, height: 400})">
- <div id="stage"></div>
- </body>
-</html>
View
BIN  demos/tiger.swf
Binary file not shown
View
11 demos/trip.html
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-<html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>Gordon: An open source Flash™ runtime written in pure JavaScript</title>
- <script type="text/javascript" src="../gordon.js"></script>
- </head>
- <body onload="new Gordon.Movie('trip.swf', {id: 'stage', width: 500, height: 400})">
- <div id="stage"></div>
- </body>
-</html>
View
BIN  demos/trip.swf
Binary file not shown
View
47 gordon.js
@@ -1,47 +0,0 @@
-/*
- * Gordon: An open source Flash™ runtime written in pure JavaScript
- *
- * Copyright (c) 2010 Tobias Schneider
- * Gordon is freely distributable under the terms of the MIT license.
- */
-
-(function(){
- var _g = Gordon = {};
- var _loadedUrls = {};
-
- if(self.importScripts){ _g.ROOT = "../"; }
- else{
- var scripts = document.getElementsByTagName("script");
- var i = scripts.length;
- while(i--){
- var match = scripts[i].src.match(/(^|.*\/)gordon\.js$/);
- if(match){ _g.ROOT = match[1]; }
- }
- }
-
- _g.xhr = function(){
- var request = new XMLHttpRequest();
- request.open.apply(request, arguments);
- return request;
- }
-
- _g.require = function(url){
- if(!url.match(/\.([^\/]*)$/)){ url += ".js"; }
- if(!_loadedUrls[url]){
- if(self.importScripts){ importScripts(_g.ROOT + url); }
- else{
- with(_g.xhr("GET", _g.ROOT + url, false)){
- send(null);
- if(200 == status){
- eval(responseText);
- _loadedUrls[url] = true;
- }else{ throw new Error("Unable to load " + url + " status: " + status); }
- }
- }
- }
- }
-})();
-
-Gordon.require("src/_base");
-Gordon.require("src/worker");
-Gordon.require("src/Movie");
View
176 src/Movie.js
@@ -1,176 +0,0 @@
-/*
- * Gordon: An open source Flash™ runtime written in pure JavaScript
- *
- * Copyright (c) 2010 Tobias Schneider
- * Gordon is freely distributable under the terms of the MIT license.
- */
-
-Gordon.require("src/Stream");
-
-(function(){
- var _g = Gordon;
- var _useJson = _g.USE_NATIVE_JSON;
- var _m = _g.movieStates;
- var _options = {
- id: null,
- name: null,
- width: 0,
- height: 0,
- autoplay: true,
- loop: true,
- quality: _g.scaleValues.HIGH,
- scale: _g.scaleValues.DEFAULT,
- bgcolor: null,
- renderer: null,
- onLoad: function(){},
- onEnterFrame: function(){}
- };
-
- _g.Movie = function(url, options){
- if(!url){ throw new Error("URL of a SWF movie file must be passed as first argument"); }
- var t = this;
- t._state = _m.LOADING;
- var xhr = _g.xhr("GET", url, false);
- xhr.overrideMimeType("text/plain; charset=x-user-defined");
- xhr.send(null);
- if(200 != xhr.status){ throw new Error("Unable to load " + url + " status: " + xhr.status); }
- var s = new _g.Stream(xhr.responseText);
- var signature = s.readString(3);
- var v = _g.validSignatures;
- if(signature != v.SWF && signature != v.COMPRESSED_SWF){ throw new Error(url + " is not a SWF movie file"); }
- t.url = url;
- for(var o in _options){ t[o] = undefined != options[o] ? options[o] : _options[o]; }
- t.stream = s;
- t.version = s.readUI8();
- t.fileLength = s.readUI32();
- if(signature == v.COMPRESSED_SWF){ s.decompress(); }
- var f = t.frameSize = s.readRect();
- t.frameRate = s.readUI16() / 256;
- t.frameCount = s.readUI16();
- var frameWidth = f.right - f.left;
- var frameHeight = f.bottom - f.top;
- if(!(t.width && t.height)){
- t.width = frameWidth;
- t.height = frameHeight;
- }
- t.currentFrame = 0;
- if(!t.renderer){
- Gordon.require("src/SvgRenderer");
- t.renderer = _g.SvgRenderer;
- }
- t._renderer = new t.renderer(t.width, t.height, frameWidth, frameHeight, t.quality, t.scale, t.bgcolor);
- var d = t._dictionary = {};
- var l = t._timeline = [];
- var parser = new Worker(_g.ROOT + "src/_parser.js");
- parser.onerror = function(){};
- parser.onmessage = function(e){
- var object = _useJson ? JSON.parse(e.data) : e.data;
- if("frame" == object.type){
- var bgcolor = object.bgcolor;
- if(bgcolor && !t.bgcolor){
- t._renderer.setBgcolor(bgcolor);
- t.bgcolor = bgcolor;
- }
- l.push(object);
- if(t.id && l.length == 1){
- var parent = document.getElementById(t.id);
- parent.innerHTML = '';
- parent.appendChild(t._renderer.getNode());
- t.goto(1);
- t.onLoad();
- if(t.autoplay){ t.play(); }
- }
- }else{
- t._renderer.defineObject(object);
- d[object.id] = object;
- }
- var action = object.action;
- if(action){ eval("object.action = function(){ (" + action + ")(t); }"); }
- };
- parser.postMessage(s.readString(s._length - s._offset));
- t._state = _m.LOADED;
- };
- _g.Movie.prototype = {
- play: function(){
- var t = this;
- if(t._state != _m.PLAYING){
- t._state = _m.PLAYING;
- var interval = setInterval(function(){
- if(t._state == _m.PLAYING){
- t.nextFrame();
- if(t.currentFrame == t.frameCount && !t.loop){ t.rewind(); }
- }else{ clearInterval(interval); }
- }, 1000 / t.frameRate);
- }
- return t;
- },
-
- stop: function(){
- this._state = _m.STOPPED;
- return this;
- },
-
- nextFrame: function(){
- var t = this;
- if(t.currentFrame == t.frameCount){ t.currentFrame = 0; }
- var frame = t._timeline[t.currentFrame];
- var r = t._renderer;
- if(frame){
- var displayList = frame.displayList;
- for(var depth in displayList){
- var character = displayList[depth];
- if(character){ r.placeCharacter(character); }
- else{ r.removeCharacter(depth); }
- }
- ++t.currentFrame;
- var action = frame.action;
- if(action){ action(); }
- t.onEnterFrame();
- }
- return t;
- },
-
- prevFrame: function(){
- this.goto(this.currentFrame - 1);
- return this;
- },
-
- goto: function(frame){
- var t = this;
- if(frame < 0){ frame = t.frameCount + frame; }
- if(frame && frame <= t.frameCount && frame != t.currentFrame){
- while(t.currentFrame != frame){ t.nextFrame(); }
- }
- return t;
- },
-
- rewind: function(){
- this.stop();
- this.goto(1);
- return this;
- },
-
- getUrl: function(url, target){
- var u = _g.urlTargets;
- switch(target){
- case u.BLANK:
- window.open(url);
- break;
- case u.PARENT:
- parent.location.href = url;
- break;
- case u.TOP:
- top.location.href = url;
- break;
- default:
- location.href = url;
- }
- return this;
- },
-
- toggleQuality: function(){
- this._renderer.toggleQuality();
- return this;
- }
- };
-})();
View
337 src/Stream.js
@@ -1,337 +0,0 @@
-/*
- * Gordon: An open source Flash™ runtime written in pure JavaScript
- *
- * Copyright (c) 2010 Tobias Schneider
- * Gordon is freely distributable under the terms of the MIT license.
- */
-
-Gordon.require("src/inflate");
-
-(function(){
- var _g = Gordon;
- var _t2p = _g.twips2px;
-
- _g.Stream = function(data){
- var t = this;
- t._buffer = data;
- t._length = t._buffer.length;
- t._offset = 0;
- t._bitBuffer = null;
- t._bitOffset = 8;
- };
- _g.Stream.prototype = {
- decompress: function() {
- var t = this;
- t._offset += 2;
- var header = t._buffer.substr(0, t._offset);
- var data = zip_inflate(t._buffer.substr(t._offset));
- t._buffer = header + data;
- t._length = t._buffer.length;
- return t;
- },
-
- readByteAt: function(position){
- return this._buffer.charCodeAt(position) & 0xff;
- },
-
- readNumber: function(numBytes, bigEndian){
- var t = this;
- var value = 0;
- if(bigEndian){
- var i = numBytes;
- while(i--){ value = value * 256 + t.readByteAt(t._offset++); }
- }else{
- var o = t._offset;
- var i = o + numBytes;
- while(i > o){ value = value * 256 + t.readByteAt(--i); }
- t._offset += numBytes;
- }
- t.align();
- return value;
- },
-
- readSNumber: function(numBytes, bigEndian){
- var value = this.readNumber(numBytes, bigEndian);
- var numBits = numBytes * 8;
- if(value >> (numBits - 1)){ value -= Math.pow(2, numBits); }
- return value;
- },
-
- readSI8: function(){
- return this.readSNumber(1);
- },
-
- readSI16: function(bigEndian){
- return this.readSNumber(2, bigEndian);
- },
-
- readSI32: function(bigEndian){
- return this.readSNumber(4, bigEndian);
- },
-
- readUI8: function(){
- return this.readByteAt(this._offset++);
- },
-
- readUI16: function(bigEndian){
- return this.readNumber(2, bigEndian);
- },
-
- readUI24: function(bigEndian){
- return this.readNumber(3, bigEndian);
- },
-
- readUI32: function(bigEndian){
- return this.readNumber(4, bigEndian);
- },
-
- readFixed: function(){
- return this._readFixedPoint(32, 16);
- },
-
- _readFixedPoint: function(numBits, precision){
- return this.readSB(numBits) * Math.pow(2, -precision);
- },
-
- readFixed8: function(){
- return this._readFixedPoint(16, 8);
- },
-
- readFloat: function(){
- return this._readFloatingPoint(8, 23);
- },
-
- _readFloatingPoint: function(numEbits, numSbits){
- var numBits = 1 + numEbits + numSbits;
- var numBytes = numBits / 8;
- var t = this;
- if(numBytes > 4){
- var value = 0;
- var i = Math.ceil(numBytes / 4);
- while(i--){
- var o = t._offset;
- var j = o + numBytes >= 4 ? 4 : numBytes % 4;
- while(j > o){ value = value * 256 + String.fromCharCode(t.readByteAt(--j)); }
- t._offset += numBytes;
- numBytes -= numBytes;
- }
- var mask = 0x01 << (numBits - 1);
- var sign = value & mask;
- var expo = 0;
- var i = numEbits;
- while(i--){
- mask >>= 1;
- expo |= buffer & mask ? 1 : 0;
- expo <<= 1;
- }
- var mantissa = 0;
- var i = numSbits;
- while(i--){
- mask >>= 1;
- if(buffer & mask){ mantissa += Math.pow(2, i - 1); }
- }
- }else{
- var sign = t.readUB(1);
- var expo = t.readUB(numEbits);
- var mantissa = t.readUB(numSbits);
- }
- var maxExpo = Math.pow(2, numEbits);
- var bias = Math.floor((maxExpo - 1) / 2);
- var scale = Math.pow(2, numSbits);
- var fraction = mantissa / scale;
- if(bias){
- if(bias < maxExpo){ var value = Math.pow(2, expo - bias) * (1 + faction); }
- else if(fraction){ var value = NaN; }
- else{ var value = Infinity; }
- }else if(fraction){ var value = Math.pow(2, 1 - bias) * fraction; }
- else{ var value = 0; }
- if(value != NaN && sign){ value *= -1; }
- return value;
- },
-
- readFloat16: function(){
- return this._readFloatingPoint(5, 10);
- },
-
- readDouble: function(){
- return this._readFloatingPoint(11, 52);
- },
-
- readEncodedU32: function(){
- var value = 0;
- var i = 5;
- while(i--){
- var number = this.readByteAt(this._offset++);
- value = value * 128 + (number & 0x7F);
- if(!(number & 0x80)){ break; }
- }
- return value;
- },
-
- readSB: function(numBits){
- var value = this.readUB(numBits);
- if(value >> (numBits - 1)){ value -= Math.pow(2, numBits); }
- return value;
- },
-
- readUB: function(numBits){
- var t = this;
- var value = 0;
- var i = numBits;
- while(i--){
- if(8 == t._bitOffset){
- t._bitBuffer = t.readUI8();
- t._bitOffset = 0;
- }
- value = value * 2 + (t._bitBuffer & (0x80 >> t._bitOffset) ? 1 : 0);
- t._bitOffset++;
- }
- return value;
- },
-
- readFB: function(numBits){
- return this._readFixedPoint(numBits, 16);
- },
-
- readString: function(numChars){
- var t = this;
- var b = t._buffer;
- if(numChars){
- var string = b.substr(t._offset, numChars);
- t._offset += numChars;
- }else{
- numChars = t._length - t._offset;
- var chars = [];
- var i = numChars;
- while(i--){
- var code = t.readByteAt(t._offset++);
- if(code){ chars.push(String.fromCharCode(code)); }
- else{ break; }
- }
- var string = chars.join('');
- }
- return string;
- },
-
- readBool: function(numBits){
- return !!this.readUB(numBits || 1);
- },
-
- readLanguageCode: function(){
- return this.readUI8();
- },
-
- readRgb: function(){
- return {
- r: this.readUI8(),
- g: this.readUI8(),
- b: this.readUI8()
- }
- },
-
- readRgba: function(){
- var rgba = this.readRgb();
- rgba.a = this.readUI8() / 256;
- return rgba;
- },
-
- readArgb: function(){
- var alpha = this.readUI8() / 256;
- var rgba = this.readRGB();
- rgba.a = alpha;
- return rgba;
- },
-
- readRect: function(){
- var t = this;
- var numBits = t.readUB(5);
- var rect = {
- left: _t2p(t.readSB(numBits)),
- right: _t2p(t.readSB(numBits)),
- top: _t2p(t.readSB(numBits)),
- bottom: _t2p(t.readSB(numBits))
- }
- t.align();
- return rect;
- },
-
- readMatrix: function(){
- var t = this;
- var hasScale = t.readBool();
- if(hasScale){
- var numBits = t.readUB(5);
- var scaleX = t.readFB(numBits);
- var scaleY = t.readFB(numBits);
- }else{ var scaleX = scaleY = 1.0; }
- var hasRotation = t.readBool();
- if(hasRotation){
- var numBits = t.readUB(5);
- var skewX = t.readFB(numBits);
- var skewY = t.readFB(numBits);
- }else{ var skewX = skewY = 0.0; }
- var numBits = t.readUB(5);
- var matrix = {
- scaleX: scaleX, scaleY: scaleY,
- skewX: skewX, skewY: skewY,
- moveX: _t2p(t.readSB(numBits)),
- moveY: _t2p(t.readSB(numBits))
- };
- t.align();
- return matrix;
- },
-
- readCxform: function(){
- return this._readCxform();
- },
-
- readCxformWithAlpha: function(){
- return this._readCxform(true);
- },
-
- _readCxform: function(withAlpha){
- var t = this;
- var hasAddTerms = t.readBool();
- var hasMultTerms = t.readBool();
- var numBits = t.readUB(4);
- if(hasMultTerms){
- var multR = t.readSB(numBits) / 256;
- var multG = t.readSB(numBits) / 256;
- var multB = t.readSB(numBits) / 256;
- var multA = withAlpha ? t.readSB(numBits) / 256 : 1;
- }else{ var multR = multG = multB = multA = 1; }
- if(hasAddTerms){
- var addR = t.readSB(numBits);
- var addG = t.readSB(numBits);
- var addB = t.readSB(numBits);
- var addA = withAlpha ? t.readSB(numBits) : 0;
- }else{ var addR = addG = addB = addA = 0; }
- var cxForm = {
- multR: multR, multG: multG, multB: multB, multA: multA,
- addR: addR, addG: addG, addB: addB, addA: addA
- }
- t.align();
- return cxform;
- },
-
- tell: function(){
- return this._offset;
- },
-
- seek: function(offset, absolute){
- this._offset = (absolute ? 0 : this._offset) + offset;
- return this;
- },
-
- reset: function(){
- this._offset = 0;
- this.align();
- return this;
- },
-
- align: function(){
- this._bitBuffer = null;
- this._bitOffset = 8;
- return this;
- }
- };
-})();
View
481 src/SvgRenderer.js
@@ -1,481 +0,0 @@
-/*
- * Gordon: An open source Flash™ runtime written in pure JavaScript
- *
- * Copyright (c) 2010 Tobias Schneider
- * Gordon is freely distributable under the terms of the MIT license.
- */
-
-(function(){
- var NS_SVG = "http://www.w3.org/2000/svg";
- var NS_XLINK = "http://www.w3.org/1999/xlink";
-
- var _g = Gordon;
- var _d = document;
- var _buttonMask = 0;
-
- _g.SvgRenderer = function(width, height, viewWidth, viewHeight, quality, scale, bgcolor){
- var t = this;
- t.width = width;
- t.height = height;
- t.viewWidth = viewWidth;
- t.viewHeight = viewHeight;
- t.quality = null;
- t.scale = scale || _g.scaleValues.DEFAULT;
- t.bgcolor = null;
- t._dictionary = {};
- t._displayList = {};
- t._eventTarget = null;
- var n = t._node = t._createElement("svg");
- var attributes = {
- width: width,
- height: height
- };
- if(viewWidth && viewHeight && (width != viewWidth || height != viewHeight)){
- var viewBox = [0, 0, viewWidth, viewHeight];
- attributes.viewBox = viewBox.toString();
- if(scale == _g.scaleValues.EXACT_FIT){ attributes.preserveAspectRatio = "none"; }
- }
- t._setAttributes(n, attributes);
- t._defs = n.appendChild(t._createElement("defs"));
- t._screen = n.appendChild(t._createElement('g'));
- t._currentDefId = 0;
- t._setQuality(quality || _g.qualityValues.HIGH);
- if(bgcolor){ t.setBgcolor(bgcolor); }
- };
- _g.SvgRenderer.prototype = {
- _createElement: function(name){
- return _d.createElementNS(NS_SVG, name);
- },
-
- _setAttributes: function(node, attributes, namespace){
- for(var name in attributes){
- var value = attributes[name];
- name = name == "className" ? "class" : name.replace(/_/g, '-');
- if(namespace){ node.setAttributeNS(namespace, name, value); }
- else{ node.setAttribute(name, value); }
- }
- return node;
- },
-
- _setQuality: function(quality){
- var q = _g.qualityValues;
- var t = this;
- switch(quality){
- case q.LOW:
- var attributes = {
- shape_rendering: "crispEdges",
- image_rendering: "optimizeSpeed",
- text_rendering: "optimizeSpeed",
- color_rendering: "optimizeSpeed"
- }
- break;
- case q.AUTO_LOW:
- case q.AUTO_HIGH:
- var attributes = {
- shape_rendering: "auto",
- image_rendering: "auto",
- text_rendering: "auto",
- color_rendering: "auto"
- }
- break;
- case q.MEDIUM:
- var attributes = {
- shape_rendering: "optimizeSpeed",
- image_rendering: "optimizeSpeed",
- text_rendering: "optimizeLegibility",
- color_rendering: "optimizeSpeed"
- }
- break;
- case q.HIGH:
- var attributes = {
- shape_rendering: "geometricPrecision",
- image_rendering: "auto",
- text_rendering: "geometricPrecision",
- color_rendering: "optimizeQuality"
- }
- break;
- case q.BEST:
- var attributes = {
- shape_rendering: "geometricPrecision",
- image_rendering: "optimizeQuality",
- text_rendering: "geometricPrecision",
- color_rendering: "optimizeQuality"
- }
- break;
- }
- t._setAttributes(t._screen, attributes);
- t.quality = quality;
- return t;
- },
-
- getNode: function(){
- return this._node;
- },
-
- setBgcolor: function(rgb){
- var t = this;
- if(!t.bgcolor){
- t._node.style.background = _color2string(rgb);
- t.bgcolor = rgb;
- }
- return t;
- },
-
- defineObject: function(object){
- var type = object.type;
- var t = this;
- var node = null;
- var id = object.id;
- var attributes = {id: type + id};
- switch(type){
- case "shape":
- var segments = object.segments;
- if(segments){
- var node = t._createElement('g');
- segments.forEach(function(segment){
- node.appendChild(t._buildShape(segment));
- });
- }else{ var node = t._buildShape(object); }
- break;
- case "image":
- var node = t._createElement("image");
- t._setAttributes(node, {href: object.uri}, NS_XLINK);
- attributes.width = object.width;
- attributes.height = object.height;
- break;
- case "button":
- var node = t._createElement('g');
- var activeArea = t._createElement('g');
- var states = object.states;
- var b = _g.buttonStates;
- for(var s in states){
- var display = s == b.HIT ? activeArea : node.appendChild(t._createElement('g'));
- t._setAttributes(display, {
- className: "state" + s,
- opacity: s == b.UP ? 1 : 0
- });
- var filter = object.filter;
- var list = states[s];
- for(var depth in list){
- if(filter){
- var character = _cloneCharacter(list[depth]);
- character.filter = filter;
- }else{ var character = list[depth]; }
- display.appendChild(t._buildCharacter(character));
- }
- }
- node.appendChild(activeArea);
- break;
- case "font":
- var info = object.info;
- if(info){
- var node = t._createElement("font");
- var faceNode = node.appendChild(t._createElement("font-face"));
- t._setAttributes(faceNode, {font_family: info.name});
- var glyphs = object.glyphs;
- var codes = info.codes;
- glyphs.forEach(function(glyph, i){
- var glyphNode = node.appendChild(t._createElement("glyph"));
- t._setAttributes(glyphNode, {
- unicode: String.fromCharCode(codes[i]),
- d: glyph.commands.join(' ')
- });
- });
- }
- break;
- case "text":
- var node = t._createElement('g');
- var strings = object.strings;
- strings.forEach(function(string){
- var textNode = node.appendChild(t._createElement("text"));
- var entries = string.entries;
- var advances = [];
- var font = t._dictionary[string.font].object;
- var info = font.info;
- var codes = info.codes
- var characters = [];
- var x = string.x;
- entries.forEach(function(entry){
- advances.push(x);
- characters.push(String.fromCharCode(codes[entry.index]));
- x += entry.advance;
- });
- t._setAttributes(textNode, {
- font_family: info.name,
- font_size: string.size,
- fill: _color2string(string.fill),
- x: advances.join(' '),
- y: string.y
- });
- textNode.appendChild(_d.createTextNode(characters.join('')));
- });
- attributes.transform = _matrix2string(object.matrix);
- break;
- case "filter":
- var node = t._createElement("filter");
- var cxform = object.cxform;
- if(cxform){
- var feNode = node.appendChild(t._createElement("feColorMatrix"));
- t._setAttributes(feNode, {
- type: "matrix",
- values: _cxform2string(cxform)
- });
- }
- break;
- }
- if(node){
- t._setAttributes(node, attributes);
- t._defs.appendChild(node);
- t._dictionary[id] = {
- object: object,
- node: node
- }
- }
- return t;
- },
-
- _buildShape: function(shape){
- var t = this;
- var node = t._createElement("path");
- var fill = shape.fill;
- var stroke = shape.stroke;
- var attributes = {d: shape.commands.join(' ')};
- if(fill){
- if(fill.type){
- t._defineFill(fill);
- attributes.fill = "url(#" + fill.type + t._currentDefId + ')';
- }else{ attributes.fill = _color2string(fill); }
- attributes.fill_rule = "evenodd";
- }else{ attributes.fill = "none"; }
- if(stroke){
- attributes.stroke = _color2string(stroke.color);
- attributes.stroke_width = Math.max(stroke.width, 1);
- attributes.stroke_linecap = attributes.stroke_linejoin = "round";
- }
- t._setAttributes(node, attributes);
- return node;
- },
-
- _defineFill: function(fill){
- var type = fill.type;
- var t = this;
- var attributes = {id: type + (++t._currentDefId)};
- switch(type){
- case "linear":
- case "radial":
- var node = t._createElement(type + "Gradient");
- attributes.gradientUnits = "userSpaceOnUse";
- attributes.gradientTransform = _matrix2string(fill.matrix);
- if("linear" == type){
- attributes.x1 = -819.2;
- attributes.x2 = 819.2;
- }else{
- attributes.cx = attributes.cy = 0;
- attributes.r = 819.2;
- }
- var s = _g.spreadModes;
- switch(fill.spread){
- case s.REFLECT:
- attributes.spreadMethod = "reflect";
- break;
- case s.REPEAT:
- attributes.spreadMethod = "repeat";
- break;
- }
- var i = _g.interpolationModes;
- if(fill.interpolation == i.LINEAR_RGB){ attributes.color_interpolation = "linearRGB"; }
- var stops = fill.stops;
- stops.forEach(function(stop){
- var stopNode = node.appendChild(t._createElement("stop"));
- t._setAttributes(stopNode, {
- offset: stop.offset,
- stop_color: _color2string(stop.color)
- });
- });
- break;
- case "pattern":
- var node = t._createElement("pattern");
- var useNode = node.appendChild(t._createElement("use"));
- var img = fill.image;
- t._setAttributes(useNode, {href: "#image" + img.id}, NS_XLINK);
- attributes.patternUnits = "userSpaceOnUse";
- attributes.patternTransform = _matrix2string(fill.matrix);
- attributes.width = img.width;
- attributes.height = img.height;
- break;
- }
- t._setAttributes(node, attributes);
- t._defs.appendChild(node);
- return t;
- },
-
- placeCharacter: function(character){
- var depth = character.depth;
- var t = this;
- var d = t._displayList;
- var replace = d[depth];
- if(!replace || replace.character !== character){
- var node = t._buildCharacter(character);
- var s = t._screen;
- if(replace && replace !== character){ t.removeCharacter(depth); }
- if(1 == depth){ s.insertBefore(node, s.firstChild); }
- else{
- var nextDepth = 0;
- for(var entry in d){
- if(entry > depth){
- nextDepth = entry;
- break;
- }
- }
- if(nextDepth){ s.insertBefore(node, d[nextDepth].node); }
- else{ s.appendChild(node); }
- }
- d[depth] = {
- character: character,
- node: node
- };
- }
- return t;
- },
-
- _buildCharacter: function(character){
- var t = this;
- var d = t._dictionary;
- var object = d[character.object].object;
- var type = object.type;
- switch(type){
- case "button":
- var node = d[character.object].node.cloneNode(true);
- var b = _g.buttonStates;
- var displayMap = {};
- for(var i in b){
- var state = b[i];
- displayMap[state] = node.getElementsByClassName("state" + state)[0];
- }
- var m = _g.mouseButtons;
- var isMouseOver = false;
- var mouseupHandle = function(event){
- if(!(_buttonMask & m.LEFT)){
- if(isMouseOver){
- setState(b.OVER);
- object.action();
- }else{ setState(b.UP); }
- _d.removeEventListener("mouseup", mouseupHandle, false);
- t.eventTarget = null;
- }
- return false;
- };
- with(displayMap[b.HIT]){
- onmouseover = function(event){
- isMouseOver = true;
- if(!t.eventTarget){
- if(_buttonMask & m.LEFT){ this.onmousedown(event); }
- else{ setState(b.OVER); }
- }
- return false;
- };
- onmouseout = function(event){
- isMouseOver = false;
- if(!t.eventTarget){ setState(this == t.eventTarget ? b.OVER : b.UP); }
- return false;
- };
- onmousedown = function(event){
- if(_buttonMask & m.LEFT){
- setState(b.DOWN);
- _d.addEventListener("mouseup", mouseupHandle, false);
- t.eventTarget = this;
- }
- return false;
- };
- onmouseup = function(event){
- setState(b.OVER);
- return false;
- };
- }
- var currentState = b.UP;
- var setState = function(state){
- t._setAttributes(displayMap[currentState], {opacity: 0});
- t._setAttributes(displayMap[state], {opacity: 1});
- currentState = state;
- };
- break;
- default:
- var node = t._createElement("use");
- t._setAttributes(node, {href: "#" + type + object.id}, NS_XLINK);
- }
- var filter = character.filter;
- if(filter){ attributes.filter = "url(#filter" + filter.id + ')'; }
- t._setAttributes(node, {
- id: "character" + character.id * -1,
- className: "depth" + character.depth,
- transform: _matrix2string(character.matrix)
- });
- return node;
- },
-
- removeCharacter: function(depth){
- var d = this._displayList;
- var s = this._screen;
- s.removeChild(d[depth].node);
- delete d[depth];
- return this;
- },
-
- toggleQuality: function(){
- var t = this;
- var q = _g.qualityValues;
- switch(t.quality){
- case q.LOW:
- t._setQuality(q.HIGH);
- break;
- case q.AUTO_LOW:
- t._setQuality(q.AUTO_HIGH);
- break;
- case q.AUTO_HIGH:
- t._setQuality(q.AUTO_LOW);
- break;
- case q.HIGH:
- t._setQuality(q.LOW);
- break;
- }
- return t;
- }
- };
-
- function _color2string(color){
- if("string" == typeof color){ return color.match(/^([0-9a-z]{1,2}){3}$/i) ? color : null; }
- with(color){
- return "rgb(" + [r, g, b] + ')';
- }
- }
-
- function _matrix2string(matrix){
- with(matrix){
- return "matrix(" + [scaleX, skewX, skewY, scaleY, moveX, moveY] + ')';
- }
- }
-
- function _cxform2string(cxform){
- with(cxform){
- return [multR, 0, 0, 0, addR, 0, multG, 0, 0, addG, 0, 0, multB, 0, addB, 0, 0, 0, multA, addA].toString();
- }
- }
-
- function _cloneCharacter(character){
- with(character){
- return {
- object: object,
- depth: depth,
- matrix: matrix,
- cxform: character.cxform
- };
- }
- }
-
- _d.addEventListener("mousedown", function(event){
- _buttonMask |= 0x01 << event.button;
- }, true);
- _d.addEventListener("mouseup", function(event){
- _buttonMask ^= 0x01 << event.button;
- }, true);
-})();
View
728 src/_parser.js
@@ -1,728 +0,0 @@
-/*
- * Gordon: An open source Flash™ runtime written in pure JavaScript
- *
- * Copyright (c) 2010 Tobias Schneider
- * Gordon is freely distributable under the terms of the MIT license.
- */
-
-importScripts("../gordon.js");
-
-(function(){
- var _g = Gordon;
- var _t2p = _g.twips2px;
-
- onmessage = function(e){
- Parser.parse(e.data);
- };
-
- (function(){
- var _s = _currentFrame = null;
- var _dictionary = {};
- var _currentCharacterId = 0;
- var _jpegTables = null;
-
- Parser = {
- parse: function(data){
- _s = new _g.Stream(data);
- var h = _g.tagHandlers;
- var f = _g.tagCodes.SHOW_FRAME;
- do{
- _currentFrame = {
- type: "frame",
- displayList: {}
- };
- do{
- var header = _s.readUI16();
- var code = header >> 6;
- var length = header & 0x3f;
- if(length >= 0x3f){ length = _s.readUI32(); }
- var handler = h[code];
- if(this[handler]){ this[handler](_s.tell(), length); }
- else{ _s.seek(length); }
- }while(code && code != f);
- }while(code);
- return this;
- },
-
- handleShowFrame: function(){
- _register(_currentFrame);
- return this;
- },
-
- handleDefineShape: function(){
- var id = _s.readUI16();
- var bounds = _s.readRect();
- var t = this;
- var fillStyles = t._readFillStyleArray();
- var lineStyles = t._readLineStyleArray();
- var numFillBits = _s.readUB(4);
- var numLineBits = _s.readUB(4);
- var segment = [];
- var isFirst = true;
- var edges = [];
- var leftFill = rightFill = fsOffset = lsOffset = 0;
- var leftFillEdges = {};
- var rightFillEdges = {};
- var i = line = 0;
- var lineEdges = {};
- var c = _g.styleChangeStates;
- var x1 = y1 = x2 = y2 = 0;
- var countFillChanges = countLineChanges = 0;
- var useSinglePath = true;
- do{
- var type = _s.readUB(1);
- var flags = null;
- if(type){
- var isStraight = _s.readBool();
- var numBits = _s.readUB(4) + 2;
- x1 = x2, y1 = y2;
- var cx = cy = null;
- if(isStraight){
- var isGeneral = _s.readBool();
- if(isGeneral){
- x2 += _t2p(_s.readSB(numBits));
- y2 += _t2p(_s.readSB(numBits));
- }else{
- var isVertical = _s.readBool();
- if(isVertical){ y2 += _t2p(_s.readSB(numBits)); }
- else{ x2 += _t2p(_s.readSB(numBits)); }
- }
- }else{
- cx = x1 + _t2p(_s.readSB(numBits));
- cy = y1 + _t2p(_s.readSB(numBits));
- x2 = cx + _t2p(_s.readSB(numBits));
- y2 = cy + _t2p(_s.readSB(numBits));
- }
- x2 = Math.round(x2 * 100) / 100;
- y2 = Math.round(y2 * 100) / 100;
- segment.push({i: i++, f: isFirst, x1: x1, y1: y1, cx: cx, cy: cy, x2: x2, y2: y2});
- isFirst = false;
- }else{
- if(segment.length){
- Array.prototype.push.apply(edges, segment);
- if(leftFill){
- var index = fsOffset + leftFill;
- var list = leftFillEdges[index];
- if(!list){ list = leftFillEdges[index] = []; }
- segment.forEach(function(edge){
- var e = _cloneEdge(edge);
- e.i = i++;
- var tx1 = e.x1;
- var ty1 = e.y1;
- e.x1 = e.x2;
- e.y1 = e.y2;
- e.x2 = tx1;
- e.y2 = ty1;
- list.push(e);
- });
- }
- if(rightFill){
- var index = fsOffset + rightFill;
- var list = rightFillEdges[index];
- if(!list){ list = rightFillEdges[index] = []; }
- Array.prototype.push.apply(list, segment);
- }
- if(line){
- var index = lsOffset + line;
- var list = lineEdges[index];
- if(!list){ list = lineEdges[index] = []; }
- Array.prototype.push.apply(list, segment);
- }
- segment = [];
- isFirst = true;
- }
- var flags = _s.readUB(5);
- if(flags){
- if(flags & c.MOVE_TO){
- var numBits = _s.readUB(5);
- x2 = _t2p(_s.readSB(numBits));
- y2 = _t2p(_s.readSB(numBits));
- }
- if(flags & c.LEFT_FILL_STYLE){
- leftFill = _s.readUB(numFillBits);
- countFillChanges++;
- }
- if(flags & c.RIGHT_FILL_STYLE){
- rightFill = _s.readUB(numFillBits);
- countFillChanges++;
- }
- if(flags & c.LINE_STYLE){
- line = _s.readUB(numLineBits);
- countLineChanges++;
- }
- if((leftFill && rightFill) || (countFillChanges + countLineChanges) > 2){
- useSinglePath = false;
- }
- if(flags & c.NEW_STYLES){
- Array.prototype.push.apply(fillStyles, t._readFillStyleArray());
- Array.prototype.push.apply(lineStyles, t._readLineStyleArray());
- numFillBits = _s.readUB(4);
- numLineBits = _s.readUB(4);
- fsOffset = fillStyles.length;
- lsOffset = lineStyles.length;
- useSinglePath = false;
- }
- }
- }
- }while(type || flags);
- _s.align();
- var shape = null;
- if(useSinglePath){
- var fill = leftFill || rightFill;
- var fillStyle = fill ? fillStyles[fsOffset + fill - 1] : null;
- var lineStyle = lineStyles[lsOffset + line - 1];
- shape = _buildShape(edges, fillStyle, lineStyle);
- shape.id = id;
- shape.bounds = bounds;
- }else{
- var fillShapes = [];
- var i = fillStyles.length;
- while(i--){
- var fill = i + 1;
- fillEdges = [];
- var list = leftFillEdges[fill];
- if(list){ Array.prototype.push.apply(fillEdges, list); }
- list = rightFillEdges[fill];
- if(list){ Array.prototype.push.apply(fillEdges, list); }
- var edgeMap = {};
- fillEdges.forEach(function(edge){
- var key = _calcPointKey(edge.x1, edge.y1);
- var list = edgeMap[key];
- if(!list){ list = edgeMap[key] = []; }
- list.push(edge);
- });
- var pathEdges = [];
- var countFillEdges = fillEdges.length;
- for(var j = 0; j < countFillEdges && !pathEdges[countFillEdges - 1]; j++){
- var edge = fillEdges[j];
- if(!edge.c){
- var segment = [];
- var firstKey = _calcPointKey(edge.x1, edge.y1);
- var isUsed = {};
- do{
- segment.push(edge);
- isUsed[edge.i] = true;
- var key = _calcPointKey(edge.x2, edge.y2);
- if(key == firstKey){
- var k = segment.length;
- while(k--){ segment[k].c = true; }
- Array.prototype.push.apply(pathEdges, segment);
- break;
- }
- var list = edgeMap[key];
- if (!(list && list.length)){ break; }
- var favEdge = fillEdges[j + 1];
- var nextEdge = null;
- for(var k = 0; list[k]; k++){
- var entry = list[k];
- if(entry == favEdge && !entry.c){
- list.splice(k, 1);
- nextEdge = entry;
- }
- }
- if(!nextEdge){
- for(var k = 0; list[k]; k++){
- var entry = list[k];
- if(!(entry.c || isUsed[entry.i])){ nextEdge = entry; }
- }
- }
- edge = nextEdge;
- }while(edge);
- }
- }
- if(pathEdges.length){
- shape = _buildShape(pathEdges, fillStyles[i]);
- shape.index = pathEdges.pop().i;
- fillShapes.push(shape);
- }
- }
- var strokeShapes = [];
- var i = lineStyles.length;
- while(i--){
- var pathEdges = lineEdges[i + 1];
- if(pathEdges){
- shape = _buildShape(pathEdges, null, lineStyles[i]);
- shape.index = pathEdges.pop().i;
- strokeShapes.push(shape);
- }
- }
- var segments = fillShapes.concat(strokeShapes);
- segments.sort(function(a, b){
- return a.index - b.index;
- });
- if(segments.length > 1){
- shape = {
- type: "shape",
- id: id,
- bounds: bounds,
- segments: segments
- }
- }else{
- delete shape.index;
- shape.id = id;
- shape.bounds = bounds;
- }
- }
- _register(shape);
- return t;
- },
-
- _readFillStyleArray: function(){
- var numStyles = _s.readUI8();
- if(0xff == numStyles){ numStyles = _s.readUI16(); }
- var styles = [];
- var i = numStyles;
- while(i--){
- var type = _s.readUI8();
- var f = _g.fillStyleTypes;
- switch(type){
- case f.SOLID:
- styles.push(_s.readRgb());
- break;
- case f.LINEAR_GRADIENT:
- case f.RADIAL_GRADIENT:
- var style = {
- type: type == f.LINEAR_GRADIENT ? "linear" : "radial",
- matrix: _s.readMatrix(),
- spread: _s.readUB(2),
- interpolation: _s.readUB(2),
- stops: []
- };
- var numStops = _s.readUB(4);
- var stops = style.stops;
- var j = numStops;
- while(j--){ stops.push({
- offset: _s.readUI8() / 255,
- color: _s.readRgb()
- }); }
- styles.push(style);
- break;
- case f.REPEATING_BITMAP:
- case f.CLIPPED_BITMAP:
- var imgId = _s.readUI16();
- var img = _dictionary[imgId];
- var matrix = _s.readMatrix();
- if(img){
- with(matrix){
- scaleX = _t2p(scaleX);
- scaleY = _t2p(scaleY);
- skewX = _t2p(skewX);
- skewY = _t2p(skewY);
- }
- styles.push({
- type: "pattern",
- image: img,
- matrix: matrix
- });
- }else{ styles.push(null); }
- break;
- }
- }
- return styles;
- },
-
- _readLineStyleArray: function(){
- var numStyles = _s.readUI8();
- if(0xff == numStyles){ numStyles = _s.readUI16(); }
- var styles = [];
- var i = numStyles;
- while(i--){ styles.push({
- width: _t2p(_s.readUI16()),
- color: _s.readRgb()
- }); }
- return styles;
- },
-
- handlePlaceObject: function(offset, length){
- var id = _s.readUI16();
- var depth = _s.readUI16();
- var character = {
- id: --_currentCharacterId,
- object: id,
- depth: depth,
- matrix: _s.readMatrix()
- };
- if(_s.tell() - offset != length){
- _register({
- type: "filter",
- id: _currentCharacterId,
- cxform: _s.readCxform()
- });
- character.filter = _currentCharacterId;
- }
- _currentFrame.displayList[depth] = character;
- return this;
- },
-
- handleRemoveObject: function(){
- var id = _s.readUI16();
- var depth = _s.readUI16();
- _currentFrame.displayList[depth] = null;
- return this;
- },
-
- handleDefineBits: function(offset, length, withTables){
- var id = _s.readUI16();
- var jpg = this._readJpeg(length - 2);
- if(withTables){ var data = _encodeBase64(jpg.data); }
- else{
- var header = _jpegTables.substr(0, _jpegTables.length - 2);
- var data = _encodeBase64(header + jpg.data.substr(2));
- }
- _register({
- type: "image",
- id: id,
- uri: "data:image/jpeg;base64," + data,
- width: jpg.width,
- height: jpg.height
- });
- return this;
- },
-
- _readJpeg: function(length){
- var data = _s.readString(length);
- var s = new _g.Stream(data);
- var width = height = 0;
- for(var i = 0; data[i]; i += 2){
- var header = s.readUI16(true);
- var length = s.readUI16(true);
- if(header == 0xffc0){
- s.seek(1);
- var height = s.readUI16(true);
- var width = s.readUI16(true);
- break;
- }
- }
- return {
- data: data,
- width: width,
- height: height
- };
- },
-
- handleDefineButton: function(){
- var id = _s.readUI16();
- var states = {};
- do{
- var flags = _s.readUI8();
- if(flags){
- var object = _s.readUI16();
- var depth = _s.readUI16();
- var character = {
- id: --_currentCharacterId,
- object: object,
- depth: depth,
- matrix: _s.readMatrix()
- }
- var state = 0x01;
- while(state <= 0x08){
- if(flags & state){
- var list = states[state];
- if(!list){ list = states[state] = {}; }
- list[depth] = character;
- }
- state <<= 1;
- }
- }
- }while(flags);
- _register({
- type: "button",
- id: id,
- states: states,
- action: this._readAction()
- });
- return this;
- },
-
- _readAction: function(){
- var stack = [];
- do{
- var code = _s.readUI8();
- var length = code > 0x80 ? _s.readUI16() : 0;
- var a = _g.actionCodes;
- switch(code){
- case a.PLAY:
- stack.push("t.play()");
- break;
- case a.STOP:
- stack.push("t.stop()");
- break;
- case a.NEXT_FRAME:
- stack.push("t.nextFrame()");
- break;
- case a.PREVIOUS_FRAME:
- stack.push("t.prevFrame()");
- break;
- case a.GOTO_FRAME:
- var frame = _s.readUI16();
- stack.push("t.goto(" + frame + ')');
- break;
- case a.GET_URL:
- var url = _s.readString();
- var target = _s.readString();
- stack.push("t.getUrl('" + url + "', '" + target + "')");
- break;
- case a.TOGGLE_QUALITY:
- stack.push("t.toggleQuality()");
- break;
- default:
- _s.seek(length);
- }
- }while(code);
- return "function(t){" + stack.join(';') + "}";
- },
-
- handleJpegTables: function(offset, length){
- _jpegTables = _s.readString(length);
- return this;
- },
-
- handleSetBackgroundColor: function(){
- _currentFrame.bgcolor = _s.readRgb();
- return this;
- },
-
- handleDefineFont: function(){
- var id = _s.readUI16();
- var numGlyphs = _s.readUI16() / 2;
- _s.seek(numGlyphs * 2 - 2);
- var c = _g.styleChangeStates;
- var glyphs = [];
- var i = numGlyphs;
- while(i--){
- var numFillBits = _s.readUB(4);
- var numLineBits = _s.readUB(4);
- var x = y = 0;
- var commands = [];
- do{
- var type = _s.readUB(1);
- var flags = null;
- if(type){
- var isStraight = _s.readBool();
- var numBits = _s.readUB(4) + 2;
- if(isStraight){
- var isGeneral = _s.readBool();
- if(isGeneral){
- x += _s.readSB(numBits);
- y += _s.readSB(numBits);
- commands.push('L', x, -y);
- }else{
- var isVertical = _s.readBool();
- if(isVertical){
- y += _s.readSB(numBits);
- commands.push('V', -y);
- }else{
- x += _s.readSB(numBits);
- commands.push('H', x);
- }
- }
- }else{
- var cx = x + _s.readSB(numBits);
- var cy = y + _s.readSB(numBits);
- x = cx + _s.readSB(numBits);
- y = cy + _s.readSB(numBits);
- commands.push('Q', cx, -cy, x, -y);
- }
- }else{
- var flags = _s.readUB(5);
- if(flags){
- if(flags & c.MOVE_TO){
- var numBits = _s.readUB(5);
- x = _s.readSB(numBits);
- y = _s.readSB(numBits);
- commands.push('M', x, -y);
- }
- if(flags & c.LEFT_FILL_STYLE || flags & c.RIGHT_FILL_STYLE){ _s.readUB(numFillBits); }
- }
- }
- }while(type || flags);
- _s.align();
- glyphs.push({commands: commands});
- }
- _register({
- type: "font",
- id: id,
- glyphs: glyphs
- });
- return this;
- },
-
- handleDefineText: function(){
- var id = _s.readUI16();
- var text = {
- type: "text",
- id: id,
- bounds: _s.readRect(),
- matrix: _s.readMatrix(),
- strings: []
- };
- var numGlyphBits = _s.readUI8();
- var numAdvBits = _s.readUI8();
- var font = fill = null;
- var x = y = size = 0;
- var string = null;
- var strings = text.strings;
- do{
- var header = _s.readUB(8);
- if(header){
- var type = header >> 7;
- if(type){
- var flags = header & 0x0f;
- if(flags){
- var string = {};
- var f = _g.textStyleFlags;
- if(flags & f.HAS_FONT){ font = _s.readUI16(); }
- if(flags & f.HAS_COLOR){ fill = _s.readRgb(); }
- if(flags & f.HAS_XOFFSET){ x = _t2p(_s.readSI16()); }
- if(flags & f.HAS_YOFFSET){ y = _t2p(_s.readSI16()); }
- if(flags & f.HAS_FONT){ size = _t2p(_s.readUI16()); }
- }
- string = {
- font: font,
- fill: fill,
- x: x,
- y: y,
- size: size
- };
- strings.push(string);
- }else{
- var numGlyphs = header & 0x7f;
- var entries = string.entries = [];
- var i = numGlyphs;
- while(i--){
- var entry = {};
- entry.index = _s.readUB(numGlyphBits);
- entry.advance = _t2p(_s.readSB(numAdvBits));
- entries.push(entry);
- }
- _s.align();
- }
- }
- }while(header);
- _register(text);
- return this;
- },
-
- handleDoAction: function(){
- _currentFrame.action = this._readAction();
- return this;
- },
-
- handleDefineFontInfo: function(){
- var fontId = _s.readUI16();
- var font = _dictionary[fontId];
- var f = font.info = {
- name: _s.readString(_s.readUI8()),
- isSmall: _s.readBool(3),
- isShiftJis: _s.readBool(),
- isAnsi: _s.readBool(),
- isItalic: _s.readBool(),
- isBold: _s.readBool(),
- codes: []
- };
- var useWideCodes = _s.readBool();
- var codes = f.codes;
- var i = font.glyphs.length;
- while(i--){
- var code = useWideCodes ? _s.readUI16() : _s.readUI8();
- codes.push(code);
- }
- _register(font);
- return this;
- },
-
- handleDefineBitsJpeg2: function(offset, length){
- return this.handleDefineBits(offset, length, true);
- },
-
- handleDefineShape2: function(){
- return this.handleDefineShape.apply(this, arguments);
- },
-
- handleDefineButtonCxform: function(){
- var buttonId = _s.readUI16();
- var button = _dictionary[buttonId];
- _register({
- id: button.id,
- type: "filter",
- cxform: _s.readCxform()
- });
- button.filter = _currentCharacterId;
- _register(button);
- return this;
- },
-
- handleProtect: function(offset, length){
- _s.seek(length);
- return this;
- }
- };
-
- var _useJson = _g.USE_NATIVE_JSON;
-
- var _register = function(object){
- postMessage(_useJson ? JSON.stringify(object) : object);
- _dictionary[object.id] = object;
- }
-
- function _cloneEdge(edge){
- with(edge){
- return {i: i, f: f, x1: x1, y1: y1, cx: cx, cy: cy, x2: x2, y2: y2};
- }
- }
-
- function _buildShape(edges, fill, stroke){
- var x1 = y1 = x2 = y2 = 0;
- var commands = [];
- edges.forEach(function(edge){
- x1 = edge.x1;
- y1 = edge.y1;
- if(x1 != x2 || y1 != y2){ commands.push('M', x1, y1); }
- x2 = edge.x2;
- y2 = edge.y2;
- if(null == edge.cx || null == edge.cy){
- if(x2 == x1){ commands.push('V', y2); }
- else if(y2 == y1){ commands.push('H', x2); }
- else{ commands.push('L', x2, y2); }
- }else{ commands.push('Q', edge.cx, edge.cy, x2, y2); }
- });
- return {
- type: "shape",
- commands: commands,
- fill: fill,
- stroke: stroke
- };
- }
-
- function _calcPointKey(x, y){
- return (x + 50000) * 100000 + y;
- }
-
- var B64_DIGITS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
- function _encodeBase64(data){
- var byteNum = 0;
- var byte = prevByte = null;
- chars = [];
- for(var i = 0; data[i]; i++){
- byteNum = i % 3;
- byte = data.charCodeAt(i) & 0xff;
- switch(byteNum){
- case 0:
- chars.push(B64_DIGITS[byte >> 2]);
- break;
- case 1:
- chars.push(B64_DIGITS[((prevByte & 3) << 4) | (byte >> 4)]);
- break;
- case 2:
- chars.push(B64_DIGITS[((prevByte & 0x0f) << 2) | (byte >> 6)], B64_DIGITS[byte & 0x3f]);
- break;
- }
- prevByte = byte;
- }
- if(!byteNum){ chars.push(B64_DIGITS[(prevByte & 3) << 4], "=="); }
- else if (byteNum == 1){ chars.push(B64_DIGITS[(prevByte & 0x0f) << 2], '='); }
- return chars.join('');
- }
- })();
-})();
View
121 src/_base.js → src/base.js
@@ -1,37 +1,29 @@
-/*
- * Gordon: An open source Flash™ runtime written in pure JavaScript
- *
- * Copyright (c) 2010 Tobias Schneider
- * Gordon is freely distributable under the terms of the MIT license.
- */
-
-(function(){
- var _g = Gordon;
-
- _g.qualityValues = {
+var Gordon = {
+ qualityValues: {
LOW: "low",
AUTO_LOW: "autolow",
AUTO_HIGH: "autohigh",
MEDIUM: "medium",
HIGH: "high",
BEST: "best"
- };
- _g.scaleValues = {
- DEFAULT: "default",
+ },
+ scaleValues: {
+ SHOW_ALL: "showall",
NO_ORDER: "noorder",
EXACT_FIT: "exactfit"
- };
- _g.validSignatures = {
+ },
+ validSignatures: {
SWF: "FWS",
COMPRESSED_SWF: "CWS"
- };
- _g.movieStates = {
+ },
+ readyStates: {
LOADING: 0,
- LOADED: 1,
- PLAYING: 2,
- STOPPED: 3
- };
- _g.tagCodes = {
+ UNINITIALIZED: 1,
+ LOADED: 2,
+ INTERACTIVE: 3,
+ COMPLETE: 4
+ },
+ tagCodes: {
END: 0,
SHOW_FRAME: 1,
DEFINE_SHAPE: 2,
@@ -96,17 +88,10 @@
START_SOUND2: 89,
DEFINE_BITS_JPEG4: 90,
DEFINE_FONT4: 91
- };
- _g.tagNames = {};
- _g.tagHandlers = {};
- for(var name in _g.tagCodes){
- var code = _g.tagCodes[name];
- _g.tagNames[code] = name;
- _g.tagHandlers[code] = "handle" + name.toLowerCase().replace(/(^|_)([a-z])/g, function(match, p1, p2){
- return p2.toUpperCase();
- });
- }
- _g.fillStyleTypes = {
+ },
+ tagNames: {},
+ tagHandlers: {},
+ fillStyleTypes: {
SOLID: 0x00,
LINEAR_GRADIENT: 0x10,
RADIAL_GRADIENT: 0x12,
@@ -115,41 +100,41 @@
CLIPPED_BITMAP: 0x41,
NON_SMOOTHED_REPEATING_BITMAP: 0x42,
NON_SMOOTHED_CLIPPED_BITMAP: 0x43
- };
- _g.spreadModes = {
+ },
+ spreadModes: {
PAD: 0,
REFLECT: 1,
REPEAT: 2
- };
- _g.interpolationModes = {
+ },
+ interpolationModes: {
RGB: 0,
LINEAR_RGB: 1
- };
- _g.styleChangeStates = {
+ },
+ styleChangeStates: {
MOVE_TO: 0x01,
LEFT_FILL_STYLE: 0x02,
RIGHT_FILL_STYLE: 0x04,
LINE_STYLE: 0x08,
NEW_STYLES: 0x10
- };
- _g.buttonStates = {
+ },
+ buttonStates: {
UP: 0x01,
OVER: 0x02,
DOWN: 0x04,
HIT: 0x08
- };
- _g.mouseButtons = {
+ },
+ mouseButtons: {
LEFT: 1,
RIGHT: 2,
MIDDLE: 3
- };
- _g.textStyleFlags = {
+ },
+ textStyleFlags: {
HAS_FONT: 0x08,
HAS_COLOR: 0x04,
HAS_XOFFSET: 0x01,
HAS_YOFFSET: 0x02
- };
- _g.actionCodes = {
+ },
+ actionCodes: {
PLAY: 0x06,
STOP: 0x07,
NEXT_FRAME: 0x04,
@@ -161,17 +146,37 @@
STOP_SOUNDS: 0x09,
TOGGLE_QUALITY: 0x08,
SET_TARGET: 0x08b
- };
- _g.urlTargets = {
+ },
+ urlTargets: {
SELF: "_self",
BLANK: "_blank",
PARENT: "_parent",
TOP: "_top"
- };
- _g.USE_NATIVE_JSON = !!self.JSON;
- _g.PX_IN_TWIPS = 20;
-
- _g.twips2px = function(twips){
- return twips / _g.PX_IN_TWIPS;
- };
-})();
+ },
+ bitmapFormats: {
+ COLORMAPPED: 3,
+ RGB15: 4,
+ RGB24: 5
+ },
+ PX_IN_TWIPS: 20
+};
+
+(function(){
+ var t = Gordon.tagCodes,
+ n = Gordon.tagNames,
+ h = Gordon.tagHandlers;
+ for(var name in t){
+ var code = t[name];
+ n[code] = name;
+ h[code] = "_handle" + name.toLowerCase().replace(/(^|_)([a-z])/g, function(match, p1, p2){
+ return p2.toUpperCase();
+ });
+ }
+}());
+
+var doc = global.document,
+ push = Array.prototype.push;
+
+function twips2px(twips){
+ return twips / Gordon.PX_IN_TWIPS;
+}
View
8 src/intro.js
@@ -0,0 +1,8 @@
+/*
+ * Gordon: An open source Flash™ runtime written in pure JavaScript
+ *
+ * Copyright (c) 2010 Tobias Schneider
+ * Gordon is freely distributable under the terms of the MIT license.
+ */
+
+(function(global){
View
199 src/movie.js
@@ -0,0 +1,199 @@
+(function(){
+ var s = Gordon.readyStates,
+ defaults = {
+ id: null,
+ width: 0,
+ height: 0,
+ autoplay: true,
+ loop: true,
+ quality: Gordon.qualityValues.HIGH,
+ scale: Gordon.scaleValues.SHOW_ALL,
+ bgcolor: null,
+ renderer: null,
+ onprogress: function(percent){},
+ onreadystatechange: function(state){},
+ onenterframe: function(frameNum){}
+ };
+
+ Gordon.Movie = function(url, options){
+ var t = this;
+ t.url = url;
+ for(var prop in defaults){ t[prop] = undefined != options[prop] ? options[prop] : defaults[prop]; }
+ if(!url){ throw new Error("URL of a SWF movie file must be passed as first argument"); }
+ t._startTime = +new Date;
+ t._readyState = s.UNINITIALIZED;
+ t._changeReadyState(t._readyState);
+ var xhr = new XMLHttpRequest();
+ xhr.open("GET", url, false);
+ xhr.overrideMimeType("text/plain; charset=x-user-defined");
+ xhr.onreadystatechange = function(){
+ if(xhr.readyState == 2){ t._changeReadyState(s.LOADING); }
+ }
+ xhr.send(null);
+ if(200 != xhr.status){ throw new Error("Unable to load " + url + " status: " + xhr.status); }
+ t._changeReadyState(s.LOADED);
+ var d = t._dictionary = {},
+ l = t._timeline = [];
+ t._framesLoaded = 0;
+ t._isPlaying = false;
+ t._currFrame = -1;
+ new Gordon.Parser(xhr.responseText, function(obj){
+ switch(obj.type){
+ case "header":
+ for(var prop in obj){ t['_' + prop] = obj[prop]; }
+ var f = t._frameSize,
+ frmWidth = f.right - f.left,
+ frmHeight = f.bottom - f.top;
+ if(!(t.width && t.height)){
+ t.width = frmWidth;
+ t.height = frmHeight;
+ }
+ var r = t.renderer = t.renderer || Gordon.SvgRenderer;
+ t._renderer = new r(t.width, t.height, frmWidth, frmHeight, t.quality, t.scale, t.bgcolor);
+ break;
+ case "frame":
+ var bgcolor = obj.bgcolor;
+ if(bgcolor && !t.bgcolor){
+ t._renderer.setBgcolor(bgcolor);
+ t.bgcolor = bgcolor;
+ }
+ var action = obj.action;
+ if(action){ eval("obj.action = function(){ (" + action + "(t)); }"); }
+ l.push(obj);
+ var f = ++t._framesLoaded;
+ t.onprogress(t.percentLoaded());
+ if(f == 1){
+ if(t.id){
+ var stage = doc.getElementById(t.id);
+ stage.innerHTML = '';
+ stage.appendChild(t._renderer.getNode());
+ t._changeReadyState(s.INTERACTIVE);
+ }
+ if(t.autoplay){ t.play(); }
+ else{ t.gotoFrame(0); }
+ }else if(f == t._frameCount){ t._changeReadyState(s.COMPLETE); }
+ break;
+ default:
+ t._renderer.defineObject(obj);
+ d[obj.id] = obj;
+ }
+ });
+ };
+ Gordon.Movie.prototype = {
+ _changeReadyState: function(state){
+ this._readyState = state;
+ this.onreadystatechange(state);
+ return this;
+ },
+
+ play: function(){
+ var t = this,
+ c = t._currFrame,
+ timeout = 1100 / t._frameRate;
+ t._isPlaying = true;
+ if(c < t._frameCount - 1){
+ if(t._framesLoaded >= c){ t.gotoFrame(c + 1); }
+ else{ timeout = 0; }
+ }else{
+ if(!t.loop){ return t.stop(); }
+ else{ t.gotoFrame(0); }
+ }
+ setTimeout(function(){
+ if(t._isPlaying){ t.play() };
+ }, timeout);
+ return t;
+ },
+
+ nextFrame: function(){
+ var t = this,
+ c = t._currFrame;
+ t.gotoFrame(c < t._frameCount - 1 ? c + 1 : 0);
+ return t;
+ },
+
+ gotoFrame: function gf(frameNum){
+ var t = this;
+ if(gf.caller !== t.play){ t.stop(); }
+ if(t._currFrame != frameNum){
+ if(frameNum < t._currFrame){ t._currFrame = -1; }
+ while(t._currFrame != frameNum){
+ var frame = t._timeline[++t._currFrame],
+ d = frame.displayList,
+ r = t._renderer;
+ for(var depth in d){
+ var character = d[depth];
+ if(character){ r.placeCharacter(character); }
+ else{ r.removeCharacter(depth); }
+ }
+ t.onenterframe(frameNum);
+ var action = frame.action;
+ if(action){ action(); }
+ }
+ }
+ return t;
+ },
+
+ stop: function(){
+ this._isPlaying = false;
+ return this;
+ },
+
+ prevFrame: function(){
+ var t = this,
+ c = t._currFrame;
+ t.gotoFrame(c > 0 ? c - 1 : t._frameCount - 1);
+ return t;
+ },
+
+ isPlaying: function(){
+ return this._isPlaying;
+ },
+
+ rewind: function(){
+ this.gotoFrame(0);
+ return this;
+ },
+
+ totalFrames: function(){
+ return this._frameCount;
+ },
+
+ percentLoaded: function(){
+ return Math.round((this._framesLoaded * 100) / this._frameCount);
+ },
+
+ currentFrame: function(){
+ return this._currFrame;
+ },
+
+ getURL: function(url, target){
+ var u = Gordon.urlTargets;
+ switch(target){
+ case u.BLANK:
+ global.open(url);
+ break;
+ case u.PARENT:
+ parent.location.href = url;
+ break;
+ case u.TOP:
+ top.location.href = url;
+ break;
+ default:
+ location.href = url;
+ }
+ return this;
+ },
+
+ toggleHighQuality: function thq(){
+ var o = thq._orig,
+ t = this,
+ q = t.quality;
+ if(o){
+ q = t.quality = o;
+ thq._orig = null;
+ }else{ t.quality = thq._orig = q; }
+ t._renderer.setQuality(q);
+ return t;
+ }
+ };
+}());
View
2  src/outro.js
@@ -0,0 +1,2 @@
+ global.Gordon = Gordon;
+}(self));
View
795 src/parser.js
@@ -0,0 +1,795 @@
+(function(){
+ var useNativeJson = !!global.JSON;
+
+ if(doc && global.Worker){
+ var scripts = doc.getElementsByTagName("script"),
+ regexp = /(^|.*\/)gordon.(min\.)?js$/,
+ src = "gordon.min.js",
+ i = scripts.length;
+ while(i--){
+ var match = regexp.exec(scripts[i].src);
+ if(match){
+ src = match[0];
+ break;
+ }
+ }
+ Gordon.Parser = function(data, ondata){
+ var t = this;
+ t.data = data;
+ t.ondata = ondata;
+ var w = t._worker = new Worker(src);
+ w.onerror = function(){};
+ w.onmessage = function(e){
+ t.ondata(useNativeJson ? JSON.parse(e.data) : e.data);
+ }
+ w.postMessage(data);
+ };
+ }else{
+ var s = currFrame = null,
+ dictionary = {},
+ currPrivateId = 0,
+ jpegTables = null;
+
+ Gordon.Parser = function(data, ondata){
+ if(ondata) { this.ondata = ondata; }
+ s = new Gordon.Stream(data);
+ var sign = s.readString(3),
+ v = Gordon.validSignatures;
+ if(sign != v.SWF && sign != v.COMPRESSED_SWF){ throw new Error(url + " is not a SWF movie file"); }
+ var version = s.readUI8(),
+ fileLen = s.readUI32();
+ if(sign == v.COMPRESSED_SWF){ s.decompress(); }
+ this.ondata({
+ type: "header",
+ version: version,
+ fileLength: fileLen,
+ frameSize: s.readRect(),
+ frameRate: s.readUI16() / 256,
+ frameCount: s.readUI16()
+ });
+ var h = Gordon.tagHandlers,
+ f = Gordon.tagCodes.SHOW_FRAME;
+ do{
+ currFrame = {
+ type: "frame",
+ displayList: {}
+ };
+ do{
+ var hdr = s.readUI16(),
+ code = hdr >> 6,
+ len = hdr & 0x3f;
+ if(len >= 0x3f){ len = s.readUI32(); }
+ var handl = h[code];
+ if(this[handl]){ this[handl](s.tell(), len); }
+ else{ s.seek(len); }
+ }while(code && code != f);
+ }while(code);
+ };
+ Gordon.Parser.prototype = {
+ ondata: function(data){
+ postMessage(useNativeJson ? JSON.stringify(data) : data);
+ },
+
+ _handleShowFrame: function(){
+ this.ondata(currFrame);
+ return this;
+ },
+
+ _handleDefineShape: function(){
+ var id = s.readUI16(),
+ bounds = s.readRect(),
+ t = this,
+ fillStyles = t._readFillStyleArray(),
+ lineStyles = t._readLineStyleArray(),
+ numFillBits = s.readUB(4),
+ numLineBits = s.readUB(4),
+ segment = [],
+ isFirst = true,
+ edges = [],
+ leftFill = rightFill = fsOffset = lsOffset = 0,
+ leftFillEdges = {},
+ rightFillEdges = {},
+ i = line = 0,
+ lineEdges = {},
+ c = Gordon.styleChangeStates,
+ x1 = y1 = x2 = y2 = 0,
+ countFillChanges = countLineChanges = 0,
+ useSinglePath = true;
+ do{
+ var type = s.readUB(1),
+ flags = null;
+ if(type){
+ var isStraight = s.readBool(),
+ numBits = s.readUB(4) + 2,
+ cx = cy = null;
+ x1 = x2, y1 = y2;
+ if(isStraight){