OSDN Git Service

for advanced optimizations
authorYuta Imaya <yuta.imaya@gree.net>
Tue, 4 Dec 2012 08:58:36 +0000 (17:58 +0900)
committerYuta Imaya <yuta.imaya@gree.net>
Tue, 4 Dec 2012 08:58:36 +0000 (17:58 +0900)
67 files changed:
action.js [deleted file]
bitmap.js [deleted file]
build.xml [new file with mode: 0644]
canvas.js [deleted file]
closure-primitives/base.js [new file with mode: 0644]
closure-primitives/depswriter.py [new file with mode: 0755]
closure-primitives/source.py [new file with mode: 0755]
closure-primitives/source.pyc [new file with mode: 0644]
closure-primitives/treescan.py [new file with mode: 0755]
closure-primitives/treescan.pyc [new file with mode: 0644]
console.js [new file with mode: 0644]
dict.js [deleted file]
display.js [deleted file]
ibit.js [deleted file]
loader.js [deleted file]
main.js [deleted file]
memory.js [deleted file]
movieclip.js [deleted file]
shape.js [deleted file]
src/action.js [new file with mode: 0644]
src/bitmap.js [new file with mode: 0644]
src/canvas.js [new file with mode: 0644]
src/dict.js [new file with mode: 0644]
src/display.js [new file with mode: 0644]
src/event.js [moved from event.js with 56% similarity]
src/ibit.js [new file with mode: 0644]
src/loader.js [new file with mode: 0644]
src/main.js [new file with mode: 0644]
src/memory.js [new file with mode: 0644]
src/movieclip.js [new file with mode: 0644]
src/shape.js [new file with mode: 0644]
src/string.js [new file with mode: 0644]
src/swf/cxform.js [new file with mode: 0644]
src/swf/fillstyles.js [new file with mode: 0644]
src/swf/gradient.js [new file with mode: 0644]
src/swf/header.js [new file with mode: 0644]
src/swf/linestyles.js [new file with mode: 0644]
src/swf/matrix.js [new file with mode: 0644]
src/swf/rect.js [new file with mode: 0644]
src/swf/rgba.js [new file with mode: 0644]
src/swf/shaperecords.js [new file with mode: 0644]
src/swf/tag.js [new file with mode: 0644]
src/swf/tag/definebitsjpeg.js [new file with mode: 0644]
src/swf/tag/defineshape.js [new file with mode: 0644]
src/swf/tag/doaction.js [new file with mode: 0644]
src/swf/tag/jpegtables.js [new file with mode: 0644]
src/swf/tag/placeobject.js [new file with mode: 0644]
src/swf/tag/setbackgroundcolor.js [new file with mode: 0644]
src/swf/tag/showframe.js [new file with mode: 0644]
string.js [deleted file]
swf/cxform.js [deleted file]
swf/fillstyles.js [deleted file]
swf/gradient.js [deleted file]
swf/header.js [deleted file]
swf/linestyles.js [deleted file]
swf/matrix.js [deleted file]
swf/rect.js [deleted file]
swf/rgba.js [deleted file]
swf/shaperecords.js [deleted file]
swf/tag.js [deleted file]
swf/tag/definebitsjpeg.js [deleted file]
swf/tag/defineshape.js [deleted file]
swf/tag/doaction.js [deleted file]
swf/tag/jpegtables.js [deleted file]
swf/tag/placeobject.js [deleted file]
swf/tag/setbackgroundcolor.js [deleted file]
swf/tag/showframe.js [deleted file]

