Beispiel #1
0
 /// <summary>
 /// Draws a geometry.
 /// </summary>
 /// <param name="brush">The fill brush.</param>
 /// <param name="pen">The stroke pen.</param>
 /// <param name="geometry">The geometry.</param>
 public void DrawGeometry(IBrush?brush, IPen?pen, Geometry geometry)
 {
     if (geometry.PlatformImpl is not null)
     {
         DrawGeometry(brush, pen, geometry.PlatformImpl);
     }
 }
Beispiel #2
0
 /// <summary>
 /// Determines if this draw operation equals another.
 /// </summary>
 /// <param name="transform">The transform of the other draw operation.</param>
 /// <param name="brush">The fill of the other draw operation.</param>
 /// <param name="pen">The stroke of the other draw operation.</param>
 /// <param name="geometry">The geometry of the other draw operation.</param>
 /// <returns>True if the draw operations are the same, otherwise false.</returns>
 /// <remarks>
 /// The properties of the other draw operation are passed in as arguments to prevent
 /// allocation of a not-yet-constructed draw operation object.
 /// </remarks>
 public bool Equals(Matrix transform, IBrush?brush, IPen?pen, IGeometryImpl geometry)
 {
     return(transform == Transform &&
            Equals(brush, Brush) &&
            Equals(Pen, pen) &&
            Equals(geometry, Geometry));
 }
Beispiel #3
0
 public bool Equals(Matrix transform, IBrush?brush, IPen?pen, Rect rect)
 {
     return(transform == Transform &&
            Equals(brush, Brush) &&
            Equals(Pen, pen) &&
            rect.Equals(Rect));
 }
Beispiel #4
0
 /// <summary>
 /// Determines if this draw operation equals another.
 /// </summary>
 /// <param name="transform">The transform of the other draw operation.</param>
 /// <param name="brush">The fill of the other draw operation.</param>
 /// <param name="pen">The stroke of the other draw operation.</param>
 /// <param name="rect">The rectangle of the other draw operation.</param>
 /// <param name="boxShadows">The box shadow parameters of the other draw operation</param>
 /// <returns>True if the draw operations are the same, otherwise false.</returns>
 /// <remarks>
 /// The properties of the other draw operation are passed in as arguments to prevent
 /// allocation of a not-yet-constructed draw operation object.
 /// </remarks>
 public bool Equals(Matrix transform, IBrush?brush, IPen?pen, RoundedRect rect, BoxShadows boxShadows)
 {
     return(transform == Transform &&
            Equals(brush, Brush) &&
            Equals(Pen, pen) &&
            BoxShadows.Equals(boxShadows) &&
            rect.Equals(Rect));
 }
Beispiel #5
0
        /// <summary>
        /// Draws a geometry.
        /// </summary>
        /// <param name="brush">The fill brush.</param>
        /// <param name="pen">The stroke pen.</param>
        /// <param name="geometry">The geometry.</param>
        public void DrawGeometry(IBrush?brush, IPen?pen, IGeometryImpl geometry)
        {
            _ = geometry ?? throw new ArgumentNullException(nameof(geometry));

            if (brush != null || PenIsVisible(pen))
            {
                PlatformImpl.DrawGeometry(brush, pen, geometry);
            }
        }
Beispiel #6
0
 /// <summary>
 /// Initializes a new instance of the <see cref="GeometryNode"/> class.
 /// </summary>
 /// <param name="transform">The transform.</param>
 /// <param name="brush">The fill brush.</param>
 /// <param name="pen">The stroke pen.</param>
 /// <param name="geometry">The geometry.</param>
 /// <param name="aux">Auxiliary data required to draw the brush.</param>
 public GeometryNode(Matrix transform,
                     IBrush?brush,
                     IPen?pen,
                     IGeometryImpl geometry,
                     IDisposable?aux)
     : base(geometry.GetRenderBounds(pen).CalculateBoundsWithLineCaps(pen), transform, aux)
 {
     Transform = transform;
     Brush     = brush?.ToImmutable();
     Pen       = pen?.ToImmutable();
     Geometry  = geometry;
 }
