crisped edge #2

Linux 向けの、実用に足る unicode ベースのビットマップフォントが、もしかして未だにないんじゃないのか? という問題を解決したい。

実のところを言えば、unicode ベースのビットマップフォントというのはすでにある。

これは Basic Multilingal Plane の全域をサポートした 8×16/16×16 ドットのビットマップフォントである。

しかしながら、いくつか問題があるのである:

  • Latin な文字について、x height が高すぎる。そのため大文字と小文字の判別がつきづらい
  • 0 に斜め線が入ってない
  • CJK な文字について、それらは Wen Quan Yi Project が作成しているフォントから提供されているのだが、漢字部分はともかくひらがなやカタカナがけっこう見づらい

こういうわけで、日常的に端末で使えるかどうかというと微妙なのであった。

一方で、GNU のプロダクトである。グリフの元データとなる hex ファイルや、さまざまなユーティリティプログラムも込ですべてが公開されている。フォークして、これらを元にさせていただきつつ新しいのを作ればよいのではないか。そうだそうだ、そうしよう。

* * *

ということで、新しくグリフをデザインしたり、懐かしの jiskan16 を持ってきたり、東雲フォントをもってきたりいろいろした結果、できた。名前は特に意味はないが、UFO とした。地球のフォントに飽きたところよ。

Latin 文字

Latin 文字

ソースコード

ソースコード

日本語の文

日本語の文

もちろんこれで完成というわけではまったくない。既知の問題として CJK のグリフがバウンディングボックスを目一杯使っているのでスクリーンにぎっしり日本語の文章を表示するとかなり見にくい。もしかしたら CJK グリフは一回り小さい wqy なビットマップフォントから改めて持ってくる必要があるかもしれない。

とりあえず個人的に使ってみつつ微調整したい。

crisped edge

日常の作業は端末エミュレータ上でのそれがほとんどなのである。

したがって、一日の大半は黒い画面上の白い文字を睨んでいるわけなのだが、ここに問題がある。ナウい OS というものはなんでもかんでもアンチエイリアスがガンガン効いたフォントをレンダリングする。一方で、端末は 10pt とか 12pt とか、けっこうこまい文字で使っている。するとこのサイズでのアンチエイリアスの効いた文字はむしろ見にくいのだ。これははっきり言ってストレスがたまる。

つまり、端末ではいわゆるビットマップフォントを使いたいということだ。しかしこれは意外なことに Linux のほうが面倒くさい。Windows(というか cygwin の mintty)では単に Terminal のような、fon 形式のフォントを選択するだけなのに、Linux の場合はそもそもビットマップフォントを選択できなかったりする。

しかしながら、さすがにフラストレーションが溜まってきたので、なんとかしたい。ここで言うなんとかしたいというのは、端末に bdf フォントを認識させるにはどうしたらいいの? 的なレベルではなく、Linux 向けの、実用に足る unicode ベースのビットマップフォントが、もしかして未だにないんじゃないの? というソレに対するアレである。

RDP 8.0 #3

以前、Windows 7 上で RDP 8.x を有効にする更新を入れたら満足に動かなかったという記事を書いたのだが、今月になって Windows Update の中にそれの更新版が来ていたようだ。以前リンクしたMSDN のドキュメントも更新されているが、 KB2574819 KB2857650 KB2830477 KB2913751 KB2913751(optional) が入ってれば良いという。うちのマシンには全て入っていた。

ということで、ホスト側 PC で改めて RDP 8.x を有効にした上で適当な別のマシンから接続し、こうやって記事を書いている。以前書いたような不具合は今のところ見られないようだ。

ありがとう MS さん!

exodus from presto opera

Blink Opera が version 20 に達した今もなお、うちの PC のメインブラウザは Opera 12.16 である。

2014 年 3 月の今現在においても、とりあえず、Presto Opera でもそれほど困る場面は多くはない。もちろん CSS3 をふんだんに使って Opera じゃ全然満足に表示できないとか、javascript の JIT がらみで Opera ごとすぽーんとプロセスが落ちたりするサイトはじわじわと増えてきている感はある。しかしメインブラウザの地位を脅かすほどのストレスをもたらすほどでは、まだない。

