예제 #1
0
        public void DrawImage(SvgImage svgImage, bool ignoreDisplay)
        {
            if (!CanDraw(svgImage, ignoreDisplay))
            {
                return;
            }

            float width    = svgImage.Width.ToDeviceValue(null, UnitRenderingType.Horizontal, svgImage);
            float height   = svgImage.Height.ToDeviceValue(null, UnitRenderingType.Vertical, svgImage);
            var   location = svgImage.Location.ToDeviceValue(null, svgImage);

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

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

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

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

            SKRect srcRect = default;

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

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

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

            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);
            }

            _skCanvas.Save();

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

            SetTransform(skMatrix);
            SetClipPath(svgImage, _disposable);

            var skPaintOpacity = SetOpacity(svgImage, _disposable);

            var skPaintFilter = SetFilter(svgImage, _disposable);

            _skCanvas.ClipRect(destClip, SKClipOperation.Intersect);

            SetClip(svgImage, destClip);

            if (skImage != null)
            {
                _skCanvas.DrawImage(skImage, srcRect, destRect);
            }

            if (svgFragment != null)
            {
                _skCanvas.Save();

                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);
                SKMatrix.PreConcat(ref skTranslationMatrix, ref skScaleMatrix);
                SetTransform(skTranslationMatrix);

                DrawFragment(svgFragment, ignoreDisplay);

                _skCanvas.Restore();
            }

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

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

            _skCanvas.Restore();
        }