Beispiel #7
0
        void RenderCore(DrawingContext context, IBrush?background, IBrush?borderBrush, BoxShadows boxShadows,
                        double borderDashOffset, PenLineCap borderLineCap, PenLineJoin borderLineJoin,
                        AvaloniaList <double>?borderDashArray)
        {
            if (_useComplexRendering)
            {
                var backgroundGeometry = _backgroundGeometryCache;
                if (backgroundGeometry != null)
                {
                    context.DrawGeometry(background, null, backgroundGeometry);
                }

                var borderGeometry = _borderGeometryCache;
                if (borderGeometry != null)
                {
                    context.DrawGeometry(borderBrush, null, borderGeometry);
                }
            }
            else
            {
                var  borderThickness = _borderThickness.Top;
                IPen?pen             = null;


                ImmutableDashStyle?dashStyle = null;

                if (borderDashArray != null && borderDashArray.Count > 0)
                {
                    dashStyle = new ImmutableDashStyle(borderDashArray, borderDashOffset);
                }

                if (borderBrush != null && borderThickness > 0)
                {
                    pen = new ImmutablePen(
                        borderBrush.ToImmutable(),
                        borderThickness,
                        dashStyle,
                        borderLineCap,
                        borderLineJoin);
                }


                var rect = new Rect(_size);
                if (!MathUtilities.IsZero(borderThickness))
                {
                    rect = rect.Deflate(borderThickness * 0.5);
                }
                var rrect = new RoundedRect(rect, _cornerRadius.TopLeft, _cornerRadius.TopRight,
                                            _cornerRadius.BottomRight, _cornerRadius.BottomLeft);

                context.PlatformImpl.DrawRectangle(background, pen, rrect, boxShadows);
            }
        }
Beispiel #8
0
 public EllipseNode(
     Matrix transform,
     IBrush?brush,
     IPen?pen,
     Rect rect,
     IDisposable?aux = null)
     : base(rect.Inflate(pen?.Thickness ?? 0), transform, aux)
 {
     Transform = transform;
     Brush     = brush?.ToImmutable();
     Pen       = pen?.ToImmutable();
     Rect      = rect;
 }
        public void DrawEllipse(IBrush?brush, IPen?pen, Rect rect)
        {
            var next = NextDrawAs <EllipseNode>();

            if (next == null || !next.Item.Equals(Transform, brush, pen, rect))
            {
                Add(new EllipseNode(Transform, brush, pen, rect, CreateChildScene(brush)));
            }
            else
            {
                ++_drawOperationindex;
            }
        }
        /// <inheritdoc/>
        public void DrawGeometry(IBrush?brush, IPen?pen, IGeometryImpl geometry)
        {
            var next = NextDrawAs <GeometryNode>();

            if (next == null || !next.Item.Equals(Transform, brush, pen, geometry))
            {
                Add(new GeometryNode(Transform, brush, pen, geometry, CreateChildScene(brush)));
            }
            else
            {
                ++_drawOperationindex;
            }
        }
Beispiel #11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="GeometryNode"/> class.
 /// </summary>
 /// <param name="transform">The transform.</param>
 /// <param name="brush">The fill brush.</param>
 /// <param name="pen">The stroke pen.</param>
 /// <param name="geometry">The geometry.</param>
 /// <param name="childScenes">Child scenes for drawing visual brushes.</param>
 public GeometryNode(Matrix transform,
                     IBrush?brush,
                     IPen?pen,
                     IGeometryImpl geometry,
                     IDictionary <IVisual, Scene>?childScenes = null)
     : base(geometry.GetRenderBounds(pen).CalculateBoundsWithLineCaps(pen), transform)
 {
     Transform   = transform;
     Brush       = brush?.ToImmutable();
     Pen         = pen?.ToImmutable();
     Geometry    = geometry;
     ChildScenes = childScenes;
 }