とは言ってもこれは時間の問題なのも確か。やがては、Presto Opera から移行しなければいけない時期が来るのは言うまでもないのである。その時のために、先立ってなぜ Presto Opera でなければいけなかったのか、の個人的な理由をまとめておこう。つまりこの要件を満たしてくれるブラウザがなければ将来であっても移行できないし、満たしてくれさえすれば今すぐにでも移行できる。

  • メーラがブラウザと一体化している: 正確にはブラウザと一体化しているのがメリットなのではなく、さまざまなアカウントのメールや、メーリングリストや、RSS フィードや、IRC や、その他もろもろをひとまとめにしてくれる。これはまあ必ずしもブラウザと一体化している必然性は実はあまりない。つまりまとめて面倒見てくれさえすればブラウザと一体化してなくても別によい
  • キーバインディングの自由度が高い: vi/vim に魂を捧げた人たちにはついていけないけど、hjkl にページスクロールを割り当てたり程度はする。また ctrl+H に [cci]Back | Close page[/cci] といった条件判断を伴うバインディングをする。あるいは、コンテンツ領域外、例えばアドレスフィールドに対して [cci]ctrl+N/P/F/B[/cci] を割り当てたりする。この全てを柔軟に聞き届けてくれるブラウザは今もなおそれほど多くはない
  • 充実したデバッガ: Dragonfly は様々な改善を経て、今では十分に使えるデバッガになっている。特にけっこう自由にキーバインディングできるのが非常によい。他のブラウザが持つデバッガはいずれもここまでの自由度は持っていない。持っていたら教えて下さい

願わくば、数年後にこれらの要件を Blink Opera が満たしていてくれればとても素晴らしいのだけど。

moon-crystal-power

赤福プラスをエクステンションのパッケージにビルドするための準備をした。

wasavi のビルドは ant を使っている。これは junit と selenium を使った機能テストと統合しているためである。一方で赤福プラスの場合はその手のテストが難しい。つまりやることの大半がふたばのサーバに対する応答なわけで、継続的な自動テストを行わせるにはふたばのサーバとして振る舞うダミーが必要になるのだが、それを真面目にやるのはなかなかな大仕事だということだ。もしかしたら junit & selenium とか、そういう話じゃなくなって、まったく別の仕組みを使う必要が出てくる可能性すらある。

となるとビルドに ant を使う必要もないわけで、赤福プラスのビルドは make で行うようにしてみた。ant でダメというわけでもないのだけれど、ビルドの手順を xml で書くのは、やっぱりとっても冗長なのである。まあきっと一般的には build.xml は直接触らず GUI でぽいぽい手順を指示するタイプのツールがメジャーなのであって、xml が冗長だ的な批判は的はずれなのだろう。xml を直接書くほうが頭おかしいのである。

しかし、それにしても、(シンプルなプロジェクトの)Makefile はやはりシンプルで、素朴で、いいなあと思いました。

hello, onedrive

OneDrive にも対応するようにした。OneDrive というのはかつては SkyDrive とよばれていた、Microsoft が提供するオンラインストレージだ。

そのためにドキュメントをいろいろ参照するわけなのだけど、まあいつもの MSDN クオリティというか、量自体は豊富なんだけど痒いところに手が届かない感じがしてあんまり使いやすくない。

あと、OAuth での認可を受けるためのエンドポイントのドメインが login.live.com なのに OneDrive(というか Live Connect)の API は apis.live.net だったりちぐはぐなのがなんか全体的にこう……なんと言ったらいいのか MS らしいですね!

かつて apple の親分だったおじさんが MS を評して曰く、「彼らはセンスが足りないんじゃない。『ない』んだ」とかなんとか、と聞いたことがあるけれど、もしかしたら、まったくもって、その通りなのかもしれない。

mkdir -p

[cci]$ mkdir -p foo/bar/baz[/cci] とすると、パスを構成する各ディレクトリがなかったら、自動的に作ってくれるという賢い動作をしてくれるじゃないですか。

オンラインストレージの API でそういう動作をしてくれるかという話。

dropbox は、まさにそういう動作をする。というより、それ以外の動作(存在しないパスが指定されたらエラーにする的な)を指定できない。ファイルをアップロードする REST エンドポイントの構造は
[cci]https://api-content.dropbox.com/[VERSION]/files_put/[ROOT IDENTIFIER]/[PATH][/cci]
というものだ。VERSION は現在は [cci]1[/cci]、ROOT IDENTIFIER はユーザーに割り当てられた空間のどこをルートにするかという指定で、[cci]dropbox[/cci] は空間全体のルートを表し、[cci]sandbox[/cci] は登録したアプリケーションごとの専用のディレクトリを表す。

