public void ApplyFilter(SvgVisualElement element, SvgRenderer renderer) { this.Buffer.Clear(); this.PopulateDefaults(element, renderer); IEnumerable<SvgFilterPrimitive> primitives = this.Children.OfType<SvgFilterPrimitive>(); if (primitives.Count() > 0) { foreach (var primitive in primitives) { this.Buffer.Add(primitive.Result, (e, r) => primitive.Process()); } // Render the final filtered image renderer.DrawImageUnscaled(this.Buffer.Last().Value(element, renderer), new Point(0, 0)); } }
public void ApplyFilter(SvgVisualElement element, ISvgRenderer renderer, Action <ISvgRenderer> renderMethod) { using (var transform = GetTransform(element)) { var bounds = GetPathBounds(element, renderer, transform); if (bounds.Width == 0f || bounds.Height == 0f) { return; } var inflate = 0.5f; using (var buffer = new ImageBuffer(bounds, inflate, renderer, renderMethod) { Transform = transform }) { foreach (var primitive in Children.OfType <SvgFilterPrimitive>()) { primitive.Process(buffer); } // Render the final filtered image var bufferImg = buffer.Buffer; var imgDraw = RectangleF.Inflate(bounds, inflate * bounds.Width, inflate * bounds.Height); var prevClip = renderer.GetClip(); try { renderer.SetClip(new Region(imgDraw)); renderer.DrawImage(bufferImg, imgDraw, new RectangleF(bounds.X, bounds.Y, imgDraw.Width, imgDraw.Height), GraphicsUnit.Pixel); } finally { renderer.SetClip(prevClip); } } } }
public static void CreateMarker(this SvgMarker svgMarker, SvgVisualElement pOwner, SKPoint pRefPoint, SKPoint pMarkerPoint1, SKPoint pMarkerPoint2, bool isStartMarker, SKRect skOwnerBounds, ref List <Drawable>?markerDrawables, CompositeDisposable disposable, Attributes ignoreAttributes = Attributes.None) { float fAngle1 = 0f; if (svgMarker.Orient.IsAuto) { float xDiff = pMarkerPoint2.X - pMarkerPoint1.X; float yDiff = pMarkerPoint2.Y - pMarkerPoint1.Y; fAngle1 = (float)(Math.Atan2(yDiff, xDiff) * 180.0 / Math.PI); if (isStartMarker && svgMarker.Orient.IsAutoStartReverse) { fAngle1 += 180; } } var markerDrawable = new MarkerDrawable(svgMarker, pOwner, pRefPoint, fAngle1, skOwnerBounds, null, null, ignoreAttributes); if (markerDrawables == null) { markerDrawables = new List <Drawable>(); } markerDrawables.Add(markerDrawable); disposable.Add(markerDrawable); }
private static SvgFillRule ToFillRule(SvgVisualElement svgVisualElement, SvgClipRule?svgClipPathClipRule) { var svgClipRule = svgClipPathClipRule is { } ? svgClipPathClipRule.Value : svgVisualElement.ClipRule;
private static SvgFillRule ToFillRule(SvgVisualElement svgVisualElement, SvgClipRule?svgClipPathClipRule) { var svgClipRule = svgClipPathClipRule ?? svgVisualElement.ClipRule; return(svgClipRule == SvgClipRule.EvenOdd ? SvgFillRule.EvenOdd : SvgFillRule.NonZero); }
public static MarkerDrawable Create(SvgMarker svgMarker, SvgVisualElement pOwner, Point pMarkerPoint, float fAngle, Rect skOwnerBounds, DrawableBase?parent, IAssetLoader assetLoader, Attributes ignoreAttributes = Attributes.None) { var drawable = new MarkerDrawable(assetLoader) { Element = svgMarker, Parent = parent, IgnoreAttributes = Attributes.Display | ignoreAttributes, IsDrawable = true }; if (!drawable.IsDrawable) { return(drawable); } var markerElement = drawable.GetMarkerElement(svgMarker); if (markerElement is null) { drawable.IsDrawable = false; return(drawable); } var skMarkerMatrix = Matrix.CreateIdentity(); var skMatrixMarkerPoint = Matrix.CreateTranslation(pMarkerPoint.X, pMarkerPoint.Y); skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixMarkerPoint); var skMatrixAngle = Matrix.CreateRotationDegrees(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); var markerWidth = svgMarker.MarkerWidth.ToDeviceValue(UnitRenderingType.Other, svgMarker, skOwnerBounds); var markerHeight = svgMarker.MarkerHeight.ToDeviceValue(UnitRenderingType.Other, svgMarker, skOwnerBounds); var viewBoxToMarkerUnitsScaleX = 1f; var viewBoxToMarkerUnitsScaleY = 1f; switch (svgMarker.MarkerUnits) { case SvgMarkerUnits.StrokeWidth: { var skMatrixStrokeWidth = Matrix.CreateScale(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 = Matrix.CreateTranslation(-refX * viewBoxToMarkerUnitsScaleX, -refY * viewBoxToMarkerUnitsScaleY); skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixTranslateRefXY); var skMatrixScaleXY = Matrix.CreateScale(viewBoxToMarkerUnitsScaleX, viewBoxToMarkerUnitsScaleY); skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixScaleXY); } break; case SvgMarkerUnits.UserSpaceOnUse: { var skMatrixTranslateRefXY = Matrix.CreateTranslation(-refX, -refY); skMarkerMatrix = skMarkerMatrix.PreConcat(skMatrixTranslateRefXY); } break; } switch (svgMarker.Overflow) { case SvgOverflow.Auto: case SvgOverflow.Visible: case SvgOverflow.Inherit: break; default: drawable.MarkerClipRect = Rect.Create( svgMarker.ViewBox.MinX, svgMarker.ViewBox.MinY, markerWidth / viewBoxToMarkerUnitsScaleX, markerHeight / viewBoxToMarkerUnitsScaleY); break; } var markerElementDrawable = DrawableFactory.Create(markerElement, skOwnerBounds, drawable, assetLoader, Attributes.Display); if (markerElementDrawable is { })
private void PopulateDefaults(SvgVisualElement element, SvgRenderer renderer) { this.ResetDefaults(); this.Buffer.Add(SvgFilterPrimitive.SourceGraphic, this.CreateSourceGraphic); this.Buffer.Add(SvgFilterPrimitive.SourceAlpha, this.CreateSourceAlpha); }
private Bitmap CreateSourceGraphic(SvgVisualElement element, SvgRenderer renderer) { if (this.sourceGraphic == null) { RectangleF bounds = element.Path.GetBounds(); this.sourceGraphic = new Bitmap((int)bounds.Width, (int)bounds.Height); using (var graphics = Graphics.FromImage(this.sourceGraphic)) { graphics.Clip = renderer.Clip; graphics.Transform = renderer.Transform; element.RenderElement(SvgRenderer.FromGraphics(graphics)); graphics.Save(); } } return this.sourceGraphic; }
private Bitmap CreateSourceAlpha(SvgVisualElement element, SvgRenderer renderer) { if (this.sourceAlpha == null) { Bitmap source = this.Buffer[SvgFilterPrimitive.SourceGraphic](element, renderer); float[][] colorMatrixElements = { new float[] {0, 0, 0, 0, 0}, // red new float[] {0, 0, 0, 0, 0}, // green new float[] {0, 0, 0, 0, 0}, // blue new float[] {0, 0, 0, 1, 1}, // alpha new float[] {0, 0, 0, 0, 0} }; // translations var matrix = new ColorMatrix(colorMatrixElements); ImageAttributes attributes = new ImageAttributes(); attributes.SetColorMatrix(matrix); this.sourceAlpha = new Bitmap(source.Width, source.Height); using (var graphics = Graphics.FromImage(this.sourceAlpha)) { graphics.DrawImage(source, new Rectangle(0, 0, source.Width, source.Height), 0, 0, source.Width, source.Height, GraphicsUnit.Pixel, attributes); graphics.Save(); } } return this.sourceAlpha; }
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); }
/// <summary> /// Svgエレメント=>Uiエレメント作成 /// </summary> /// <param name="svgVisualElementType">編集対象のSvgエレメントタイプ</param> /// <param name="svgVisualElement">編集対象のSvgエレメント</param> private FrameworkElement GenerateUiElement(Type svgVisualElementType, SvgVisualElement svgVisualElement) { return(null); }
internal void DrawMarker(SvgMarker svgMarker, SvgVisualElement pOwner, SKPoint pMarkerPoint, float fAngle) { var markerElement = GetMarkerElement(svgMarker); if (markerElement == null) { return; } var skMarkerMatrix = SKMatrix.MakeIdentity(); var skMatrixMarkerPoint = SKMatrix.MakeTranslation(pMarkerPoint.X, pMarkerPoint.Y); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixMarkerPoint); var skMatrixAngle = SKMatrix.MakeRotationDegrees(svgMarker.Orient.IsAuto ? fAngle : svgMarker.Orient.Angle); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixAngle); var strokeWidth = pOwner.StrokeWidth.ToDeviceValue(null, UnitRenderingType.Other, svgMarker); var refX = svgMarker.RefX.ToDeviceValue(null, UnitRenderingType.Horizontal, svgMarker); var refY = svgMarker.RefY.ToDeviceValue(null, UnitRenderingType.Horizontal, svgMarker); float markerWidth = svgMarker.MarkerWidth; float markerHeight = svgMarker.MarkerHeight; float viewBoxToMarkerUnitsScaleX = 1f; float viewBoxToMarkerUnitsScaleY = 1f; switch (svgMarker.MarkerUnits) { case SvgMarkerUnits.StrokeWidth: { var skMatrixStrokeWidth = SKMatrix.MakeScale(strokeWidth, strokeWidth); SKMatrix.PreConcat(ref skMarkerMatrix, ref 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); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixTranslateRefXY); var skMatrixScaleXY = SKMatrix.MakeScale(viewBoxToMarkerUnitsScaleX, viewBoxToMarkerUnitsScaleY); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixScaleXY); } break; case SvgMarkerUnits.UserSpaceOnUse: { var skMatrixTranslateRefXY = SKMatrix.MakeTranslation(-refX, -refY); SKMatrix.PreConcat(ref skMarkerMatrix, ref skMatrixTranslateRefXY); } break; } _skCanvas.Save(); var skMatrix = SkiaUtil.GetSKMatrix(svgMarker.Transforms); SKMatrix.PreConcat(ref skMatrix, ref skMarkerMatrix); SetTransform(skMatrix); SetClipPath(svgMarker, _disposable); var skPaintOpacity = SetOpacity(svgMarker, _disposable); var skPaintFilter = SetFilter(svgMarker, _disposable); switch (svgMarker.Overflow) { case SvgOverflow.Auto: case SvgOverflow.Visible: case SvgOverflow.Inherit: break; default: var skClipRect = SKRect.Create( svgMarker.ViewBox.MinX, svgMarker.ViewBox.MinY, markerWidth / viewBoxToMarkerUnitsScaleX, markerHeight / viewBoxToMarkerUnitsScaleY); _skCanvas.ClipRect(skClipRect, SKClipOperation.Intersect); break; } Draw(markerElement, true); if (skPaintFilter != null) { _skCanvas.Restore(); } if (skPaintOpacity != null) { _skCanvas.Restore(); } _skCanvas.Restore(); }
public override Brush GetBrush(SvgVisualElement styleOwner, ISvgRenderer renderer, float opacity, bool forStroke = false) { return(new SolidBrush(_Color)); }