ObjectStreams.cs
// 
// このコードは、DioDocs for PDF のサンプルの一部として提供されています。
// © MESCIUS inc. All rights reserved.
// 
using System;
using System.IO;
using System.IO.Compression;
using System.Drawing;
using System.Collections.Generic;
using GrapeCity.Documents.Pdf;
using GrapeCity.Documents.Text;
using GrapeCity.Documents.Common;
using GCTEXT = GrapeCity.Documents.Text;
using GCDRAW = GrapeCity.Documents.Drawing;

namespace DsPdfWeb.Demos
{
    // SavePdfOptions.UseObjectStreamsプロパティの使用方法について。
    // PDFのサイズを縮小するデモです。
    //
    // サイズの削減は状況に応じて異なることに注意してください。
    // ソースのPDFの実際の内容について説明します。
    public class ObjectStreams
    {
        public int CreatePDF(Stream stream)
        {
            // 5 ページの最適化されていない PDF を作成します。
            var tmpInput = MakeInputFile();
            var fiInput = new FileInfo(tmpInput);

            // 新しい PDF を作成し、そこにソースのPDFをロードして最適化します。
            var tmpOutput = Path.GetTempFileName();
            var tmpDoc = new GcPdfDocument();
            using (var fs = File.OpenRead(tmpInput))
            {
                tmpDoc.Load(fs);
                // デフォルトでは、GcPdfDocumentはPDFを保存するときにCompressionLevel.Fastestを使用します。
                // PDFのサイズが重要な場合は、最適な圧縮レベルを使用する必要があります。
                tmpDoc.CompressionLevel = CompressionLevel.Optimal;
                // ストリームサイズを最小限に抑え、オブジェクトストリームを使用します。
                tmpDoc.Save(tmpOutput, new SavePdfOptions(SaveMode.Default, PdfStreamHandling.MinimizeSize, UseObjectStreams.Multiple));
            }
            var fiOutput = new FileInfo(tmpOutput);

            // 結果として得られる PDF の入力ファイルと出力ファイルのサイズを記録します。
            var doc = new GcPdfDocument();
            Common.Util.AddNote(String.Format(
                "PDF を保存する際に UseObjectStreams.Multiple オプションを使用すると、ほとんどの場合、生成されるファイルサイズが削減され、" +
                "場合によっては大幅に小さくなります。今回の例では、「大規模なドキュメント」サンプルによって生成されたPDFのサイズが {0:N0} バイトから " +
                "{1:N0} バイトに減少しました。これは、品質の劣化やPDFの表示速度の低下なしに実現しています。\n" +
                "UseObjectStreams.Single オプションを使用すると、さらに僅かに小さなPDFサイズを実現できますが、" +
                "その代わりに PDFビューアでの表示速度が遅くなる可能性があります。\n" +
                "これらの結果をローカル環境で再現するには、このサンプルをダウンロードして実行し、有効なライセンスキーを指定してください。\n" +
                "(ライセンスキーがない場合、読み込みが 5 ページまでに制限され、サイズ削減の効果が十分に得られない可能性があります。)\n" +
                "また、サンプルコードを修正して一時的な入力ファイルと出力ファイルを保持し、ファイルマネージャを使用してサイズを比較することもできます。",
                fiInput.Length, fiOutput.Length),
                doc.NewPage());
            doc.Save(stream);

            // 一時ファイルの削除
            File.Delete(tmpInput);
            File.Delete(tmpOutput);

            return doc.Pages.Count;
        }

        static string MakeInputFile()
        {
            // 生成するページ数
            const int N = Common.Util.LargeDocumentIterations;
            var start = Common.Util.TimeNow();
            var doc = new GcPdfDocument();
            // テキストを保持/フォーマットするための TextLayout を準備します。
            var tl = new TextLayout(72)
            {
                MaxWidth = doc.PageSize.Width,
                MaxHeight = doc.PageSize.Height,
                MarginAll = 72,
                FirstLineIndent = 36,
            };
            tl.DefaultFormat.Font = StandardFonts.Times;
            tl.DefaultFormat.FontSize = 12;
            // ドキュメントを生成します。
            for (int pageIdx = 0; pageIdx < N; ++pageIdx)
            {
                tl.Append(Common.Util.LoremIpsum(1));
                tl.PerformLayout(true);
                doc.NewPage().Graphics.DrawTextLayout(tl, PointF.Empty);
                tl.Clear();
            }
            // タイトル ページを挿入します (StartDoc/EndDoc を使用している場合は実行できません)。
            tl.FirstLineIndent = 0;
            var fnt = GCTEXT.Font.FromFile(Path.Combine("Resources", "Fonts", "yumin.ttf"));
            var tf0 = new TextFormat() { Font = fnt, FontSize = 24, FontBold = true };
            tl.Append(string.Format("Large Document\n{0} Pages of Lorem Ipsum\n\n", N), tf0);
            var tf1 = new TextFormat(tf0) { FontSize = 14, FontItalic = true };
            tl.Append(string.Format("Generated on {0} in {1:m\\m\\ s\\s\\ fff\\m\\s}.", Common.Util.TimeNow().ToString("R"), Common.Util.TimeNow() - start), tf1);
            tl.TextAlignment = TextAlignment.Center;
            tl.PerformLayout(true);
            doc.Pages.Insert(0).Graphics.DrawTextLayout(tl, PointF.Empty);

            // 結果の PDF を UseObjectStreams.None (デフォルト) を使用して一時ファイルに保存します。
            var outFn = Path.GetTempFileName();
            doc.Save(outFn, new SavePdfOptions(SaveMode.Default, PdfStreamHandling.Copy, UseObjectStreams.None));
            return outFn;
        }
    }
}