Exemple #1
0
        public static SKPicture?ToPicture(SvgFragment svgFragment)
        {
            var skSize   = SvgExtensions.GetDimensions(svgFragment);
            var skBounds = SKRect.Create(skSize);

            using var drawable = DrawableFactory.Create(svgFragment, skBounds, null, null, Attributes.None);
            if (drawable == null)
            {
                return(null);
            }

            drawable.PostProcess();

            if (skBounds.IsEmpty)
            {
                skBounds = GetBounds(drawable);
            }

            using var skPictureRecorder = new SKPictureRecorder();
            using var skCanvas          = skPictureRecorder.BeginRecording(skBounds);
#if USE_EXPERIMENTAL_LINEAR_RGB
            // TODO:
            using var skPaint       = new SKPaint();
            using var skColorFilter = SKColorFilter.CreateTable(null, SvgPaintingExtensions.s_LinearRGBtoSRGB, SvgPaintingExtensions.s_LinearRGBtoSRGB, SvgPaintingExtensions.s_LinearRGBtoSRGB);
            using var skImageFilter = SKImageFilter.CreateColorFilter(skColorFilter);
            skPaint.ImageFilter     = skImageFilter;
            skCanvas.SaveLayer(skPaint);
#endif
            drawable?.Draw(skCanvas, 0f, 0f);
#if USE_EXPERIMENTAL_LINEAR_RGB
            // TODO:
            skCanvas.Restore();
#endif
            return(skPictureRecorder.EndRecording());
        }
Exemple #2
0
        public static void Draw(SKCanvas skCanvas, SvgFragment svgFragment)
        {
            var skSize   = SvgExtensions.GetDimensions(svgFragment);
            var skBounds = SKRect.Create(skSize);

            using var drawable = DrawableFactory.Create(svgFragment, skBounds, null, null, Attributes.None);
            drawable?.PostProcess();
            drawable?.Draw(skCanvas, 0f, 0f);
        }
Exemple #3
0
        public static Drawable?ToDrawable(SvgFragment svgFragment)
        {
            var skSize   = SvgExtensions.GetDimensions(svgFragment);
            var skBounds = SKRect.Create(skSize);
            var drawable = DrawableFactory.Create(svgFragment, skBounds, null, null, Attributes.None);

            drawable?.PostProcess();
            return(drawable);
        }
Exemple #4
0
        public static void Draw(SkiaSharp.SKCanvas skCanvas, SvgFragment svgFragment)
        {
            var references = new HashSet <Uri> {
                svgFragment.OwnerDocument.BaseUri
            };
            var size     = SvgExtensions.GetDimensions(svgFragment);
            var bounds   = SKRect.Create(size);
            var drawable = DrawableFactory.Create(svgFragment, bounds, null, s_assetLoader, references);

            if (drawable is { })
Exemple #5
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));
        }
Exemple #6
0
        public static SKPicture?ToPicture(SvgFragment svgFragment, out Drawable?drawable)
        {
            var skSize   = SvgExtensions.GetDimensions(svgFragment);
            var skBounds = SKRect.Create(skSize);

            drawable = DrawableFactory.Create(svgFragment, skBounds, null, null, Attributes.None);
            if (drawable == null)
            {
                return(null);
            }

            drawable.PostProcess();

            if (skBounds.IsEmpty)
            {
                skBounds = GetBounds(drawable);
            }

            using var skPictureRecorder = new SKPictureRecorder();
            using var skCanvas          = skPictureRecorder.BeginRecording(skBounds);
            drawable?.Draw(skCanvas, 0f, 0f);
            return(skPictureRecorder.EndRecording());
        }
Exemple #7
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);
        }
Exemple #8
0
        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);
                }
            }
        }
