Exemplo n.º 1
0
        public void ApplyFilter(SvgVisualElement element, SvgRenderer renderer)
        {
            this.Buffer.Clear();
            this.PopulateDefaults(element, renderer);

            IEnumerable<SvgFilterPrimitive> primitives = this.Children.OfType<SvgFilterPrimitive>();

            if (primitives.Count() > 0)
            {
                foreach (var primitive in primitives)
                {
                    this.Buffer.Add(primitive.Result, (e, r) => primitive.Process());
                }

                // Render the final filtered image
                renderer.DrawImageUnscaled(this.Buffer.Last().Value(element, renderer), new Point(0, 0));
            }
        }
Exemplo n.º 2
0
        public void ApplyFilter(SvgVisualElement element, ISvgRenderer renderer, Action <ISvgRenderer> renderMethod)
        {
            using (var transform = GetTransform(element))
            {
                var bounds = GetPathBounds(element, renderer, transform);
                if (bounds.Width == 0f || bounds.Height == 0f)
                {
                    return;
                }

                var inflate = 0.5f;
                using (var buffer = new ImageBuffer(bounds, inflate, renderer, renderMethod)
                {
                    Transform = transform
                })
                {
                    foreach (var primitive in Children.OfType <SvgFilterPrimitive>())
                    {
                        primitive.Process(buffer);
                    }

                    // Render the final filtered image
                    var bufferImg = buffer.Buffer;
                    var imgDraw   = RectangleF.Inflate(bounds, inflate * bounds.Width, inflate * bounds.Height);

                    var prevClip = renderer.GetClip();
                    try
                    {
                        renderer.SetClip(new Region(imgDraw));
                        renderer.DrawImage(bufferImg, imgDraw, new RectangleF(bounds.X, bounds.Y, imgDraw.Width, imgDraw.Height), GraphicsUnit.Pixel);
                    }
                    finally
                    {
                        renderer.SetClip(prevClip);
                    }
                }
            }
        }
Exemplo n.º 3
0
        public static void CreateMarker(this SvgMarker svgMarker, SvgVisualElement pOwner, SKPoint pRefPoint, SKPoint pMarkerPoint1, SKPoint pMarkerPoint2, bool isStartMarker, SKRect skOwnerBounds, ref List <Drawable>?markerDrawables, CompositeDisposable disposable, Attributes ignoreAttributes = Attributes.None)
        {
            float fAngle1 = 0f;

            if (svgMarker.Orient.IsAuto)
            {
                float xDiff = pMarkerPoint2.X - pMarkerPoint1.X;
                float yDiff = pMarkerPoint2.Y - pMarkerPoint1.Y;
                fAngle1 = (float)(Math.Atan2(yDiff, xDiff) * 180.0 / Math.PI);
                if (isStartMarker && svgMarker.Orient.IsAutoStartReverse)
                {
                    fAngle1 += 180;
                }
            }

            var markerDrawable = new MarkerDrawable(svgMarker, pOwner, pRefPoint, fAngle1, skOwnerBounds, null, null, ignoreAttributes);

            if (markerDrawables == null)
            {
                markerDrawables = new List <Drawable>();
            }
            markerDrawables.Add(markerDrawable);
            disposable.Add(markerDrawable);
        }
