PHPのGDで文字を描く

PHPで画像を扱うにはGDが楽なのですが、文字を書こうとすると思ったポイントで描画されません。
おそらくDPIを設定しないとだめなのでしょうが、PHPのリファレンスを探しても見つかりませんでした。
仕方がないのでいろいろ値をとりながら調べてみると、96dpiということが判明。
webではなくアプリケーション向けに72dpiで画像を生成するには以下のような手順となった。
ちなみに画像からはみ出にくいように調整もしてある。

$fontSize = 72;
$dpi = 96;
$margin = $fontSize / 8;
$baseline = $fontSize + $margin;
$size = $fontSize + $margin * 2;

$image = imagecreatetruecolor( $size, $size );

imageantialias( $image, true );
imagealphablending( $image, false );
imageSaveAlpha( $image, true );

$fillcolor = imagecolorallocatealpha( $image, 0, 0, 0, 127 );
imagefill( $image, 0, 0, $fillcolor );

$black = imagecolorallocate( $image, 0, 0, 0 );

$text = mb_convert_encoding( "あ", 'utf8' );
$font = 'xxxx.otf'; // 適当に置き換えて
imagettftext( $image, $fontSize/$dpi*$fontSize, 0, 0, $baseline, $black, $font, $text );

imagepng( $image, 'output.png', 9 );
imagedestroy( $image );

印刷も考えるとEPSで描いてから画像にするのが一番確実だけど、imagemagic(正確にはghostscript)を経由するのも面倒だしこうなった。

PerlでCGI::Sessionがcoreserverではうまく動かない

Perlでセッション管理の話です。
PHPだとセッションはsession_start()と$_SESSIONで楽に扱えますが、Perlではたまに苦しみます。
さて、今回はローカルのVistaのActivePerlでは正常に動くスクリプトをcoreserverにアップすると挙動が違うのです。
クッキーは更新されているのに、セッションファイルが更新されません。
クッキーがない場合はセッションファイルを作成しているのですが、それ以降の更新が行えません。
また、クッキーだけ残してセッションファイルを削除するとセッションファイルの作成すらしてくれません。
極めつけはアクセスすると1分ごとにセッションファイルが量産されていくのです。
もちろんセッションの有効期限はそんなに短くありません。
どうしてかな~と、いじっているとどうやらリダイレクトが悪さをしているようです。
たとえばログイン処理でログインに成功するとログイン後のトップページへリダイレクトするわけですが、そうすると正常にセッションが更新されません。
リダイレクトをやめて一度ページを表示するなど出力をクローズしておけば期待した動きをしてくれます。

でも、CGI::redirectとCGI::Sessionの相性が悪いという話は聞いたことがありません。自分の開発環境では一度もそういう現象には出くわしたことがありません。
環境が違う点といえば・・・cgiwarpぐらいかな。「CGI::Session coreserver」とかでぐぐっても同じ現象の記事が見つからないので自分の書き方が悪いのかな~

UTF-8とUnicode

文字を扱うときは普段からUTF-8を使用します。Shift_JISやeucはめったに使いません。
さて、UTF-8はUnicodeなのですが、表記の方法で躓きました。
PerlやPHPなどのスクリプトで扱う場合は、たとえば「あ」なら「\xe3\x81\x82」と記述するのですが、「U+xxxx」という表記が必要な自体にでくわしました。
Flashで文字のコードを取得使用とするとこの表記でしか取得できないようで、文字を管理するにはコードで管理したほうが楽なのでこのコードで扱うことに島した。
さてここで問題です。「U+xxxx」の表記ってコレいったいナニ?といろいろ調べていくと、「UCS2」というコード体系だということが判明。Perでこの表記を取得するには以下のとおり。

my $string = 'あ';
&from_to( $string, 'utf8', 'ucs2' );
print unpack('H*', $string );
# 3042


JcodeよりもEncodeのほうがいいらしい?この当たりは試してないのでどちらとも。ただ、日本語に依存するものがないときは基本的にEncodeを使ったほうが安全という話。今回はUTF-8からUCS2なので、下手に日本語環境を考えるとコードが化けたりしかねない。
これで、文字を管理することができるようになりました。
UCS2って今まで気にしなかったコード名です。他にもUCS4とかあるようです。