Exemple #9
0
        public UseDrawable(SvgUse svgUse, SKRect skOwnerBounds, Drawable?root, Drawable?parent, Attributes ignoreAttributes = Attributes.None)
            : base(svgUse, root, parent)
        {
            IgnoreAttributes = ignoreAttributes;
            IsDrawable       = CanDraw(svgUse, IgnoreAttributes) && HasFeatures(svgUse, IgnoreAttributes);

            if (!IsDrawable)
            {
                return;
            }

            if (SvgExtensions.HasRecursiveReference(svgUse, (e) => e.ReferencedElement, new HashSet <Uri>()))
            {
                IsDrawable = false;
                return;
            }

            var svgReferencedElement = SvgExtensions.GetReference <SvgElement>(svgUse, svgUse.ReferencedElement);

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

            float x      = svgUse.X.ToDeviceValue(UnitRenderingType.Horizontal, svgUse, skOwnerBounds);
            float y      = svgUse.Y.ToDeviceValue(UnitRenderingType.Vertical, svgUse, skOwnerBounds);
            float width  = svgUse.Width.ToDeviceValue(UnitRenderingType.Horizontal, svgUse, skOwnerBounds);
            float height = svgUse.Height.ToDeviceValue(UnitRenderingType.Vertical, svgUse, skOwnerBounds);

            if (width <= 0f)
            {
                width = new SvgUnit(SvgUnitType.Percentage, 100f).ToDeviceValue(UnitRenderingType.Horizontal, svgUse, skOwnerBounds);
            }

            if (height <= 0f)
            {
                height = new SvgUnit(SvgUnitType.Percentage, 100f).ToDeviceValue(UnitRenderingType.Vertical, svgUse, skOwnerBounds);
            }

            var originalReferencedElementParent = svgReferencedElement.Parent;
            var referencedElementParent         = default(FieldInfo);

            try
            {
                referencedElementParent = svgReferencedElement.GetType().GetField("_parent", BindingFlags.NonPublic | BindingFlags.Instance);
                if (referencedElementParent != null)
                {
                    referencedElementParent.SetValue(svgReferencedElement, svgUse);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                Debug.WriteLine(ex.StackTrace);
            }

            svgReferencedElement.InvalidateChildPaths();

            if (svgReferencedElement is SvgSymbol svgSymbol)
            {
                ReferencedDrawable = new SymbolDrawable(svgSymbol, x, y, width, height, skOwnerBounds, root, this, ignoreAttributes);
                _disposable.Add(ReferencedDrawable);
            }
            else
            {
                var drawable = DrawableFactory.Create(svgReferencedElement, skOwnerBounds, root, this, ignoreAttributes);
                if (drawable != null)
                {
                    ReferencedDrawable = drawable;
                    _disposable.Add(ReferencedDrawable);
                }
                else
                {
                    IsDrawable = false;
                    return;
                }
            }

            IsAntialias = SvgPaintingExtensions.IsAntialias(svgUse);

            TransformedBounds = ReferencedDrawable.TransformedBounds;

            Transform = SvgTransformsExtensions.ToSKMatrix(svgUse.Transforms);
            if (!(svgReferencedElement is SvgSymbol))
            {
                var skMatrixTranslateXY = SKMatrix.MakeTranslation(x, y);
                Transform = Transform.PreConcat(skMatrixTranslateXY);
            }

            Fill   = null;
            Stroke = null;

            // TODO: Transform _skBounds using _skMatrix.
            TransformedBounds = Transform.MapRect(TransformedBounds);

            try
            {
                if (referencedElementParent != null)
                {
                    referencedElementParent.SetValue(svgReferencedElement, originalReferencedElementParent);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                Debug.WriteLine(ex.StackTrace);
            }
        }
Exemple #10
0
        public ImageDrawable(SvgImage svgImage, SKRect skOwnerBounds, Drawable?root, Drawable?parent, Attributes ignoreAttributes = Attributes.None)
            : base(svgImage, root, parent)
        {
            IgnoreAttributes = ignoreAttributes;
            IsDrawable       = CanDraw(svgImage, IgnoreAttributes) && HasFeatures(svgImage, IgnoreAttributes);

            if (!IsDrawable)
            {
                return;
            }

            float width    = svgImage.Width.ToDeviceValue(UnitRenderingType.Horizontal, svgImage, skOwnerBounds);
            float height   = svgImage.Height.ToDeviceValue(UnitRenderingType.Vertical, svgImage, skOwnerBounds);
            float x        = svgImage.Location.X.ToDeviceValue(UnitRenderingType.Horizontal, svgImage, skOwnerBounds);
            float y        = svgImage.Location.Y.ToDeviceValue(UnitRenderingType.Vertical, svgImage, skOwnerBounds);
            var   location = new SKPoint(x, y);

            if (width <= 0f || height <= 0f || svgImage.Href == null)
            {
                IsDrawable = false;
                return;
            }

            // TODO: Check for image recursive references.
            //if (SkiaUtil.HasRecursiveReference(svgImage, (e) => e.Href))
            //{
            //    _canDraw = false;
            //    return;
            //}

            var image       = SvgImageExtensions.GetImage(svgImage.Href, svgImage.OwnerDocument);
            var skImage     = image as SKImage;
            var svgFragment = image as SvgFragment;

            if (skImage == null && svgFragment == null)
            {
                IsDrawable = false;
                return;
            }

            if (skImage != null)
            {
                _disposable.Add(skImage);
            }

            SrcRect = default;

            if (skImage != null)
            {
                SrcRect = SKRect.Create(0f, 0f, skImage.Width, skImage.Height);
            }

            if (svgFragment != null)
            {
                var skSize = SvgExtensions.GetDimensions(svgFragment);
                SrcRect = SKRect.Create(0f, 0f, skSize.Width, skSize.Height);
            }

            var destClip = SKRect.Create(location.X, location.Y, width, height);

            var aspectRatio = svgImage.AspectRatio;

            if (aspectRatio.Align != SvgPreserveAspectRatio.none)
            {
                var fScaleX = destClip.Width / SrcRect.Width;
                var fScaleY = destClip.Height / SrcRect.Height;
                var xOffset = 0f;
                var yOffset = 0f;

                if (aspectRatio.Slice)
                {
                    fScaleX = Math.Max(fScaleX, fScaleY);
                    fScaleY = Math.Max(fScaleX, fScaleY);
                }
                else
                {
                    fScaleX = Math.Min(fScaleX, fScaleY);
                    fScaleY = Math.Min(fScaleX, fScaleY);
                }

                switch (aspectRatio.Align)
                {
                case SvgPreserveAspectRatio.xMinYMin:
                    break;

                case SvgPreserveAspectRatio.xMidYMin:
                    xOffset = (destClip.Width - SrcRect.Width * fScaleX) / 2;
                    break;

                case SvgPreserveAspectRatio.xMaxYMin:
                    xOffset = (destClip.Width - SrcRect.Width * fScaleX);
                    break;

                case SvgPreserveAspectRatio.xMinYMid:
                    yOffset = (destClip.Height - SrcRect.Height * fScaleY) / 2;
                    break;

                case SvgPreserveAspectRatio.xMidYMid:
                    xOffset = (destClip.Width - SrcRect.Width * fScaleX) / 2;
                    yOffset = (destClip.Height - SrcRect.Height * fScaleY) / 2;
                    break;

                case SvgPreserveAspectRatio.xMaxYMid:
                    xOffset = (destClip.Width - SrcRect.Width * fScaleX);
                    yOffset = (destClip.Height - SrcRect.Height * fScaleY) / 2;
                    break;

                case SvgPreserveAspectRatio.xMinYMax:
                    yOffset = (destClip.Height - SrcRect.Height * fScaleY);
                    break;

                case SvgPreserveAspectRatio.xMidYMax:
                    xOffset = (destClip.Width - SrcRect.Width * fScaleX) / 2;
                    yOffset = (destClip.Height - SrcRect.Height * fScaleY);
                    break;

                case SvgPreserveAspectRatio.xMaxYMax:
                    xOffset = (destClip.Width - SrcRect.Width * fScaleX);
                    yOffset = (destClip.Height - SrcRect.Height * fScaleY);
                    break;
                }

                DestRect = SKRect.Create(
                    destClip.Left + xOffset,
                    destClip.Top + yOffset,
                    SrcRect.Width * fScaleX,
                    SrcRect.Height * fScaleY);
            }
            else
            {
                DestRect = destClip;
            }

            Clip = destClip;

            var skClipRect = SvgClippingExtensions.GetClipRect(svgImage, destClip);

            if (skClipRect != null)
            {
                Clip = skClipRect;
            }

            if (skImage != null)
            {
                Image = skImage;
            }

            if (svgFragment != null)
            {
                FragmentDrawable = new FragmentDrawable(svgFragment, skOwnerBounds, root, this, ignoreAttributes);
                _disposable.Add(FragmentDrawable);
            }

            IsAntialias = SvgPaintingExtensions.IsAntialias(svgImage);

            if (Image != null)
            {
                TransformedBounds = DestRect;
            }

            if (FragmentDrawable != null)
            {
                //_skBounds = _fragmentDrawable._skBounds;
                TransformedBounds = DestRect;
            }

            Transform         = SvgTransformsExtensions.ToSKMatrix(svgImage.Transforms);
            FragmentTransform = SKMatrix.MakeIdentity();
            if (FragmentDrawable != null)
            {
                float dx = DestRect.Left;
                float dy = DestRect.Top;
                float sx = DestRect.Width / SrcRect.Width;
                float sy = DestRect.Height / SrcRect.Height;
                var   skTranslationMatrix = SKMatrix.MakeTranslation(dx, dy);
                var   skScaleMatrix       = SKMatrix.MakeScale(sx, sy);
                FragmentTransform = FragmentTransform.PreConcat(skTranslationMatrix);
                FragmentTransform = FragmentTransform.PreConcat(skScaleMatrix);
            }

            Fill   = null;
            Stroke = null;

            // TODO: Transform _skBounds using _skMatrix.
            TransformedBounds = Transform.MapRect(TransformedBounds);
        }
Exemple #11
0
        public FragmentDrawable(SvgFragment svgFragment, SKRect skOwnerBounds, Drawable?root, Drawable?parent, Attributes ignoreAttributes = Attributes.None)
            : base(svgFragment, root, parent)
        {
            IgnoreAttributes = ignoreAttributes;
            IsDrawable       = HasFeatures(svgFragment, IgnoreAttributes);

            if (!IsDrawable)
            {
                return;
            }

            var svgFragmentParent = svgFragment.Parent;

            float x = svgFragmentParent == null ? 0f : svgFragment.X.ToDeviceValue(UnitRenderingType.Horizontal, svgFragment, skOwnerBounds);
            float y = svgFragmentParent == null ? 0f : svgFragment.Y.ToDeviceValue(UnitRenderingType.Vertical, svgFragment, skOwnerBounds);

            var skSize = SvgExtensions.GetDimensions(svgFragment);

            if (skOwnerBounds.IsEmpty)
            {
                skOwnerBounds = SKRect.Create(x, y, skSize.Width, skSize.Height);
            }

            CreateChildren(svgFragment, skOwnerBounds, this, this, ignoreAttributes);

            IsAntialias = SvgPaintingExtensions.IsAntialias(svgFragment);

            TransformedBounds = skOwnerBounds;

            CreateTransformedBounds();

            Transform = SvgTransformsExtensions.ToSKMatrix(svgFragment.Transforms);
            var skMatrixViewBox = SvgTransformsExtensions.ToSKMatrix(svgFragment.ViewBox, svgFragment.AspectRatio, x, y, skSize.Width, skSize.Height);

            SKMatrix.PreConcat(ref Transform, ref skMatrixViewBox);

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

            default:
                if (skSize.IsEmpty)
                {
                    Overflow = SKRect.Create(
                        x,
                        y,
                        Math.Abs(TransformedBounds.Left) + TransformedBounds.Width,
                        Math.Abs(TransformedBounds.Top) + TransformedBounds.Height);
                }
                else
                {
                    Overflow = SKRect.Create(x, y, skSize.Width, skSize.Height);
                }
                break;
            }

            var clipPathUris = new HashSet <Uri>();
            var svgClipPath  = svgFragment.GetUriElementReference <SvgClipPath>("clip-path", clipPathUris);

            if (svgClipPath != null && svgClipPath.Children != null)
            {
                ClipPath = IgnoreAttributes.HasFlag(Attributes.ClipPath) ? null : SvgClippingExtensions.GetClipPath(svgClipPath, TransformedBounds, clipPathUris, _disposable);
            }
            else
            {
                ClipPath = null;
            }

            Fill   = null;
            Stroke = null;

            // TODO: Transform _skBounds using _skMatrix.
            SKMatrix.MapRect(ref Transform, out TransformedBounds, ref TransformedBounds);
        }
Exemple #12
0
        public static SkiaSharp.SKPicture?ToPicture(SvgFragment svgFragment)
        {
            var picture = SvgExtensions.ToModel(svgFragment, s_assetLoader, out _, out _);

            return(picture?.ToSKPicture());
        }