Aoedeの読書画面はSwiftUIで作られていて、単語の一つひとつがそれぞれ小さなビューになっています。おかげで看板のエフェクトはその場に貼り付けやすかったのですが、長い章には向かない形です。数千語あれば、レイアウトすべきビューも数千個。フォロースクロールもぎこちない段取りを踏むことになります。遅延リストでは画面外の位置がわからないので、アクティブな行を中央に保つために、settleパスと、着地点を再確認するリカバリーのタスクが要るのです。動きはしますが、本が長くなるほどこちらに抗ってくる構造です。
そこでワークツリーで、リーダーをTextKit 2の上に作り直しました。NSTextLayoutManagerをUIKitとAppKitでホストし、SwiftUI側のインターフェースは同じまま。ドキュメント全体が一つのattributed stringになり、単一のフラグメントパスで描かれます。TextKitは画面外の矩形を直接解決するので、settleとリカバリーの段取りはまるごと消えます。読書ハイライトはTextKitのレンダリング属性で再レイアウトなしに色を変え、カラオケの塗りとフォーカスレンズのグローは、ディスプレイリンクからアクティブな単語の矩形だけを描き直します。GPUエフェクトのシマーとウェーブは、実際のレイアウトフラグメントに合わせたCAMetalLayerのオーバーレイへ移しました。Aoedeのリーダーをリーダーたらしめるものは、すべて連れてくる必要がありました。行間に余白を確保したふりがなのルビ、隠した既知語、辞書のポップオーバー、本文内検索、そしてあらゆるジェスチャー。
まだ実験です。全体をLabsのトグルの裏に置いてあるので、同じ本と同じ再生で二つの画面をA/B比較できます。それが唯一の正直な判定方法です。MetalのエフェクトはシミュレータのMetalが限られているため実機未検証で、フレームレートの改善もまだ腰を据えて計測していません。ここでの賭けは、証明済みというより構造的なものです。一つにレイアウトされたテキストオブジェクトのほうが、数千個の個別ビューより長い本を滑らかにスクロールするはず。SwiftUIリーダーを置き換えるのか、それともフォークのまま残すのかを決める前に、それを体で確かめたいのです。