flash

2008年05月01日

(速報)SWF SpecificationがOpenになりました

はてなブックマークに登録

以前、「SWFファイルフォーマットとライセンス 」で、SWFのファイルフォーマット仕様書の利用許諾に、SWFファイルを読み込むプログラムを作成してはいけないと書かれていることを紹介しました。

今日、Adobeから「Adobe and Industry Leaders Establish Open Screen Project」というプレスリリースがあり、その中に以下の一文がありました。

- Removing restrictions on use of the SWF and FLV/F4V specifications

ということで、SWFの仕様書を制限無しに読むことが可能になったようです。

他にも、Flash Playerの移植レイヤが公開され、Flash Playerを移植してもライセンス料が取られなくなる等が発表されているようです。私もまだ流し読みしかしていないのですが、とても大きなニュースなのでとりいそぎ紹介させていただきました。

追記:
SWFとFLVの仕様書がこちらからダウンロードできるようになっています。
Open Screen Project / For developers


@methane
klab_gijutsu2 at 15:37|この記事のURLComments(0)TrackBack(2)
2008年03月07日

Flex SDKのswfutilsをハックしてみる

はてなブックマークに登録

Flex SDKのswfutilsでswfとXMLの相互変換を試してみる で、swfxc.jarを作成し、SWFXからSWFへの変換を試してみたところ、上手くいきませんでした。 swfxc.jarのMain-ClassであるSwfxParserクラスを中心にFlex SDKのソースを読んで、swfxcが失敗する理由を探ってみました。

eclipseの準備

まず、eclipseの準備をします。準備の手順は %FLEX_SDK%/development/eclipse/readme.txt に書いてあります。importするプロジェクトを選択する画面で、flex-swfutilsを選択してください。他にcompiler等を選ぶことができます。

SwfxParser.javaの概観

SwfxParser#main()は、SwfxParserクラスのインスタンスを生成してparse()メソッドを呼んでいます。SwfxParser#parse()は、SAXParserのインスタンスを生成して、自身をイベントハンドラとしてSAXParser#parse()を呼んでいます。SwfxParserは、DefaultHandlerクラスのstartElement(), endElement(), endDocument()メソッドをオーバーライドして、SAXのイベントを処理しています。

