Inheritance: SvgPathSeg
Ejemplo n.º 1
0
        public List <SvgPathSeg> Parse(char[] pathDataBuffer)
        {
            //parse pathdata to pathsegments
            List <SvgPathSeg> pathSegments = new List <SvgPathSeg>();
            List <float>      numbers      = new List <float>();
            int j            = pathDataBuffer.Length;
            int currentState = 0;

            for (int i = 0; i < j;)
            {
                //lex and parse
                char c = pathDataBuffer[i];
                switch (currentState)
                {
                case 0:
                {
                    //init state
                    switch (c)
                    {
                    case 'M':
                    case 'm':
                    {
                        //move to
                        ParseNumberList(pathDataBuffer, i + 1, out i, numbers);
                        if (numbers.Count == 2)
                        {
                            var moveTo = new SvgPathSegMoveTo(
                                numbers[0],
                                numbers[1]);
                            moveTo.IsRelative = c == 'm';
                            pathSegments.Add(moveTo);
                        }
                        else
                        {                  //error
                            throw new NotSupportedException();
                        }
                        numbers.Clear();                //reset
                    }
                    break;

                    case 'L':
                    case 'l':
                    {
                        //line to
                        ParseNumberList(pathDataBuffer, i + 1, out i, numbers);
                        if (numbers.Count == 2)
                        {
                            var lineTo = new SvgPathSegLineTo(
                                numbers[0], numbers[1]);
                            lineTo.IsRelative = c == 'l';
                            pathSegments.Add(lineTo);
                        }
                        else
                        {                  //error
                            throw new NotSupportedException();
                        }
                        numbers.Clear();                //reset
                    }
                    break;

                    case 'H':
                    case 'h':
                    {
                        ParseNumberList(pathDataBuffer, i + 1, out i, numbers);
                        if (numbers.Count == 1)
                        {
                            var h = new SvgPathSegLineToHorizontal(
                                numbers[0]);
                            h.IsRelative = c == 'h';
                            pathSegments.Add(h);
                        }
                        else
                        {                  //error
                            throw new NotSupportedException();
                        }
                        numbers.Clear();                //reset
                    }
                    break;

                    case 'V':
                    case 'v':
                    {
                        ParseNumberList(pathDataBuffer, i + 1, out i, numbers);
                        if (numbers.Count == 1)
                        {
                            var v = new SvgPathSegLineToVertical(
                                numbers[0]);
                            v.IsRelative = c == 'v';
                            pathSegments.Add(v);
                        }
                        else
                        {                  //error
                            throw new NotSupportedException();
                        }
                        numbers.Clear();                //reset
                    }
                    break;

                    case 'Z':
                    case 'z':
                    {
                        pathSegments.Add(new SvgPathSegClosePath());
                        i++;
                    }
                    break;

                    case 'A':
                    case 'a':
                    {
                        ParseNumberList(pathDataBuffer, i + 1, out i, numbers);
                        if (numbers.Count == 7)
                        {
                            var arc = new SvgPathSegArc(
                                numbers[0], numbers[1],
                                numbers[2], (int)numbers[3], (int)numbers[4],
                                numbers[5], numbers[6]);
                            arc.IsRelative = c == 'a';
                            pathSegments.Add(arc);
                        }
                        else
                        {
                            throw new NotSupportedException();
                        }
                        numbers.Clear();
                    }
                    break;

                    case 'C':
                    case 'c':
                    {
                        ParseNumberList(pathDataBuffer, i + 1, out i, numbers);
                        if (numbers.Count == 6)
                        {
                            var squadCurve = new SvgPathSegCurveToCubic(
                                numbers[0], numbers[1],
                                numbers[2], numbers[3],
                                numbers[4], numbers[5]);
                            squadCurve.IsRelative = c == 'c';
                            pathSegments.Add(squadCurve);
                        }
                        else
                        {
                            throw new NotSupportedException();
                        }
                        numbers.Clear();
                    }
                    break;

                    case 'Q':
                    case 'q':
                    {
                        ParseNumberList(pathDataBuffer, i + 1, out i, numbers);
                        if (numbers.Count == 4)
                        {
                            var quadCurve = new SvgPathSegCurveToQuadratic(
                                numbers[0], numbers[1],
                                numbers[2], numbers[3]);
                            quadCurve.IsRelative = c == 'q';
                            pathSegments.Add(quadCurve);
                        }
                        else
                        {
                            throw new NotSupportedException();
                        }
                        numbers.Clear();
                    }
                    break;

                    case 'S':
                    case 's':
                    {
                        ParseNumberList(pathDataBuffer, i + 1, out i, numbers);
                        if (numbers.Count == 4)
                        {
                            var scubicCurve = new SvgPathSegCurveToCubicSmooth(
                                numbers[0], numbers[1],
                                numbers[2], numbers[3]);
                            scubicCurve.IsRelative = c == 's';
                            pathSegments.Add(scubicCurve);
                        }
                        else
                        {
                            throw new NotSupportedException();
                        }
                        numbers.Clear();
                    }
                    break;

                    case 'T':
                    case 't':
                    {
                        ParseNumberList(pathDataBuffer, i + 1, out i, numbers);
                        if (numbers.Count == 2)
                        {
                            var squadCurve = new SvgPathSegCurveToQuadraticSmooth(
                                numbers[0], numbers[1]);
                            squadCurve.IsRelative = c == 't';
                            pathSegments.Add(squadCurve);
                        }
                        else
                        {
                            throw new NotSupportedException();
                        }
                        numbers.Clear();
                    }
                    break;

                    default:
                    {
                    }
                    break;
                    }
                }
                break;

                default:
                {
                }
                break;
                }
            }
            return(pathSegments);
        }
