/// <summary>
    /// Parses a PolyLineSegment element.
    /// </summary>
    PolyLineSegment ParsePolyLineSegment()
    {
      Debug.Assert(this.reader.Name == "PolyLineSegment");
      PolyLineSegment seg = new PolyLineSegment();
      while (MoveToNextAttribute())
      {
        switch (this.reader.Name)
        {
          case "IsStroked":
            seg.IsStroked = ParseBool(this.reader.Value);
            break;

          case "Points":
            seg.Points = Point.ParsePoints(this.reader.Value);
            break;

          default:
            UnexpectedAttribute(this.reader.Name);
            break;
        }
      }
      MoveBeyondThisElement();
      return seg;
    }
    /// <summary>
    /// Writes the specified PolyLineSegment to the content stream.
    /// </summary>
    void WriteSegment(PolyLineSegment seg)
    {
#if DEBUG_
      // WPF uses zero lengh rounded line to draw circles. These circles PDF renders without antializing (Acrobat 8.1)
      // TODO: Bug in Acrobat or rendering issue?
      if (seg.Points.Count == 1)
      {
        if (seg.Points[0] == this.currentPoint)
          seg.Points[0] = new Point(this.currentPoint.X + 10, this.currentPoint.Y);
      }
#endif
      foreach (Point point in seg.Points)
      {
        WriteLiteral("{0:0.###} {1:0.###} l\n", point.X, point.Y);
        this.currentPoint = point;
      }
    }
    /// <summary>
    /// Parses a PathGeometry from a data string element.
    /// </summary>
    PathGeometry ParsePathGeometry(string data)
    {
#if DEBUG_
      // XPS = M 20,100 C 45,50 70,150 95,100 S 145,150 170,100 220,150 245,100 C 220,50 195,150 170,100 S 120,150 95,100 45,150 20,100
      // XXX = M20,100C45,50 70,150 95,100 120,50 145,150 170,100 195,50 220,150 245,100 220,50 195,150 170,100 145,50 120,150 95,100 70,50 45,150 20,100
      if (data.StartsWith("M 20,100 C 45,50 70,150 95,100 S 145,"))
        Debugger.Break();
#endif
      PathGeometry geo = TryParseStaticResource<PathGeometry>(data);
      if (geo != null)
        return geo;

      data = FixHack(data);
      // From the algorithm on page 365 in XPS 1.0 specs
      // See Petzold page 813
      geo = new PathGeometry();
      Point point = new Point();
      PathFigure figure = null;
      TokenizerHelper helper = new TokenizerHelper(data);
      helper.NextTokenRequired();
      do
      {
        string token = helper.GetCurrentToken();
        switch (token[0])
        {
          // FillRule
          case 'F':
            geo.FillRule = helper.NextTokenRequired() == "1" ? FillRule.NonZero : FillRule.EvenOdd;
            break;

          // Move 
          case 'M':
            {
              figure = new PathFigure();
              geo.Figures.Add(figure);
              point = new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired()));
              figure.StartPoint = point;
            }
            break;

          // Move 
          case 'm':
            {
              figure = new PathFigure();
              geo.Figures.Add(figure);
              point = new Point(point.X + ParseDouble(helper.NextTokenRequired()), point.Y + ParseDouble(helper.NextTokenRequired()));
              figure.StartPoint = point;
            }
            break;

          // Line 
          case 'L':
            {
              PolyLineSegment seg;
              int segCount = figure.Segments.Count;
              if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyLineSegment) != null)
              { }
              else
              {
                seg = new PolyLineSegment();
                figure.Segments.Add(seg);
              }
              do
              {
                point = new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired()));
                seg.Points.Add(point);
              } while (!Char.IsLetter(helper.PeekNextCharacter()));
            }
            break;

          // Line 
          case 'l':
            {
              PolyLineSegment seg;
              int segCount = figure.Segments.Count;
              if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyLineSegment) != null)
              { }
              else
              {
                seg = new PolyLineSegment();
                figure.Segments.Add(seg);
              }
              do
              {
                point = new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired()));
                seg.Points.Add(point);
              } while (!Char.IsLetter(helper.PeekNextCharacter()));
            }
            break;

          // Horizontal Line 
          case 'H':
            {
              PolyLineSegment seg;
              int segCount = figure.Segments.Count;
              if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyLineSegment) != null)
              { }
              else
              {
                seg = new PolyLineSegment();
                figure.Segments.Add(seg);
              }
              do
              {
                point.X = ParseDouble(helper.NextTokenRequired());
                seg.Points.Add(point);
              } while (!Char.IsLetter(helper.PeekNextCharacter()));
            }
            break;

          // Horizontal Line 
          case 'h':
            {
              PolyLineSegment seg;
              int segCount = figure.Segments.Count;
              if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyLineSegment) != null)
              { }
              else
              {
                seg = new PolyLineSegment();
                figure.Segments.Add(seg);
              }
              do
              {
                point.X += ParseDouble(helper.NextTokenRequired());
                seg.Points.Add(point);
              } while (!Char.IsLetter(helper.PeekNextCharacter()));
            }
            break;

          // Vertical Line 
          case 'V':
            {
              PolyLineSegment seg;
              int segCount = figure.Segments.Count;
              if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyLineSegment) != null)
              { }
              else
              {
                seg = new PolyLineSegment();
                figure.Segments.Add(seg);
              }
              do
              {
                point.Y = ParseDouble(helper.NextTokenRequired());
                seg.Points.Add(point);
              } while (!Char.IsLetter(helper.PeekNextCharacter()));
            }
            break;

          // Vertical Line 
          case 'v':
            {
              PolyLineSegment seg;
              int segCount = figure.Segments.Count;
              if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyLineSegment) != null)
              { }
              else
              {
                seg = new PolyLineSegment();
                figure.Segments.Add(seg);
              }
              do
              {
                point.Y += ParseDouble(helper.NextTokenRequired());
                seg.Points.Add(point);
              } while (!Char.IsLetter(helper.PeekNextCharacter()));
            }
            break;

          // Elliptical Arc
          case 'A':
            do
            {
              // I cannot believe it: "A70.1,50.1 1,34 0 0 170.1,30.1"
              // The rotation angle "1,34" uses a ',' instead of a '.' in my German Windows Vista!
              //A70.1,50.1    1,34   0   0   170.1,30.1
              ArcSegment seg = new ArcSegment();
              figure.Segments.Add(seg);
              seg.Size = new Size(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired()));
              seg.RotationAngle = ParseDouble(helper.NextTokenRequired());
              seg.IsLargeArc = helper.NextTokenRequired() == "1";
              seg.SweepDirection = helper.NextTokenRequired() == "1" ? SweepDirection.Clockwise : SweepDirection.Counterclockwise;
              point = new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired()));
              seg.Point = point;
            } while (!Char.IsLetter(helper.PeekNextCharacter()));
            break;

          // Elliptical Arc
          case 'a':
            do
            {
              ArcSegment seg = new ArcSegment();
              figure.Segments.Add(seg);
              seg.Size = new Size(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired()));
              seg.RotationAngle = ParseDouble(helper.NextTokenRequired());
              seg.IsLargeArc = helper.NextTokenRequired() == "1";
              seg.SweepDirection = helper.NextTokenRequired() == "1" ? SweepDirection.Clockwise : SweepDirection.Counterclockwise;
              point = new Point(point.X + ParseDouble(helper.NextTokenRequired()), point.Y + ParseDouble(helper.NextTokenRequired()));
              seg.Point = point;
            } while (!Char.IsLetter(helper.PeekNextCharacter()));
            break;

          // Cubic Bézier Curve
          case 'C':
            {
              PolyBezierSegment seg;
              int segCount = figure.Segments.Count;
              if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyBezierSegment) != null)
              { }
              else
              {
                seg = new PolyBezierSegment();
                figure.Segments.Add(seg);
              }
              do
              {
                seg.Points.Add(new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired())));
                seg.Points.Add(new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired())));
                point = new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired()));
                seg.Points.Add(point);
              } while (!Char.IsLetter(helper.PeekNextCharacter()));
            }
            break;

          // Cubic Bézier Curve
          case 'c':
            {
              PolyBezierSegment seg;
              int segCount = figure.Segments.Count;
              if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyBezierSegment) != null)
              { }
              else
              {
                seg = new PolyBezierSegment();
                figure.Segments.Add(seg);
              }
              do
              {
                seg.Points.Add(new Point(point.X + ParseDouble(helper.NextTokenRequired()), point.Y + ParseDouble(helper.NextTokenRequired())));
                seg.Points.Add(new Point(point.X + ParseDouble(helper.NextTokenRequired()), point.Y + ParseDouble(helper.NextTokenRequired())));
                point = new Point(point.X + ParseDouble(helper.NextTokenRequired()), point.Y + ParseDouble(helper.NextTokenRequired()));
                seg.Points.Add(point);
              } while (!Char.IsLetter(helper.PeekNextCharacter()));
            }
            break;

          // Smooth Cubic Bézier Curve
          case 'S':
            {
              PolyBezierSegment seg;
              int segCount = figure.Segments.Count;
              if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyBezierSegment) != null)
              { }
              else
              {
                seg = new PolyBezierSegment();
                figure.Segments.Add(seg);
              }
              do
              {
                Point pt = new Point();
                int count = seg.Points.Count;
                segCount = figure.Segments.Count;
                if (count > 0)
                {
                  Point lastCtrlPoint = seg.Points[count - 2];
                  pt.X = 2 * point.X - lastCtrlPoint.X;
                  pt.Y = 2 * point.Y - lastCtrlPoint.Y;
                }
                else if (segCount > 1 && figure.Segments[count - 2] is PolyBezierSegment)
                {
                  PolyBezierSegment lastSeg = (PolyBezierSegment)figure.Segments[count - 2];
                  count = lastSeg.Points.Count;
                  Point lastCtrlPoint = lastSeg.Points[count - 2];
                  pt.X = 2 * point.X - lastCtrlPoint.X;
                  pt.Y = 2 * point.Y - lastCtrlPoint.Y;
                }
                else
                {
                  pt = point;
                }
                seg.Points.Add(pt);
                seg.Points.Add(new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired())));
                point = new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired()));
                seg.Points.Add(point);
              } while (!Char.IsLetter(helper.PeekNextCharacter()));
            }
            break;

          // Smooth Cubic Bézier Curve
          case 's':
            {
              PolyBezierSegment seg;
              int segCount = figure.Segments.Count;
              if (segCount > 0 && (seg = figure.Segments[segCount - 1] as PolyBezierSegment) != null)
              { }
              else
              {
                seg = new PolyBezierSegment();
                figure.Segments.Add(seg);
              }
              do
              {
                Point pt = new Point();
                int count = seg.Points.Count;
                segCount = figure.Segments.Count;
                if (count > 0)
                {
                  Point lastCtrlPoint = seg.Points[count - 2];
                  pt.X = 2 * point.X - lastCtrlPoint.X;
                  pt.Y = 2 * point.Y - lastCtrlPoint.Y;
                }
                else if (segCount > 1 && figure.Segments[count - 2] is PolyBezierSegment)
                {
                  PolyBezierSegment lastSeg = (PolyBezierSegment)figure.Segments[count - 2];
                  count = lastSeg.Points.Count;
                  Point lastCtrlPoint = lastSeg.Points[count - 2];
                  pt.X = 2 * point.X - lastCtrlPoint.X;
                  pt.Y = 2 * point.Y - lastCtrlPoint.Y;
                }
                else
                {
                  pt = point;
                }
                seg.Points.Add(pt);
                seg.Points.Add(new Point(point.X + ParseDouble(helper.NextTokenRequired()), point.Y + ParseDouble(helper.NextTokenRequired())));
                point = new Point(point.X + ParseDouble(helper.NextTokenRequired()), point.Y + ParseDouble(helper.NextTokenRequired()));
                seg.Points.Add(point);
              } while (!Char.IsLetter(helper.PeekNextCharacter()));
            }
            break;

          // Quadratic Bézier Curve
          case 'Q':
            {
              PolyQuadraticBezierSegment seg = new PolyQuadraticBezierSegment();
              figure.Segments.Add(seg);
              do
              {
                seg.Points.Add(new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired())));
                point = new Point(ParseDouble(helper.NextTokenRequired()), ParseDouble(helper.NextTokenRequired()));
                seg.Points.Add(point);
              } while (!Char.IsLetter(helper.PeekNextCharacter()));
            }
            break;

          // Quadratic Bézier Curve
          case 'q':
            {
              PolyQuadraticBezierSegment seg = new PolyQuadraticBezierSegment();
              figure.Segments.Add(seg);
              do
              {
                seg.Points.Add(new Point(point.X + ParseDouble(helper.NextTokenRequired()), point.Y + ParseDouble(helper.NextTokenRequired())));
                point = new Point(point.X + ParseDouble(helper.NextTokenRequired()), point.Y + ParseDouble(helper.NextTokenRequired()));
                seg.Points.Add(point);
              } while (!Char.IsLetter(helper.PeekNextCharacter()));
            }
            break;

          // Close
          case 'Z':
          case 'z':
            {
              figure.IsClosed = true;
              if (figure.Segments.Count > 0)
              {
                PathSegment seg = figure.Segments[0];
              }
              point = figure.StartPoint;
              figure = null;
            }
            break;

          default:
            Debug.Assert(false);
            break;
        }
      } while (helper.NextToken());
      return geo;
    }