예제 #1
0
        public static SKPath?GetSvgVisualElementClipPath(SvgVisualElement svgVisualElement, SKRect skBounds, HashSet <Uri> uris, CompositeDisposable disposable)
        {
            if (svgVisualElement == null || svgVisualElement.ClipPath == null)
            {
                return(null);
            }

            if (SvgExtensions.HasRecursiveReference(svgVisualElement, (e) => e.ClipPath, uris))
            {
                return(null);
            }

            var svgClipPath = SvgExtensions.GetReference <SvgClipPath>(svgVisualElement, svgVisualElement.ClipPath);

            if (svgClipPath == null || svgClipPath.Children == null)
            {
                return(null);
            }

            return(GetClipPath(svgClipPath, skBounds, uris, disposable));
        }
예제 #2
0
        public static MaskDrawable?GetSvgElementMask(SvgElement svgElement, SKRect skBounds, HashSet <Uri> uris, CompositeDisposable disposable)
        {
            var svgMaskRef = svgElement.GetUriElementReference <SvgMask>("mask", uris);

            if (svgMaskRef == null || svgMaskRef.Children == null)
            {
                return(null);
            }
            var maskDrawable = new MaskDrawable(svgMaskRef, skBounds, null, null, Attributes.None);

            disposable.Add(maskDrawable);
            return(maskDrawable);
        }
예제 #3
0
        public static SKPath?GetClipPath(SvgClipPath svgClipPath, SKRect skBounds, HashSet <Uri> uris, CompositeDisposable disposable)
        {
            var skPathClip = default(SKPath);

            var clipPathClipPath = GetClipPathClipPath(svgClipPath, skBounds, uris, disposable);

            if (clipPathClipPath != null && !clipPathClipPath.IsEmpty)
            {
                skPathClip = clipPathClipPath;
            }

            var clipPath = GetClipPath(svgClipPath.Children, skBounds, uris, disposable);

            if (clipPath != null)
            {
                var skMatrix = SKMatrix.MakeIdentity();

                if (svgClipPath.ClipPathUnits == SvgCoordinateUnits.ObjectBoundingBox)
                {
                    var skScaleMatrix = SKMatrix.MakeScale(skBounds.Width, skBounds.Height);
                    skMatrix = skMatrix.PostConcat(skScaleMatrix);

                    var skTranslateMatrix = SKMatrix.MakeTranslation(skBounds.Left, skBounds.Top);
                    skMatrix = skMatrix.PostConcat(skTranslateMatrix);
                }

                var skTransformsMatrix = SvgTransformsExtensions.ToSKMatrix(svgClipPath.Transforms);
                skMatrix = skMatrix.PostConcat(skTransformsMatrix);

                clipPath.Transform(skMatrix);

                if (skPathClip == null)
                {
                    skPathClip = clipPath;
                }
                else
                {
                    var result = skPathClip.Op(clipPath, SKPathOp.Intersect);
                    disposable.Add(result);
                    skPathClip = result;
                }
            }

            if (skPathClip == null)
            {
                skPathClip = new SKPath();
                disposable.Add(skPathClip);
            }

            return(skPathClip);
        }
예제 #4
0
        public static SKPath?GetClipPathClipPath(SvgClipPath svgClipPath, SKRect skBounds, HashSet <Uri> uris, CompositeDisposable disposable)
        {
            var svgClipPathRef = svgClipPath.GetUriElementReference <SvgClipPath>("clip-path", uris);

            if (svgClipPathRef == null || svgClipPathRef.Children == null)
            {
                return(null);
            }

            var clipPath = GetClipPath(svgClipPathRef, skBounds, uris, disposable);

            if (clipPath != null)
            {
                var skMatrix = SKMatrix.MakeIdentity();

                if (svgClipPathRef.ClipPathUnits == SvgCoordinateUnits.ObjectBoundingBox)
                {
                    var skScaleMatrix = SKMatrix.MakeScale(skBounds.Width, skBounds.Height);
                    skMatrix = skMatrix.PostConcat(skScaleMatrix);

                    var skTranslateMatrix = SKMatrix.MakeTranslation(skBounds.Left, skBounds.Top);
                    skMatrix = skMatrix.PostConcat(skTranslateMatrix);
                }

                var skTransformsMatrix = SvgTransformsExtensions.ToSKMatrix(svgClipPathRef.Transforms);
                skMatrix = skMatrix.PostConcat(skTransformsMatrix);

                clipPath.Transform(skMatrix);
            }

            return(clipPath);
        }
예제 #5
0
        private static SKPath?GetClipPath(SvgElementCollection svgElementCollection, SKRect skBounds, HashSet <Uri> uris, CompositeDisposable disposable)
        {
            var skPathClip = default(SKPath);

            foreach (var svgElement in svgElementCollection)
            {
                if (svgElement is SvgVisualElement visualChild)
                {
                    if (!CanDraw(visualChild, Attributes.None))
                    {
                        continue;
                    }
                    var skPath = GetClipPath(visualChild, skBounds, uris, disposable);
                    if (skPath != null)
                    {
                        if (skPathClip == null)
                        {
                            skPathClip = skPath;
                        }
                        else
                        {
                            var result = skPathClip.Op(skPath, SKPathOp.Union);
                            disposable.Add(result);
                            skPathClip = result;
                        }
                    }
                }
            }

            return(skPathClip);
        }
예제 #6
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);
        }
예제 #7
0
 public SKSvgRenderer(SKCanvas skCanvas, SKSize skSize)
 {
     _skCanvas   = skCanvas;
     _skSize     = skSize;
     _disposable = new CompositeDisposable();
 }