Ejemplo n.º 2
0
        public static void MakeBezierCurveFromArc(ref PointF start,
            ref PointF end,
            float rx,
            float ry,
            float angle,
            SvgArcSize arcSize,
            SvgArcSweep arcSweep,
            out PointF[] bezier4Points)
        {
            double sinPhi = Math.Sin(angle * SvgPathSegArc.RAD_PER_DEG);
            double cosPhi = Math.Cos(angle * SvgPathSegArc.RAD_PER_DEG);
            double x1dash = cosPhi * (start.X - end.X) / 2.0 + sinPhi * (start.Y - end.Y) / 2.0;
            double y1dash = -sinPhi * (start.X - end.X) / 2.0 + cosPhi * (start.Y - end.Y) / 2.0;
            double root;
            double numerator = (rx * rx * ry * ry) - (rx * rx * y1dash * y1dash) - (ry * ry * x1dash * x1dash);
            if (numerator < 0.0)
            {
                float s = (float)Math.Sqrt(1.0 - numerator / (rx * rx * ry * ry));
                rx *= s;
                ry *= s;
                root = 0.0;
            }
            else
            {
                root = ((arcSize == SvgArcSize.Large && arcSweep == SvgArcSweep.Positive)
                    || (arcSize == SvgArcSize.Small && arcSweep == SvgArcSweep.Negative) ? -1.0 : 1.0) * Math.Sqrt(numerator / (rx * rx * y1dash * y1dash + ry * ry * x1dash * x1dash));
            }


            double cxdash = root * rx * y1dash / ry;
            double cydash = -root * ry * x1dash / rx;
            double cx = cosPhi * cxdash - sinPhi * cydash + (start.X + end.X) / 2.0;
            double cy = sinPhi * cxdash + cosPhi * cydash + (start.Y + end.Y) / 2.0;
            double theta1 = SvgPathSegArc.CalculateVectorAngle(1.0, 0.0, (x1dash - cxdash) / rx, (y1dash - cydash) / ry);
            double dtheta = SvgPathSegArc.CalculateVectorAngle((x1dash - cxdash) / rx, (y1dash - cydash) / ry, (-x1dash - cxdash) / rx, (-y1dash - cydash) / ry);
            if (arcSweep == SvgArcSweep.Negative && dtheta > 0)
            {
                dtheta -= 2.0 * Math.PI;
            }
            else if (arcSweep == SvgArcSweep.Positive && dtheta < 0)
            {
                dtheta += 2.0 * Math.PI;
            }

            int nsegments = (int)Math.Ceiling((double)Math.Abs(dtheta / (Math.PI / 2.0)));
            double delta = dtheta / nsegments;
            double t = 8.0 / 3.0 * Math.Sin(delta / 4.0) * Math.Sin(delta / 4.0) / Math.Sin(delta / 2.0);
            double startX = start.X;
            double startY = start.Y;
            bezier4Points = new PointF[nsegments * 4];
            int nn = 0;
            for (int n = 0; n < nsegments; ++n)
            {
                double cosTheta1 = Math.Cos(theta1);
                double sinTheta1 = Math.Sin(theta1);
                double theta2 = theta1 + delta;
                double cosTheta2 = Math.Cos(theta2);
                double sinTheta2 = Math.Sin(theta2);
                double endpointX = cosPhi * rx * cosTheta2 - sinPhi * ry * sinTheta2 + cx;
                double endpointY = sinPhi * rx * cosTheta2 + cosPhi * ry * sinTheta2 + cy;
                double dx1 = t * (-cosPhi * rx * sinTheta1 - sinPhi * ry * cosTheta1);
                double dy1 = t * (-sinPhi * rx * sinTheta1 + cosPhi * ry * cosTheta1);
                double dxe = t * (cosPhi * rx * sinTheta2 + sinPhi * ry * cosTheta2);
                double dye = t * (sinPhi * rx * sinTheta2 - cosPhi * ry * cosTheta2);
                bezier4Points[nn] = new PointF((float)startX, (float)startY);
                bezier4Points[nn + 1] = new PointF((float)(startX + dx1), (float)(startY + dy1));
                bezier4Points[nn + 2] = new PointF((float)(endpointX + dxe), (float)(endpointY + dye));
                bezier4Points[nn + 3] = new PointF((float)endpointX, (float)endpointY);
                nn += 4;
                theta1 = theta2;
                startX = (float)endpointX;
                startY = (float)endpointY;
            }
        }
