Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(WriteableBitmap): Invalidation should cause a redrawing #18408

Merged
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices.WindowsRuntime;
using Uno.UI.Samples.Controls;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
Expand All @@ -24,26 +26,18 @@ public WriteableBitmap_MultiInvalidate()
private void UpdateSource(object sender, RoutedEventArgs e)
{
var randomizer = new Random(_seed++);
if (_bitmap.PixelBuffer is Windows.Storage.Streams.Buffer buffer
&& buffer.GetType().GetField("_data", BindingFlags.NonPublic | BindingFlags.Instance)?.GetValue(buffer) is Memory<byte> data)
var stream = _bitmap.PixelBuffer.AsStream();
var length = _bitmap.PixelBuffer.Length;
for (var i = 0; i < length; i++)
{
var span = data.Span;
for (var i = 0; i < data.Length; i++)
if (i % 4 == 3)
{
if (i % 4 == 3)
{
// Alpha channel
span[i] = 255;
}
else
{
span[i] = (byte)randomizer.Next(256);
}
stream.WriteByte(255);
}
else
{
stream.WriteByte((byte)randomizer.Next(256));
}
}
else
{
throw new InvalidOperationException("Could not access _data field in Buffer type.");
}

// This request to the image to redraw the buffer
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,119 +133,6 @@ public void When_SetSourceAsync_Stream_Then_StreamClonedSynchronously()
}
#endif

[TestMethod]
[RunsOnUIThread]
public async Task When_WriteableBitmap_Assigned_With_Data_Present()
{
if (!ApiInformation.IsTypePresent("Microsoft.UI.Xaml.Media.Imaging.RenderTargetBitmap"))
{
Assert.Inconclusive(); // System.NotImplementedException: RenderTargetBitmap is not supported on this platform.;
}

var wb = new WriteableBitmap(20, 20);

var parent = new Border()
{
Width = 50,
Height = 50,
Background = new SolidColorBrush(Colors.Blue),
};

var rect = new Rectangle
{
Width = 20,
Height = 20,
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center,
};

parent.Child = rect;

WindowHelper.WindowContent = parent;

await WindowHelper.WaitForIdle();
await WindowHelper.WaitForLoaded(rect);

var bgraPixelData = Enumerable.Repeat<byte>(255, (int)wb.PixelBuffer.Length).ToArray();

using (Stream stream = wb.PixelBuffer.AsStream())
{
stream.Write(bgraPixelData, 0, bgraPixelData.Length);
}

rect.Fill = new ImageBrush
{
ImageSource = wb
};

await WindowHelper.WaitForIdle();

var snapshot = await UITestHelper.ScreenShot(parent);
var coords = parent.GetRelativeCoords(rect);
await WindowHelper.WaitForIdle();

ImageAssert.DoesNotHaveColorInRectangle(
snapshot, new System.Drawing.Rectangle((int)coords.X, (int)coords.Y, (int)coords.Width, (int)coords.Height), Colors.Blue);
}

[TestMethod]
[RunsOnUIThread]
#if __WASM__
[Ignore("https://github.com/unoplatform/uno/issues/12445")]
#endif
public async Task When_WriteableBitmap_SetSource_Should_Update_PixelWidth_And_PixelHeight()
{
if (!ApiInformation.IsTypePresent("Microsoft.UI.Xaml.Media.Imaging.RenderTargetBitmap"))
{
Assert.Inconclusive(); // System.NotImplementedException: RenderTargetBitmap is not supported on this platform.;
}

var writeableBitmap = new WriteableBitmap(1, 1);
var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/ingredient3.png"));
using (var stream = await file.OpenReadAsync())
{
await writeableBitmap.SetSourceAsync(stream);
}

Assert.AreEqual(147, writeableBitmap.PixelWidth);
Assert.AreEqual(147, writeableBitmap.PixelHeight);

var parent = new Border()
{
Width = 147,
Height = 147,
};

var rect = new Rectangle
{
Width = 147,
Height = 147,
};

parent.Child = rect;

WindowHelper.WindowContent = parent;

await WindowHelper.WaitForIdle();
await WindowHelper.WaitForLoaded(rect);

rect.Fill = new ImageBrush
{
ImageSource = writeableBitmap
};

await WindowHelper.WaitForIdle();

var renderer = new RenderTargetBitmap();

await renderer.RenderAsync(parent);
var snapshot = await RawBitmap.From(renderer, rect);

#if !__IOS__ && !__MACOS__ // https://github.com/unoplatform/uno/issues/12705
ImageAssert.HasColorAt(snapshot, 1, 1, Color.FromArgb(0xFF, 0xFA, 0xB8, 0x63), tolerance: 5);
#endif
}

[TestMethod]
[RunsOnUIThread]
public async Task When_ImageBrush_Source_Changes()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Markup;
using Microsoft.UI.Xaml.Media.Imaging;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Runtime.InteropServices.WindowsRuntime;
using Private.Infrastructure;
using Windows.Storage;
using static Private.Infrastructure.TestServices;
using Microsoft.UI.Xaml.Shapes;
using Microsoft.UI.Xaml.Media;
using Windows.UI;
using Uno.UI.RuntimeTests.Helpers;
using Uno.UI.RuntimeTests.Extensions;
using Windows.Foundation.Metadata;
using Microsoft.UI.Xaml;
using System.Linq;

