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); }
public SwitchDrawable(SvgSwitch svgSwitch, SKRect skOwnerBounds, Drawable?root, Drawable?parent, Attributes ignoreAttributes = Attributes.None) : base(svgSwitch, root, parent) { IgnoreAttributes = ignoreAttributes; IsDrawable = CanDraw(svgSwitch, IgnoreAttributes) && HasFeatures(svgSwitch, IgnoreAttributes); if (!IsDrawable) { return; } foreach (var child in svgSwitch.Children) { if (!IsKnownElement(child)) { continue; } bool hasRequiredFeatures = HasRequiredFeatures(child); bool hasRequiredExtensions = HasRequiredExtensions(child); bool hasSystemLanguage = HasSystemLanguage(child); if (hasRequiredFeatures && hasRequiredExtensions && hasSystemLanguage) { //var ignoreAttributesSwitch = ignoreAttributes // | Attributes.Visibility // | Attributes.Display // | Attributes.RequiredFeatures // | Attributes.RequiredExtensions // | Attributes.SystemLanguage; var drawable = DrawableFactory.Create(child, skOwnerBounds, root, parent, ignoreAttributes); if (drawable != null) { FirstChild = drawable; _disposable.Add(FirstChild); } break; } } if (FirstChild == null) { IsDrawable = false; return; } IsAntialias = SvgPaintingExtensions.IsAntialias(svgSwitch); TransformedBounds = FirstChild.TransformedBounds; Transform = SvgTransformsExtensions.ToSKMatrix(svgSwitch.Transforms); Fill = null; Stroke = null; // TODO: Transform _skBounds using _skMatrix. TransformedBounds = Transform.MapRect(TransformedBounds); }
public PolylineDrawable(SvgPolyline svgPolyline, SKRect skOwnerBounds, Drawable?root, Drawable?parent, Attributes ignoreAttributes = Attributes.None) : base(svgPolyline, root, parent) { IgnoreAttributes = ignoreAttributes; IsDrawable = CanDraw(svgPolyline, IgnoreAttributes) && HasFeatures(svgPolyline, IgnoreAttributes); if (!IsDrawable) { return; } Path = svgPolyline.Points?.ToSKPath(svgPolyline.FillRule, false, skOwnerBounds, _disposable); if (Path == null || Path.IsEmpty) { IsDrawable = false; return; } IsAntialias = SvgPaintingExtensions.IsAntialias(svgPolyline); TransformedBounds = Path.Bounds; Transform = SvgTransformsExtensions.ToSKMatrix(svgPolyline.Transforms); bool canDrawFill = true; bool canDrawStroke = true; if (SvgPaintingExtensions.IsValidFill(svgPolyline)) { Fill = SvgPaintingExtensions.GetFillSKPaint(svgPolyline, TransformedBounds, ignoreAttributes, _disposable); if (Fill == null) { canDrawFill = false; } } if (SvgPaintingExtensions.IsValidStroke(svgPolyline, TransformedBounds)) { Stroke = SvgPaintingExtensions.GetStrokeSKPaint(svgPolyline, TransformedBounds, ignoreAttributes, _disposable); if (Stroke == null) { canDrawStroke = false; } } if (canDrawFill && !canDrawStroke) { IsDrawable = false; return; } SvgMarkerExtensions.CreateMarkers(svgPolyline, Path, skOwnerBounds, ref MarkerDrawables, _disposable); // TODO: Transform _skBounds using _skMatrix. TransformedBounds = Transform.MapRect(TransformedBounds); }
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.PostConcat(ref skMatrix, ref skScaleMatrix); var skTranslateMatrix = SKMatrix.MakeTranslation(skBounds.Left, skBounds.Top); SKMatrix.PostConcat(ref skMatrix, ref skTranslateMatrix); } var skTransformsMatrix = SvgTransformsExtensions.ToSKMatrix(svgClipPath.Transforms); SKMatrix.PostConcat(ref skMatrix, ref 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); }
public GroupDrawable(SvgGroup svgGroup, SKRect skOwnerBounds, Drawable?root, Drawable?parent, Attributes ignoreAttributes = Attributes.None) : base(svgGroup, root, parent) { IgnoreAttributes = ignoreAttributes; IsDrawable = CanDraw(svgGroup, IgnoreAttributes) && HasFeatures(svgGroup, IgnoreAttributes); // NOTE: Call AddMarkers only once. SvgMarkerExtensions.AddMarkers(svgGroup); CreateChildren(svgGroup, skOwnerBounds, root, this, ignoreAttributes); // TODO: Check if children are explicitly set to be visible. //foreach (var child in ChildrenDrawables) //{ // if (child.IsDrawable) // { // IsDrawable = true; // break; // } //} if (!IsDrawable) { return; } IsAntialias = SvgPaintingExtensions.IsAntialias(svgGroup); TransformedBounds = SKRect.Empty; CreateTransformedBounds(); Transform = SvgTransformsExtensions.ToSKMatrix(svgGroup.Transforms); Fill = null; Stroke = null; // TODO: Transform _skBounds using _skMatrix. TransformedBounds = Transform.MapRect(TransformedBounds); }
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); }
public MarkerDrawable(SvgMarker svgMarker, SvgVisualElement pOwner, SKPoint pMarkerPoint, float fAngle, SKRect skOwnerBounds, Drawable?root, Drawable?parent, Attributes ignoreAttributes = Attributes.None) : base(svgMarker, root, parent) { IgnoreAttributes = Attributes.Display | ignoreAttributes; IsDrawable = true; if (!IsDrawable) { return; } var markerElement = GetMarkerElement(svgMarker); if (markerElement == null) { IsDrawable = false; return; } var skMarkerMatrix = SKMatrix.MakeIdentity(); var skMatrixMarkerPoint = SKMatrix.MakeTranslation(pMarkerPoint.X, pMarkerPoint.Y); skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixMarkerPoint); var skMatrixAngle = SKMatrix.MakeRotationDegrees(svgMarker.Orient.IsAuto ? fAngle : svgMarker.Orient.Angle); skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixAngle); var strokeWidth = pOwner.StrokeWidth.ToDeviceValue(UnitRenderingType.Other, svgMarker, skOwnerBounds); var refX = svgMarker.RefX.ToDeviceValue(UnitRenderingType.Horizontal, svgMarker, skOwnerBounds); var refY = svgMarker.RefY.ToDeviceValue(UnitRenderingType.Vertical, svgMarker, skOwnerBounds); float markerWidth = svgMarker.MarkerWidth.ToDeviceValue(UnitRenderingType.Other, svgMarker, skOwnerBounds); float markerHeight = svgMarker.MarkerHeight.ToDeviceValue(UnitRenderingType.Other, svgMarker, skOwnerBounds); float viewBoxToMarkerUnitsScaleX = 1f; float viewBoxToMarkerUnitsScaleY = 1f; switch (svgMarker.MarkerUnits) { case SvgMarkerUnits.StrokeWidth: { var skMatrixStrokeWidth = SKMatrix.MakeScale(strokeWidth, strokeWidth); skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixStrokeWidth); var viewBoxWidth = svgMarker.ViewBox.Width; var viewBoxHeight = svgMarker.ViewBox.Height; var scaleFactorWidth = (viewBoxWidth <= 0) ? 1 : (markerWidth / viewBoxWidth); var scaleFactorHeight = (viewBoxHeight <= 0) ? 1 : (markerHeight / viewBoxHeight); viewBoxToMarkerUnitsScaleX = Math.Min(scaleFactorWidth, scaleFactorHeight); viewBoxToMarkerUnitsScaleY = Math.Min(scaleFactorWidth, scaleFactorHeight); var skMatrixTranslateRefXY = SKMatrix.MakeTranslation(-refX * viewBoxToMarkerUnitsScaleX, -refY * viewBoxToMarkerUnitsScaleY); skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixTranslateRefXY); var skMatrixScaleXY = SKMatrix.MakeScale(viewBoxToMarkerUnitsScaleX, viewBoxToMarkerUnitsScaleY); skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixScaleXY); } break; case SvgMarkerUnits.UserSpaceOnUse: { var skMatrixTranslateRefXY = SKMatrix.MakeTranslation(-refX, -refY); skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixTranslateRefXY); } break; } switch (svgMarker.Overflow) { case SvgOverflow.Auto: case SvgOverflow.Visible: case SvgOverflow.Inherit: break; default: MarkerClipRect = SKRect.Create( svgMarker.ViewBox.MinX, svgMarker.ViewBox.MinY, markerWidth / viewBoxToMarkerUnitsScaleX, markerHeight / viewBoxToMarkerUnitsScaleY); break; } var drawable = DrawableFactory.Create(markerElement, skOwnerBounds, root, this, Attributes.Display); if (drawable != null) { MarkerElementDrawable = drawable; _disposable.Add(MarkerElementDrawable); } else { IsDrawable = false; return; } IsAntialias = SvgPaintingExtensions.IsAntialias(svgMarker); TransformedBounds = MarkerElementDrawable.TransformedBounds; Transform = SvgTransformsExtensions.ToSKMatrix(svgMarker.Transforms); Transform = Transform.PreConcat(skMarkerMatrix); Fill = null; Stroke = null; // TODO: Transform _skBounds using _skMatrix. TransformedBounds = Transform.MapRect(TransformedBounds); }
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); } }
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 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); }
public SymbolDrawable(SvgSymbol svgSymbol, float x, float y, float width, float height, SKRect skOwnerBounds, Drawable?root, Drawable?parent, Attributes ignoreAttributes) : base(svgSymbol, root, parent) { IgnoreAttributes = ignoreAttributes; IsDrawable = CanDraw(svgSymbol, IgnoreAttributes) && HasFeatures(svgSymbol, IgnoreAttributes); if (!IsDrawable) { return; } if (svgSymbol.CustomAttributes.TryGetValue("width", out string?_widthString)) { if (new SvgUnitConverter().ConvertFromString(_widthString) is SvgUnit _width) { width = _width.ToDeviceValue(UnitRenderingType.Horizontal, svgSymbol, skOwnerBounds); } } if (svgSymbol.CustomAttributes.TryGetValue("height", out string?heightString)) { if (new SvgUnitConverter().ConvertFromString(heightString) is SvgUnit _height) { height = _height.ToDeviceValue(UnitRenderingType.Vertical, svgSymbol, skOwnerBounds); } } SvgOverflow svgOverflow = SvgOverflow.Hidden; if (svgSymbol.TryGetAttribute("overflow", out string overflowString)) { if (new SvgOverflowConverter().ConvertFromString(overflowString) is SvgOverflow _svgOverflow) { svgOverflow = _svgOverflow; } } switch (svgOverflow) { case SvgOverflow.Auto: case SvgOverflow.Visible: case SvgOverflow.Inherit: break; default: Overflow = SKRect.Create(x, y, width, height); break; } CreateChildren(svgSymbol, skOwnerBounds, root, this, ignoreAttributes); IsAntialias = SvgPaintingExtensions.IsAntialias(svgSymbol); TransformedBounds = SKRect.Empty; CreateTransformedBounds(); Transform = SvgTransformsExtensions.ToSKMatrix(svgSymbol.Transforms); var skMatrixViewBox = SvgTransformsExtensions.ToSKMatrix(svgSymbol.ViewBox, svgSymbol.AspectRatio, x, y, width, height); Transform = Transform.PreConcat(skMatrixViewBox); Fill = null; Stroke = null; // TODO: Transform _skBounds using _skMatrix. TransformedBounds = Transform.MapRect(TransformedBounds); }