Flashへのフォント埋め込みは無法地帯?

Flashはいろいろできてとても便利です。
画像や図形、それに肝心の文字。
さて、ここで文字を表示するためのフォントのお話です。

Adobeがライセンスを持っているフォント(FlashやAdobeReaderにバンドルされているもの)は自由に埋め込むことができます。
しかし、Windowsについているフォントや、オフィス系ソフトを入れると入るフォントはライセンス上そのアプリケーションとセットでなければなりません。
そして、そのフォントは商用利用できないことがほとんどです。
つまり、「このフォントを使って何がしを注文できます」と商売はできないということです。

商用フォントであればこれらの制限はないものが多いですが、Flahsへの埋め込みは別です。
Flashへの埋め込みは個人であってもNGなものがほとんどのようです。
静止画テキストであればその文字限定ということで画像と同じ扱いなのか、特に問題はないものの、ユーザが個別に入力できる文字にそのフォントで表示できるようなダイナミックテキストになるとほとんどアウトです。
つまり、フォント情報をフォントとして扱える状態で埋め込むことは配布と同じことになり、ライセンス違反となります。
フォント自体に埋め込めない機能があればいいのですが、パスとして引っ張り出せば回避されますからね。

さて、web上で名刺などをデザインできるサイトがちらほらありますが、アクセスしたパソコンにあるフォントしか表示できなかったり、フォントの都合で出来上がりは見た目と違うと断ってあるサイトはさておき、「パソコンになければサーバからダウンロードします」と露骨にライセンス違反と思われる行為を宣言しているサイトを見つけました。
おそらくフォントを埋め込んだswfを個別に読み込むのでしょう。システムとしては理に適っていますがライセンス的には・・・
ここまで露骨だとある意味ほほえましいですが、フォントベンダーが放置している理由も良くわかりません。相手にするほどでもないというのか、正規の配布ライセンスを持ているのか(フォントサーバ扱いのライセンスになるのでン百万ぐらいするらしい)謎です。

ちなみに埋め込みに関するライセンスを回避するには、フォントとして再利用できない形で表示するのであれば問題ないようです。つまり、フォントデータから自由に「文字を表示」できる状態を用意することが問題で、文字ではない画像で表示するのであればフォントを再利用できない状態であると判断されるとのことです。だって、そうじゃないと校正をFAXやメールに添付して送ることもライセンス違反になっちゃいますからね。

何がいいたいかというと、フォントを利用した何かを転送することが問題なのではなく、フォントの情報そのものが転送されることに問題があるということです。結論として画像でやれと。

失敗を認めた日本でのセカンドライフ

今日のワールドビジネスサテライト(以下、WBS)で仮想空間の特集をやってましたが、いまごろになってやっとセカンドライフの失敗を認めましたね。
電通(博報堂もだったか?)のしかけたこのビジネスは、ネットをしらないビジネスユーザには受けたものの、日本のカルチャーであるゲームに興味を持っていた者には既知のサービスでしかも空振りで失敗に終わっていたことは誰もがしっていた。当時のアスキーの記事には失笑したものだが。
そして、アメーバのアバタサービスが成功したかのような記事があったけれど、「もともとのユーザが多いだけでアバタサービスが新しいわけではない」ことをきちんと取り上げるべきだ。
アバタサービスなんてはるか昔からあるわけだし、個人的にちょっとやっていたけれど、知る人ぞ知る動物のアバタサービス「gopets」が突然終わったこともはるか昔。
正直、今頃アバタを取り上げるなんて、あの映画とタイアップしているのか。WBSも広告の言いなりに落ちたわけではあるまい?
最近のWBSには、ところどころほころびが生じている。取材の能力が落ちているとしか言いようがない。ガイアやルビコンのほうがまだましに思えることもある。
昔のWBSなら全方面から取材をこなし、一方ではこうだが他方ではこうだとどこから見ても納得できる内容だった。
だが最近はどうだ、片方からしかも狭い見地からしか取材を行っていないものが増えている。
失敗談をきちんと取り上げるトレたまが最後の砦だ。

Adobe Flash CS4の不可解な挙動