Exemplo n.º 4
0
 private static SvgFillRule ToFillRule(SvgVisualElement svgVisualElement, SvgClipRule?svgClipPathClipRule)
 {
     var svgClipRule = svgClipPathClipRule is { } ? svgClipPathClipRule.Value : svgVisualElement.ClipRule;
        private static SvgFillRule ToFillRule(SvgVisualElement svgVisualElement, SvgClipRule?svgClipPathClipRule)
        {
            var svgClipRule = svgClipPathClipRule ?? svgVisualElement.ClipRule;

            return(svgClipRule == SvgClipRule.EvenOdd ? SvgFillRule.EvenOdd : SvgFillRule.NonZero);
        }
Exemplo n.º 6
0
        public static MarkerDrawable Create(SvgMarker svgMarker, SvgVisualElement pOwner, Point pMarkerPoint, float fAngle, Rect skOwnerBounds, DrawableBase?parent, IAssetLoader assetLoader, Attributes ignoreAttributes = Attributes.None)
        {
            var drawable = new MarkerDrawable(assetLoader)
            {
                Element          = svgMarker,
                Parent           = parent,
                IgnoreAttributes = Attributes.Display | ignoreAttributes,
                IsDrawable       = true
            };

            if (!drawable.IsDrawable)
            {
                return(drawable);
            }

            var markerElement = drawable.GetMarkerElement(svgMarker);

            if (markerElement is null)
            {
                drawable.IsDrawable = false;
                return(drawable);
            }

            var skMarkerMatrix = Matrix.CreateIdentity();

            var skMatrixMarkerPoint = Matrix.CreateTranslation(pMarkerPoint.X, pMarkerPoint.Y);

            skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixMarkerPoint);

            var skMatrixAngle = Matrix.CreateRotationDegrees(svgMarker.Orient.IsAuto ? fAngle : svgMarker.Orient.Angle);

            skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixAngle);

            var strokeWidth = pOwner.StrokeWidth.ToDeviceValue(UnitRenderingType.Other, svgMarker, skOwnerBounds);

            var refX         = svgMarker.RefX.ToDeviceValue(UnitRenderingType.Horizontal, svgMarker, skOwnerBounds);
            var refY         = svgMarker.RefY.ToDeviceValue(UnitRenderingType.Vertical, svgMarker, skOwnerBounds);
            var markerWidth  = svgMarker.MarkerWidth.ToDeviceValue(UnitRenderingType.Other, svgMarker, skOwnerBounds);
            var markerHeight = svgMarker.MarkerHeight.ToDeviceValue(UnitRenderingType.Other, svgMarker, skOwnerBounds);
            var viewBoxToMarkerUnitsScaleX = 1f;
            var viewBoxToMarkerUnitsScaleY = 1f;

            switch (svgMarker.MarkerUnits)
            {
            case SvgMarkerUnits.StrokeWidth:
            {
                var skMatrixStrokeWidth = Matrix.CreateScale(strokeWidth, strokeWidth);
                skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixStrokeWidth);

                var viewBoxWidth  = svgMarker.ViewBox.Width;
                var viewBoxHeight = svgMarker.ViewBox.Height;

                var scaleFactorWidth  = viewBoxWidth <= 0 ? 1 : markerWidth / viewBoxWidth;
                var scaleFactorHeight = viewBoxHeight <= 0 ? 1 : markerHeight / viewBoxHeight;

                viewBoxToMarkerUnitsScaleX = Math.Min(scaleFactorWidth, scaleFactorHeight);
                viewBoxToMarkerUnitsScaleY = Math.Min(scaleFactorWidth, scaleFactorHeight);

                var skMatrixTranslateRefXY = Matrix.CreateTranslation(-refX * viewBoxToMarkerUnitsScaleX, -refY * viewBoxToMarkerUnitsScaleY);
                skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixTranslateRefXY);

                var skMatrixScaleXY = Matrix.CreateScale(viewBoxToMarkerUnitsScaleX, viewBoxToMarkerUnitsScaleY);
                skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixScaleXY);
            }
            break;

            case SvgMarkerUnits.UserSpaceOnUse:
            {
                var skMatrixTranslateRefXY = Matrix.CreateTranslation(-refX, -refY);
                skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixTranslateRefXY);
            }
            break;
            }

            switch (svgMarker.Overflow)
            {
            case SvgOverflow.Auto:
            case SvgOverflow.Visible:
            case SvgOverflow.Inherit:
                break;

            default:
                drawable.MarkerClipRect = Rect.Create(
                    svgMarker.ViewBox.MinX,
                    svgMarker.ViewBox.MinY,
                    markerWidth / viewBoxToMarkerUnitsScaleX,
                    markerHeight / viewBoxToMarkerUnitsScaleY);
                break;
            }

            var markerElementDrawable = DrawableFactory.Create(markerElement, skOwnerBounds, drawable, assetLoader, Attributes.Display);

            if (markerElementDrawable is { })
