private SvgPointF getPrevPoint() { SvgPathSeg prevSeg = PreviousSeg; SvgPointF prevPoint; if(prevSeg == null) { prevPoint = new SvgPointF(0,0); } else { prevPoint = prevSeg.AbsXY; } return prevPoint; }
/// <summary> /// Initializes a new instance of the <see cref="SvgTransformF"/> class /// to the geometric transform defined by the specified rectangle and /// array of points. /// </summary> /// <param name="rect"> /// A <see cref="SvgRectF"/> structure that represents the rectangle /// to be transformed. /// </param> /// <param name="plgpts"> /// An array of three <see cref="SvgPointF"/> structures that represents the /// points of a parallelogram to which the upper-left, upper-right, and /// lower-left corners of the rectangle is to be transformed. The /// lower-right corner of the parallelogram is implied by the first three /// corners. /// </param> /// <exception cref="ArgumentNullException"> /// If the <paramref name="plgpts"/> is <see langword="null"/>. /// </exception> /// <exception cref="ArgumentException"> /// If the length of the <paramref name="plgpts"/> array is not equal /// to 3. /// </exception> /// <exception cref="ArgumentOutOfRangeException"> /// If the width or height of the <paramref name="rect"/> is zero. /// </exception> public SvgTransformF(SvgRectF rect, SvgPointF[] plgpts) { if (plgpts == null) { throw new ArgumentNullException("plgpts"); } if (plgpts.Length != 3) { throw new ArgumentException("plgpts"); } if ((rect.Width == 0) || (rect.Height == 0)) { throw new ArgumentOutOfRangeException("rect"); } MapRectToRect(rect, plgpts); }
public void RenderMarker0(WpfDrawingRenderer renderer, WpfDrawingContext gr, SvgMarkerPosition markerPos, SvgStyleableElement refElement) { //PathGeometry g; //g.GetPointAtFractionLength( ISharpMarkerHost markerHostElm = (ISharpMarkerHost)refElement; SvgMarkerElement markerElm = (SvgMarkerElement)_svgElement; SvgPointF[] vertexPositions = markerHostElm.MarkerPositions; int start; int len; // Choose which part of the position array to use switch (markerPos) { case SvgMarkerPosition.Start: start = 0; len = 1; break; case SvgMarkerPosition.Mid: start = 1; len = vertexPositions.Length - 2; break; default: // == MarkerPosition.End start = vertexPositions.Length - 1; len = 1; break; } for (int i = start; i < start + len; i++) { SvgPointF point = vertexPositions[i]; Matrix m = GetTransformMatrix(_svgElement); //GraphicsContainer gc = gr.BeginContainer(); this.BeforeRender(renderer); //gr.TranslateTransform(point.X, point.Y); //PAUL: //m.Translate(point.X, point.Y); if (markerElm.OrientType.AnimVal.Equals((ushort)SvgMarkerOrient.Angle)) { m.Rotate(markerElm.OrientAngle.AnimVal.Value); //gr.RotateTransform((double)markerElm.OrientAngle.AnimVal.Value); } else { double angle; switch (markerPos) { case SvgMarkerPosition.Start: angle = markerHostElm.GetStartAngle(i + 1); break; case SvgMarkerPosition.Mid: //angle = (markerHostElm.GetEndAngle(i) + markerHostElm.GetStartAngle(i + 1)) / 2; angle = SvgNumber.CalcAngleBisection(markerHostElm.GetEndAngle(i), markerHostElm.GetStartAngle(i + 1)); break; default: angle = markerHostElm.GetEndAngle(i); break; } //gr.RotateTransform(angle); m.Rotate(angle); } if (markerElm.MarkerUnits.AnimVal.Equals((ushort)SvgMarkerUnit.StrokeWidth)) { string propValue = refElement.GetPropertyValue("stroke-width"); if (propValue.Length == 0) { propValue = "1"; } SvgLength strokeWidthLength = new SvgLength("stroke-width", propValue, refElement, SvgLengthDirection.Viewport); double strokeWidth = strokeWidthLength.Value; //gr.ScaleTransform(strokeWidth, strokeWidth); m.Scale(strokeWidth, strokeWidth); } SvgPreserveAspectRatio spar = (SvgPreserveAspectRatio)markerElm.PreserveAspectRatio.AnimVal; double[] translateAndScale = spar.FitToViewBox( (SvgRect)markerElm.ViewBox.AnimVal, new SvgRect(0, 0, markerElm.MarkerWidth.AnimVal.Value, markerElm.MarkerHeight.AnimVal.Value)); //PAUL: //m.Translate(-(double)markerElm.RefX.AnimVal.Value * translateAndScale[2], -(double)markerElm.RefY.AnimVal.Value * translateAndScale[3]); //PAUL: m.Scale(translateAndScale[2], translateAndScale[3]); m.Translate(point.X, point.Y); //Matrix oldTransform = TransformMatrix; //TransformMatrix = m; //try //{ //newTransform.Append(m); //TransformGroup tg = new TransformGroup(); //renderer.Canvas.re //gr.TranslateTransform( // -(double)markerElm.RefX.AnimVal.Value * translateAndScale[2], // -(double)markerElm.RefY.AnimVal.Value * translateAndScale[3] // ); //gr.ScaleTransform(translateAndScale[2], translateAndScale[3]); renderer.RenderChildren(markerElm); // markerElm.RenderChildren(renderer); //} //finally //{ // TransformMatrix = oldTransform; //} // //gr.EndContainer(gc); _matrix = m; this.Render(renderer); //gr.EndContainer(gc); this.AfterRender(renderer); } }
public void RenderMarker(WpfDrawingRenderer renderer, WpfDrawingContext gr, SvgMarkerPosition markerPos, SvgStyleableElement refElement) { ISharpMarkerHost markerHostElm = (ISharpMarkerHost)refElement; SvgPointF[] vertexPositions = markerHostElm.MarkerPositions; int start = 0; int len = 0; // Choose which part of the position array to use switch (markerPos) { case SvgMarkerPosition.Start: start = 0; len = 1; break; case SvgMarkerPosition.Mid: start = 1; len = vertexPositions.Length - 2; break; default: // == MarkerPosition.End start = vertexPositions.Length - 1; len = 1; break; } int end = start + len; TransformGroup transform = new TransformGroup(); for (int i = start; i < end; i++) { SvgPointF point = vertexPositions[i]; //GdiGraphicsContainer gc = gr.BeginContainer(); this.BeforeRender(renderer); //Matrix matrix = Matrix.Identity; Matrix matrix = GetTransformMatrix(_svgElement, transform); ISvgAnimatedEnumeration orientType = _markerElement.OrientType; if (orientType.AnimVal.Equals((ushort)SvgMarkerOrient.Angle)) { double scaleValue = _markerElement.OrientAngle.AnimVal.Value; if (!scaleValue.Equals(0)) { matrix.Rotate(scaleValue); transform.Children.Add(new RotateTransform(scaleValue)); } } else { bool isAutoReverse = orientType.AnimVal.Equals((ushort)SvgMarkerOrient.AutoStartReverse); double angle = 0; switch (markerPos) { case SvgMarkerPosition.Start: angle = markerHostElm.GetStartAngle(i); //angle = markerHostElm.GetStartAngle(i + 1); if (vertexPositions.Length >= 2) { SvgPointF pMarkerPoint1 = vertexPositions[start]; SvgPointF pMarkerPoint2 = vertexPositions[end]; float xDiff = pMarkerPoint2.X - pMarkerPoint1.X; float yDiff = pMarkerPoint2.Y - pMarkerPoint1.Y; double angleMarker = (float)(Math.Atan2(yDiff, xDiff) * 180.0 / Math.PI); if (!angleMarker.Equals(angle)) { angle = angleMarker; } } // A value of 'auto-start-reverse' means the same as 'auto' except that for a // marker placed by 'marker-start', the orientation is 180° different from // the orientation as determined by 'auto'. if (isAutoReverse) { angle += 180; } break; case SvgMarkerPosition.Mid: //angle = (markerHostElm.GetEndAngle(i) + markerHostElm.GetStartAngle(i + 1)) / 2; angle = SvgNumber.CalcAngleBisection(markerHostElm.GetEndAngle(i), markerHostElm.GetStartAngle(i + 1)); break; default: angle = markerHostElm.GetEndAngle(i - 1); //angle = markerHostElm.GetEndAngle(i); if (vertexPositions.Length >= 2) { SvgPointF pMarkerPoint1 = vertexPositions[start - 1]; SvgPointF pMarkerPoint2 = vertexPositions[start]; float xDiff = pMarkerPoint2.X - pMarkerPoint1.X; float yDiff = pMarkerPoint2.Y - pMarkerPoint1.Y; double angleMarker = (float)(Math.Atan2(yDiff, xDiff) * 180.0 / Math.PI); if (!angleMarker.Equals(angle)) { angle = angleMarker; } } break; } matrix.Rotate(angle); transform.Children.Add(new RotateTransform(angle)); } // 'viewBox' and 'preserveAspectRatio' attributes // viewBox -> viewport(0, 0, markerWidth, markerHeight) SvgPreserveAspectRatio spar = (SvgPreserveAspectRatio)_markerElement.PreserveAspectRatio.AnimVal; double[] translateAndScale = spar.FitToViewBox((SvgRect)_markerElement.ViewBox.AnimVal, new SvgRect(0, 0, _markerElement.MarkerWidth.AnimVal.Value, _markerElement.MarkerHeight.AnimVal.Value)); // Warning at this time, refX and refY are relative to the painted element's coordinate system. // We need to move the reference point to the marker's coordinate system double refX = _markerElement.RefX.AnimVal.Value; double refY = _markerElement.RefY.AnimVal.Value; if (!(refX.Equals(0) && refY.Equals(0))) { var ptRef = matrix.Transform(new Point(refX, refY)); refX = ptRef.X; refY = ptRef.Y; matrix.Translate(-refX, -refY); transform.Children.Add(new TranslateTransform(-refX, -refY)); } //matrix.Translate(-markerElm.RefX.AnimVal.Value * translateAndScale[2], // -markerElm.RefY.AnimVal.Value * translateAndScale[3]); //transform.Children.Add(new TranslateTransform(-markerElm.RefX.AnimVal.Value * translateAndScale[2], // -markerElm.RefY.AnimVal.Value * translateAndScale[3])); // compute an additional transform for 'strokeWidth' coordinate system ISvgAnimatedEnumeration markerUnits = _markerElement.MarkerUnits; if (markerUnits.AnimVal.Equals((ushort)SvgMarkerUnit.StrokeWidth)) { SvgLength strokeWidthLength = new SvgLength(refElement, "stroke-width", SvgLengthSource.Css, SvgLengthDirection.Viewport, "1"); double strokeWidth = strokeWidthLength.Value; if (!strokeWidth.Equals(1)) { matrix.Scale(strokeWidth, strokeWidth); transform.Children.Add(new ScaleTransform(strokeWidth, strokeWidth)); } } if (!(translateAndScale[2].Equals(1) && translateAndScale[3].Equals(1))) { matrix.Scale(translateAndScale[2], translateAndScale[3]); transform.Children.Add(new ScaleTransform(translateAndScale[2], translateAndScale[3])); } matrix.Translate(point.X, point.Y); transform.Children.Add(new TranslateTransform(point.X, point.Y)); _matrix = matrix; this.Transform = transform; this.Render(renderer); //Clip(gr); renderer.RenderChildren(_markerElement); //gr.EndContainer(gc); this.AfterRender(renderer); } }
private double GetAngleAt(int index, double angle, SvgMarkerPosition position, ISharpMarkerHost markerHost) { if (markerHost == null || _pathFigures == null || _pathFigures.Count == 0) { return(angle); } var marker = markerHost.GetMarker(index + 1); PathGeometry pathFlattened = null; if (_pathFigures.Count != 1) { if (index < _pathFigures.Count) { PathGeometry path = new PathGeometry(new PathFigure[] { _pathFigures[index] }); pathFlattened = path.GetFlattenedPathGeometry(); } } else { PathFigure figureAt = _pathFigures[0]; if (figureAt.Segments.Count == 1) { PathGeometry path = new PathGeometry(new PathFigure[] { figureAt }); pathFlattened = path.GetFlattenedPathGeometry(); } else { if (marker.IsCurve == false) { return(angle); } if (index < figureAt.Segments.Count) { var pathSegment = figureAt.Segments[index]; Point startPoint = new Point(0, 0); if (marker != null) { var pathSet = marker.Segment; if (pathSet != null && pathSet.Limits != null && pathSet.Limits.Length == 2) { SvgPointF point = pathSet.Limits[0]; startPoint = new Point(point.ValueX, point.ValueY); } } PathFigure targetFigure = new PathFigure(startPoint, new PathSegment[] { pathSegment }, false); PathGeometry path = new PathGeometry(new PathFigure[] { targetFigure }); pathFlattened = path.GetFlattenedPathGeometry(); } } } if (pathFlattened != null) { double progress = 1; switch (position) { case SvgMarkerPosition.End: progress = 1; break; case SvgMarkerPosition.Start: progress = 0; break; case SvgMarkerPosition.Mid: progress = 0; break; } Point locationAt; Point tagentAt; pathFlattened.GetPointAtFractionLength(progress, out locationAt, out tagentAt); return(Math.Atan2(tagentAt.Y, tagentAt.X) * 180 / Math.PI); } return(angle); }
private void MapRectToRect(SvgRectF rect, SvgPointF[] plgpts) { SvgPointF pt1 = new SvgPointF(plgpts[1].X - plgpts[0].X, plgpts[1].Y - plgpts[0].Y); SvgPointF pt2 = new SvgPointF(plgpts[2].X - plgpts[0].X, plgpts[2].Y - plgpts[0].Y); this.m11 = pt1.X / rect.Width; this.m12 = pt1.Y / rect.Width; this.m21 = pt2.X / rect.Height; this.m22 = pt2.Y / rect.Height; this.dx = plgpts[0].X - rect.X / rect.Width * pt1.X - rect.Y / rect.Height * pt2.X; this.dy = plgpts[0].Y - rect.X / rect.Width * pt1.Y - rect.Y / rect.Height * pt2.Y; }
/// <summary> /// Multiplies each vector in an array by the matrix. The translation /// elements of this matrix (third row) are ignored. /// </summary> /// <param name="pts"> /// An array of <see cref="SvgPointF"/> structures that represents the points /// to transform. /// </param> public void TransformVectors(SvgPointF[] pts) { if (pts == null) { throw new ArgumentNullException("pts"); } int nLength = pts.Length; for (int i = nLength - 1; i >= 0; --i) { float x = pts[i].X; float y = pts[i].Y; pts[i].ValueX = x * m11 + y * m21; pts[i].ValueY = x * m12 + y * m22; } }
public void PaintMarker(GdiGraphicsRenderer renderer, GdiGraphicsWrapper gr, SvgMarkerPosition markerPos, SvgStyleableElement refElement) { ISharpMarkerHost markerHostElm = (ISharpMarkerHost)refElement; SvgMarkerElement markerElm = (SvgMarkerElement)element; SvgPointF[] vertexPositions = markerHostElm.MarkerPositions; int start; int len; // Choose which part of the position array to use switch (markerPos) { case SvgMarkerPosition.Start: start = 0; len = 1; break; case SvgMarkerPosition.Mid: start = 1; len = vertexPositions.Length - 2; break; default: // == MarkerPosition.End start = vertexPositions.Length - 1; len = 1; break; } for (int i = start; i < start + len; i++) { SvgPointF point = vertexPositions[i]; GdiGraphicsContainer gc = gr.BeginContainer(); gr.TranslateTransform(point.X, point.Y); if (markerElm.OrientType.AnimVal.Equals((ushort)SvgMarkerOrient.Angle)) { gr.RotateTransform((float)markerElm.OrientAngle.AnimVal.Value); } else { double angle; switch (markerPos) { case SvgMarkerPosition.Start: angle = markerHostElm.GetStartAngle(i + 1); break; case SvgMarkerPosition.Mid: //angle = (markerHostElm.GetEndAngle(i) + markerHostElm.GetStartAngle(i + 1)) / 2; angle = SvgNumber.CalcAngleBisection(markerHostElm.GetEndAngle(i), markerHostElm.GetStartAngle(i + 1)); break; default: angle = markerHostElm.GetEndAngle(i); break; } gr.RotateTransform((float)angle); } if (markerElm.MarkerUnits.AnimVal.Equals((ushort)SvgMarkerUnit.StrokeWidth)) { SvgLength strokeWidthLength = new SvgLength(refElement, "stroke-width", SvgLengthSource.Css, SvgLengthDirection.Viewport, "1"); float strokeWidth = (float)strokeWidthLength.Value; gr.ScaleTransform(strokeWidth, strokeWidth); } SvgPreserveAspectRatio spar = (SvgPreserveAspectRatio)markerElm.PreserveAspectRatio.AnimVal; double[] translateAndScale = spar.FitToViewBox((SvgRect)markerElm.ViewBox.AnimVal, new SvgRect(0, 0, markerElm.MarkerWidth.AnimVal.Value, markerElm.MarkerHeight.AnimVal.Value)); gr.TranslateTransform(-(float)(markerElm.RefX.AnimVal.Value * translateAndScale[2]), -(float)(markerElm.RefY.AnimVal.Value * translateAndScale[3])); gr.ScaleTransform((float)translateAndScale[2], (float)translateAndScale[3]); Clip(gr); renderer.RenderChildren(markerElm); gr.EndContainer(gc); } }
/// <overloads> /// Applies a clockwise rotation about the specified point to this /// <see cref="SvgTransformF"/> by appending or prepending the rotation. /// </overloads> /// <summary> /// Applies a clockwise rotation about the specified point to this /// <see cref="SvgTransformF"/> by prepending the rotation. /// </summary> /// <param name="angle"> /// The angle (extent) of the rotation, in degrees. /// </param> /// <param name="point"> /// A <see cref="SvgPointF"/> that represents the center of the rotation. /// </param> public void RotateAt(float angle, SvgPointF point) { Translate(point.X, point.Y); Rotate(angle); Translate(-point.X, -point.Y); }
public static GraphicsPath CreatePath(SvgPathElement element) { GraphicsPath gp = new GraphicsPath(); SvgPointF initPoint = new SvgPointF(0, 0); SvgPointF lastPoint = new SvgPointF(0, 0); ISvgPathSeg segment = null; SvgPathSegMoveto pathMoveTo = null; SvgPathSegLineto pathLineTo = null; SvgPathSegCurveto pathCurveTo = null; SvgPathSegArc pathArc = null; ISvgPathSegList segments = element.PathSegList; int nElems = segments.NumberOfItems; for (int i = 0; i < nElems; i++) { segment = segments.GetItem(i); if (DynamicCast.Cast(segment, out pathMoveTo)) { //SvgPathSegMoveto seg = (SvgPathSegMoveto)segment; gp.StartFigure(); lastPoint = initPoint = pathMoveTo.AbsXY; } else if (DynamicCast.Cast(segment, out pathLineTo)) { //SvgPathSegLineto seg = (SvgPathSegLineto)segment; SvgPointF p = pathLineTo.AbsXY; gp.AddLine(lastPoint.X, lastPoint.Y, p.X, p.Y); lastPoint = p; } else if (DynamicCast.Cast(segment, out pathCurveTo)) { // SvgPathSegCurveto seg = (SvgPathSegCurveto)segment; SvgPointF xy = pathCurveTo.AbsXY; SvgPointF x1y1 = pathCurveTo.CubicX1Y1; SvgPointF x2y2 = pathCurveTo.CubicX2Y2; gp.AddBezier(lastPoint.X, lastPoint.Y, x1y1.X, x1y1.Y, x2y2.X, x2y2.Y, xy.X, xy.Y); lastPoint = xy; } else if (DynamicCast.Cast(segment, out pathArc)) { //SvgPathSegArc seg = (SvgPathSegArc)segment; SvgPointF p = pathArc.AbsXY; if (lastPoint.Equals(p)) { // If the endpoints (x, y) and (x0, y0) are identical, then this // is equivalent to omitting the elliptical arc segment entirely. } else if (pathArc.R1 == 0 || pathArc.R2 == 0) { // Ensure radii are valid gp.AddLine(lastPoint.X, lastPoint.Y, p.X, p.Y); } else { CalculatedArcValues calcValues = pathArc.GetCalculatedArcValues(); GraphicsPath gp2 = new GraphicsPath(); gp2.StartFigure(); gp2.AddArc((float)(calcValues.Cx - calcValues.CorrRx), (float)(calcValues.Cy - calcValues.CorrRy), (float)calcValues.CorrRx * 2, (float)calcValues.CorrRy * 2, (float)calcValues.AngleStart, (float)calcValues.AngleExtent); Matrix matrix = new Matrix(); matrix.Translate(-(float)calcValues.Cx, -(float)calcValues.Cy); gp2.Transform(matrix); matrix = new Matrix(); matrix.Rotate((float)pathArc.Angle); gp2.Transform(matrix); matrix = new Matrix(); matrix.Translate((float)calcValues.Cx, (float)calcValues.Cy); gp2.Transform(matrix); gp.AddPath(gp2, true); } lastPoint = p; } else if (segment is SvgPathSegClosePath) { gp.CloseFigure(); lastPoint = initPoint; } } string fillRule = element.GetPropertyValue("fill-rule"); if (fillRule == "evenodd") gp.FillMode = FillMode.Alternate; else gp.FillMode = FillMode.Winding; return gp; }
public Geometry CreateGeometry(SvgPathElement element) { PathGeometry geometry = new PathGeometry(); var comparer = StringComparison.OrdinalIgnoreCase; string fillRule = element.GetPropertyValue("fill-rule"); string clipRule = element.GetAttribute("clip-rule"); if (!string.IsNullOrWhiteSpace(clipRule) && string.Equals(clipRule, "evenodd", comparer) || string.Equals(clipRule, CssConstants.ValNonzero, comparer)) { fillRule = clipRule; } if (string.Equals(fillRule, "evenodd", comparer)) { geometry.FillRule = FillRule.EvenOdd; } else if (string.Equals(fillRule, CssConstants.ValNonzero, comparer)) { geometry.FillRule = FillRule.Nonzero; } SvgPointF initPoint = new SvgPointF(0, 0); SvgPointF lastPoint = new SvgPointF(0, 0); SvgPointF ptXY = new SvgPointF(0, 0); SvgPathSeg segment = null; SvgPathSegMoveto pathMoveTo = null; SvgPathSegLineto pathLineTo = null; SvgPathSegCurveto pathCurveTo = null; SvgPathSegArc pathArc = null; SvgPathSegList segments = element.PathSegList; int numSegs = segments.NumberOfItems; if (numSegs == 0) { return(geometry); } PathFigure pathFigure = null; for (int i = 0; i < numSegs; i++) { segment = segments.GetItem(i); switch (segment.PathType) { case SvgPathType.MoveTo: //if (DynamicCast.Cast(segment, out pathMoveTo)) pathMoveTo = (SvgPathSegMoveto)segment; if (pathFigure != null) { pathFigure.IsClosed = false; pathFigure.IsFilled = true; geometry.Figures.Add(pathFigure); pathFigure = null; } lastPoint = initPoint = pathMoveTo.AbsXY; pathFigure = new PathFigure(); pathFigure.StartPoint = new Point(initPoint.ValueX, initPoint.ValueY); break; case SvgPathType.LineTo: //else if (DynamicCast.Cast(segment, out pathLineTo)) pathLineTo = (SvgPathSegLineto)segment; ptXY = pathLineTo.AbsXY; pathFigure.Segments.Add(new LineSegment(new Point(ptXY.ValueX, ptXY.ValueY), true)); lastPoint = ptXY; break; case SvgPathType.CurveTo: //else if (DynamicCast.Cast(segment, out pathCurveTo)) pathCurveTo = (SvgPathSegCurveto)segment; SvgPointF xy = pathCurveTo.AbsXY; SvgPointF x1y1 = pathCurveTo.CubicX1Y1; SvgPointF x2y2 = pathCurveTo.CubicX2Y2; pathFigure.Segments.Add(new BezierSegment(new Point(x1y1.ValueX, x1y1.ValueY), new Point(x2y2.ValueX, x2y2.ValueY), new Point(xy.ValueX, xy.ValueY), true)); lastPoint = xy; break; case SvgPathType.ArcTo: //else if (DynamicCast.Cast(segment, out pathArc)) pathArc = (SvgPathSegArc)segment; ptXY = pathArc.AbsXY; if (lastPoint.Equals(ptXY)) { // If the endpoints (x, y) and (x0, y0) are identical, then this // is equivalent to omitting the elliptical arc segment entirely. } else if (pathArc.R1.Equals(0) || pathArc.R2.Equals(0)) { // Ensure radii are valid pathFigure.Segments.Add(new LineSegment(new Point(ptXY.ValueX, ptXY.ValueY), true)); } else { CalculatedArcValues calcValues = pathArc.GetCalculatedArcValues(); pathFigure.Segments.Add(new ArcSegment(new Point(ptXY.ValueX, ptXY.ValueY), new Size(pathArc.R1, pathArc.R2), pathArc.Angle, pathArc.LargeArcFlag, pathArc.SweepFlag ? SweepDirection.Clockwise : SweepDirection.Counterclockwise, true)); } lastPoint = ptXY; break; case SvgPathType.Close: //else if (segment is SvgPathSegClosePath) if (pathFigure != null) { pathFigure.IsClosed = true; pathFigure.IsFilled = true; geometry.Figures.Add(pathFigure); pathFigure = null; } lastPoint = initPoint; break; } } if (pathFigure != null) { pathFigure.IsClosed = false; pathFigure.IsFilled = true; geometry.Figures.Add(pathFigure); } return(geometry); }
public void PaintMarker(GdiGraphicsRenderer renderer, GdiGraphics gr, SvgMarkerPosition markerPos, SvgStyleableElement refElement) { ISharpMarkerHost markerHostElm = (ISharpMarkerHost)refElement; SvgMarkerElement markerElm = (SvgMarkerElement)_svgElement; SvgPointF[] vertexPositions = markerHostElm.MarkerPositions; if (vertexPositions == null) { return; } var comparer = StringComparison.OrdinalIgnoreCase; bool mayHaveCurves = markerHostElm.MayHaveCurves; int start; int len; // Choose which part of the position array to use switch (markerPos) { case SvgMarkerPosition.Start: start = 0; len = 1; break; case SvgMarkerPosition.Mid: start = 1; len = vertexPositions.Length - 2; break; default: // == MarkerPosition.End start = vertexPositions.Length - 1; len = 1; break; } int end = start + len; for (int i = start; i < end; i++) { SvgPointF point = vertexPositions[i]; GdiGraphicsContainer gc = gr.BeginContainer(); gr.TranslateTransform(point.X, point.Y); if (markerElm.OrientType.AnimVal.Equals((ushort)SvgMarkerOrient.Angle)) { double scaleValue = markerElm.OrientAngle.AnimVal.Value; if (!scaleValue.Equals(0)) { gr.RotateTransform((float)scaleValue); } } else { double angle; switch (markerPos) { case SvgMarkerPosition.Start: angle = markerHostElm.GetStartAngle(i); //angle = markerHostElm.GetStartAngle(i + 1); if (vertexPositions.Length >= 2) { SvgPointF pMarkerPoint1 = vertexPositions[start]; SvgPointF pMarkerPoint2 = vertexPositions[end]; float xDiff = pMarkerPoint2.X - pMarkerPoint1.X; float yDiff = pMarkerPoint2.Y - pMarkerPoint1.Y; double angleMarker = (float)(Math.Atan2(yDiff, xDiff) * 180.0 / Math.PI); if (!angleMarker.Equals(angle)) { angle = angleMarker; } } break; case SvgMarkerPosition.Mid: //angle = (markerHostElm.GetEndAngle(i) + markerHostElm.GetStartAngle(i + 1)) / 2; angle = SvgNumber.CalcAngleBisection(markerHostElm.GetEndAngle(i), markerHostElm.GetStartAngle(i + 1)); break; default: angle = markerHostElm.GetEndAngle(i - 1); //double angle2 = markerHostElm.GetEndAngle(i); if (vertexPositions.Length >= 2) { SvgPointF pMarkerPoint1 = vertexPositions[start - 1]; SvgPointF pMarkerPoint2 = vertexPositions[start]; float xDiff = pMarkerPoint2.X - pMarkerPoint1.X; float yDiff = pMarkerPoint2.Y - pMarkerPoint1.Y; double angleMarker = (float)(Math.Atan2(yDiff, xDiff) * 180.0 / Math.PI); if (!angleMarker.Equals(angle)) { angle = angleMarker; } } //if (mayHaveCurves) //{ // angle = this.GetAngleAt(start - 1, angle, markerPos, markerHostElm); //} break; } gr.RotateTransform((float)angle); } // 'viewBox' and 'preserveAspectRatio' attributes // viewBox -> viewport(0, 0, markerWidth, markerHeight) var spar = (SvgPreserveAspectRatio)markerElm.PreserveAspectRatio.AnimVal; double[] translateAndScale = spar.FitToViewBox((SvgRect)markerElm.ViewBox.AnimVal, new SvgRect(0, 0, markerElm.MarkerWidth.AnimVal.Value, markerElm.MarkerHeight.AnimVal.Value)); //// Warning at this time, refX and refY are relative to the painted element's coordinate system. //// We need to move the reference point to the marker's coordinate system //float refX = (float)markerElm.RefX.AnimVal.Value; //float refY = (float)markerElm.RefY.AnimVal.Value; ////if (!(refX.Equals(0) && refY.Equals(0))) ////{ //// var points = new PointF[] { new PointF(refX, refY) }; //// gr.Transform.TransformPoints(points); //// refX = points[0].X; //// refY = points[0].Y; //// gr.TranslateTransform(-refX, -refY); ////} //if (markerElm.MarkerUnits.AnimVal.Equals((ushort)SvgMarkerUnit.StrokeWidth)) //{ // SvgLength strokeWidthLength = new SvgLength(refElement, // "stroke-width", SvgLengthSource.Css, SvgLengthDirection.Viewport, "1"); // float strokeWidth = (float)strokeWidthLength.Value; // gr.ScaleTransform(strokeWidth, strokeWidth); //} //gr.TranslateTransform(-(float)(markerElm.RefX.AnimVal.Value * translateAndScale[2]), // -(float)(markerElm.RefY.AnimVal.Value * translateAndScale[3])); //gr.ScaleTransform((float)translateAndScale[2], (float)translateAndScale[3]); // compute an additional transform for 'strokeWidth' coordinate system ISvgAnimatedEnumeration markerUnits = markerElm.MarkerUnits; if (markerUnits.AnimVal.Equals((ushort)SvgMarkerUnit.StrokeWidth)) { SvgLength strokeWidthLength = new SvgLength(refElement, "stroke-width", SvgLengthSource.Css, SvgLengthDirection.Viewport, SvgConstants.ValOne); double strokeWidth = strokeWidthLength.Value; if (!strokeWidth.Equals(1)) { gr.ScaleTransform((float)strokeWidth, (float)strokeWidth); } } gr.TranslateTransform(-(float)(markerElm.RefX.AnimVal.Value * translateAndScale[2]), -(float)(markerElm.RefY.AnimVal.Value * translateAndScale[3])); if (!(translateAndScale[2].Equals(1) && translateAndScale[3].Equals(1))) { gr.ScaleTransform((float)translateAndScale[2], (float)translateAndScale[3]); } // gr.TranslateTransform(point.X, point.Y); RectangleF rectClip = RectangleF.Empty; if (markerUnits.AnimVal.Equals((ushort)SvgMarkerUnit.StrokeWidth)) { string overflowAttr = markerElm.GetAttribute("overflow"); if (string.IsNullOrWhiteSpace(overflowAttr) || overflowAttr.Equals("scroll", comparer) || overflowAttr.Equals(CssConstants.ValHidden, comparer)) { var markerClip = RectangleF.Empty; SvgRect clipRect = (SvgRect)markerElm.ViewBox.AnimVal; if (clipRect != null && !clipRect.IsEmpty) { rectClip = new RectangleF((float)clipRect.X, (float)clipRect.Y, (float)clipRect.Width, (float)clipRect.Height); } else if (markerElm.IsSizeDefined) { rectClip = new RectangleF(0, 0, (float)markerElm.MarkerWidth.AnimVal.Value, (float)markerElm.MarkerHeight.AnimVal.Value); } } } if (rectClip.IsEmpty) { SetClip(gr); } else { gr.SetClip(rectClip); } renderer.RenderChildren(markerElm); gr.EndContainer(gc); } }
public void RenderMarker(WpfDrawingRenderer renderer, WpfDrawingContext gr, SvgMarkerPosition markerPos, SvgStyleableElement refElement) { ISharpMarkerHost markerHostElm = (ISharpMarkerHost)refElement; SvgPointF[] vertexPositions = markerHostElm.MarkerPositions; int start; int len; // Choose which part of the position array to use switch (markerPos) { case SvgMarkerPosition.Start: start = 0; len = 1; break; case SvgMarkerPosition.Mid: start = 1; len = vertexPositions.Length - 2; break; default: // == MarkerPosition.End start = vertexPositions.Length - 1; len = 1; break; } TransformGroup transform = new TransformGroup(); for (int i = start; i < start + len; i++) { SvgPointF point = vertexPositions[i]; //GdiGraphicsContainer gc = gr.BeginContainer(); this.BeforeRender(renderer); //Matrix matrix = Matrix.Identity; Matrix matrix = GetTransformMatrix(_svgElement, transform); ISvgAnimatedEnumeration orientType = _markerElement.OrientType; if (orientType.AnimVal.Equals((ushort)SvgMarkerOrient.Angle)) { matrix.Rotate(_markerElement.OrientAngle.AnimVal.Value); transform.Children.Add(new RotateTransform(_markerElement.OrientAngle.AnimVal.Value)); } else { double angle = 0; // double angle0 = 0; switch (markerPos) { case SvgMarkerPosition.Start: //angle0 = markerHostElm.GetStartAngle(i + 1); angle = markerHostElm.GetStartAngle(i); break; case SvgMarkerPosition.Mid: //angle = (markerHostElm.GetEndAngle(i) + markerHostElm.GetStartAngle(i + 1)) / 2; angle = SvgNumber.CalcAngleBisection(markerHostElm.GetEndAngle(i), markerHostElm.GetStartAngle(i + 1)); break; default: angle = markerHostElm.GetEndAngle(i - 1); //angle0 = markerHostElm.GetEndAngle(i); break; } matrix.Rotate(angle); transform.Children.Add(new RotateTransform(angle)); } // 'viewBox' and 'preserveAspectRatio' attributes // viewBox -> viewport(0, 0, markerWidth, markerHeight) SvgPreserveAspectRatio spar = (SvgPreserveAspectRatio)_markerElement.PreserveAspectRatio.AnimVal; double[] translateAndScale = spar.FitToViewBox((SvgRect)_markerElement.ViewBox.AnimVal, new SvgRect(0, 0, _markerElement.MarkerWidth.AnimVal.Value, _markerElement.MarkerHeight.AnimVal.Value)); // Warning at this time, refX and refY are relative to the painted element's coordinate system. // We need to move the reference point to the marker's coordinate system double refX = _markerElement.RefX.AnimVal.Value; double refY = _markerElement.RefY.AnimVal.Value; var ptRef = matrix.Transform(new Point(refX, refY)); refX = ptRef.X; refY = ptRef.Y; matrix.Translate(-refX, -refY); transform.Children.Add(new TranslateTransform(-refX, -refY)); //matrix.Translate(-markerElm.RefX.AnimVal.Value * translateAndScale[2], // -markerElm.RefY.AnimVal.Value * translateAndScale[3]); //transform.Children.Add(new TranslateTransform(-markerElm.RefX.AnimVal.Value * translateAndScale[2], // -markerElm.RefY.AnimVal.Value * translateAndScale[3])); // compute an additional transform for 'strokeWidth' coordinate system ISvgAnimatedEnumeration markerUnits = _markerElement.MarkerUnits; if (markerUnits.AnimVal.Equals((ushort)SvgMarkerUnit.StrokeWidth)) { SvgLength strokeWidthLength = new SvgLength(refElement, "stroke-width", SvgLengthSource.Css, SvgLengthDirection.Viewport, "1"); double strokeWidth = strokeWidthLength.Value; matrix.Scale(strokeWidth, strokeWidth); transform.Children.Add(new ScaleTransform(strokeWidth, strokeWidth)); } matrix.Scale(translateAndScale[2], translateAndScale[3]); transform.Children.Add(new ScaleTransform(translateAndScale[2], translateAndScale[3])); matrix.Translate(point.X, point.Y); transform.Children.Add(new TranslateTransform(point.X, point.Y)); _matrix = matrix; this.Transform = transform; this.Render(renderer); //Clip(gr); renderer.RenderChildren(_markerElement); //gr.EndContainer(gc); this.AfterRender(renderer); } }
public static Geometry CreateGeometry(SvgPathElement element) { PathGeometry geometry = new PathGeometry(); string fillRule = element.GetPropertyValue("fill-rule"); string clipRule = element.GetAttribute("clip-rule"); if (!String.IsNullOrEmpty(clipRule) && String.Equals(clipRule, "evenodd") || String.Equals(clipRule, "nonzero")) { fillRule = clipRule; } if (fillRule == "evenodd") geometry.FillRule = FillRule.EvenOdd; else if (fillRule == "nonzero") geometry.FillRule = FillRule.Nonzero; SvgPointF initPoint = new SvgPointF(0, 0); SvgPointF lastPoint = new SvgPointF(0, 0); ISvgPathSeg segment = null; SvgPathSegMoveto pathMoveTo = null; SvgPathSegLineto pathLineTo = null; SvgPathSegCurveto pathCurveTo = null; SvgPathSegArc pathArc = null; ISvgPathSegList segments = element.PathSegList; int nElems = segments.NumberOfItems; PathFigure pathFigure = null; for (int i = 0; i < nElems; i++) { segment = segments.GetItem(i); if (DynamicCast.Cast(segment, out pathMoveTo)) { if (pathFigure != null) { pathFigure.IsClosed = false; pathFigure.IsFilled = true; geometry.Figures.Add(pathFigure); pathFigure = null; } lastPoint = initPoint = pathMoveTo.AbsXY; pathFigure = new PathFigure(); pathFigure.StartPoint = new Point(initPoint.ValueX, initPoint.ValueY); } else if (DynamicCast.Cast(segment, out pathLineTo)) { SvgPointF p = pathLineTo.AbsXY; pathFigure.Segments.Add(new LineSegment(new Point(p.ValueX, p.ValueY), true)); lastPoint = p; } else if (DynamicCast.Cast(segment, out pathCurveTo)) { SvgPointF xy = pathCurveTo.AbsXY; SvgPointF x1y1 = pathCurveTo.CubicX1Y1; SvgPointF x2y2 = pathCurveTo.CubicX2Y2; pathFigure.Segments.Add(new BezierSegment(new Point(x1y1.ValueX, x1y1.ValueY), new Point(x2y2.ValueX, x2y2.ValueY), new Point(xy.ValueX, xy.ValueY), true)); lastPoint = xy; } else if (DynamicCast.Cast(segment, out pathArc)) { SvgPointF p = pathArc.AbsXY; if (lastPoint.Equals(p)) { // If the endpoints (x, y) and (x0, y0) are identical, then this // is equivalent to omitting the elliptical arc segment entirely. } else if (pathArc.R1 == 0 || pathArc.R2 == 0) { // Ensure radii are valid pathFigure.Segments.Add(new LineSegment(new Point(p.ValueX, p.ValueY), true)); } else { CalculatedArcValues calcValues = pathArc.GetCalculatedArcValues(); pathFigure.Segments.Add(new ArcSegment(new Point(p.ValueX, p.ValueY), new Size(pathArc.R1, pathArc.R2), pathArc.Angle, pathArc.LargeArcFlag, pathArc.SweepFlag ? SweepDirection.Clockwise : SweepDirection.Counterclockwise, true)); } lastPoint = p; } else if (segment is SvgPathSegClosePath) { if (pathFigure != null) { pathFigure.IsClosed = true; pathFigure.IsFilled = true; geometry.Figures.Add(pathFigure); pathFigure = null; } lastPoint = initPoint; } } if (pathFigure != null) { pathFigure.IsClosed = false; pathFigure.IsFilled = true; geometry.Figures.Add(pathFigure); } return geometry; }
public void RenderMarker2(WpfDrawingRenderer renderer, WpfDrawingContext gr, SvgMarkerPosition markerPos, SvgStyleableElement refElement) { ISharpMarkerHost markerHostElm = (ISharpMarkerHost)refElement; SvgMarkerElement markerElm = (SvgMarkerElement)_svgElement; SvgPointF[] vertexPositions = markerHostElm.MarkerPositions; int start; int len; // Choose which part of the position array to use switch (markerPos) { case SvgMarkerPosition.Start: start = 0; len = 1; break; case SvgMarkerPosition.Mid: start = 1; len = vertexPositions.Length - 2; break; default: // == MarkerPosition.End start = vertexPositions.Length - 1; len = 1; break; } for (int i = start; i < start + len; i++) { SvgPointF point = vertexPositions[i]; //GdiGraphicsContainer gc = gr.BeginContainer(); this.BeforeRender(renderer); //Matrix matrix = Matrix.Identity; Matrix matrix = GetTransformMatrix(_svgElement); if (markerElm.OrientType.AnimVal.Equals((ushort)SvgMarkerOrient.Angle)) { matrix.Rotate(markerElm.OrientAngle.AnimVal.Value); } else { double angle = 0; switch (markerPos) { case SvgMarkerPosition.Start: angle = markerHostElm.GetStartAngle(i + 1); break; case SvgMarkerPosition.Mid: //angle = (markerHostElm.GetEndAngle(i) + markerHostElm.GetStartAngle(i + 1)) / 2; angle = SvgNumber.CalcAngleBisection(markerHostElm.GetEndAngle(i), markerHostElm.GetStartAngle(i + 1)); break; default: angle = markerHostElm.GetEndAngle(i); break; } matrix.Rotate(angle); } if (markerElm.MarkerUnits.AnimVal.Equals((ushort)SvgMarkerUnit.StrokeWidth)) { SvgLength strokeWidthLength = new SvgLength(refElement, "stroke-width", SvgLengthSource.Css, SvgLengthDirection.Viewport, "1"); double strokeWidth = strokeWidthLength.Value; matrix.Scale(strokeWidth, strokeWidth); } SvgPreserveAspectRatio spar = (SvgPreserveAspectRatio)markerElm.PreserveAspectRatio.AnimVal; double[] translateAndScale = spar.FitToViewBox((SvgRect)markerElm.ViewBox.AnimVal, new SvgRect(0, 0, markerElm.MarkerWidth.AnimVal.Value, markerElm.MarkerHeight.AnimVal.Value)); matrix.Translate(-markerElm.RefX.AnimVal.Value * translateAndScale[2], -markerElm.RefY.AnimVal.Value * translateAndScale[3]); matrix.Scale(translateAndScale[2], translateAndScale[3]); matrix.Translate(point.X, point.Y); _matrix = matrix; this.Render(renderer); //Clip(gr); renderer.RenderChildren(markerElm); //gr.EndContainer(gc); this.AfterRender(renderer); } }
public static GraphicsPath CreatePath(SvgPathElement element) { GraphicsPath gp = new GraphicsPath(); SvgPointF initPoint = new SvgPointF(0, 0); SvgPointF lastPoint = new SvgPointF(0, 0); SvgPointF ptXY = new SvgPointF(0, 0); SvgPathSeg segment = null; SvgPathSegMoveto pathMoveTo = null; SvgPathSegLineto pathLineTo = null; SvgPathSegCurveto pathCurveTo = null; SvgPathSegArc pathArc = null; SvgPathSegList segments = element.PathSegList; int nElems = segments.NumberOfItems; for (int i = 0; i < nElems; i++) { segment = segments.GetItem(i); switch (segment.PathType) { case SvgPathType.MoveTo: //if (DynamicCast.Cast(segment, out pathMoveTo)) pathMoveTo = (SvgPathSegMoveto)segment; gp.StartFigure(); lastPoint = initPoint = pathMoveTo.AbsXY; break; case SvgPathType.LineTo: //else if (DynamicCast.Cast(segment, out pathLineTo)) pathLineTo = (SvgPathSegLineto)segment; ptXY = pathLineTo.AbsXY; gp.AddLine(lastPoint.X, lastPoint.Y, ptXY.X, ptXY.Y); lastPoint = ptXY; break; case SvgPathType.CurveTo: //else if (DynamicCast.Cast(segment, out pathCurveTo)) pathCurveTo = (SvgPathSegCurveto)segment; SvgPointF xy = pathCurveTo.AbsXY; SvgPointF x1y1 = pathCurveTo.CubicX1Y1; SvgPointF x2y2 = pathCurveTo.CubicX2Y2; gp.AddBezier(lastPoint.X, lastPoint.Y, x1y1.X, x1y1.Y, x2y2.X, x2y2.Y, xy.X, xy.Y); lastPoint = xy; break; case SvgPathType.ArcTo: //else if (DynamicCast.Cast(segment, out pathArc)) pathArc = (SvgPathSegArc)segment; ptXY = pathArc.AbsXY; if (lastPoint.Equals(ptXY)) { // If the endpoints (x, y) and (x0, y0) are identical, then this // is equivalent to omitting the elliptical arc segment entirely. } else if (pathArc.R1.Equals(0) || pathArc.R2.Equals(0)) { // Ensure radii are valid gp.AddLine(lastPoint.X, lastPoint.Y, ptXY.X, ptXY.Y); } else { CalculatedArcValues calcValues = pathArc.GetCalculatedArcValues(); GraphicsPath subPath = new GraphicsPath(); subPath.StartFigure(); subPath.AddArc((float)(calcValues.Cx - calcValues.CorrRx), (float)(calcValues.Cy - calcValues.CorrRy), (float)calcValues.CorrRx * 2, (float)calcValues.CorrRy * 2, (float)calcValues.AngleStart, (float)calcValues.AngleExtent); Matrix matrix = new Matrix(); matrix.Translate(-(float)calcValues.Cx, -(float)calcValues.Cy); subPath.Transform(matrix); matrix = new Matrix(); matrix.Rotate((float)pathArc.Angle); subPath.Transform(matrix); matrix = new Matrix(); matrix.Translate((float)calcValues.Cx, (float)calcValues.Cy); subPath.Transform(matrix); gp.AddPath(subPath, true); } lastPoint = ptXY; break; case SvgPathType.Close: //else if (segment is SvgPathSegClosePath) gp.CloseFigure(); lastPoint = initPoint; break; } } string fillRule = element.GetPropertyValue("fill-rule"); if (fillRule == "evenodd") { gp.FillMode = FillMode.Alternate; } else { gp.FillMode = FillMode.Winding; } return(gp); }
/// <summary> /// Applies a clockwise rotation about the specified point to this /// <see cref="SvgTransformF"/> in the specified order. /// </summary> /// <param name="angle"> /// The angle (extent) of the rotation, in degrees. /// </param> /// <param name="point"> /// A <see cref="SvgPointF"/> that represents the center of the rotation. /// </param> /// <param name="order"> /// A <see cref="TransformOrder"/> that specifies the order (append or /// prepend) in which the rotation is applied. /// </param> public void RotateAt(float angle, SvgPointF point, SvgTransformOrder order) { if (order == SvgTransformOrder.Prepend) { Translate(point.X, point.Y); Rotate(angle); Translate(-point.X, -point.Y); } else { Translate(-point.X, -point.Y); Rotate(angle, SvgTransformOrder.Append); Translate(point.X, point.Y); } }