こんにちは。Sleipnir for Mac, Sleipnir Mobile for iPhone / iPad 開発担当の金内です。
今日は究極の先端的ウェブブラウザ Sleipnir for Mac の実装に用いている Mac OS X の Layer-Backed View という技術についてご紹介します。
ところで、先日 Sleipnir の先端ぶりを紹介するビデオを公開したのですが、もうご覧いただけたでしょうか?もしまだでしたらこの機会にぜひどうぞ。
まえおき
この記事に出てくる NSView は、GUI の 基本要素となるクラスです。iOS で言えば UIView、Android で言えば View に相当します。
Layer-Backed View は、NSView を Core Animation の描画単位であるレイヤ(CALayer)ベースの新しい描画モデルにするというものです。レイヤを使うから “Layer-Backed” なわけですね。これにより NSView に Core Animation の機能が統合され、NSView を使った UI でなめらかなアニメーションを実現できてしまうわけです。
背景
今をときめく iOS は、もともと OS X と同じ基盤から開発されたのはみなさんご存じのとおり(初期に OS X iPhone と呼ばれていたことも)。iOS と OS X はその後もお互いのいいところを取り入れながら、進化を続けています。
Layer-Backed View は、2007 年 10 月にリリースされた Mac OS X Leopard (10.5) で Core Animation とともに導入されています。そう、2007年。iPhone がこの世に登場したあの年です。同じく Core Animation を搭載して登場した iPhone では、当初から UIKit が Core Animation のレイヤを使った設計となっており、同様の仕組みを AppKit/NSView で実現するものが Layer-Backed View と言えます。
レイヤごとに描画イメージをキャッシュする Core Animation の描画モデルは、メモリ消費量では不利なものの、それを補ってあまりあるパフォーマンスや柔軟性をもたらしてくれます。そのため、後発である iOS の UIView はすべてレイヤベースで実現されているのですが、Mac ではもともと違う描画モデルを採用していたこともあり、オプション扱いとなっています。
つまり UIView も Layer-Backed View に含まれるわけですが、この記事では特にことわらない限り、Layer-Backed View と書いたらLayer-Backed な NSView を表わすこととします。
Sleipnir の Layer-Backed View たち
アニメーションが必要なところはほとんど Layer-Backed View を使っています。つまり、タブバー、ブックマークバー、ポータルフィールド、TiledTab、タブスイッチなどなど。
あんなところもこんなところも Layer-Backed View なのです。
開発中、ウェブページを表示している WebView も Layer-Backed にして動かしてみましたが、まだ対応していないようでスクロールがおかしくなったりするのでやめてます。
使い方
NSView を Layer-Backed にするには次の1行だけで OK です。
[view setWantsLayer:YES];
この「ウォンツレイヤー!イエス!!」を NSView の初期化段階(awakeFromNib など)で呼び出せば、その View 以下すべての階層の View が Layer-Backed となります。見た目にはわからないながらも、背後では違う描画モデルになっているのです。あとからaddSubview: すると追加した View も Layer-Backed になります。
Layer-Backed View のベースとなっているレイヤは AppKit が自動的に管理するので、アプリケーションのコードから直接いじってはいけないことになっています。
Layer-Backed View と似て非なるものに、Layer-Hosted View があります。これは NSView に setLayer: してアプリ側で用意したレイヤを持たせるもので、こちらの場合 AppKit はレイヤの面倒を見てくれません。両者は動作や制約が違うので混乱しないようにしましょう。
いいことばかりではなかったり
新しい描画モデルの Layer-Backed View はいいことがたくさんあるのですが、困ったことがないわけでもありません。
発展途上で変化が激しい
Layer-Backed View は Leopard で導入されて、Snow Leopard、Lion、Mountain Lion と急激な進化の過程にあり、OS のバージョンごとにけっこう動作が違います。包括的なドキュメントもあまりなく、いちばんの情報源が AppKit のリリースノートだったりとかもします。
テキストレンダリング問題
Layer-Backed View は Mountain Lion でかなり完成度が高まりましたが、過去のリリースではいくつか問題もありました。その中のひとつでやっかいなのが、Lion 以前の環境でテキスト表示がおかしくなる問題です。
詳しく言うと、不透過ではない Layer-Backed View 上でテキストを描画すると、液晶モニタのサブピクセルを使ったアンチエイリアス(LCD Font Smoothing)がうまくかからずに、ギザギザが目立つ汚い文字になってしまうというものです。
読めないほどではないにしろ、文字の美しさは Mac の大切な特徴なので無視できません。困ったことに Apple 謹製の NSTextField を使っても発生してしまうのです。シンジラレナイ!(下図)
Sleipnir ではこの問題を回避するために、テキストの描画前に NSGraphicsContext から LCD Font Smoothing オフにして、描画後に元に戻すという実装になっています。LCD Font Smoothing がかからないので本来の美しさにはなりませんが、何もしないよりはずっとキレイにレンダリングしてくれます(下図)。
未来は Layer-Backed View か?
今後、UI はもっとアニメーションをうまくつかったリッチなものになっていくでしょうから、Layer-Backed View の役割は大きくなっていくと思われます。Apple のドキュメントでも「Mountain Lion 以降の環境ではすべて Layer-Backed View で作るのもアリ」というようなことが書かれています。
ここは思い切って「未来は Layer-Backed View だ!!」と断言…..しときましょうか….
Sleipnir for Mac の進化は続く…
10 年を超える歴史を背負いつつ、OS X も新しい設計を取り入れてどんどん進化しています。Sleipnir for Mac も OS X の良さをいかして、究極の先端的ウェブブラウザとしての魅力をもっともっと磨いていきますので、応援よろしくお願いします!
Layer-Backed View フル活用のSleipnir for Mac はこちら