/// <summary> /// Parses the string. /// </summary> private void ParseString(IStreamCodeGenerator codeGenerator, string pathString) { // Check to ensure that there's something to parse if (pathString == null) { return; } int curIndex = 0; // skip any leading space while ((curIndex < pathString.Length) && Char.IsWhiteSpace(pathString, curIndex)) { curIndex++; } // Is there anything to look at? if (curIndex < pathString.Length) { // If so, we only care if the first non-WhiteSpace char encountered is 'F' if (pathString[curIndex] == 'F') { curIndex++; // Since we found 'F' the next non-WhiteSpace char must be 0 or 1 - look for it. while ((curIndex < pathString.Length) && Char.IsWhiteSpace(pathString, curIndex)) { curIndex++; } // If we ran out of text, this is an error, because 'F' cannot be specified without 0 or 1 // Also, if the next token isn't 0 or 1, this too is illegal if ((curIndex == pathString.Length) || ((pathString[curIndex] != '0') && (pathString[curIndex] != '1'))) { throw new Exception("Format"); } var fillRule = pathString[curIndex] == '0' ? FillRule.EvenOdd : FillRule.Nonzero; codeGenerator.SetFillRule(fillRule); // Increment curIndex to point to the next char curIndex++; } } Parse(codeGenerator, pathString, curIndex); }
/// <summary> /// Parse a PathFigureCollection string /// </summary> internal void Parse(IStreamCodeGenerator codeGenerator, string pathString, int startIndex) { // [BreakingChange] Dev10 Bug #453199 // We really should throw an ArgumentNullException here for context and pathString. // From original code // This is only used in call to Double.Parse formatProvider = System.Globalization.CultureInfo.InvariantCulture; this.codeGenerator = codeGenerator; this.pathString = pathString; pathLength = pathString.Length; curIndex = startIndex; secondLastPoint = new Point(0, 0); lastPoint = new Point(0, 0); lastStart = new Point(0, 0); figureStarted = false; bool first = true; char last_cmd = ' '; while (ReadToken()) // Empty path is allowed in XAML { char cmd = token; if (first) { if ((cmd != 'M') && (cmd != 'm')) // Path starts with M|m { ThrowBadToken(); } first = false; } switch (cmd) { case 'm': case 'M': // XAML allows multiple points after M/m lastPoint = ReadPoint(cmd, !AllowComma); codeGenerator.BeginFigure(lastPoint, IsFilled, !IsClosed); figureStarted = true; lastStart = lastPoint; last_cmd = 'M'; while (IsNumber(AllowComma)) { lastPoint = ReadPoint(cmd, !AllowComma); codeGenerator.LineTo(lastPoint, IsStroked, !IsSmoothJoin); last_cmd = 'L'; } break; case 'l': case 'L': case 'h': case 'H': case 'v': case 'V': EnsureFigure(); do { switch (cmd) { case 'l': lastPoint = ReadPoint(cmd, !AllowComma); break; case 'L': lastPoint = ReadPoint(cmd, !AllowComma); break; case 'h': lastPoint.X += ReadNumber(!AllowComma); break; case 'H': lastPoint.X = ReadNumber(!AllowComma); break; case 'v': lastPoint.Y += ReadNumber(!AllowComma); break; case 'V': lastPoint.Y = ReadNumber(!AllowComma); break; } codeGenerator.LineTo(lastPoint, IsStroked, !IsSmoothJoin); }while (IsNumber(AllowComma)); last_cmd = 'L'; break; case 'c': case 'C': // cubic Bezier case 's': case 'S': // smooth cublic Bezier EnsureFigure(); codeGenerator.BeginBezier(); do { Point p; if ((cmd == 's') || (cmd == 'S')) { if (last_cmd == 'C') { p = Reflect(); } else { p = lastPoint; } secondLastPoint = ReadPoint(cmd, !AllowComma); } else { p = ReadPoint(cmd, !AllowComma); secondLastPoint = ReadPoint(cmd, AllowComma); } lastPoint = ReadPoint(cmd, AllowComma); codeGenerator.BezierTo(p, secondLastPoint, lastPoint, IsStroked, !IsSmoothJoin); last_cmd = 'C'; }while (IsNumber(AllowComma)); codeGenerator.EndBezier(); break; case 'q': case 'Q': // quadratic Bezier case 't': case 'T': // smooth quadratic Bezier EnsureFigure(); do { if ((cmd == 't') || (cmd == 'T')) { if (last_cmd == 'Q') { secondLastPoint = Reflect(); } else { secondLastPoint = lastPoint; } lastPoint = ReadPoint(cmd, !AllowComma); } else { secondLastPoint = ReadPoint(cmd, !AllowComma); lastPoint = ReadPoint(cmd, AllowComma); } codeGenerator.QuadraticBezierTo(secondLastPoint, lastPoint, IsStroked, !IsSmoothJoin); last_cmd = 'Q'; }while (IsNumber(AllowComma)); break; case 'a': case 'A': EnsureFigure(); do { // A 3,4 5, 0, 0, 6,7 double w = ReadNumber(!AllowComma); double h = ReadNumber(AllowComma); double rotation = ReadNumber(AllowComma); bool large = ReadBool(); bool sweep = ReadBool(); var startPoint = lastPoint; lastPoint = ReadPoint(cmd, AllowComma); codeGenerator.ArcTo( startPoint, lastPoint, new Size(w, h), rotation, large, sweep, IsStroked, !IsSmoothJoin ); }while (IsNumber(AllowComma)); last_cmd = 'A'; break; case 'z': case 'Z': EnsureFigure(); codeGenerator.SetClosedState(IsClosed); figureStarted = false; last_cmd = 'Z'; lastPoint = lastStart; // Set reference point to be first point of current figure break; default: ThrowBadToken(); break; } } }