namespace Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Media_Imaging
{
[TestClass]
[RunsOnUIThread]
public class Given_WriteableBitmap
{
[TestMethod]
public async Task When_Invalidated()
{
if (!ApiInformation.IsTypePresent("Microsoft.UI.Xaml.Media.Imaging.RenderTargetBitmap"))
{
Assert.Inconclusive(); // System.NotImplementedException: RenderTargetBitmap is not supported on this platform.;

Check warning on line 35 in src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Media_Imaging/Given_WriteableBitmap.cs

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Media_Imaging/Given_WriteableBitmap.cs#L35

Remove this commented out code.
}

var seed = 42;
var bitmap = new WriteableBitmap(200, 200);
var border = new Border
{
Width = 200,
Height = 200,
Background = new ImageBrush { ImageSource = bitmap }
};

UpdateSource();

await UITestHelper.Load(border);

var snapshot1 = await UITestHelper.ScreenShot(border);

UpdateSource();
await WindowHelper.WaitForIdle();

var snapshot2 = await UITestHelper.ScreenShot(border);
await ImageAssert.AreNotEqualAsync(snapshot1, snapshot2);

void UpdateSource()
{
var randomizer = new Random(seed++);
var stream = bitmap.PixelBuffer.AsStream();
var length = bitmap.PixelBuffer.Length;
for (var i = 0; i < length; i++)
{
if (i % 4 == 3)

Check failure on line 66 in src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Media_Imaging/Given_WriteableBitmap.cs

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Media_Imaging/Given_WriteableBitmap.cs#L66

The result of this modulus operation may not be positive.
{
stream.WriteByte(255);
}
else
{
stream.WriteByte((byte)randomizer.Next(256));
}
}

bitmap.Invalidate();
}
}

[TestMethod]
[RunsOnUIThread]
public async Task When_WriteableBitmap_Assigned_With_Data_Present()
{
if (!ApiInformation.IsTypePresent("Microsoft.UI.Xaml.Media.Imaging.RenderTargetBitmap"))
{
Assert.Inconclusive(); // System.NotImplementedException: RenderTargetBitmap is not supported on this platform.;
}

var wb = new WriteableBitmap(20, 20);

var parent = new Border()
{
Width = 50,
Height = 50,
Background = new SolidColorBrush(Colors.Blue),
};

var rect = new Rectangle
{
Width = 20,
Height = 20,
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center,
};

parent.Child = rect;

WindowHelper.WindowContent = parent;

await WindowHelper.WaitForIdle();
await WindowHelper.WaitForLoaded(rect);

var bgraPixelData = Enumerable.Repeat<byte>(255, (int)wb.PixelBuffer.Length).ToArray();

using (Stream stream = wb.PixelBuffer.AsStream())
{
stream.Write(bgraPixelData, 0, bgraPixelData.Length);
}

rect.Fill = new ImageBrush
{
ImageSource = wb
};

await WindowHelper.WaitForIdle();

var snapshot = await UITestHelper.ScreenShot(parent);
var coords = parent.GetRelativeCoords(rect);
await WindowHelper.WaitForIdle();

ImageAssert.DoesNotHaveColorInRectangle(
snapshot, new System.Drawing.Rectangle((int)coords.X, (int)coords.Y, (int)coords.Width, (int)coords.Height), Colors.Blue);
}

[TestMethod]
[RunsOnUIThread]
#if __WASM__
[Ignore("https://github.com/unoplatform/uno/issues/12445")]
#endif
public async Task When_WriteableBitmap_SetSource_Should_Update_PixelWidth_And_PixelHeight()
{
if (!ApiInformation.IsTypePresent("Microsoft.UI.Xaml.Media.Imaging.RenderTargetBitmap"))
{
Assert.Inconclusive(); // System.NotImplementedException: RenderTargetBitmap is not supported on this platform.;
}

var writeableBitmap = new WriteableBitmap(1, 1);
var file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/ingredient3.png"));
using (var stream = await file.OpenReadAsync())
{
await writeableBitmap.SetSourceAsync(stream);
}

Assert.AreEqual(147, writeableBitmap.PixelWidth);
Assert.AreEqual(147, writeableBitmap.PixelHeight);

var parent = new Border()
{
Width = 147,
Height = 147,
};

var rect = new Rectangle
{
Width = 147,
Height = 147,
};

parent.Child = rect;

WindowHelper.WindowContent = parent;

await WindowHelper.WaitForIdle();
await WindowHelper.WaitForLoaded(rect);

rect.Fill = new ImageBrush
{
ImageSource = writeableBitmap
};

await WindowHelper.WaitForIdle();

var renderer = new RenderTargetBitmap();

await renderer.RenderAsync(parent);
var snapshot = await RawBitmap.From(renderer, rect);

#if !__IOS__ && !__MACOS__ // https://github.com/unoplatform/uno/issues/12705
ImageAssert.HasColorAt(snapshot, 1, 1, Color.FromArgb(0xFF, 0xFA, 0xB8, 0x63), tolerance: 5);
#endif
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,6 @@ partial void UpdatePlatform()
var newState = new BorderLayerState(drawArea.Size, _borderInfoProvider);
var previousLayoutState = _currentState;

if (newState.Equals(previousLayoutState))
{
return;
}

MartinZikmund marked this conversation as resolved.
Show resolved Hide resolved
var newStateBackgroundImageSource = GetBackgroundImageSource(newState);
var oldStateBackgroundImageSource = GetBackgroundImageSource(previousLayoutState);

Expand Down
Loading