Ejemplo n.º 3
0
 public List<SvgPathSeg> Parse(char[] pathDataBuffer)
 {
     //parse pathdata to pathsegments
     List<SvgPathSeg> pathSegments = new List<SvgPathSeg>();
     List<float> numbers = new List<float>();
     int j = pathDataBuffer.Length;
     int currentState = 0;
     for (int i = 0; i < j;)
     {
         //lex and parse
         char c = pathDataBuffer[i];
         switch (currentState)
         {
             case 0:
                 {
                     //init state
                     switch (c)
                     {
                         case 'M':
                         case 'm':
                             {
                                 //move to 
                                 ParseNumberList(pathDataBuffer, i + 1, out i, numbers);
                                 if (numbers.Count == 2)
                                 {
                                     var moveTo = new SvgPathSegMoveTo(
                                          numbers[0],
                                          numbers[1]);
                                     moveTo.IsRelative = c == 'm';
                                     pathSegments.Add(moveTo);
                                 }
                                 else
                                 {  //error 
                                     throw new NotSupportedException();
                                 }
                                 numbers.Clear();//reset
                             }
                             break;
                         case 'L':
                         case 'l':
                             {
                                 //line to
                                 ParseNumberList(pathDataBuffer, i + 1, out i, numbers);
                                 if (numbers.Count == 2)
                                 {
                                     var lineTo = new SvgPathSegLineTo(
                                          numbers[0], numbers[1]);
                                     lineTo.IsRelative = c == 'l';
                                     pathSegments.Add(lineTo);
                                 }
                                 else
                                 {  //error 
                                     throw new NotSupportedException();
                                 }
                                 numbers.Clear();//reset
                             }
                             break;
                         case 'H':
                         case 'h':
                             {
                                 ParseNumberList(pathDataBuffer, i + 1, out i, numbers);
                                 if (numbers.Count == 1)
                                 {
                                     var h = new SvgPathSegLineToHorizontal(
                                         numbers[0]);
                                     h.IsRelative = c == 'h';
                                     pathSegments.Add(h);
                                 }
                                 else
                                 {  //error 
                                     throw new NotSupportedException();
                                 }
                                 numbers.Clear();//reset
                             }
                             break;
                         case 'V':
                         case 'v':
                             {
                                 ParseNumberList(pathDataBuffer, i + 1, out i, numbers);
                                 if (numbers.Count == 1)
                                 {
                                     var v = new SvgPathSegLineToVertical(
                                         numbers[0]);
                                     v.IsRelative = c == 'v';
                                     pathSegments.Add(v);
                                 }
                                 else
                                 {  //error 
                                     throw new NotSupportedException();
                                 }
                                 numbers.Clear();//reset
                             }
                             break;
                         case 'Z':
                         case 'z':
                             {
                                 pathSegments.Add(new SvgPathSegClosePath());
                                 i++;
                             }
                             break;
                         case 'A':
                         case 'a':
                             {
                                 ParseNumberList(pathDataBuffer, i + 1, out i, numbers);
                                 if (numbers.Count == 7)
                                 {
                                     var arc = new SvgPathSegArc(
                                         numbers[0], numbers[1],
                                         numbers[2], (int)numbers[3], (int)numbers[4],
                                         numbers[5], numbers[6]);
                                     arc.IsRelative = c == 'a';
                                     pathSegments.Add(arc);
                                 }
                                 else
                                 {
                                     throw new NotSupportedException();
                                 }
                                 numbers.Clear();
                             }
                             break;
                         case 'C':
                         case 'c':
                             {
                                 ParseNumberList(pathDataBuffer, i + 1, out i, numbers);
                                 if (numbers.Count == 6)
                                 {
                                     var squadCurve = new SvgPathSegCurveToCubic(
                                         numbers[0], numbers[1],
                                         numbers[2], numbers[3],
                                         numbers[4], numbers[5]);
                                     squadCurve.IsRelative = c == 'c';
                                     pathSegments.Add(squadCurve);
                                 }
                                 else
                                 {
                                     throw new NotSupportedException();
                                 }
                                 numbers.Clear();
                             }
                             break;
                         case 'Q':
                         case 'q':
                             {
                                 ParseNumberList(pathDataBuffer, i + 1, out i, numbers);
                                 if (numbers.Count == 4)
                                 {
                                     var quadCurve = new SvgPathSegCurveToQuadratic(
                                         numbers[0], numbers[1],
                                         numbers[2], numbers[3]);
                                     quadCurve.IsRelative = c == 'q';
                                     pathSegments.Add(quadCurve);
                                 }
                                 else
                                 {
                                     throw new NotSupportedException();
                                 }
                                 numbers.Clear();
                             }
                             break;
                         case 'S':
                         case 's':
                             {
                                 ParseNumberList(pathDataBuffer, i + 1, out i, numbers);
                                 if (numbers.Count == 4)
                                 {
                                     var scubicCurve = new SvgPathSegCurveToCubicSmooth(
                                         numbers[0], numbers[1],
                                         numbers[2], numbers[3]);
                                     scubicCurve.IsRelative = c == 's';
                                     pathSegments.Add(scubicCurve);
                                 }
                                 else
                                 {
                                     throw new NotSupportedException();
                                 }
                                 numbers.Clear();
                             }
                             break;
                         case 'T':
                         case 't':
                             {
                                 ParseNumberList(pathDataBuffer, i + 1, out i, numbers);
                                 if (numbers.Count == 2)
                                 {
                                     var squadCurve = new SvgPathSegCurveToQuadraticSmooth(
                                         numbers[0], numbers[1]);
                                     squadCurve.IsRelative = c == 't';
                                     pathSegments.Add(squadCurve);
                                 }
                                 else
                                 {
                                     throw new NotSupportedException();
                                 }
                                 numbers.Clear();
                             }
                             break;
                         default:
                             {
                             }
                             break;
                     }
                 }
                 break;
             default:
                 {
                 }
                 break;
         }
     }
     return pathSegments;
 }