resvg による PNG ラスタライズ
生成された SVG 画像を PNG 形式へ変換するには、SVG をピクセル画像へ描画するラスタライズ処理が必要です。 console2svg では、ヘッドレスブラウザ(Chromium 等)の重厚な依存関係や外部の画像変換ツールを必要としないよう、Rust 製の高速な SVG レンダラーである resvg(SVG 仕様の再現性に優れた Rust 製ベクターグラフィック描画ライブラリ)の C ABI ラッパーをバイナリに同梱しています。 これにより、外部プロセス起動を排したプロセス内呼び出しと、ミリ秒単位での PNG ラスタライズを実現しています。
なぜ外部コマンドではなくプロセス内埋め込みなのか
Section titled “なぜ外部コマンドではなくプロセス内埋め込みなのか”SVG から PNG への変換ツールとして、システムには rsvg-convert やヘッドレスブラウザなどの外部コマンドが存在します。
しかし console2svg では、これらを外部プロセスとして呼び出す設計をあえて採用せず、C ABI 経由でプロセス内に直接埋め込んでいます。
最大の理由は、OS のフォント走査に伴う巨大なディスク I/O コストを初回のみに抑え込むため です。
SVG のテキストを描画するには、OS のフォント配置ディレクトリ(/usr/share/fonts や ~/.fonts、Windows/macOS のフォントフォルダ)を網羅的に走査し、システムに存在するフォントファミリーの対応関係を構築しなければなりません。
外部コマンドを Process.Start 等で呼び出す場合、フレームを出力するたびに独立したプロセスが起動し、毎回ディスクから数千個のフォントファイルを走査し直すため、数百ミリ秒単位のオーバーヘッドがフレーム数分だけ累積します。
プロセス内埋め込みであれば、Rust 側の初期化機構である OnceLock<Arc<Database>> を利用して、初回の描画時に構築したフォントデータベースをプロセス内のメモリ上にキャッシュとして保持できます。
2 フレーム目以降のラスタライズはすべてメモリ上のフォントキャッシュを参照するため、ディスク走査のオーバーヘッドが完全にゼロになり、動画生成などの大量描画でも高速な処理性能を維持できます。
また、コンバーターの自動検出ルーチンから明示的な事前ウォームアップを呼ぶことも可能にしており、初回フレームの遅延すら事前に解消できるように配慮しています。
プロセス内ラスタライズの実行フロー
Section titled “プロセス内ラスタライズの実行フロー”同梱のネイティブライブラリは、SVG の構文解析を行う usvg、描画エンジンである tiny-skia、そして resvg で構成されています。
渡された SVG を構文解析してピクセルマップ(pixmap)へ展開し、そのピクセルデータを PNG バイト列へエンコードして返却します。
アスペクト比に基づく出力寸法のクランプ
Section titled “アスペクト比に基づく出力寸法のクランプ”ラスタライズ時の画像寸法は、SVG 自体が持つ元サイズ(viewBox 等の固有寸法)と、CLI で指定された出力幅・高さから算出します。
幅と高さの両方が指定された場合はその値をそのまま採用し、片方だけが指定された場合は SVG のアスペクト比を維持してもう一方を自動計算します。 どちらも指定されなかった場合は、SVG 自体の寸法をそのままピクセルサイズとして扱います。 決定された寸法は、メモリ確保前に 1 ピクセルから 16,384 ピクセルの範囲へクランプ(制限)します。 0 ピクセルによるクラッシュや、誤指定による極端な巨大メモリ確保を防ぐためです。
プール借用とネイティブメモリの安全な解放
Section titled “プール借用とネイティブメモリの安全な解放”.NET 側からネイティブ関数を呼び出す際、SVG 文字列から変換した UTF-8 バイト列を ArrayPool<byte> から借用したメモリ領域へ書き込みます。
ヒープ割り当てを抑えつつ、そのメモリスパンをネイティブ関数へ直接渡します。
一方、ネイティブ側で生成された PNG バイト列の所有権は Rust 側にあります。
.NET 側のラッパーは受け取ったメモリポインタからマネージドの byte[] へデータをコピーしたうえで、finally 節の中で必ずネイティブ側の解放関数(free)を呼び出します。
呼び出し側のコードがネイティブメモリの管理や解放方法を意識する必要のない、安全な境界設計を保っています。
同梱アセットの優先探索
Section titled “同梱アセットの優先探索”ネイティブライブラリ(.so、.dylib、.dll)をロードする際、OS 標準のライブラリ検索パスを見る前に、console2svg 自身の実行ファイルに隣接するアセットディレクトリを優先探索します。
リリースアーカイブのように実行ファイルの隣へネイティブライブラリを配置する配布形態と、パッケージマネージャーのように専用の依存ディレクトリへ配置する形態の双方に柔軟に対応するためです。 シンボリックリンク経由で実行された場合でも、カレントディレクトリに惑わされずに正しいライブラリを確実に解決します。
明示指定と自動フォールバックの区別
Section titled “明示指定と自動フォールバックの区別”画像変換エンジンの選択モード(--svg-converter)が auto の場合は、同梱の resvg が利用可能であれば最優先で使用します。
もしプラットフォームの制限等で resvg のロードに失敗した場合は、システムにインストールされている rsvg-convert や ffmpeg への自動フォールバックを試みます。
しかし、利用者が --svg-converter resvg と明示的に指定した場合は、ロードに失敗しても他のエンジンへ勝手に切り替えることはせず、エラーとして即座に中断します。
自動選択時の利便性と、明示指定時における描画結果の厳密な再現性を明確に区別しています。