Files
docview/docs/design/02-architecture.md
T
2026-09-21 13:41:40 +09:00

9.2 KiB

02 全体アーキテクチャ

採用構成

Qt 6 / C++20 / Qt Quickをアプリケーション基盤とし、PDFは独立したPDFiumワーカー、HTML・EPUBはQt WebEngineで描画する。CMakeで構成し、両OSの依存バージョンを同じリリース単位で固定する。具体的なQtパッチ版・PDFiumコミットは実装開始時に選ぶ。

Qt PDFはアプリのPDF処理には使わない。PDFiumの公開APIにアクセスする窓口を一つにし、構造タグの読取りも同じワーカーに閉じ込める。Qt WebEngine内蔵のPDFビューアは無効化する。Qt WebEngine自身の内部依存に含まれるPDFiumまで配布物から除去できるとは想定しない。

flowchart TB
  UI[Qt Quick Reader Shell] --> APP[Application Services]
  APP --> BROKER[Main Process / File Broker]
  BROKER --> PDF[Sandboxed PDFWorker / PDFium]
  BROKER --> ARCHIVE[Sandboxed ArchiveWorker]
  BROKER --> WEB[Qt WebEngine / Isolated Content]
  APP --> STORE[Config and State Store]
  PDF --> UI
  ARCHIVE --> BROKER
  BROKER --> ROOT[Document Scoped Resources]
  ROOT --> WEB

矢印は論理的な要求・応答を表す。PDFWorker・ArchiveWorkerは別OSプロセスであり、Qt WebEngineは独自のマルチプロセス構成を持つ。主プロセスから子プロセスを起動するだけではOSによるアクセス制限は成立しないため、07の隔離条件を別途満たす。

責務分割

層・要素 責務 保有しない責務
Reader Shell 本文領域、目次、一覧、ステータス、コマンド欄、アクセシブル名 形式固有の解析、任意ファイル読取り
Input Router モード・フォーカス・IMEを考慮したキー解釈、コマンド生成 PDFページ番号への直接変換
Document Controller セッション、遷移、位置、戻る/進む、エラーの統括 描画エンジンの内部API露出
Navigation Service アダプターの目次・見出し・リンクを共通モデルへ変換 見た目だけによる見出しの推測
Render Scheduler 可視域優先、先読み、取消し、キャッシュ、世代管理 ファイルの権限判定
Format Adapter PDF/HTML/EPUB固有の能力・位置・描画の変換 他形式の特例をUIへ要求すること
File Broker 開く操作で許可されたファイル、範囲読取り、仮想資源の提供 PDF/XML/HTML/画像の主プロセス内解析
PDFWorker PDFium初期化、文書解析、ページ描画、文字・構造・リンク抽出 外部通信、原本文書の書込み
ArchiveWorker ZIP検証・展開、EPUB XML解析、文書資源索引 任意パスへの書込み、外部実体参照
Web Content Host docスキーム、通信遮断、DOMナビゲーション、本文表示 アプリ全体の権限や設定へのアクセス
Settings / State Store 検証済み設定とローカル読書状態の保存 文書由来スクリプトの評価

依存の向きはUI→アプリケーション→抽象インターフェース。形式固有コードは抽象インターフェースを実装する。PDFium、WebEngine、OS APIはそれぞれの境界内へ閉じ込める。

文書を開く流れ

  1. UIがOSファイル選択または明示されたローカルパスをFile Brokerへ渡す。Brokerは通常ファイル・権限・実体パス・容量を確認する。
  2. 拡張子と先頭の限定的なシグネチャを照合する。ZIPとEPUBの詳細判定はArchiveWorkerで行う。HTMLは拡張子/MIMEと文字コード情報から扱い、文書本文を主プロセスで解釈しない。
  3. 新しいsessionIdとgenerationを発行する。既存の文書は新文書の入口検証が済むまで保持し、失敗時に元の位置へ戻れるようにする。
  4. PDFは読取り専用ハンドルまたは範囲読取りチャネルをPDFWorkerへ渡す。HTMLは選択ファイルの親ディレクトリを許可ルート候補にし、ZIP/EPUBは検証済みのセッション用資源集合を構築する。
  5. 最初に必要な本文と最低限のメタデータを要求する。全ページのサムネイル、全文字抽出、全ファイルのハッシュ計算が終わるまで本文表示を待たせない。
  6. 初期本文が表示できた時点でReadyへ移行し、目次・見出し・先読みを低優先で進める。準備途中の目次は「読込中」とし、「目次なし」と区別する。
  7. 新文書のコミット後に旧セッションを破棄し、旧要求・共有メモリ・一時資源を解放する。旧generationの応答は採用しない。

