1

C# アプリケーションにあるベクター アートに基づいて PDF を作成しようとしています。GraphicsPath からポイントとタイプをマッピングしようとすると、2 つの大きな問題があります。

  1. 一部のパスは単に欠落しています。
  2. サブパスが内部境界である場合、何らかの方法でそれを示す必要があります。つまり、文字 d の円が塗りつぶされます。

NuGet で iTextSharp 5.5.2 を参照しています。ここでは AddString のみを使用しています。これは、この例で複雑なパスを作成する簡単な方法を示すためです。私の必要に応じて、パスを使用して PDF にテキストを配置しません。

using iTextSharp.text;
using iTextSharp.text.pdf;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PdfGen
{
    class StackQuestion
    {
        public static void Main()
        {
            string filename = @"d:\itext.pdf";
            using (var doc = new Document())
            using (var fs = new FileStream(filename, FileMode.Create))
            {
                var writer = PdfWriter.GetInstance(doc, fs);
                doc.Open();
                writer.DirectContent.SetColorFill(BaseColor.BLACK);
                var path = new GraphicsPath(FillMode.Winding);
                path.AddString("Hello World", FontFamily.GenericSerif, 
                    (int)FontStyle.Regular, 25f, RectangleF.Empty, 
                    StringFormat.GenericDefault);
                AddPath(path, writer.DirectContent);
                doc.Close();
            }
            System.Diagnostics.Process.Start(filename);
        }

        static void AddPath(GraphicsPath path, PdfContentByte to)
        {
            var view = to.PdfDocument.PageSize;
            path.FillMode = System.Drawing.Drawing2D.FillMode.Winding;
            var d = path.PathData;
            for (int i = 0; i < d.Points.Length && i < d.Types.Length; i++)
            {
                var t = (PathPointType)d.Types[i];
                var p = Fix(d.Points[i], view);
                if (Match(t, PathPointType.Bezier))
                {
                    var p2 = Fix(d.Points[++i], view);
                    if (d.Types.Length > i + 1 && 
                        Match((PathPointType)d.Types[i + 1], 
                            PathPointType.Bezier3))
                    {
                        var p3 = Fix(d.Points[++i], view);
                        to.CurveTo(p.X, p.Y, p2.X, p2.Y, p3.X, p3.Y);
                    }
                    else
                    {
                        to.CurveTo(p.X, p.Y, p2.X, p2.Y);
                    }
                }
                if (Match(t, PathPointType.Line))
                {
                    to.LineTo(p.X, p.Y);
                }
                if (Match(t, PathPointType.CloseSubpath))
                {
                    to.ClosePath();
                    to.EoFill();
                }
                if (t == PathPointType.Start)
                {
                    to.NewPath();
                    to.MoveTo(p.X, p.Y);
                }
            }
        }

        static bool Match(PathPointType type, PathPointType match)
        {
            return (type & match) == match;
        }

        static System.Drawing.PointF Fix(System.Drawing.PointF pt, 
            iTextSharp.text.Rectangle view)
        {
            return new System.Drawing.PointF(pt.X, view.Height - pt.Y);
        }
    }
}
4

1 に答える 1

1

他の誰かが iTextSharp で GraphicsPath をプロットするための簡単な関数を必要としている場合に備えて、私は自分自身に答えを投稿しています。質問のサンプル コードには 2 つの問題がありました。

  1. mklが指摘したように、私はあまりにも頻繁に埋めようとしていた
  2. PathPointType.Line が PathPointType.Bezier の有効なマスクであることを認識できなかったため、曲線の後に線を原点に戻すコードです。

更新コード:

using iTextSharp.text;
using iTextSharp.text.pdf;
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;

namespace PdfGen
{
    class StackQuestion
    {
        public static void Main()
        {
            string filename = @"d:\itext.pdf";
            using (var doc = new Document())
            using (var fs = new FileStream(filename, FileMode.Create))
            {
                var writer = PdfWriter.GetInstance(doc, fs);
                doc.Open();
                writer.DirectContent.SetColorFill(BaseColor.BLACK);
                var path = new GraphicsPath(FillMode.Winding);
                path.AddString("Hello World", FontFamily.GenericSansSerif,
                    (int)FontStyle.Regular, 90f, PointF.Empty,
                    StringFormat.GenericDefault);
                AddPath(path, writer.DirectContent);
                writer.DirectContent.EoFill();
                doc.Close();
            }
            System.Diagnostics.Process.Start(filename);
        }

        static void AddPath(GraphicsPath path, PdfContentByte to)
        {
            var view = to.PdfDocument.PageSize;
            var d = path.PathData;
            to.NewPath();
            PointF? start = null;
            for (int i = 0; i < d.Points.Length && i < d.Types.Length; i++)
            {
                var t = (PathPointType)d.Types[i];
                var p = Fix(d.Points[i], view);
                if (Match(t, PathPointType.Bezier))
                {
                    var p2 = Fix(d.Points[++i], view);
                    if (d.Types.Length > i + 1 &&
                        Match((PathPointType)d.Types[i + 1],
                            PathPointType.Bezier))
                    {
                        var p3 = Fix(d.Points[++i], view);
                        to.CurveTo(p.X, p.Y, p2.X, p2.Y, p3.X, p3.Y);
                    }
                    else
                    {
                        to.CurveTo(p.X, p.Y, p2.X, p2.Y);
                    }
                }
                else if (Match(t, PathPointType.Line))
                {
                    to.LineTo(p.X, p.Y);
                }
                if (Match(t, PathPointType.CloseSubpath))
                {
                    if (start != null)
                        to.LineTo(start.Value.X, start.Value.Y);
                    start = null;
                    to.ClosePath();
                }
                if (t == PathPointType.Start)
                {
                    if (start != null)
                        to.LineTo(start.Value.X, start.Value.Y);
                    start = p;
                    to.MoveTo(p.X, p.Y);
                }
            }
        }

        static bool Match(PathPointType type, PathPointType match)
        {
            return (type & match) == match;
        }

        static System.Drawing.PointF Fix(System.Drawing.PointF pt,
            iTextSharp.text.Rectangle view)
        {
            return new System.Drawing.PointF(pt.X, view.Height - pt.Y);
        }
    }
}
于 2014-09-12T14:26:18.690 に答える