Beispiel #12
0
 public EllipseNode(
     Matrix transform,
     IBrush?brush,
     IPen?pen,
     Rect rect,
     IDictionary <IVisual, Scene>?childScenes = null)
     : base(rect.Inflate(pen?.Thickness ?? 0), transform)
 {
     Transform   = transform;
     Brush       = brush?.ToImmutable();
     Pen         = pen?.ToImmutable();
     Rect        = rect;
     ChildScenes = childScenes;
 }
        /// <inheritdoc/>
        public void DrawRectangle(IBrush?brush, IPen?pen, RoundedRect rect,
                                  BoxShadows boxShadows = default)
        {
            var next = NextDrawAs <RectangleNode>();

            if (next == null || !next.Item.Equals(Transform, brush, pen, rect, boxShadows))
            {
                Add(new RectangleNode(Transform, brush, pen, rect, boxShadows, CreateChildScene(brush)));
            }
            else
            {
                ++_drawOperationindex;
            }
        }
Beispiel #14
0
        /// <summary>
        /// Draws an ellipse with the specified Brush and Pen.
        /// </summary>
        /// <param name="brush">The brush used to fill the ellipse, or <c>null</c> for no fill.</param>
        /// <param name="pen">The pen used to stroke the ellipse, or <c>null</c> for no stroke.</param>
        /// <param name="center">The location of the center of the ellipse.</param>
        /// <param name="radiusX">The horizontal radius of the ellipse.</param>
        /// <param name="radiusY">The vertical radius of the ellipse.</param>
        /// <remarks>
        /// The brush and the pen can both be null. If the brush is null, then no fill is performed.
        /// If the pen is null, then no stoke is performed. If both the pen and the brush are null, then the drawing is not visible.
        /// </remarks>
        public void DrawEllipse(IBrush?brush, IPen?pen, Point center, double radiusX, double radiusY)
        {
            if (brush == null && !PenIsVisible(pen))
            {
                return;
            }

            var originX = center.X - radiusX;
            var originY = center.Y - radiusY;
            var width   = radiusX * 2;
            var height  = radiusY * 2;

            PlatformImpl.DrawEllipse(brush, pen, new Rect(originX, originY, width, height));
        }
Beispiel #15
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RectangleNode"/> class.
 /// </summary>
 /// <param name="transform">The transform.</param>
 /// <param name="brush">The fill brush.</param>
 /// <param name="pen">The stroke pen.</param>
 /// <param name="rect">The rectangle to draw.</param>
 /// <param name="boxShadows">The box shadow parameters</param>
 /// <param name="aux">Auxiliary data required to draw the brush.</param>
 public RectangleNode(
     Matrix transform,
     IBrush?brush,
     IPen?pen,
     RoundedRect rect,
     BoxShadows boxShadows,
     IDisposable?aux = null)
     : base(boxShadows.TransformBounds(rect.Rect).Inflate((pen?.Thickness ?? 0) / 2), transform, aux)
 {
     Transform  = transform;
     Brush      = brush?.ToImmutable();
     Pen        = pen?.ToImmutable();
     Rect       = rect;
     BoxShadows = boxShadows;
 }
Beispiel #16
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RectangleNode"/> class.
 /// </summary>
 /// <param name="transform">The transform.</param>
 /// <param name="brush">The fill brush.</param>
 /// <param name="pen">The stroke pen.</param>
 /// <param name="rect">The rectangle to draw.</param>
 /// <param name="boxShadows">The box shadow parameters</param>
 /// <param name="childScenes">Child scenes for drawing visual brushes.</param>
 public RectangleNode(
     Matrix transform,
     IBrush?brush,
     IPen?pen,
     RoundedRect rect,
     BoxShadows boxShadows,
     IDictionary <IVisual, Scene>?childScenes = null)
     : base(boxShadows.TransformBounds(rect.Rect).Inflate((pen?.Thickness ?? 0) / 2), transform)
 {
     Transform   = transform;
     Brush       = brush?.ToImmutable();
     Pen         = pen?.ToImmutable();
     Rect        = rect;
     ChildScenes = childScenes;
     BoxShadows  = boxShadows;
 }
