Point GetNextPointFromCurveData(CurveStream curveStream) {
     return new Point(GetNextDoubleFromCurveData(curveStream), GetNextDoubleFromCurveData(curveStream));
 }
        double GetNextDoubleFromCurveData(CurveStream curveStream) {
            var a = curveStream.GetNextCurveStreamElement();
            if (a == null)
                Error("cannot parse curveData");

            var d = a as DoubleStreamElement;
            if (d == null)
                Error("cannot parse curveData");
// ReSharper disable PossibleNullReferenceException
            return d.Double;
// ReSharper restore PossibleNullReferenceException
        }
 void ProceedWithLines(Curve curve, CurveStream curveStream, ref Point currentPoint) {
     do {
         curve.AddSegment(new LineSegment(currentPoint, currentPoint = GetNextPointFromCurveData(curveStream)));
     } while (curveStream.PickNextCurveStreamElement() is DoubleStreamElement);
 }
        ICurve ReadEllepticalArc(CurveStream curveStream, ref Point currentPoint) {
            /*
            var rx = "A"+DoubleToString(ellipse.AxisA.Length);
            var ry = DoubleToString(ellipse.AxisB.Length);
            var xAxisRotation = DoubleToString(180*Point.Angle(new Point(1, 0), ellipse.AxisA)/Math.PI);
            var largeArcFlag = Math.Abs(ellipse.ParEnd - ellipse.ParStart) >= Math.PI ? "1" : "0";
            var sweepFlag = ellipse.ParEnd > ellipse.ParStart ? "1" : "0"; //it happens because of the y-axis orientation down in SVG
            var endPoint=PointToString(ellipse.End);
            return string.Join(" ", new[] {rx, ry, xAxisRotation, largeArcFlag, sweepFlag, endPoint});
            var endPoint = GetCurveDataPoint(curveStream);
             */
            var rx = GetNextDoubleFromCurveData(curveStream);
            var ry = GetNextDoubleFromCurveData(curveStream);
            var xAxisRotation = GetNextDoubleFromCurveData(curveStream)/180*Math.PI;
            var largeArcFlag = (int) GetNextDoubleFromCurveData(curveStream);
            var sweepFlag = (int) GetNextDoubleFromCurveData(curveStream);
            var endPoint = GetNextPointFromCurveData(curveStream);
            //figure out the transform to the circle
            //then solve this problem on the circle
            if (ApproximateComparer.Close(rx, 0) || ApproximateComparer.Close(ry, 0))
                Error("ellipseArc radius is too small");
            var yScale = rx/ry;
            var rotationMatrix = PlaneTransformation.Rotation(-xAxisRotation);
            var scaleMatrix = new PlaneTransformation(1, 0, 0, 0, yScale, 0);
            var transform = scaleMatrix*rotationMatrix;
            var start = transform*currentPoint;
            currentPoint = endPoint;
            var end = transform*endPoint;
            Point center;
            double startAngle;
            double endAngle;
            Point axisY;
            GetArcCenterAndAngles(rx, largeArcFlag, sweepFlag, start, end, out center, out startAngle, out endAngle,
                out axisY);
            var inverted = transform.Inverse;
            center = inverted*center;
            var rotation = PlaneTransformation.Rotation(xAxisRotation);
            var axisX = rotation*new Point(rx, 0);
            axisY = rotation*(axisY/yScale);
            var ret = new Ellipse(startAngle, endAngle, axisX, axisY, center);

            Debug.Assert(ApproximateComparer.Close(ret.End, endPoint));
            return ret;
        }
 void ReadEllepticalArc(Curve curve, CurveStream curveStream, ref Point currentPoint) {
     curve.AddSegment(ReadEllepticalArc(curveStream, ref currentPoint));
 }
 void AddCurveSegment(CurveStream curveStream, char c, Curve curve, ref Point currentPoint) {
     switch (c) {
         case 'M': //moveto
             currentPoint = GetNextPointFromCurveData(curveStream);
             break;
         case 'm': //relative moveto
             throw new NotImplementedException();
         case 'Z':
         case 'z': //closepath
             if (curve.Segments.Count == 0)
                 Error("the curve is too short");
             curve.AddSegment(new LineSegment(currentPoint, currentPoint = curve.Start));
             break;
         case 'L': //lineto
             ProceedWithLines(curve, curveStream, ref currentPoint);
             break;
         case 'l': //lineto relative
             throw new NotImplementedException();
         case 'H': //lineto horizontal
             throw new NotImplementedException();
         case 'h': //lineto horizontal relative
             throw new NotImplementedException();
         case 'V': //lineto vertical
             throw new NotImplementedException();
         case 'v': //lineto vertical relative
             throw new NotImplementedException();
         case 'C': //cubic Bezier
             ProceedWithCubicBeziers(curve, curveStream, ref currentPoint);
             break;
         case 'c': //cubic Bezier relative
             throw new NotImplementedException();
         case 'S': //cubic Bezier shorthand
             throw new NotImplementedException();
         case 's': //cubic Bezier relative shorthand
             throw new NotImplementedException();
         case 'Q': //quadratic Bezier
             throw new NotImplementedException();
         case 'q': //quadratic Bezier relative
             throw new NotImplementedException();
         case 'T': //quadratic Bezier shorthand
             throw new NotImplementedException();
         case 't': //quadratic Bezier relative shorthand
             throw new NotImplementedException();
         case 'A': //elleptical arc
             ReadEllepticalArc(curve, curveStream, ref currentPoint);
             break;
         case 'a': //eleptical arc relative
             throw new NotImplementedException();
         default:
             Error("unknown character " + c);
             break;
     }
 }
 ICurve ParseCurve(string curveData) {
     var curve = new Curve();
     var curveStream = new CurveStream(curveData);
     var currentPoint = new Point();
     do {
         var curveStreamElement = curveStream.GetNextCurveStreamElement();
         if (curveStreamElement == null)
             return curve;
         var charStreamElement = curveStreamElement as CharStreamElement;
         if (charStreamElement == null) {
             Error("wrong formatted curve string " + curveStreamElement);
             return null;
         }
         AddCurveSegment(curveStream, charStreamElement.Char, curve, ref currentPoint);
     } while (true);
 }