在PDF中绘制GraphicsPath

时间:2014-09-11 20:48:38

标签: itextsharp gdi+ graphicspath

我正在尝试根据我在C#应用程序中使用的一些矢量艺术来创建PDF。当我尝试从GraphicsPath映射点和类型时,我遇到两个主要问题。

  1. 有些路径很简单。
  2. 当子路径是内部边界时,我需要以某种方式指示。即,填写字母d中的圆圈。
  3. 我在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);
            }
        }
    }
    

1 个答案:

答案 0 :(得分:1)

我正在给自己发一个答案,以防其他人需要一个简单的函数在iTextSharp中绘制一个GraphicsPath。我在问题中的示例代码遇到了两个问题:

  1. 正如mkl指出我试图经常填写
  2. 我没注意到PathPointType.Line是PathPointType.Bezier中的有效掩码,所以代码在曲线后面将一行放回原点。
  3. 更新代码:

    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);
            }
        }
    }