実際には、[cci]sandbox/foo.txt[/cci] は 例えば単に [cci]dropbox/app/akahukuplus/foo.txt[/cci] と同じ場所を示す。sandbox を指定している限り、誤っておかしなディレクトリのファイルを読み書きしてしまうことはないというシンプルだけど確かに効果のあるからくりだ。

そして、PATH で目的のファイルのパスを指定する。つまりエンドポイント URL に対象となるパスの、その階層構造も含まれている。

一方で、Google Drive はどうかというと、そもそも階層構造の中の特定の位置を文字列で示すという概念がない(気がする)。[cci]/foo/bar/baz.txt[/cci] というパスの baz.txt の情報を得るには、ルート上のファイルの中で [cci]foo[/cci] を検索し、そのディレクトリの下にある [cci]bar[/cci] を検索し…という処理を再帰的に行う必要があり、そのつど REST のネットワークアクセスが発生する。非常に、恐ろしく無駄だ。なぜ、パス文字列という概念を google が導入しないのかはわからない。そういう環境なので、そもそも mkdir -p 的な動作を期待できない。

 * * *

というわけで、akahukuplus のバックエンドの gdrive ファイルシステムモジュールでは、例えば [cci]/dat/b/1234567890.jpg[/cci] というパスにファイルを保存したい際は mkdir オプションを指定できるようにした。この値が [cci]auto[/cci] で、かつ指定のパスが存在していなかった場合は mkdir -p 相当の動作をエミュレートしてから保存処理を再度実行する。

OAuth 2.0 in a browser extension

アプリケーションが OAuth 2.0 における認可を得る際の手順は、そのアプリケーションの性格によっていくつかの系統に分かれる。このあたりは google のドキュメントなどにまとまっているのだが、つまり

  • Web サーバが主体になる場合
  • ネイティブアプリケーションが主体になる場合
  • ブラウザが主体になる場合

と大別される。いずれにしても、基本的には

  1. 認可を得るための一時的なコードを得るための最初のリクエスト(これは正確には認可を得るためのページを web ブラウザで開くだけの処理だ。認可を得るかどうかはそのページを見ているユーザが判断する)
  2. そのコードをアクセストークンへ交換するための 2 度目のリクエスト
  3. 得たアクセストークンが正しいものであるかの確認のリクエスト(これは認可を得るための必須の処理ではないけれど、普通は行う)

を順に行うという流れに従うのだが、何が主体になるかで微妙なところが微妙に違う。具体的には、一時的なコードを得るための経路や、アプリケーションごとに割り当てられるクライアント ID、クライアントシークレットの扱いなどだ。

  • Web サーバが主体になる場合、リクエスト 1 の際にリダイレクト URL を指定する。この URL として、Web サーバの管理が及ぶ適当なものを与える。アプリケーションを利用するユーザが承認すると、ユーザが見ているブラウザのページは自動的にリダイレクト URL に転送される。このとき、URL に追加されているクエリ文字列に一時コードが含まれているので、Web サーバはそれを得ることができる。
  • ネイティブアプリケーションが主体になる場合、Web サーバのようには行かないので、2 つの特殊なリダイレクト URL のどちらかを使用する。[cci]urn:ietf:wg:oauth:2.0:oob[/cci] を指定した場合は、何やら呪文のようなアドレスだが、つまりリクエスト 1 の時点で単にページ上に一時コードを表示して一旦終了ということだ。これをユーザが手作業でアプリケーションにコピペする。[cci]http://localhost[/cci] を指定した場合は、あらかじめネイティブアプリケーションがローカルマシンの適当なポートをリスンしておき、その経路を通して一時コードを得る。
  • ブラウザが主体になる場合は特殊で、一時コードをすっ飛ばしていきなりアクセストークンを得ることができてしまう。ただしこれで得たアクセストークンは非常に短い有効期間しか持っていない。

と、ここまでは、上のドキュメントに書いてあることそのままなので、いいのである。問題は、ブラウザに組み込まれるエクステンションの場合はどのシナリオを選択すればいいの? ということだ。

エクステンションは単なるブラウザ上のスクリプトよりも多くの機能を持っているので、ブラウザだからといってブラウザ主体のシナリオのみ許されるわけではない。それどころか、とても興味深いことに、ブラウザのエクステンションは工夫次第によって 3 つのシナリオを全てを実装できてしまう。そして同時に、いずれの方式にも若干の気をつけるポイントも出てくる。どれを選択するべきなのか?

 * * *