startElement()は以下のようになっており、XMLエレメントの名前と同じ名前で、引数にAttributesクラスを取るメソッドを探して実行します。endElement()も、引数が空のメソッドを探す以外はstartElement()と同じです。例えば、<DefineSprite>タグを見つけるとSwfxParser#DefineSprite(Attributes attributes)が実行され、</DefineSprite>を見つけるとSwfxParser#DefineSprite()が実行されることになります。

    public void startElement(String uri, String localName,
                             String qName, Attributes attributes)
            throws SAXException
    {
        try
        {
            Method method = getClass().getMethod(qName, new Class[]{Attributes.class});
            method.invoke(this, new Object[]{attributes});
        }
        catch (NoSuchMethodException e)
        {
            warning(new SAXParseException("no start handler for " + qName, locator));
        }

これらのイベントハンドラは、基本的に、そのタグに対応するオブジェクトを生成してtagHandlerに渡します。SwfxParser#mainはtagHandlerにTagEncoderというswfバイナリを出力するクラスのオブジェクトを登録しているので、swfファイルが出力される事になります。

他に重要な部分に、SwfxParserのメンバ変数のdictとstackがあります。Define系タグを処理するときにdictにidとオブジェクトを記憶させておいて、後にPlaceObject等を処理するときにid経由で参照先を探すのに利用します。stackは、DefineShapeとlineやcurveのようにタグとデータ構造がツリー状になっているときに使います。親タグの開始時にstack.push()し、子データを処理するときにstack.peek()で参照した親にデータを登録し、親タグの終了時にstack.pop()します。

klab.swfxをswfに変換させてみる

と、SwfxParserが理解できたところで、何でklab.swfxからklab.swfが生成できなかったかを調べてみます。 例外ハンドラを幾つか追加して調べてみたところ、dictからid=3のオブジェクトを探して見つからないために、そこで終了していました。klab.swfxのなかでid=3のオブジェクトを探したところ、DefineTextでした。SwfxParser#DefineText()メソッドが無いために、dictにid=3のDefineTextオブジェクトが登録されておらず、エラーになっています。DefineTextの部分のswfxは次のようになっています。

  <DefineText id='3' bounds='(106,414),(2570,1654)' matrix='t0,0'>
    <textRecord  font='Verdana' height='1620' yOffset='1620' color='#00000000'>
      1+1152 
    </textRecord>
  </DefineText>

DefineText以外にも大量にタグのハンドラが足りてない気がするのは無視して、とりあえずこのswfxのparseに挑戦します。 まず、<textRecord>に対応するSwfxParser#textRecord()を作ります。楽勝・・・と思いきや、font='Verdana'で引っかかりました。フォントは、DefineTextの前にDefineFont2タグで定義されており、id='2'が割り当てられています。idが一意なのに対してフォント名は一意ではないので、この部分はフォント名ではなくidを参照するべきです。とりあえず、その場しのぎでごまかしたものが次のコードになります。

    public void textRecord(Attributes attributes) throws SAXParseException
    {
    	TextRecord tr = new TextRecord();
    	String fontname = getAttribute(attributes, "font"); 
    	tr.setFont(dict.getFontFace(fontname, true, false)); // set dummy value to bold and italic.
    	tr.setHeight(parseInt(getAttribute(attributes, "height")));
    	tr.setY(parseInt(getAttribute(attributes, "yOffset")));
    	tr.setColor(parseColor(getAttribute(attributes, "color")));

    	DefineText dt = (DefineText)stack.peek();
    	dt.records.add(tr);
    }
    
    public void textRecord()
    {
    }

次はSwfxParser#DefineText()です。これは特に引っかかることなく次のように実装しました。

    public void DefineText(Attributes attributes) throws SAXException
    {
    	DefineText dt = new DefineText(stagDefineText);
    	int id = parseInt(getAttribute(attributes, "id"));

    	dt.bounds = parseRect(getAttribute(attributes, "bounds"));
    	dt.matrix = parseMatrix(getAttribute(attributes, "matrix"));

    	createCharacter(id, dt);
    	stack.push(dt);
    }
    
    public void DefineText()
    {
    	DefineText dt = (DefineText)stack.pop();
    	tagHandler.defineText(dt);
    }

これで動くか?と思ったら、まだダメでした。引っかかったのはparseRect()です。swfxを生成するときは、Rect#toString()を利用していて、swfxを読み込むときにはSwfxParser#parseRect()を利用しているのですが、Rect#toString()が状況によって2種類のフォーマットを使い分けて出力していて、SwfxParser#parseRect()はその片方にしか対応していないために、parseに失敗していました。

SwfxParser#parseRect()をRect#toString()にあわせて拡張したらまた先に進めるハズです。が、ここでキレました。そもそも、Rect#toString()があまりイケてません。しかも、rect.equals(parseRect(rect.toString())) == trueを満たすようなparseRect()がSwfxParserのメソッドというのもどうかと思います。SwfxParser#parseRect()じゃなくてRect#fromString()であるべきでは無いでしょうか?せめて同じpackageにあるべきですよね?swfxのフォーマットも含めていろいろ修正したいです。

でも、Flex SDK プロジェクトと離れたところで頑張って修正するのももったいないです。ということで、Flex SDKを使ってSWF⇔XML相互変換は一旦あきらめます。これからは、swf弄りは今までどおりswfmillを使いつつ、Flex SDKに対してはプロジェクトのforumで議論してパッチ作成という形で参加して行こうと考えています。

結局こんなオチになってしまってすみません。Flex SDKプロジェクトでswfutils.jarへのAdobe外部からの貢献が多くなれば、AdobeもSWF File Format SpecificationのEULA(swfutils.jarの修正すら不可能)を変更してくれる気になるかもしれないので、swf関係者の皆さんも一緒にFlex SDKをハックしてみましょう。


@methane
klab_gijutsu2 at 14:55|この記事のURLComments(0)TrackBack(0)
2008年03月06日

Flex SDKのswfutilsでswfとXMLの相互変換を試してみる

はてなブックマークに登録

SWFファイルフォーマットとライセンス(その2) で、swfutils.jarがSWFとSWFXというXMLフォーマットで相互変換できそうだとお伝えしましたが、その後相互変換に挑戦してみた経過をまとめます。

Flex SDKの用意

svn trunkのFlex SDKを用意します。(多分、sdk/branches/3.0.x を利用してもこの記事で行っている範囲では同じだと思います)

今回の例では、Windows XPで、C:\usr\flexsdk にFlex SDKをインストールしますが、皆さんの好みで適当に読み替えてください。SubversionとJDKとantはインストールされて環境変数(%PATH%, %JAVA_HOME%, %ANT_HOME%等)は適当に設定されているものとします。

C:\>cd usr\
C:\usr>svn co http://opensource.adobe.com/svn/opensource/flex/sdk/trunk flexsdk
C:\usr>cd flexsdk
C:\usr\flexsdk>ant
C:\usr\flexsdk>set FLEX_SDK=C:\usr\flexsdk
C:\usr\flexsdk>set PATH=%FLEX_SDK%\bin;%PATH%

SWFからSWFXへの変換

この段階で、SWFからSWFXへの変換はできます。ためしに、弊社のTOPページで使われているFlashを解析してみます。http://www.klab.org/images/main.swf をダウンロードして、C:\work ディレクトリ内に保存してください。

C:\usr\flexsdk>cd C:\work
C:\work>swfdump -out klab.swfx main.swf

これで、klab.swfxという名前のXMLファイルができました。

ちなみに、ここでは%FLEX_SDK%/bin/swfdump.exeという実行ファイルを利用しましたが、同じディレクトリにシェルスクリプト版のswfdumpも用意されています。シェルスクリプトのソースを読めば、swfdumpで実際に実行されるのが、java -jar %FLEX_SDK%/lib/swfdump.jar であることが判ります。

swfxc.jarとswfxc.batの作成

今度はSWFXからSWFへの変換をしたいのですが、こちら側のコマンドはありません。ソースコードを読むと、SwfxParser.javaを使えばできそうなので、SWFXからSWFへの変換用のjarを作ってみます。

jarの名前は、SWFX Compilerの略で、swfxc.jarにしました。%FLEX_SDK%/modules/swfutils/build.xmlを修正して、swfxc.jarを作成するようにします。次のpatchを当ててから、もう一度antを実行すれば、%FLEX_SDK%/lib/swfxc.jarができあがります。

Index: build.xml
===================================================================
--- build.xml   (revision 751)
+++ build.xml   (working copy)
@@ -60,13 +60,24 @@
                 <attribute name="Class-Path" value="asc.jar swfutils.jar"/>
             </manifest>
         </jar>
-
+        <echo message="Building lib/swfxc.jar"/>
+        <jar file="${lib.dir}/swfxc.jar" basedir="${module.src}" includes="flash/swf/tools/swfx.xsd">
+            <manifest>
+                <attribute name="Sealed" value="${manifest.sealed}"/>
+                <attribute name="Implementation-Title" value="${manifest.Implementation-Title} - SWFx Compiler"/>
+                <attribute name="Implementation-Version" value="${manifest.Implementation-Version}.${build.number}"/>
+                <attribute name="Implementation-Vendor" value="${manifest.Implementation-Vendor}"/>
+                <attribute name="Main-Class" value="flash.swf.tools.SwfxParser"/>
+                <attribute name="Class-Path" value="asc.jar swfutils.jar"/>
+            </manifest>
+        </jar>
     </target>

     <target name="clean" description="clean">
         <delete failonerror="false" includeEmptyDirs="true">
             <fileset file="${lib.dir}/swfutils.jar"/>
             <fileset file="${lib.dir}/swfdump.jar"/>
+            <fileset file="${lib.dir}/swfxc.jar"/>
             <fileset dir="${module.classes}">
                 <include name="**/*"/>
             </fileset>

このjarを直接叩いても良いのですが、面倒なので、batファイルを作成する事にします。次のようなbatファイルを、%FLEX_SDK%/bin/swfxc.batという名前で作成してください。

java -jar %FLEX_SDK%\lib\swfxc.jar -aspath . %1 %2 %3 %4 %5 %6 %7 %8 %9

swfxc.batができたので、ためしに先ほど作成したklab.swfxをswfに戻してみます。swfxcは引数無しで実行してもusageを出したりしてくれないのですが、 SwfxParser.java を読むと、入力ファイル名を引数で指定し、その拡張子を.swfに変更したものを出力することがわかります。ということで、実行してみましょう。

C:\work>swfxc klab.swfx

・・・klab.swfができません。失敗です。

(続く)


@methane
klab_gijutsu2 at 17:52|この記事のURLComments(0)TrackBack(0)
2008年03月03日

SWFファイルフォーマットとライセンス(その2)

はてなブックマークに登録

少し前の話になりますが、とうとうFlex 3 SDKとAIR SDKが公開されました。既にお使いの方も多いかと思います。 さて、以前「SWFファイルフォーマットとライセンス」という記事を書いたのですが、Flex 3 SDKが公開されてどうなったかの続報をお伝えします。

まず、大きな変更として、オープンソースな部分が増えました。Flex 2 SDKのときはFlex FrameworkのみがMPL(Mozilla Public License)だったのですが、Flex 3 SDKになって、コンパイラ、デバッガ、SWFライブラリ等もMPLになりました。Adobe Open SourceFlex SDK プロジェクト があるので、詳しくはそちらをご覧下さい。「プロジェクトページなんてどうでも良い、早くソースを見せろ」という方は、Flex SDK のsvnリポジトリが <http://opensource.adobe.com/svn/opensource/flex/sdk/> にあるので、svn coして下さい。

で、このリポジトリを探してみたのですが、残念ながらSWF Fileformat Specificationは含まれていませんでした。その代わりswfutils.jarが想像以上にすごい事が判りました。勝手にswfを生成するためのライブラリだと思っていたのですが、swfを読み込むこともできるのです。

flexsdkのbin/ディレクトリの中には、swfdumpという、swfファイルをswfxというXMLフォーマットでダンプするツールが含まれています。この実体は flash.swf.tools.SwfPrinter#main()になります。なんか、swfのリバースエンジニアリング大歓迎っていう感じのツールですね(笑)

flexsdkのbin/ディレクトリに含まれてはいないのですが、swfxからswfへの変換もswfutils.jarに含まれています。flash.swf.tools.SwfParser#main()が実体なので、

$ java -cp $FLEX_HOME/lib/swfutils.jar flash.swf.tools.SwfxParser test.swfx
とすると実行することができます。が、実行してみようとしてみたところ、swfx.xsdというリソースの取得に失敗して止まってしまいます。swfx.xsd自体はflexsdk/modules/swfutils/src/java/flash/swf/tools/swfx.xsd にあるので、これからJavaとJarとAntを勉強してSwfxParserを使えるjarの作成に挑戦してみます。

Flex SDKの中には、コンパイラやディスアセンブラ等色々含まれていますので、swf関係者(?)な方はぜひ覗いて見てください


@methane
klab_gijutsu2 at 19:44|この記事のURLComments(0)TrackBack(0)
2008年01月24日

swfmillでFlash Lite 1のswfを扱えるようにしてみた

はてなブックマークに登録

Flashに関連するオープンソースなツールのひとつに、swfmillがあります。swfmillは、swfファイルを解析してxmlファイルに変換したり、逆にxmlからswfファイルを生成することができるツールです。swfmillの使い方についてはいろいろなところで紹介されているので、ここではFlash Lite 1.xのswfファイルをswfmillで扱うときの問題点について紹介したいと思います。

続きを読む
klab_gijutsu2 at 19:12|この記事のURLComments(15)TrackBack(0)
2008年01月10日

SWFファイルフォーマットとライセンス

はてなブックマークに登録

今回は、SWFを弄るときに必ず理解しておかないといけない、ライセンスに関する注意点をまとめてみます。

まず、公式なSWFファイルフォーマットの資料として、Adobe Systems Inc. (以降、Adobe) が"SWF and FLV File Format Specification" (以降、公式仕様)を公開されています。 (http://www.adobe.com/licensing/developer/)

この公式仕様の利用許諾が "SWF and FLV File Format Specification License Agreement" になるのですが、この中に次のような文があります。

3. Restrictions
a. You may not use the Specification in any way to create or develop a runtime, client, player, executable or other program that reads or renders SWF files.
続きを読む
klab_gijutsu2 at 13:54|この記事のURLComments(4)TrackBack(0)
2007年12月28日

ActionScript Debugger を公開します

はてなブックマークに登録

昨日のConverterにつづいて、Debuggerの方も公開します。お試し版のWebアプリも用意しましたので、ぜひ触ってみてください。

続きを読む
klab_gijutsu2 at 11:31|この記事のURLComments(0)TrackBack(0)
2007年12月27日

ActionScript Converter '3to2' を公開します

はてなブックマークに登録

少し遅くなってしまいましたが、去る 11 月 27 日に開催された Tech-mobi2007 でお話させていただいた ActionScript Converter "3to2 (サントゥニー)" の講演資料とソースコードを公開させていただきます。

続きを読む
klab_gijutsu2 at 15:22|この記事のURLComments(0)TrackBack(0)
Blog内検索
Archives
このブログについて
DSASとは、KLab が構築し運用しているコンテンツサービス用のLinuxベースのインフラです。現在5ヶ所のデータセンタにて構築し、運用していますが、我々はDSASをより使いやすく、より安全に、そしてより省力で運用できることを目指して、日々改良に勤しんでいます。
このブログでは、そんな DSAS で使っている技術の紹介や、実験してみた結果の報告、トラブルに巻き込まれた時の経験談など、広く深く、色々な話題を織りまぜて紹介していきたいと思います。
最新コメント