いろいろいじくっていると、パブリッシュ時にエラーを吐いてくれます。
もちろん、構文に問題があるからなのですが。
で、出くわしたこんなエラー
「ReferenceError: Error #1065: 変数 ComponentShim は定義されていません。」
グーグル先生に尋ねても知らん振り。
仕方がないので何千行もあるソースをコメントアウトしたりtraceの場所を増やしてみても変えたりしてもこのメッセージ1行のみ。
つまりコンパイル時のエラーらしい。

ならコンパイルエラーと書け。
構文エラーじゃないじゃん?

いろいろ弄っていると、いつの間にかシンボルの1つが画面から消えているのに気がついた。
オブジェクトとしては存在するんだけれど、表示されない。
ボタンでは表示できるがムービークリップでは表示できない。
一度ファイルを閉じて開きなおしてみるが、なぜか保存時のものに回復されず、最新の状態が復帰してしまう。
これはまさに顔面蒼白という状態である。

もうどうにでもなれと、アプリケーションを落として再起動してみると・・・
なんてことはない。
正常に機能していた。

そういえば操作を戻す作業をしてからおかしくなったような・・・?
どうやらFlashのガベージコレクションには欠陥があるようだ。
どういう手順で発症するのかわからないが、何らかの条件で最新の状態のみが優先されリセットされていないらしい。
それで戻る操作をすると整合性が取れなくなり、コンパイラのどっかで構文エラーが発生してパブリッシュに失敗するようだ。
しかし検索してもヒットしないエラーにお目にかかれるとは。

PC用にスピーカを買ってみた

いままで何十年も前、もとい十何年も前に買ったスピーカをだましだまし使ってました。
見た目もぼろく、音も負荷がかかるとコーンがバリバリと鳴るどうしようもない代物でした。
ちゃんと聞くときにはヘッドフォンを使っていたわけだけど、イヤーパッドが劣化してきて音が片方だけ漏れてバランスが悪くなってました。1万5千のヘッドフォンだけど2年近くも使うとエージングが聞きすぎてそろそろ音がなまってもきているし。
仕方がないので、何かいいものはないかと探していたわけだけど、ケーブルのとり回しに悩んでいていいものが見当たらなかった。
店頭でデモ機を聞き比べても安かろう悪かろうな物ばっかりで。

結局、あえてデモ機を置いてないものを選んでみた。まぁ、こういうひねくれ感が自分らしさというかなんと言うか。
で、持ち帰ってびっくり。
しっかりと鳴らしてくれる。
少々重量もあるので低音もしっかりと。
しっかり過ぎて机まで鳴ってしまうので、ゴム板をかませて床鳴りを解消。
音量がかなりでかいので、PCのボリュームを絞ってもそこそこの音量になるが、しっかりと解像度がある。
ケーブルが硬めだが、よく見ればしっかりシールドしているのでよしとする。
エンクロージャが球体に近いので、指向性が若干ぼやけるが、気持ち外向きにすると音像が安定する。
Windowsはもちろん、LinuxでもOS関係なく鳴らせる。
サラウンドのソフトが付いてるけれど、全然興味がないので封も切らずにそのまんま。
てことで、久しぶりに買ってよかったと思える代物でした。

ビックカメラで駆ったけど1980円もした。
アマゾンなら400円ぐらいも安かったのか・・・orz=3

ActionScript3のthisに悶え苦しんだ

Javascriptがそれなりに使いこなせれば、ActionScript2も特に問題がなかったわけですが、今頃になっていじり始めたActionScript3(以下AS3)で悶え苦しみました。
イベントやシンボルの扱いが変わったことも、調べさえすれば特に問題にならず、着実に開発は進んでいたのですが・・・
さて、行き詰ったのが「this」の扱い。
いままでは、とにかく「オレオレ!」でよかったので、イベントに関数を宛がってやれば、関数からオブジェクトをごにょるのはとても簡単でした。
が、AS3ではなぜか常にグローバル?なオブジェクト(実在してないっぽいのだが)になってしまう。

