title: Draw a GraphicsPath in a PDF
body: <p>I am trying to create a PDF based on some vector art I have in my C# application.  I have two major problems when I try to map the points and types from a GraphicsPath. </p>
  
  <ol>
  <li>Some paths are just plain missing.</li>
  <li>When a sub path is an internal boundary I need to indicate that somehow.  ie, the circle in the letter d is filled in.</li>
  </ol>
  
  <p>I'm referencing iTextSharp 5.5.2 on NuGet.  I'm only using AddString here because I want an easy way to demonstrate creating a complex path in this example.  For my need I won't be using a path to place text in the PDF.</p>
  
  <pre><code>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 &lt; d.Points.Length &amp;&amp; i &lt; 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 &gt; i + 1 &amp;&amp; 
                          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 &amp; 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);
          }
      }
  }
  </code></pre>