internal static Geometry ParseGeometry(string pathString /*, IFormatProvider formatProvider*/) { FillRule fillRule = FillRule.EvenOdd; PathStreamGeometryContext context = new PathStreamGeometryContext(); ParseStringToStreamGeometryContext(context, pathString /*, formatProvider*/, ref fillRule); var geometry = context.GetPathGeometry(); geometry.FillRule = fillRule; return(geometry); }
/// <summary> /// Parse a PathFigureCollection string. /// </summary> internal static PathFigureCollection ParsePathFigureCollection( string pathString, IFormatProvider formatProvider) { PathStreamGeometryContext context = new PathStreamGeometryContext(); AbbreviatedGeometryParser parser = new AbbreviatedGeometryParser(); parser.ParseToGeometryContext(context, pathString, 0 /* curIndex */); PathGeometry pathGeometry = context.GetPathGeometry(); return(pathGeometry.Figures); }
private static void ParseStringToStreamGeometryContext(PathStreamGeometryContext geometry, string pathString /*, IFormatProvider formatProvider*/, ref FillRule fillRule) { // Check to ensure that there's something to parse if (pathString != null) { 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 FormatException(SR.Get(SRID.Parsers_IllegalToken)); throw new FormatException("Parsers Illegal Token"); } fillRule = pathString[curIndex] == '0' ? FillRule.EvenOdd : FillRule.Nonzero; // Increment curIndex to point to the next char curIndex++; } } AbbreviatedGeometryParser parser = new AbbreviatedGeometryParser(); parser.ParseToGeometryContext(geometry, pathString, curIndex); } }
/// <summary> /// Parse a PathFigureCollection string /// </summary> internal void ParseToGeometryContext(PathStreamGeometryContext context, 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 this._formatProvider = global::System.Globalization.CultureInfo.InvariantCulture; this._context = context; this._pathString = pathString; this._pathLength = pathString.Length; this._curIndex = startIndex; this._secondLastPoint = new Point(0, 0); this._lastPoint = new Point(0, 0); this._lastStart = new Point(0, 0); this._figureStarted = false; bool first = true; char last_cmd = ' '; while (this.ReadToken()) // Empty path is allowed in XAML { char cmd = this._token; if (first) { if ((cmd != 'M') && (cmd != 'm')) // Path starts with M|m { this.ThrowBadToken(); } first = false; } switch (cmd) { case 'm': case 'M': // XAML allows multiple points after M/m this._lastPoint = this.ReadPoint(cmd, !AllowComma); //context.BeginFigure(this._lastPoint, IsFilled, !IsClosed); context.BeginFigure(this._lastPoint, IsFilled, !IsClosed); this._figureStarted = true; this._lastStart = _lastPoint; last_cmd = 'M'; while (this.IsNumber(AllowComma)) { this._lastPoint = this.ReadPoint(cmd, !AllowComma); context.LineTo(this._lastPoint, IsStroked, !IsSmoothJoin); last_cmd = 'L'; } break; case 'l': case 'L': case 'h': case 'H': case 'v': case 'V': this.EnsureFigure(); do { switch (cmd) { case 'l': this._lastPoint = this.ReadPoint(cmd, !AllowComma); break; case 'L': this._lastPoint = this.ReadPoint(cmd, !AllowComma); break; case 'h': this._lastPoint.X += this.ReadNumber(!AllowComma); break; case 'H': this._lastPoint.X = this.ReadNumber(!AllowComma); break; case 'v': this._lastPoint.Y += this.ReadNumber(!AllowComma); break; case 'V': this._lastPoint.Y = this.ReadNumber(!AllowComma); break; } context.LineTo(this._lastPoint, IsStroked, !IsSmoothJoin); }while (this.IsNumber(AllowComma)); last_cmd = 'L'; break; case 'c': case 'C': // cubic Bezier case 's': case 'S': // smooth cublic Bezier this.EnsureFigure(); do { Point p; if ((cmd == 's') || (cmd == 'S')) { if (last_cmd == 'C') { p = this.Reflect(); } else { p = this._lastPoint; } this._secondLastPoint = this.ReadPoint(cmd, !AllowComma); } else { p = this.ReadPoint(cmd, !AllowComma); this._secondLastPoint = this.ReadPoint(cmd, AllowComma); } this._lastPoint = this.ReadPoint(cmd, AllowComma); context.BezierTo(p, this._secondLastPoint, this._lastPoint, IsStroked, !IsSmoothJoin); last_cmd = 'C'; }while (this.IsNumber(AllowComma)); break; case 'q': case 'Q': // quadratic Bezier case 't': case 'T': // smooth quadratic Bezier this.EnsureFigure(); do { if ((cmd == 't') || (cmd == 'T')) { if (last_cmd == 'Q') { this._secondLastPoint = this.Reflect(); } else { this._secondLastPoint = this._lastPoint; } this._lastPoint = this.ReadPoint(cmd, !AllowComma); } else { this._secondLastPoint = this.ReadPoint(cmd, !AllowComma); this._lastPoint = this.ReadPoint(cmd, AllowComma); } context.QuadraticBezierTo(this._secondLastPoint, this._lastPoint, IsStroked, !IsSmoothJoin); last_cmd = 'Q'; }while (this.IsNumber(AllowComma)); break; case 'a': case 'A': this.EnsureFigure(); do { // A 3,4 5, 0, 0, 6,7 double w = this.ReadNumber(!AllowComma); double h = this.ReadNumber(AllowComma); double rotation = this.ReadNumber(AllowComma); bool large = this.ReadBool(); bool sweep = this.ReadBool(); this._lastPoint = this.ReadPoint(cmd, AllowComma); context.ArcTo( this._lastPoint, new Size(w, h), rotation, large, #if PBTCOMPILER sweep, #else sweep ? SweepDirection.Clockwise : SweepDirection.Counterclockwise, #endif IsStroked, !IsSmoothJoin ); }while (this.IsNumber(AllowComma)); last_cmd = 'A'; break; case 'z': case 'Z': this.EnsureFigure(); context.SetClosedState(IsClosed); this._figureStarted = false; last_cmd = 'Z'; this._lastPoint = this._lastStart; // Set reference point to be first point of current figure break; default: this.ThrowBadToken(); break; } } }