Repository: tobeytailor/gordon
Branch: main
Commit: 0deb62cf7702
Files: 16
Total size: 105.9 KB
Directory structure:
gitextract_4a59zi76/
├── .gitignore
├── MIT-LICENSE
├── README.md
├── Rakefile
├── build/
│ └── compiler.jar
└── src/
├── base.js
├── intro.js
├── movie.js
├── outro.js
├── parser.js
├── renderer/
│ ├── canvas.js
│ ├── css.js
│ ├── svg.js
│ ├── vml.js
│ └── webgl.js
└── stream.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
dist/
================================================
FILE: MIT-LICENSE
================================================
Copyright (c) 2010 Tobias Schneider
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
================================================
FILE: README.md
================================================
Gordon
======
#### An open source Flash™ runtime written in pure JavaScript ####
Visit the GitHub Wiki for more information: <http://wiki.github.com/tobeytailor/gordon/>
================================================
FILE: Rakefile
================================================
src_dir = 'src'
renderer_dir = File.join(src_dir, 'renderer')
dist_dir = 'dist'
build_dir = 'build'
base_files = [ 'base', 'stream', 'parser', 'movie' ].map { |file| File.join(src_dir, file + '.js') }
renderer_files = [ 'svg' ].map { |file| File.join(renderer_dir, file + '.js') }
build_files = base_files + renderer_files
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 'mkdir -p ' + dist_dir
sh 'cat ' + intro + ' > ' + output_file
sh 'for file in ' + build_files.join(' ') + "; do echo | cat $file - | sed 's/^/ /' >> " + 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
end
================================================
FILE: src/base.js
================================================
var win = window,
doc = win.document,
fromCharCode = String.fromCharCode,
push = Array.prototype.push,
min = Math.min,
max = Math.max;
Gordon = {
debug: false,
qualityValues: {
LOW: "low",
AUTO_LOW: "autolow",
AUTO_HIGH: "autohigh",
MEDIUM: "medium",
HIGH: "high",
BEST: "best"
},
scaleValues: {
SHOW_ALL: "showall",
NO_ORDER: "noorder",
EXACT_FIT: "exactfit"
},
validSignatures: {
SWF: "FWS",
COMPRESSED_SWF: "CWS"
},
readyStates: {
LOADING: 0,
UNINITIALIZED: 1,
LOADED: 2,
INTERACTIVE: 3,
COMPLETE: 4
},
tagCodes: {
END: 0,
SHOW_FRAME: 1,
DEFINE_SHAPE: 2,
PLACE_OBJECT: 4,
REMOVE_OBJECT: 5,
DEFINE_BITS: 6,
DEFINE_BUTTON: 7,
JPEG_TABLES: 8,
SET_BACKGROUND_COLOR: 9,
DEFINE_FONT: 10,
DEFINE_TEXT: 11,
DO_ACTION: 12,
DEFINE_FONT_INFO: 13,
DEFINE_SOUND: 14,
START_SOUND: 15,
DEFINE_BUTTON_SOUND: 17,
SOUND_STREAM_HEAD: 18,
SOUND_STREAM_BLOCK: 19,
DEFINE_BITS_LOSSLESS: 20,
DEFINE_BITS_JPEG2: 21,
DEFINE_SHAPE2: 22,
DEFINE_BUTTON_CXFORM: 23,
PROTECT: 24,
PLACE_OBJECT2: 26,
REMOVE_OBJECT2: 28,
DEFINE_SHAPE3: 32,
DEFINE_TEXT2: 33,
DEFINE_BUTTON2: 34,
DEFINE_BITS_JPEG3: 35,
DEFINE_BITS_LOSSLESS2: 36,
DEFINE_EDIT_TEXT: 37,
DEFINE_SPRITE: 39,
FRAME_LABEL: 43,
SOUND_STREAM_HEAD2: 45,
DEFINE_MORPH_SHAPE: 46,
DEFINE_FONT2: 48,
EXPORT_ASSETS: 56,
IMPORT_ASSETS: 57,
ENABLE_DEBUGGER: 58,
DO_INIT_ACTION: 59,
DEFINE_VIDEO_STREAM: 60,
VIDEO_FRAME: 61,
DEFINE_FONT_INFO2: 62,
ENABLE_DEBUGGER2: 64,
SCRIPT_LIMITS: 65,
SET_TAB_INDEX: 66,
FILE_ATTRIBUTES: 69,
PLACE_OBJECT3: 70,
IMPORT_ASSETS2: 71,
DEFINE_FONT_ALIGN_ZONES: 73,
CSM_TEXT_SETTINGS: 74,
DEFINE_FONT3: 75,
SYMBOL_CLASS: 76,
METADATA: 77,
DEFINE_SCALING_GRID: 78,
DO_ABC: 82,
DEFINE_SHAPE4: 83,
DEFINE_MORPH_SHAPE2: 84,
DEFINE_SCENE_AND_FRAME_LABEL_DATA: 86,
DEFINE_BINARY_DATA: 87,
DEFINE_FONT_NAME: 88,
START_SOUND2: 89,
DEFINE_BITS_JPEG4: 90,
DEFINE_FONT4: 91
},
controlTags: [0, 1, 4, 5, 15, 18, 19, 26, 28, 43, 45],
tagNames: {},
tagHandlers: {},
fillStyleTypes: {
SOLID: 0x00,
LINEAR_GRADIENT: 0x10,
RADIAL_GRADIENT: 0x12,
FOCAL_RADIAL_GRADIENT: 0x13,
REPEATING_BITMAP: 0x40,
CLIPPED_BITMAP: 0x41,
NON_SMOOTHED_REPEATING_BITMAP: 0x42,
NON_SMOOTHED_CLIPPED_BITMAP: 0x43
},
spreadModes: {
PAD: 0,
REFLECT: 1,
REPEAT: 2
},
interpolationModes: {
RGB: 0,
LINEAR_RGB: 1
},
styleChangeStates: {
MOVE_TO: 0x01,
LEFT_FILL_STYLE: 0x02,
RIGHT_FILL_STYLE: 0x04,
LINE_STYLE: 0x08,
NEW_STYLES: 0x10
},
buttonStates: {
UP: 0x01,
OVER: 0x02,
DOWN: 0x04,
HIT: 0x08
},
mouseButtons: {
LEFT: 1,
RIGHT: 2,
MIDDLE: 3
},
textStyleFlags: {
HAS_FONT: 0x08,
HAS_COLOR: 0x04,
HAS_XOFFSET: 0x01,
HAS_YOFFSET: 0x02
},
actionCodes: {
NEXT_FRAME: 0x04,
PREVIOUS_FRAME: 0x05,
PLAY: 0x06,
STOP: 0x07,
TOGGLE_QUALITY: 0x08,
STOP_SOUNDS: 0x09,
ADD: 0x0a,
SUBTRACT: 0x0b,
MULTIPLY: 0x0c,
DIVIDE: 0x0d,
EQUALS: 0x0e,
LESS: 0x0f,
AND: 0x10,
OR: 0x11,
NOT: 0x12,
STRING_EQUALS: 0x13,
STRING_LENGTH: 0x14,
STRING_EXTRACT: 0x15,
POP: 0x17,
TO_INTEGER: 0x18,
GET_VARIABLE: 0x1c,
SET_VARIABLE: 0x1d,
SET_TARGET2: 0x20,
STRING_ADD: 0x21,
GET_PROPERTY: 0x22,
SET_PROPERTY: 0x23,
CLONE_SPRITE: 0x24,
REMOVE_SPRITE: 0x25,
TRACE: 0x26,
START_DRAG: 0x27,
END_DRAG: 0x28,
STRING_LESS: 0x29,
THROW: 0x2a,
CAST_OP: 0x2b,
IMPLEMENTS_OP: 0x2c,
FS_COMMAND2: 0x2d,
RANDOM_NUMBER: 0x30,
MBSTRING_LENGTH: 0x31,
CHAR_TO_ASCII: 0x32,
ASCII_TO_CHAR: 0x33,
GET_TIME: 0x34,
MBSTRING_EXTRACT: 0x35,
MBCHAR_TO_ASCII: 0x36,
MBASCII_TO_CHAR: 0x37,
DELETE: 0x3a,
DELETE2: 0x3b,
DEFINE_LOCAL: 0x3c,
CALL_FUNCTION: 0x3d,
RETURN: 0x3e,
MODULO: 0x3f,
NEW_OBJECT: 0x40,
DEFINE_LOCAL2: 0x41,
INIT_ARRAY: 0x42,
INIT_OBJECT: 0x43,
TYPE_OF: 0x44,
TARGET_PATH: 0x45,
ENUMERATE: 0x46,
ADD2: 0x47,
LESS2: 0x48,
EQUALS2: 0x49,
TO_NUMBER: 0x4a,
TO_STRING: 0x4b,
PUSH_DUPLICATE: 0x4c,
STACK_SWAP: 0x4d,
GET_MEMBER: 0x4e,
SET_MEMBER: 0x4f,
INCREMENT: 0x50,
DECREMENT: 0x51,
CALL_METHOD: 0x52,
NEW_METHOD: 0x53,
INSTANCE_OF: 0x54,
ENUMERATE2: 0x55,
DO_INIT_ACTION: 0x59,
BIT_AND: 0x60,
BIT_OR: 0x61,
BIT_XOR: 0x62,
BIT_LSHIFT: 0x63,
BIT_RSHIFT: 0x64,
BIT_URSHIFT: 0x65,
STRICT_EQUALS: 0x66,
GREATER: 0x67,
STRING_GREATER: 0x68,
EXTENDS: 0x69,
GOTO_FRAME: 0x81,
DO_ABC: 0x82,
GET_URL: 0x83,
STORE_REGISTER: 0x87,
CONSTANT_POOL: 0x88,
WAIT_FOR_FRAME: 0x8a,
SET_TARGET: 0x8b,
SET_GO_TO_LABEL: 0x8c,
WAIT_FOR_FRAME2: 0x8d,
DEFINE_FUNCTION2: 0x8e,
TRY: 0x8f,
WITH: 0x94,
PUSH: 0x96,
JUMP: 0x99,
GET_URL2: 0x9a,
DEFINE_FUNCTION: 0x9b,
IF: 0x9d,
CALL: 0x9e,
GOTO_FRAME2: 0x9f
},
valueTypes: {
STRING: 0,
FLOATING_POINT: 1,
NULL: 2,
UNDEFINED: 3,
REGISTER: 4,
BOOLEAN: 5,
DOUBLE: 6,
INTEGER: 7,
CONSTANT8: 8,
SWIFF_CONSTANT16: 9
},
urlTargets: {
SELF: "_self",
BLANK: "_blank",
PARENT: "_parent",
TOP: "_top"
},
bitmapFormats: {
COLORMAPPED: 3,
RGB15: 4,
RGB24: 5
},
placeFlags: {
MOVE: 0x01,
HAS_CHARACTER: 0x02,
HAS_MATRIX: 0x04,
HAS_CXFORM: 0x08,
HAS_RATIO: 0x10,
HAS_NAME: 0x20,
HAS_CLIP_DEPTH: 0x40,
HAS_CLIP_ACTIONS: 0x80
},
defaultRenderer: null
};
(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 console = window.console || {
log: function(){}
}
function trace(){
if(Gordon.debug){ console.log.apply(console, arguments); }
}
================================================
FILE: src/intro.js
================================================
/*
* 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(window, undefined){
================================================
FILE: src/movie.js
================================================
(function(){
var LOCATION_DIRNAME = win.location.href.replace(/[^\/]*$/, ''),
defaults = {
id: '',
width: 0,
height: 0,
autoplay: true,
loop: true,
quality: Gordon.qualityValues.HIGH,
scale: Gordon.scaleValues.SHOW_ALL,
bgcolor: '',
poster: '',
renderer: null,
onprogress: function(percent){},
onreadystatechange: function(state){}
};
Gordon.Movie = function(url, options){
var t = this,
s = Gordon.readyStates;
t.url = url;
for(var prop in defaults){ t[prop] = prop in options ? 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.framesLoaded = 0;
t.isPlaying = false;
t.currentFrame = 0;
t.currentLabel = undefined;
t._readyState = s.UNINITIALIZED;
t._changeReadyState(t._readyState);
var d = t._dictionary = {},
l = t._timeline = [];
t._changeReadyState(s.LOADING);
new Gordon.Parser((/^\w:\/\//.test(url) ? '' : LOCATION_DIRNAME) + url, function(obj){
var action = obj.action;
if(action){ eval("obj.action = function(){ " + action + "; }"); }
switch(obj.type){
case "header":
for(var prop in obj){ t['_' + prop] = obj[prop]; }
var f = t._frameSize,
r = t.renderer = t.renderer || Gordon.SvgRenderer,
id = t.id;
if(!(t.width && t.height)){
t.width = (f.right - f.left) / 20;
t.height = (f.bottom - f.top) / 20;
};
t._renderer = new r(t.width, t.height, f, t.quality, t.scale, t.bgcolor);
t.totalFrames = t._frameCount;
if(id){
var stage = t._stage = doc.getElementById(id),
bgcolor = t.bgcolor,
bgParts = [],
poster = t.poster;
stage.innerHTML = '';
if(t.bgcolor){ bgParts.push(bgcolor); }
if(poster){ bgParts.push(poster, "center center"); }
if(bgParts.length){ stage.setAttribute("style", "background: " + bgParts.join(' ')); }
}
t._changeReadyState(s.LOADED);
break;
case "frame":
t._renderer.frame(obj);
l.push(obj);
var lbl = obj.label,
n = ++t.framesLoaded;
if(lbl){ t._labeledFrameNums[lbl] = n; }
t.onprogress(~~((n * 100) / t.totalFrames));
if(1 == n){
var stage = t._stage;
if(stage){
stage.appendChild(t._renderer.node);
t._changeReadyState(s.INTERACTIVE);
}
if(t.autoplay){ t.play(); }
else{ t.goTo(1); }
}
if(n == t.totalFrames){ t._changeReadyState(s.COMPLETE); }
break;
default:
t._renderer.define(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.currentFrame,
timeout = 1000 / t._frameRate;
t.isPlaying = true;
if(c < t.totalFrames){
if(t.framesLoaded > c){ t.goTo(c + 1); }
else{ timeout = 0; }
}else{
if(!t.loop){ return t.stop(); }
else{ t.goTo(1); }
}
setTimeout(function(){
if(t.isPlaying){ t.play() };
}, timeout);
return t;
},
next: function(){
var t = this,
c = t.currentFrame;
t.goTo(c < t.totalFrames ? c + 1 : 1);
return t;
},
goTo: function gf(frmNumOrLabel){
var t = this,
c = t.currentFrame,
r = t._renderer;
if(gf.caller !== t.play){ t.stop(); }
if(isNaN(frmNumOrLabel)){
var frmNum = t._labeledFrameNums[frmNumOrLabel];
if(frmNum){ t.goTo(frmNum); }
}else if(frmNumOrLabel != c){
if(frmNumOrLabel < c){ c = t.currentFrame = 0; }
var l = t._timeline;
while(c != frmNumOrLabel){
c = ++t.currentFrame;
var idx = c - 1,
frm = l[idx],
action = frm.action;
r.show(idx);
t.currentLabel = frm.lbl;
if(action){ action.call(this); }
}
}
return t;
},
stop: function(){
this.isPlaying = false;
return this;
},
prev: function(){
var t = this,
c = t.currentFrame;
t.goTo(c > 1 ? c - 1 : t.totalFrames);
return t;
},
rewind: function(){
this.goTo(1);
return this;
},
getURL: function(url, target){
var u = Gordon.urlTargets;
switch(target){
case u.BLANK:
win.open(url);
break;
case u.PARENT:
win.parent.location.href = url;
break;
case u.TOP:
win.top.location.href = url;
break;
default:
win.location.href = url;
}
return this;
},
toggleQuality: function thq(){
var o = thq._quality,
t = this,
q = t.quality;
if(o){
q = t.quality = o;
thq._quality = null;
}else{ t.quality = thq._quality = q; }
t._renderer.setQuality(q);
return t;
},
getTime: function(){
return this._startTime;
}
};
})();
================================================
FILE: src/outro.js
================================================
win.Gordon = Gordon;
})(self);
================================================
FILE: src/parser.js
================================================
(function(){
if(doc && window.Worker){
var REGEXP_SCRIPT_SRC = /(^|.*\/)gordon.(min\.)?js$/,
scripts = doc.getElementsByTagName("script"),
src = '',
i = scripts.length;
while(i--){
var path = scripts[i].src;
if(REGEXP_SCRIPT_SRC.test(path)){
src = path;
break;
}
}
worker = new Worker(src);
Gordon.Parser = function(data, ondata){
var t = this,
w = t._worker = worker;
t.data = data;
t.ondata = ondata;
w.onmessage = function(e){
t.ondata(e.data);
};
w.postMessage(data);
};
}else{
Gordon.Parser = function(url, ondata){
var xhr = new XMLHttpRequest(),
t = this;
xhr.open("GET", url, false);
xhr.overrideMimeType("text/plain; charset=x-user-defined");
xhr.send();
if(200 != xhr.status){ throw new Error("Unable to load " + url + " status: " + xhr.status); }
if(ondata) { t.ondata = ondata; }
var s = t._stream = new Gordon.Stream(xhr.responseText),
sign = s.readString(3),
v = Gordon.validSignatures,
version = s.readUI8(),
fileLen = s.readUI32(),
h = Gordon.tagHandlers,
f = Gordon.tagCodes.SHOW_FRAME;
if(sign == v.COMPRESSED_SWF){ s.decompress(); }
else if(sign != v.SWF){ throw new Error(url + " is not a SWF movie file"); }
this.ondata({
type: "header",
version: version,
fileLength: fileLen,
frameSize: s.readRect(),
frameRate: s.readUI16() / 256,
frameCount: s.readUI16()
});
t._dictionary = {};
t._jpegTables = null;
do{
var frm = {
type: "frame",
displayList: {}
};
do{
var hdr = s.readUI16(),
code = hdr >> 6,
len = hdr & 0x3f,
handl = h[code];
if(0x3f == len){ len = s.readUI32(); }
var offset = s.offset;
if(code){
if(code == f){
t.ondata(frm);
break;
}
if(t[handl]){ t[handl](s, offset, len, frm); }
else{ s.seek(len); }
}
}while(code && code != f);
}while(code);
};
Gordon.Parser.prototype = {
ondata: function(data){
postMessage(data);
},
_handleDefineShape: function(s, offset, len, frm, withAlpha){
var id = s.readUI16(),
shape = {
type: "shape",
id: id,
bounds: s.readRect()
}
t = this,
fillStyles = t._readFillStyles(s, withAlpha),
lineStyles = t._readLineStyles(s, withAlpha),
edges = t._readEdges(s, fillStyles, lineStyles, withAlpha);
if(edges instanceof Array){
var segments = shape.segments = [];
for(var i = 0, seg = edges[0]; seg; seg = edges[++i]){ segments.push({
type: "shape",
id: id + '-' + (i + 1),
commands: edges2cmds(seg.records, !!seg.line),
fill: seg.fill,
line: seg.line
}); }
}else{
shape.commands = edges2cmds(edges.records, !!edges.line),
shape.fill = edges.fill,
shape.line = edges.line
}
t.ondata(shape);
t._dictionary[id] = shape;
return t;
},
_readEdges: function(s, fillStyles, lineStyles, withAlpha, morph){
var numFillBits = s.readUB(4),
numLineBits = s.readUB(4),
x1 = 0,
y1 = 0,
x2 = 0,
y2 = 0,
seg = [],
i = 0,
isFirst = true,
edges = [],
leftFill = 0,
rightFill = 0,
fsOffset = 0,
lsOffset = 0,
leftFillEdges = {},
rightFillEdges = {},
line = 0,
lineEdges = {},
c = Gordon.styleChangeStates,
countFChanges = 0,
countLChanges = 0,
useSinglePath = true;
do{
var type = s.readUB(1),
flags = null;
if(type){
var isStraight = s.readBool(),
numBits = s.readUB(4) + 2,
cx = null,
cy = null;
x1 = x2;
y1 = y2;
if(isStraight){
var isGeneral = s.readBool();
if(isGeneral){
x2 += s.readSB(numBits);
y2 += s.readSB(numBits);
}else{
var isVertical = s.readBool();
if(isVertical){ y2 += s.readSB(numBits); }
else{ x2 += s.readSB(numBits); }
}
}else{
cx = x1 + s.readSB(numBits);
cy = y1 + s.readSB(numBits);
x2 = cx + s.readSB(numBits);
y2 = cy + s.readSB(numBits);
}
seg.push({
i: i++,
f: isFirst,
x1: x1, y1: y1,
cx: cx, cy: cy,
x2: x2, y2: y2
});
isFirst = false;
}else{
if(seg.length){
push.apply(edges, seg);
if(leftFill){
var idx = fsOffset + leftFill,
list = leftFillEdges[idx] || (leftFillEdges[idx] = []);
for(var j = 0, edge = seg[0]; edge; edge = seg[++j]){
var e = cloneEdge(edge),
tx1 = e.x1,
ty1 = e.y1;
e.i = i++;
e.x1 = e.x2;
e.y1 = e.y2;
e.x2 = tx1;
e.y2 = ty1;
list.push(e);
}
}
if(rightFill){
var idx = fsOffset + rightFill,
list = rightFillEdges[idx] || (rightFillEdges[idx] = []);
push.apply(list, seg);
}
if(line){
var idx = lsOffset + line,
list = lineEdges[idx] || (lineEdges[idx] = []);
push.apply(list, seg);
}
seg = [];
isFirst = true;
}
var flags = s.readUB(5);
if(flags){
if(flags & c.MOVE_TO){
var numBits = s.readUB(5);
x2 = s.readSB(numBits);
y2 = s.readSB(numBits);
}
if(flags & c.LEFT_FILL_STYLE){
leftFill = s.readUB(numFillBits);
countFChanges++;
}
if(flags & c.RIGHT_FILL_STYLE){
rightFill = s.readUB(numFillBits);
countFChanges++;
}
if(flags & c.LINE_STYLE){
line = s.readUB(numLineBits);
countLChanges++;
}
if((leftFill && rightFill) || countFChanges + countLChanges > 2){ useSinglePath = false; }
if(flags & c.NEW_STYLES){
fsOffset = fillStyles.length;
lsOffset = lineStyles.length;
push.apply(fillStyles, t._readFillStyles(s, withAlpha || morph));
push.apply(lineStyles, t._readLineStyles(s, withAlpha || morph));
numFillBits = s.readUB(4);
numLineBits = s.readUB(4);
useSinglePath = false;
}
}
}
}while(type || flags);
s.align();
if(useSinglePath){
var fill = leftFill || rightFill;
return {
records: edges,
fill: fill ? fillStyles[fsOffset + fill - 1] : null,
line: lineStyles[lsOffset + line - 1]
};
}else{
var segments = [];
for(var i = 0; fillStyles[i]; i++){
var fill = i + 1,
list = leftFillEdges[fill],
fillEdges = [],
edgeMap = {};
if(list){ push.apply(fillEdges, list); }
list = rightFillEdges[fill];
if(list){ push.apply(fillEdges, list); }
for(var j = 0, edge = fillEdges[0]; edge; edge = fillEdges[++j]){
var key = pt2key(edge.x1, edge.y1),
list = edgeMap[key] || (edgeMap[key] = []);
list.push(edge);
}
var recs = [],
countFillEdges = fillEdges.length,
l = countFillEdges - 1;
for(var j = 0; j < countFillEdges && !recs[l]; j++){
var edge = fillEdges[j];
if(!edge.c){
var seg = [],
firstKey = pt2key(edge.x1, edge.y1),
usedMap = {};
do{
seg.push(edge);
usedMap[edge.i] = true;
var key = pt2key(edge.x2, edge.y2),
list = edgeMap[key],
favEdge = fillEdges[j + 1],
nextEdge = null;
if(key == firstKey){
var k = seg.length;
while(k--){ seg[k].c = true; }
push.apply(recs, seg);
break;
}
if (!(list && list.length)){ break; }
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 || usedMap[entry.i])){ nextEdge = entry; }
}
}
edge = nextEdge;
}while(edge);
}
}
var l = recs.length;
if(l){ segments.push({
records: recs,
fill: fillStyles[i],
"_index": recs[l - 1].i
}); }
}
var i = lineStyles.length;
while(i--){
var recs = lineEdges[i + 1];
if(recs){ segments.push({
records: recs,
line: lineStyles[i],
_index: recs[recs.length - 1].i
}); }
}
segments.sort(function(a, b){
return a._index - b._index;
});
if(segments.length > 1){ return segments; }
else{ return segments[0]; }
}
},
_readFillStyles: function(s, withAlpha, morph){
var numStyles = s.readUI8(),
styles = [];
if(0xff == numStyles){ numStyles = s.readUI16(); }
while(numStyles--){
var type = s.readUI8(),
f = Gordon.fillStyleTypes;
switch(type){
case f.SOLID:
if(morph){ styles.push([s.readRGBA(), s.readRGBA()]); }
else{ styles.push(withAlpha ? s.readRGBA() : s.readRGB()); }
break;
case f.LINEAR_GRADIENT:
case f.RADIAL_GRADIENT:
if(morph){ var matrix = [nlizeMatrix(s.readMatrix()), nlizeMatrix(s.readMatrix())]; }
else{ var matrix = nlizeMatrix(s.readMatrix()); }
var stops = [],
style = {
type: type == f.LINEAR_GRADIENT ? "linear" : "radial",
matrix: matrix,
spread: morph ? Godon.spreadModes.PAD : s.readUB(2),
interpolation: morph ? Godon.interpolationModes.RGB : s.readUB(2),
stops: stops
},
numStops = s.readUB(4);
while(numStops--){
var offset = s.readUI8() / 256,
color = withAlpha || morph ? s.readRGBA() : s.readRGB();
stops.push({
offset: morph ? [offset, s.readUI8() / 256] : offset,
color: morph ? [color, s.readRGBA()] : color
});
}
styles.push(style);
break;
case f.REPEATING_BITMAP:
case f.CLIPPED_BITMAP:
var imgId = s.readUI16(),
img = this._dictionary[imgId],
matrix = morph ? [s.readMatrix(), s.readMatrix()] : s.readMatrix();
if(img){
styles.push({
type: "pattern",
image: img,
matrix: matrix,
repeat: type == f.REPEATING_BITMAP
});
}else{ styles.push(null); }
break;
}
}
return styles;
},
_readLineStyles: function(s, withAlpha, morph){
var numStyles = s.readUI8(),
styles = [];
if(0xff == numStyles){ numStyles = s.readUI16(); }
while(numStyles--){
var width = s.readUI16(),
color = withAlpha || morph ? s.readRGBA() : s.readRGB()
styles.push({
width: morph ? [width, s.readUI16()] : width,
color: morph ? [color, s.readRGBA()] : color
});
}
return styles;
},
_handlePlaceObject: function(s, offset, len, frm){
var objId = s.readUI16(),
depth = s.readUI16(),
t = this,
character = {
object: t._dictionary[objId].id,
depth: depth,
matrix: s.readMatrix()
};
if(s.offset - offset != len){ character.cxform = s.readCxform(); }
frm.displayList[depth] = character;
return t;
},
_handleRemoveObject: function(s, offset, len, frm){
var id = s.readUI16(),
depth = s.readUI16();
frm.displayList[depth] = null;
return this;
},
_handleDefineBits: function(s, offset, len, frm, withAlpha){
var id = s.readUI16(),
img = {
type: "image",
id: id,
width: 0,
height: 0
},
t = this,
h = t._jpegTables;
if(withAlpha){
var alphaDataOffset = s.readUI32(),
data = s.readString(alphaDataOffset);
img.alphaData = s.readString(len - (s.offset - offset));
}else{ var data = s.readString(len - 2); }
for(var i = 0; data[i]; i++){
var word = ((data.charCodeAt(i) & 0xff) << 8) | (data.charCodeAt(++i) & 0xff);
if(0xffd9 == word){
word = ((data.charCodeAt(++i) & 0xff) << 8) | (data.charCodeAt(++i) & 0xff);
if(word == 0xffd8){
data = data.substr(0, i - 4) + data.substr(i);
i -= 4;
}
}else if(0xffc0 == word){
i += 3;
img.height = ((data.charCodeAt(++i) & 0xff) << 8) | (data.charCodeAt(++i) & 0xff);
img.width = ((data.charCodeAt(++i) & 0xff) << 8) | (data.charCodeAt(++i) & 0xff);
break;
}
}
img.data = h ? h.substr(0, h.length - 2) + data.substr(2) : data;
t.ondata(img);
t._dictionary[id] = img;
return t;
},
_handleDefineButton: function(s, offset, len, frm, advanced){
var id = s.readUI16(),
t = this,
d = t._dictionary,
states = {},
button = {
type: "button",
id: id,
states: states,
trackAsMenu: advanced ? s.readBool(8) : false
};
if(advanced){ s.seek(2); }
do{
var flags = s.readUI8();
if(flags){
var objId = s.readUI16(),
depth = s.readUI16(),
state = 0x01,
character = {
object: d[objId].id,
depth: depth,
matrix: s.readMatrix()
};
if(advanced){ character.cxform = s.readCxformA(); }
while(state <= 0x08){
if(flags & state){
var list = states[state] || (states[state] = {});
list[depth] = character;
}
state <<= 1;
}
}
}while(flags);
button.action = t._readAction(s, s.offset, len - (s.offset - offset));
t.ondata(button);
d[id] = button;
return t;
},
_readAction: function(s, offset, len){
s.seek(len - (s.offset - offset));
return '';
},
_handleJpegTables: function(s, offset, len){
this._jpegTables = s.readString(len);
return this;
},
_handleSetBackgroundColor: function(s, offset, len, frm){
frm.bgcolor = s.readRGB();
return this;
},
_handleDefineFont: function(s){
var id = s.readUI16(),
numGlyphs = s.readUI16() / 2,
glyphs = [],
t = this,
font = {
type: "font",
id: id,
glyphs: glyphs
};
s.seek(numGlyphs * 2 - 2);
while(numGlyphs--){ glyphs.push(t._readGlyph(s)); }
t.ondata(font);
t._dictionary[id] = font;
return t;
},
_readGlyph: function(s){
var numFillBits = s.readUB(4),
numLineBits = s.readUB(4),
x = 0,
y = 0,
cmds = [],
c = Gordon.styleChangeStates;
do{
var type = s.readUB(1),
flags = null;
if(type){
var isStraight = s.readBool(),
numBits = s.readUB(4) + 2;
if(isStraight){
var isGeneral = s.readBool();
if(isGeneral){
x += s.readSB(numBits);
y += s.readSB(numBits);
cmds.push('L' + x + ',' + y);
}else{
var isVertical = s.readBool();
if(isVertical){
y += s.readSB(numBits);
cmds.push('V' + y);
}else{
x += s.readSB(numBits);
cmds.push('H' + x);
}
}
}else{
var cx = x + s.readSB(numBits),
cy = y + s.readSB(numBits);
x = cx + s.readSB(numBits);
y = cy + s.readSB(numBits);
cmds.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);
cmds.push('M' + x + ',' + y);
}
if(flags & c.LEFT_FILL_STYLE || flags & c.RIGHT_FILL_STYLE){ s.readUB(numFillBits); }
}
}
}while(type || flags);
s.align();
return {commands: cmds.join('')};
},
_handleDefineText: function(s, offset, length, frm, withAlpha){
var id = s.readUI16(),
strings = [],
txt = {
type: "text",
id: id,
bounds: s.readRect(),
matrix: s.readMatrix(),
strings: strings
},
numGlyphBits = s.readUI8(),
numAdvBits = s.readUI8(),
fontId = null,
fill = null,
x = 0,
y = 0,
size = 0,
str = null,
d = this._dictionary;
do{
var hdr = s.readUB(8);
if(hdr){
var type = hdr >> 7;
if(type){
var flags = hdr & 0x0f;
if(flags){
var f = Gordon.textStyleFlags;
if(flags & f.HAS_FONT){ fontId = s.readUI16(); }
if(flags & f.HAS_COLOR){ fill = withAlpha ? s.readRGBA() : s.readRGB(); }
if(flags & f.HAS_XOFFSET){ x = s.readSI16(); }
if(flags & f.HAS_YOFFSET){ y = s.readSI16(); }
if(flags & f.HAS_FONT){ size = s.readUI16(); }
}
str = {
font: d[fontId].id,
fill: fill,
x: x,
y: y,
size: size,
entries: []
};
strings.push(str);
}else{
var numGlyphs = hdr & 0x7f,
entries = str.entries;
while(numGlyphs--){
var idx = s.readUB(numGlyphBits),
adv = s.readSB(numAdvBits);
entries.push({
index: idx,
advance: adv
});
x += adv;
}
s.align();
}
}
}while(hdr);
this.ondata(txt);
d[id] = txt;
return this;
},
_handleDoAction: function(s, offset, len, frm){
frm.action = this._readAction(s, offset, len);
return this;
},
_handleDefineFontInfo: function(s, offset, len){
var d = this._dictionary,
fontId = s.readUI16(),
font = d[fontId],
codes = [],
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: codes
},
u = f.isUTF8 = s.readBool(),
i = font.glyphs.length;
while(i--){ codes.push(u ? s.readUI16() : s.readUI8()); }
this.ondata(font);
d[fontId] = font;
return this;
},
_handleDefineBitsLossless: function(s, offset, len, frm, withAlpha){
var id = s.readUI16(),
format = s.readUI8(),
img = {
type: "image",
id: id,
width: s.readUI16(),
height: s.readUI16(),
withAlpha: withAlpha
};
if(format == Gordon.bitmapFormats.COLORMAPPED){ img.colorTableSize = s.readUI8() + 1; }
img.colorData = s.readString(len - (s.offset - offset));
this.ondata(img);
this._dictionary[id] = img;
return this;
},
_handleDefineBitsJpeg2: function(s, offset, len){
return this._handleDefineBits(s, offset, len);
},
_handleDefineShape2: function(s, offset, len){
return this._handleDefineShape(s, offset, len);
},
_handleDefineButtonCxform: function(s){
var t = this,
d = t._dictionary,
buttonId = s.readUI16(),
button = d[buttonId];
button.cxform = s.readCxform();
t.ondata(button);
d[buttonId] = button;
return t;
},
_handleProtect: function(s, offset, len){
s.seek(len);
return this;
},
_handlePlaceObject2: function(s, offset, len, frm){
var flags = s.readUI8(),
depth = s.readUI16(),
f = Gordon.placeFlags,
character = {depth: depth},
t = this;
if(flags & f.HAS_CHARACTER){
var objId = s.readUI16();
character.object = t._dictionary[objId].id;
}
if(flags & f.HAS_MATRIX){ character.matrix = s.readMatrix(); }
if(flags & f.HAS_CXFORM){ character.cxform = s.readCxformA(); }
if(flags & f.HAS_RATIO){ character.ratio = s.readUI16(); }
if(flags & f.HAS_NAME){ character.name = s.readString(); }
if(flags & f.HAS_CLIP_DEPTH){ character.clipDepth = s.readUI16(); }
if(flags & f.HAS_CLIP_ACTIONS){ s.seek(len - (s.offset - offset)) }
frm.displayList[depth] = character;
return t;
},
_handleRemoveObject2: function(s, offset, len, frm){
var depth = s.readUI16();
frm.displayList[depth] = null;
return this;
},
_handleDefineShape3: function(s, offset, len, frm){
return this._handleDefineShape(s, offset, len, frm, true);
},
_handleDefineText2: function(s, offset, len, frm){
return this._handleDefineText(s, offset, len, frm, true);
},
_handleDefineButton2: function(s, offset, len, frm){
return t._handleDefineButton(s, offset, len, frm, true);
},
_handleDefineBitsJpeg3: function(s, offset, len, frm){
return this._handleDefineBits(s, offset, len, frm, true);
},
_handleDefineBitsLossless2: function(s, offset, len, frm){
return this._handleDefineBitsLossless(s, offset, len, frm, true);
},
_handleDefineSprite: function(s, offset, len){
var id = s.readUI16(),
frameCount = s.readUI16(),
h = Gordon.tagHandlers,
f = Gordon.tagCodes.SHOW_FRAME,
c = Gordon.controlTags,
timeline = [],
sprite = {
id: id,
timeline: timeline
},
t = this;
do{
var frm = {
type: "frame",
displayList: {}
};
do{
var hdr = s.readUI16(),
code = hdr >> 6,
len = hdr & 0x3f,
handl = h[code];
if(0x3f == len){ len = s.readUI32(); }
var offset = s.offset;
if(code){
if(code == f){
timeline.push(c);
break;
}
if(c[code] && t[handl]){ t[handl](s, offset, len, frm); }
else{ s.seek(len); }
}
}while(code);
}while(code);
t.ondata(sprite);
t._dictionary[id] = sprite;
return t;
},
_handleFrameLabel: function(s, offset, len, frm){
frm.label = s.readString();
return this;
},
_handleDefineMorphShape: function(s, offset, len){
var id = s.readUI16(),
startBounds = s.readRect(),
endBounds = s.readRect(),
endEdgesOffset = s.readUI32(),
t = this,
fillStyles = t._readFillStyles(s, true, true),
lineStyles = t._readLineStyles(s, true, true),
morph = {
type: "morph",
id: id,
startEdges: t._readEdges(s, fillStyles, lineStyles, true, true),
endEdges: t._readEdges(s, fillStyles, lineStyles, true, true)
};
t.ondata(morph);
t._dictionary[id] = morph;
return t;
},
_handleDefineFont2: function(s, offset, len){
var id = s.readUI16(),
hasLayout = s.readBool(),
glyphs = [],
font = {
type: "font",
id: id,
glyphs: glyphs
},
codes = [],
f = font.info = {
isShiftJIS: s.readBool(),
isSmall: s.readBool(),
isANSI: s.readBool(),
useWideOffsets: s.readBool(),
isUTF8: s.readBool(),
isItalic: s.readBool(),
isBold: s.readBool(),
languageCode: s.readLanguageCode(),
name: s.readString(s.readUI8()),
codes: codes
},
i = numGlyphs = s.readUI16(),
w = f.useWideOffsets,
offsets = [],
tablesOffset = s.offset,
u = f.isUTF8;
while(i--){ offsets.push(w ? s.readUI32() : s.readUI16()); }
s.seek(w ? 4 : 2);
for(var i = 0, o = offsets[0]; o; o = offsets[++i]){
s.seek(tablesOffset + o, true);
glyphs.push(this._readGlyph(s));
}
var i = numGlyphs;
while(i--){ codes.push(u ? s.readUI16() : s.readUI8()); };
if(hasLayout){
f.ascent = s.readUI16();
f.descent = s.readUI16();
f.leading = s.readUI16();
var advanceTable = f.advanceTable = [],
boundsTable = f.boundsTable = [],
kerningTable = f.kerningTable = [];
i = numGlyphs;
while(i--){ advanceTable.push(s.readUI16()); };
i = numGlyphs;
while(i--){ boundsTable.push(s.readRect()); };
var kerningCount = s.readUI16();
while(kerningCount--){ kerningTable.push({
code1: u ? s.readUI16() : s.readUI8(),
code2: u ? s.readUI16() : s.readUI8(),
adjustment: s.readUI16()
}); }
}
this.ondata(font);
this._dictionary[id] = font;
return this;
}
};
function nlizeMatrix(matrix){
return {
scaleX: matrix.scaleX * 20, scaleY: matrix.scaleY * 20,
skewX: matrix.skewX * 20, skewY: matrix.skewY * 20,
moveX: matrix.moveX, moveY: matrix.moveY
};
}
function cloneEdge(edge){
return {
i: edge.i,
f: edge.f,
x1: edge.x1, y1: edge.y1,
cx: edge.cx, cy: edge.cy,
x2: edge.x2, y2: edge.y2
};
}
function edges2cmds(edges, stroke){
var firstEdge = edges[0],
x1 = 0,
y1 = 0,
x2 = 0,
y2 = 0,
cmds = [];
for(var i = 0, edge = firstEdge; edge; edge = edges[++i]){
x1 = edge.x1;
y1 = edge.y1;
if(x1 != x2 || y1 != y2 || !i){ cmds.push('M' + x1 + ',' + y1); }
x2 = edge.x2;
y2 = edge.y2;
if(null == edge.cx || null == edge.cy){
if(x2 == x1){ cmds.push('V' + y2); }
else if(y2 == y1){ cmds.push('H' + x2); }
else{ cmds.push('L' + x2 + ',' + y2); }
}else{ cmds.push('Q' + edge.cx + ',' + edge.cy + ',' + x2 + ',' + y2); }
};
if(!stroke && (x2 != firstEdge.x1 || y2 != firstEdge.y1)){ cmds.push('L' + firstEdge.x1 + ',' + firstEdge.y1) }
return cmds.join('');
}
function pt2key(x, y){
return (x + 50000) * 100000 + y;
}
win.onmessage = function(e){
new Gordon.Parser(e.data);
};
}
})();
================================================
FILE: src/renderer/canvas.js
================================================
/* TODO */
================================================
FILE: src/renderer/css.js
================================================
/* TODO */
================================================
FILE: src/renderer/svg.js
================================================
(function(){
var NS_SVG = "http://www.w3.org/2000/svg",
NS_XLINK = "http://www.w3.org/1999/xlink",
NS_XHTML = "http://www.w3.org/1999/xhtml",
b = Gordon.buttonStates,
buttonStates = {},
buttonMask = 0;
for(var state in b){ buttonStates[b[state]] = state.toLowerCase(); }
Gordon.SvgRenderer = function(width, height, frmSize, quality, scale, bgcolor){
var t = this,
n = t.node = t._createElement("svg"),
frmLeft = frmSize.left,
frmTop = frmSize.top,
attrs = {
width: width,
height: height,
viewBox: '' + [frmLeft, frmTop, frmSize.right - frmLeft, frmSize.bottom - frmTop]
};
t.width = width;
t.height = height;
t.frmSize = frmSize;
t.quality = quality || Gordon.qualityValues.HIGH;
t.scale = scale || Gordon.scaleValues.SHOW_ALL;
t.bgcolor = bgcolor;
if(scale == Gordon.scaleValues.EXACT_FIT){ attrs.preserveAspectRatio = "none"; }
t._setAttributes(n, attrs);
t._defs = n.appendChild(t._createElement("defs"));
var s = t._stage = n.appendChild(t._createElement('g'));
t._setAttributes(s, {
"fill-rule": "evenodd",
"stroke-linecap": "round",
"stroke-linejoin": "round"
});
t.setQuality(t.quality);
if(bgcolor){ t.setBgcolor(bgcolor); }
t._dictionary = {};
t._fills = {};
t._set = {};
t._timeline = [];
t._displayList = {};
t._eventTarget = null;
};
Gordon.SvgRenderer.prototype = {
_createElement: function(name){
return doc.createElementNS(NS_SVG, name);
},
_setAttributes: function(node, attrs, ns){
if(node){
for(var name in attrs){
if(ns){ node.setAttributeNS(ns, name, attrs[name]); }
else{ node.setAttribute(name, attrs[name]); }
}
}
return node;
},
setQuality: function(quality){
var q = Gordon.qualityValues,
t = this;
switch(quality){
case q.LOW:
var attrs = {
"shape-rendering": "crispEdges",
"image-rendering": "optimizeSpeed",
"text-rendering": "optimizeSpeed",
"color-rendering": "optimizeSpeed"
}
break;
case q.AUTO_LOW:
case q.AUTO_HIGH:
var attrs = {
"shape-rendering": "auto",
"image-rendering": "auto",
"text-rendering": "auto",
"color-rendering": "auto"
}
break;
case q.MEDIUM:
var attrs = {
"shape-rendering": "optimizeSpeed",
"image-rendering": "optimizeSpeed",
"text-rendering": "optimizeLegibility",
"color-rendering": "optimizeSpeed"
}
break;
case q.HIGH:
var attrs = {
"shape-rendering": "geometricPrecision",
"image-rendering": "auto",
"text-rendering": "geometricPrecision",
"color-rendering": "optimizeQuality"
}
break;
case q.BEST:
var attrs = {
"shape-rendering": "geometricPrecision",
"image-rendering": "optimizeQuality",
"text-rendering": "geometricPrecision",
"color-rendering": "optimizeQuality"
}
break;
}
t._setAttributes(t._stage, attrs);
t.quality = quality;
return t;
},
setBgcolor: function(rgb){
var t = this;
if(!t.bgcolor){
t.node.style.background = color2string(rgb);
t.bgcolor = rgb;
}
return t;
},
define: function(obj){
var t = this,
d = t._dictionary,
id = obj.id,
item = d[id],
type = obj.type,
node = null,
attrs = {id: type[0] + id};
if(!item || !item.node){
switch(type){
case "shape":
var segments = obj.segments,
fill = obj.fill;
if(segments){
var node = t._createElement('g'),
frag = doc.createDocumentFragment();
for(var i = 0, seg = segments[0]; seg; seg = segments[++i]){
var segNode = frag.appendChild(t._createElement("path"));
t._setAttributes(segNode, {id: 's' + seg.id, d: seg.commands});
}
node.appendChild(frag);
}else{
if(fill && "pattern" == fill.type && !fill.repeat){
var node = t._createElement("use");
t._setAttributes(node, {href: "#" + fill.image.id}, NS_XLINK);
attrs.transform = matrix2string(fill.matrix);
}else{
var node = t._createElement("path");
attrs.d = obj.commands;
}
}
break;
case "image":
var node = t._createElement("image"),
colorData = obj.colorData,
width = obj.width,
height = obj.height;
if(colorData){
var colorTableSize = obj.colorTableSize || 0,
bpp = (obj.withAlpha ? 4 : 3),
cmIdx = colorTableSize * bpp,
data = (new Gordon.Stream(colorData)).unzip(true),
withAlpha = obj.withAlpha,
pxIdx = 0,
canvas = doc.createElement("canvas"),
ctx = canvas.getContext("2d"),
imgData = ctx.getImageData(0, 0, width, height),
pxData = imgData.data,
pad = colorTableSize ? ((width + 3) & ~3) - width : 0
canvas.width = width;
canvas.height = height;
for(var y = 0; y < height; y++){
for(var x = 0; x < width; x++){
var idx = (colorTableSize ? data[cmIdx++] : cmIdx) * bpp,
alpha = withAlpha ? data[cmIdx + 3] : 255;
if(alpha){
pxData[pxIdx] = data[idx];
pxData[pxIdx + 1] = data[idx + 1];
pxData[pxIdx + 2] = data[idx + 2];
pxData[pxIdx + 3] = alpha;
}
pxIdx += 4;
}
cmIdx += pad;
}
ctx.putImageData(imgData, 0, 0);
var uri = canvas.toDataURL();
}else{
var alphaData = obj.alphaData,
uri = "data:image/jpeg;base64," + btoa(obj.data);
if(alphaData){
var img = new Image(),
canvas = doc.createElement("canvas"),
ctx = canvas.getContext("2d"),
len = width * height,
data = (new Gordon.Stream(alphaData)).unzip(true);
img.src = uri;
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0);
var imgData = ctx.getImageData(0, 0, width, height),
pxData = imgData.data,
pxIdx = 0;
for(var i = 0; i < len; i++){
pxData[pxIdx + 3] = data[i];
pxIdx += 4;
}
ctx.putImageData(imgData, 0, 0);
uri = canvas.toDataURL();
}
}
t._setAttributes(node, {href: uri}, NS_XLINK);
attrs.width = width;
attrs.height = height;
break;
case "font":
var info = obj.info;
if(info){
var node = t._createElement("font"),
faceNode = node.appendChild(t._createElement("font-face")),
advanceTable = info.advanceTable
glyphs = obj.glyphs,
codes = info.codes,
frag = doc.createDocumentFragment(),
kerningTable = info.kerningTable;
t._setAttributes(faceNode, {
"font-family": id,
"units-per-em": 20480,
ascent: info.ascent || 20480,
descent: info.ascent || 20480,
"horiz-adv-x": advanceTable ? '' + advanceTable : 20480
});
for(var i = 0, glyph = glyphs[0]; glyph; glyph = glyphs[++i]){
var cmds = glyph.commands,
code = codes[i];
if(cmds && code){
var glyphNode = frag.appendChild(t._createElement("glyph"));
t._setAttributes(glyphNode, {
unicode: fromCharCode(code),
d: glyph.commands
});
}
}
if(kerningTable){
for(var i = 0, kern = kerningTable[0]; kern; kern = kerningTable[++i]){
var kernNode = frag.appendChild(t._createElement("hkern"));
t._setAttributes(kernNode, {
g1: kern.code1,
g2: kern.code2,
k: kern.adjustment
});
}
}
node.appendChild(frag);
}
break;
case "text":
var frag = doc.createDocumentFragment(),
strings = obj.strings;
for(var i = 0, string = strings[0]; string; string = strings[++i]){
var txtNode = frag.appendChild(t._createElement("text")),
entries = string.entries,
font = t._dictionary[string.font].object,
info = font.info,
codes = info.codes,
advances = [],
chars = [];
x = string.x,
y = string.y * -1;
for(var j = 0, entry = entries[0]; entry; entry = entries[++j]){
var str = fromCharCode(codes[entry.index]);
if(' ' != str || chars.length){
advances.push(x);
chars.push(str);
}
x += entry.advance;
}
t._setAttributes(txtNode, {
id: 't' + id + '-' + (i + 1),
"font-family": font.id,
"font-size": string.size * 20,
x: advances.join(' '),
y: y
});
txtNode.appendChild(doc.createTextNode(chars.join('')));
}
if(strings.length > 1){
var node = t._createElement('g');
node.appendChild(frag);
}else{ var node = frag.firstChild; }
break;
}
if(node){
t._setAttributes(node, attrs);
t._defs.appendChild(node);
}
d[id] = {
object: obj,
node: node
}
}else{ d[id].object = obj; }
return t;
},
frame: function(frm){
var bgcolor = frm.bgcolor,
t = this,
d = frm.displayList;
if(bgcolor && !t.bgcolor){
t.setBgcolor(bgcolor);
t.bgcolor = bgcolor;
}
for(depth in d){
var character = d[depth];
if(character){ t._cast(character); }
}
t._timeline.push(frm);
return t;
},
_cast: function(character, cxform2){
var t = this,
objId = character.object || t._displayList[character.depth].character.object;
if(objId){
if(character.clipDepth){
var cpNode = t._defs.appendChild(t._createElement("clipPath")),
useNode = cpNode.appendChild(t._createElement("use")),
attrs = {id: 'p' + objId},
matrix = character.matrix;
t._setAttributes(useNode, {href: '#s' + objId}, NS_XLINK);
if(matrix){ attrs.transform = matrix2string(matrix); }
t._setAttributes(useNode, attrs);
}
var cxform1 = character.cxform,
cxform = cxform1 && cxform2 ? concatCxform(cxform1, cxform2) : cxform1 || cxform2,
characterId = character._id = objectId({
object: objId,
cxform: cxform
});
if(!t._set[characterId]){
var obj = t._dictionary[objId].object,
node = null,
type = obj.type,
t = this,
attrs = {id: 'c' + characterId};
switch(type){
case "shape":
var segments = obj.segments;
if(segments){
var node = t._createElement('g'),
frag = doc.createDocumentFragment();
for(var i = 0, seg = segments[0]; seg; seg = segments[++i]){
var useNode = frag.appendChild(t._createElement("use"));
t._setAttributes(useNode, {href: '#s' + objId}, NS_XLINK);
t._setStyle(useNode, obj.fill, obj.line, cxform);
}
node.appendChild(frag);
}else{
var node = t._createElement("use");
t._setAttributes(node, {href: '#s' + objId}, NS_XLINK);
t._setStyle(node, obj.fill, obj.line, cxform);
}
break;
case "button":
var states1 = obj.states,
states2 = character._states = {},
btnCxform = obj.cxform;
for(var state in states1){
var list1 = states1[state],
list2 = states2[state] || (states2[state] = {});
for(var depth in list1){
var stateCharacter = list2[depth] = cloneCharacter(list1[depth]);
t._cast(stateCharacter, cxform1 || btnCxform);
}
}
break;
case "text":
var strings = obj.strings,
numStrings = strings.length,
frag = doc.createDocumentFragment(),
matrix = cloneMatrix(obj.matrix);
for(var i = 0; i < numStrings; i++){
var useNode = frag.appendChild(t._createElement("use")),
id = objId + (numStrings > 1 ? '-' + (i + 1) : ''),
string = strings[i];
t._setAttributes(useNode, {href: '#t' + id}, NS_XLINK);
t._setStyle(useNode, string.fill, null, cxform);
}
if(strings.length > 1){
var node = t._createElement('g');
node.appendChild(frag);
}else{ var node = frag.firstChild; }
matrix.scaleY *= -1;
attrs.transform = matrix2string(matrix);
break;
}
if(node){
t._setAttributes(node, attrs);
t._defs.appendChild(node);
t._set[characterId] = {
character: character,
node: node
};
}
}
}
return t;
},
_setStyle: function(node, fill, line, cxform){
var t = this,
attrs = {};
if(fill){
var type = fill.type;
if(fill.type){
var fillNode = t._defs.appendChild(t._buildFill(fill, cxform));
attrs.fill = "url(#" + fillNode.id + ')';
}else{
var color = cxform ? transformColor(fill, cxform) : fill,
alpha = color.alpha;
attrs.fill = color2string(color);
if(undefined != alpha && alpha < 1){ attrs["fill-opacity"] = alpha; }
}
}else{ attrs.fill = "none"; }
if(line){
var color = cxform ? transformColor(line.color, cxform) : line.color,
alpha = color.alpha;
attrs.stroke = color2string(color);
attrs["stroke-width"] = max(line.width, 20);
if(undefined != alpha && alpha < 1){ attr["stroke-opacity"] = alpha; }
}
t._setAttributes(node, attrs);
return t;
},
_buildFill: function(fill, cxform){
var t = this,
f = t._fills,
id = objectId({
fill: fill,
cxform: cxform
}),
node = f[id];
if(!node){
var type = fill.type,
attrs = {id: type[0] + id};
switch(type){
case "linear":
case "radial":
var node = t._createElement(type + "Gradient"),
s = Gordon.spreadModes,
i = Gordon.interpolationModes,
stops = fill.stops;
attrs.gradientUnits = "userSpaceOnUse";
attrs.gradientTransform = matrix2string(fill.matrix);
if("linear" == type){
attrs.x1 = -819.2;
attrs.x2 = 819.2;
}else{
attrs.cx = attrs.cy = 0;
attrs.r = 819.2;
}
switch(fill.spread){
case s.REFLECT:
attrs.spreadMethod = "reflect";
break;
case s.REPEAT:
attrs.spreadMethod = "repeat";
break;
}
if(fill.interpolation == i.LINEAR_RGB){ attrs["color-interpolation"] = "linearRGB"; }
stops.forEach(function(stop){
var stopNode = node.appendChild(t._createElement("stop")),
color = cxform ? transformColor(stop.color, cxform) : stop.color;
t._setAttributes(stopNode, {
offset: stop.offset,
"stop-color": color2string(color),
"stop-opacity": "alpha" in color ? 1 : color.alpha
});
});
break;
case "pattern":
var node = t._createElement("pattern"),
fillImg = fill.image,
width = fillImg.width,
height = fillImg.height;
if(cxform){
var img = new Image(),
origin = doc.getElementById('i' + fillImg.id),
canvas = doc.createElement("canvas"),
ctx = canvas.getContext("2d"),
imgNode = node.appendChild(t._createElement("image"));
img.src = origin.getAttribute("href");
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0);
var imgData = ctx.getImageData(0, 0, width, height),
pxData = imgData.data,
len = pxData.length,
multR = cxform.multR,
multG = cxform.multG,
multB = cxform.multB,
addR = cxform.addR,
addG = cxform.addG,
addB = cxform.addB;
for(var i = 0; i < len; i+= 4){
pxData[i] = ~~max(0, min((pxData[i] * multR) + addR, 255));
pxData[i + 1] = ~~max(0, min((pxData[i + 1] * multG) + addG, 255));
pxData[i + 2] = ~~max(0, min((pxData[i + 2] * multB) + addB, 255));
}
ctx.putImageData(imgData, 0, 0);
t._setAttributes(imgNode, {href: canvas.toDataURL()}, NS_XLINK);
t._setAttributes(imgNode, {
width: width,
height: height,
opacity: ~~max(0, min(cxform.multA + cxform.addA, 1))
});
}else{
var useNode = node.appendChild(t._createElement("use"));
t._setAttributes(useNode, {href: "#i" + fillImg.id}, NS_XLINK);
}
attrs.patternUnits = "userSpaceOnUse";
attrs.patternTransform = matrix2string(fill.matrix);
attrs.width = width;
attrs.height = height;
break;
}
t._setAttributes(node, attrs);
t._fills[id] = node;
}
return node;
},
show: function(frmIdx){
var t = this,
frm = t._timeline[frmIdx],
d = frm.displayList;
for(var depth in d){
var character = d[depth];
if(character){ t.place(character); }
else{ t.remove(depth); }
}
return t;
},
place: function(character){
var depth = character.depth,
t = this,
d = t._displayList,
replace = d[depth];
if(replace && !character.object){
var id = character._id,
node = replace.node,
matrix = character.matrix;
if(id != replace.character._id){ t._setAttributes(node, {href: "#c" + id}, NS_XLINK); }
var matrix = character.matrix;
if(matrix && matrix != replace.matrix){ t._setAttributes(node, {transform: matrix2string(matrix)}); }
}else{
if(character.clipDepth){
var node = t._createElement('g');
t._setAttributes(node, {"clip-path": "url(#p" + character.object + ')'});
}else{ var node = t._prepare(character); }
if(replace){ t.remove(depth); }
var stage = t._stage;
if(1 == depth){ stage.insertBefore(node, stage.firstChild); }
else{
var nextDepth = 0;
for(var entry in d){
var c = d[entry].character;
if(c.clipDepth && depth <= c.clipDepth){ stage = d[entry].node; }
if(entry > depth){
nextDepth = entry;
break;
}
}
if(nextDepth){ stage.insertBefore(node, d[nextDepth].node); }
else{ stage.appendChild(node); }
}
}
d[depth] = {
character: character,
node: node
};
return t;
},
_prepare: function(character){
var t = this,
obj = t._dictionary[character.object].object,
type = obj.type,
node = null,
matrix = character.matrix;
switch(type){
case "button":
var node = t._createElement('g'),
states = character._states,
btnCxform = obj.cxform,
hitNode = null,
stateNodes = {},
frag = doc.createDocumentFragment(),
style = doc.body.style,
currState = b.UP,
m = Gordon.mouseButtons,
isMouseOver = false,
action = obj.action,
trackAsMenu = obj.trackAsMenu;
for(var state in states){
var stateFrag = doc.createDocumentFragment(),
list = states[state];
for(var depth in list){ stateFrag.appendChild(t._prepare(list[depth])); }
if(stateFrag.length > 1){
var stateNode = t._createElement('g');
stateNode.appendChild(stateFrag);
}else{ var stateNode = stateFrag.firstChild; }
if(state == b.HIT){
t._setAttributes(stateNode, {opacity: 0});
hitNode = stateNode;
}else{
t._setAttributes(stateNode, {visibility: state == b.UP ? "visible" : "hidden"});
stateNodes[state] = frag.appendChild(stateNode);
}
}
node.appendChild(frag);
node.appendChild(hitNode);
function setState(state){
if(state == b.UP){ style.cursor = setState._cursor || "default"; }
else{
setState._cursor = style.cursor;
style.cursor = "pointer";
}
t._setAttributes(stateNodes[currState], {visibility: "hidden"});
t._setAttributes(stateNodes[state], {visibility: "visible"});
currState = state;
};
hitNode.onmouseover = function(){
if(!(buttonMask & m.LEFT)){ setState(b.OVER); }
else if(this == t.eventTarget){ setState(b.DOWN); }
return false;
}
hitNode.onmousedown = function(){
t.eventTarget = this;
setState(b.DOWN);
var handle = doc.addEventListener("mouseup", function(){
setState(b.UP);
doc.removeEventListener("mouseup", handle, true);
t.eventTarget = null;
}, true);
return false;
}
hitNode.onmouseup = function(){
setState(b.OVER);
if(this == t.eventTarget){
if(action){ action(); }
t.eventTarget = null;
}
return false;
}
hitNode.onmouseout = function(){
if(this == t.eventTarget){
if(trackAsMenu){
t.eventTarget = null;
setState(b.UP);
}else{ setState(b.OVER); }
}
else{ setState(b.UP); }
return false;
}
break;
default:
var node = t._createElement("use");
t._setAttributes(node, {href: "#c" + character._id}, NS_XLINK);
}
if(matrix){ t._setAttributes(node, {transform: matrix2string(matrix)}); }
return node;
},
remove: function(depth){
var d = this._displayList,
item = d[depth],
node = item.node,
parentNode = node.parentNode;
if(item.character.clipDepth){
var childNodes = node.childNodes;
for(var c in childNodes){ parentNode.insertBefore(childNodes[c], node); }
}
parentNode.removeChild(node);
delete d[depth];
return this;
}
};
var REGEXP_IS_COLOR = /^([\da-f]{1,2}){3}$/i;
function color2string(color){
if("string" == typeof color){ return REGEXP_IS_COLOR.test(color) ? color : null; }
return "rgb(" + [color.red, color.green, color.blue] + ')';
}
function matrix2string(matrix){
return "matrix(" + [
matrix.scaleX, matrix.skewX,
matrix.skewY, matrix.scaleY,
matrix.moveX, matrix.moveY
] + ')';
}
function transformColor(color, cxform){
return {
red: ~~max(0, min((color.red * cxform.multR) + cxform.addR, 255)),
green: ~~max(0, min((color.green * cxform.multG) + cxform.addG, 255)),
blue: ~~max(0, min((color.blue * cxform.multB) + cxform.addB, 255)),
alpha: ~~max(0, min((color.alpha * cxform.multA) + cxform.addA, 255))
}
}
function objectId(obj){
var memo = objectId._memo || (objectId._memo = {}),
nextId = (objectId._nextId || (objectId._nextId = 1)),
key = object2key(obj),
origId = memo[key];
if(!origId){ memo[key] = nextId; }
return origId || objectId._nextId++;
}
function object2key(obj){
var a = 1,
b = 0;
for(var prop in obj){
var val = obj[prop];
if("object" == typeof val){ a += object2key(val); }
else{
var buff = '' + val;
for(var j = 0; buff[j]; j++){
a = (a + buff.charCodeAt(j)) % 65521;
b = (b + a) % 65521;
}
}
}
return (b << 16) | a;
}
function concatCxform(cxform1, cxform2){
return{
multR: cxform1.multR * cxform2.multR, multG: cxform1.multG * cxform2.multG,
multB: cxform1.multB * cxform2.multB, multA: cxform1.multA * cxform2.multA,
addR: cxform1.addR + cxform2.addR, addG: cxform1.addG + cxform2.addG,
addB: cxform1.addB + cxform2.addB, addA: cxform1.addA + cxform2.addA
}
}
function cloneCharacter(character){
return {
object: character.object,
depth: character.depth,
matrix: character.matrix,
cxform: character.cxform
};
}
function cloneMatrix(matrix){
return {
scaleX: matrix.scaleX, scaleY: matrix.scaleY,
skewX: matrix.skewX, skewY: matrix.skewY,
moveX: matrix.moveX, moveY: matrix.moveY
};
}
if(doc){
doc.addEventListener("mousedown", function(e){
buttonMask |= 0x01 << e.button;
}, true);
doc.addEventListener("mouseup", function(e){
buttonMask ^= 0x01 << e.button;
}, true);
}
})();
================================================
FILE: src/renderer/vml.js
================================================
/* TODO */
================================================
FILE: src/renderer/webgl.js
================================================
/* TODO */
================================================
FILE: src/stream.js
================================================
(function(){
var DEFLATE_CODE_LENGTH_ORDER = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15],
DEFLATE_CODE_LENGHT_MAP = [
[0, 3], [0, 4], [0, 5], [0, 6], [0, 7], [0, 8], [0, 9], [0, 10], [1, 11], [1, 13], [1, 15], [1, 17],
[2, 19], [2, 23], [2, 27], [2, 31], [3, 35], [3, 43], [3, 51], [3, 59], [4, 67], [4, 83], [4, 99],
[4, 115], [5, 131], [5, 163], [5, 195], [5, 227], [0, 258]
],
DEFLATE_DISTANCE_MAP = [
[0, 1], [0, 2], [0, 3], [0, 4], [1, 5], [1, 7], [2, 9], [2, 13], [3, 17], [3, 25], [4, 33], [4, 49],
[5, 65], [5, 97], [6, 129], [6, 193], [7, 257], [7, 385], [8, 513], [8, 769], [9, 1025], [9, 1537],
[10, 2049], [10, 3073], [11, 4097], [11, 6145], [12, 8193], [12, 12289], [13, 16385], [13, 24577]
];
Gordon.Stream = function(data){
var buff = [],
t = this,
i = t.length = data.length;
t.offset = 0;
for(var i = 0; data[i]; i++){ buff.push(fromCharCode(data.charCodeAt(i) & 0xff)); }
t._buffer = buff.join('');
t._bitBuffer = null;
t._bitOffset = 8;
};
Gordon.Stream.prototype = {
readByteAt: function(pos){
return this._buffer.charCodeAt(pos);
},
readNumber: function(numBytes, bigEnd){
var t = this,
val = 0;
if(bigEnd){
while(numBytes--){ val = (val << 8) | t.readByteAt(t.offset++); }
}else{
var o = t.offset,
i = o + numBytes;
while(i > o){ val = (val << 8) | t.readByteAt(--i); }
t.offset += numBytes;
}
t.align();
return val;
},
readSNumber: function(numBytes, bigEnd){
var val = this.readNumber(numBytes, bigEnd),
numBits = numBytes * 8;
if(val >> (numBits - 1)){ val -= Math.pow(2, numBits); }
return val;
},
readSI8: function(){
return this.readSNumber(1);
},
readSI16: function(bigEnd){
return this.readSNumber(2, bigEnd);
},
readSI32: function(bigEnd){
return this.readSNumber(4, bigEnd);
},
readUI8: function(){
return this.readNumber(1);
},
readUI16: function(bigEnd){
return this.readNumber(2, bigEnd);
},
readUI24: function(bigEnd){
return this.readNumber(3, bigEnd);
},
readUI32: function(bigEnd){
return this.readNumber(4, bigEnd);
},
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,
numBytes = numBits / 8,
t = this,
val = 0.0;
if(numBytes > 4){
var i = Math.ceil(numBytes / 4);
while(i--){
var buff = [],
o = t.offset,
j = o + (numBytes >= 4 ? 4 : numBytes % 4);
while(j > o){
buff.push(t.readByteAt(--j));
numBytes--;
t.offset++;
}
}
var s = new Gordon.Stream(fromCharCode.apply(String, buff)),
sign = s.readUB(1),
expo = s.readUB(numEBits),
mantis = 0,
i = numSBits;
while(i--){
if(s.readBool()){ mantis += Math.pow(2, i); }
}
}else{
var sign = t.readUB(1),
expo = t.readUB(numEBits),
mantis = t.readUB(numSBits);
}
if(sign || expo || mantis){
var maxExpo = Math.pow(2, numEBits),
bias = ~~((maxExpo - 1) / 2),
scale = Math.pow(2, numSBits),
fract = mantis / scale;
if(bias){
if(bias < maxExpo){ val = Math.pow(2, expo - bias) * (1 + fract); }
else if(fract){ val = NaN; }
else{ val = Infinity; }
}else if(fract){ val = Math.pow(2, 1 - bias) * fract; }
if(NaN != val && sign){ val *= -1; }
}
return val;
},
readFloat16: function(){
return this._readFloatingPoint(5, 10);
},
readDouble: function(){
return this._readFloatingPoint(11, 52);
},
readEncodedU32: function(){
var val = 0;
for(var i = 0; i < 5; i++){
var num = this.readByteAt(this._offset++);
val = val | ((num & 0x7f) << (7 * i));
if(!(num & 0x80)){ break; }
}
return val;
},
readSB: function(numBits){
var val = this.readUB(numBits);
if(val >> (numBits - 1)){ val -= Math.pow(2, numBits); }
return val;
},
readUB: function(numBits, lsb){
var t = this,
val = 0;
for(var i = 0; i < numBits; i++){
if(8 == t._bitOffset){
t._bitBuffer = t.readUI8();
t._bitOffset = 0;
}
if(lsb){ val |= (t._bitBuffer & (0x01 << t._bitOffset++) ? 1 : 0) << i; }
else{ val = (val << 1) | (t._bitBuffer & (0x80 >> t._bitOffset++) ? 1 : 0); }
}
return val;
},
readFB: function(numBits){
return this._readFixedPoint(numBits, 16);
},
readString: function(numChars){
var t = this,
b = t._buffer;
if(undefined != numChars){
var str = b.substr(t.offset, numChars);
t.offset += numChars;
}else{
var chars = [],
i = t.length - t.offset;
while(i--){
var code = t.readByteAt(t.offset++);
if(code){ chars.push(fromCharCode(code)); }
else{ break; }
}
var str = chars.join('');
}
return str;
},
readBool: function(numBits){
return !!this.readUB(numBits || 1);
},
seek: function(offset, absolute){
var t = this;
t.offset = (absolute ? 0 : t.offset) + offset;
t.align();
return t;
},
align: function(){
this._bitBuffer = null;
this._bitOffset = 8;
return this;
},
readLanguageCode: function(){
return this.readUI8();
},
readRGB: function(){
return {
red: this.readUI8(),
green: this.readUI8(),
blue: this.readUI8()
}
},
readRGBA: function(){
var rgba = this.readRGB();
rgba.alpha = this.readUI8() / 255;
return rgba;
},
readARGB: function(){
var alpha = this.readUI8() / 255,
rgba = this.readRGB();
rgba.alpha = alpha;
return rgba;
},
readRect: function(){
var t = this;
numBits = t.readUB(5),
rect = {
left: t.readSB(numBits),
right: t.readSB(numBits),
top: t.readSB(numBits),
bottom: t.readSB(numBits)
};
t.align();
return rect;
},
readMatrix: function(){
var t = this,
hasScale = t.readBool();
if(hasScale){
var numBits = t.readUB(5),
scaleX = t.readFB(numBits),
scaleY = t.readFB(numBits);
}else{ var scaleX = scaleY = 1.0; }
var hasRotation = t.readBool();
if(hasRotation){
var numBits = t.readUB(5),
skewX = t.readFB(numBits),
skewY = t.readFB(numBits);
}else{ var skewX = skewY = 0.0; }
var numBits = t.readUB(5);
matrix = {
scaleX: scaleX, scaleY: scaleY,
skewX: skewX, skewY: skewY,
moveX: t.readSB(numBits), moveY: t.readSB(numBits)
};
t.align();
return matrix;
},
readCxform: function(){
return this._readCxf();
},
readCxformA: function(){
return this._readCxf(true);
},
_readCxf: function(withAlpha){
var t = this;
hasAddTerms = t.readBool(),
hasMultTerms = t.readBool(),
numBits = t.readUB(4);
if(hasMultTerms){
var multR = t.readSB(numBits) / 256,
multG = t.readSB(numBits) / 256,
multB = t.readSB(numBits) / 256,
multA = withAlpha ? t.readSB(numBits) / 256 : 1;
}else{ var multR = multG = multB = multA = 1; }
if(hasAddTerms){
var addR = t.readSB(numBits),
addG = t.readSB(numBits),
addB = t.readSB(numBits),
addA = withAlpha ? t.readSB(numBits) / 256 : 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;
},
decompress: function(){
var t = this,
b = t._buffer,
o = t.offset,
data = b.substr(0, o) + t.unzip();
t.length = data.length;
t.offset = o;
t._buffer = data;
return t;
},
unzip: function uz(raw){
var t = this,
buff = [],
o = DEFLATE_CODE_LENGTH_ORDER,
m = DEFLATE_CODE_LENGHT_MAP,
d = DEFLATE_DISTANCE_MAP;
t.seek(2);
do{
var isFinal = t.readUB(1, true),
type = t.readUB(2, true);
if(type){
if(1 == type){
var distTable = uz.fixedDistTable,
litTable = uz.fixedLitTable;
if(!distTable){
var bitLengths = [];
for(var i = 0; i < 32; i++){ bitLengths.push(5); }
distTable = uz.fixedDistTable = buildHuffTable(bitLengths);
}
if(!litTable){
var bitLengths = [];
for(var i = 0; i <= 143; i++){ bitLengths.push(8); }
for(; i <= 255; i++){ bitLengths.push(9); }
for(; i <= 279; i++){ bitLengths.push(7); }
for(; i <= 287; i++){ bitLengths.push(8); }
litTable = uz.fixedLitTable = buildHuffTable(bitLengths);
}
}else{
var numLitLengths = t.readUB(5, true) + 257,
numDistLengths = t.readUB(5, true) + 1,
numCodeLenghts = t.readUB(4, true) + 4,
codeLengths = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for(var i = 0; i < numCodeLenghts; i++){ codeLengths[o[i]] = t.readUB(3, true); }
var codeTable = buildHuffTable(codeLengths),
litLengths = [],
prevCodeLen = 0,
maxLengths = numLitLengths + numDistLengths;
while(litLengths.length < maxLengths){
var sym = decodeSymbol(t, codeTable);
switch(sym){
case 16:
var i = t.readUB(2, true) + 3;
while(i--){ litLengths.push(prevCodeLen); }
break;
case 17:
var i = t.readUB(3, true) + 3;
while(i--){ litLengths.push(0); }
break;
case 18:
var i = t.readUB(7, true) + 11;
while(i--){ litLengths.push(0); }
break;
default:
if(sym <= 15){
litLengths.push(sym);
prevCodeLen = sym;
}
}
}
var distTable = buildHuffTable(litLengths.splice(numLitLengths, numDistLengths)),
litTable = buildHuffTable(litLengths);
}
do{
var sym = decodeSymbol(t, litTable);
if(sym < 256){ buff.push(raw ? sym : fromCharCode(sym)); }
else if(sym > 256){
var lengthMap = m[sym - 257],
len = lengthMap[1] + t.readUB(lengthMap[0], true),
distMap = d[decodeSymbol(t, distTable)],
dist = distMap[1] + t.readUB(distMap[0], true),
i = buff.length - dist;
while(len--){ buff.push(buff[i++]); }
}
}while(256 != sym);
}else{
t.align();
var len = t.readUI16(),
nlen = t.readUI16();
if(raw){ while(len--){ buff.push(t.readUI8()); } }
else{ buff.push(t.readString(len)); }
}
}while(!isFinal);
t.seek(4);
return raw ? buff : buff.join('');
}
};
function buildHuffTable(bitLengths){
var numLengths = bitLengths.length,
blCount = [],
maxBits = max.apply(Math, bitLengths),
nextCode = [],
code = 0,
table = {},
i = numLengths;
while(i--){
var len = bitLengths[i];
blCount[len] = (blCount[len] || 0) + (len > 0);
}
for(var i = 1; i <= maxBits; i++){
var len = i - 1;
if(undefined == blCount[len]){ blCount[len] = 0; }
code = (code + blCount[i - 1]) << 1;
nextCode[i] = code;
}
for(var i = 0; i < numLengths; i++){
var len = bitLengths[i];
if(len){
table[nextCode[len]] = {
length: len,
symbol: i
};
nextCode[len]++;
}
}
return table;
}
function decodeSymbol(s, table) {
var code = 0,
len = 0;
while(true){
code = (code << 1) | s.readUB(1, true);
len++;
var entry = table[code];
if(undefined != entry && entry.length == len){ return entry.symbol }
}
}
})();
gitextract_4a59zi76/
├── .gitignore
├── MIT-LICENSE
├── README.md
├── Rakefile
├── build/
│ └── compiler.jar
└── src/
├── base.js
├── intro.js
├── movie.js
├── outro.js
├── parser.js
├── renderer/
│ ├── canvas.js
│ ├── css.js
│ ├── svg.js
│ ├── vml.js
│ └── webgl.js
└── stream.js
SYMBOL INDEX (16 symbols across 4 files)
FILE: src/base.js
function trace (line 303) | function trace(){
FILE: src/parser.js
function nlizeMatrix (line 870) | function nlizeMatrix(matrix){
function cloneEdge (line 878) | function cloneEdge(edge){
function edges2cmds (line 888) | function edges2cmds(edges, stroke){
function pt2key (line 911) | function pt2key(x, y){
FILE: src/renderer/svg.js
function setState (line 624) | function setState(state){
function color2string (line 697) | function color2string(color){
function matrix2string (line 702) | function matrix2string(matrix){
function transformColor (line 710) | function transformColor(color, cxform){
function objectId (line 719) | function objectId(obj){
function object2key (line 728) | function object2key(obj){
function concatCxform (line 745) | function concatCxform(cxform1, cxform2){
function cloneCharacter (line 754) | function cloneCharacter(character){
function cloneMatrix (line 763) | function cloneMatrix(matrix){
FILE: src/stream.js
function buildHuffTable (line 411) | function buildHuffTable(bitLengths){
function decodeSymbol (line 442) | function decodeSymbol(s, table) {
Condensed preview — 16 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (112K chars).
[
{
"path": ".gitignore",
"chars": 6,
"preview": "dist/\n"
},
{
"path": "MIT-LICENSE",
"chars": 1060,
"preview": "Copyright (c) 2010 Tobias Schneider\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof thi"
},
{
"path": "README.md",
"chars": 172,
"preview": "Gordon\n======\n\n#### An open source Flash™ runtime written in pure JavaScript ####\n\nVisit the GitHub Wiki for more inform"
},
{
"path": "Rakefile",
"chars": 1061,
"preview": "src_dir = 'src'\nrenderer_dir = File.join(src_dir, 'renderer')\ndist_dir = 'dist'\nbuild_dir = 'build'\nbase_files = [ 'base"
},
{
"path": "src/base.js",
"chars": 7372,
"preview": "var win = window,\n doc = win.document,\n fromCharCode = String.fromCharCode,\n push = Array.prototype.push,\n m"
},
{
"path": "src/intro.js",
"chars": 227,
"preview": "/*\n * Gordon: An open source Flash™ runtime written in pure JavaScript\n *\n * Copyright (c) 2010 Tobias Schneider\n "
},
{
"path": "src/movie.js",
"chars": 6791,
"preview": "(function(){\n var LOCATION_DIRNAME = win.location.href.replace(/[^\\/]*$/, ''),\n defaults = {\n id: '"
},
{
"path": "src/outro.js",
"chars": 35,
"preview": " win.Gordon = Gordon;\n})(self);\n"
},
{
"path": "src/parser.js",
"chars": 39660,
"preview": "(function(){\n if(doc && window.Worker){\n var REGEXP_SCRIPT_SRC = /(^|.*\\/)gordon.(min\\.)?js$/,\n scr"
},
{
"path": "src/renderer/canvas.js",
"chars": 11,
"preview": "/* TODO */\n"
},
{
"path": "src/renderer/css.js",
"chars": 11,
"preview": "/* TODO */\n"
},
{
"path": "src/renderer/svg.js",
"chars": 35472,
"preview": "(function(){\n var NS_SVG = \"http://www.w3.org/2000/svg\",\n NS_XLINK = \"http://www.w3.org/1999/xlink\",\n N"
},
{
"path": "src/renderer/vml.js",
"chars": 11,
"preview": "/* TODO */\n"
},
{
"path": "src/renderer/webgl.js",
"chars": 11,
"preview": "/* TODO */\n"
},
{
"path": "src/stream.js",
"chars": 16533,
"preview": "(function(){\n var DEFLATE_CODE_LENGTH_ORDER = [16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15],\n "
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the tobeytailor/gordon GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 16 files (105.9 KB), approximately 22.6k tokens, and a symbol index with 16 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.