Web サーバシナリオを選択した場合、適当な外部の Web サーバを用意し、リダイレクト URL を作る。エクステンションはリクエスト 1 によるアクセスにまつわるブラウザのページ遷移を監視し、リダイレクト URL に達した時点でクエリ文字列を得ればいい。これに嫌な点があるとすると、一時コードを含んだ URL が認可サーバからブラウザに来るパスの他にもう一度、ネットワークを流れてしまうということだ。そのためリダイレクト URL を SSL 経由にしたりする必要があるが、これはなかなかコストのかかる作業である。

ネイティブアプリケーションシナリオを選択した場合、外部 Web サーバは不要だ。ブラウザのリダイレクトを [cci]oob[/cci] にし、ページに一時コードが表示された時点でエクステンションからそれを読み取ればいい(このへんがちょっとハックでストレートじゃないのが気になるが)。一方で、これは Web サーバシナリオでも実質的に同じだが、クライアント ID とクライアントシークレットをエクステンションのパッケージに内包させなければならないのが気になる。全然シークレットでもなんでもなくなってしまうのである(これは、上のドキュメントにも書いてあることであるが、ネイティブアプリケーションシナリオにおいてはどうにもならない副作用だ)。

wasavi は dropbox のクライアント情報に関しては、エクステンションのパッケージ内に暗号化して含めるようにしている。これはプレーンな状態で含めようとしたら dropbox の審査で暗号化しろよ! と怒られたのでそうした経緯があるのだが、しかしまあ、ブラウザのエクステンションである。すなわち javascript コードがそのまま入ってるのである。コードを読めば、どう復号するのかはすぐわかっちゃうわけで、意味があるのかどうかはいまいちわからない。

最後のブラウザシナリオでは上に書いたような問題点は一見ない。アクセストークンを得るためにクライアントシークレットは不要だ(クライアント ID は必要なのでこのあたりの問題が根本的に解決するわけではない)。しかしこの形式で得たアクセストークンは前述したとおりすぐ切れる。wasavi では Google Drive との接続はこの方式を用いているのだが、だいたい 1 時間もするとすぐに再認可のページに飛ばされてしまう。これは使い勝手が良いとはちょっと言えない。

reborn: akahukuplus

この一ヶ月特に何も作っていなかったというのはつまり、引っ越ししたのでそもそもネットから遮断されていたということなのだが、その直前までは何をしていたのかといえば、wasavi に関してはほとんどコードをいじっていない。

いじっていたのは赤福プラスとよばれるブラウザ用拡張なのである。

かつてふたば☆ちゃんねる向けに IE のコンテキストメニューを拡張する赤福というツールを作った。赤福プラスはその Opera 版というわけだ。Opera 版は当時の Opera が搭載したばかりのユーザースクリプトの仕組に乗っかって動作し、コンテキストメニューにとどまらない様々な機能を持っていた。

その後、Chrome でも動くようにしたり、その過程でブラウザ拡張として構成しなおしたりしたのだが、さすがに建て増し続きだったし、また IE6 あたりでも動作するようにしていたので、例えば Selector API とか XPath とか続々とブラウザに搭載されていく新機能を使うわけにも行かず、中味はなかなかぐぬぬなコードになっていた。

今回、そんなわけで一から作り直してみようということである。残念ながら IE はサポート外となる。最近の IE 自身は、新しい赤福プラスを動作させるポテンシャルは十分あるのだけど、スクリプトベースの拡張の仕組みがないので。一方で、Presto Opera はサポートする。サポートするも何も、Opera 12 で開発してるので、未だにファーストクラスのブラウザだったりする。この他には Chrome と Blink Opera でテストする。気が向けば Firefox 版も作るかもしれない(気が向かないのは、Firefox には別の人が作った赤福がすでにあるからである)。

技術的な面に目を向けてみると、フロントエンドとバックエンドで全く違ういくつかのトピックがある。

まずフロントエンドからだが、赤福プラスというのはつまりふたばの画像掲示板の html を動的にちょっと書き換えるツールだ。ここではふたばの画像掲示板に DOMContentLoaded でスクリプトを引っ掛けて、ページの DOM をごにょごにょするのがフロントエンドの役割だ。

しかし、ふたばの画像掲示板が吐く html というのは、まああんまりそういう再利用はしやすくないのである。そこで、おそらく他のふたば用ツールはほとんどやっていないであろう手法を取る。ページを読み込んだらそれをスクレイピングし、一旦中間的な xml を構築する。さらにそれを XSLT プロセッサに与えて html に変換するのである。続きのレスを読んだりダイアログを出したりするときも必要なら XSL による変換が入るので、けっこう XSLT が大回転することになる。