diff --git a/action.js b/action.js
deleted file mode 100644 (file)
index 78bc9cf..0000000
--- a/action.js
+++ /dev/null
@@ -1,50 +0,0 @@
-(function(global) {
-    var FlappAction= function() {
-       this.actionRecord = null;
-    };
-    FlappAction.exec = function(tag, movieClip, rootMovieClip) {
-       console.debug("FlappAction.exec");
-       var actionsBit = new FlappIBit();
-       actionsBit.input(tag.actions);
-       var code = 0;
-       var stack = [];
-       while (code = actionsBit.ui8()) {
-           if (code < 0x80) {
-               switch (code) {
-               case 0x06: // Play
-                   movieClip.play();
-                   break;
-               case 0x07: // Stop
-                   movieClip.stop();
-                   break;
-               case 0x1d: // SetVariables
-                   movieClip.setVariable(stack.pop(), stack.pop());
-                   break;
-               default:
-                   console.debug("FlappActiom: not implemented yet. code=0x%02x", code);
-                   break;
-               }
-           } else {
-               var actionLength = actionsBit.input(tag.actions);
-               var nextActionOffset = actionsBit.getBytePos() + actionLength;
-               switch (code) {
-               case 0x81: // GotoFrame
-                   movieClip.gotoFrame(actionsBit.si16());
-                   break;
-               case 0x83: // GetURL
-                   // 
-                   break;
-               case 0x8c: // GoToLabel
-                   movieClip.gotoLabel(actionsBit.strN(actionLength));
-                   break;
-               //case 0x96: // Push
-               default:
-                   console.debug("FlappActiom: not implemented yet. code=0x%02x", code);
-                   break;
-               }
-               actionsBit.setPos(nextActionOffset, 0);
-           }
-       }
-    };
-    global.FlappAction = FlappAction;
-})(this);
diff --git a/bitmap.js b/bitmap.js
deleted file mode 100644 (file)
index 5aec7f1..0000000
--- a/bitmap.js
+++ /dev/null
@@ -1,65 +0,0 @@
-(function(global) {
-    var FlappBitmap = function() {
-       ;
-    };
-    FlappBitmap.prototype = {
-
-    };
-    FlappBitmap.jpegChunkOffsets = function(jpegData) {
-       var offsetTable = {};
-       var ibit = new FlappIBit();
-       while (ibit.HasNext(2)) {
-           var marker = ibit.ui16be();
-           var offset = ibit.getBytePos();
-           switch (marker) {
-            case 0xFFD8: // SOI
-            case 0xFFD9: // EOI
-               break;
-            case 0xFFDA: // SOS + [RST] + EOI
-               length = ibit.len() - offset;
-               offsetTable[marker] = [offset, length]
-               break;
-           default:
-               length = ibit.ui16be() + 2;
-               offsetTable[marker] = [offset, length]
-
-               break;
-           }
-       }
-       return offsetTable;
-    }
-
-    FlappBitmap.toJpeg = function(swfJpeg, jpegTables) {
-       var offsetTable = FlappBitmap.jpegChunkOffsets(swfJpeg);
-       var hasDQT = (0xFFDB in offsetTable)?true:false;
-       if (hasDQT === false) {
-           var offsetTable2 = FlappBitmap.jpegChunkOffsets(jpegTables);
-       }
-       var jpegArray = [0xFF, 0xD8]; // SOI
-       // APP0, SOF0, DQT, DHT, SOS
-       var jpegOrder = [0xFFE0, 0xFFC0, 0xFFDB, 0xFFC4, 0xFFDA];
-       for (var i = 0, l = jpegOrder; i < l ; i++) {
-           var marker = jpegOrder[i];
-           var swfJpegOffset = (marker in offsetTable)?true:false;
-           if (swfJpegOffset) {
-               var entry = offsetTable[marker];
-           } else {
-               var entry = offsetTable2[marker];
-           }
-           var offset = entry[0];
-           var enfoffset = offset + entry[1];
-           for (j = offset; j < enfoffset ; j++) {
-               if (swfJpegOffset) {
-                   jpegArray.join(swfJpeg[j]);
-               } else {
-                   jpegArray.join(jpegTables[j]);
-               }
-           }
-       }
-       return FlappString.ArrayToString(jpegArray).join('');
-    };
-    FlappBitmap.toPng = function(lossless) {
-       ;
-    };
-    global.FlappBitmap = FlappBitmap;
-})(this);
diff --git a/build.xml b/build.xml
new file mode 100644 (file)
index 0000000..c95c9c5
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<project name="project" default="all" >
+  <property name="level" value="ADVANCED_OPTIMIZATIONS"/>
+  <property name="src" value="./src"/>
+  <property name="vendor" value="./vendor"/>
+  <property name="bin" value="./bin"/>
+  <property name="compiler" value="build/compiler.jar"/>
+  <property name="closure_primitives" value="closure-primitives/base.js"/>
+  <property name="depswriter" value="closure-primitives/depswriter.py"/>
+  <property name="depend" value="deps.js"/>
+
+  <!-- ビルドの事前準備 -->
+  <target name="prebuild" description="ビルドの事前準備を行う">
+     <mkdir dir="${bin}"/>
+  </target>
+
+  <!-- 依存関係を解決する -->
+  <target name="deps" description="依存関係を解決する">
+    <exec executable="python" failonerror="true">
+      <arg line="${depswriter}"/>
+      <arg line="--root_with_prefix=&quot;. ..&quot;"/>
+      <arg line="--output_file=${depend}"/>
+    </exec>
+    <fileset dir="${src}" includes="**/*.js" id="srcpath"/>
+    <pathconvert property="srcfiles" refid="srcpath" pathsep=" "/>
+    <echo message="${srcfiles}"/>
+  </target>
+
+  <!-- ビルド -->
+  <target name="build" depends="deps,prebuild" description="ビルドを行う">
+    <!-- 出力ファイル名 -->
+    <local name="outfile"/>
+    <property name="outfile" value="${bin}/flapp.js"/>
+    <!-- ビルド -->
+    <java jar="${compiler}" fork="true" failonerror="true">
+      <arg line="--warning_level=VERBOSE"/>
+      <arg line="--compilation_level=${level}"/>
+      <arg line="--define=goog.DEBUG=false"/>
+      <arg line="--externs=console.js"/>
+      <arg line="--output_wrapper='(function() {%output%}).call(this);'"/>
+      <arg line="--summary_detail_level=3"/>
+      <arg line="--language_in=ECMASCRIPT5_STRICT"/>
+      <arg line="--js_output_file=${outfile}"/>
+      <arg line="--js=${closure_primitives}"/>
+      <arg line="--js=${depend}"/>
+      <arg line="${srcfiles}"/>
+    </java>
+  </target>
+
+  <!-- compiler help -->
+  <target name="help">
+    <java jar="${compiler}" fork="true" failonerror="true">
+      <arg line="--help"/>
+    </java>
+  </target>
+
+  <!-- 全て作成 -->
+  <target name="all" depends="build" />
+
+  <!--  削除 -->
+  <target name="clean">
+    <delete file="${depend}"/>
+    <delete dir="${bin}"/>
+  </target>
+
+  <!-- リビルド -->
+  <target name="rebuild" depends="clean,all"/>
+</project>
diff --git a/canvas.js b/canvas.js
deleted file mode 100644 (file)
index fb23db2..0000000
--- a/canvas.js
+++ /dev/null
@@ -1,10 +0,0 @@
-(function(global) {
-    var FlappCanvas = function(canvas) {
-       this.canvas = canvas;
-       this.ctx = canvas.getContext('2d');
-    };
-    FlappCanvas.prototype = {
-       
-    }
-    global.FlappCanvas = FlappCanvas;
-})(this);
diff --git a/closure-primitives/base.js b/closure-primitives/base.js
new file mode 100644 (file)
index 0000000..8793073
--- /dev/null
@@ -0,0 +1,1488 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Bootstrap for the Google JS Library (Closure).
+ *
+ * In uncompiled mode base.js will write out Closure's deps file, unless the
+ * global <code>CLOSURE_NO_DEPS</code> is set to true.  This allows projects to
+ * include their own deps file(s) from different locations.
+ *
+ *
+ * @provideGoog
+ */
+
+
+/**
+ * @define {boolean} Overridden to true by the compiler when --closure_pass
+ *     or --mark_as_compiled is specified.
+ */
+var COMPILED = false;
+
+
+/**
+ * Base namespace for the Closure library.  Checks to see goog is
+ * already defined in the current scope before assigning to prevent
+ * clobbering if base.js is loaded more than once.
+ *
+ * @const
+ */
+var goog = goog || {}; // Identifies this file as the Closure base.
+
+
+/**
+ * Reference to the global context.  In most cases this will be 'window'.
+ */
+goog.global = this;
+
+
+/**
+ * @define {boolean} DEBUG is provided as a convenience so that debugging code
+ * that should not be included in a production js_binary can be easily stripped
+ * by specifying --define goog.DEBUG=false to the JSCompiler. For example, most
+ * toString() methods should be declared inside an "if (goog.DEBUG)" conditional
+ * because they are generally used for debugging purposes and it is difficult
+ * for the JSCompiler to statically determine whether they are used.
+ */
+goog.DEBUG = true;
+
+
+/**
+ * @define {string} LOCALE defines the locale being used for compilation. It is
+ * used to select locale specific data to be compiled in js binary. BUILD rule
+ * can specify this value by "--define goog.LOCALE=<locale_name>" as JSCompiler
+ * option.
+ *
+ * Take into account that the locale code format is important. You should use
+ * the canonical Unicode format with hyphen as a delimiter. Language must be
+ * lowercase, Language Script - Capitalized, Region - UPPERCASE.
+ * There are few examples: pt-BR, en, en-US, sr-Latin-BO, zh-Hans-CN.
+ *
+ * See more info about locale codes here:
+ * http://www.unicode.org/reports/tr35/#Unicode_Language_and_Locale_Identifiers
+ *
+ * For language codes you should use values defined by ISO 693-1. See it here
+ * http://www.w3.org/WAI/ER/IG/ert/iso639.htm. There is only one exception from
+ * this rule: the Hebrew language. For legacy reasons the old code (iw) should
+ * be used instead of the new code (he), see http://wiki/Main/IIISynonyms.
+ */
+goog.LOCALE = 'en';  // default to en
+
+
+/**
+ * Creates object stubs for a namespace.  The presence of one or more
+ * goog.provide() calls indicate that the file defines the given
+ * objects/namespaces.  Build tools also scan for provide/require statements
+ * to discern dependencies, build dependency files (see deps.js), etc.
+ * @see goog.require
+ * @param {string} name Namespace provided by this file in the form
+ *     "goog.package.part".
+ */
+goog.provide = function(name) {
+  if (!COMPILED) {
+    // Ensure that the same namespace isn't provided twice. This is intended
+    // to teach new developers that 'goog.provide' is effectively a variable
+    // declaration. And when JSCompiler transforms goog.provide into a real
+    // variable declaration, the compiled JS should work the same as the raw
+    // JS--even when the raw JS uses goog.provide incorrectly.
+    if (goog.isProvided_(name)) {
+      throw Error('Namespace "' + name + '" already declared.');
+    }
+    delete goog.implicitNamespaces_[name];
+
+    var namespace = name;
+    while ((namespace = namespace.substring(0, namespace.lastIndexOf('.')))) {
+      if (goog.getObjectByName(namespace)) {
+        break;
+      }
+      goog.implicitNamespaces_[namespace] = true;
+    }
+  }
+
+  goog.exportPath_(name);
+};
+
+
+/**
+ * Marks that the current file should only be used for testing, and never for
+ * live code in production.
+ * @param {string=} opt_message Optional message to add to the error that's
+ *     raised when used in production code.
+ */
+goog.setTestOnly = function(opt_message) {
+  if (COMPILED && !goog.DEBUG) {
+    opt_message = opt_message || '';
+    throw Error('Importing test-only code into non-debug environment' +
+                opt_message ? ': ' + opt_message : '.');
+  }
+};
+
+
+if (!COMPILED) {
+
+  /**
+   * Check if the given name has been goog.provided. This will return false for
+   * names that are available only as implicit namespaces.
+   * @param {string} name name of the object to look for.
+   * @return {boolean} Whether the name has been provided.
+   * @private
+   */
+  goog.isProvided_ = function(name) {
+    return !goog.implicitNamespaces_[name] && !!goog.getObjectByName(name);
+  };
+
+  /**
+   * Namespaces implicitly defined by goog.provide. For example,
+   * goog.provide('goog.events.Event') implicitly declares
+   * that 'goog' and 'goog.events' must be namespaces.
+   *
+   * @type {Object}
+   * @private
+   */
+  goog.implicitNamespaces_ = {};
+}
+
+
+/**
+ * Builds an object structure for the provided namespace path,
+ * ensuring that names that already exist are not overwritten. For
+ * example:
+ * "a.b.c" -> a = {};a.b={};a.b.c={};
+ * Used by goog.provide and goog.exportSymbol.
+ * @param {string} name name of the object that this file defines.
+ * @param {*=} opt_object the object to expose at the end of the path.
+ * @param {Object=} opt_objectToExportTo The object to add the path to; default
+ *     is |goog.global|.
+ * @private
+ */
+goog.exportPath_ = function(name, opt_object, opt_objectToExportTo) {
+  var parts = name.split('.');
+  var cur = opt_objectToExportTo || goog.global;
+
+  // Internet Explorer exhibits strange behavior when throwing errors from
+  // methods externed in this manner.  See the testExportSymbolExceptions in
+  // base_test.html for an example.
+  if (!(parts[0] in cur) && cur.execScript) {
+    cur.execScript('var ' + parts[0]);
+  }
+
+  // Certain browsers cannot parse code in the form for((a in b); c;);
+  // This pattern is produced by the JSCompiler when it collapses the
+  // statement above into the conditional loop below. To prevent this from
+  // happening, use a for-loop and reserve the init logic as below.
+
+  // Parentheses added to eliminate strict JS warning in Firefox.
+  for (var part; parts.length && (part = parts.shift());) {
+    if (!parts.length && goog.isDef(opt_object)) {
+      // last part and we have an object; use it
+      cur[part] = opt_object;
+    } else if (cur[part]) {
+      cur = cur[part];
+    } else {
+      cur = cur[part] = {};
+    }
+  }
+};
+
+
+/**
+ * Returns an object based on its fully qualified external name.  If you are
+ * using a compilation pass that renames property names beware that using this
+ * function will not find renamed properties.
+ *
+ * @param {string} name The fully qualified name.
+ * @param {Object=} opt_obj The object within which to look; default is
+ *     |goog.global|.
+ * @return {?} The value (object or primitive) or, if not found, null.
+ */
+goog.getObjectByName = function(name, opt_obj) {
+  var parts = name.split('.');
+  var cur = opt_obj || goog.global;
+  for (var part; part = parts.shift(); ) {
+    if (goog.isDefAndNotNull(cur[part])) {
+      cur = cur[part];
+    } else {
+      return null;
+    }
+  }
+  return cur;
+};
+
+
+/**
+ * Globalizes a whole namespace, such as goog or goog.lang.
+ *
+ * @param {Object} obj The namespace to globalize.
+ * @param {Object=} opt_global The object to add the properties to.
+ * @deprecated Properties may be explicitly exported to the global scope, but
+ *     this should no longer be done in bulk.
+ */
+goog.globalize = function(obj, opt_global) {
+  var global = opt_global || goog.global;
+  for (var x in obj) {
+    global[x] = obj[x];
+  }
+};
+
+
+/**
+ * Adds a dependency from a file to the files it requires.
+ * @param {string} relPath The path to the js file.
+ * @param {Array} provides An array of strings with the names of the objects
+ *                         this file provides.
+ * @param {Array} requires An array of strings with the names of the objects
+ *                         this file requires.
+ */
+goog.addDependency = function(relPath, provides, requires) {
+  if (!COMPILED) {
+    var provide, require;
+    var path = relPath.replace(/\\/g, '/');
+    var deps = goog.dependencies_;
+    for (var i = 0; provide = provides[i]; i++) {
+      deps.nameToPath[provide] = path;
+      if (!(path in deps.pathToNames)) {
+        deps.pathToNames[path] = {};
+      }
+      deps.pathToNames[path][provide] = true;
+    }
+    for (var j = 0; require = requires[j]; j++) {
+      if (!(path in deps.requires)) {
+        deps.requires[path] = {};
+      }
+      deps.requires[path][require] = true;
+    }
+  }
+};
+
+
+
+
+// NOTE(nnaze): The debug DOM loader was included in base.js as an orignal
+// way to do "debug-mode" development.  The dependency system can sometimes
+// be confusing, as can the debug DOM loader's asyncronous nature.
+//
+// With the DOM loader, a call to goog.require() is not blocking -- the
+// script will not load until some point after the current script.  If a
+// namespace is needed at runtime, it needs to be defined in a previous
+// script, or loaded via require() with its registered dependencies.
+// User-defined namespaces may need their own deps file.  See http://go/js_deps,
+// http://go/genjsdeps, or, externally, DepsWriter.
+// http://code.google.com/closure/library/docs/depswriter.html
+//
+// Because of legacy clients, the DOM loader can't be easily removed from
+// base.js.  Work is being done to make it disableable or replaceable for
+// different environments (DOM-less JavaScript interpreters like Rhino or V8,
+// for example). See bootstrap/ for more information.
+
+
+/**
+ * @define {boolean} Whether to enable the debug loader.
+ *
+ * If enabled, a call to goog.require() will attempt to load the namespace by
+ * appending a script tag to the DOM (if the namespace has been registered).
+ *
+ * If disabled, goog.require() will simply assert that the namespace has been
+ * provided (and depend on the fact that some outside tool correctly ordered
+ * the script).
+ */
+goog.ENABLE_DEBUG_LOADER = true;
+
+
+/**
+ * Implements a system for the dynamic resolution of dependencies
+ * that works in parallel with the BUILD system. Note that all calls
+ * to goog.require will be stripped by the JSCompiler when the
+ * --closure_pass option is used.
+ * @see goog.provide
+ * @param {string} name Namespace to include (as was given in goog.provide())
+ *     in the form "goog.package.part".
+ */
+goog.require = function(name) {
+
+  // if the object already exists we do not need do do anything
+  // TODO(arv): If we start to support require based on file name this has
+  //            to change
+  // TODO(arv): If we allow goog.foo.* this has to change
+  // TODO(arv): If we implement dynamic load after page load we should probably
+  //            not remove this code for the compiled output
+  if (!COMPILED) {
+    if (goog.isProvided_(name)) {
+      return;
+    }
+
+    if (goog.ENABLE_DEBUG_LOADER) {
+      var path = goog.getPathFromDeps_(name);
+      if (path) {
+        goog.included_[path] = true;
+        goog.writeScripts_();
+        return;
+      }
+    }
+
+    var errorMessage = 'goog.require could not find: ' + name;
+    if (goog.global.console) {
+      goog.global.console['error'](errorMessage);
+    }
+
+
+      throw Error(errorMessage);
+
+  }
+};
+
+
+/**
+ * Path for included scripts
+ * @type {string}
+ */
+goog.basePath = '';
+
+
+/**
+ * A hook for overriding the base path.
+ * @type {string|undefined}
+ */
+goog.global.CLOSURE_BASE_PATH;
+
+
+/**
+ * Whether to write out Closure's deps file. By default,
+ * the deps are written.
+ * @type {boolean|undefined}
+ */
+goog.global.CLOSURE_NO_DEPS;
+
+
+/**
+ * A function to import a single script. This is meant to be overridden when
+ * Closure is being run in non-HTML contexts, such as web workers. It's defined
+ * in the global scope so that it can be set before base.js is loaded, which
+ * allows deps.js to be imported properly.
+ *
+ * The function is passed the script source, which is a relative URI. It should
+ * return true if the script was imported, false otherwise.
+ */
+goog.global.CLOSURE_IMPORT_SCRIPT;
+
+
+/**
+ * Null function used for default values of callbacks, etc.
+ * @return {void} Nothing.
+ */
+goog.nullFunction = function() {};
+
+
+/**
+ * The identity function. Returns its first argument.
+ *
+ * @param {*=} opt_returnValue The single value that will be returned.
+ * @param {...*} var_args Optional trailing arguments. These are ignored.
+ * @return {?} The first argument. We can't know the type -- just pass it along
+ *      without type.
+ * @deprecated Use goog.functions.identity instead.
+ */
+goog.identityFunction = function(opt_returnValue, var_args) {
+  return opt_returnValue;
+};
+
+
+/**
+ * When defining a class Foo with an abstract method bar(), you can do:
+ *
+ * Foo.prototype.bar = goog.abstractMethod
+ *
+ * Now if a subclass of Foo fails to override bar(), an error
+ * will be thrown when bar() is invoked.
+ *
+ * Note: This does not take the name of the function to override as
+ * an argument because that would make it more difficult to obfuscate
+ * our JavaScript code.
+ *
+ * @type {!Function}
+ * @throws {Error} when invoked to indicate the method should be
+ *   overridden.
+ */
+goog.abstractMethod = function() {
+  throw Error('unimplemented abstract method');
+};
+
+
+/**
+ * Adds a {@code getInstance} static method that always return the same instance
+ * object.
+ * @param {!Function} ctor The constructor for the class to add the static
+ *     method to.
+ */
+goog.addSingletonGetter = function(ctor) {
+  ctor.getInstance = function() {
+    if (ctor.instance_) {
+      return ctor.instance_;
+    }
+    if (goog.DEBUG) {
+      // NOTE: JSCompiler can't optimize away Array#push.
+      goog.instantiatedSingletons_[goog.instantiatedSingletons_.length] = ctor;
+    }
+    return ctor.instance_ = new ctor;
+  };
+};
+
+
+/**
+ * All singleton classes that have been instantiated, for testing. Don't read
+ * it directly, use the {@code goog.testing.singleton} module. The compiler
+ * removes this variable if unused.
+ * @type {!Array.<!Function>}
+ * @private
+ */
+goog.instantiatedSingletons_ = [];
+
+
+if (!COMPILED && goog.ENABLE_DEBUG_LOADER) {
+  /**
+   * Object used to keep track of urls that have already been added. This
+   * record allows the prevention of circular dependencies.
+   * @type {Object}
+   * @private
+   */
+  goog.included_ = {};
+
+
+  /**
+   * This object is used to keep track of dependencies and other data that is
+   * used for loading scripts
+   * @private
+   * @type {Object}
+   */
+  goog.dependencies_ = {
+    pathToNames: {}, // 1 to many
+    nameToPath: {}, // 1 to 1
+    requires: {}, // 1 to many
+    // used when resolving dependencies to prevent us from
+    // visiting the file twice
+    visited: {},
+    written: {} // used to keep track of script files we have written
+  };
+
+
+  /**
+   * Tries to detect whether is in the context of an HTML document.
+   * @return {boolean} True if it looks like HTML document.
+   * @private
+   */
+  goog.inHtmlDocument_ = function() {
+    var doc = goog.global.document;
+    return typeof doc != 'undefined' &&
+           'write' in doc;  // XULDocument misses write.
+  };
+
+
+  /**
+   * Tries to detect the base path of the base.js script that bootstraps Closure
+   * @private
+   */
+  goog.findBasePath_ = function() {
+    if (goog.global.CLOSURE_BASE_PATH) {
+      goog.basePath = goog.global.CLOSURE_BASE_PATH;
+      return;
+    } else if (!goog.inHtmlDocument_()) {
+      return;
+    }
+    var doc = goog.global.document;
+    var scripts = doc.getElementsByTagName('script');
+    // Search backwards since the current script is in almost all cases the one
+    // that has base.js.
+    for (var i = scripts.length - 1; i >= 0; --i) {
+      var src = scripts[i].src;
+      var qmark = src.lastIndexOf('?');
+      var l = qmark == -1 ? src.length : qmark;
+      if (src.substr(l - 7, 7) == 'base.js') {
+        goog.basePath = src.substr(0, l - 7);
+        return;
+      }
+    }
+  };
+
+
+  /**
+   * Imports a script if, and only if, that script hasn't already been imported.
+   * (Must be called at execution time)
+   * @param {string} src Script source.
+   * @private
+   */
+  goog.importScript_ = function(src) {
+    var importScript = goog.global.CLOSURE_IMPORT_SCRIPT ||
+        goog.writeScriptTag_;
+    if (!goog.dependencies_.written[src] && importScript(src)) {
+      goog.dependencies_.written[src] = true;
+    }
+  };
+
+
+  /**
+   * The default implementation of the import function. Writes a script tag to
+   * import the script.
+   *
+   * @param {string} src The script source.
+   * @return {boolean} True if the script was imported, false otherwise.
+   * @private
+   */
+  goog.writeScriptTag_ = function(src) {
+    if (goog.inHtmlDocument_()) {
+      var doc = goog.global.document;
+      doc.write(
+          '<script type="text/javascript" src="' + src + '"></' + 'script>');
+      return true;
+    } else {
+      return false;
+    }
+  };
+
+
+  /**
+   * Resolves dependencies based on the dependencies added using addDependency
+   * and calls importScript_ in the correct order.
+   * @private
+   */
+  goog.writeScripts_ = function() {
+    // the scripts we need to write this time
+    var scripts = [];
+    var seenScript = {};
+    var deps = goog.dependencies_;
+
+    function visitNode(path) {
+      if (path in deps.written) {
+        return;
+      }
+
+      // we have already visited this one. We can get here if we have cyclic
+      // dependencies
+      if (path in deps.visited) {
+        if (!(path in seenScript)) {
+          seenScript[path] = true;
+          scripts.push(path);
+        }
+        return;
+      }
+
+      deps.visited[path] = true;
+
+      if (path in deps.requires) {
+        for (var requireName in deps.requires[path]) {
+          // If the required name is defined, we assume that it was already
+          // bootstrapped by other means.
+          if (!goog.isProvided_(requireName)) {
+            if (requireName in deps.nameToPath) {
+              visitNode(deps.nameToPath[requireName]);
+            } else {
+              throw Error('Undefined nameToPath for ' + requireName);
+            }
+          }
+        }
+      }
+
+      if (!(path in seenScript)) {
+        seenScript[path] = true;
+        scripts.push(path);
+      }
+    }
+
+    for (var path in goog.included_) {
+      if (!deps.written[path]) {
+        visitNode(path);
+      }
+    }
+
+    for (var i = 0; i < scripts.length; i++) {
+      if (scripts[i]) {
+        goog.importScript_(goog.basePath + scripts[i]);
+      } else {
+        throw Error('Undefined script input');
+      }
+    }
+  };
+
+
+  /**
+   * Looks at the dependency rules and tries to determine the script file that
+   * fulfills a particular rule.
+   * @param {string} rule In the form goog.namespace.Class or project.script.
+   * @return {?string} Url corresponding to the rule, or null.
+   * @private
+   */
+  goog.getPathFromDeps_ = function(rule) {
+    if (rule in goog.dependencies_.nameToPath) {
+      return goog.dependencies_.nameToPath[rule];
+    } else {
+      return null;
+    }
+  };
+
+  goog.findBasePath_();
+
+  // Allow projects to manage the deps files themselves.
+  if (!goog.global.CLOSURE_NO_DEPS) {
+    goog.importScript_(goog.basePath + 'deps.js');
+  }
+}
+
+
+
+//==============================================================================
+// Language Enhancements
+//==============================================================================
+
+
+/**
+ * This is a "fixed" version of the typeof operator.  It differs from the typeof
+ * operator in such a way that null returns 'null' and arrays return 'array'.
+ * @param {*} value The value to get the type of.
+ * @return {string} The name of the type.
+ */
+goog.typeOf = function(value) {
+  var s = typeof value;
+  if (s == 'object') {
+    if (value) {
+      // Check these first, so we can avoid calling Object.prototype.toString if
+      // possible.
+      //
+      // IE improperly marshals tyepof across execution contexts, but a
+      // cross-context object will still return false for "instanceof Object".
+      if (value instanceof Array) {
+        return 'array';
+      } else if (value instanceof Object) {
+        return s;
+      }
+
+      // HACK: In order to use an Object prototype method on the arbitrary
+      //   value, the compiler requires the value be cast to type Object,
+      //   even though the ECMA spec explicitly allows it.
+      var className = Object.prototype.toString.call(
+          /** @type {Object} */ (value));
+      // In Firefox 3.6, attempting to access iframe window objects' length
+      // property throws an NS_ERROR_FAILURE, so we need to special-case it
+      // here.
+      if (className == '[object Window]') {
+        return 'object';
+      }
+
+      // We cannot always use constructor == Array or instanceof Array because
+      // different frames have different Array objects. In IE6, if the iframe
+      // where the array was created is destroyed, the array loses its
+      // prototype. Then dereferencing val.splice here throws an exception, so
+      // we can't use goog.isFunction. Calling typeof directly returns 'unknown'
+      // so that will work. In this case, this function will return false and
+      // most array functions will still work because the array is still
+      // array-like (supports length and []) even though it has lost its
+      // prototype.
+      // Mark Miller noticed that Object.prototype.toString
+      // allows access to the unforgeable [[Class]] property.
+      //  15.2.4.2 Object.prototype.toString ( )
+      //  When the toString method is called, the following steps are taken:
+      //      1. Get the [[Class]] property of this object.
+      //      2. Compute a string value by concatenating the three strings
+      //         "[object ", Result(1), and "]".
+      //      3. Return Result(2).
+      // and this behavior survives the destruction of the execution context.
+      if ((className == '[object Array]' ||
+           // In IE all non value types are wrapped as objects across window
+           // boundaries (not iframe though) so we have to do object detection
+           // for this edge case
+           typeof value.length == 'number' &&
+           typeof value.splice != 'undefined' &&
+           typeof value.propertyIsEnumerable != 'undefined' &&
+           !value.propertyIsEnumerable('splice')
+
+          )) {
+        return 'array';
+      }
+      // HACK: There is still an array case that fails.
+      //     function ArrayImpostor() {}
+      //     ArrayImpostor.prototype = [];
+      //     var impostor = new ArrayImpostor;
+      // this can be fixed by getting rid of the fast path
+      // (value instanceof Array) and solely relying on
+      // (value && Object.prototype.toString.vall(value) === '[object Array]')
+      // but that would require many more function calls and is not warranted
+      // unless closure code is receiving objects from untrusted sources.
+
+      // IE in cross-window calls does not correctly marshal the function type
+      // (it appears just as an object) so we cannot use just typeof val ==
+      // 'function'. However, if the object has a call property, it is a
+      // function.
+      if ((className == '[object Function]' ||
+          typeof value.call != 'undefined' &&
+          typeof value.propertyIsEnumerable != 'undefined' &&
+          !value.propertyIsEnumerable('call'))) {
+        return 'function';
+      }
+
+
+    } else {
+      return 'null';
+    }
+
+  } else if (s == 'function' && typeof value.call == 'undefined') {
+    // In Safari typeof nodeList returns 'function', and on Firefox
+    // typeof behaves similarly for HTML{Applet,Embed,Object}Elements
+    // and RegExps.  We would like to return object for those and we can
+    // detect an invalid function by making sure that the function
+    // object has a call method.
+    return 'object';
+  }
+  return s;
+};
+
+
+/**
+ * Returns true if the specified value is not |undefined|.
+ * WARNING: Do not use this to test if an object has a property. Use the in
+ * operator instead.  Additionally, this function assumes that the global
+ * undefined variable has not been redefined.
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is defined.
+ */
+goog.isDef = function(val) {
+  return val !== undefined;
+};
+
+
+/**
+ * Returns true if the specified value is |null|
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is null.
+ */
+goog.isNull = function(val) {
+  return val === null;
+};
+
+
+/**
+ * Returns true if the specified value is defined and not null
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is defined and not null.
+ */
+goog.isDefAndNotNull = function(val) {
+  // Note that undefined == null.
+  return val != null;
+};
+
+
+/**
+ * Returns true if the specified value is an array
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is an array.
+ */
+goog.isArray = function(val) {
+  return goog.typeOf(val) == 'array';
+};
+
+
+/**
+ * Returns true if the object looks like an array. To qualify as array like
+ * the value needs to be either a NodeList or an object with a Number length
+ * property.
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is an array.
+ */
+goog.isArrayLike = function(val) {
+  var type = goog.typeOf(val);
+  return type == 'array' || type == 'object' && typeof val.length == 'number';
+};
+
+
+/**
+ * Returns true if the object looks like a Date. To qualify as Date-like
+ * the value needs to be an object and have a getFullYear() function.
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is a like a Date.
+ */
+goog.isDateLike = function(val) {
+  return goog.isObject(val) && typeof val.getFullYear == 'function';
+};
+
+
+/**
+ * Returns true if the specified value is a string
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is a string.
+ */
+goog.isString = function(val) {
+  return typeof val == 'string';
+};
+
+
+/**
+ * Returns true if the specified value is a boolean
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is boolean.
+ */
+goog.isBoolean = function(val) {
+  return typeof val == 'boolean';
+};
+
+
+/**
+ * Returns true if the specified value is a number
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is a number.
+ */
+goog.isNumber = function(val) {
+  return typeof val == 'number';
+};
+
+
+/**
+ * Returns true if the specified value is a function
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is a function.
+ */
+goog.isFunction = function(val) {
+  return goog.typeOf(val) == 'function';
+};
+
+
+/**
+ * Returns true if the specified value is an object.  This includes arrays
+ * and functions.
+ * @param {*} val Variable to test.
+ * @return {boolean} Whether variable is an object.
+ */
+goog.isObject = function(val) {
+  var type = typeof val;
+  return type == 'object' && val != null || type == 'function';
+  // return Object(val) === val also works, but is slower, especially if val is
+  // not an object.
+};
+
+
+/**
+ * Gets a unique ID for an object. This mutates the object so that further
+ * calls with the same object as a parameter returns the same value. The unique
+ * ID is guaranteed to be unique across the current session amongst objects that
+ * are passed into {@code getUid}. There is no guarantee that the ID is unique
+ * or consistent across sessions. It is unsafe to generate unique ID for
+ * function prototypes.
+ *
+ * @param {Object} obj The object to get the unique ID for.
+ * @return {number} The unique ID for the object.
+ */
+goog.getUid = function(obj) {
+  // TODO(arv): Make the type stricter, do not accept null.
+
+  // In Opera window.hasOwnProperty exists but always returns false so we avoid
+  // using it. As a consequence the unique ID generated for BaseClass.prototype
+  // and SubClass.prototype will be the same.
+  return obj[goog.UID_PROPERTY_] ||
+      (obj[goog.UID_PROPERTY_] = ++goog.uidCounter_);
+};
+
+
+/**
+ * Removes the unique ID from an object. This is useful if the object was
+ * previously mutated using {@code goog.getUid} in which case the mutation is
+ * undone.
+ * @param {Object} obj The object to remove the unique ID field from.
+ */
+goog.removeUid = function(obj) {
+  // TODO(arv): Make the type stricter, do not accept null.
+
+  // DOM nodes in IE are not instance of Object and throws exception
+  // for delete. Instead we try to use removeAttribute
+  if ('removeAttribute' in obj) {
+    obj.removeAttribute(goog.UID_PROPERTY_);
+  }
+  /** @preserveTry */
+  try {
+    delete obj[goog.UID_PROPERTY_];
+  } catch (ex) {
+  }
+};
+
+
+/**
+ * Name for unique ID property. Initialized in a way to help avoid collisions
+ * with other closure javascript on the same page.
+ * @type {string}
+ * @private
+ */
+goog.UID_PROPERTY_ = 'closure_uid_' +
+    Math.floor(Math.random() * 2147483648).toString(36);
+
+
+/**
+ * Counter for UID.
+ * @type {number}
+ * @private
+ */
+goog.uidCounter_ = 0;
+
+
+/**
+ * Adds a hash code field to an object. The hash code is unique for the
+ * given object.
+ * @param {Object} obj The object to get the hash code for.
+ * @return {number} The hash code for the object.
+ * @deprecated Use goog.getUid instead.
+ */
+goog.getHashCode = goog.getUid;
+
+
+/**
+ * Removes the hash code field from an object.
+ * @param {Object} obj The object to remove the field from.
+ * @deprecated Use goog.removeUid instead.
+ */
+goog.removeHashCode = goog.removeUid;
+
+
+/**
+ * Clones a value. The input may be an Object, Array, or basic type. Objects and
+ * arrays will be cloned recursively.
+ *
+ * WARNINGS:
+ * <code>goog.cloneObject</code> does not detect reference loops. Objects that
+ * refer to themselves will cause infinite recursion.
+ *
+ * <code>goog.cloneObject</code> is unaware of unique identifiers, and copies
+ * UIDs created by <code>getUid</code> into cloned results.
+ *
+ * @param {*} obj The value to clone.
+ * @return {*} A clone of the input value.
+ * @deprecated goog.cloneObject is unsafe. Prefer the goog.object methods.
+ */
+goog.cloneObject = function(obj) {
+  var type = goog.typeOf(obj);
+  if (type == 'object' || type == 'array') {
+    if (obj.clone) {
+      return obj.clone();
+    }
+    var clone = type == 'array' ? [] : {};
+    for (var key in obj) {
+      clone[key] = goog.cloneObject(obj[key]);
+    }
+    return clone;
+  }
+
+  return obj;
+};
+
+
+/**
+ * A native implementation of goog.bind.
+ * @param {Function} fn A function to partially apply.
+ * @param {Object|undefined} selfObj Specifies the object which |this| should
+ *     point to when the function is run.
+ * @param {...*} var_args Additional arguments that are partially
+ *     applied to the function.
+ * @return {!Function} A partially-applied form of the function bind() was
+ *     invoked as a method of.
+ * @private
+ * @suppress {deprecated} The compiler thinks that Function.prototype.bind
+ *     is deprecated because some people have declared a pure-JS version.
+ *     Only the pure-JS version is truly deprecated.
+ */
+goog.bindNative_ = function(fn, selfObj, var_args) {
+  return /** @type {!Function} */ (fn.call.apply(fn.bind, arguments));
+};
+
+
+/**
+ * A pure-JS implementation of goog.bind.
+ * @param {Function} fn A function to partially apply.
+ * @param {Object|undefined} selfObj Specifies the object which |this| should
+ *     point to when the function is run.
+ * @param {...*} var_args Additional arguments that are partially
+ *     applied to the function.
+ * @return {!Function} A partially-applied form of the function bind() was
+ *     invoked as a method of.
+ * @private
+ */
+goog.bindJs_ = function(fn, selfObj, var_args) {
+  if (!fn) {
+    throw new Error();
+  }
+
+  if (arguments.length > 2) {
+    var boundArgs = Array.prototype.slice.call(arguments, 2);
+    return function() {
+      // Prepend the bound arguments to the current arguments.
+      var newArgs = Array.prototype.slice.call(arguments);
+      Array.prototype.unshift.apply(newArgs, boundArgs);
+      return fn.apply(selfObj, newArgs);
+    };
+
+  } else {
+    return function() {
+      return fn.apply(selfObj, arguments);
+    };
+  }
+};
+
+
+/**
+ * Partially applies this function to a particular 'this object' and zero or
+ * more arguments. The result is a new function with some arguments of the first
+ * function pre-filled and the value of |this| 'pre-specified'.<br><br>
+ *
+ * Remaining arguments specified at call-time are appended to the pre-
+ * specified ones.<br><br>
+ *
+ * Also see: {@link #partial}.<br><br>
+ *
+ * Usage:
+ * <pre>var barMethBound = bind(myFunction, myObj, 'arg1', 'arg2');
+ * barMethBound('arg3', 'arg4');</pre>
+ *
+ * @param {Function} fn A function to partially apply.
+ * @param {Object|undefined} selfObj Specifies the object which |this| should
+ *     point to when the function is run.
+ * @param {...*} var_args Additional arguments that are partially
+ *     applied to the function.
+ * @return {!Function} A partially-applied form of the function bind() was
+ *     invoked as a method of.
+ * @suppress {deprecated} See above.
+ */
+goog.bind = function(fn, selfObj, var_args) {
+  // TODO(nicksantos): narrow the type signature.
+  if (Function.prototype.bind &&
+      // NOTE(nicksantos): Somebody pulled base.js into the default
+      // Chrome extension environment. This means that for Chrome extensions,
+      // they get the implementation of Function.prototype.bind that
+      // calls goog.bind instead of the native one. Even worse, we don't want
+      // to introduce a circular dependency between goog.bind and
+      // Function.prototype.bind, so we have to hack this to make sure it
+      // works correctly.
+      Function.prototype.bind.toString().indexOf('native code') != -1) {
+    goog.bind = goog.bindNative_;
+  } else {
+    goog.bind = goog.bindJs_;
+  }
+  return goog.bind.apply(null, arguments);
+};
+
+
+/**
+ * Like bind(), except that a 'this object' is not required. Useful when the
+ * target function is already bound.
+ *
+ * Usage:
+ * var g = partial(f, arg1, arg2);
+ * g(arg3, arg4);
+ *
+ * @param {Function} fn A function to partially apply.
+ * @param {...*} var_args Additional arguments that are partially
+ *     applied to fn.
+ * @return {!Function} A partially-applied form of the function bind() was
+ *     invoked as a method of.
+ */
+goog.partial = function(fn, var_args) {
+  var args = Array.prototype.slice.call(arguments, 1);
+  return function() {
+    // Prepend the bound arguments to the current arguments.
+    var newArgs = Array.prototype.slice.call(arguments);
+    newArgs.unshift.apply(newArgs, args);
+    return fn.apply(this, newArgs);
+  };
+};
+
+
+/**
+ * Copies all the members of a source object to a target object. This method
+ * does not work on all browsers for all objects that contain keys such as
+ * toString or hasOwnProperty. Use goog.object.extend for this purpose.
+ * @param {Object} target Target.
+ * @param {Object} source Source.
+ */
+goog.mixin = function(target, source) {
+  for (var x in source) {
+    target[x] = source[x];
+  }
+
+  // For IE7 or lower, the for-in-loop does not contain any properties that are
+  // not enumerable on the prototype object (for example, isPrototypeOf from
+  // Object.prototype) but also it will not include 'replace' on objects that
+  // extend String and change 'replace' (not that it is common for anyone to
+  // extend anything except Object).
+};
+
+
+/**
+ * @return {number} An integer value representing the number of milliseconds
+ *     between midnight, January 1, 1970 and the current time.
+ */
+goog.now = Date.now || (function() {
+  // Unary plus operator converts its operand to a number which in the case of
+  // a date is done by calling getTime().
+  return +new Date();
+});
+
+
+/**
+ * Evals javascript in the global scope.  In IE this uses execScript, other
+ * browsers use goog.global.eval. If goog.global.eval does not evaluate in the
+ * global scope (for example, in Safari), appends a script tag instead.
+ * Throws an exception if neither execScript or eval is defined.
+ * @param {string} script JavaScript string.
+ */
+goog.globalEval = function(script) {
+  if (goog.global.execScript) {
+    goog.global.execScript(script, 'JavaScript');
+  } else if (goog.global.eval) {
+    // Test to see if eval works
+    if (goog.evalWorksForGlobals_ == null) {
+      goog.global.eval('var _et_ = 1;');
+      if (typeof goog.global['_et_'] != 'undefined') {
+        delete goog.global['_et_'];
+        goog.evalWorksForGlobals_ = true;
+      } else {
+        goog.evalWorksForGlobals_ = false;
+      }
+    }
+
+    if (goog.evalWorksForGlobals_) {
+      goog.global.eval(script);
+    } else {
+      var doc = goog.global.document;
+      var scriptElt = doc.createElement('script');
+      scriptElt.type = 'text/javascript';
+      scriptElt.defer = false;
+      // Note(user): can't use .innerHTML since "t('<test>')" will fail and
+      // .text doesn't work in Safari 2.  Therefore we append a text node.
+      scriptElt.appendChild(doc.createTextNode(script));
+      doc.body.appendChild(scriptElt);
+      doc.body.removeChild(scriptElt);
+    }
+  } else {
+    throw Error('goog.globalEval not available');
+  }
+};
+
+
+/**
+ * Indicates whether or not we can call 'eval' directly to eval code in the
+ * global scope. Set to a Boolean by the first call to goog.globalEval (which
+ * empirically tests whether eval works for globals). @see goog.globalEval
+ * @type {?boolean}
+ * @private
+ */
+goog.evalWorksForGlobals_ = null;
+
+
+/**
+ * Optional map of CSS class names to obfuscated names used with
+ * goog.getCssName().
+ * @type {Object|undefined}
+ * @private
+ * @see goog.setCssNameMapping
+ */
+goog.cssNameMapping_;
+
+
+/**
+ * Optional obfuscation style for CSS class names. Should be set to either
+ * 'BY_WHOLE' or 'BY_PART' if defined.
+ * @type {string|undefined}
+ * @private
+ * @see goog.setCssNameMapping
+ */
+goog.cssNameMappingStyle_;
+
+
+/**
+ * Handles strings that are intended to be used as CSS class names.
+ *
+ * This function works in tandem with @see goog.setCssNameMapping.
+ *
+ * Without any mapping set, the arguments are simple joined with a
+ * hyphen and passed through unaltered.
+ *
+ * When there is a mapping, there are two possible styles in which
+ * these mappings are used. In the BY_PART style, each part (i.e. in
+ * between hyphens) of the passed in css name is rewritten according
+ * to the map. In the BY_WHOLE style, the full css name is looked up in
+ * the map directly. If a rewrite is not specified by the map, the
+ * compiler will output a warning.
+ *
+ * When the mapping is passed to the compiler, it will replace calls
+ * to goog.getCssName with the strings from the mapping, e.g.
+ *     var x = goog.getCssName('foo');
+ *     var y = goog.getCssName(this.baseClass, 'active');
+ *  becomes:
+ *     var x= 'foo';
+ *     var y = this.baseClass + '-active';
+ *
+ * If one argument is passed it will be processed, if two are passed
+ * only the modifier will be processed, as it is assumed the first
+ * argument was generated as a result of calling goog.getCssName.
+ *
+ * @param {string} className The class name.
+ * @param {string=} opt_modifier A modifier to be appended to the class name.
+ * @return {string} The class name or the concatenation of the class name and
+ *     the modifier.
+ */
+goog.getCssName = function(className, opt_modifier) {
+  var getMapping = function(cssName) {
+    return goog.cssNameMapping_[cssName] || cssName;
+  };
+
+  var renameByParts = function(cssName) {
+    // Remap all the parts individually.
+    var parts = cssName.split('-');
+    var mapped = [];
+    for (var i = 0; i < parts.length; i++) {
+      mapped.push(getMapping(parts[i]));
+    }
+    return mapped.join('-');
+  };
+
+  var rename;
+  if (goog.cssNameMapping_) {
+    rename = goog.cssNameMappingStyle_ == 'BY_WHOLE' ?
+        getMapping : renameByParts;
+  } else {
+    rename = function(a) {
+      return a;
+    };
+  }
+
+  if (opt_modifier) {
+    return className + '-' + rename(opt_modifier);
+  } else {
+    return rename(className);
+  }
+};
+
+
+/**
+ * Sets the map to check when returning a value from goog.getCssName(). Example:
+ * <pre>
+ * goog.setCssNameMapping({
+ *   "goog": "a",
+ *   "disabled": "b",
+ * });
+ *
+ * var x = goog.getCssName('goog');
+ * // The following evaluates to: "a a-b".
+ * goog.getCssName('goog') + ' ' + goog.getCssName(x, 'disabled')
+ * </pre>
+ * When declared as a map of string literals to string literals, the JSCompiler
+ * will replace all calls to goog.getCssName() using the supplied map if the
+ * --closure_pass flag is set.
+ *
+ * @param {!Object} mapping A map of strings to strings where keys are possible
+ *     arguments to goog.getCssName() and values are the corresponding values
+ *     that should be returned.
+ * @param {string=} opt_style The style of css name mapping. There are two valid
+ *     options: 'BY_PART', and 'BY_WHOLE'.
+ * @see goog.getCssName for a description.
+ */
+goog.setCssNameMapping = function(mapping, opt_style) {
+  goog.cssNameMapping_ = mapping;
+  goog.cssNameMappingStyle_ = opt_style;
+};
+
+
+/**
+ * To use CSS renaming in compiled mode, one of the input files should have a
+ * call to goog.setCssNameMapping() with an object literal that the JSCompiler
+ * can extract and use to replace all calls to goog.getCssName(). In uncompiled
+ * mode, JavaScript code should be loaded before this base.js file that declares
+ * a global variable, CLOSURE_CSS_NAME_MAPPING, which is used below. This is
+ * to ensure that the mapping is loaded before any calls to goog.getCssName()
+ * are made in uncompiled mode.
+ *
+ * A hook for overriding the CSS name mapping.
+ * @type {Object|undefined}
+ */
+goog.global.CLOSURE_CSS_NAME_MAPPING;
+
+
+if (!COMPILED && goog.global.CLOSURE_CSS_NAME_MAPPING) {
+  // This does not call goog.setCssNameMapping() because the JSCompiler
+  // requires that goog.setCssNameMapping() be called with an object literal.
+  goog.cssNameMapping_ = goog.global.CLOSURE_CSS_NAME_MAPPING;
+}
+
+
+/**
+ * Abstract implementation of goog.getMsg for use with localized messages.
+ * @param {string} str Translatable string, places holders in the form {$foo}.
+ * @param {Object=} opt_values Map of place holder name to value.
+ * @return {string} message with placeholders filled.
+ */
+goog.getMsg = function(str, opt_values) {
+  var values = opt_values || {};
+  for (var key in values) {
+    var value = ('' + values[key]).replace(/\$/g, '$$$$');
+    str = str.replace(new RegExp('\\{\\$' + key + '\\}', 'gi'), value);
+  }
+  return str;
+};
+
+
+/**
+ * Exposes an unobfuscated global namespace path for the given object.
+ * Note that fields of the exported object *will* be obfuscated,
+ * unless they are exported in turn via this function or
+ * goog.exportProperty
+ *
+ * <p>Also handy for making public items that are defined in anonymous
+ * closures.
+ *
+ * ex. goog.exportSymbol('public.path.Foo', Foo);
+ *
+ * ex. goog.exportSymbol('public.path.Foo.staticFunction',
+ *                       Foo.staticFunction);
+ *     public.path.Foo.staticFunction();
+ *
+ * ex. goog.exportSymbol('public.path.Foo.prototype.myMethod',
+ *                       Foo.prototype.myMethod);
+ *     new public.path.Foo().myMethod();
+ *
+ * @param {string} publicPath Unobfuscated name to export.
+ * @param {*} object Object the name should point to.
+ * @param {Object=} opt_objectToExportTo The object to add the path to; default
+ *     is |goog.global|.
+ */
+goog.exportSymbol = function(publicPath, object, opt_objectToExportTo) {
+  goog.exportPath_(publicPath, object, opt_objectToExportTo);
+};
+
+
+/**
+ * Exports a property unobfuscated into the object's namespace.
+ * ex. goog.exportProperty(Foo, 'staticFunction', Foo.staticFunction);
+ * ex. goog.exportProperty(Foo.prototype, 'myMethod', Foo.prototype.myMethod);
+ * @param {Object} object Object whose static property is being exported.
+ * @param {string} publicName Unobfuscated name to export.
+ * @param {*} symbol Object the name should point to.
+ */
+goog.exportProperty = function(object, publicName, symbol) {
+  object[publicName] = symbol;
+};
+
+
+/**
+ * Inherit the prototype methods from one constructor into another.
+ *
+ * Usage:
+ * <pre>
+ * function ParentClass(a, b) { }
+ * ParentClass.prototype.foo = function(a) { }
+ *
+ * function ChildClass(a, b, c) {
+ *   goog.base(this, a, b);
+ * }
+ * goog.inherits(ChildClass, ParentClass);
+ *
+ * var child = new ChildClass('a', 'b', 'see');
+ * child.foo(); // works
+ * </pre>
+ *
+ * In addition, a superclass' implementation of a method can be invoked
+ * as follows:
+ *
+ * <pre>
+ * ChildClass.prototype.foo = function(a) {
+ *   ChildClass.superClass_.foo.call(this, a);
+ *   // other code
+ * };
+ * </pre>
+ *
+ * @param {Function} childCtor Child class.
+ * @param {Function} parentCtor Parent class.
+ */
+goog.inherits = function(childCtor, parentCtor) {
+  /** @constructor */
+  function tempCtor() {};
+  tempCtor.prototype = parentCtor.prototype;
+  childCtor.superClass_ = parentCtor.prototype;
+  childCtor.prototype = new tempCtor();
+  /** @override */
+  childCtor.prototype.constructor = childCtor;
+};
+
+
+/**
+ * Call up to the superclass.
+ *
+ * If this is called from a constructor, then this calls the superclass
+ * contructor with arguments 1-N.
+ *
+ * If this is called from a prototype method, then you must pass
+ * the name of the method as the second argument to this function. If
+ * you do not, you will get a runtime error. This calls the superclass'
+ * method with arguments 2-N.
+ *
+ * This function only works if you use goog.inherits to express
+ * inheritance relationships between your classes.
+ *
+ * This function is a compiler primitive. At compile-time, the
+ * compiler will do macro expansion to remove a lot of
+ * the extra overhead that this function introduces. The compiler
+ * will also enforce a lot of the assumptions that this function
+ * makes, and treat it as a compiler error if you break them.
+ *
+ * @param {!Object} me Should always be "this".
+ * @param {*=} opt_methodName The method name if calling a super method.
+ * @param {...*} var_args The rest of the arguments.
+ * @return {*} The return value of the superclass method.
+ */
+goog.base = function(me, opt_methodName, var_args) {
+  var caller = arguments.callee.caller;
+  if (caller.superClass_) {
+    // This is a constructor. Call the superclass constructor.
+    return caller.superClass_.constructor.apply(
+        me, Array.prototype.slice.call(arguments, 1));
+  }
+
+  var args = Array.prototype.slice.call(arguments, 2);
+  var foundCaller = false;
+  for (var ctor = me.constructor;
+       ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) {
+    if (ctor.prototype[opt_methodName] === caller) {
+      foundCaller = true;
+    } else if (foundCaller) {
+      return ctor.prototype[opt_methodName].apply(me, args);
+    }
+  }
+
+  // If we did not find the caller in the prototype chain,
+  // then one of two things happened:
+  // 1) The caller is an instance method.
+  // 2) This method was not called by the right caller.
+  if (me[opt_methodName] === caller) {
+    return me.constructor.prototype[opt_methodName].apply(me, args);
+  } else {
+    throw Error(
+        'goog.base called from a method of one name ' +
+        'to a method of a different name');
+  }
+};
+
+
+/**
+ * Allow for aliasing within scope functions.  This function exists for
+ * uncompiled code - in compiled code the calls will be inlined and the
+ * aliases applied.  In uncompiled code the function is simply run since the
+ * aliases as written are valid JavaScript.
+ * @param {function()} fn Function to call.  This function can contain aliases
+ *     to namespaces (e.g. "var dom = goog.dom") or classes
+ *    (e.g. "var Timer = goog.Timer").
+ */
+goog.scope = function(fn) {
+  fn.call(goog.global);
+};
+
+
diff --git a/closure-primitives/depswriter.py b/closure-primitives/depswriter.py
new file mode 100755 (executable)
index 0000000..dfecc4b
--- /dev/null
@@ -0,0 +1,202 @@
+#!/usr/bin/env python
+#
+# Copyright 2009 The Closure Library Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS-IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""Generates out a Closure deps.js file given a list of JavaScript sources.
+
+Paths can be specified as arguments or (more commonly) specifying trees
+with the flags (call with --help for descriptions).
+
+Usage: depswriter.py [path/to/js1.js [path/to/js2.js] ...]
+"""
+
+import logging
+import optparse
+import os
+import posixpath
+import shlex
+import sys
+
+import source
+import treescan
+
+
+__author__ = 'nnaze@google.com (Nathan Naze)'
+
+
+def MakeDepsFile(source_map):
+  """Make a generated deps file.
+
+  Args:
+    source_map: A dict map of the source path to source.Source object.
+
+  Returns:
+    str, A generated deps file source.
+  """
+
+  # Write in path alphabetical order
+  paths = sorted(source_map.keys())
+
+  lines = []
+
+  for path in paths:
+    js_source = source_map[path]
+
+    # We don't need to add entries that don't provide anything.
+    if js_source.provides:
+      lines.append(_GetDepsLine(path, js_source))
+
+  return ''.join(lines)
+
+
+def _GetDepsLine(path, js_source):
+  """Get a deps.js file string for a source."""
+
+  provides = sorted(js_source.provides)
+  requires = sorted(js_source.requires)
+
+  return 'goog.addDependency(\'%s\', %s, %s);\n' % (path, provides, requires)
+
+
+def _GetOptionsParser():
+  """Get the options parser."""
+
+  parser = optparse.OptionParser(__doc__)
+
+  parser.add_option('--output_file',
+                    dest='output_file',
+                    action='store',
+                    help=('If specified, write output to this path instead of '
+                          'writing to standard output.'))
+  parser.add_option('--root',
+                    dest='roots',
+                    default=[],
+                    action='append',
+                    help='A root directory to scan for JS source files. '
+                    'Paths of JS files in generated deps file will be '
+                    'relative to this path.  This flag may be specified '
+                    'multiple times.')
+  parser.add_option('--root_with_prefix',
+                    dest='roots_with_prefix',
+                    default=[],
+                    action='append',
+                    help='A root directory to scan for JS source files, plus '
+                    'a prefix (if either contains a space, surround with '
+                    'quotes).  Paths in generated deps file will be relative '
+                    'to the root, but preceded by the prefix.  This flag '
+                    'may be specified multiple times.')
+  parser.add_option('--path_with_depspath',
+                    dest='paths_with_depspath',
+                    default=[],
+                    action='append',
+                    help='A path to a source file and an alternate path to '
+                    'the file in the generated deps file (if either contains '
+                    'a space, surround with whitespace). This flag may be '
+                    'specified multiple times.')
+  return parser
+
+
+def _NormalizePathSeparators(path):
+  """Replaces OS-specific path separators with POSIX-style slashes.
+
+  Args:
+    path: str, A file path.
+
+  Returns:
+    str, The path with any OS-specific path separators (such as backslash on
+      Windows) replaced with URL-compatible forward slashes. A no-op on systems
+      that use POSIX paths.
+  """
+  return path.replace(os.sep, posixpath.sep)
+
+
+def _GetRelativePathToSourceDict(root, prefix=''):
+  """Scans a top root directory for .js sources.
+
+  Args:
+    root: str, Root directory.
+    prefix: str, Prefix for returned paths.
+
+  Returns:
+    dict, A map of relative paths (with prefix, if given), to source.Source
+      objects.
+  """
+  # Remember and restore the cwd when we're done. We work from the root so
+  # that paths are relative from the root.
+  start_wd = os.getcwd()
+  os.chdir(root)
+
+  path_to_source = {}
+  for path in treescan.ScanTreeForJsFiles('.'):
+    prefixed_path = _NormalizePathSeparators(os.path.join(prefix, path))
+    path_to_source[prefixed_path] = source.Source(source.GetFileContents(path))
+
+  os.chdir(start_wd)
+
+  return path_to_source
+
+
+def _GetPair(s):
+  """Return a string as a shell-parsed tuple.  Two values expected."""
+  try:
+    # shlex uses '\' as an escape character, so they must be escaped.
+    s = s.replace('\\', '\\\\')
+    first, second = shlex.split(s)
+    return (first, second)
+  except:
+    raise Exception('Unable to parse input line as a pair: %s' % s)
+
+
+def main():
+  """CLI frontend to MakeDepsFile."""
+  logging.basicConfig(format=(sys.argv[0] + ': %(message)s'),
+                      level=logging.INFO)
+  options, args = _GetOptionsParser().parse_args()
+
+  path_to_source = {}
+
+  # Roots without prefixes
+  for root in options.roots:
+    path_to_source.update(_GetRelativePathToSourceDict(root))
+
+  # Roots with prefixes
+  for root_and_prefix in options.roots_with_prefix:
+    root, prefix = _GetPair(root_and_prefix)
+    path_to_source.update(_GetRelativePathToSourceDict(root, prefix=prefix))
+
+  # Source paths
+  for path in args:
+    path_to_source[path] = source.Source(source.GetFileContents(path))
+
+  # Source paths with alternate deps paths
+  for path_with_depspath in options.paths_with_depspath:
+    srcpath, depspath = _GetPair(path_with_depspath)
+    path_to_source[depspath] = source.Source(source.GetFileContents(srcpath))
+
+  # Make our output pipe.
+  if options.output_file:
+    out = open(options.output_file, 'w')
+  else:
+    out = sys.stdout
+
+  out.write('// This file was autogenerated by %s.\n' % sys.argv[0])
+  out.write('// Please do not edit.\n')
+
+  out.write(MakeDepsFile(path_to_source))
+
+
+if __name__ == '__main__':
+  main()
diff --git a/closure-primitives/source.py b/closure-primitives/source.py
new file mode 100755 (executable)
index 0000000..c2ee1fb
--- /dev/null
@@ -0,0 +1,114 @@
+# Copyright 2009 The Closure Library Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS-IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""Scans a source JS file for its provided and required namespaces.
+
+Simple class to scan a JavaScript file and express its dependencies.
+"""
+
+__author__ = 'nnaze@google.com'
+
+
+import re
+
+_BASE_REGEX_STRING = '^\s*goog\.%s\(\s*[\'"](.+)[\'"]\s*\)'
+_PROVIDE_REGEX = re.compile(_BASE_REGEX_STRING % 'provide')
+_REQUIRES_REGEX = re.compile(_BASE_REGEX_STRING % 'require')
+
+# This line identifies base.js and should match the line in that file.
+_GOOG_BASE_LINE = (
+    'var goog = goog || {}; // Identifies this file as the Closure base.')
+
+
+class Source(object):
+  """Scans a JavaScript source for its provided and required namespaces."""
+
+  # Matches a "/* ... */" comment.
+  # Note: We can't definitively distinguish a "/*" in a string literal without a
+  # state machine tokenizer. We'll assume that a line starting with whitespace
+  # and "/*" is a comment.
+  _COMMENT_REGEX = re.compile(
+      r"""
+      ^\s*   # Start of a new line and whitespace
+      /\*    # Opening "/*"
+      .*?    # Non greedy match of any characters (including newlines)
+      \*/    # Closing "*/""",
+      re.MULTILINE | re.DOTALL | re.VERBOSE)
+
+  def __init__(self, source):
+    """Initialize a source.
+
+    Args:
+      source: str, The JavaScript source.
+    """
+
+    self.provides = set()
+    self.requires = set()
+
+    self._source = source
+    self._ScanSource()
+
+  def __str__(self):
+    return 'Source %s' % self._path
+
+  def GetSource(self):
+    """Get the source as a string."""
+    return self._source
+
+  @classmethod
+  def _StripComments(cls, source):
+    return cls._COMMENT_REGEX.sub('', source)
+
+  def _ScanSource(self):
+    """Fill in provides and requires by scanning the source."""
+
+    source = self._StripComments(self.GetSource())
+
+    source_lines = source.splitlines()
+    for line in source_lines:
+      match = _PROVIDE_REGEX.match(line)
+      if match:
+        self.provides.add(match.group(1))
+      match = _REQUIRES_REGEX.match(line)
+      if match:
+        self.requires.add(match.group(1))
+
+    # Closure's base file implicitly provides 'goog'.
+    for line in source_lines:
+      if line == _GOOG_BASE_LINE:
+        if len(self.provides) or len(self.requires):
+          raise Exception(
+              'Base files should not provide or require namespaces.')
+        self.provides.add('goog')
+
+
+def GetFileContents(path):
+  """Get a file's contents as a string.
+
+  Args:
+    path: str, Path to file.
+
+  Returns:
+    str, Contents of file.
+
+  Raises:
+    IOError: An error occurred opening or reading the file.
+
+  """
+  fileobj = open(path)
+  try:
+    return fileobj.read()
+  finally:
+    fileobj.close()
diff --git a/closure-primitives/source.pyc b/closure-primitives/source.pyc
new file mode 100644 (file)
index 0000000..84523ff
Binary files /dev/null and b/closure-primitives/source.pyc differ
diff --git a/closure-primitives/treescan.py b/closure-primitives/treescan.py
new file mode 100755 (executable)
index 0000000..6694593
--- /dev/null
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+#
+# Copyright 2010 The Closure Library Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS-IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+"""Shared utility functions for scanning directory trees."""
+
+import os
+import re
+
+
+__author__ = 'nnaze@google.com (Nathan Naze)'
+
+
+# Matches a .js file path.
+_JS_FILE_REGEX = re.compile(r'^.+\.js$')
+
+
+def ScanTreeForJsFiles(root):
+  """Scans a directory tree for JavaScript files.
+
+  Args:
+    root: str, Path to a root directory.
+
+  Returns:
+    An iterable of paths to JS files, relative to cwd.
+  """
+  return ScanTree(root, path_filter=_JS_FILE_REGEX)
+
+
+def ScanTree(root, path_filter=None, ignore_hidden=True):
+  """Scans a directory tree for files.
+
+  Args:
+    root: str, Path to a root directory.
+    path_filter: A regular expression filter.  If set, only paths matching
+      the path_filter are returned.
+    ignore_hidden: If True, do not follow or return hidden directories or files
+      (those starting with a '.' character).
+
+  Yields:
+    A string path to files, relative to cwd.
+  """
+
+  def OnError(os_error):
+    raise os_error
+
+  for dirpath, dirnames, filenames in os.walk(root, onerror=OnError):
+    # os.walk allows us to modify dirnames to prevent decent into particular
+    # directories.  Avoid hidden directories.
+    for dirname in dirnames:
+      if ignore_hidden and dirname.startswith('.'):
+        dirnames.remove(dirname)
+
+    for filename in filenames:
+
+      # nothing that starts with '.'
+      if ignore_hidden and filename.startswith('.'):
+        continue
+
+      fullpath = os.path.join(dirpath, filename)
+
+      if path_filter and not path_filter.match(fullpath):
+        continue
+
+      yield os.path.normpath(fullpath)
diff --git a/closure-primitives/treescan.pyc b/closure-primitives/treescan.pyc
new file mode 100644 (file)
index 0000000..cd7fb62
Binary files /dev/null and b/closure-primitives/treescan.pyc differ
diff --git a/console.js b/console.js
new file mode 100644 (file)
index 0000000..e3acad9
--- /dev/null
@@ -0,0 +1,5 @@
+var console = {};
+
+console.log = function() {
+  return void 0;
+}
diff --git a/dict.js b/dict.js
deleted file mode 100644 (file)
index d173635..0000000
--- a/dict.js
+++ /dev/null
@@ -1,14 +0,0 @@
-(function(global) {
-    var FlappDict = function() {
-       this.characters = {};
-    };
-    FlappDict.prototype = {
-       set: function(id, tag) {
-           this.characters[tag.id] = tag;
-       },
-       get: function(id) {
-           return this.characters[id];
-       }
-    };
-    global.FlappDict = FlappDict;
-})(this);
diff --git a/display.js b/display.js
deleted file mode 100644 (file)
index 79c19b0..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-(function(global) {
-    var FlappDisplay = function() {
-       this.objs = {};
-       this.places = {};
-    };
-    FlappDisplay.prototype = {
-       set: function(depth, obj, place) {
-           if (obj) {
-               this.objs[depth] = obj;
-               if (place.matrix) {
-                   obj.matrix = place.matrix;
-               }
-               if (place.colorTransform) {
-                   obj.colorTransform = place.colorTransform;
-               }
-           }
-           this.places[depth] = place;
-       },
-       getObj: function(depth) {
-           return this.objs[depth];
-       },
-       getPlace: function(depth) {
-           return this.places[depth];
-       },
-       del: function(depth) {
-           delete this.objs[depth];
-           delete this.places[depth];
-       },
-       descSortedDepth: function() {
-           var depthList = new Array(this.objs.length);
-           var keys = Object.keys(this.objs);
-           return keys.sort(
-               function(a,b) { return (a>b)?-1:((a<b)?1:0); }
-           );
-       }
-    };
-    global.FlappDisplay = FlappDisplay;
-})(this);
diff --git a/ibit.js b/ibit.js
deleted file mode 100644 (file)
index 4f8dc15..0000000
--- a/ibit.js
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- input bit stream reader
- (c) 2012/11/17- yoya@awm.jp
-*/
-
-(function(global) {
-    var FlappIBit = function() {
-       this.byteOffset = 0;
-       this.bitOffset = 0;
-       this.dataAllocLen = 0;
-       this.data = null;
-       this.dataLen = 0;
-    };
-    FlappIBit.prototype = {
-       input: function(data) {
-           if (typeof data === 'string') {
-               this.inputStr(data);
-           } else {
-               this.inputArray(data);
-           }
-       },
-       inputStr: function(data) {
-           var dataLen = data.length;
-           if (this.dataAllocLen < dataLen) {
-               var oldData = this.data;
-               this.data = new Uint8Array(dataLen);
-               for (var i = 0 , l = this.dataLen; i < l ; i++) {
-                   this.data[i] = data.charCodeAt(i);
-               }
-               this.dataAllocLen = dataLen;
-           }
-           for (var i = this.dataLen ; i < dataLen ; i++) {
-               this.data[i] = data.charCodeAt(i);
-           }
-           this.dataLen = dataLen;
-       },
-       inputArray: function(data) {
-           this.data = data;
-           this.dataAllocLen = this.dataLen = data.length;
-       },
-       len: function() { // data lengh
-           return this.dataLen;
-       },
-       hasNext: function(len) {
-           var nextOffset = this.byteOffset + (this.bitOffset?1:0) + len;
-           return (nextOffset < this.dataLen)?true:false;
-       },
-       getBytePos: function() { // get byte position
-           return this.byteOffset;
-       },
-       setPos: function(byteOffset, bitOffset) { // set byte position
-           this.byteOffset = byteOffset;
-           this.bitOffset = bitOffset;
-       },
-       seek: function(byteDelta, bitDelta) { // relative seek
-           this.byteOffset += byteDelta;
-           this.bitOffset += bitDelta;
-           if (this.bitOffset < 0) {
-               do {
-                   this.byteOffset --;
-                   this.bitOffset += 8;
-               } while (this.bitOffset < 0);
-           } else if (this.bitOffset > 7) {
-               do {
-                   this.byteOffset ++;
-                   this.bitOffset -= 8;
-               } while (this.bitOffset > 7);
-           }
-       },
-       a: function() { // skip bit
-           if (this.bitOffset) {
-               this.byteOffset++;
-               this.bitOffset = 0;
-           }
-       },
-       b: function() { // bit
-           var value = (this.data[this.byteOffset] >>> (7 - this.bitOffset++)) & 1;
-           if (this.bitOffset === 8) {
-               this.byteOffset++;
-               this.bitOffset = 0;
-           }
-           return value;
-       },
-       ub: function(len) { // unsigned bits
-           var value = 0;
-           while (len--) {
-               value = (value << 1) | this.b();
-           }
-           return value;
-       },
-       sb: function(len) { // signed bits
-           var value = 0;
-           if (len === 0) return 0; // XXX
-           var msb = this.b();
-           if (msb) {
-               var orig_len = len;
-           }
-           while (--len) {
-               value = (value << 1) | this.b();
-           }
-           if (msb) {
-               return value - (1 << (orig_len - 1));
-           }
-           return value;
-       },
-       si8: function() { // snsigned 8-bit integer
-           value = this.ui8();
-           return (value & 0x80)?(value - 0x100):value;
-       },
-       si16: function() { // snsigned 16-bit integer
-           value = this.ui16();
-           return (value & 0x8000)?(value - 0x10000):value;
-
-       },
-       si32: function() { // snsigned 32-bit integer
-           value = this.ui32();
-           return (value & 0x80000000)?(value - 0x100000000):value;
-       },
-       ui8: function() { // unsigned 8-bit integer
-           this.a();
-           return this.data[this.byteOffset++];
-       },
-       ui16: function() { // unsigned 16-bit integer
-           this.a();
-           return this.data[this.byteOffset++] |
-               (this.data[this.byteOffset++] << 8);
-       },
-       ui32: function() { // unsigned 32-bit integer
-           this.a();
-           return this.data[this.byteOffset++] |
-               (this.data[this.byteOffset++] << 8) |
-               (this.data[this.byteOffset++] << 16) |
-               (this.data[this.byteOffset++] << 24);
-       },
-       sub: function(len) {
-           this.a();
-           var data = this.data.subarray(this.byteOffset, this.byteOffset + len);
-           this.byteOffset += len;
-           return data;
-       },
-       strN: function(len) {
-           this.a();
-           var data = this.data;
-           var str = [];
-           for (var i = this.byteOffset, l = this.byteOffset + len ; i < len ; i++) {
-               str.push(String.fromCharCode(data[i]))
-           }
-           this.byteOffset += len;
-//         return new FlappUTF8().fromSJISArray(data);
-           return str.join('');
-       },
-       str: function(len) {
-           this.a();
-           var byteOffset = this.byteOffset;
-           var dataLen = this.dataLen;
-           for (var i = byteOffset ; i < dataLen ; i++) {
-               if (this.data[i] === 0) {
-                   data = this.strN(i - byteOffset);
-                   this.byteOffset++; // skip "\0"
-                   return data;
-               }
-           }
-           return this.strN(i - byteOffset);
-       }
-
-    };
-    global.FlappIBit = FlappIBit;
-})(this);
diff --git a/loader.js b/loader.js
deleted file mode 100644 (file)
index 934c58a..0000000
--- a/loader.js
+++ /dev/null
@@ -1,94 +0,0 @@
-(function(global) {
-    var FlappLoader = function(flapp) {
-       this.flapp = flapp;
-    }
-    FlappLoader.prototype = {
-       fromURL: function(url, dict, movieClip) {
-           console.debug("FlappLoader.prototype.fromURL("+url+",flapp,dict,movieClip");
-           var xhr = new XMLHttpRequest();
-           var ibit = new FlappIBit();
-           var loader = this;
-           this.header = null;
-           xhr.onreadystatechange = function() {
-               if (xhr.readyState > 1) {
-                    if (xhr.status == 200) {
-                       if (xhr.responseText) {
-                           ibit.input(xhr.responseText);
-                           loader.parse(ibit, dict, movieClip);
-                       }
-                    }
-               }
-           }
-           xhr.open('GET', url);
-           // xhr.responseType = 'arraybuffer';
-           xhr.overrideMimeType('text/plain; charset=x-user-defined');
-            xhr.send(null);
-       },
-       parse: function(ibit, dict, movieClip) {
-           // console.debug("FlappLoader.prototype.parse");
-           if (ibit.len() < 20) { // 20 is minumum size for swf header, maybe.
-               return ;
-           }
-           if (this.header === null) {
-               this.header = FlappSWFHeader.load(ibit);
-               console.debug(this.header);
-               flapp.setHeader(this.header);
-           }
-           var jpegTables = null;
-           while (ibit.a(), ibit.hasNext(2)) {
-               var headPos = ibit.getBytePos();
-               var tag_and_length = ibit.ui16(); // tag and length
-               var code = tag_and_length >>> 6;
-               var length = tag_and_length & 0x3f;
-               if (length === 0x3f) {
-                   if (ibit.hasNext(4) === false) {
-                       ibit.setPos(headPos, 0);
-                       break;
-                   }
-                   length = ibit.ui32();
-               }
-               if (ibit.hasNext(length) === false) {
-                   ibit.setPos(headPos, 0);
-                   break;
-               }
-               var startOfContent = ibit.getBytePos();
-               var tag = new FlappSWFTag.load(code, length, ibit);
-//             console.debug(tag);
-               switch (code) {
-               case 1: // ShowFrame
-                   movieClip.appendControlTag(tag);
-                   break;
-               case 2: // DefineShape
-               case 22: // DefineShape2
-               case 32: // DefineShape3
-                   dict.set(tag.id, tag);
-                   break;
-               case 6: // DefineBits(JPEG)
-                   var jpeg = FlappBitmap.toJpeg(tag.jpegData, jpegTables);
-                   var image = new Image();
-                   image.src = "data:image/jpeg;base64,"+btoa(jpeg);
-                   tag.image = image;
-                   dict.set(tag.id, tag);
-                   break;
-               case 8: // JPEGTables
-                   jpegTables = tag;
-                   break;
-               case 9: // SetBackgroundColor
-                   // set canvas background
-                   break;
-               case 12: // DoAction
-                   movieClip.appendControlTag(tag);
-                   break;
-               case 26: // PlaceObject2
-                   movieClip.appendControlTag(tag);
-                   break;
-               default:
-                   console.warn("Unknown swf tag code:"+code);
-                   break;
-               }
-               ibit.setPos(startOfContent + length, 0);
-           }
-       }
-    };
-    global.FlappLoader = FlappLoader;
-})(this);
diff --git a/main.js b/main.js
deleted file mode 100644 (file)
index f97e869..0000000
--- a/main.js
+++ /dev/null
@@ -1,45 +0,0 @@
-(function(global) {
-    var Flapp = function(url, canvas_id) {
-       console.debug("Flapp("+url+","+canvas_id+")");
-       this.url = url;
-       this.canvas_id = canvas_id;
-       this.canvas = document.getElementById(canvas_id);
-       global.flapp = this; // debug
-       this.header = null
-//     this.frameTick = 1000 / 10; // default 0.1[sec]
-       this.frameTick = 1000; // default
-    };
-    Flapp.prototype = {
-       play: function() {
-           console.debug("Flapp.prototype.play");
-           var flapp = this;
-           var loader = new FlappLoader(flapp); // file loader
-           this.dict = new FlappDict(); // content dictionary
-           this.movieClip = new FlappMovieClip(); // root MC
-           loader.fromURL(this.url, this.dict, this.movieClip);
-           this.canvas = new FlappCanvas(this.canvas);
-           this.run(this.dict, this.movieClip, this.canvas);
-       },
-       setHeader: function(header) {
-//         this.frameTick = 1000 / header.framerate;
-           this.frameTick = 1000;
-           this.movieClip.totalframes = header.framecount;
-       },
-       run: function(dict, movieClip, canvas) {
-           console.debug("Flapp::run");
-           var flapp = this;
-           this.canvas = canvas;
-           this.tick(flapp, this.dict, this.movieClip);
-       },
-       tick: function(flapp, dict, movieClip) {
-           console.debug("Flapp::tick "+movieClip.currentFrame);
-           setTimeout(flapp.tick, flapp.frameTick, flapp, dict, movieClip);
-           if (movieClip.control(dict)) {
-               movieClip.action();
-               movieClip.render(flapp.canvas);
-               movieClip.increment();
-           }
-       }
-    };
-    global.Flapp = Flapp;
-})(this);
diff --git a/memory.js b/memory.js
deleted file mode 100644 (file)
index f9b422c..0000000
--- a/memory.js
+++ /dev/null
@@ -1,14 +0,0 @@
-(function(global) {
-    var FlappMemory = function() {
-       ;
-    };
-    FlappMemory.prototype = {
-       add: function(key, content) {
-           ;
-       },
-       del: function(key, content) {
-           ;
-       }
-    };
-    global.FlappMemory = FlappMemory;
-})(this);
diff --git a/movieclip.js b/movieclip.js
deleted file mode 100644 (file)
index 5ace6c4..0000000
+++ /dev/null
@@ -1,220 +0,0 @@
-(function(global) {
-    var FlappMovieClip = function(parentMovieClip, name, matrix, colorTransform) {
-       this.OBJECT_TYPE = 2; // 1:Shape, 2: MovieClip
-       this.parentMovieClip = parentMovieClip?parentMovieCli:null;
-       this.rootMovieClip = parentMovieClip?parentMovieClip.rootMovieClip:this;
-       this.name = name?name:'anonymous';
-       this.matrix = matrix;
-       this.colorTransform = colorTransform;
-       this.childMovieClips = {}; // name => movieClip
-       this.childMovieClips_seqnum = 1; // for name movieClip
-       this.clearControlTags();
-       //
-       this.prevShowFramePos = 0;
-       //
-       canvas = document.createElement('canvas');
-       canvas.width = 240; // XXX
-       canvas.height = 240; // XXX
-       this.canvas = canvas;
-       this.canvasDirty = false; // dirtyFlag
-       //
-       this.displayList = new FlappDisplay();
-       //
-       this.totalframes = 0;
-       this.currentFrame = 0;
-       this.playing = true;
-       // this.loop = true;
-       this.loop = false;
-       var actionVarriableTable = {};
-       var actionVarriablOrigKeys = {};
-    };
-    FlappMovieClip.prototype = {
-       clearControlTags: function(controlTag) {
-           this.controlTagsList = [[]]; //
-           this.actionTagsList = [[]];
-           this.labelMap = {}; // label => frameNum
-           this.framesLoaded = 0;
-       },
-       appendControlTag: function(controlTag) {
-           // console.debug("FlappMovieClip::appendControlTag");
-           if (controlTag.code === 12) { // DoAction
-               this.actionTagsList[this.framesLoaded].push(controlTag);
-               return ;
-           }
-           this.controlTagsList[this.framesLoaded].push(controlTag);
-           if (controlTag.code === 1) { // ShowFrame
-               this.controlTagsList.push([]);
-               this.actionTagsList.push([]);
-               this.framesLoaded++;
-           } else if (controlTag.code === 43) { // FrameLabel
-               this.labelMap[controlTag.name] = this.framesLoaded;
-           }
-       },
-       setControlTags: function(controlTags) {
-           this.clearControlTags();
-           for (var i = 0, l = controlTags.length ; i < l ; i++) {
-               this.appendControlTag(controlTags[i]);
-           }
-       },
-       addChildMovieClip: function(name, movieClip) {
-           this.childMovieClips[name] = movieClip;
-       },
-       deleteChildMovieClip: function(name) {
-           delete this.childMovieClips[name];
-       },
-       control: function(dict) {
-           if (this.totalframes === 0) { // imcomplete
-               return false;
-           }
-           console.debug("FlappMovieClip::control");
-           if (this.framesLoaderd < this.totalframes) { // imcomplete
-               if (this.currentFrame < this.framesLoaderd) {
-                   return false; // idle
-               }
-           }
-           for (var mc in this.childMovieClips) {
-               this.childMovieClips[mc].control(dict);
-           }
-           if (this.playing) {
-               this.controlThis(dict);
-           }
-           return true;
-       },
-       controlThis: function(dict) {
-           console.debug("FlappMovieClip::controlThis");
-           var tag, i, l;
-           var defineTag;
-           if ((this.currentFrame < 0 ) || (this.totalframes <= this.currentFrame)) {
-               this.currentFrame = 0;
-           }
-           var controlTags = this.controlTagsList[this.currentFrame];
-
-           for (i = 0, l = controlTags.length ; i < l ; i++) {
-               tag = controlTags[i];
-               switch (tag.code) {
-               case 1: // ShowFrame
-                   break;
-               case 26: // PlaceObject2
-                   // set display List;
-                   var obj = null;
-                   if (tag.move) {
-                       this.displayList.set(tag.depth, obj, tag);
-                   } else {
-                       defineTag = dict.get(tag.id);
-                       console.log(tag);
-                       if (defineTag.code === 39) { // DefineSprite
-                           var name = tag.name;
-                           if (name === null) {
-                               name = "instance"+this.childMovieClips_seqnum;
-                               defineTag.name = name;
-                               this.childMovieClips_seqnum++;
-                           }
-                           var obj = FlappMovieClip(this, name, tag.matrix, tag.colorTransform);
-                           obj.setControlTags(defineTag.controlTags);
-                           this.addChildMovieClip(name, obj);
-                       } else if (defineTag.code === 2) { // DefineShape
-                           var obj = new FlappShape(name, tag.matrix, tag.colorTransform);
-                           console.log(obj);
-                           obj.loadShapeTag(defineTag);
-                       }
-                       this.displayList.set(tag.depth, obj, tag);
-                       break;
-                   }
-               }
-           }
-       },
-       action: function() {
-           for (var mc in this.childMovieClips) {
-               this.childMovieClips[mc].action();
-           }
-           if (this.playing) {
-               this.actionThis();
-           }
-
-       },
-       actionThis: function() {
-           var actionTags = this.actionTagsList[this.currentFrame];
-           var l = actionTags.length;
-           console.debug("FlappMovieClip::actionThis: actionTags.length:"+l);
-           for (var i = 0 ; i < l ; i++) {
-               var tag = actionTags[i];
-               var movieClip = this;
-               FlappAction.exec(tag, movieClip, this.rootMovieClip);
-           }
-       },
-       increment: function() {
-           for (var mc in this.childMovieClips) {
-               this.childMovieClips[mc].increment();
-           }
-           if (this.playing) {
-               this.incrementThis();
-           }
-       },
-       incrementThis: function() {
-           console.debug("FlappMovieClip::incrementThis: "+this.currentFrame);
-           this.currentFrame++;
-           if (this.totalframes <= this.currentFrame) {
-               if (this.loop) {
-                   this.currentFrame = 0; // play
-               } else {
-                   this.playing = false;
-               }
-           }
-           if (this.totalframes === 1) {
-               this.playing = false;
-           }
-       },
-       render: function(canvas) {
-           var depthList = this.displayList.descSortedDepth();
-           for (var i = 0, l = depthList.length  ; i < l ; i++) {
-               var depth = depthList[i];
-               var obj = this.displayList.getObj(depth);
-               if (obj.OBJECT_TYPE === 2) { // MovieClip
-                   obj.render(this.canvas);
-               } else if ((obj.OBJECT_TYPE === 2) && (this.playing == true)) {
-                   obj.render(this.canvas);
-               }
-           }
-       },
-       setVariable: function(key, value) {
-           var lcKey = key.toLowerCase();
-           actionVarriableTable[lcKey] = value;
-           actionVarriablOrigKeys[lcKey] = key;
-       },
-       getVariable: function(key) {
-           var lcKey = key.toLowerCase();
-           if (lcKey in actionVarriableTable) {
-               return actionVarriableTable[lcKey];
-           }
-           return null;
-       },
-       gotoFrame: function(frameNum) {
-           console.debug("FlappMovieClip::gotoFrame"+frameNum);
-           this.currentFrame = frameNum;
-       },
-       gotoLabel: function(frameLabel) {
-           frameNum = labelMap[frameLabel];
-           console.debug("FlappMovieClip::gotoFrame"+frameLabel+"=>"+frameNum);
-           this.currentFrame = frameNum;
-       },
-       play: function() {
-           this.playing = true;
-       },
-       stop: function() {
-           this.playing = false;
-       },
-       destroy: function() { // destructor
-           for (name in this.childMovieClips) {
-               this.childMovieClips[name].destroy();
-           }
-           this.parentMovieClip = null;
-           this.rootMovieClip = null;
-           this.controlTagsList = null;
-           this.actionTagsList = null;
-           this.labelMap = null;
-           this.canvas = null;
-           this.displayList = null;
-       }
-    };
-    global.FlappMovieClip = FlappMovieClip;
-})(this);
diff --git a/shape.js b/shape.js
deleted file mode 100644 (file)
index f15a3f4..0000000
--- a/shape.js
+++ /dev/null
@@ -1,21 +0,0 @@
-(function(global) {
-    var FlappShape = function(name, matrix, colorTransform) {
-       this.OBJECT_TYPE = 1; // 1:Shape, 2:MovieClip
-       this.canvas = document.createElement('canvas');
-       canvas.width = 240; // XXX
-       canvas.height = 240; // XXX
-       this.renderCode = "";
-    };
-    FlappShape.prototype = {
-       loadShapeTag: function(shape) {
-           ;
-       },
-       render: function(canvas) {
-           ;
-       }
-    };
-    FlappShape.shapetoRenderCode = function(shapeTag) {
-       ;
-    }
-    global.FlappShape = FlappShape;
-})(this);
diff --git a/src/action.js b/src/action.js
new file mode 100644 (file)
index 0000000..e46cb73
--- /dev/null
@@ -0,0 +1,58 @@
+goog.provide('FlappAction');
+goog.require('FlappIBit');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappAction = function() {
+    this.actionRecord = null;
+};
+
+FlappAction.exec = function(tag, movieClip, rootMovieClip) {
+    console.debug("FlappAction.exec");
+    var actionsBit = new FlappIBit();
+    actionsBit.input(tag.actions);
+    var code = 0;
+    var stack = [];
+    while (code = actionsBit.ui8()) {
+        if (code < 0x80) {
+            switch (code) {
+            case 0x06: // Play
+                movieClip.play();
+                break;
+            case 0x07: // Stop
+                movieClip.stop();
+                break;
+            case 0x1d: // SetVariables
+                movieClip.setVariable(stack.pop(), stack.pop());
+                break;
+            default:
+                console.debug("FlappActiom: not implemented yet. code=0x%02x", code);
+                break;
+            }
+        } else {
+            var actionLength = actionsBit.input(tag.actions);
+            var nextActionOffset = actionsBit.getBytePos() + actionLength;
+            switch (code) {
+            case 0x81: // GotoFrame
+                movieClip.gotoFrame(actionsBit.si16());
+                break;
+            case 0x83: // GetURL
+                //
+                break;
+            case 0x8c: // GoToLabel
+                movieClip.gotoLabel(actionsBit.strN(actionLength));
+                break;
+                //case 0x96: // Push
+            default:
+                console.debug("FlappActiom: not implemented yet. code=0x%02x", code);
+                break;
+            }
+            actionsBit.setPos(nextActionOffset, 0);
+        }
+    }
+};
+
+});
diff --git a/src/bitmap.js b/src/bitmap.js
new file mode 100644 (file)
index 0000000..c2c557f
--- /dev/null
@@ -0,0 +1,72 @@
+goog.provide('FlappBitmap');
+goog.require('FlappIBit');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappBitmap = function() {
+    ;
+};
+
+FlappBitmap.jpegChunkOffsets = function(jpegData) {
+    var offsetTable = {};
+    var ibit = new FlappIBit();
+    while (ibit.hasNext(2)) {
+        var marker = ibit.ui16be();
+        var offset = ibit.getBytePos();
+        var length;
+        switch (marker) {
+        case 0xFFD8: // SOI
+        case 0xFFD9: // EOI
+            break;
+        case 0xFFDA: // SOS + [RST] + EOI
+            length = ibit.len() - offset;
+            offsetTable[marker] = [offset, length]
+            break;
+        default:
+            length = ibit.ui16be() + 2;
+            offsetTable[marker] = [offset, length]
+
+            break;
+        }
+    }
+    return offsetTable;
+};
+
+FlappBitmap.toJpeg = function(swfJpeg, jpegTables) {
+    var offsetTable = FlappBitmap.jpegChunkOffsets(swfJpeg);
+    var hasDQT = (0xFFDB in offsetTable);
+    if (hasDQT === false) {
+        var offsetTable2 = FlappBitmap.jpegChunkOffsets(jpegTables);
+    }
+    var jpegArray = [0xFF, 0xD8]; // SOI
+    // APP0, SOF0, DQT, DHT, SOS
+    var jpegOrder = [0xFFE0, 0xFFC0, 0xFFDB, 0xFFC4, 0xFFDA];
+    for (var i = 0, l = jpegOrder; i < l ; i++) {
+        var marker = jpegOrder[i];
+        var swfJpegOffset = (marker in offsetTable);
+        if (swfJpegOffset) {
+            var entry = offsetTable[marker];
+        } else {
+            var entry = offsetTable2[marker];
+        }
+        var offset = entry[0];
+        var enfoffset = offset + entry[1];
+        for (var j = offset; j < enfoffset ; j++) {
+            if (swfJpegOffset) {
+                jpegArray.join(swfJpeg[j]);
+            } else {
+                jpegArray.join(jpegTables[j]);
+            }
+        }
+    }
+    return FlappString.ArrayToString(jpegArray);
+};
+
+FlappBitmap.toPng = function(lossless) {
+    ;
+};
+
+});
diff --git a/src/canvas.js b/src/canvas.js
new file mode 100644 (file)
index 0000000..79ee603
--- /dev/null
@@ -0,0 +1,13 @@
+goog.provide('FlappCanvas');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappCanvas = function(canvas) {
+    this.canvas = canvas;
+    this.ctx = canvas.getContext('2d');
+};
+
+});
diff --git a/src/dict.js b/src/dict.js
new file mode 100644 (file)
index 0000000..35ee865
--- /dev/null
@@ -0,0 +1,21 @@
+goog.provide('FlappDict');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappDict = function() {
+    this.characters = {};
+};
+
+FlappDict.prototype = {
+    set: function(id, tag) {
+        this.characters[tag.id] = tag;
+    },
+    get: function(id) {
+        return this.characters[id];
+    }
+};
+
+});
diff --git a/src/display.js b/src/display.js
new file mode 100644 (file)
index 0000000..3d417e8
--- /dev/null
@@ -0,0 +1,45 @@
+goog.provide('FlappDisplay');
+
+goog.scope(function () {
+
+/**
+ * @constructor
+ */
+FlappDisplay = function() {
+    this.objs = {};
+    this.places = {};
+};
+
+FlappDisplay.prototype = {
+    set: function(depth, obj, place) {
+        if (obj) {
+            this.objs[depth] = obj;
+            if (place.matrix) {
+                obj.matrix = place.matrix;
+            }
+            if (place.colorTransform) {
+                obj.colorTransform = place.colorTransform;
+            }
+        }
+        this.places[depth] = place;
+    },
+    getObj: function(depth) {
+        return this.objs[depth];
+    },
+    getPlace: function(depth) {
+        return this.places[depth];
+    },
+    del: function(depth) {
+        delete this.objs[depth];
+        delete this.places[depth];
+    },
+    descSortedDepth: function() {
+        var depthList = new Array(this.objs.length);
+        var keys = Object.keys(this.objs);
+        return keys.sort(
+            function(a,b) { return (a>b)?-1:((a<b)?1:0); }
+        );
+    }
+};
+
+});
similarity index 56%
rename from event.js
rename to src/event.js
index de00d69..e04cbdb 100644 (file)
--- a/event.js
@@ -1,5 +1,11 @@
-(function(global) {
-    var FlappEvent = function() {
+goog.provide('FlappEvent');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappEvent = function() {
        this.eventMap = {};
     };
     FlappEvent.prototype = {
@@ -8,5 +14,5 @@
            // addListner to Obejct.
        }
     };
-    global.FlappEvent = FlappEvent;
-})(this);
+
+});
diff --git a/src/ibit.js b/src/ibit.js
new file mode 100644 (file)
index 0000000..5c71ed1
--- /dev/null
@@ -0,0 +1,174 @@
+/*
+ input bit stream reader
+ (c) 2012/11/17- yoya@awm.jp
+*/
+goog.provide('FlappIBit');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappIBit = function() {
+    this.byteOffset = 0;
+    this.bitOffset = 0;
+    this.dataAllocLen = 0;
+    this.data = null;
+    this.dataLen = 0;
+};
+
+FlappIBit.prototype = {
+    input: function(data) {
+        if (typeof data === 'string') {
+            this.inputStr(data);
+        } else {
+            this.inputArray(data);
+        }
+    },
+    inputStr: function(data) {
+        var dataLen = data.length;
+        if (this.dataAllocLen < dataLen) {
+            var oldData = this.data;
+            this.data = new Uint8Array(dataLen);
+            for (var i = 0 , l = this.dataLen; i < l ; i++) {
+                this.data[i] = data.charCodeAt(i);
+            }
+            this.dataAllocLen = dataLen;
+        }
+        for (var i = this.dataLen ; i < dataLen ; i++) {
+            this.data[i] = data.charCodeAt(i);
+        }
+        this.dataLen = dataLen;
+    },
+    inputArray: function(data) {
+        this.data = data;
+        this.dataAllocLen = this.dataLen = data.length;
+    },
+    len: function() { // data lengh
+        return this.dataLen;
+    },
+    hasNext: function(len) {
+        var nextOffset = this.byteOffset + (this.bitOffset?1:0) + len;
+        return (nextOffset < this.dataLen);
+    },
+    getBytePos: function() { // get byte position
+        return this.byteOffset;
+    },
+    setPos: function(byteOffset, bitOffset) { // set byte position
+        this.byteOffset = byteOffset;
+        this.bitOffset = bitOffset;
+    },
+    seek: function(byteDelta, bitDelta) { // relative seek
+        this.byteOffset += byteDelta;
+        this.bitOffset += bitDelta;
+        if (this.bitOffset < 0) {
+            do {
+                this.byteOffset --;
+                this.bitOffset += 8;
+            } while (this.bitOffset < 0);
+        } else if (this.bitOffset > 7) {
+            do {
+                this.byteOffset ++;
+                this.bitOffset -= 8;
+            } while (this.bitOffset > 7);
+        }
+    },
+    a: function() { // skip bit
+        if (this.bitOffset) {
+            this.byteOffset++;
+            this.bitOffset = 0;
+        }
+    },
+    b: function() { // bit
+        var value = (this.data[this.byteOffset] >>> (7 - this.bitOffset++)) & 1;
+        if (this.bitOffset === 8) {
+            this.byteOffset++;
+            this.bitOffset = 0;
+        }
+        return value;
+    },
+    ub: function(len) { // unsigned bits
+        var value = 0;
+        while (len--) {
+            value = (value << 1) | this.b();
+        }
+        return value;
+    },
+    sb: function(len) { // signed bits
+        var value = 0;
+        if (len === 0) return 0; // XXX
+        var msb = this.b();
+        if (msb) {
+            var orig_len = len;
+        }
+        while (--len) {
+            value = (value << 1) | this.b();
+        }
+        if (msb) {
+            return value - (1 << (orig_len - 1));
+        }
+        return value;
+    },
+    si8: function() { // snsigned 8-bit integer
+        var value = this.ui8();
+        return (value & 0x80)?(value - 0x100):value;
+    },
+    si16: function() { // snsigned 16-bit integer
+        var value = this.ui16();
+        return (value & 0x8000)?(value - 0x10000):value;
+
+    },
+    si32: function() { // snsigned 32-bit integer
+        var value = this.ui32();
+        return (value & 0x80000000)?(value - 0x100000000):value;
+    },
+    ui8: function() { // unsigned 8-bit integer
+        this.a();
+        return this.data[this.byteOffset++];
+    },
+    ui16: function() { // unsigned 16-bit integer
+        this.a();
+        return this.data[this.byteOffset++] |
+            (this.data[this.byteOffset++] << 8);
+    },
+    ui32: function() { // unsigned 32-bit integer
+        this.a();
+        return this.data[this.byteOffset++] |
+            (this.data[this.byteOffset++] << 8) |
+            (this.data[this.byteOffset++] << 16) |
+            (this.data[this.byteOffset++] << 24);
+    },
+    sub: function(len) {
+        this.a();
+        var data = this.data.subarray(this.byteOffset, this.byteOffset + len);
+        this.byteOffset += len;
+        return data;
+    },
+    strN: function(len) {
+        this.a();
+        var data = this.data;
+        var str = [];
+        for (var i = this.byteOffset, l = this.byteOffset + len ; i < len ; i++) {
+            str.push(String.fromCharCode(data[i]))
+        }
+        this.byteOffset += len;
+//         return new FlappUTF8().fromSJISArray(data);
+        return str.join('');
+    },
+    str: function(len) {
+        this.a();
+        var byteOffset = this.byteOffset;
+        var dataLen = this.dataLen;
+        var data;
+        for (var i = byteOffset ; i < dataLen ; i++) {
+            if (this.data[i] === 0) {
+                data = this.strN(i - byteOffset);
+                this.byteOffset++; // skip "\0"
+                return data;
+            }
+        }
+        return this.strN(i - byteOffset);
+    }
+};
+
+});
diff --git a/src/loader.js b/src/loader.js
new file mode 100644 (file)
index 0000000..70f7ebe
--- /dev/null
@@ -0,0 +1,103 @@
+goog.provide('FlappLoader');
+goog.require('FlappIBit');
+goog.require('FlappSWFHeader')
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappLoader = function(flapp) {
+    this.flapp = flapp;
+};
+
+FlappLoader.prototype = {
+    fromURL: function(url, dict, movieClip) {
+        console.debug("FlappLoader.prototype.fromURL("+url+",flapp,dict,movieClip");
+        var xhr = new XMLHttpRequest();
+        var ibit = new FlappIBit();
+        var loader = this;
+        this.header = null;
+        xhr.onreadystatechange = function() {
+            if (xhr.readyState > 1) {
+                if (xhr.status == 200) {
+                    if (xhr.responseText) {
+                        ibit.input(xhr.responseText);
+                        loader.parse(ibit, dict, movieClip);
+                    }
+                }
+            }
+        };
+        xhr.open('GET', url);
+        // xhr.responseType = 'arraybuffer';
+        xhr.overrideMimeType('text/plain; charset=x-user-defined');
+        xhr.send(null);
+    },
+    parse: function(ibit, dict, movieClip) {
+        // console.debug("FlappLoader.prototype.parse");
+        if (ibit.len() < 20) { // 20 is minumum size for swf header, maybe.
+            return ;
+        }
+        if (this.header === null) {
+            this.header = FlappSWFHeader.load(ibit);
+            console.debug(this.header);
+            this.flapp.setHeader(this.header);
+        }
+        var jpegTables = null;
+        while (ibit.a(), ibit.hasNext(2)) {
+            var headPos = ibit.getBytePos();
+            var tag_and_length = ibit.ui16(); // tag and length
+            var code = tag_and_length >>> 6;
+            var length = tag_and_length & 0x3f;
+            if (length === 0x3f) {
+                if (ibit.hasNext(4) === false) {
+                    ibit.setPos(headPos, 0);
+                    break;
+                }
+                length = ibit.ui32();
+            }
+            if (ibit.hasNext(length) === false) {
+                ibit.setPos(headPos, 0);
+                break;
+            }
+            var startOfContent = ibit.getBytePos();
+            var tag = new FlappSWFTag.load(code, length, ibit);
+//             console.debug(tag);
+            switch (code) {
+            case 1: // ShowFrame
+                movieClip.appendControlTag(tag);
+                break;
+            case 2: // DefineShape
+            case 22: // DefineShape2
+            case 32: // DefineShape3
+                dict.set(tag.id, tag);
+                break;
+            case 6: // DefineBits(JPEG)
+                var jpeg = FlappBitmap.toJpeg(tag.jpegData, jpegTables);
+                var image = new Image();
+                image.src = "data:image/jpeg;base64," + goog.global.btoa(jpeg);
+                tag.image = image;
+                dict.set(tag.id, tag);
+                break;
+            case 8: // JPEGTables
+                jpegTables = tag;
+                break;
+            case 9: // SetBackgroundColor
+                // set canvas background
+                break;
+            case 12: // DoAction
+                movieClip.appendControlTag(tag);
+                break;
+            case 26: // PlaceObject2
+                movieClip.appendControlTag(tag);
+                break;
+            default:
+                console.warn("Unknown swf tag code:"+code);
+                break;
+            }
+            ibit.setPos(startOfContent + length, 0);
+        }
+    }
+};
+
+});
diff --git a/src/main.js b/src/main.js
new file mode 100644 (file)
index 0000000..6f750a0
--- /dev/null
@@ -0,0 +1,58 @@
+goog.provide('Flapp');
+goog.require('FlappLoader');
+goog.require('FlappDict');
+goog.require('FlappCanvas');
+goog.require('FlappMovieClip');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+Flapp = function(url, canvas_id) {
+    console.debug("Flapp("+url+","+canvas_id+")");
+    this.url = url;
+    this.canvas_id = canvas_id;
+    this.canvas = document.getElementById(canvas_id);
+    goog.global.flapp = this; // debug
+    this.header = null
+//     this.frameTick = 1000 / 10; // default 0.1[sec]
+    this.frameTick = 1000; // default
+};
+Flapp.prototype = {
+    play: function() {
+        console.debug("Flapp.prototype.play");
+        var flapp = this;
+        var loader = new FlappLoader(flapp); // file loader
+        this.dict = new FlappDict(); // content dictionary
+        this.movieClip = new FlappMovieClip(); // root MC
+        loader.fromURL(this.url, this.dict, this.movieClip);
+        this.canvas = new FlappCanvas(this.canvas);
+        this.run(this.dict, this.movieClip, this.canvas);
+    },
+    setHeader: function(header) {
+//         this.frameTick = 1000 / header.framerate;
+        this.frameTick = 1000;
+        this.movieClip.totalframes = header.framecount;
+    },
+    run: function(dict, movieClip, canvas) {
+        console.debug("Flapp::run");
+        var flapp = this;
+        this.canvas = canvas;
+        this.tick(flapp, this.dict, this.movieClip);
+    },
+    tick: function(flapp, dict, movieClip) {
+        console.debug("Flapp::tick "+movieClip.currentFrame);
+        setTimeout(flapp.tick, flapp.frameTick, flapp, dict, movieClip);
+        if (movieClip.control(dict)) {
+            movieClip.action();
+            movieClip.render(flapp.canvas);
+            movieClip.increment();
+        }
+    }
+};
+
+goog.exportSymbol('Flapp', Flapp);
+goog.exportSymbol('Flapp.prototype.play', Flapp.prototype.play);
+
+});
diff --git a/src/memory.js b/src/memory.js
new file mode 100644 (file)
index 0000000..373d6b1
--- /dev/null
@@ -0,0 +1,21 @@
+goog.provide('FlappMemory');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappMemory = function() {
+    ;
+};
+
+FlappMemory.prototype = {
+    add: function(key, content) {
+        ;
+    },
+    del: function(key, content) {
+        ;
+    }
+};
+
+});
diff --git a/src/movieclip.js b/src/movieclip.js
new file mode 100644 (file)
index 0000000..23dca47
--- /dev/null
@@ -0,0 +1,230 @@
+goog.provide('FlappMovieClip');
+goog.require('FlappDisplay');
+goog.require('FlappShape');
+goog.require('FlappAction');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappMovieClip = function(parentMovieClip, name, matrix, colorTransform) {
+    this.OBJECT_TYPE = 2; // 1:Shape, 2: MovieClip
+    this.parentMovieClip = parentMovieClip?parentMovieClip:null;
+    this.rootMovieClip = parentMovieClip?parentMovieClip.rootMovieClip:this;
+    this.name = name?name:'anonymous';
+    this.matrix = matrix;
+    this.colorTransform = colorTransform;
+    this.childMovieClips = {}; // name => movieClip
+    this.childMovieClips_seqnum = 1; // for name movieClip
+    this.clearControlTags();
+    //
+    this.prevShowFramePos = 0;
+    //
+    var canvas = document.createElement('canvas');
+    canvas.width = 240; // XXX
+    canvas.height = 240; // XXX
+    this.canvas = canvas;
+    this.canvasDirty = false; // dirtyFlag
+    //
+    this.displayList = new FlappDisplay();
+    //
+    this.totalframes = 0;
+    this.currentFrame = 0;
+    this.playing = true;
+    // this.loop = true;
+    this.loop = false;
+    this.actionVarriableTable = {};
+    this.actionVarriablOrigKeys = {};
+};
+
+FlappMovieClip.prototype = {
+    clearControlTags: function(controlTag) {
+        this.controlTagsList = [[]]; //
+        this.actionTagsList = [[]];
+        this.labelMap = {}; // label => frameNum
+        this.framesLoaded = 0;
+    },
+    appendControlTag: function(controlTag) {
+        // console.debug("FlappMovieClip::appendControlTag");
+        if (controlTag.code === 12) { // DoAction
+            this.actionTagsList[this.framesLoaded].push(controlTag);
+            return ;
+        }
+        this.controlTagsList[this.framesLoaded].push(controlTag);
+        if (controlTag.code === 1) { // ShowFrame
+            this.controlTagsList.push([]);
+            this.actionTagsList.push([]);
+            this.framesLoaded++;
+        } else if (controlTag.code === 43) { // FrameLabel
+            this.labelMap[controlTag.name] = this.framesLoaded;
+        }
+    },
+    setControlTags: function(controlTags) {
+        this.clearControlTags();
+        for (var i = 0, l = controlTags.length ; i < l ; i++) {
+            this.appendControlTag(controlTags[i]);
+        }
+    },
+    addChildMovieClip: function(name, movieClip) {
+        this.childMovieClips[name] = movieClip;
+    },
+    deleteChildMovieClip: function(name) {
+        delete this.childMovieClips[name];
+    },
+    control: function(dict) {
+        if (this.totalframes === 0) { // imcomplete
+            return false;
+        }
+        console.debug("FlappMovieClip::control");
+        if (this.framesLoaderd < this.totalframes) { // imcomplete
+            if (this.currentFrame < this.framesLoaderd) {
+                return false; // idle
+            }
+        }
+        for (var mc in this.childMovieClips) {
+            this.childMovieClips[mc].control(dict);
+        }
+        if (this.playing) {
+            this.controlThis(dict);
+        }
+        return true;
+    },
+    controlThis: function(dict) {
+        console.debug("FlappMovieClip::controlThis");
+        var tag, i, l;
+        var defineTag;
+        if ((this.currentFrame < 0 ) || (this.totalframes <= this.currentFrame)) {
+            this.currentFrame = 0;
+        }
+        var controlTags = this.controlTagsList[this.currentFrame];
+
+        for (i = 0, l = controlTags.length ; i < l ; i++) {
+            tag = controlTags[i];
+            switch (tag.code) {
+            case 1: // ShowFrame
+                break;
+            case 26: // PlaceObject2
+                // set display List;
+                var obj = null;
+                if (tag.move) {
+                    this.displayList.set(tag.depth, obj, tag);
+                } else {
+                    defineTag = dict.get(tag.id);
+                    console.log(tag);
+                    if (defineTag.code === 39) { // DefineSprite
+                        var name = tag.name;
+                        if (name === null) {
+                            name = "instance"+this.childMovieClips_seqnum;
+                            defineTag.name = name;
+                            this.childMovieClips_seqnum++;
+                        }
+                        var obj = FlappMovieClip(this, name, tag.matrix, tag.colorTransform);
+                        obj.setControlTags(defineTag.controlTags);
+                        this.addChildMovieClip(name, obj);
+                    } else if (defineTag.code === 2) { // DefineShape
+                        var obj = new FlappShape(name, tag.matrix, tag.colorTransform);
+                        console.log(obj);
+                        obj.loadShapeTag(defineTag);
+                    }
+                    this.displayList.set(tag.depth, obj, tag);
+                    break;
+                }
+            }
+        }
+    },
+    action: function() {
+        for (var mc in this.childMovieClips) {
+            this.childMovieClips[mc].action();
+        }
+        if (this.playing) {
+            this.actionThis();
+        }
+
+    },
+    actionThis: function() {
+        var actionTags = this.actionTagsList[this.currentFrame];
+        var l = actionTags.length;
+        console.debug("FlappMovieClip::actionThis: actionTags.length:"+l);
+        for (var i = 0 ; i < l ; i++) {
+            var tag = actionTags[i];
+            var movieClip = this;
+            FlappAction.exec(tag, movieClip, this.rootMovieClip);
+        }
+    },
+    increment: function() {
+        for (var mc in this.childMovieClips) {
+            this.childMovieClips[mc].increment();
+        }
+        if (this.playing) {
+            this.incrementThis();
+        }
+    },
+    incrementThis: function() {
+        console.debug("FlappMovieClip::incrementThis: "+this.currentFrame);
+        this.currentFrame++;
+        if (this.totalframes <= this.currentFrame) {
+            if (this.loop) {
+                this.currentFrame = 0; // play
+            } else {
+                this.playing = false;
+            }
+        }
+        if (this.totalframes === 1) {
+            this.playing = false;
+        }
+    },
+    render: function(canvas) {
+        var depthList = this.displayList.descSortedDepth();
+        for (var i = 0, l = depthList.length  ; i < l ; i++) {
+            var depth = depthList[i];
+            var obj = this.displayList.getObj(depth);
+            if (obj.OBJECT_TYPE === 2) { // MovieClip
+                obj.render(this.canvas);
+            } else if ((obj.OBJECT_TYPE === 2) && (this.playing == true)) {
+                obj.render(this.canvas);
+            }
+        }
+    },
+    setVariable: function(key, value) {
+        var lcKey = key.toLowerCase();
+        this.actionVarriableTable[lcKey] = value;
+        this.actionVarriablOrigKeys[lcKey] = key;
+    },
+    getVariable: function(key) {
+        var lcKey = key.toLowerCase();
+        if (lcKey in this.actionVarriableTable) {
+            return this.actionVarriableTable[lcKey];
+        }
+        return null;
+    },
+    gotoFrame: function(frameNum) {
+        console.debug("FlappMovieClip::gotoFrame"+frameNum);
+        this.currentFrame = frameNum;
+    },
+    gotoLabel: function(frameLabel) {
+        var frameNum = this.labelMap[frameLabel];
+        console.debug("FlappMovieClip::gotoFrame"+frameLabel+"=>"+frameNum);
+        this.currentFrame = frameNum;
+    },
+    play: function() {
+        this.playing = true;
+    },
+    stop: function() {
+        this.playing = false;
+    },
+    destroy: function() { // destructor
+        for (var name in this.childMovieClips) {
+            this.childMovieClips[name].destroy();
+        }
+        this.parentMovieClip = null;
+        this.rootMovieClip = null;
+        this.controlTagsList = null;
+        this.actionTagsList = null;
+        this.labelMap = null;
+        this.canvas = null;
+        this.displayList = null;
+    }
+};
+
+});
diff --git a/src/shape.js b/src/shape.js
new file mode 100644 (file)
index 0000000..a926e21
--- /dev/null
@@ -0,0 +1,30 @@
+goog.provide('FlappShape');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappShape = function(name, matrix, colorTransform) {
+    this.OBJECT_TYPE = 1; // 1:Shape, 2:MovieClip
+    this.canvas = document.createElement('canvas');
+    this.canvas.width = 240; // XXX
+    this.canvas.height = 240; // XXX
+    this.renderCode = "";
+};
+
+FlappShape.prototype = {
+    loadShapeTag: function(shape) {
+        ;
+    },
+    render: function(canvas) {
+        ;
+    }
+};
+
+
+FlappShape.shapetoRenderCode = function(shapeTag) {
+    ;
+};
+
+});
diff --git a/src/string.js b/src/string.js
new file mode 100644 (file)
index 0000000..415160c
--- /dev/null
@@ -0,0 +1,69 @@
+goog.provide('FlappString');
+
+var SJISToUTF8 = {};
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappString = function() {
+    ;
+};
+
+FlappString.ArrayToString = function(sjisArray) {
+    var strArray = [];
+    for (var i = 0, l = sjisArray.length ; i < l ; i++) {
+        strArray.push(String.fromCharCode(sjisArray[i]));
+    }
+    return strArray.join('');
+};
+
+FlappString.SJISArrayToString = function(sjisArray) {
+    console.log("FlappString::SJISArrayToString");
+    var string = FlappString.ArrayToString(sjisArray);
+    if (string in SJISToUTF8) {
+        return SJISToUTF8[string];
+    }
+    SJISToUTF8[string] = string; // dummy string
+    var b = new Blob([sjisArray]);
+    var fr = new FileReader();
+    fr.onloadend = function() {
+        SJISToUTF8[string] = this.result;
+    };
+    fr.readAsText(b, "sjis");
+
+    return string;
+};
+
+FlappString.SJISToUTF8 = function(string) {
+    if (string in SJISToUTF8) {
+        return SJISToUTF8[string];
+    }
+    return null;
+};
+
+FlappString.SJISArrayMBLength = function(sjis){
+    var len = 0;
+    for (var i = 0, l = sjis.length ; i < l ; i++) {
+        if (sjis[i] & 0x80) {
+            i++;
+        }
+        len ++;
+    }
+    return len;
+};
+
+FlappString.SJISArrayMBExtract = function(sjis){
+    var extractedSJIS = [];
+    for (var i = 0, l = sjis.length ; i < l ; i++) {
+        if (sjis[i] & 0x80) {
+            extractedSJIS.join([sjis[i++], sjis[i]]);
+        } else {
+            extractedSJIS.join([sjis[i]]);
+        }
+    }
+    return extractedSJIS;
+}
+
+});
diff --git a/src/swf/cxform.js b/src/swf/cxform.js
new file mode 100644 (file)
index 0000000..d18b2b7
--- /dev/null
@@ -0,0 +1,57 @@
+goog.provide('FlappSWFCXForm');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappSWFCXForm = function(ibit) {
+    ;
+};
+
+FlappSWFCXForm.load = function(ibit, hasAlpha) {
+    ibit.a();
+    var hasAddTerms = ibit.b();
+    var hasMultiTerms = ibit.b();
+    var nBits = ibit.ub(4);
+    if (hasMultiTerms) {
+        var redMultiTerm   = ibit.sb(nBits);
+        var greenMultiTerm = ibit.sb(nBits);
+        var blueMultiTerm  = ibit.sb(nBits);
+        if (hasAlpha) {
+            var alphaMultiTerm = ibit.sb(nBits);
+        }
+    } else {
+        var redMultiTerm   = 256;
+        var greenMultiTerm = 256;
+        var blueMultiTerm  = 256;
+        if (hasAlpha) {
+            var alphaMultiTerm = 256;
+        }
+    }
+    if (hasAddTerms) {
+        var redAddTerm   = ibit.sb(nBits);
+        var greenAddTerm = ibit.sb(nBits);
+        var blueAddTerm  = ibit.sb(nBits);
+        if (hasAlpha) {
+            var alphaAddTerm = ibit.sb(nBits);
+        }
+    } else {
+        var redAddTerm   = 0;
+        var greenAddTerm = 0;
+        var blueAddTerm  = 0;
+        if (hasAlpha) {
+            var alphaAddTerm = 0;
+        }
+    }
+    return {
+        redMultiTerm:redMultiTerm,
+        greenMultiTerm:greenMultiTerm,
+        blueMultiTerm:blueMultiTerm,
+        redAddTerm:redAddTerm,
+        greenAddTerm:greenAddTerm,
+        blueAddTerm:blueAddTerm
+    };
+};
+
+});
diff --git a/src/swf/fillstyles.js b/src/swf/fillstyles.js
new file mode 100644 (file)
index 0000000..304ec9c
--- /dev/null
@@ -0,0 +1,57 @@
+goog.provide('FlappSWFFillStyles');
+goog.require('FlappSWFMatrix');
+goog.require('FlappSWFGradient');
+goog.require('FlappSWFRGBA');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappSWFFillStyles = function(ibit) {
+    ;
+};
+
+FlappSWFFillStyles.load = function(code, ibit) {
+    ibit.a();
+    var count = ibit.ui8();
+    if ((code > 2) && (count === 0xff)) {
+        count = ibit.ui16();
+    }
+    var fillStyles = new Array(count);
+    var hasAlpha = (code < 32)?false:true;
+    for (var i = 0 ; i < count ;  i++) {
+        fillStyles[i] = FlappSWFFillStyles.loadStyle(ibit, hasAlpha);
+    }
+    return fillStyles;
+};
+
+FlappSWFFillStyles.loadStyle = function(ibit, hasAlpha) {
+    ibit.a();
+    var type = ibit.ui8();
+    var style = {type: type};
+    switch (type) {
+    case 0x00: // solid fill
+        style.color = FlappSWFRGBA.load(ibit, hasAlpha);
+        break;
+    case 0x10: // linear gradient fill
+    case 0x12: // radial gradient fill
+        style.matrix = FlappSWFMatrix.load(ibit);
+        style.gradient = new FlappSWFGradient(ibit, hasAlpha);
+        break;
+    case 0x13: // focal radial gradient fill
+        style.matrix = FlappSWFMatrix.load(ibit);
+        style.gradient = new FlappSWFGradient(ibit, hasAlpha);
+        break;
+    case 0x40: // repeating bitmap fill
+    case 0x41: // clipped bitmap fill
+    case 0x42: // non-smoothed repeating bitmap
+    case 0x43: // non-smoothed clipped bitmap
+        style.bitmapId = ibit.ui16();
+        style.matrix = FlappSWFMatrix.load(ibit);
+        break;
+    }
+    return style;
+}
+
+});
diff --git a/src/swf/gradient.js b/src/swf/gradient.js
new file mode 100644 (file)
index 0000000..c483217
--- /dev/null
@@ -0,0 +1,34 @@
+goog.provide('FlappSWFGradient');
+goog.require('FlappSWFRGBA');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappSWFGradient = function(ibit) {
+    ;
+};
+
+FlappSWFGradient.load = function(code, ibit) {
+    var hasAlpha = !(code<32);
+    ibit.a();
+    var bs; // TODO
+    var spread = bs.getUIBits(2);
+    var interpolationMode = bs.getUIBits(2);
+    var numGradients = bs.getUIBits(4);
+    this.NumGradients = numGradients;
+    var gradientRecords = [];
+    for (var i = 0 ; i < numGradients ; i++) {
+        var ratio = ibit.ui8();
+        var color = FlappSWFRGBA.load(ibit, hasAlpha);
+        gradientRecords.push({ratio:ratio, color:color});
+    }
+    return {
+        spreadMode: spread,
+        interpolationMode: interpolationMode,
+        gradientRecords: gradientRecords
+    };
+};
+
+});
diff --git a/src/swf/header.js b/src/swf/header.js
new file mode 100644 (file)
index 0000000..aadb4ac
--- /dev/null
@@ -0,0 +1,23 @@
+goog.provide('FlappSWFHeader');
+goog.require('FlappSWFRect');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappSWFHeader = function() {
+    ;
+};
+
+FlappSWFHeader.load = function(ibit) {
+    return { signature: ibit.strN(3),
+        version: ibit.ui8(),
+        filesize: ibit.ui32(),
+        framesize: FlappSWFRect.load(ibit),
+        framerate: ibit.ui16() / 0x100,
+        framecount: ibit.ui16()
+    };
+};
+    
+});
diff --git a/src/swf/linestyles.js b/src/swf/linestyles.js
new file mode 100644 (file)
index 0000000..3c54383
--- /dev/null
@@ -0,0 +1,33 @@
+goog.provide('FlappSWFLineStyles');
+goog.require('FlappSWFRGBA');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappSWFLineStyles = function(ibit) {
+    ;
+};
+
+FlappSWFLineStyles.load = function(code, ibit) {
+    ibit.a();
+    var count = ibit.ui8();
+    if ((code > 2) && (count === 0xff)) {
+        count = ibit.ui16();
+    }
+    var lineStyles = new Array(count);
+    var hasAlpha = !(code < 32);
+    for (var i = 0 ; i < count ;  i++) {
+        lineStyles[i] = FlappSWFLineStyles.loadStyle(ibit, hasAlpha);
+    }
+    return lineStyles;
+};
+
+FlappSWFLineStyles.loadStyle = function(ibit, hasAlpha) {
+    var width = ibit.ui16();
+    var color = FlappSWFRGBA.load(ibit, hasAlpha);
+    return {width:width, color:color};
+}
+
+});
diff --git a/src/swf/matrix.js b/src/swf/matrix.js
new file mode 100644 (file)
index 0000000..fa3b2c6
--- /dev/null
@@ -0,0 +1,43 @@
+goog.provide('FlappSWFMatrix');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappSWFMatrix = function(ibit) {
+    ;
+};
+
+FlappSWFMatrix.identity = function() {
+    return { scaleX:1, scaleY:1, skew0:0, skew1:0, transX:0, transY:0 };
+};
+
+FlappSWFMatrix.load = function(ibit) {
+    ibit.a();
+    if (ibit.b()) { // HasScale
+        var nScaleBits = ibit.ub(5);
+        var scaleX = ibit.sb(nScaleBits) / 0x10000;
+        var scaleY = ibit.sb(nScaleBits) / 0x10000;
+    } else {
+        var scaleX = 1;
+        var scaleY = 1;
+    }
+    if (ibit.b()) { // HasSkew
+        var nSkewBits = ibit.ub(5);
+        var skew0 = ibit.sb(nSkewBits) / 0x10000;
+        var skew1 = ibit.sb(nSkewBits) / 0x10000;
+    } else {
+        var skew0 = 0;
+        var skew1 = 0;
+    }
+    var nTransBits = ibit.ub(5);
+    var transX = ibit.sb(nTransBits);
+    var transY = ibit.sb(nTransBits);
+
+    return { scaleX:scaleX, scaleY:scaleY, skew0:skew0, skew1:skew1,
+        transX:transX, transY:transY
+    };
+};
+
+});
diff --git a/src/swf/rect.js b/src/swf/rect.js
new file mode 100644 (file)
index 0000000..1987c13
--- /dev/null
@@ -0,0 +1,23 @@
+goog.provide('FlappSWFRect');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappSWFRect = function(ibit) {
+    ;
+};
+
+FlappSWFRect.load = function(ibit) {
+    ibit.a();
+    var nbit = ibit.ub(5);
+    return {
+        xmin: ibit.sb(nbit),
+        xmax: ibit.sb(nbit),
+        ymin: ibit.sb(nbit),
+        ymax: ibit.sb(nbit)
+    };
+};
+
+});
diff --git a/src/swf/rgba.js b/src/swf/rgba.js
new file mode 100644 (file)
index 0000000..08f955f
--- /dev/null
@@ -0,0 +1,30 @@
+goog.provide('FlappSWFRGBA');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappSWFRGBA = function(ibit) {
+    ;
+};
+
+FlappSWFRGBA.load = function(ibit, hasAlpha) {
+    ibit.a();
+    if (hasAlpha) {
+        return {
+            red: ibit.ui8(),
+            green: ibit.ui8(),
+            blue: ibit.ui8(),
+            alpha: ibit.ui8()
+        };
+    }
+    return {
+        red: ibit.ui8(),
+        green: ibit.ui8(),
+        blue: ibit.ui8(),
+        alpha: 255
+    };
+};
+
+});
diff --git a/src/swf/shaperecords.js b/src/swf/shaperecords.js
new file mode 100644 (file)
index 0000000..9d992a4
--- /dev/null
@@ -0,0 +1,132 @@
+goog.provide('FlappSWFShapeRecords');
+goog.require('FlappSWFFillStyles');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappSWFShapeRecords = function(ibit) {
+    ;
+};
+
+FlappSWFShapeRecords.load = function(code, ibit, fillStyles, lineStyles, numFillBits, numLineBits) {
+    var shapeRecords = []; // [[fillstyle0, fillstyle1, linestyle, edgetypes, [edges]], [], ...]
+    var fillStyleBaseIndex = 0;
+    var lineStyleBaseIndex = 0;
+    var fillStyle0 = 0, fillStyle1 = 0, lineStyle = 0;
+    var currentX = 0, currentY = 0;
+    ibit.a();
+    var edgetypearray = ['M'];
+    var edges = [currentX, currentY];
+    var first6bits;
+    while (first6bits = ibit.ub(6)) {
+        if (first6bits & 0x20) { // Edge (1XXXXX)
+            var numBits = first6bits & 0x0F;
+            if (first6bits & 0x10) { // Straight Edge (11XXXX)
+                var deltaX = 0, deltaY = 0;
+                var generalLine = ibit.b();
+                if (generalLine) { // Straight Edge
+                    deltaX = ibit.sb(numBits + 2);
+                    deltaY = ibit.sb(numBits + 2);
+                } else { // Straight Edge
+                    var vertLine = ibit.b();
+                    if (vertLine) { // Straight Edge
+                        deltaY = ibit.sb(numBits + 2);
+                    } else {
+                        deltaX = ibit.sb(numBits + 2);
+                    }
+                }
+                var x = currentX + deltaX;
+                var y = currentY + deltaY;
+                edgetypearray.push('S');
+                edges.push(x, y);
+                currentX = x;
+                currentY = y;
+            } else { // Curved Edge (10XXXX)
+                var controlDeltaX = ibit.sb(numBits + 2);
+                var controlDeltaY = ibit.sb(numBits + 2);
+                var anchorDeltaX = ibit.sb(numBits + 2);
+                var anchorDeltaY = ibit.sb(numBits + 2);
+                var controlX = currentX + controlDeltaX;
+                var controlY = currentY + controlDeltaY;
+                var anchorX = controlX + anchorDeltaX;
+                var anchorY = controlY + anchorDeltaY;
+                edgetypearray.push('C');
+                edges.push(controlX, controlY,
+                    anchorX, anchorY);
+                currentX = anchorX;
+                currentY = anchorY;
+            }
+        } else if (first6bits) { // Change (0XXXXX != 000000)
+            if (edgetypearray.length > 1) {
+                shapeRecords.push(
+                    [fillStyle0, fillStyle1, lineStyle, edgetypearray.join(''),
+                        edges]
+                );
+            }
+            if (first6bits & 0x10) { // StateNewStyles
+                fillStyleBaseIndex = fillStyles.length;
+                lineStyleBaseIndex = lineStyles.length;
+                var appendFillStyles = FlappSWFFillStyles.load(code, ibit);
+                var appendLineStyles = FlappSWFLineStyles.load(code, ibit);
+                var extendFillStyles = [];
+                var extendLineStyles = [];
+                for (var i = 0, l = fillStyles.length ; i < l ; i++) {
+                    extendFillStyles.push(fillStyles[i]);
+                }
+                for (var i = 0, l = appendFillStyles.length ; i < l ; i++) {
+                    extendFillStyles.push(appendFillStyles[i]);
+                }
+                for (var i = 0, l = lineStyles.length ; i < l ; i++) {
+                    extendLineStyles.push(lineStyles[i]);
+                }
+                for (var i = 0, l = appendLineStyles.length ; i < l ; i++) {
+                    extendLineStyles.push(appendLineStyles[i]);
+                }
+                fillStyles = extendFillStyles;
+                lineStyles = extendFillStyles;
+                ibit.a();
+                var numBits = ibit.ui8();
+                numFillBits = numBits >> 4;
+                numLineBits = numBits & 0x0f;
+                fillStyleBaseIndex = fillStyles.length;
+                lineStyleBaseIndex = lineStyles.length;
+            }
+            if (first6bits & 1) { // StateMoveTo
+                var moveBits = ibit.ub(5);
+                currentX = ibit.sb(moveBits); // MoveDeltaX(?)
+                currentY = ibit.sb(moveBits); // MoveDeltaY(?)
+            }
+            if (first6bits & 2) { // StateFillStyle0
+                fillStyle0 = ibit.ub(numFillBits);
+                if (fillStyle0) {
+                    fillStyle0 += fillStyleBaseIndex;
+                }
+            }
+            if (first6bits & 4) { // StateFillStyle1
+                fillStyle1 = ibit.ub(numFillBits);
+                if (fillStyle1) {
+                    fillStyle1 += fillStyleBaseIndex;
+                }
+            }
+            if (first6bits & 8) { // StateLineStyle
+                lineStyle = ibit.ub(numLineBits);
+                if (lineStyle) {
+                    lineStyle += lineStyleBaseIndex;
+                }
+            }
+            edgetypearray = ['M'];
+            edges = [currentX, currentY];
+        }
+    }
+    if (edgetypearray.length > 1) {
+        shapeRecords.push(
+            [fillStyle0, fillStyle1, lineStyle, edgetypearray.join(''),
+                edges]
+        );
+    }
+    return shapeRecords;
+};
+
+});
diff --git a/src/swf/tag.js b/src/swf/tag.js
new file mode 100644 (file)
index 0000000..7e70f4a
--- /dev/null
@@ -0,0 +1,52 @@
+goog.provide('FlappSWFTag');
+goog.require('FlappSWFTagShowFrame');
+goog.require('FlappSWFTagDefineShape');
+goog.require('FlappSWFTagDefineBitsJPEG');
+goog.require('FlappSWFTagJPEGTables');
+goog.require('FlappSWFTagSetBackgroundColor');
+goog.require('FlappSWFTagDoAction');
+goog.require('FlappSWFTagPlaceObject');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappSWFTag = function() {
+     ;
+};
+
+// tag factory
+FlappSWFTag.load = function(code, length, ibit) {
+//     console.log("FlappSWFTag.load(code:"+code+", length:"+length+", ibit)");
+    var tag = null;
+    switch (code) {
+    case 1: // ShowFrame
+        tag = new FlappSWFTagShowFrame(code, length, ibit);
+        break;
+    case 2: // DefineShape
+    case 22: // DefineShape2
+    case 32: // DefineShape3
+        tag = new FlappSWFTagDefineShape(code, length, ibit);
+        break;
+    case 6: // DefineBits(JPEG)
+        tag = new FlappSWFTagDefineBitsJPEG(code, length, ibit);
+        break;
+    case 8: // JPEGTables
+        tag = new FlappSWFTagJPEGTables(code, length, ibit);
+        break;
+    case 9: // SetBackgroundColor
+        tag = new FlappSWFTagSetBackgroundColor(code, length, ibit);
+        break;
+    case 12: // DoAction
+        tag = new FlappSWFTagDoAction(code, length, ibit);
+        break;
+    case 26: // PlaceObject2
+        tag = new FlappSWFTagPlaceObject(code, length, ibit);
+        break;
+    }
+//     console.debug(tag);
+    return tag;
+};
+
+});
diff --git a/src/swf/tag/definebitsjpeg.js b/src/swf/tag/definebitsjpeg.js
new file mode 100644 (file)
index 0000000..9fc202b
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+  DefineBitsJPEG parser
+*/
+goog.provide('FlappSWFTagDefineBitsJPEG');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappSWFTagDefineBitsJPEG = function(code, length, ibit) {
+//     console.log("FlappSWFTagDefineBitsJPEG(code:"+code+", length:"+length+", ibit)");
+    this.code = code;
+    this.length = length;
+    this.id = ibit.ui16();
+    if (code <= 21) { // DefineBits & DefineBitsJPEG2
+        this.jpegData = ibit.sub(length - 2);
+    } else {
+        var alphaDataOffset = ibit.ui32();
+        this.jpegData = ibit.sub(alphaDataOffset);
+        this.abitmapAlphaData = (length - 2 - alphaDataOffset);
+    }
+};
+
+});
diff --git a/src/swf/tag/defineshape.js b/src/swf/tag/defineshape.js
new file mode 100644 (file)
index 0000000..1b52c3d
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+  DefineShape parser
+*/
+goog.provide('FlappSWFTagDefineShape');
+goog.require('FlappSWFShapeRecords');
+goog.require('FlappSWFFillStyles');
+goog.require('FlappSWFLineStyles');
+goog.require('FlappSWFRect');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappSWFTagDefineShape = function(code, length, ibit) {
+//     console.log("FlappSWFTagDefineShape(code:"+code+", length:"+length+", ibit)");
+    this.code = code;
+    this.length = length;
+    this.id = ibit.ui16();
+    this.bounds = FlappSWFRect.load(ibit);
+    var fillStyles = FlappSWFFillStyles.load(code, ibit);
+    var lineStyles = FlappSWFLineStyles.load(code, ibit);
+    ibit.a();
+    var numBits = ibit.ui8();
+    var numFillBits = numBits >> 4;
+    var numLineBits = numBits & 0x0f;
+    this.fillStyles = fillStyles;
+    this.lineStyles = lineStyles;
+    this.shapes = FlappSWFShapeRecords.load(code, ibit, fillStyles, lineStyles, numFillBits, numLineBits);
+};
+
+});
diff --git a/src/swf/tag/doaction.js b/src/swf/tag/doaction.js
new file mode 100644 (file)
index 0000000..9bf82ff
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+  DoAction parser
+*/
+goog.provide('FlappSWFTagDoAction');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappSWFTagDoAction = function(code, length, ibit) {
+//     console.log("FlappSWFTagDoAction(code:"+code+", length:"+length+", ibit)");
+    this.code = code;
+    this.length = length;
+    //
+    this.actions = ibit.sub(length);
+};
+
+});
diff --git a/src/swf/tag/jpegtables.js b/src/swf/tag/jpegtables.js
new file mode 100644 (file)
index 0000000..346b435
--- /dev/null
@@ -0,0 +1,19 @@
+/*
+  JPEGTables parser
+*/
+goog.provide('FlappSWFTagJPEGTables');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappSWFTagJPEGTables = function(code, length, ibit) {
+//     console.log("FlappSWFTagJPEGTables(code:"+code+", length:"+length+", ibit)");
+    this.code = code;
+    this.length = length;
+    //
+    this.jpegData = ibit.sub(length);
+};
+
+});
diff --git a/src/swf/tag/placeobject.js b/src/swf/tag/placeobject.js
new file mode 100644 (file)
index 0000000..9433c33
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+  PlaceObject parser
+*/
+goog.provide('FlappSWFTagPlaceObject');
+goog.require('FlappSWFMatrix');
+goog.require('FlappSWFCXForm');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappSWFTagPlaceObject = function(code, length, ibit) {
+//     console.log("FlappSWFTagPlaceObject(code:"+code+", length:"+length+", ibit)");
+    this.code = code;
+    this.length = length;
+    //
+    if (code === 26) { // PlaceObject2
+        var placeFlag = ibit.ui8();
+        var placeFlagHasClipActions    = (placeFlag & 0x80);
+        var placeFlagHasClipDepth      = (placeFlag & 0x40);
+        var placeFlagHasName           = (placeFlag & 0x20);
+        var placeFlagHasRatio          = (placeFlag & 0x10);
+        var placeFlagHasColorTransform = (placeFlag & 0x08);
+        var placeFlagHasMatrix         = (placeFlag & 0x04);
+        var placeFlagHasCharacter      = (placeFlag & 0x02);
+        var placeFlagMove              = (placeFlag & 0x01);
+        this.move = placeFlagMove;
+        this.depth = ibit.ui16();
+        this.id = (placeFlagHasCharacter)?ibit.ui16():null;
+        this.matrix = (placeFlagHasMatrix)?FlappSWFMatrix.load(ibit):null;
+        this.colorTransform = (placeFlagHasColorTransform)?FlappSWFCXForm(ibit, true):null;
+        this.ratio = (placeFlagHasRatio)?ibit.ui16():null;
+        this.name = (placeFlagHasName)?ibit.str():null;
+        this.clipDepth = (placeFlagHasClipDepth)?ibit.ui16():null;
+        // ClipActions swf5 later
+    } else if (code === 4) { // PlaceObject
+        this.id = ibit.ui16();
+        this.depth = ibit.ui16();
+        this.matrix = FlappSWFMatrix.load(ibit);
+        ibit.a();
+        this.colorTransform = (ibit.hasNext(1))?FlappSWFCXForm(ibit, false):null;
+    }
+};
+
+});
diff --git a/src/swf/tag/setbackgroundcolor.js b/src/swf/tag/setbackgroundcolor.js
new file mode 100644 (file)
index 0000000..d039a54
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+  SetBackgroundColor parser
+*/
+goog.provide('FlappSWFTagSetBackgroundColor');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappSWFTagSetBackgroundColor = function(code, length, ibit) {
+//     console.log("FlappSWFTagSetBackgroundColor(code:"+code+", length:"+length+", ibit)");
+    this.code = code;
+    this.length = length;
+    //
+    this.red = ibit.ui8();
+    this.green = ibit.ui8();
+    this.blue = ibit.ui8();
+};
+
+});
diff --git a/src/swf/tag/showframe.js b/src/swf/tag/showframe.js
new file mode 100644 (file)
index 0000000..987da19
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+  ShowFrame parser
+*/
+goog.provide('FlappSWFTagShowFrame');
+
+goog.scope(function() {
+
+/**
+ * @constructor
+ */
+FlappSWFTagShowFrame = function(code, length, ibit) {
+//     console.log("FlappSWFTagShowFrame(code:"+code+", length:"+length+", ibit)");
+    this.code = code;
+    this.length = length;
+};
+
+});
diff --git a/string.js b/string.js
deleted file mode 100644 (file)
index 5bba189..0000000
--- a/string.js
+++ /dev/null
@@ -1,59 +0,0 @@
-(function(global) {
-    var SJISToUTF8 = {};
-    var FlappString = function() {
-       ;
-    };
-
-    FlappString.prototype = {
-       
-    };
-    FlappString.ArrayToString = function(sjisArray) {
-       var strArray = [];
-       for (var i = 0, l = sjisArray.length ; i < l ; i++) {
-           strArray.push(String.fromCharCode(sjisArray[i]));
-       }
-       return strArray.join('');
-    }
-    FlappString.SJISArrayToString = function(sjisArray) {
-       console.log("FlappString::SJISArrayToString");
-       string = FlappString.ArrayToString(sjisArray);
-       if (string in SJISToUTF8) {
-           return string;
-       }
-       SJISToUTF8[string] = string; // dummy string
-       var b = new Blob([sjisArray]);
-       var fr = new FileReader();
-       fr.onloadend = function() {
-           SJISToUTF8[string] = this.result;
-       }
-       ret = fr.readAsText(b, "sjis");
-    };
-    FlappString.SJISToUTF8 = function(string) {
-       if (string in SJISToUTF8) {
-           return SJISToUTF8[string];
-       }
-       return null;
-    };
-    FlappString.SJISArrayMBLength = function(sjis){
-       var len = 0;
-       for (i = 0, l = sjis.length ; i < l ; i++) {
-           if (sjis[i] & 0x80) {
-               i++;
-           }
-           len ++;
-       }
-       return len;
-    };
-    FlappString.SJISArrayMBExtract = function(sjis){
-       var extractedSJIS = [];
-       for (i = 0, l = sjis.length ; i < l ; i++) {
-           if (sjis[i] & 0x80) {
-               extractedSJIS.join([sjis[i++], sjis[i]]);
-           } else {
-               extractedSJIS.join([sjis[i]]);
-           }
-       }
-       return extractedSJIS;
-    }
-    global.FlappString = FlappString;
-})(this);
diff --git a/swf/cxform.js b/swf/cxform.js
deleted file mode 100644 (file)
index 8829407..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-(function(global) {
-    var FlappSWFCXForm = function(ibit) {
-       ;
-    };
-    FlappSWFCXForm.load = function(ibit, hasAlpha) {
-       ibit.a();
-       var hasAddTerms = ibit.b();
-       var hasMultiTerms = ibit.b();
-       var nBits = ibit.ub(4);
-       if (hasMultiTerm) {
-           var redMultiTerm   = ibit.sb(nBits);
-           var greenMultiTerm = ibit.sb(nBits);
-           var blueMultiTerm  = ibit.sb(nBits);
-           if (hasAlpha) {
-               var alphaMultiTerm = ibit.sb(nBits);
-           }
-       } else {
-           var redMultiTerm   = 256;
-           var greenMultiTerm = 256;
-           var blueMultiTerm  = 256;
-           if (hasAlpha) {
-               var alphaMultiTerm = 256;
-           }
-       }
-       if (hasAddTerms) {
-           var redAddTerm   = ibit.sb(nBits);
-           var greenAddTerm = ibit.sb(nBits);
-           var blueAddTerm  = ibit.sb(nBits);
-           if (hasAlpha) {
-               var alphaAddTerm = ibit.sb(nBits);
-           }
-       } else {
-           var redAddTerm   = 0;
-           var greenAddTerm = 0;
-           var blueAddTerm  = 0;
-           if (hasAlpha) {
-               var alphaAddTerm = 0;
-           }
-       }
-       return { redMultiTerm:redMuliTerm,
-                greenMultiTerm:greenMultiTerm,
-                blueMultiTerm:blueMultiTerm,
-                redAddTerm:redAddTerm,
-                greenAddTerm:greenAddTerm,
-                blueAddTerm:blueAddTerm
-              };
-    };
-
-    global.FlappSWFCXForm = FlappSWFCXForm;
-})(this);
diff --git a/swf/fillstyles.js b/swf/fillstyles.js
deleted file mode 100644 (file)
index a95cb92..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-(function(global) {
-    var FlappSWFFillStyles = function(ibit) {
-       ;
-    };
-    FlappSWFFillStyles.load = function(code, ibit) {
-       ibit.a();
-       var count = ibit.ui8();
-        if ((code > 2) && (count === 0xff)) {
-            count = ibit.ui16();
-        }
-       var fillStyles = new Array(count);
-       var hasAlpha = (code < 32)?false:true;
-       for (var i = 0 ; i < count ;  i++) {
-           fillStyles[i] = FlappSWFFillStyles.loadStyle(ibit, hasAlpha);
-       }
-       return fillStyles;
-    };
-    FlappSWFFillStyles.loadStyle = function(ibit, hasAlpha) {
-       ibit.a();
-       var type = ibit.ui8();
-       var style = {type: type};
-        switch (type) {
-        case 0x00: // solid fill
-            style.color = FlappSWFRGBA.load(ibit, hasAlpha);
-           break;
-        case 0x10: // linear gradient fill
-        case 0x12: // radial gradient fill
-           style.matrix = FlappSWFMatrix.load(ibit);
-           style.gradient = new FlappSWFGradient(ibit, hasAlpha);
-           break;
-        case 0x13: // focal radial gradient fill
-           style.matrix = FlappSWFMatrix.load(ibit);
-           style.gradient = new FlappSWFGradient(ibit, hasAlpha);
-           break;
-        case 0x40: // repeating bitmap fill
-        case 0x41: // clipped bitmap fill
-        case 0x42: // non-smoothed repeating bitmap
-        case 0x43: // non-smoothed clipped bitmap
-           style.bitmapId = ibit.ui16();
-           style.matrix = FlappSWFMatrix.load(ibit);
-           break;
-       }
-       return style;
-    }
-
-    global.FlappSWFFillStyles = FlappSWFFillStyles;
-})(this);
diff --git a/swf/gradient.js b/swf/gradient.js
deleted file mode 100644 (file)
index a6f1bbb..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-(function(global) {
-    var FlappSWFGradient = function(ibit) {
-       ;
-    };
-    FlappSWFGradient.load = function(code, ibit) {
-       var gradientRecords = [];
-       var hasAlpha = (code<32)?false:true;
-       ibit.a();
-       this.SpreadMode = bs.getUIBits(2);
-        this.InterpolationMode = bs.getUIBits(2);
-        var numGradients = bs.getUIBits(4);
-        this.NumGradients = numGradients;
-        var gradientRecords = [];
-        for (i = 0 ; i < numGradients ; i++) {
-           var ratio = ibit.ui8();
-           var color = FlappSWFRGBA.load(ibit, hasAlpha);
-            gradientRecords.push({ratio:ratio, color:color});
-        }
-       return { spreadMode: spread,
-                interpolationMode: interpolationMode,
-                gradientRecords: gradientRecords };
-    }
-    global.FlappSWFGradient = FlappSWFGradient;
-})(this);
diff --git a/swf/header.js b/swf/header.js
deleted file mode 100644 (file)
index ac3d8a3..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-(function(global) {
-    var FlappSWFHeader = function() {
-       ;
-    };
-    FlappSWFHeader.prototype = {
-       
-    };
-    FlappSWFHeader.load = function(ibit) {
-       return { signature: ibit.strN(3),
-                version: ibit.ui8(),
-                filesize: ibit.ui32(),
-                framesize: FlappSWFRect.load(ibit),
-                framerate: ibit.ui16() / 0x100,
-                framecount: ibit.ui16()
-              };
-    };
-    
-    global.FlappSWFHeader = FlappSWFHeader;
-})(this);
diff --git a/swf/linestyles.js b/swf/linestyles.js
deleted file mode 100644 (file)
index 6a1b8ea..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-(function(global) {
-    var FlappSWFLineStyles = function(ibit) {
-       ;
-    };
-    FlappSWFLineStyles.load = function(code, ibit) {
-
-       ibit.a();
-       var count = ibit.ui8();
-        if ((code > 2) && (count === 0xff)) {
-            count = ibit.ui16();
-        }
-       var lineStyles = new Array(count);
-       var hasAlpha = (code < 32)?false:true;
-       for (var i = 0 ; i < count ;  i++) {
-           lineStyles[i] = FlappSWFLineStyles.loadStyle(ibit, hasAlpha);
-       }
-       return lineStyles;
-    };
-    FlappSWFLineStyles.loadStyle = function(ibit, hasAlpha) {
-       var width = ibit.ui16();
-        var color = FlappSWFRGBA.load(ibit, hasAlpha);
-       return {width:width, color:color};
-    }
-    global.FlappSWFLineStyles = FlappSWFLineStyles;
-})(this);
diff --git a/swf/matrix.js b/swf/matrix.js
deleted file mode 100644 (file)
index 2215c59..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-(function(global) {
-    var FlappSWFMatrix = function(ibit) {
-       ;
-    };
-    FlappSWFMatrix.identity = function() {
-       return { scaleX:1, scaleY:1, skew0:0, skew1:0, transX:0, transY:0 };
-    };
-    FlappSWFMatrix.load = function(ibit) {
-       ibit.a();
-       if (ibit.b()) { // HasScale
-           var nScaleBits = ibit.ub(5);
-           var scaleX = ibit.sb(nScaleBits) / 0x10000;
-           var scaleY = ibit.sb(nScaleBits) / 0x10000;
-       } else {
-           var scaleX = 1;
-           var scaleY = 1;
-           
-       }
-       if (ibit.b()) { // HasSkew
-           var nSkewBits = ibit.ub(5);
-           var skew0 = ibit.sb(nSkewBits) / 0x10000;
-           var skew1 = ibit.sb(nSkeweBits) / 0x10000;
-       } else {
-           var skew0 = 0;
-           var skew1 = 0;
-       }
-       var nTransBits = ibit.ub(5);
-       var transX = ibit.sb(nTransBits);
-       var transY = ibit.sb(nTransBits);
-
-       return { scaleX:scaleX, scaleY:scaleY, skew0:skew0, skew1:skew1,
-                transX:transX, transY:transY
-              };
-    };
-
-    global.FlappSWFMatrix = FlappSWFMatrix;
-})(this);
diff --git a/swf/rect.js b/swf/rect.js
deleted file mode 100644 (file)
index bc1d6fd..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-(function(global) {
-    var FlappSWFRect = function(ibit) {
-       ;
-    };
-    FlappSWFRect.load = function(ibit) {
-       ibit.a();
-       var nbit = ibit.ub(5);
-       return { xmin: ibit.sb(nbit),
-                xmax: ibit.sb(nbit),
-                ymin: ibit.sb(nbit),
-                ymax: ibit.sb(nbit) };
-    };
-
-    global.FlappSWFRect = FlappSWFRect;
-})(this);
diff --git a/swf/rgba.js b/swf/rgba.js
deleted file mode 100644 (file)
index e637d69..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-(function(global) {
-    var FlappSWFRGBA = function(ibit) {
-       ;
-    };
-    FlappSWFRGBA.load = function(ibit, hasAlpha) {
-       ibit.a();
-       if (hasAlpha) {
-           return { red: ibit.ui8(),
-                    green: ibit.ui8(),
-                    blue: ibit.ui8(),
-                    alpha: ibit.ui8()
-                  };
-       }
-       return { red: ibit.ui8(),
-                green: ibit.ui8(),
-                blue: ibit.ui8(),
-                alpha: 255
-              };
-    }
-    global.FlappSWFRGBA = FlappSWFRGBA;
-})(this);
diff --git a/swf/shaperecords.js b/swf/shaperecords.js
deleted file mode 100644 (file)
index b0d85f7..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-(function(global) {
-    var FlappSWFShapeRecords = function(ibit) {
-       ;
-    };
-    FlappSWFShapeRecords.load = function(code, ibit, fillStyles, lineStyles, numFillBits, numLineBits) {
-       var shapeRecords = []; // [[fillstyle0, fillstyle1, linestyle, edgetypes, [edges]], [], ...]
-       var fillStyleBaseIndex = 0;
-       var lineStyleBaseIndex = 0;
-       var fillStyle0 = 0, fillStyle1 = 0, lineStyle = 0;
-       var currentX = 0, currentY = 0;
-       ibit.a();
-       var edgetypearray = ['M'];
-       var edges = [currentX, currentY];
-       var first6bits;
-       while (first6bits = ibit.ub(6)) {
-           if (first6bits & 0x20) { // Edge (1XXXXX)
-               var numBits = first6bits & 0x0F;
-               if (first6bits & 0x10) { // Straight Edge (11XXXX)
-                   var deltaX = 0, deltaY = 0;
-                   var generalLine = ibit.b();
-                   if (generalLine) { // Straight Edge
-                       deltaX = ibit.sb(numBits + 2);
-                       deltaY = itib.sb(numBits + 2);
-                   } else { // Straight Edge
-                       var vertLine = ibit.b();
-                       if (vertLine) { // Straight Edge
-                           deltaY = ibit.sb(numBits + 2);
-                       } else {
-                           deltaX = ibit.sb(numBits + 2);
-                       }
-                   }
-                   var x = currentX + deltaX;
-                   var y = currentY + deltaY;
-                   edgetypearray.push('S');
-                   edges.push(x, y);
-                   currentX = x;
-                   currentY = y;
-               } else { // Curved Edge (10XXXX)
-                   var controlDeltaX = ibit.sb(numBits + 2);
-                   var controlDeltaY = ibit.sb(numBits + 2);
-                   var anchorDeltaX = ibit.sb(numBits + 2);
-                   var anchorDeltaY = ibit.sb(numBits + 2);
-                   var controlX = currentX + controlDeltaX;
-                   var controlY = currentY + controlDeltaY;
-                   var anchorX = controlX + anchorDeltaX;
-                   var anchorY = controlY + anchorDeltaY;
-                   edgetypearray.push('C');
-                   edges.push(controlX, controlY,
-                              anchorX, anchorY);
-                   currentX = anchorX;
-                   currentY = anchorY;
-               }
-           } else if (first6bits) { // Change (0XXXXX != 000000)
-               if (edgetypearray.length > 1) {
-                   shapeRecords.push(
-                       [fillStyle0, fillStyle1, lineStyle, edgetypearray.join(''),
-                        edges]
-                   );
-               }
-               if (first6bits & 0x10) { // StateNewStyles
-                   fillStyleBaseIndex = fillStyles.length;
-                   lineStyleBaseIndex = lineStyles.length;
-                   var appendFillStyles = FlappSWFFillStyles.load(code, ibit);
-                   var appendLineStyles = FlappSWFLineStyles.load(code, ibit);
-                   var extendFillStyles = [];
-                   var extendLineStyles = [];
-                   for (var i = 0, l = fillStyles.length ; i < l ; i++) {
-                       extendFillStyles.push(fillStyles[i]);
-                   }
-                   for (var i = 0, l = appendFillStyles.length ; i < l ; i++) {
-                       extendFillStyles.push(appendFillStyles[i]);
-                   }
-                   for (var i = 0, l = lineStyles.length ; i < l ; i++) {
-                       extendLineStyles.push(lineStyles[i]);
-                   }
-                   for (var i = 0, l = appendLineStyles.length ; i < l ; i++) {
-                       extendLineStyles.push(appendLineStyles[i]);
-                   }
-                   fillStyles = extendFillStyles;
-                   lineStyles = extendFillStyles;
-                   ibit.a();
-                   var numBits = ibit.ui8();
-                   numFillBits = numBits >> 4;
-                   numLineBits = numBits & 0x0f;
-                   fillStyleBaseIndex = fillStyles.length;
-                   lineStyleBaseIndex = lineStyles.length;
-               }
-               if (first6bits & 1) { // StateMoveTo
-                   var moveBits = ibit.ub(5);
-                   currentX = ibit.sb(moveBits); // MoveDeltaX(?)
-                   currentY = ibit.sb(moveBits); // MoveDeltaY(?)
-               }
-               if (first6bits & 2) { // StateFillStyle0
-                   fillStyle0 = ibit.ub(numFillBits);
-                   if (fillStyle0) {
-                       fillStyle0 += fillStyleBaseIndex; 
-                   }
-               }
-               if (first6bits & 4) { // StateFillStyle1
-                   fillStyle1 = ibit.ub(numFillBits);
-                   if (fillStyle1) {
-                       fillStyle1 += fillStyleBaseIndex; 
-                   }
-               }
-               if (first6bits & 8) { // StateLineStyle
-                   lineStyle = ibit.ub(numLineBits);
-                   if (lineStyle) {
-                       lineStyle += lineStyleBaseIndex; 
-                   }
-               }
-               edgetypearray = ['M'];
-               edges = [currentX, currentY];
-           }
-       }
-       if (edgetypearray.length > 1) {
-           shapeRecords.push(
-               [fillStyle0, fillStyle1, lineStyle, edgetypearray.join(''),
-                edges]
-           );
-       }
-       return shapeRecords;
-    }
-    global.FlappSWFShapeRecords = FlappSWFShapeRecords;
-})(this);
diff --git a/swf/tag.js b/swf/tag.js
deleted file mode 100644 (file)
index 6a0c654..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-(function(global) {
-    var FlappSWFTag = function() {
-       ;
-    };
-    // tag factory
-    FlappSWFTag.load = function(code, length, ibit) {
-//     console.log("FlappSWFTag.load(code:"+code+", length:"+length+", ibit)");
-       var tag = null;
-       switch (code) {
-       case 1: // ShowFrame
-           tag = new FlappSWFTagShowFrame(code, length, ibit);
-           break;
-       case 2: // DefineShape
-       case 22: // DefineShape2
-       case 32: // DefineShape3
-           tag = new FlappSWFTagDefineShape(code, length, ibit);
-           break;
-       case 6: // DefineBits(JPEG)
-           tag = new FlappSWFTagDefineBitsJPEG(code, length, ibit);
-           break;
-       case 8: // JPEGTables
-           tag = new FlappSWFTagJPEGTables(code, length, ibit);
-           break;
-       case 9: // SetBackgroundColor
-           tag = new FlappSWFTagSetBackgroundColor(code, length, ibit);
-           break;
-       case 12: // DoAction
-           tag = new FlappSWFTagDoAction(code, length, ibit);
-           break;
-       case 26: // PlaceObject2
-           tag = new FlappSWFTagPlaceObject(code, length, ibit);
-           break;
-       }
-//     console.debug(tag);
-       return tag;
-    }
-    global.FlappSWFTag = FlappSWFTag;
-})(this);
diff --git a/swf/tag/definebitsjpeg.js b/swf/tag/definebitsjpeg.js
deleted file mode 100644 (file)
index 570ca9d..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
-  DefineBitsJPEG parser
-*/
-
-(function(global) {
-    var FlappSWFTagDefineBitsJPEG = function(code, length, ibit) {
-//     console.log("FlappSWFTagDefineBitsJPEG(code:"+code+", length:"+length+", ibit)");
-       this.code = code;
-       this.length = length;
-       this.id = ibit.ui16();
-       if (code <= 21) { // DefineBits & DefineBitsJPEG2
-         this.jpegData = ibit.sub(length - 2);
-       } else {
-         var alphaDataOffset = ibit.ui32();
-         this.jpegData = ibit.sub(alphaDataOffset);
-         this.abitmapAlphaData = (length - 2 - alphaDataOffset);
-       }
-    }
-    global.FlappSWFTagDefineBitsJPEG = FlappSWFTagDefineBitsJPEG;
-})(this);
diff --git a/swf/tag/defineshape.js b/swf/tag/defineshape.js
deleted file mode 100644 (file)
index 9b6256e..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
-  DefineShape parser
-*/
-
-(function(global) {
-    var FlappSWFTagDefineShape = function(code, length, ibit) {
-//     console.log("FlappSWFTagDefineShape(code:"+code+", length:"+length+", ibit)");
-       this.code = code;
-       this.length = length;
-       this.id = ibit.ui16();
-        this.bounds = FlappSWFRect.load(ibit);
-       var fillStyles = FlappSWFFillStyles.load(code, ibit);
-       var lineStyles = FlappSWFLineStyles.load(code, ibit);
-       ibit.a();
-        var numBits = ibit.ui8();
-        var numFillBits = numBits >> 4;
-        var numLineBits = numBits & 0x0f;
-        this.fillStyles = fillStyles;
-        this.lineStyles = lineStyles;
-        this.shapes = FlappSWFShapeRecords.load(code, ibit, fillStyles, lineStyles, numFillBits, numLineBits);
-    }
-    global.FlappSWFTagDefineShape = FlappSWFTagDefineShape;
-})(this);
diff --git a/swf/tag/doaction.js b/swf/tag/doaction.js
deleted file mode 100644 (file)
index 930ebcd..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
-  DoAction parser
-*/
-
-(function(global) {
-    var FlappSWFTagDoAction = function(code, length, ibit) {
-//     console.log("FlappSWFTagDoAction(code:"+code+", length:"+length+", ibit)");
-       this.code = code;
-       this.length = length;
-       //
-       this.actions = ibit.sub(length);
-    }
-    global.FlappSWFTagDoAction = FlappSWFTagDoAction;
-})(this);
diff --git a/swf/tag/jpegtables.js b/swf/tag/jpegtables.js
deleted file mode 100644 (file)
index a07a01c..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
-  JPEGTables parser
-*/
-
-(function(global) {
-    var FlappSWFTagJPEGTables = function(code, length, ibit) {
-//     console.log("FlappSWFTagJPEGTables(code:"+code+", length:"+length+", ibit)");
-       this.code = code;
-       this.length = length;
-       //
-       this.jpegData = ibit.sub(length);
-    }
-    global.FlappSWFTagJPEGTables = FlappSWFTagJPEGTables;
-})(this);
diff --git a/swf/tag/placeobject.js b/swf/tag/placeobject.js
deleted file mode 100644 (file)
index 50217ea..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
-  PlaceObject parser
-*/
-
-(function(global) {
-    var FlappSWFTagPlaceObject = function(code, length, ibit) {
-//     console.log("FlappSWFTagPlaceObject(code:"+code+", length:"+length+", ibit)");
-       this.code = code;
-       this.length = length;
-       //
-       if (code === 26) { // PlaceObject2
-           var placeFlag = ibit.ui8();
-           var placeFlagHasClipActions    = (placeFlag & 0x80)?true:false;
-           var placeFlagHasClipDepth      = (placeFlag & 0x40)?true:false;
-           var placeFlagHasName           = (placeFlag & 0x20)?true:false;
-           var placeFlagHasRatio          = (placeFlag & 0x10)?true:false;
-           var placeFlagHasColorTransform = (placeFlag & 0x08)?true:false;
-           var placeFlagHasMatrix         = (placeFlag & 0x04)?true:false;
-           var placeFlagHasCharacter      = (placeFlag & 0x02)?true:false;
-           var placeFlagMove              = (placeFlag & 0x01)?true:false;
-           this.move = placeFlagMove;
-           this.depth = ibit.ui16();
-           this.id = (placeFlagHasCharacter)?ibit.ui16():null;
-           this.matrix = (placeFlagHasMatrix)?FlappSWFMatrix.load(ibit):null;
-           this.colorTransform = (placeFlagHasColorTransform)?FlappSWFCXForm(ibit, true):null;
-           this.ratio = (placeFlagHasRatio)?ibit.ui16():null;
-           this.name = (placeFlagHasName)?ibit.str():null;
-           this.clipDepth = (placeFlagHasClipDepth)?ibit.ui16():null;
-           // ClipActions swf5 later
-       } else if (code === 4) { // PlaceObject
-           this.id = ibit.ui16();
-           this.depth = ibit.ui16();
-           this.matrix = FlappSWFMatrix.load(ibit);
-           ibit.a();
-           this.colorTransform = (ibit.hasNext(1))?FlappSWFCXForm(ibit, false):null;
-       }
-    }
-    global.FlappSWFTagPlaceObject = FlappSWFTagPlaceObject;
-})(this);
diff --git a/swf/tag/setbackgroundcolor.js b/swf/tag/setbackgroundcolor.js
deleted file mode 100644 (file)
index 3df5aa2..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
-  SetBackgroundColor parser
-*/
-
-(function(global) {
-    var FlappSWFTagSetBackgroundColor = function(code, length, ibit) {
-//     console.log("FlappSWFTagSetBackgroundColor(code:"+code+", length:"+length+", ibit)");
-       this.code = code;
-       this.length = length;
-       //
-       this.red = ibit.ui8();
-       this.green = ibit.ui8();
-       this.blue = ibit.ui8();
-    }
-
-    global.FlappSWFTagSetBackgroundColor = FlappSWFTagSetBackgroundColor;
-})(this);
diff --git a/swf/tag/showframe.js b/swf/tag/showframe.js
deleted file mode 100644 (file)
index da74775..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
-  ShowFrame parser
-*/
-
-(function(global) {
-    var FlappSWFTagShowFrame = function(code, length, ibit) {
-//     console.log("FlappSWFTagShowFrame(code:"+code+", length:"+length+", ibit)");
-       this.code = code;
-       this.length = length;
-    }
-    global.FlappSWFTagShowFrame = FlappSWFTagShowFrame;
-})(this);