OptimizeFonts.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;

namespace DsPdfWeb.Demos
{
    // このサンプルでは、GcPdfDocument.OptimizeFonts() メソッドを使用して、重複するフォントを統合し、
    // 使用されていない埋め込みフォントを削除することにより、PDF のサイズを縮小する方法を紹介します。
    //
    // サンプルでは、PDF の最初の5ページを抽出し、それらのページを1つの新しいドキュメントに結合しています。
    // 各ページには独自のフォントが埋め込まれているため、作成された PDF には不要なフォントデータが含まれ、
    // ファイルサイズが過大になってしまいます。
    // サンプルでは、結合された PDF のサイズを記録し、その PDF に対して OptimizeFonts() を実行し、
    // 最適化後の PDF のサイズも記録します。この結果は、サンプルで生成した PDF に出力されており、
    // OptimizeFonts() を実行した効果を確認いただけます。
    //
    // なお、このサンプルで最適化される PDF は結果がわかりやすくなるよう多少工夫されていますが、
    // 実際のアプリケーションでも同様の PDF を処理することが考えられます。
    // OptimizeFonts() メソッドは、そのような PDF のサイズを(時には大幅に)減少させることができます。
    // ただ、実際の結果は異なることがあります。
    public class OptimizeFonts
    {
        public int CreatePDF(Stream stream)
        {
            // 5ページの最適化されていない PDF を作成します。
            var srcFn = Path.Combine("Resources", "PDFs", "CompleteJavaScriptBook.pdf");
            var tmpInput = MakeInputFile(srcFn);
            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.OptimizeFonts();
                tmpDoc.Save(tmpOutput);
            }
            var fiOutput = new FileInfo(tmpOutput);

            // 結果の PDF に最適化前と最適化後のファイルサイズを記録します。
            var doc = new GcPdfDocument();
            Common.Util.AddNote(String.Format(
                "GcPdfDocument.OptimizeFonts() メソッドを使用して、重複するフォントを統合し、使用されていない埋め込みフォントを削除することにより、" +
                "5ページの PDF のサイズを {0:N0} バイトから {1:N0} バイトに縮小できました。\n" +
                "この結果をローカルで再現するには、このサンプルをダウンロードして実行してください。また、サンプルコードを修正して、最適化されていないファイルと" +
                "最適化されたファイルを保存し、ファイルマネージャーを使用してそのサイズを比較することもできます。", fiInput.Length, fiOutput.Length),
                doc.NewPage());
            doc.Save(stream);

            // クリーンアップを行います。
            File.Delete(tmpInput);
            File.Delete(tmpOutput);

            return doc.Pages.Count;
        }

        static string MakeInputFile(string inFn)
        {
            var indoc = new GcPdfDocument();
            using var fs = File.OpenRead(inFn);
            indoc.Load(fs);

            // 元の PDF の最初の5ページから5つの PDF を作成します。
            var pageCount = 5;
            var docs = new List<GcPdfDocument>(pageCount);
            for (int i = 0; i < pageCount; ++i)
            {
                var outdoc = new GcPdfDocument();
                outdoc.MergeWithDocument(indoc, new MergeDocumentOptions() { PagesRange = new OutputRange(i + 1, i + 1) });
                docs.Add(outdoc);
            }
            // 5つの PDF を1つの PDF に結合します。
            var doc = new GcPdfDocument();
            foreach (var d in docs)
                doc.MergeWithDocument(d);

            // 出来上がった PDF を一時ファイルに保存します。
            var outFn = Path.GetTempFileName();
            doc.Save(outFn);
            return outFn;
        }
    }
}