Lion と Mountain Lion の Tips

MacSoft

Lion と Mountain Lion。見た目がほとんど同じ両 OS だけど、ログイン画面で見分ける方法がある。(非 Retina 環境のみ確認)

システムの起動が終わったあと、画面中央のリンゴがずるずる上に移動してログイン画面になるけど、Lion ではそのマークがかすれている。Mountain Lion ではくっきりと表示されるのだ。

ぜひ家族や友人の Mac のログイン画面を見て Mountain Lion かどうかを当てて驚かせてみてほしい。

...

未だに信じられない!

中央位置の計算 x=(W-w)/2 かどこかで小数点以下を切り捨て忘れ、1 ピクセルに満たないずれが起きてしまったのだろうか。

最初に見たときは、Apple なら当然すぐに直すだろうと思っていた。
だが製品版どころか 10.7.1、10.7.2、10.7.3、とバージョンアップしても直らなかった...
結局直ったのは 1 年ぐらい経ってリリースされた 10.8。

自分は基本的に「ジョブズがいたらこういうことはしないはずだ」なんてくだらないことを言うことはないのだけど、この件に関しては言いたい。

ジョブズがいたらこうはなってない。iPhone の画面に小さく表示される Google ロゴの黄色いグラデーションがおかしい件について日曜日にも関わらず Google の責任者に電話してすぐに直すことを伝えたようなジョブズが、こんな目立つ位置にあって、動いた後で余計に目立つ、そして Mac を起動してまず目にする存在である、それも自社のロゴがピクセルずれを起こしているのをそのまま 1 年も放置するなんて許すはずがない!
Lion はジョブズが生きているときに出たけど、もう iOS が精一杯で、OS X までチェックする時間と体力が残っていなかったのだろう。

...というかジョブズの名前を出すレベルでもないと思う。自分ですら初めて見たときに気づいたし。

昔から未完成レベルの物をリリースすることはあるけれど、最低限こういう部分だけはしっかり仕上げてリリースする会社だったはず。この件は残念だった。

OS X 10.8 で改善された Layer Backed View とテキストレンダリング

MacDev

以前 NSView (AppKit) の CALayer 対応について、テキストのサブピクセルレンダリングが上手く機能しない問題があるという記事を書いた。Sleipnir for Mac の開発ブログ記事でもこの問題に触れられている。

復習すると、

  • 古くからの描画方式では通常 1 つのウインドウにつき 1 枚のグラフィックスコンテキストがある。
  • layer-backing を有効にするとそれぞれの NSView がグラフィックスコンテキストを持つようになる。
  • サブピクセルレンダリングは背景の色に依存。必ず背景の上に描画しないといけないので Layer-backed view とは相性が悪い。

...しかし、あれは Lion の時点での話。

Mountain Lion での改善

10.8 の AppKit Release Note にはこんなことが書かれている:

NSTextField has been updated to allow LCD font smoothing to work when the view is layer-backed. Prior to 10.8, NSTextField would directly draw the text into the layer's contents; this would cause text to render incorrectly due to the LCD font smoothing algorithm not having adjacent pixels to smooth fonts with. Layer-backed applications that manually draw text should move to using NSTextField to get proper LCD font smoothing.

自分の理解:

  • NSTextField がアップデートして layer-backed でもサブピクセルレンダリングできるようになった!
  • これまで NSTextField の描画内容は、ほかの NSView サブクラスと同様、layer の contents に 1 枚のビットマップ画像として設定されていた。これでは描画するときにその背景を知りようがないので正しくサブピクセルレンダリングできない。
  • そこで 10.8 以降は何か特別な仕組みで描画するようになったみたい。
  • 今後は、自作ビュー内に自力で描画していたテキストも NSTextField に任せるといいらしい。

続きを読むとこれが機能するには条件があって:

One caveat is that NSTextField does require an ancestor which is layer-backed and opaque; it does not have to be the direct parent view, but some view in the ancestor chain must be opaque for this to be turned on and work correctly.

NSTextField の superview をたどっていったとき、先祖のどこかで「layer-backed かつ opaque」なビューが必要らしい。

実験してみよう

いくつかの疑問:

  • 本当に機能するの?
  • 10.7 との違いは?
  • 裏にあるビューの中で色が変化しても大丈夫?

まず、NSWindow を 1 つ用意。contentView の中に NSTextField と SomeView を配置。

  • contentView:ウインドウ全体を覆うビュー。
    • 背景を [NSColor windowBackgroundColor] で塗りつぶす。
  • SomeView:適当な図形を表示するビュー。
    • -isOpaque で YES を返す。
    • 2 つ用意。上には NSTextField の兄弟として、下には NSTextField の親として配置。

結果 1:Layer なし

AppKit の昔からある描画方式。

言うまでもなくサブピクセルレンダリングは正しく機能している。これが理想。

結果 2:OS X 10.7.5 での結果

これ以降は contentView が layer-backed である。

字がふにゃふにゃしていて汚い。

結果 3:OS X 10.8.2 での結果

Release Note に書かれていた通りだ。

  • NSTextField と SomeView が兄弟関係にある上では効いていない。
  • 親子関係にある下ではしっかりサブピクセルレンダリングされている。

サブピクセルレンダリングが効いていない部分(上)も Lion(結果 2)より奇麗。

結果 4

おまけ。contentView を opaque にしてみた。

これで全体にサブピクセルレンダリングが効くようだ。結果 1 との違いもないのではないか。

結論

NSView が CALayer による layer-backing をサポートしていても使うのをあきらめてしまう原因の一つだったけど、Mountain Lion で大きく改善されたようだ。ちょっとした制約はあるけれども。