public override void PostProcess() { var element = Element; if (element == null) { return; } var enableMask = !IgnoreAttributes.HasFlag(Attributes.Mask); ClipPath = null; if (enableMask == true) { MaskDrawable = SvgClippingExtensions.GetSvgElementMask(element, TransformedBounds, new HashSet <Uri>(), _disposable); if (MaskDrawable != null) { CreateMaskPaints(); } } else { MaskDrawable = null; } Opacity = null; Filter = null; }
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); }
public virtual void PostProcess() { var element = Element; if (element == null) { return; } var visualElement = element as SvgVisualElement; var enableClip = !IgnoreAttributes.HasFlag(Attributes.ClipPath); var enableMask = !IgnoreAttributes.HasFlag(Attributes.Mask); var enableOpacity = !IgnoreAttributes.HasFlag(Attributes.Opacity); var enableFilter = !IgnoreAttributes.HasFlag(Attributes.Filter); if (visualElement != null && enableClip == true) { ClipPath = SvgClippingExtensions.GetSvgVisualElementClipPath(visualElement, TransformedBounds, new HashSet <Uri>(), _disposable); } else { ClipPath = null; } if (enableMask == true) { MaskDrawable = SvgClippingExtensions.GetSvgElementMask(element, TransformedBounds, new HashSet <Uri>(), _disposable); if (MaskDrawable != null) { CreateMaskPaints(); } } else { MaskDrawable = null; } if (enableOpacity == true) { Opacity = SvgPaintingExtensions.GetOpacitySKPaint(element, _disposable); } else { Opacity = null; } if (visualElement != null && enableFilter == true) { Filter = SvgFiltersExtensions.GetFilterSKPaint(visualElement, TransformedBounds, this, _disposable, out var isValid); if (isValid == false) { IsDrawable = false; return; } } else { Filter = null; } }
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); }