for( var i = 0; i < 10; i ++ ){
    var mc:Object = new mcHoge();
    mc.name = 'hoge' + i;
    mc.addEventListener(
        MouseEvent.MOUSE_OVER,
        editPointAnchorMouseOverHandler
    );
    function editPointAnchorMouseOverHandler(evt:MouseEvent):void{
        trace(this.name);
    }
    obj.addChild( mc );
}


いままではこんな感じで(AS3用にイベントを書いてあるよ)thisを追跡できたのに、AS3ではできない。
マウスが乗っかるとundefinedとなる。
ちなみにobjはStageとかで読み替えてみて。
いろいろ調べてもどうでもいいウンチク(もちろん大事なのだが)ばかりで、AS3の解説本の著者がグダグダ語っていたりするがよく見ればAdobeの例文のままで悲しい思いをするだけで実例がない。「ActionScript3 this global」とかでググってもだめっぽい。
本当はクラスにすればいいんだろうけど、別ファイルにしなければならないらしい?
同じファイルの中でパッケージ宣言できないのは厳しい。
使いまわさなくても都合上クラスが便利なこともある(性格にはクラスであるべきことのほうが多いのだが)のにファイル分けなきゃいけないの?
と、それたところで軌道修正。

結局のところ、別に関数を用意して、その中でオブジェクトを作ってやって戻り値もオブジェクトにすれば、擬似的にパッケージ化できることが判明。OOPを実装したはずのAS3のコンパイラが関数をどう扱っているのかなぞである。
結局はこうなった。

for( var i = 0; i < 10; i ++ ){
    var mc:Object = fuga( i );
    obj.addChild( mc );
}
function fuga( i:int ):Object {
    var mc:Object = new mcHoge();
    mc.name = 'hoge' + i;
    mc.addEventListener(
        MouseEvent.MOUSE_OVER,
        editPointAnchorMouseOverHandler
    );
    function editPointAnchorMouseOverHandler(evt:MouseEvent):void{
        trace(this.name);
    }
    return mc;
}


実質、関数をオブジェクトと定義しているわけだが、関数は関数しか宣言できないのでオブジェクト・・・あれ?
もしかしてこう書けばいい?
var mc:Object = function( i:int ):Object{ var mc:Object = new mcHoge(); [省略]; return mc; }
とすると強制型変換に失敗したと怒られた。
理屈ではこれでいいはずなのに、なんでだろ?
まぁ、初めたばかりだし、AS3の書き方に慣れてからまた考えよう。

Adobeの体験版をインストールしたらひどい目にあった

IllustratorのデザインをHTMLに起こす作業が必要になって、Dreamweaverなら一発で変換できるかもしれないと入れてみた。
結論からするとできなかったわけだが、後で気がついたことがいろいろと。

まずファイルの関連付けが強制的に変更される。
テキスト関係の関連付けがごっそりと入れ替わってひどい目にあった。
それに、コンテキストメニューにAdobe Driveというよくわからないメニューが追加されて非常にうっとうしい。しかも表示しない設定がどこにもない。

Adobeの技術にはいろいろとお世話になっているけれど、こういう所はまったくもって共感できない。
レジストリいじるしかないのかなぁ。はぁ。

能勢名物くれべのでっちようかん

突然ですが食べ物のお話です。
年末年始は実家に帰省してました。
そのあいだに自宅鯖がダウンしたり波乱のあった年越しでしたが。

さて、実家は猪名川、猪名川といえば能勢(むちゃくちゃや)でウマいものといえば「くれべ」の「でっちようかん」
能勢で買おうと思ってもちょっとっ遠いので(能勢は近いがくれべが遠い)ので、地元で探したものの店においてない。
しかたがないので、いつもの様に清和台の消防署前にあるショッピングモールで手に入れた。

やはりウマい。
本当にウマいと思える食べ物は
この能勢(大阪)の「くれべ」の「でっちようかん」
そして鳴門(徳島)の「そば処 橋本」のそば

グルメではないから食べ歩きなどはしないが、また食べたいと思う食べ物は30年以上生きててもまだこの2つしかない。
ちなみに、行列のできる店で何度か食べたことがあるが、待たされてやっと食べられたからウマいと勘違いしているだろうだけで、はっきりいってウマい店は一つもない。まぁ、マズくはないレベルである。