では、他のクライアントも検討してみませんか?子供向けの描画アプリを持っていて、その時点での描画の状態を保持するものを生成したいと考えているようです。
はっきり言って、XML はそれほど効率的ではありません。それはその目的ではありません。機械と人間の両方で読み取り可能、検証可能などです。
代わりに、そのキャンバスの状態を JSON でサーバーに送信するベースの Web ページはどうでしょうか<Canvas>
(バイト数が少なく、それらを構築する作業も少なくなります)。サーバーは、必要な地獄のライブラリ/言語で動作できます。多くの JSON->my-language ライブラリがあちこちに浮かんでいます。
PDF ライブラリの選択は、サーバーにインストールされているものによってのみ制限されます。また、読み書きをできるだけ少なくしたいとおっしゃいました。
最も効率的なセットアップは、キャンバスの変更 (イメージを含む) の影響を最小限に抑えるように調整された、読み取り専用の部分的な PDF を既にメモリにロードしておくことです。各セッションは、その部分的な PDF を複製し、JSON を PDF グラフィック コマンドに変換し、PDF を保存します。
PDF の構造的な変更を最小限に抑えるには、インライン画像を使用します。PDF に新しいオブジェクトがないということは、クロス リファレンス テーブルをまったく変更する必要がないことを意味します (フォントを追加するか、既存の画像を再利用するまで)。オブジェクト間に特定の量のスペースを埋め込んだ「ドキュメント情報」ディクショナリを作成して、バイト オフセットを変更せずに入力できるようにすることができます (外部参照テーブルを再計算する必要があります)。
ページサイズをいじる必要があるかもしれませんし、必要ないかもしれません...ここでは1ページについて話しているだけですよね?
したがって、PDFは次のようになります...
%%PDF-1.6
<3-4 random high order bytes to convince folks that we're a binary stream>
1 0 obj
<</Type/Catalog/Pages 2 0 R>>
endobj
2 0 obj
<</Type/Pages/Count 1/Kids[3 0 R]>>
endobj
3 0 obj
<</Type/Page/Contents 4 0 R/MediaBox[0 0 612 792]/Parent 2 0 R>>
endobj
5 0 obj
<</Type/DocInfo/Author() --<insert big whitespace gap here>--
/Title() --<ditto>--
/Subject() --<ditto>--
/Keywords() --<ditto>--
/Creator(My app's Name)
/Producer(My pdf library's name)
/CreationDate(encodedDateWhenThisTemplateWasBuilt) D:YYYYMMDDHHMMSS-timeZoneOffset
/ModDate() --<another, smaller whitespace gap>--
>>
4 0 obj
<</Filter/SeveralDifferentFiltersAvailable/Length --<byte length of the stream in this file>-->>
stream
そして、あなたのテンプレートはそこで止まります。同様の「PDF の終わり」テンプレートは、次のようになります。
endstream
endobj
xref
0 6
0000000000 65535 f
0000000010 00000 n
0000000025 00000 n
0000000039 00000 n
0000000097 00000 n
0000000050 00000 n
trailer
<</Root 1 0 R/Size 6/Info 5 0 R>>
startxref
--<some white space>--
%%EOF
最後の数字の列はすべて間違っています。最初の列は、その特定のオブジェクトのバイト オフセットです (そして、今はバイト数を数えることができません)。2 番目の列はほとんど無関係です。
PDF入力アプリは次のことを知る必要があります:
- 最初のテンプレート内に入力する予定のすべてのバイト オフセット。
- ちなみに、すべての「ドキュメント情報」フィールドはすべてオプションです。/Info キーとそれが指す辞書はオプションです。あなたが気にするなら、それらを引っ張ることができます。
- コンテンツ ストリームの /Length キー。これは、ストリーム自体のフィルター後のバイト長である必要があります。
- JSON を pdf 描画コマンドに変換する方法。少しごまかしたい場合は、iText [Sharp] の PdfContentByte クラスを使用し、その描画コマンドを使用して、完成したバイト ストリームを取得し、それを PDF に平手打ちすることができます。必ずインライン画像を使用してください。そうしないと、このスキーム全体が窓の外に出てしまいます。必要に応じて、同様に消化できる他のライブラリがおそらくあるでしょう。または、PDF の仕様を読んで、自分で作成することもできます。PDF のコンテンツ構文のかなり限定されたサブセットに固執することになります。
- ファイルの先頭からの単語「xref」のバイト オフセット。これを計算できます: LengthOfInitialTemplate + LengthOfContentStream + OffsetFromStartOf2ndTemplateTo'xref'.
- 「startxref」の下の行のバイト オフセット。これは、「xref」の事前に計算されたバイト オフセットを書き込む場所です。
それ以上の効率は得られません。テンプレートを一度読んだことがあります。一度必要なバイト オフセットを読み取り/計算します。