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