複数文書を常駐させない。切替中の旧文書保持は一時的な例外とし、メモリ圧迫時は最後の表示画像と復帰位置だけを保つ。

描画・スケジューリング

PDFiumのAPI呼出しはワーカー内で直列化する。複数スレッドから無保護で呼び出さない。最初はアクティブ文書につきPDFWorker一つとし、追加並列化は性能実測後の変更とする。PDFiumのスレッド条件は公開APIを参照する。

優先度は「新しい可視ページ→可視ページの高解像度化→移動方向の隣接ページ→逆方向→サムネイル→検索索引/構造抽出」。先読みはまず前後1ページまでとし、キャッシュ余裕とキー操作から調整する。解析中にUIスレッドを同期的に待たせない。

拡大したページは512×512デバイスピクセルのタイルを基本とし、外周に2ピクセルの描画余白を持たせて表示時に切り落とす。CropBox、回転、倍率、DPRを含む変換行列をタイルとリンク・文字の当たり判定で共有する。タイルの継ぎ目・端の欠落は08の必須試験で確認する。

倍率変更中は既存画像を暫定拡大し、新しい倍率で再描画する。旧倍率の応答が新しい画面を上書きしないようgenerationとrenderRevisionを検証する。リサイズだけでは全文書を再解析しない。

PDFの段階描画を利用できる処理は短い区間で取消しを確認する。中断不能なデコードや解析はワーカー監視の期限で扱い、UI側の取消し完了とワーカーの実処理終了を同一視しない。

キャッシュと資源管理

資源 方針 初期提案
PDF画像タイル バイト数基準LRU、可視タイル優先 256 MiB、設定可能
PDFページオブジェクト 現在・前後を保持し不要分を閉じる 前後1ページ
サムネイル パネル表示時に可視行から作る 64 MiB以内で画像予算と調整
WebEngine 文書セッション用off-the-record profile 永続Cookie・遠隔cacheなし
ZIP展開 安全検証済み専用ディレクトリ、一時資源 上限は03・07
読書状態 小さなJSON、画像や本文は保存しない 06を参照

PDFの画像キャッシュ予算はアプリ全体のRSS上限を意味しない。WebEngine、GPU、パーサー、一時バッファは別に消費するため、08で子プロセス込みの総使用量を測る。メモリ圧迫時は先読み停止→不可視キャッシュ解放→解像度抑制の通知→文書処理停止の順で対応する。

拡張の契約

新形式の追加はFormatAdapterの実装、型判定の登録、能力情報、位置型の追加、共通適合試験への登録で行う。UIは能力情報を見てページ一覧・見出し・検索の可否を決める。画面内へ形式名による条件分岐を散在させない。

キーはCommand Registry内の安定したcommandIdに対応する。新しい操作は同じ入口へ登録し、既定キーがない操作もコマンド欄から実行できる。設定ファイルはスキーマに定義された値だけを受け付ける。

初期版の拡張は配布元がビルド時に組み込むモジュールに限る。第三者の任意コードを読み込むプラグイン機構は将来設計とする。将来導入する場合も、文書がプラグインや設定を自動的に選択・実行することは許可しない。

主な依存とビルド境界

部分 採用案 管理単位
UI・共通基盤 Qt Core / Gui / Quick / Qml / Quick Controls、C++20 同一Qtリリース
HTML・EPUB本文 Qt WebEngine / WebEngineQuick Qtと整合したChromium依存
PDF PDFium公開C API、V8/XFA無効ビルドを基本 固定コミット・ビルドオプション
ZIP・XML 維持管理されているライブラリをArchiveWorkerへ組込み G0でZIP64・文字コード・制限設定を確認し固定
設定 TOML 1.0互換パーサー、独自スキーマ検証 parser版とschema_versionを別管理
IPC 長さ付きCBORメッセージと制御された共有バッファ protocolVersion

ZIP・TOML等のライブラリ名は、制限付き処理・ライセンス・更新頻度を確認してG0で固定する。ライブラリ選定未了でも、受け入れるデータと制限は03・05・06・07で固定する。