Beispiel #17
0
        public override void Dispose()
        {
            if (_isOpen)
            {
                _context.EndFigure(false); _isOpen = false;
            }
            _context.Dispose();
            // Passing a null brush is a workaround for https://github.com/AvaloniaUI/Avalonia/issues/1419
            IBrush?brush = Foreground?.ToSolidColorBrush() ?? _canvas.CurrentBrush;
            IPen?  pen   = null;

            if (_canvas.CurrentStyle == PaintStyle.Stroke)
            {
                pen = new Pen(brush); brush = null;
            }
            _canvas.DrawingContext.DrawGeometry(brush, pen, _path);
        }
Beispiel #18
0
        /// <inheritdoc/>
        public bool Equals(IPen?other)
        {
            if (ReferenceEquals(this, other))
            {
                return(true);
            }
            else if (other is null)
            {
                return(false);
            }

            return(EqualityComparer <IBrush> .Default.Equals(Brush, other.Brush) &&
                   Thickness == other.Thickness &&
                   EqualityComparer <IDashStyle> .Default.Equals(DashStyle, other.DashStyle) &&
                   LineCap == other.LineCap &&
                   LineJoin == other.LineJoin &&
                   MiterLimit == other.MiterLimit);
        }
Beispiel #19
0
        /// <summary>
        /// Draws a rectangle with the specified Brush and Pen.
        /// </summary>
        /// <param name="brush">The brush used to fill the rectangle, or <c>null</c> for no fill.</param>
        /// <param name="pen">The pen used to stroke the rectangle, or <c>null</c> for no stroke.</param>
        /// <param name="rect">The rectangle bounds.</param>
        /// <param name="radiusX">The radius in the X dimension of the rounded corners.
        ///     This value will be clamped to the range of 0 to Width/2
        /// </param>
        /// <param name="radiusY">The radius in the Y dimension of the rounded corners.
        ///     This value will be clamped to the range of 0 to Height/2
        /// </param>
        /// <param name="boxShadows">Box shadow effect parameters</param>
        /// <remarks>
        /// The brush and the pen can both be null. If the brush is null, then no fill is performed.
        /// If the pen is null, then no stoke is performed. If both the pen and the brush are null, then the drawing is not visible.
        /// </remarks>
        public void DrawRectangle(IBrush?brush, IPen?pen, Rect rect, double radiusX = 0, double radiusY = 0,
                                  BoxShadows boxShadows = default)
        {
            if (brush == null && !PenIsVisible(pen))
            {
                return;
            }

            if (!MathUtilities.IsZero(radiusX))
            {
                radiusX = Math.Min(radiusX, rect.Width / 2);
            }

            if (!MathUtilities.IsZero(radiusY))
            {
                radiusY = Math.Min(radiusY, rect.Height / 2);
            }

            PlatformImpl.DrawRectangle(brush, pen, new RoundedRect(rect, radiusX, radiusY), boxShadows);
        }
Beispiel #20
0
    /// <summary>
    /// Calculates the bounds of a given geometry with respect to the pens <see cref="IPen.LineCap"/>
    /// </summary>
    /// <param name="originalBounds">The calculated bounds without <see cref="IPen.LineCap"/>s</param>
    /// <param name="pen">The pen with information about the <see cref="IPen.LineCap"/>s</param>
    /// <returns></returns>
    public static Rect CalculateBoundsWithLineCaps(this Rect originalBounds, IPen?pen)
    {
        if (pen is null || MathUtilities.IsZero(pen.Thickness))
        {
            return(originalBounds);
        }

        switch (pen.LineCap)
        {
        case PenLineCap.Flat:
            return(originalBounds);

        case PenLineCap.Round:
            return(originalBounds.Inflate(pen.Thickness / 2));

        case PenLineCap.Square:
            return(originalBounds.Inflate(pen.Thickness));

        default:
            throw new ArgumentOutOfRangeException();
        }
    }
Beispiel #21
0
 private static bool PenIsVisible(IPen?pen)
 {
     return(pen?.Brush != null && pen.Thickness > 0);
 }