MingとはFlashファイルを出力するライブラリで、 最近ではFlex2やMTASCなどに押され気味な気がしないでも無いが、 フォントの埋め込みができるというのと、C/C++から直接ストリームにSWFファイルを出力できるというところがヨサゲだったので、ちょっと触ってみる。
http://www.libming.org/docs/libming/index.html http://www.libming.org/docs/perl/index.html
VCのプロジェクトから0.3.0のDLLを作ろうとしたが、ファイルポインタをDLLに渡すところで落ちる。MinGWでビルドしたものも、VC6からリンクすると同じ問題にはまって解決できなかったので、仕方が無いので静的ライブラリとして作成した。
結局日本語フォントを使うと落ちるのは変わらず。仕方が無いのでVCを諦めて、完全にMinGWでコンパイルすることにしたらあっさり通った。最初からこうすればよかった。
自作プラグイン/flash.inc.php - Pukiwiki-official
#include <stdio.h>
#include "ming.h"
#define FONT_FILE "Sazanami Mincho.fdb"
#define WIDTH 300
#define HEIGHT 200
#define SIZE 40
int main()
{
const char str[] = "こんにちは";
FILE *f;
SWFFont font;
SWFText text;
SWFDisplayItem d;
SWFMovie movie = newSWFMovie();
SWFMovie_setDimension(movie, WIDTH, HEIGHT);
SWFMovie_setBackground(movie, 0x33, 0x44, 0x33);
SWFMovie_setRate(movie, 12);
f = fopen(FONT_FILE, "rb");
if (f == NULL) {
printf("failed to open font file!\n");
return 1;
}
font = loadSWFFontFromFile(f);
text = newSWFText();
SWFText_setFont(text, font);
SWFText_setColor(text, 0xff, 0xff, 0xff, 0xff);
SWFText_setHeight(text, SIZE);
SWFText_setSpacing(text, 0);
SWFText_addUTF8String(text, str, NULL);
d = SWFMovie_add(movie, (SWFCharacter)text);
SWFDisplayItem_move(d, 10, 100);
SWFMovie_save(movie, "ming_test01.swf");
return 0;
}
| |
0.3.0には文字を表示するための三つの関数がある。
で、日本語を使う場合、addUTF8StringかaddWideStringのどっちかを使わなければならない。ところで、UTF-8をWideStringに変換するコンバーターがmingw-0.3.0/src/blocks/utf8.cにあるので、文字列を一文字ずつループするときはUTF-8をを長さが固定のWideStringに変換した方が便利だ。
Flashのオーサリングツール上、シンボルとインスタンスと呼ばれているものは、Mingでは、インスタンスはSWFDisplayItemと呼ばれ、シンボルはSWFMovieClipらしい。SWFMovie_addExportを使ってMovieClipにリンケージ識別子をつけてシンボル化する。SWFShapeとかはダメでSWFMovieClipしかシンボル化できないようだ?
#include <stdio.h>
#include <ming.h>
#define WIDTH 300
#define HEIGHT 200
#define STRINGIZE1(s) #s
#define STRINGIZE(s) STRINGIZE1(s)
int main()
{
SWFMovie movie = newSWFMovie();
SWFShape shape = newSWFShape();
SWFMovieClip mc = newSWFMovieClip();
SWFFill fill;
SWFAction action;
SWFMovie_setDimension(movie, WIDTH, HEIGHT);
SWFMovie_setBackground(movie, 0xff, 0xff, 0xff);
SWFMovie_setRate(movie, 12);
SWFShape_setLineStyle(shape, 100, 0x00, 0x00, 0xff, 0xff);
fill = SWFShape_addSolidFill(shape, 0x00, 0xff, 0xff, 0xff);
SWFShape_setLeftFill(shape, fill);
SWFShape_movePenTo(shape, 0, 0);
SWFShape_drawLineTo(shape, 30, 0);
SWFShape_drawLineTo(shape, 30, 30);
SWFShape_drawLineTo(shape, 0, 30);
SWFShape_drawLineTo(shape, 0, 0);
SWFMovieClip_add(mc, (SWFBlock)shape);
SWFMovieClip_nextFrame(mc);
SWFMovie_addExport(movie, (SWFBlock)mc, "square");
action = compileSWFActionCode(
"for (var i = 0; i < 30; i++) {\n"
" var name = 'square' + i;\n"
" _root.attachMovie('square', name, i+1);\n"
" _root[name]._x = Math.random() * " STRINGIZE(WIDTH) ";\n"
" _root[name]._y = Math.random() * " STRINGIZE(HEIGHT) ";\n"
"}\n"
);
SWFMovie_add(movie, (SWFBlock)action);
SWFMovie_save(movie, "ming_test02.swf");
return 0;
}
traceを埋め込むことはできようようだが、FlashMXから実行してみても出力されないみたいなんですが。
int create_debug_trace (SWFMovie *movie)
{
SWFAction action;
SWFTextField text = newSWFTextField();
SWFBrowserFont font = newSWFBrowserFont("_serif");
SWFTextField_setBounds(text,300,50);
SWFTextField_setFlags(text,
SWFTEXTFIELD_WORDWRAP
| SWFTEXTFIELD_MULTILINE
| SWFTEXTFIELD_AUTOSIZE );
SWFTextField_setFont(text,(SWFBlock)font);
SWFTextField_setVariableName(text, "log");
SWFMovie_add(movie,(SWFBlock)text);
action = compileSWFActionCode(
"var log = '';"
"function dump(x) {\n"
" log += x + '\n';"
" log.scroll = log.maxscroll;\n"
"};\n"
"dump('*** DEBUG DUMP ***');\n"
);
SWFMovie_add(movie, (SWFBlock)action);
return 0;
}
色々言いたいことはあるが、(ありません)とりあえずこんな感じでTextFieldに出力することにした。ActionScriptからdump("log message")する。本当はTextFieldの生成もActionScriptから
createTextField('log', 1, 0, 0, 200, 50);
log.text = "debug message";
みたいにしたかったのだが、どうしてもこれができなかった。原因不明(0.3.0)。同じコードでもFlash MXから問題なく表示できるのでmingのコンパイラのバグのような気がしないでもない。よくわからない。あとでmingの0.4b3を試してみるかもしれない。原因がわかった。原因は
int main()
{
SWFMoive movie = newSWFMoive();
Ming_useSWFVersion(6);
}
のように、Movie生成をSWFのバージョン定義をする前にしていたことだった。ソースを追っかけてて気がついた。まず最初にMing_useSWFVersionでバージョンを決めてから様々なオブジェクトを生成しなければならないようだ。それで結局上のコードは破棄して、こんな風にした。
int create_debug_dump (SWFMovie *movie)
{
SWFAction action;
action = compileSWFActionCode(
"createTextField('log', 0xFFFFFFFF, 0, 0, 300, 100);\n"
"log.type = 'input';\n"
"log.multiline = true;\n"
"log.variable = 'logmsg';\n"
"function dump(x) {\n"
" logmsg += x + '\n';\n"
" logmsg.scroll = logmsg.maxscroll;\n"
"};\n"
"dump('*** DEBUG DUMP ***');\n"
);
SWFMovie_add(movie, (SWFBlock)action);
return 0;
}