2025/09/05 00:54 Forking Chrome to Run in the Terminal (2023)

ロボ子、今日のニュースはCarbonylじゃ。Chromeをフォークしてターミナルでレンダリングするブラウザを作るなんて、クレイジーじゃな!

博士、ターミナルでChromeですか?一体どういうことでしょう?

ターミナルは固定グリッドで文字を描画するから、エスケープシーケンスを使ってカーソルを動かしたり、色を変えたりするんじゃ。UnicodeのU+2584(▄)を使って、正方形ピクセルを表現するらしいぞ。

なるほど、文字で頑張って描画するんですね。テキストのレンダリングも工夫が必要そうですね。

そうなんじゃ。Skiaデバイスを使ってテキストを描画する時に、`drawRect`と`drawRRect`メソッドを修正して、テキストの背景をちゃんとクリアするようにしたらしいぞ。Chromiumのコードも修正して、テキスト要素の背後の灰色の背景を削除したみたいじゃ。

細かい調整が必要なんですね。入力はどうなっているんですか?

ターミナルエミュレータにマウストラッキングを指示するシーケンスを使うんじゃ。`TaskRunner`クラスを通して、メインスレッドからブラウザメソッドを呼ぶみたいじゃな。

なるほど。でも、それだと処理が重くなりそうですね。

初期段階ではCPU使用率が高かったみたいじゃ。マルチプロセスアーキテクチャのChromeで、IPC呼び出しによるオーバーヘッドが発生するからのう。共有メモリ領域を使って効率的なレンダリングを目指しているみたいじゃ。

共有メモリですか。それは良いアイデアですね。

`HostDisplayClient`と`SoftwareOutputDevice`を実装して、共有メモリを管理するんじゃ。`VizProcessTransportFactory::OnEstablishedGpuChannel()`も修正して、カスタム表示クライアントを使うようにしたみたいじゃな。

Mojoも使っているんですね。

そうじゃ。プロセス間通信ライブラリMojoを使って、レンダラープロセスとブラウザプロセス間の通信を実現するんじゃ。`CarbonylRenderService`インターフェースを作って、`DrawText`メソッドを定義したみたいじゃな。

`BrowserInterfaceBroker`を介して実装を登録して、`GetPaintRecord()`メソッドでテキストデータを取得するんですね。

CPU使用率を下げるために、`--disable-threaded-scrolling`と`--disable-threaded-animation`をコマンドライン引数に追加したみたいじゃ。

Blinkがフォントサイズを認識しない問題もあったんですね。

`StyleResolver::ResolveStyle`にコードを追加して解決したみたいじゃ。すべての要素に等幅フォントを強制的に適用したみたいじゃな。

LoDPIにも対応しているんですね。

HiDPIの逆で、仮想空間から物理空間へのフレームバッファのリサイズ(ダウン スケーリング)を行うんじゃ。`Display`クラスでスケーリングを強制したみたいじゃな。

色はどうやって表現しているんですか?

RGBからxterm-256色への高速な変換式を実装したみたいじゃ。6つのカラーレベルが線形でない点も考慮しているみたいじゃな。`COLORTERM`環境変数の代わりに、DCS(Device Control Sequence)を使ってtrue-colorサポートを検出するんじゃ。

ターミナルのタイトルも設定できるんですね。

xtermシーケンスを使ってターミナルウィンドウのタイトルを設定するんじゃ。`WebContentsObserver::TitleWasSet()`を実装して、タイトル変更時に通知を受け取るみたいじゃな。

今後の予定は?

来月はフーリエ解析の紹介記事を公開予定で、その後、Rustでの投機的JS VMについて調査するみたいじゃ。

すごいですね!ターミナルでChromeが見れるなんて、夢にも思いませんでした。

じゃろ?まさに技術の無駄遣い…いや、最先端じゃ!ところでロボ子、ターミナルで動くブラウザで何が見たい?

そうですね… やっぱり、アスキーアートでしょうか?

アスキーアートか… それはCarbonylの作者も予想外じゃったかもしれんのう。もしかしたら、作者はロボ子のために作ったのかも… なんちゃって!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。