/// <summary>
    /// Parses a PolyQuadraticBezierSegment element.
    /// </summary>
    PolyQuadraticBezierSegment ParsePolyQuadraticBezierSegment()
    {
      Debug.Assert(this.reader.Name == "PolyQuadraticBezierSegment");
      PolyQuadraticBezierSegment seg = new PolyQuadraticBezierSegment();
      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 PolyQuadraticBezierSegment to the content stream.
    /// </summary>
    internal void WriteSegment(PolyQuadraticBezierSegment seg)
    {
#if true
      if (!DevHelper.FlattenPolyQuadraticBezierSegment)
      {
        int count = seg.Points.Count;
        PointStopCollection points = seg.Points;
        Point pt0 = this.currentPoint;
        for (int idx = 0; idx < count - 1; )
        {
          Point pt1 = points[idx++];
          Point pt2 = points[idx++];
          // Cannot believe it: I just guessed the formula and it works!
          WriteLiteral("{0:0.####} {1:0.####} {2:0.####} {3:0.####} {4:0.####} {5:0.####} c\n",
            pt1.X - (pt1.X - pt0.X) / 3, pt1.Y - (pt1.Y - pt0.Y) / 3,
            pt1.X + (pt2.X - pt1.X) / 3, pt1.Y + (pt2.Y - pt1.Y) / 3,
            pt2.X, pt2.Y);
          this.currentPoint = pt0 = pt2;
        }
      }
      else
      {
        PolyLineSegment lseg = WpfUtils.FlattenSegment(this.currentPoint, seg);
        WriteSegment(lseg);
      }
#else
      // TODO: Convert quadratic Bezier curve in cubic Bézier curve
      PolyLineSegment lseg = WpfUtils.FlattenSegment(this.currentPoint, seg);
      WriteSegment(lseg);
#endif
    }
    /// <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;
    }