Exemplo n.º 7
0
        private void PopulateDefaults(SvgVisualElement element, SvgRenderer renderer)
        {
            this.ResetDefaults();

            this.Buffer.Add(SvgFilterPrimitive.SourceGraphic, this.CreateSourceGraphic);
            this.Buffer.Add(SvgFilterPrimitive.SourceAlpha, this.CreateSourceAlpha);
        }
Exemplo n.º 8
0
        private Bitmap CreateSourceGraphic(SvgVisualElement element, SvgRenderer renderer)
        {
            if (this.sourceGraphic == null)
            {
                RectangleF bounds = element.Path.GetBounds();
                this.sourceGraphic = new Bitmap((int)bounds.Width, (int)bounds.Height);

                using (var graphics = Graphics.FromImage(this.sourceGraphic))
                {
                    graphics.Clip = renderer.Clip;
                    graphics.Transform = renderer.Transform;

                    element.RenderElement(SvgRenderer.FromGraphics(graphics));

                    graphics.Save();
                }
            }

            return this.sourceGraphic;
        }
Exemplo n.º 9
0
        private Bitmap CreateSourceAlpha(SvgVisualElement element, SvgRenderer renderer)
        {
            if (this.sourceAlpha == null)
            {
                Bitmap source = this.Buffer[SvgFilterPrimitive.SourceGraphic](element, renderer);

                float[][] colorMatrixElements = {
                   new float[] {0, 0, 0, 0, 0},        // red
                   new float[] {0, 0, 0, 0, 0},        // green
                   new float[] {0, 0, 0, 0, 0},        // blue
                   new float[] {0, 0, 0, 1, 1},        // alpha
                   new float[] {0, 0, 0, 0, 0} };    // translations

                var matrix = new ColorMatrix(colorMatrixElements);

                ImageAttributes attributes = new ImageAttributes();
                attributes.SetColorMatrix(matrix);

                this.sourceAlpha = new Bitmap(source.Width, source.Height);

                using (var graphics = Graphics.FromImage(this.sourceAlpha))
                {

                    graphics.DrawImage(source, new Rectangle(0, 0, source.Width, source.Height), 0, 0,
                          source.Width, source.Height, GraphicsUnit.Pixel, attributes);
                    graphics.Save();
                }
            }

            return this.sourceAlpha;
        }
