[Android] Changes to improve Border control drawing performance (#3620)

* Changes to improve Border control drawing performance

* Avoid to draw unnecesary Path
This commit is contained in:
Javier Suárez 2022-01-13 17:46:43 +01:00 коммит произвёл GitHub
Родитель 8316f7ab23
Коммит 516fe302fe
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 78 добавлений и 74 удалений

Просмотреть файл

@ -23,12 +23,11 @@ namespace Microsoft.Maui.Graphics
bool _disposed;
ARect? _bounds;
int _width;
int _height;
Path? _clipPath;
Path? _maskPath;
APaint? _maskPaint;
APaint? _borderPaint;
IShape? _shape;
@ -60,6 +59,9 @@ namespace Microsoft.Maui.Graphics
public void SetBackgroundColor(AColor? backgroundColor)
{
if (_backgroundColor == backgroundColor)
return;
_backgroundColor = backgroundColor;
InvalidateSelf();
@ -98,6 +100,9 @@ namespace Microsoft.Maui.Graphics
public void SetBackground(LinearGradientPaint linearGradientPaint)
{
if (_background == linearGradientPaint)
return;
_invalidatePath = true;
_backgroundColor = null;
@ -109,6 +114,9 @@ namespace Microsoft.Maui.Graphics
public void SetBackground(RadialGradientPaint radialGradientPaint)
{
if (_background == radialGradientPaint)
return;
_invalidatePath = true;
_backgroundColor = null;
@ -130,6 +138,9 @@ namespace Microsoft.Maui.Graphics
public void SetBorderShape(IShape? shape)
{
if (_shape == shape)
return;
_invalidatePath = true;
_shape = shape;
@ -140,6 +151,9 @@ namespace Microsoft.Maui.Graphics
public void SetBorderColor(AColor? borderColor)
{
if (_borderColor == borderColor)
return;
_borderColor = borderColor;
InvalidateSelf();
@ -178,6 +192,9 @@ namespace Microsoft.Maui.Graphics
public void SetBorderBrush(LinearGradientPaint linearGradientPaint)
{
if (_stroke == linearGradientPaint)
return;
_invalidatePath = true;
_borderColor = null;
@ -189,6 +206,9 @@ namespace Microsoft.Maui.Graphics
public void SetBorderBrush(RadialGradientPaint radialGradientPaint)
{
if (_stroke == radialGradientPaint)
return;
_invalidatePath = true;
_borderColor = null;
@ -210,9 +230,14 @@ namespace Microsoft.Maui.Graphics
public void SetBorderWidth(double strokeWidth)
{
float strokeThickness = (float)(strokeWidth * _density);
if (_strokeThickness == strokeThickness)
return;
_invalidatePath = true;
_strokeThickness = (float)(strokeWidth * _density);
_strokeThickness = strokeThickness;
InitializeBorderIfNeeded();
InvalidateSelf();
@ -238,6 +263,9 @@ namespace Microsoft.Maui.Graphics
public void SetBorderMiterLimit(float strokeMiterLimit)
{
if (_strokeMiterLimit == strokeMiterLimit)
return;
_strokeMiterLimit = strokeMiterLimit;
InvalidateSelf();
@ -260,6 +288,9 @@ namespace Microsoft.Maui.Graphics
break;
}
if (_strokeLineJoin == aLineJoin)
return;
_strokeLineJoin = aLineJoin;
InvalidateSelf();
@ -282,6 +313,9 @@ namespace Microsoft.Maui.Graphics
break;
}
if (_strokeLineCap == aLineCap)
return;
_strokeLineCap = aLineCap;
InvalidateSelf();
@ -289,18 +323,23 @@ namespace Microsoft.Maui.Graphics
protected override void OnBoundsChange(ARect? bounds)
{
if (bounds != null)
if (_bounds != bounds)
{
var width = bounds.Width();
var height = bounds.Height();
_bounds = bounds;
if (_width == width && _height == height)
return;
if (_bounds != null)
{
var width = _bounds.Width();
var height = _bounds.Height();
_invalidatePath = true;
if (_width == width && _height == height)
return;
_width = width;
_height = height;
_invalidatePath = true;
_width = width;
_height = height;
}
}
base.OnBoundsChange(bounds);
@ -352,13 +391,6 @@ namespace Microsoft.Maui.Graphics
{
_clipPath.Reset();
_clipPath.Set(clipPath);
if (_maskPath != null && HasBorder())
{
_maskPath.Reset();
_maskPath.AddRect(0, 0, _width, _height, Path.Direction.Cw!);
_maskPath.InvokeOp(_clipPath, Path.Op.Difference!);
}
}
}
}
@ -374,9 +406,6 @@ namespace Microsoft.Maui.Graphics
if (_clipPath != null && _borderPaint != null)
canvas.DrawPath(_clipPath, _borderPaint);
if (_maskPath != null && _maskPaint != null)
canvas.DrawPath(_maskPath, _maskPaint);
canvas.RestoreToCount(saveCount);
}
else
@ -419,19 +448,6 @@ namespace Microsoft.Maui.Graphics
{
if (disposing)
{
if (_maskPath != null)
{
_maskPath.Dispose();
_maskPath = null;
}
if (_maskPaint != null)
{
_maskPaint.SetXfermode(null);
_maskPaint.Dispose();
_maskPaint = null;
}
if (_borderPaint != null)
{
_borderPaint.Dispose();
@ -455,18 +471,6 @@ namespace Microsoft.Maui.Graphics
return;
}
if (_maskPath == null)
_maskPath = new Path();
if (_maskPaint == null)
{
_maskPaint = new APaint(PaintFlags.AntiAlias);
_maskPaint.SetStyle(APaint.Style.FillAndStroke);
PorterDuffXfermode porterDuffClearMode = new PorterDuffXfermode(PorterDuff.Mode.Clear);
_maskPaint.SetXfermode(porterDuffClearMode);
}
if (_borderPaint == null)
{
_borderPaint = new APaint(PaintFlags.AntiAlias);

Просмотреть файл

@ -17,6 +17,10 @@ namespace Microsoft.Maui.Handlers
CrossPlatformArrange = VirtualView.CrossPlatformArrange
};
// We only want to use a hardware layer for the entering view because its quite likely
// the view will invalidate several times the Drawable (Draw).
viewGroup.SetLayerType(Android.Views.LayerType.Hardware, null);
return viewGroup;
}
@ -51,6 +55,7 @@ namespace Microsoft.Maui.Handlers
{
// If we're being disconnected from the xplat element, then we should no longer be managing its chidren
nativeView.RemoveAllViews();
base.DisconnectHandler(nativeView);
}
}

Просмотреть файл

@ -8,9 +8,9 @@ namespace Microsoft.Maui.Platform
public static void UpdateStrokeShape(this AView nativeView, IBorder border)
{
var borderShape = border.Shape;
MauiDrawable? background = nativeView.Background as MauiDrawable;
MauiDrawable? mauiDrawable = nativeView.Background as MauiDrawable;
if (background == null && borderShape == null)
if (mauiDrawable == null && borderShape == null)
return;
nativeView.UpdateMauiDrawable(border);
@ -19,82 +19,83 @@ namespace Microsoft.Maui.Platform
public static void UpdateStroke(this AView nativeView, IBorder border)
{
var stroke = border.Stroke;
MauiDrawable? background = nativeView.Background as MauiDrawable;
MauiDrawable? mauiDrawable = nativeView.Background as MauiDrawable;
if (background == null && stroke.IsNullOrEmpty())
if (mauiDrawable == null && stroke.IsNullOrEmpty())
return;
nativeView.UpdateMauiDrawable(border);
mauiDrawable?.SetBorderBrush(border.Stroke);
}
public static void UpdateStrokeThickness(this AView nativeView, IBorder border)
{
MauiDrawable? background = nativeView.Background as MauiDrawable;
MauiDrawable? mauiDrawable = nativeView.Background as MauiDrawable;
bool hasBorder = border.Shape != null && border.Stroke != null;
if (background == null && !hasBorder)
if (mauiDrawable == null && !hasBorder)
return;
nativeView.UpdateMauiDrawable(border);
mauiDrawable?.SetBorderWidth(border.StrokeThickness);
}
public static void UpdateStrokeDashPattern(this AView nativeView, IBorder border)
{
var strokeDashPattern = border.StrokeDashPattern;
MauiDrawable? background = nativeView.Background as MauiDrawable;
MauiDrawable? mauiDrawable = nativeView.Background as MauiDrawable;
bool hasBorder = border.Shape != null && border.Stroke != null;
if (background == null && !hasBorder && (strokeDashPattern == null || strokeDashPattern.Length == 0))
if (mauiDrawable == null && !hasBorder && (strokeDashPattern == null || strokeDashPattern.Length == 0))
return;
nativeView.UpdateMauiDrawable(border);
mauiDrawable?.SetBorderDash(border.StrokeDashPattern, border.StrokeDashOffset);
}
public static void UpdateStrokeDashOffset(this AView nativeView, IBorder border)
{
MauiDrawable? background = nativeView.Background as MauiDrawable;
MauiDrawable? mauiDrawable = nativeView.Background as MauiDrawable;
bool hasBorder = border.Shape != null && border.Stroke != null;
if (background == null && !hasBorder)
if (mauiDrawable == null && !hasBorder)
return;
nativeView.UpdateMauiDrawable(border);
mauiDrawable?.SetBorderDash(border.StrokeDashPattern, border.StrokeDashOffset);
}
public static void UpdateStrokeMiterLimit(this AView nativeView, IBorder border)
{
MauiDrawable? background = nativeView.Background as MauiDrawable;
MauiDrawable? mauiDrawable = nativeView.Background as MauiDrawable;
bool hasBorder = border.Shape != null && border.Stroke != null;
if (background == null && !hasBorder)
if (mauiDrawable == null && !hasBorder)
return;
nativeView.UpdateMauiDrawable(border);
mauiDrawable?.SetBorderMiterLimit(border.StrokeMiterLimit);
}
public static void UpdateStrokeLineCap(this AView nativeView, IBorder border)
{
MauiDrawable? background = nativeView.Background as MauiDrawable;
MauiDrawable? mauiDrawable = nativeView.Background as MauiDrawable;
bool hasBorder = border.Shape != null && border.Stroke != null;
if (background == null && !hasBorder)
if (mauiDrawable == null && !hasBorder)
return;
nativeView.UpdateMauiDrawable(border);
mauiDrawable?.SetBorderLineCap(border.StrokeLineCap);
}
public static void UpdateStrokeLineJoin(this AView nativeView, IBorder border)
{
MauiDrawable? background = nativeView.Background as MauiDrawable;
MauiDrawable? mauiDrawable = nativeView.Background as MauiDrawable;
bool hasBorder = border.Shape != null && border.Stroke != null;
if (background == null && !hasBorder)
if (mauiDrawable == null && !hasBorder)
return;
nativeView.UpdateMauiDrawable(border);
mauiDrawable?.SetBorderLineJoin(border.StrokeLineJoin);
}
internal static void UpdateMauiDrawable(this AView nativeView, IBorder border)
@ -114,12 +115,6 @@ namespace Microsoft.Maui.Platform
}
mauiDrawable.SetBackground(border.Background);
mauiDrawable.SetBorderBrush(border.Stroke);
mauiDrawable.SetBorderWidth(border.StrokeThickness);
mauiDrawable.SetBorderDash(border.StrokeDashPattern, border.StrokeDashOffset);
mauiDrawable.SetBorderMiterLimit(border.StrokeMiterLimit);
mauiDrawable.SetBorderLineJoin(border.StrokeLineJoin);
mauiDrawable.SetBorderLineCap(border.StrokeLineCap);
mauiDrawable.SetBorderShape(border.Shape);
}
}