Fix compilation: restore clean RC1 codebase
- Restore clean BindableProperty.Create syntax from RC1 commit - Remove decompiler artifacts with mangled delegate types - Add Svg.Skia package reference for icon support - Fix duplicate type definitions - Library now compiles successfully (0 errors) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,254 +1,232 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Microsoft.Maui.Platform.Linux.Rendering;
|
||||
|
||||
/// <summary>
|
||||
/// Manages dirty rectangles for optimized rendering.
|
||||
/// Only redraws areas that have been invalidated.
|
||||
/// </summary>
|
||||
public class DirtyRectManager
|
||||
{
|
||||
private readonly List<SKRect> _dirtyRects = new List<SKRect>();
|
||||
private readonly List<SKRect> _dirtyRects = new();
|
||||
private readonly object _lock = new();
|
||||
private bool _fullRedrawNeeded = true;
|
||||
private SKRect _bounds;
|
||||
private int _maxDirtyRects = 10;
|
||||
|
||||
private readonly object _lock = new object();
|
||||
/// <summary>
|
||||
/// Gets or sets the maximum number of dirty rectangles to track before
|
||||
/// falling back to a full redraw.
|
||||
/// </summary>
|
||||
public int MaxDirtyRects
|
||||
{
|
||||
get => _maxDirtyRects;
|
||||
set => _maxDirtyRects = Math.Max(1, value);
|
||||
}
|
||||
|
||||
private bool _fullRedrawNeeded = true;
|
||||
/// <summary>
|
||||
/// Gets whether a full redraw is needed.
|
||||
/// </summary>
|
||||
public bool NeedsFullRedraw => _fullRedrawNeeded;
|
||||
|
||||
private SKRect _bounds;
|
||||
/// <summary>
|
||||
/// Gets the current dirty rectangles.
|
||||
/// </summary>
|
||||
public IReadOnlyList<SKRect> DirtyRects
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _dirtyRects.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int _maxDirtyRects = 10;
|
||||
/// <summary>
|
||||
/// Gets whether there are any dirty regions.
|
||||
/// </summary>
|
||||
public bool HasDirtyRegions
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _fullRedrawNeeded || _dirtyRects.Count > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int MaxDirtyRects
|
||||
{
|
||||
get
|
||||
{
|
||||
return _maxDirtyRects;
|
||||
}
|
||||
set
|
||||
{
|
||||
_maxDirtyRects = Math.Max(1, value);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Sets the rendering bounds.
|
||||
/// </summary>
|
||||
public void SetBounds(SKRect bounds)
|
||||
{
|
||||
if (_bounds != bounds)
|
||||
{
|
||||
_bounds = bounds;
|
||||
InvalidateAll();
|
||||
}
|
||||
}
|
||||
|
||||
public bool NeedsFullRedraw => _fullRedrawNeeded;
|
||||
/// <summary>
|
||||
/// Invalidates a specific region.
|
||||
/// </summary>
|
||||
public void Invalidate(SKRect rect)
|
||||
{
|
||||
if (rect.IsEmpty) return;
|
||||
|
||||
public IReadOnlyList<SKRect> DirtyRects
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _dirtyRects.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
lock (_lock)
|
||||
{
|
||||
if (_fullRedrawNeeded) return;
|
||||
|
||||
public bool HasDirtyRegions
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
return _fullRedrawNeeded || _dirtyRects.Count > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Clamp to bounds
|
||||
rect = SKRect.Intersect(rect, _bounds);
|
||||
if (rect.IsEmpty) return;
|
||||
|
||||
public void SetBounds(SKRect bounds)
|
||||
{
|
||||
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (_bounds != bounds)
|
||||
{
|
||||
_bounds = bounds;
|
||||
InvalidateAll();
|
||||
}
|
||||
}
|
||||
// Try to merge with existing dirty rects
|
||||
for (int i = 0; i < _dirtyRects.Count; i++)
|
||||
{
|
||||
if (_dirtyRects[i].Contains(rect))
|
||||
{
|
||||
// Already covered
|
||||
return;
|
||||
}
|
||||
|
||||
public void Invalidate(SKRect rect)
|
||||
{
|
||||
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_005b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_014f: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_011c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
|
||||
if (((SKRect)(ref rect)).IsEmpty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lock (_lock)
|
||||
{
|
||||
if (_fullRedrawNeeded)
|
||||
{
|
||||
return;
|
||||
}
|
||||
rect = SKRect.Intersect(rect, _bounds);
|
||||
if (((SKRect)(ref rect)).IsEmpty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < _dirtyRects.Count; i++)
|
||||
{
|
||||
SKRect val = _dirtyRects[i];
|
||||
if (((SKRect)(ref val)).Contains(rect))
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (((SKRect)(ref rect)).Contains(_dirtyRects[i]))
|
||||
{
|
||||
_dirtyRects[i] = rect;
|
||||
MergeDirtyRects();
|
||||
return;
|
||||
}
|
||||
SKRect val2 = SKRect.Intersect(_dirtyRects[i], rect);
|
||||
if (!((SKRect)(ref val2)).IsEmpty)
|
||||
{
|
||||
float num = ((SKRect)(ref val2)).Width * ((SKRect)(ref val2)).Height;
|
||||
val = _dirtyRects[i];
|
||||
float width = ((SKRect)(ref val)).Width;
|
||||
val = _dirtyRects[i];
|
||||
float num2 = Math.Min(width * ((SKRect)(ref val)).Height, ((SKRect)(ref rect)).Width * ((SKRect)(ref rect)).Height);
|
||||
if (num > num2 * 0.5f)
|
||||
{
|
||||
_dirtyRects[i] = SKRect.Union(_dirtyRects[i], rect);
|
||||
MergeDirtyRects();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
_dirtyRects.Add(rect);
|
||||
if (_dirtyRects.Count > _maxDirtyRects)
|
||||
{
|
||||
_fullRedrawNeeded = true;
|
||||
_dirtyRects.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rect.Contains(_dirtyRects[i]))
|
||||
{
|
||||
// New rect covers existing
|
||||
_dirtyRects[i] = rect;
|
||||
MergeDirtyRects();
|
||||
return;
|
||||
}
|
||||
|
||||
public void InvalidateAll()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_fullRedrawNeeded = true;
|
||||
_dirtyRects.Clear();
|
||||
}
|
||||
}
|
||||
// Check if they overlap significantly (50% overlap)
|
||||
var intersection = SKRect.Intersect(_dirtyRects[i], rect);
|
||||
if (!intersection.IsEmpty)
|
||||
{
|
||||
float intersectArea = intersection.Width * intersection.Height;
|
||||
float smallerArea = Math.Min(
|
||||
_dirtyRects[i].Width * _dirtyRects[i].Height,
|
||||
rect.Width * rect.Height);
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_fullRedrawNeeded = false;
|
||||
_dirtyRects.Clear();
|
||||
}
|
||||
}
|
||||
if (intersectArea > smallerArea * 0.5f)
|
||||
{
|
||||
// Merge the rectangles
|
||||
_dirtyRects[i] = SKRect.Union(_dirtyRects[i], rect);
|
||||
MergeDirtyRects();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SKRect GetCombinedDirtyRect()
|
||||
{
|
||||
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
|
||||
lock (_lock)
|
||||
{
|
||||
if (_fullRedrawNeeded || _dirtyRects.Count == 0)
|
||||
{
|
||||
return _bounds;
|
||||
}
|
||||
SKRect val = _dirtyRects[0];
|
||||
for (int i = 1; i < _dirtyRects.Count; i++)
|
||||
{
|
||||
val = SKRect.Union(val, _dirtyRects[i]);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
}
|
||||
// Add as new dirty rect
|
||||
_dirtyRects.Add(rect);
|
||||
|
||||
public void ApplyClipping(SKCanvas canvas)
|
||||
{
|
||||
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_002e: Expected O, but got Unknown
|
||||
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
|
||||
lock (_lock)
|
||||
{
|
||||
if (_fullRedrawNeeded || _dirtyRects.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SKPath val = new SKPath();
|
||||
try
|
||||
{
|
||||
foreach (SKRect dirtyRect in _dirtyRects)
|
||||
{
|
||||
val.AddRect(dirtyRect, (SKPathDirection)0);
|
||||
}
|
||||
canvas.ClipPath(val, (SKClipOperation)1, false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
((IDisposable)val)?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check if we have too many dirty rects
|
||||
if (_dirtyRects.Count > _maxDirtyRects)
|
||||
{
|
||||
// Fall back to full redraw
|
||||
_fullRedrawNeeded = true;
|
||||
_dirtyRects.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void MergeDirtyRects()
|
||||
{
|
||||
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
|
||||
bool flag;
|
||||
do
|
||||
{
|
||||
flag = false;
|
||||
for (int i = 0; i < _dirtyRects.Count - 1; i++)
|
||||
{
|
||||
for (int j = i + 1; j < _dirtyRects.Count; j++)
|
||||
{
|
||||
SKRect val = SKRect.Intersect(_dirtyRects[i], _dirtyRects[j]);
|
||||
if (!((SKRect)(ref val)).IsEmpty)
|
||||
{
|
||||
_dirtyRects[i] = SKRect.Union(_dirtyRects[i], _dirtyRects[j]);
|
||||
_dirtyRects.RemoveAt(j);
|
||||
flag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
while (flag);
|
||||
}
|
||||
/// <summary>
|
||||
/// Invalidates the entire rendering area.
|
||||
/// </summary>
|
||||
public void InvalidateAll()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_fullRedrawNeeded = true;
|
||||
_dirtyRects.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all dirty regions after rendering.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_fullRedrawNeeded = false;
|
||||
_dirtyRects.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the combined dirty region as a single rectangle.
|
||||
/// </summary>
|
||||
public SKRect GetCombinedDirtyRect()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_fullRedrawNeeded || _dirtyRects.Count == 0)
|
||||
{
|
||||
return _bounds;
|
||||
}
|
||||
|
||||
var combined = _dirtyRects[0];
|
||||
for (int i = 1; i < _dirtyRects.Count; i++)
|
||||
{
|
||||
combined = SKRect.Union(combined, _dirtyRects[i]);
|
||||
}
|
||||
return combined;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies dirty region clipping to a canvas.
|
||||
/// </summary>
|
||||
public void ApplyClipping(SKCanvas canvas)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
if (_fullRedrawNeeded || _dirtyRects.Count == 0)
|
||||
{
|
||||
// No clipping needed for full redraw
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a path from all dirty rects
|
||||
using var path = new SKPath();
|
||||
foreach (var rect in _dirtyRects)
|
||||
{
|
||||
path.AddRect(rect);
|
||||
}
|
||||
|
||||
canvas.ClipPath(path);
|
||||
}
|
||||
}
|
||||
|
||||
private void MergeDirtyRects()
|
||||
{
|
||||
// Simple merge pass - could be optimized
|
||||
bool merged;
|
||||
do
|
||||
{
|
||||
merged = false;
|
||||
for (int i = 0; i < _dirtyRects.Count - 1; i++)
|
||||
{
|
||||
for (int j = i + 1; j < _dirtyRects.Count; j++)
|
||||
{
|
||||
var intersection = SKRect.Intersect(_dirtyRects[i], _dirtyRects[j]);
|
||||
if (!intersection.IsEmpty)
|
||||
{
|
||||
_dirtyRects[i] = SKRect.Union(_dirtyRects[i], _dirtyRects[j]);
|
||||
_dirtyRects.RemoveAt(j);
|
||||
merged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (merged) break;
|
||||
}
|
||||
} while (merged);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user