@ -1,4 +1,7 @@
using System ;
using System.Collections.Generic ;
using System.Collections.Specialized ;
using Avalonia.Collections ;
using Avalonia.Media.Immutable ;
using Avalonia.Rendering.Composition ;
using Avalonia.Rendering.Composition.Drawing ;
@ -56,8 +59,7 @@ namespace Avalonia.Media
/// Initializes a new instance of the <see cref="Pen"/> class.
/// </summary>
public Pen ( )
{
}
{ }
/// <summary>
/// Initializes a new instance of the <see cref="Pen"/> class.
@ -75,8 +77,7 @@ namespace Avalonia.Media
PenLineCap lineCap = PenLineCap . Flat ,
PenLineJoin lineJoin = PenLineJoin . Miter ,
double miterLimit = 1 0.0 ) : this ( new SolidColorBrush ( color ) , thickness , dashStyle , lineCap , lineJoin , miterLimit )
{
}
{ }
/// <summary>
/// Initializes a new instance of the <see cref="Pen"/> class.
@ -178,6 +179,69 @@ namespace Avalonia.Media
MiterLimit ) ;
}
/// <summary>
/// Smart reuse and update pen properties.
/// </summary>
/// <param name="pen">Old pen to modify.</param>
/// <param name="brush">The brush used to draw.</param>
/// <param name="thickness">The stroke thickness.</param>
/// <param name="strokeDashArray">The stroke dask array.</param>
/// <param name="strokeDaskOffset">The stroke dask offset.</param>
/// <param name="lineCap">The line cap.</param>
/// <param name="lineJoin">The line join.</param>
/// <param name="miterLimit">The miter limit.</param>
/// <returns>If a new instance was created and visual invalidation required.</returns>
internal static bool TryModifyOrCreate ( ref IPen ? pen ,
IBrush ? brush ,
double thickness ,
IList < double > ? strokeDashArray = null ,
double strokeDaskOffset = default ,
PenLineCap lineCap = PenLineCap . Flat ,
PenLineJoin lineJoin = PenLineJoin . Miter ,
double miterLimit = 1 0.0 )
{
var previousPen = pen ;
if ( brush is null )
{
pen = null ;
return previousPen is not null ;
}
IDashStyle ? dashStyle = null ;
if ( strokeDashArray is { Count : > 0 } )
{
// strokeDashArray can be IList (instead of AvaloniaList) in future
// So, if it supports notification - create a mutable DashStyle
dashStyle = strokeDashArray is INotifyCollectionChanged
? new DashStyle ( strokeDashArray , strokeDaskOffset )
: new ImmutableDashStyle ( strokeDashArray , strokeDaskOffset ) ;
}
if ( brush is IImmutableBrush immutableBrush & & dashStyle is null or ImmutableDashStyle )
{
pen = new ImmutablePen (
immutableBrush ,
thickness ,
( ImmutableDashStyle ? ) dashStyle ,
lineCap ,
lineJoin ,
miterLimit ) ;
return true ;
}
var mutablePen = previousPen as Pen ? ? new Pen ( ) ;
mutablePen . Brush = brush ;
mutablePen . Thickness = thickness ;
mutablePen . LineCap = lineCap ;
mutablePen . LineJoin = lineJoin ;
mutablePen . DashStyle = dashStyle ;
mutablePen . MiterLimit = miterLimit ;
pen = mutablePen ;
return ! Equals ( previousPen , pen ) ;
}
void RegisterForSerialization ( )
{
_ resource . RegisterForInvalidationOnAllCompositors ( this ) ;
@ -186,21 +250,21 @@ namespace Avalonia.Media
protected override void OnPropertyChanged ( AvaloniaPropertyChangedEventArgs change )
{
RegisterForSerialization ( ) ;
if ( change . Property = = BrushProperty )
if ( change . Property = = BrushProperty )
_ resource . ProcessPropertyChangeNotification ( change ) ;
if ( change . Property = = DashStyleProperty )
if ( change . Property = = DashStyleProperty )
UpdateDashStyleSubscription ( ) ;
base . OnPropertyChanged ( change ) ;
}
void UpdateDashStyleSubscription ( )
{
var newValue = _ resource . IsAttached ? DashStyle as DashStyle : null ;
if ( ReferenceEquals ( _ subscribedToDashes , newValue ) )
if ( ReferenceEquals ( _ subscribedToDashes , newValue ) )
return ;
if ( _ subscribedToDashes ! = null & & _ weakSubscriber ! = null )
@ -221,9 +285,9 @@ namespace Avalonia.Media
_ subscribedToDashes = newValue ;
}
}
private CompositorResourceHolder < ServerCompositionSimplePen > _ resource ;
IPen ICompositionRenderResource < IPen > . GetForCompositor ( Compositor c ) = > _ resource . GetForCompositor ( c ) ;
void ICompositionRenderResource . AddRefOnCompositor ( Compositor c )