2011年4月30日土曜日

iTextで移動先の設定する方法

PDF間で特定の位置にリンクする場合、移動先名を設定しないとできません。

iTextで作成する場合、PdfDestinationで飛び先の位置を設定を予め作成したあとにそれぞれのページに追加します。 PdfContentByteもしくはPdfWriterのどちらかから追加できます。また一括でAddNamedDestinationsを使って一括に登録することが可能です。

次は新規文書に移動先を設定する例です。

using System;
using System.Drawing;
using iTextSharp.text;
using iTextSharp.text.pdf;
 
namespace ConsoleApplication1
{
    class Program
    {
        const float pt2mm = 72f / 25.4f;
 
        static void Main(string[] args)
        {
            string savePdf = "hogehoge.pdf";
            string loadPdf = "fugafuga.pdf";
 
            // 新規から作成
            string outputPath = @"hogehoge.pdf";
            Document pdoc = new Document(PageSize.A4);
            PdfWriter pw = PdfWriter.GetInstance(pdoc, new FileStream(outputPath, FileMode.Create));

            // 移動先の場所を設定
            PdfDestination dest = new PdfDestination(PdfDestination.XYZ, 105 * pt2mm, 148.5F * pt2mm, 0);
            
            // コンテンツの書き出し
            pdoc.Open();
            PdfContentByte pcb = pw.DirectContent;
            pcb.LocalDestination("name1", dest);        // 移動先名の作成
            Paragraph p = new Paragraph("Hello World");
            pdoc.Add(p);
            pcb.ClosePath();

            pdoc.NewPage();

            pw.AddNamedDestination("name2", 2, dest);   // 移動先名の作成
            pcb.ClosePath();
            pdoc.Close();
        }
    }
}

だが既存のPDFに追加する場合、新規から作成する場合と同じ設定を行ってもバグなのか分からないが追加することはできません。

仕方が無いので直接命令を書き込みます。
移動先の設定はCatalog→Names→Dests→Namesで取得できます。

PdfReader pdf = new PdfReader(@"hogehoge.pdf");
PdfDictionary root = pdf.Catalog;
PdfDictionary pDests = root.GetAsDict(PdfName.NAMES).GetAsDict(PdfName.DESTS);
PdfArray pDestNames = pDests.GetAsArray(PdfName.NAMES);
if (pDestNames == null)
{
    // 移動先の設定がない場合、作成する
    pDests.Put(PdfName.NAMES, new PdfArray());
    pDestNames = pDests.GetAsArray(PdfName.NAMES);
}

配列に移動先名、移動先の設定の順番に書き込みます。

PdfDestination dest = new PdfDestination(PdfDestination.XYZ, 0, 0, 0);
dest.AddPage(pdf.GetPageOrigRef(1));
pDestNames.Add(new PdfString("name1"));
pDestNames.Add(dest);

まとめると次のとおりになります。

using System;
using System.Drawing;
using iTextSharp.text;
using iTextSharp.text.pdf;
 
namespace ConsoleApplication1
{
    class Program
    {
        const float pt2mm = 72f / 25.4f;
 
        static void Main(string[] args)
        {
            string sourcePdf = @"hogehoge.pdf";
            string outputPath = @"fugafuga.pdf";

            PdfReader pdf = new PdfReader(sourcePdf);
            PdfStamper stamper = new PdfStamper(pdf, new FileStream(outputPath, FileMode.Create));

            // 既存PDFにあれこれ追加
            PdfContentByte cb = stamper.GetUnderContent(1);
            cb.BeginText();
            cb.SetFontAndSize(BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.WINANSI, BaseFont.EMBEDDED), 18);
            cb.ShowTextAligned(Element.ALIGN_LEFT, "Sample", 30, 600, 0);
            cb.EndText();

            // 移動先の生成
            PdfDestination dest = new PdfDestination(PdfDestination.XYZ, 0, 0, 0);
            if (dest.HasPage())
                dest.ArrayList[0] = pdf.GetPageOrigRef(2);
            else
                dest.AddPage(pdf.GetPageOrigRef(2));

            // 移動先を設定
            PdfDictionary root = pdf.Catalog;
            PdfDictionary pDests = root.GetAsDict(PdfName.NAMES).GetAsDict(PdfName.DESTS);
            PdfArray pDestNames = pDests.GetAsArray(PdfName.NAMES);
            if (pDestNames == null)
            {
                pDests.Put(PdfName.NAMES, new PdfArray());
                pDestNames = pDests.GetAsArray(PdfName.NAMES);
            }
            pDestNames.Add(new PdfString("name"));
            pDestNames.Add(dest);

            stamper.Close();
            pdf.Close();
        }
    }
}

0 件のコメント:

コメントを投稿