internal void DrawMarkers(SvgMarkerElement svgMarkerElement, SKPath sKPath) { var pathTypes = SkiaUtil.GetPathTypes(sKPath); var pathLength = pathTypes.Count; if (svgMarkerElement.MarkerStart != null) { var refPoint1 = pathTypes[0].Point; var index = 1; while (index < pathLength && pathTypes[index].Point == refPoint1) { ++index; } var refPoint2 = pathTypes[index].Point; var marker = svgMarkerElement.OwnerDocument.GetElementById <SvgMarker>(svgMarkerElement.MarkerStart.ToString()); DrawMarker(marker, svgMarkerElement, refPoint1, refPoint1, refPoint2, true); } if (svgMarkerElement.MarkerMid != null) { var marker = svgMarkerElement.OwnerDocument.GetElementById <SvgMarker>(svgMarkerElement.MarkerMid.ToString()); int bezierIndex = -1; for (int i = 1; i <= pathLength - 2; i++) { // for Bezier curves, the marker shall only been shown at the last point if ((pathTypes[i].Type & (byte)PathPointType.PathTypeMask) == (byte)PathPointType.Bezier) { bezierIndex = (bezierIndex + 1) % 3; } else { bezierIndex = -1; } if (bezierIndex == -1 || bezierIndex == 2) { DrawMarker(marker, svgMarkerElement, pathTypes[i].Point, pathTypes[i - 1].Point, pathTypes[i].Point, pathTypes[i + 1].Point); } } } if (svgMarkerElement.MarkerEnd != null) { var marker = svgMarkerElement.OwnerDocument.GetElementById <SvgMarker>(svgMarkerElement.MarkerEnd.ToString()); var index = pathLength - 1; var refPoint1 = pathTypes[index].Point; --index; while (index > 0 && pathTypes[index].Point == refPoint1) { --index; } var refPoint2 = pathTypes[index].Point; DrawMarker(marker, svgMarkerElement, refPoint1, refPoint2, pathTypes[pathLength - 1].Point, false); } }
protected override void Initialize(SvgElement element) { base.Initialize(element); _matrix = Matrix.Identity; _drawGroup = null; _hostElement = null; _pathFigures = null; _markerElement = element as SvgMarkerElement; }
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 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 WpfMarkerRendering(SvgElement element) : base(element) { _markerElement = element as SvgMarkerElement; }
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 static void CreateMarkers(this SvgMarkerElement svgMarkerElement, SKPath skPath, SKRect skOwnerBounds, ref List <Drawable>?markerDrawables, CompositeDisposable disposable) { var pathTypes = skPath.GetPathTypes(); var pathLength = pathTypes.Count; var markerStart = svgMarkerElement.MarkerStart; if (markerStart != null && pathLength > 0 && !SvgExtensions.HasRecursiveReference(svgMarkerElement, (e) => e.MarkerStart, new HashSet <Uri>())) { var marker = SvgExtensions.GetReference <SvgMarker>(svgMarkerElement, markerStart); if (marker != null) { var refPoint1 = pathTypes[0].Point; var index = 1; while (index < pathLength && pathTypes[index].Point == refPoint1) { ++index; } var refPoint2 = pathLength == 1 ? refPoint1 : pathTypes[index].Point; CreateMarker(marker, svgMarkerElement, refPoint1, refPoint1, refPoint2, true, skOwnerBounds, ref markerDrawables, disposable); } } var markerMid = svgMarkerElement.MarkerMid; if (markerMid != null && pathLength > 0 && !SvgExtensions.HasRecursiveReference(svgMarkerElement, (e) => e.MarkerMid, new HashSet <Uri>())) { var marker = SvgExtensions.GetReference <SvgMarker>(svgMarkerElement, markerMid); if (marker != null) { int bezierIndex = -1; for (int i = 1; i <= pathLength - 2; i++) { // for Bezier curves, the marker shall only been shown at the last point if ((pathTypes[i].Type & (byte)PathPointType.PathTypeMask) == (byte)PathPointType.Bezier) { bezierIndex = (bezierIndex + 1) % 3; } else { bezierIndex = -1; } if (bezierIndex == -1 || bezierIndex == 2) { CreateMarker(marker, svgMarkerElement, pathTypes[i].Point, pathTypes[i - 1].Point, pathTypes[i].Point, pathTypes[i + 1].Point, skOwnerBounds, ref markerDrawables, disposable); } } } } var markerEnd = svgMarkerElement.MarkerEnd; if (markerEnd != null && pathLength > 0 && !SvgExtensions.HasRecursiveReference(svgMarkerElement, (e) => e.MarkerEnd, new HashSet <Uri>())) { var marker = SvgExtensions.GetReference <SvgMarker>(svgMarkerElement, markerEnd); if (marker != null) { var index = pathLength - 1; var refPoint1 = pathTypes[index].Point; if (pathLength > 1) { --index; while (index > 0 && pathTypes[index].Point == refPoint1) { --index; } } var refPoint2 = pathLength == 1 ? refPoint1 : pathTypes[index].Point; CreateMarker(marker, svgMarkerElement, refPoint1, refPoint2, pathTypes[pathLength - 1].Point, false, skOwnerBounds, ref markerDrawables, disposable); } } }
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); } }