Repository: unoplatform/uno
File: src/Uno.UI/UI/Xaml/Media/Imaging/RenderTargetBitmap.skia.cs (C#)

Code before:

				return ImageData.FromCompositionSurface(new SkiaCompositionSurface(image));
			}
			catch (Exception error)
			{
				return ImageData.FromError(error);
			}
		}

		private static (int ByteCount, int Width, int Height) RenderAsBgra8_Premul(UIElement element, ref UnmanagedArrayOfBytes? buffer, Size? scaledSize = null)
		{
			var compositor = Compositor.GetSharedCompositor();

			bool? previousCompMode = compositor.IsSoftwareRenderer;
			compositor.IsSoftwareRenderer = true;

			var renderSize = element.RenderSize;
			var visual = element.Visual;

			if (renderSize is { IsEmpty: true } or { Width: 0, Height: 0 })
			{
				return (0, 0, 0);
			}

			// Note: RenderTargetBitmap returns images with the current DPI (a 50x50 Border rendered on WinUI will return a 75x75 image)
			var dpi = element.XamlRoot?.VisualTree.RootScale.GetEffectiveRasterizationScale() ?? DisplayInformation.GetForCurrentView()?.RawPixelsPerViewPixel ?? 1;
			var (width, height) = ((int)(renderSize.Width * dpi), (int)(renderSize.Height * dpi));
			var info = new SKImageInfo(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);
			using var surface = SKSurface.Create(info);
			//Ensure Clear
			var canvas = surface.Canvas;
			canvas.Clear(SKColors.Transparent);
			canvas.Scale((float)dpi);
			visual.RenderRootVisual(canvas, offsetOverride: Vector2.Zero);

			var img = surface.Snapshot();

			var bitmap = img.ToSKBitmap();
			if (scaledSize.HasValue)
			{
				var scaledBitmap = bitmap.Resize(
					new SKImageInfo((int)scaledSize.Value.Width, (int)scaledSize.Value.Height, SKColorType.Bgra8888, SKAlphaType.Premul),
					new SKSamplingOptions(SKCubicResampler.CatmullRom));
				bitmap.Dispose();
				bitmap = scaledBitmap;
				(width, height) = (bitmap.Width, bitmap.Height);
			}

			var byteCount = bitmap.ByteCount;
			EnsureBuffer(ref buffer, byteCount);
			unsafe

Review comment (bug):
I Initially didn't like hot-fixing the clip here and I thought it would be a lot nicer to send this as a parameter to RenderRootVisual itself. But actually, this is exactly what we have to do because only the "layout clip" should be removed but not the clip from UIElement.Clip (I've tested on WinUI), so if we send a parameter to RenderRootVisual to ignore the clipping altogether for the "root element", then that's actually incorrect.

Code after:

				return ImageData.FromCompositionSurface(new SkiaCompositionSurface(image));
			}
			catch (Exception error)
			{
				return ImageData.FromError(error);
			}
		}

		private static (int ByteCount, int Width, int Height) RenderAsBgra8_Premul(UIElement element, ref UnmanagedArrayOfBytes? buffer, Size? scaledSize = null)
		{
			var compositor = Compositor.GetSharedCompositor();

			bool? previousCompMode = compositor.IsSoftwareRenderer;
			compositor.IsSoftwareRenderer = true;

			var renderSize = element.RenderSize;
			var visual = element.Visual;

			var previousClip = visual.LayoutClip;

			try
			{
				// Remove any existing layout clip, we want to render the full element, not
				// the clipped part based on the existing parent's layout slot.
				visual.LayoutClip = null;

				if (renderSize is { IsEmpty: true } or { Width: 0, Height: 0 })
				{
					return (0, 0, 0);
				}

				// Note: RenderTargetBitmap returns images with the current DPI (a 50x50 Border rendered on WinUI will return a 75x75 image)
				var dpi = element.XamlRoot?.VisualTree.RootScale.GetEffectiveRasterizationScale() ?? DisplayInformation.GetForCurrentView()?.RawPixelsPerViewPixel ?? 1;
				var (width, height) = ((int)(renderSize.Width * dpi), (int)(renderSize.Height * dpi));
				var info = new SKImageInfo(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);
				using var surface = SKSurface.Create(info);
				//Ensure Clear
				var canvas = surface.Canvas;
				canvas.Clear(SKColors.Transparent);
				canvas.Scale((float)dpi);
				visual.RenderRootVisual(canvas, offsetOverride: Vector2.Zero);

				var img = surface.Snapshot();

				var bitmap = img.ToSKBitmap();
				if (scaledSize.HasValue)
				{
					var scaledBitmap = bitmap.Resize(
						new SKImageInfo((int)scaledSize.Value.Width, (int)scaledSize.Value.Height, SKColorType.Bgra8888, SKAlphaType.Premul),
						new SKSamplingOptions(SKCubicResampler.CatmullRom));