Sep 12, 2009
Perl/Tk で縦書きビューワーを作ろう (4)
悪戦苦闘の末、ページを先へ進む機能だけでなく後へ戻る機能も加わり、読んでいるページが何ページ目なのかも表示させるようにしてあります。とりあえずは UTF-8入出力専用の縦書きビューワーとして基本的な機能はなんとか実現させたような気がします。そういう訳で、相変わらず縦書きグリフの表示は出来ませんけども、無理矢理、ぽちたて 0.0.1 としてリリースしちゃいました。
既に数々の素敵で高機能な縦書きビューワーがある中、一応 Windows で使えない事も無いとはいえ、扱える入出力日本語文字コードが UTF-8 だけなので事実上 Linux/UNIX上で使う事しか想定していないぽちたて。需要は世界中にぽち一人しかしれませんが、今後もちまちま作り続けようと思っています。…それでも使ってみてくれた奇特な方がいらっしゃいましたら、バグレポートをメールなりコメントなりで絶賛大募集中です。
- ぽちたて 0.0.1 を動かすのに必要ないろいろ
- Perl
- Perl/Tk
- Lingua::JA::Fold
- 機能
- UTF-8 のテキストファイルを UTF-8 で縦書き表示します。
- 注意点
- 相変わらず縦書きグリフが表示出来ません。
- 相変わらずとんでもなく起動が遅いですがフリーズと間違えないで下さい。
- Linux上の Perl 5.10.0 でしか動作を確認していません。
- 使い方
- $ pochitate001.pl sampletext.txt
というわけでぽち*ぷ〜ちに公開用ページ Perl/Tk で縦書きビューワー『ぽちたて』を作ってみたを作りました。
しかし、なんとか Linux/UNIX上で TrueTypeフォントの縦書きグリフを表示する良い方法が無いものでしょうか?
Sep 10, 2009
Perl/Tk で縦書きビューワーを作ろう (3)
今日は余裕が無いのでやっと最低限の機能で動き出したコードだけ…。
- ぽちたてを動かすのに必要ないろいろ
- Perl (多分、5.8.8以上)
- Perl/Tk
- Lingua::JA::Fold
- 機能
- UTF-8 のテキストファイルを UTF-8 で縦書き表示します。
- 注意点
- 縦書きグリフが表示出来ません。
- 前のページへ戻る機能はありません。
- 今読んでるのが何ページ目なのか表示しません。
- とんでもなく起動が遅いですがフリーズと間違えないで下さい。
- Perl と CPAN を使える環境なら Windows でも動作するとは思いますけども、Linux の Perl5.10.0 でしか動作を確認していません。
pochitat20090910.pl
#!/usr/bin/perl
## 使い方 ###########################
# #
# $ pochitate20090910.pl sample.txt #
# #
#####################################
use strict;
use warnings;
use utf8;
use Tk;
use Lingua::JA::Fold qw(fold);
# 設定
my $font_family = 'IPA明朝';
my $font_size = 11;
my $font_style = 'normal';
my $font_color = '#000000';
my $background_color = '#e0ffff';
my $text_width = 523;
my $text_height = 28;
my $line_horizontal_margin = 26;
my $chr_vertical_margin = 15;
my $fold_length = 42; # 文庫本1ページの標準的な一行の文字数
my $page_lines = 18; # 文庫本1ページの標準的な行数
# メインウィンドウの準備
my $top = MainWindow->new( -title => 'ぽちたて' );
# フレームの準備
my $frame_top = $top->Frame();
my $frame_bottom = $top->Frame();
# 主画面となるキャンバスウィジェットの配置
$frame_top = $top->Canvas( width => 603, height => 671 );
$frame_top->create( 'rectangle', 1, 1, 602, 670, -fill => $background_color );
# ページ移動ボタンの配置(「<」で次ページ、「×」で終了)
my @chr_ids;
$frame_bottom->Button( -text => '<', -command => [ \&write_tategaki, \@chr_ids ],
-font => [ $font_family, 4, $font_style ] )->pack( -side => 'left' );
$frame_bottom->Button( -text => '×', -command => \&exit,
-font => [ $font_family, 4, $font_style ] )->pack( -side => 'left' );
# フレーム内の配置
$frame_top->pack();
$frame_bottom->pack( -side => 'right' );
# テキストファイルからの読み込みと折り返し処理
my $strs;
while(<>){
utf8::decode($_);
$strs = $strs . fold( 'text' => $_, 'length' => $fold_length,
'mode' => 'traditional' );
}
open my $fh, "<", \$strs or die "Couldn't open for reading: $!\n";
&write_tategaki(\@chr_ids);
MainLoop();
sub write_tategaki{
my $chr_ids = shift;
my $lines;
my $line_width = $text_width;
unless (eof $fh){
for my $c_id (@$chr_ids){
$frame_top->delete( $c_id );
}
@$chr_ids = ();
}
while(<$fh>){
utf8::decode($_);
my $chr_height = $text_height;
my @string = split(//, $_);
for my $chr (@string){
$frame_top->create( 'text', $line_width, $chr_height,
-fill => $font_color, -text => $chr,
-font => [ $font_family, $font_size, $font_style ] );
push @$chr_ids, $id;
$chr_height += $chr_vertical_margin;
}
$line_width -= $line_horizontal_margin;
$lines++;
last if ($lines > $page_lines - 1);
}
}
Sep 09, 2009
Perl/Tk で縦書きビューワーを作ろう (2)
今日も今日とてぽちたて作りです。
今日は自動折り返し機能や指定した行数を越えて縦書き描画しない機能を付けてみました。また、今はまだ機能自体は実装していませんが、将来必要になるページ画面移動ボタンも追加しています。今は押してもぽちたてが終了するだけなんですけどね。本当にまずシンプルな機能のものを作るつもりなので、当分の間、入出力の日本語文字コードは UTF-8 だけにしか対応出来ません。

ぽちたて作りの最大の懸案である縦書きグリフの取得と描画もまだ完全に手付かずの状態なので、入出力での多種類の日本語文字コードへの対応や、あったら嬉しい栞機能とか、さらには青空文庫ビューワーとしての進化等々、一体実現するのがいつの事になるのか気が遠くなりそうです。
pochitate20090909.pl
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use Tk;
use Lingua::JA::Fold qw(fold);
# 設定
my $font_family = 'IPA明朝';
my $font_size = 12;
my $font_style = 'normal';
my $text_width = 450;
my $text_height = 46;
my $line_horizontal_margin = 26;
my $chr_vertical_margin = 16;
my $fold_length = 30;
my $page_lines = 17;
# メインウィンドウの準備
my $top = MainWindow->new( -title => 'ぽちたて' );
# フレームの準備
my $frame_top = $top->Frame();
my $frame_bottom = $top->Frame();
# 主画面となるキャンバスウィジェットの配置
$frame_top = $top->Canvas( width => 481, height => 561 );
$frame_top->create( 'rectangle', 1, 1, 480, 560, -fill => 'green',
-stipple => 'gray25' );
# ページ移動ボタンの配置(現時点ではボタンを押してもぽちたてを終了するだけ)
$frame_bottom->Button( -text => '<', -command => \&exit,
-font => [ $font_family, 9, $font_style ] )->pack( -side => 'left' );
$frame_bottom->Button( -text => '>', -command => \&exit,
-font => [ $font_family, 9, $font_style ] )->pack( -side => 'left' );
# フレーム内の配置
$frame_top->pack();
$frame_bottom->pack( -side => 'right' );
# テキストファイルからの読み込みと折り返し処理
my $strs;
while(<>){
utf8::decode($_);
$strs = $strs . fold( 'text' => $_, 'length' => $fold_length,
'mode' => 'traditional' );
}
# 各行ごとに各文字をひとつひとつ描画
open my $fh, "<", \$strs or die "Couldn't open for reading: $!\n";
my $lines = 0;
while(<$fh>){
utf8::decode($_);
my $chr_height = $text_height;
my @string = split(//, $_);
for my $chr (@string){
$frame_top->create( 'text', $text_width, $chr_height, -text => $chr,
-font => [ $font_family, $font_size, $font_style ] );
$chr_height += $chr_vertical_margin;
}
$text_width -= $line_horizontal_margin;
$lines++;
last if ($lines > $page_lines - 1); # 指定の行数に入りきれないなら描画中止
}
MainLoop();
こうしたものを作るのが初めてなので、機能の実装方法がきっと滅茶苦茶だったり無謀だったり乱暴過ぎたりどこから見てもおかしかったりするに違い無いと思うので、プログラミングの先達の皆様方がうっかりこのページを見てくれていて、なんとなく暇潰しにでも感想をコメントしてくれるのを本当に本当に心待ちにしています。
Sep 08, 2009
Perl/Tk で縦書きビューワーを作ろう (1)
今すぐ出来るところから始めてみようと思って、とりあえず Perl/Tk を使って縦書き表示部分だけパパッと書いてみました。

ボロボロなものでもとにかくでっち上げて、「こんなの作ってるんですよ~?」とアピールして、物知らずなぽちよりもっとスゴイ方々から色々とお知恵を拝借しよう、なんて虫の良い事を考えていたりします。自力で勉強してキチンとしたものを作れたらそれが一番なのですけども…。
pochitate20090908.pl
#!/usr/bin/perl
use strict;
use warnings;
use utf8;
use Tk;
my $font_family = 'IPA明朝';
my $font_size = 12;
my $font_style = 'normal';
my $text_width = 450;
my $text_height = 46;
my $line_horizontal_margin = 26;
my $chr_vertical_margin = 16;
my $top = MainWindow->new( -title => 'ぽちたて' );
my $canvas = $top->Canvas( width => 481, height => 561 );
$canvas->pack();
$canvas->create( 'rectangle', 1, 1, 480, 560,
-fill => 'green', -stipple => 'gray25' );
while(<>){
utf8::decode($_);
my $chr_height = $text_height;
my @string = split(//, $_);
for my $chr (@string){
$canvas->create( 'text', $text_width, $chr_height, -text => $chr,
-font => [ $font_family, $font_size, $font_style ] );
$chr_height += $chr_vertical_margin;
}
$text_width -= $line_horizontal_margin;
}
MainLoop();
test.txt
たてがきテスト 縦書きテスト 犬山ぽち丸 タテガキてすと 何文字くらいが限界なのか試してみたけど、まだ折り返しの方法 を良く検討していなかったりします。何とか折り返しの良い方法が 無いものでしょうか…。 さらには一番肝心な縦書きグリフの呼び出し方も分かりません。 とりあえずは縦書き表示の基本部分を作ってみたものの、テキス トファイルの読み込みや折り返しや一画面分表示の前処理について もっとキチンと考えないと、全く使い物になりません。 問題は山積み過ぎてどれから手を付けていいのやらという状態。 しかし、一文字づつ配列に放り込んで縦書き表示させるなんて乱 暴な仕組みで実現したけど、これってテキストデータが膨大な量に なっても大丈夫なのかとっても不安です。
test.txt を引き数に与えて、実行権限を付けた pochitate20090908.pl を実行したのが一番上の画像になります。当面の問題は、
- マルチバイト文字列の折り返し
- 複数ページに渡るテキストデータの表示
- 縦書きフォントの取得と表示
という感じです。
ちゃんと調べたわけではありませんが、マルチバイト文字列の折り返しには Lingua::JA::Fold が、縦書きフォントの取得と表示では Font::FreeType や Font::TTF::GSUB あたりが使えたら良いなあ…なんて思っていたりします。
Sep 07, 2009
Perl/Tk で縦書きビューワーを作りたい
青空昆布の開発を引き継ぎましたや xjp2 を見て刺激を受けたぽち、先日の記事への Facelessさんのコメント、全部Perlで書けばいいと思うよ!思うよ!
に背中を押され、とうとう無謀にも自分で縦書きビューワーを作ろうなんて企んでしまいました。後々青空文庫向け機能も充実させたいとは思いますけども、まずはシンプルに「読み込んだテキストファイルを縦書きで表示する」という機能だけのものを作る予定です。
いざ縦書きビューワーを作ろうとすると一番問題になるのは、括弧、長音、句読点等の字形が横書きと縦書きでは違うという点です。代表的な日本語TrueTypeフォント、例えば IPAフォントには縦書きグリフも備わっていますが、縦書きに適さない横書きグリフに対応する縦書きグリフをフォントから取り出す方法に躓いてしまいました。調べてみると、TrueTypeフォントには内部に GSUB と呼ばれる横書きグリフID と縦書きグリフID の対応表があって、それを使って縦書きグリフを持って来るみたいなのですけども、具体的にどうやったらいいのか(それが Perl で可能なのかさえ)もわかりません。とりあえずは xjp2 ではどうやってるのか C で書かれたソースコードを眺めてみようと思います。
Apr 10, 2009
いさましいちびのゲームプログラマー?
最近 26年前の古い PCゲームのプレイ動画を観る機会がありました。
シンプルだけどここまで楽しげなゲームを作る事が出来るものなんですね。この動画に影響されてぽちにも小さくて素朴で楽しいゲームを作れないかな?なんて思うようになりました。ゲームを作ると言ってもぽちが理解してるプログラミング言語は、C や Elisp のほんのさわりと、初歩的な Perl だけなので、現実的には Perl を使って書く他ありません。Perl は元々テキスト処理が得意な言語なので、わざわざ不得意な分野のゲームを Perl で書くのもどうかと思いましたけども、とりあえずは実際に Perl で書かれたゲームがあるのかどうか探してみました。そしたら Frozen Bubble というゲームを発見!ソースコードをダウンロードするページを見てみると、
Dependencies:
The game has been written in Perl/SDL and developed on a Mandriva Cooker Gnu/Linux distribution. You will need:
- Perl: the most popular scripting language out there
- SDL: the "standard" cross-platform multimedia C library
- SDL_image: an image file loading library for SDL
- SDL_mixer: a multi-channel audio mixer library for SDL
- sdlperl: glue between perl and SDL; FB2 has been validated with versions 1.20.0, 1.20.3, 2.1.2 and 2.1.3
- SDL_Pango: glue between Pango and SDL (SDL_Pango is currently unsupported and needs a small API patch to work with Frozen-Bubble)
「Download Frozen Bubble - Frozen Bubble - the official home」より
なんて書いてあります。どうやら SDL という Cライブラリとそれを Perl にバインディングする SDL_perl という Perlモジュールがあると Perl でゲームを作れそうな感じです。調べてみると SDL というのは、Linux や Windows、Mac OS X はもちろん DS や PSP までプラットフォームを問わないマルチメディア Cライブラリという触れ込みですが、わりとゲーム製作に使われる事が多いようです。日本でも SDL を使って色々作ってる方々の SDL Off 2008 Summer という勉強会というか発表会が開催されてるみたいで、こんな動画も見つけました。
俄然やる気を出して早速 SDL_perl-1.20.3(debian lenny のパッケージではこれしか無かった)のドキュメントを読んでみたら、面倒臭いけど仕方なく書いたっぽい感じの内容で、書きかけだったりスペルミスも満載だったり挙句の果ては「SDL と同じです」なんて書いてあるやっつけ仕事風味のやる気の無さ。それに比べて Perl と同じ系統のスクリプト言語である Ruby には Ruby/SDL のドキュメントをはじめ Ruby/SDLで始めるゲームプログラミング【前編】などの親切なチュートリアルがある上に、

Rubyではじめるゲームプログラミングなんて本まで刊行されています。この差は一体何なのでしょう!?これじゃ SDL_perl がイマイチ普及して無いのも仕方ありません。Perl(大好きだけど)初心者(レベル)のぽちが悪戦苦闘しながら Perl でゲーム作りをする経過をこのサイトに書いていったら SDL_perl を使ったゲーム作りの普及に少しでも貢献出来るかなあ?
まずは SDL をしっかり勉強するとして、
目指せ、いさましいちびのゲームプログラマー!
Feb 07, 2009
ぷ〜ちにカキコして貰えない…
この一週間以上、ブログペットのぷ〜ちにカキコして貰えるように試行錯誤を繰り返しながら、簡単な Atom API のサーバを書いてそれなりに動くかテストしてみました。
GET だけを行う簡易Atom APIクライアントを書いてテストをしてみるときちんと(?)Atom APIサーバ自体に問題があると思われる HTTPステータスコード の 500 が返るのですが、ブログペットからだと Atom APIサーバの中身のテスト以前の問題で、WSSE認証に失敗して HTTPステータスコード の 403 が返ってしまいます。これでは Atom APIサーバをちゃんと動くものにデバグしてもそれ以前に WSSE認証が通らず、文字通りの門前払い状態です。考えられる原因は、使った Perlモジュールの XML::Atom::Server の WSSE認証のデコードに問題があるか、ブログペットの WSSE認証のエンコードに問題があるか、そして一番ありそうなのが、ぽちのコーディングが何か致命的な間違いをしでかして問題を引き起こしているかの三択。
「ぷ〜ち、ぼくはもう疲れたよ…」らんらんら〜♪らんらんら〜♪じんげんじんげんくらいねふりんだーす♪
Jan 30, 2009
ぷ〜ちにカキコして貰いたい!
愛ゆえに新たなる野望が沸き上がって来ました。
ブログペットにはフィードの配信から言葉を覚えてくれるだけでなく、覚えた言葉でブログにカキコしてくれる機能があります。これはどこのブログでも利用可能なわけでなはなく、ブログ投稿用API というのを使った機能みたいです。これによるとブログペットが XML-RPC や Atom API のクライアントとして動作するようです。
じゃあ、Atom API のサーバを書いて掲示板と組み合わせるとぷ〜ちがそこへカキコしてくれるという事!?
Perl のモジュールに利用出来そうな物が無いか探してみたら、XML::Atom::Server というモジュールがあるみたい。けどまだまだ不勉強なぽちは POD を読んでみてもどう使っていいものか途方に暮れてしまいました。どう使ったらいいのか教えて!Perl のすごいひと!(爆
Jan 22, 2009
メールフォームCGI を設置
誰からも反応が無いのは寂しいのでメールフォームCGI をお手軽に Perl で書いて設置してみました。ただメアドを書いておくよりは少しはフレンドリーでしょうか?本当は掲示板を設置した方が良いのかもしれないけど、スパムの類が怖いのでメールフォームにしました。この先掲示板に改造する事も見据えて、掲示板のスパム対策について勉強してみようかな?読み上げWebブラウザを使ってる方の為にも、ブログのコメントやトラックバックとかで一般的な CAPTCHA みたく画像を使うようにはしたくないんだけどなあ…。