Exemplo n.º 10
0
        public static SKPath?GetClipPath(SvgVisualElement svgVisualElement, SKRect skBounds, HashSet <Uri> uris, CompositeDisposable disposable)
        {
            if (!CanDraw(svgVisualElement, Attributes.None))
            {
                return(null);
            }
            switch (svgVisualElement)
            {
            case SvgPath svgPath:
            {
                var fillRule = (svgPath.ClipRule == SvgClipRule.EvenOdd) ? SvgFillRule.EvenOdd : SvgFillRule.NonZero;
                var skPath   = svgPath.PathData?.ToSKPath(fillRule, disposable);
                if (skPath != null)
                {
                    var skMatrix = SvgTransformsExtensions.ToSKMatrix(svgPath.Transforms);
                    skPath.Transform(skMatrix);

                    var skPathClip = GetSvgVisualElementClipPath(svgPath, skPath.Bounds, uris, disposable);
                    if (skPathClip != null)
                    {
                        var result = skPath.Op(skPathClip, SKPathOp.Intersect);
                        disposable.Add(result);
                        return(result);
                    }

                    return(skPath);
                }
            }
            break;

            case SvgRectangle svgRectangle:
            {
                var fillRule = (svgRectangle.ClipRule == SvgClipRule.EvenOdd) ? SvgFillRule.EvenOdd : SvgFillRule.NonZero;
                var skPath   = svgRectangle.ToSKPath(fillRule, skBounds, disposable);
                if (skPath != null)
                {
                    var skMatrix = SvgTransformsExtensions.ToSKMatrix(svgRectangle.Transforms);
                    skPath.Transform(skMatrix);

                    var skPathClip = GetSvgVisualElementClipPath(svgRectangle, skPath.Bounds, uris, disposable);
                    if (skPathClip != null)
                    {
                        var result = skPath.Op(skPathClip, SKPathOp.Intersect);
                        disposable.Add(result);
                        return(result);
                    }

                    return(skPath);
                }
            }
            break;

            case SvgCircle svgCircle:
            {
                var fillRule = (svgCircle.ClipRule == SvgClipRule.EvenOdd) ? SvgFillRule.EvenOdd : SvgFillRule.NonZero;
                var skPath   = svgCircle.ToSKPath(fillRule, skBounds, disposable);
                if (skPath != null)
                {
                    var skMatrix = SvgTransformsExtensions.ToSKMatrix(svgCircle.Transforms);
                    skPath.Transform(skMatrix);

                    var skPathClip = GetSvgVisualElementClipPath(svgCircle, skPath.Bounds, uris, disposable);
                    if (skPathClip != null)
                    {
                        var result = skPath.Op(skPathClip, SKPathOp.Intersect);
                        disposable.Add(result);
                        return(result);
                    }

                    return(skPath);
                }
            }
            break;

            case SvgEllipse svgEllipse:
            {
                var fillRule = (svgEllipse.ClipRule == SvgClipRule.EvenOdd) ? SvgFillRule.EvenOdd : SvgFillRule.NonZero;
                var skPath   = svgEllipse.ToSKPath(fillRule, skBounds, disposable);
                if (skPath != null)
                {
                    var skMatrix = SvgTransformsExtensions.ToSKMatrix(svgEllipse.Transforms);
                    skPath.Transform(skMatrix);

                    var skPathClip = GetSvgVisualElementClipPath(svgEllipse, skPath.Bounds, uris, disposable);
                    if (skPathClip != null)
                    {
                        var result = skPath.Op(skPathClip, SKPathOp.Intersect);
                        disposable.Add(result);
                        return(result);
                    }

                    return(skPath);
                }
            }
            break;

            case SvgLine svgLine:
            {
                var fillRule = (svgLine.ClipRule == SvgClipRule.EvenOdd) ? SvgFillRule.EvenOdd : SvgFillRule.NonZero;
                var skPath   = svgLine.ToSKPath(fillRule, skBounds, disposable);
                if (skPath != null)
                {
                    var skMatrix = SvgTransformsExtensions.ToSKMatrix(svgLine.Transforms);
                    skPath.Transform(skMatrix);

                    var skPathClip = GetSvgVisualElementClipPath(svgLine, skPath.Bounds, uris, disposable);
                    if (skPathClip != null)
                    {
                        var result = skPath.Op(skPathClip, SKPathOp.Intersect);
                        disposable.Add(result);
                        return(result);
                    }

                    return(skPath);
                }
            }
            break;

            case SvgPolyline svgPolyline:
            {
                var fillRule = (svgPolyline.ClipRule == SvgClipRule.EvenOdd) ? SvgFillRule.EvenOdd : SvgFillRule.NonZero;
                var skPath   = svgPolyline.Points?.ToSKPath(fillRule, false, skBounds, disposable);
                if (skPath != null)
                {
                    var skMatrix = SvgTransformsExtensions.ToSKMatrix(svgPolyline.Transforms);
                    skPath.Transform(skMatrix);

                    var skPathClip = GetSvgVisualElementClipPath(svgPolyline, skPath.Bounds, uris, disposable);
                    if (skPathClip != null)
                    {
                        var result = skPath.Op(skPathClip, SKPathOp.Intersect);
                        disposable.Add(result);
                        return(result);
                    }

                    return(skPath);
                }
            }
            break;

            case SvgPolygon svgPolygon:
            {
                var fillRule = (svgPolygon.ClipRule == SvgClipRule.EvenOdd) ? SvgFillRule.EvenOdd : SvgFillRule.NonZero;
                var skPath   = svgPolygon.Points?.ToSKPath(fillRule, true, skBounds, disposable);
                if (skPath != null)
                {
                    var skMatrix = SvgTransformsExtensions.ToSKMatrix(svgPolygon.Transforms);
                    skPath.Transform(skMatrix);

                    var skPathClip = GetSvgVisualElementClipPath(svgPolygon, skPath.Bounds, uris, disposable);
                    if (skPathClip != null)
                    {
                        var result = skPath.Op(skPathClip, SKPathOp.Intersect);
                        disposable.Add(result);
                        return(result);
                    }

                    return(skPath);
                }
            }
            break;

            case SvgUse svgUse:
            {
                if (SvgExtensions.HasRecursiveReference(svgUse, (e) => e.ReferencedElement, new HashSet <Uri>()))
                {
                    break;
                }

                var svgReferencedVisualElement = SvgExtensions.GetReference <SvgVisualElement>(svgUse, svgUse.ReferencedElement);
                if (svgReferencedVisualElement == null || svgReferencedVisualElement is SvgSymbol)
                {
                    break;
                }

                if (!CanDraw(svgReferencedVisualElement, Attributes.None))
                {
                    break;
                }

                var skPath = GetClipPath(svgReferencedVisualElement, skBounds, uris, disposable);
                if (skPath != null)
                {
                    var skMatrix = SvgTransformsExtensions.ToSKMatrix(svgUse.Transforms);
                    skPath.Transform(skMatrix);

                    var skPathClip = GetSvgVisualElementClipPath(svgUse, skPath.Bounds, uris, disposable);
                    if (skPathClip != null)
                    {
                        var result = skPath.Op(skPathClip, SKPathOp.Intersect);
                        disposable.Add(result);
                        return(result);
                    }

                    return(skPath);
                }
            }
            break;

            case SvgText svgText:
            {
                // TODO: Get path from SvgText.
            }
            break;

            default:
                break;
            }
            return(null);
        }