これによってふたばの元々の html に振り回されるのはスクレイピング処理部だけになり、その他の部分は自分で完全に制御できる xml だけを見ればよくなる。また、ページ全体を制御できるのでよりダイナミックにページを構成することが可能になる。たとえばスティッキーなサムネイルとかバナー、固定ヘッダなどをなんでも導入できるようになる。

次にバックエンド。バックエンドとはつまり拡張の表に出てこない裏方の部分だが、実はこれは wasavi とちょっと関連する。wasavi もバックエンドを持っている。wasavi もまたいくつかのブラウザで動くため、各ブラウザの拡張の仕組みをある程度抽象化させた部分をもっているのだが、残念ながら完全ではなかった。また、wasavi というアプリケーションからも独立してるわけでもなかった。

これがずっと気にかかっていたので、今回を機にブラウザ拡張の抽象化層をきっちり作り、またアプリケーションからも完全に独立させたい。その抽象化層をベースにして赤福プラスのバックエンドを構築し、さらに wasavi にもバックポートする。なかなか遠大・壮大な計画なのである。

バックエンドに関してはもうひとつやることがある。オンラインストレージをアプリケーションから利用する際の承認において、dropbox はなんかなかなか OAuth 2.0 をサポートしなかった。ので、wasavi も jsOAuth というちょっと癖のあるライブラリを使って OAuth 1.0 で繋ぐしかなかったのである。しかし最近なのか結構前なのか知らないけど、いつの間にか OAuth 2.0 がサポートされていたのでそのへんの仕組みをごっそり書き直したい。当然この辺りも wasavi にバックポートされることになる。

赤福プラスにおいては、オンラインストレージは画像の保存・スレッドの保存時に利用することになる。画像のサムネイルから保存ボタンを押すとオンラインストレージの API を通して保存を行うのである。オンラインストレージ側の機能でローカルや複数デバイス間で同期することができる。

最近の状況はこんな感じです。

serif or sans-serif

文字の形は一般的に書体、フォント、タイプフェイスなどとよばれる。

欧文の場合、まず大きく分けて serif 体と sans-serif 体(と、その他)がある。見た目上の決定的な違いは、前者がいわゆるヒゲ付きで、後者がヒゲなしだということなのだが、1 文字 1 文字の見た目以上の違いがもっといろいろなところに現れる。

書籍などの印刷物なんかでは、だいたい本文のような長い段落の文章は serif で組む。serif のほうが読みやすいからである。対して、見出しのように目立ってなんぼの部分は sans-serif で組む。そのほうが目立つからである。とこのように、それぞれのデザインに用途の向き不向きがある。したがって普通は適材適所にそれぞれの特徴を活かした組版を行う。

翻ってコンピュータ上でのテキストの組版、とりわけ web ページのそれはどうなのかというと、残念ながら長い文章であっても serif が使われることは少ないように思える。特に日本語のページではそうである。これは一つ理由が考えられて、現在の一般的なディスプレイのピクセル密度では、serif 体はあんまり綺麗に表現できないのである。

個人的には、ディスプレイ上であっても長い文章は serif で読みたい。日本語の書体では serif / sans-serif は明朝体 / ゴシック体というものに対応する。しかしどうもゴシック体で組まれた文章は、クールでポップでかっこよくはあるのだけど、なんというか真摯さに欠ける。どんな高尚な内容の文章も、メイリオとかヒラギノ角でレンダリングしてしまうと、薄っぺらな C 調言葉にしか見えなくなってしまうのである。これは「おまえは何を言っているんだ」と言われそうだが、かなり本気でそう思っている。そんなわけで、もっと明朝体をゴリ押ししたい。ゴリ押ししていきたい。どうでもいいけど C 調とか我ながら発想が古いなあ。

さて、最近は特にモバイル機器を先頭に、ディスプレイの解像度はじわじわと上がりつつある。96ppi どころか、一気に 200 とか 300 とかの ppi に達しているものもある。これくらいの解像度があれば十分 serif も明朝体も綺麗に表示できる。ヘタしたら、アンチエイリアシングのような小細工すら必要ないかもしれない。この分だと、あと数年もすればほとんどのディスプレイが高解像度に置き換わるのではないか。そうするとつまり、ハードウェアの面では明朝体ゴリ押し計画に対する障壁はないことになる。

問題はソフトウェアの面なのである。