Exemplo n.º 11
0
        public MarkerDrawable(SvgMarker svgMarker, SvgVisualElement pOwner, SKPoint pMarkerPoint, float fAngle, SKRect skOwnerBounds, Drawable?root, Drawable?parent, Attributes ignoreAttributes = Attributes.None)
            : base(svgMarker, root, parent)
        {
            IgnoreAttributes = Attributes.Display | ignoreAttributes;
            IsDrawable       = true;

            if (!IsDrawable)
            {
                return;
            }

            var markerElement = GetMarkerElement(svgMarker);

            if (markerElement == null)
            {
                IsDrawable = false;
                return;
            }

            var skMarkerMatrix = SKMatrix.MakeIdentity();

            var skMatrixMarkerPoint = SKMatrix.MakeTranslation(pMarkerPoint.X, pMarkerPoint.Y);

            skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixMarkerPoint);

            var skMatrixAngle = SKMatrix.MakeRotationDegrees(svgMarker.Orient.IsAuto ? fAngle : svgMarker.Orient.Angle);

            skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixAngle);

            var strokeWidth = pOwner.StrokeWidth.ToDeviceValue(UnitRenderingType.Other, svgMarker, skOwnerBounds);

            var   refX         = svgMarker.RefX.ToDeviceValue(UnitRenderingType.Horizontal, svgMarker, skOwnerBounds);
            var   refY         = svgMarker.RefY.ToDeviceValue(UnitRenderingType.Vertical, svgMarker, skOwnerBounds);
            float markerWidth  = svgMarker.MarkerWidth.ToDeviceValue(UnitRenderingType.Other, svgMarker, skOwnerBounds);
            float markerHeight = svgMarker.MarkerHeight.ToDeviceValue(UnitRenderingType.Other, svgMarker, skOwnerBounds);
            float viewBoxToMarkerUnitsScaleX = 1f;
            float viewBoxToMarkerUnitsScaleY = 1f;

            switch (svgMarker.MarkerUnits)
            {
            case SvgMarkerUnits.StrokeWidth:
            {
                var skMatrixStrokeWidth = SKMatrix.MakeScale(strokeWidth, strokeWidth);
                skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixStrokeWidth);

                var viewBoxWidth  = svgMarker.ViewBox.Width;
                var viewBoxHeight = svgMarker.ViewBox.Height;

                var scaleFactorWidth  = (viewBoxWidth <= 0) ? 1 : (markerWidth / viewBoxWidth);
                var scaleFactorHeight = (viewBoxHeight <= 0) ? 1 : (markerHeight / viewBoxHeight);

                viewBoxToMarkerUnitsScaleX = Math.Min(scaleFactorWidth, scaleFactorHeight);
                viewBoxToMarkerUnitsScaleY = Math.Min(scaleFactorWidth, scaleFactorHeight);

                var skMatrixTranslateRefXY = SKMatrix.MakeTranslation(-refX * viewBoxToMarkerUnitsScaleX, -refY * viewBoxToMarkerUnitsScaleY);
                skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixTranslateRefXY);

                var skMatrixScaleXY = SKMatrix.MakeScale(viewBoxToMarkerUnitsScaleX, viewBoxToMarkerUnitsScaleY);
                skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixScaleXY);
            }
            break;

            case SvgMarkerUnits.UserSpaceOnUse:
            {
                var skMatrixTranslateRefXY = SKMatrix.MakeTranslation(-refX, -refY);
                skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixTranslateRefXY);
            }
            break;
            }

            switch (svgMarker.Overflow)
            {
            case SvgOverflow.Auto:
            case SvgOverflow.Visible:
            case SvgOverflow.Inherit:
                break;

            default:
                MarkerClipRect = SKRect.Create(
                    svgMarker.ViewBox.MinX,
                    svgMarker.ViewBox.MinY,
                    markerWidth / viewBoxToMarkerUnitsScaleX,
                    markerHeight / viewBoxToMarkerUnitsScaleY);
                break;
            }

            var drawable = DrawableFactory.Create(markerElement, skOwnerBounds, root, this, Attributes.Display);

            if (drawable != null)
            {
                MarkerElementDrawable = drawable;
                _disposable.Add(MarkerElementDrawable);
            }
            else
            {
                IsDrawable = false;
                return;
            }

            IsAntialias = SvgPaintingExtensions.IsAntialias(svgMarker);

            TransformedBounds = MarkerElementDrawable.TransformedBounds;

            Transform = SvgTransformsExtensions.ToSKMatrix(svgMarker.Transforms);
            Transform = Transform.PreConcat(skMarkerMatrix);

            Fill   = null;
            Stroke = null;

            // TODO: Transform _skBounds using _skMatrix.
            TransformedBounds = Transform.MapRect(TransformedBounds);
        }
Exemplo n.º 12
0
 /// <summary>
 /// Svgエレメント=>Uiエレメント作成
 /// </summary>
 /// <param name="svgVisualElementType">編集対象のSvgエレメントタイプ</param>
 /// <param name="svgVisualElement">編集対象のSvgエレメント</param>
 private FrameworkElement GenerateUiElement(Type svgVisualElementType, SvgVisualElement svgVisualElement)
 {
     return(null);
 }
Exemplo n.º 13
0
        internal void DrawMarker(SvgMarker svgMarker, SvgVisualElement pOwner, SKPoint pMarkerPoint, float fAngle)
        {
            var markerElement = GetMarkerElement(svgMarker);

            if (markerElement == null)
            {
                return;
            }

            var skMarkerMatrix = SKMatrix.MakeIdentity();

            var skMatrixMarkerPoint = SKMatrix.MakeTranslation(pMarkerPoint.X, pMarkerPoint.Y);

            SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixMarkerPoint);

            var skMatrixAngle = SKMatrix.MakeRotationDegrees(svgMarker.Orient.IsAuto ? fAngle : svgMarker.Orient.Angle);

            SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixAngle);

            var strokeWidth = pOwner.StrokeWidth.ToDeviceValue(null, UnitRenderingType.Other, svgMarker);

            var   refX         = svgMarker.RefX.ToDeviceValue(null, UnitRenderingType.Horizontal, svgMarker);
            var   refY         = svgMarker.RefY.ToDeviceValue(null, UnitRenderingType.Horizontal, svgMarker);
            float markerWidth  = svgMarker.MarkerWidth;
            float markerHeight = svgMarker.MarkerHeight;
            float viewBoxToMarkerUnitsScaleX = 1f;
            float viewBoxToMarkerUnitsScaleY = 1f;

            switch (svgMarker.MarkerUnits)
            {
            case SvgMarkerUnits.StrokeWidth:
            {
                var skMatrixStrokeWidth = SKMatrix.MakeScale(strokeWidth, strokeWidth);
                SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixStrokeWidth);

                var viewBoxWidth  = svgMarker.ViewBox.Width;
                var viewBoxHeight = svgMarker.ViewBox.Height;

                var scaleFactorWidth  = (viewBoxWidth <= 0) ? 1 : (markerWidth / viewBoxWidth);
                var scaleFactorHeight = (viewBoxHeight <= 0) ? 1 : (markerHeight / viewBoxHeight);

                viewBoxToMarkerUnitsScaleX = Math.Min(scaleFactorWidth, scaleFactorHeight);
                viewBoxToMarkerUnitsScaleY = Math.Min(scaleFactorWidth, scaleFactorHeight);

                var skMatrixTranslateRefXY = SKMatrix.MakeTranslation(-refX * viewBoxToMarkerUnitsScaleX, -refY * viewBoxToMarkerUnitsScaleY);
                SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixTranslateRefXY);

                var skMatrixScaleXY = SKMatrix.MakeScale(viewBoxToMarkerUnitsScaleX, viewBoxToMarkerUnitsScaleY);
                SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixScaleXY);
            }
            break;

            case SvgMarkerUnits.UserSpaceOnUse:
            {
                var skMatrixTranslateRefXY = SKMatrix.MakeTranslation(-refX, -refY);
                SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixTranslateRefXY);
            }
            break;
            }

            _skCanvas.Save();

            var skMatrix = SkiaUtil.GetSKMatrix(svgMarker.Transforms);

            SKMatrix.PreConcat(ref skMatrix, ref skMarkerMatrix);
            SetTransform(skMatrix);
            SetClipPath(svgMarker, _disposable);

            var skPaintOpacity = SetOpacity(svgMarker, _disposable);

            var skPaintFilter = SetFilter(svgMarker, _disposable);

            switch (svgMarker.Overflow)
            {
            case SvgOverflow.Auto:
            case SvgOverflow.Visible:
            case SvgOverflow.Inherit:
                break;

            default:
                var skClipRect = SKRect.Create(
                    svgMarker.ViewBox.MinX,
                    svgMarker.ViewBox.MinY,
                    markerWidth / viewBoxToMarkerUnitsScaleX,
                    markerHeight / viewBoxToMarkerUnitsScaleY);
                _skCanvas.ClipRect(skClipRect, SKClipOperation.Intersect);
                break;
            }

            Draw(markerElement, true);

            if (skPaintFilter != null)
            {
                _skCanvas.Restore();
            }

            if (skPaintOpacity != null)
            {
                _skCanvas.Restore();
            }

            _skCanvas.Restore();
        }
 public override Brush GetBrush(SvgVisualElement styleOwner, ISvgRenderer renderer, float opacity, bool forStroke = false)
 {
     return(new SolidBrush(_Color));
 }