### Install SkiaSharp.Extended Core Utilities Source: https://github.com/mono/skiasharp.extended/blob/main/docs/index.md Install the core utilities package for SkiaSharp.Extended using the .NET CLI. ```bash dotnet add package SkiaSharp.Extended ``` -------------------------------- ### Quick Start: Create and Interpolate Paths Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/path-interpolation.md Defines start and end paths (square and star) and creates an SKPathInterpolation object to get a path at a specific transition point (0.5). ```csharp using SkiaSharp; using SkiaSharp.Extended; // Define your start and end paths var square = SKGeometry.CreateSquarePath(100); var star = SKGeometry.CreateRegularStarPath(100, 40, 5); // Create the interpolation var interpolation = new SKPathInterpolation(square, star); // Get paths at any point in the transition (0 to 1) var halfway = interpolation.Interpolate(0.5f); ``` -------------------------------- ### Complete Migration Example: Before (SkiaSharp.Extended.Svg) Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/svg-migration.md A complete C# code example demonstrating the usage of SkiaSharp.Extended.Svg for loading and drawing SVGs within a MAUI application. This serves as the 'before' state for migration. ```csharp using SkiaSharp; using SkiaSharp.Extended.Svg; using SkiaSharp.Views.Maui; using SkiaSharp.Views.Maui.Controls; namespace MyApp { public partial class MyPage : ContentPage { private SKSvg? svg; private void LoadSvg() { svg = new SKSvg(); using var stream = FileSystem.OpenAppPackageFileAsync("image.svg").Result; svg.Load(stream); } private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) { var canvas = e.Surface.Canvas; canvas.Clear(SKColors.White); if (svg?.Picture != null) { canvas.DrawPicture(svg.Picture); } } } } ``` -------------------------------- ### Complete Confetti Example Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/confetti.md A comprehensive example demonstrating how to configure multiple aspects of an SKConfettiSystem, including emitter, colors, shapes, velocity, and lifetime, for a celebratory effect. ```csharp void CelebrateAchievement() { confettiView.Systems.Add(new SKConfettiSystem { Emitter = SKConfettiEmitter.Burst(150), EmitterBounds = SKConfettiEmitterBounds.Center, Colors = { Colors.Gold, Colors.Orange, Colors.Yellow }, Shapes = { new SKConfettiSquareShape(), new SKConfettiCircleShape() }, MinimumInitialVelocity = 150, MaximumInitialVelocity = 350, Lifetime = 4.0, FadeOut = true }); } ``` -------------------------------- ### Complete Migration Example: After (Svg.Skia) Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/svg-migration.md A complete C# code example demonstrating the usage of Svg.Skia for loading and drawing SVGs within a MAUI application. This shows the 'after' state post-migration, highlighting the minimal API changes. ```csharp using SkiaSharp; using Svg.Skia; // Changed this line using SkiaSharp.Views.Maui; using SkiaSharp.Views.Maui.Controls; namespace MyApp { public partial class MyPage : ContentPage { private SKSvg? svg; private void LoadSvg() { svg = new SKSvg(); using var stream = FileSystem.OpenAppPackageFileAsync("image.svg").Result; svg.Load(stream); // Same API! } private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) { var canvas = e.Surface.Canvas; canvas.Clear(SKColors.White); if (svg?.Picture != null) { canvas.DrawPicture(svg.Picture); // Same API! } } } } ``` -------------------------------- ### Install SkiaSharp.Extended MAUI Controls Source: https://github.com/mono/skiasharp.extended/blob/main/docs/index.md Install the MAUI controls package for SkiaSharp.Extended, which includes the core utilities, using the .NET CLI. ```bash dotnet add package SkiaSharp.Extended.UI.Maui ``` -------------------------------- ### Package Version Conflicts Example Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/svg-migration.md An example of how to align SkiaSharp-related package versions in a .NET project file to resolve conflicts during migration. ```xml ``` -------------------------------- ### Usage Pattern: Loading Indicator Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/path-interpolation.md Example of morphing between a circle and a square to create a loading animation. ```csharp // Morph between simple shapes for a loading animation var circle = new SKPath(); circle.AddCircle(0, 0, 50); var square = SKGeometry.CreateSquarePath(80); var loading = new SKPathInterpolation(circle, square); ``` -------------------------------- ### Update NuGet Packages Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/svg-migration.md Remove the old SkiaSharp.Extended.Svg package and install the Svg.Skia package using the .NET CLI. ```bash # Remove the old package dotnet remove package SkiaSharp.Extended.Svg # Add Svg.Skia dotnet add package Svg.Skia ``` -------------------------------- ### API Response with BlurHash Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/blurhash.md Example of including a pre-computed BlurHash in an API response alongside image URLs and dimensions. ```json { "imageUrl": "https://example.com/photo.jpg", "blurHash": "LjPsbRxG%gx^aJxuM|W=?^X8Mxn$", "width": 1920, "height": 1080 } ``` -------------------------------- ### Trigger a Confetti Burst Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/confetti.md Initiate a confetti burst by adding an SKConfettiSystem to the SKConfettiView's Systems collection. This example configures a burst of 100 particles from the center. ```csharp confettiView.Systems.Add(new SKConfettiSystem { Emitter = SKConfettiEmitter.Burst(100), EmitterBounds = SKConfettiEmitterBounds.Center }); ``` -------------------------------- ### Animation Example: MorphingShape Class Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/path-interpolation.md A class to manage the animation progress of a shape morph. It updates the progress over time and reverses direction at the ends (0 and 1). ```csharp public class MorphingShape { private readonly SKPathInterpolation interpolation; private float progress = 0f; private float direction = 1f; public MorphingShape(SKPath from, SKPath to) { interpolation = new SKPathInterpolation(from, to); } public void Update(float deltaTime) { progress += deltaTime * direction; if (progress >= 1f || progress <= 0f) direction *= -1; // Reverse at ends } public void Draw(SKCanvas canvas, SKPaint paint) { var path = interpolation.Interpolate(progress); canvas.DrawPath(path, paint); } } ``` -------------------------------- ### MAUI XAML Usage of BlurHashConverter Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/blurhash.md Example of how to use the BlurHashConverter in MAUI XAML to bind an image source to a BlurHash string. ```xml ``` -------------------------------- ### Usage Pattern: Icon Transitions Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/path-interpolation.md Demonstrates creating a smooth transition between two icon paths, such as play and pause, based on an animation progress value. ```csharp // Smooth transition between UI states (play → pause) var playIcon = CreatePlayIconPath(); var pauseIcon = CreatePauseIconPath(); var transition = new SKPathInterpolation(playIcon, pauseIcon); var currentIcon = transition.Interpolate(animationProgress); ``` -------------------------------- ### Customization: Pre-calculating for Performance Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/path-interpolation.md Shows how to call Prepare() on an SKPathInterpolation object to pre-calculate point mappings for faster subsequent Interpolate() calls. ```csharp var interpolation = new SKPathInterpolation(from, to); interpolation.Prepare(); // Pre-calculate point mappings // Now Interpolate() calls are faster for (float t = 0; t <= 1; t += 0.1f) { var path = interpolation.Interpolate(t); } ``` -------------------------------- ### Compare Images Using File Paths Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/pixel-comparer.md Demonstrates comparing two images directly from their file paths using the SKPixelComparer.Compare method. ```csharp Compare("a.png", "b.png") ``` -------------------------------- ### Offsetting a Path to a Specific Center Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/geometry.md Demonstrates how to position a path created at the origin to a desired center point using the Offset method. ```csharp var path = SKGeometry.CreateRegularStarPath(50, 20, 5); path.Offset(centerX, centerY); canvas.DrawPath(path, paint); ``` -------------------------------- ### Include Raw Assets in .NET MAUI Project Source: https://github.com/mono/skiasharp.extended/blob/main/samples/SkiaSharpDemo/Resources/Raw/AboutAssets.txt This XML snippet shows how to configure your .csproj file to include all files in the Resources\Raw directory and its subdirectories as MauiAssets. The LogicalName ensures the file is deployed with its original path and name. ```xml ``` -------------------------------- ### Configure Pixel Comparison Options Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/pixel-comparer.md Sets up SKPixelComparerOptions to customize comparison behavior, including per-channel tolerance and alpha channel comparison. Per-channel tolerance is enabled by default. ```csharp var options = new SKPixelComparerOptions { TolerancePerChannel = true, // Check each channel independently (default: true) CompareAlpha = true // Include alpha channel in comparison (default: false) }; var result = SKPixelComparer.Compare(expected, actual, options); ``` -------------------------------- ### Tolerance-Based Comparison with Options Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/pixel-comparer.md Applies tolerance-based pixel comparison while also utilizing custom SKPixelComparerOptions for advanced control. ```csharp // Tolerance-based with options var result = SKPixelComparer.Compare(expected, actual, tolerance: 10, options); ``` -------------------------------- ### Load Lottie Animations from Different Sources Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/lottie.md Load Lottie animations programmatically from app resources, a URL, or a stream by creating an appropriate SKLottieImageSource object. ```csharp // From app resources (recommended) lottieView.Source = new SKFileLottieImageSource { File = "animation.json" }; // From a URL lottieView.Source = new SKUriLottieImageSource { Uri = new Uri("https://...") }; // From a stream lottieView.Source = new SKStreamLottieImageSource { Stream = myStream }; ``` -------------------------------- ### Compare SKBitmaps Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/pixel-comparer.md Illustrates comparing two SKBitmap objects using the SKPixelComparer.Compare method. ```csharp Compare(bitmapA, bitmapB) ``` -------------------------------- ### Compare SKImages Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/pixel-comparer.md Shows how to compare two SKImage objects using the SKPixelComparer.Compare method. ```csharp Compare(imageA, imageB) ``` -------------------------------- ### Compare Two Images Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/pixel-comparer.md Compares two image files and returns a detailed result object containing various difference metrics. Ensure the image files exist and are accessible. ```csharp using SkiaSharp; using SkiaSharp.Extended; var result = SKPixelComparer.Compare("expected.png", "actual.png"); Console.WriteLine($"Total pixels: {result.TotalPixels}"); Console.WriteLine($"Error pixels: {result.ErrorPixelCount}"); Console.WriteLine($"Error percentage: {result.ErrorPixelPercentage:P2}"); Console.WriteLine($"Absolute error: {result.AbsoluteError}"); Console.WriteLine($"RMSE: {result.RootMeanSquaredError:F4}"); Console.WriteLine($"PSNR: {result.PeakSignalToNoiseRatio:F2} dB"); ``` -------------------------------- ### Compare SKPixmaps Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/pixel-comparer.md Demonstrates comparing two SKPixmap objects using the SKPixelComparer.Compare method. ```csharp Compare(pixmapA, pixmapB) ``` -------------------------------- ### Create a Regular Star Path Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/geometry.md Generates an SKPath for a regular star. Specify outer and inner radii, and the number of points. ```csharp using SkiaSharp; using SkiaSharp.Extended; // Create a 5-pointed star var starPath = SKGeometry.CreateRegularStarPath( outerRadius: 100, innerRadius: 40, points: 5); // Draw it on a canvas canvas.DrawPath(starPath, paint); ``` -------------------------------- ### Create a Star Path with Different Points Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/geometry.md Generates an SKPath for a regular star. Use different inner and outer radii to control the star's appearance. ```csharp // Classic 5-pointed star var star5 = SKGeometry.CreateRegularStarPath( outerRadius: 50, innerRadius: 20, points: 5); // Star of David (6-pointed) var star6 = SKGeometry.CreateRegularStarPath( outerRadius: 50, innerRadius: 30, points: 6); ``` -------------------------------- ### Loading SVG from Stream Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/svg-migration.md Demonstrates loading an SVG from a stream using the SKSvg class. The API for loading SVGs remains the same between SkiaSharp.Extended.Svg and Svg.Skia. ```csharp // Both old and new code look the same! var svg = new SKSvg(); using (var stream = GetType().Assembly.GetManifestResourceStream(resourceId)) { if (stream != null) { svg.Load(stream); } } ``` -------------------------------- ### Handle Lottie Animation Lifecycle Events Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/lottie.md Subscribe to animation lifecycle events like 'AnimationLoaded', 'AnimationFailed', and 'AnimationCompleted' to react to the animation's state changes. Note that 'AnimationCompleted' only fires for finite animations. ```csharp lottieView.AnimationLoaded += (s, e) => { Console.WriteLine($"Loaded! Duration: {lottieView.Duration}"); }; lottieView.AnimationFailed += (s, e) => { Console.WriteLine($"Failed to load animation"); }; lottieView.AnimationCompleted += (s, e) => { Console.WriteLine("Animation finished playing"); }; ``` -------------------------------- ### Accessing Deployed Raw Assets in .NET MAUI Source: https://github.com/mono/skiasharp.extended/blob/main/samples/SkiaSharpDemo/Resources/Raw/AboutAssets.txt This C# code demonstrates how to load and read the content of a raw asset file that has been deployed with your .NET MAUI application. Ensure the asset is correctly included using the MauiAsset build action. ```csharp async Task LoadMauiAsset() { using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt"); using var reader = new StreamReader(stream); var contents = reader.ReadToEnd(); } ``` -------------------------------- ### Update Using Statements Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/svg-migration.md Replace the old SkiaSharp.Extended.Svg namespace with the new Svg.Skia namespace in your C# code. ```csharp // OLD - Remove this using SkiaSharp.Extended.Svg; // NEW - Add this using Svg.Skia; ``` -------------------------------- ### Compare Images with Tolerance for Minor Differences Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/pixel-comparer.md Compares images while allowing for minor differences using a per-pixel tolerance or an RMSE threshold. Useful for tests with potential platform-specific variations. ```csharp [Fact] public void UI_MatchesBaseline_WithTolerance() { using var actual = CaptureScreenshot(); using var expected = SKImage.FromEncodedData("baselines/screen.png"); // Option 1: Use per-pixel tolerance to ignore minor differences var result = SKPixelComparer.Compare(expected, actual, tolerance: 10); Assert.Equal(0, result.ErrorPixelCount); // Option 2: Use RMSE threshold (like .NET MAUI VisualTestUtils) var result2 = SKPixelComparer.Compare(expected, actual); Assert.True(result2.NormalizedRootMeanSquaredError < 0.005, $"NRMSE too high: {result2.NormalizedRootMeanSquaredError:F4}"); } ``` -------------------------------- ### Compare Pixels with Per-Channel Tolerance Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/pixel-comparer.md Compares two images and counts pixels where any channel's difference exceeds the specified tolerance. Channels within tolerance are ignored for all metrics. ```csharp // Ignore channels where the individual difference is 10 or less var result = SKPixelComparer.Compare(expected, actual, tolerance: 10); Console.WriteLine($"Pixels exceeding tolerance: {result.ErrorPixelCount}"); ``` -------------------------------- ### Control Lottie Animation Playback Programmatically Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/lottie.md Manage the animation's playback state and progress using C# code. Set 'IsAnimationEnabled' to false to pause and true to resume. You can also jump to a specific 'Progress' point or check 'IsComplete'. ```csharp // Pause the animation lottieView.IsAnimationEnabled = false; // Resume lottieView.IsAnimationEnabled = true; // Jump to specific progress lottieView.Progress = TimeSpan.FromSeconds(1.5); // Check if complete if (lottieView.IsComplete) { // Animation finished } ``` -------------------------------- ### Compare Images for Visual Regression Testing Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/pixel-comparer.md Compares two images and asserts that there are no differing pixels. Suitable for use in test suites to catch unintended rendering changes. ```csharp [Fact] public void ChartRendering_MatchesBaseline() { using var actual = RenderChart(testData); using var expected = SKImage.FromEncodedData("baselines/chart.png"); var result = SKPixelComparer.Compare(expected, actual); Assert.Equal(0, result.ErrorPixelCount); } ``` -------------------------------- ### Mask-Based Comparison with Options Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/pixel-comparer.md Performs mask-based pixel comparison using SKPixelComparer.Compare, incorporating custom SKPixelComparerOptions. ```csharp // Mask-based with options var result = SKPixelComparer.Compare(expected, actual, mask, options); ``` -------------------------------- ### Create a Regular Polygon Path Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/geometry.md Generates an SKPath for a regular polygon. Specify the radius and the number of points (sides). ```csharp // Pentagon (5 sides) var pentagon = SKGeometry.CreateRegularPolygonPath(radius: 50, points: 5); // Hexagon (6 sides) var hexagon = SKGeometry.CreateRegularPolygonPath(radius: 50, points: 6); // Octagon (8 sides) var octagon = SKGeometry.CreateRegularPolygonPath(radius: 50, points: 8); ``` -------------------------------- ### Encode Image to BlurHash Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/blurhash.md Encodes a SKBitmap into a BlurHash string. Use 4x3 components as a good default for most images. ```csharp using SkiaSharp; using SkiaSharp.Extended; using var bitmap = SKBitmap.Decode("photo.jpg"); string hash = SKBlurHash.Serialize(bitmap, 4, 3); // Returns something like: "LjPsbRxG%gx^aJxuM|W=?^X8Mxn$" ``` -------------------------------- ### Decode BlurHash to Placeholder Bitmap Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/blurhash.md Decodes a BlurHash string into a SKBitmap. A placeholder size of 32x32 is usually sufficient. ```csharp var placeholder = SKBlurHash.DeserializeBitmap(hash, 32, 32); // Use this blurred bitmap while the real image loads ``` -------------------------------- ### Confetti Emitter Patterns Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/confetti.md Configure how particles are emitted using SKConfettiEmitter. Options include instant bursts, continuous streams, or infinite emissions with specified rates. ```csharp // Instant explosion - all particles at once Emitter = SKConfettiEmitter.Burst(100); // Continuous stream - 50 particles per second, for 3 seconds Emitter = SKConfettiEmitter.Stream(50, 3); // Infinite - 30 particles per second, forever Emitter = SKConfettiEmitter.Infinite(30); ``` -------------------------------- ### Draw Basic Shapes Using Canvas Extensions Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/geometry.md Convenient methods to draw basic shapes like squares, triangles, polygons, and stars directly onto a canvas using SkiaSharp.Extended. ```csharp using SkiaSharp; using SkiaSharp.Extended; // Square canvas.DrawSquare(cx: 50, cy: 50, side: 40, paint); // Triangle (by radius) canvas.DrawTriangle(cx: 150, cy: 50, radius: 30, paint); // Regular polygon canvas.DrawRegularPolygon(cx: 250, cy: 50, radius: 30, points: 6, paint); // Star canvas.DrawStar(cx: 350, cy: 50, outerRadius: 30, innerRadius: 12, points: 5, paint); ``` -------------------------------- ### Generate Difference Image Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/pixel-comparer.md Generates a full-color image visualizing per-channel differences between two images. Useful for understanding the magnitude and distribution of differences. ```csharp using var diff = SKPixelComparer.GenerateDifferenceImage("expected.png", "actual.png"); // Each pixel's R, G, B values represent the absolute channel differences using var data = diff.Encode(SKEncodedImageFormat.Png, 100); File.WriteAllBytes("diff-image.png", data.ToArray()); ``` -------------------------------- ### Compare Images with Tolerance Mask Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/pixel-comparer.md Compares two images using an optional tolerance mask to ignore minor differences. The mask must have the same dimensions as the images being compared. ```csharp using var expected = SKImage.FromEncodedData("expected.png"); using var actual = SKImage.FromEncodedData("actual.png"); using var mask = SKImage.FromEncodedData("tolerance-mask.png"); var result = SKPixelComparer.Compare(expected, actual, mask); ``` -------------------------------- ### Customization: Max Segment Length Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/path-interpolation.md Demonstrates creating SKPathInterpolation with different maxSegmentLength values to control curve smoothness and performance. ```csharp // Default (5 units) - good balance of quality and performance var interpolation = new SKPathInterpolation(from, to); // Smoother curves (smaller segments) var smooth = new SKPathInterpolation(from, to, maxSegmentLength: 2f); // Faster performance (larger segments) var fast = new SKPathInterpolation(from, to, maxSegmentLength: 10f); ``` -------------------------------- ### SPA Redirect Logic Source: https://github.com/mono/skiasharp.extended/blob/main/docs/404.html This JavaScript code redirects users directly navigating to a Blazor sample sub-page. It encodes the path and query string to restore the correct route in the Blazor router. ```javascript (function () { var l = window.location; var pathParts = l.pathname.split('/'); var sampleIdx = pathParts.indexOf('sample'); if (sampleIdx !== -1 && sampleIdx < pathParts.length - 1 && pathParts[sampleIdx + 1] !== '') { var basePath = pathParts.slice(0, sampleIdx + 1).join('/'); var remaining = pathParts.slice(sampleIdx + 1).join('/').replace(/&/g, '~and~'); l.replace( l.protocol + '//' + l.hostname + (l.port ? ':' + l.port : '') + basePath + '/?/' + remaining + (l.search ? '&' + l.search.slice(1).replace(/&/g, '~and~') : '') + l.hash ); } })(); ``` -------------------------------- ### Decode BlurHash with Custom Punch Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/blurhash.md Decodes a BlurHash string into a SKBitmap with adjustable contrast. A punch value greater than 1.0 increases vibrancy. ```csharp // Default punch (1.0) var normal = SKBlurHash.DeserializeBitmap(hash, 32, 32); // More vibrant (1.5) var vibrant = SKBlurHash.DeserializeBitmap(hash, 32, 32, punch: 1.5f); ``` -------------------------------- ### Compare Pixels with Summed Tolerance Mode Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/pixel-comparer.md Compares two images using summed tolerance mode, where the total difference across all RGB channels must exceed the tolerance to count as an error. This mode is configured via SKPixelComparerOptions. ```csharp // Summed: ignore pixels where the total RGB difference is 15 or less var options = new SKPixelComparerOptions { TolerancePerChannel = false }; var result = SKPixelComparer.Compare(expected, actual, tolerance: 15, options); ``` -------------------------------- ### Confetti Physics Properties Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/confetti.md Configure the physical properties of confetti particles, including their size and mass, which affects how they fall and respond to gravity. ```csharp Physics = { new SKConfettiPhysics { Size = 10, Mass = 0.5 }, // Small, light new SKConfettiPhysics { Size = 20, Mass = 1.0 }, // Medium new SKConfettiPhysics { Size = 30, Mass = 2.0 } // Large, heavy (falls faster) } ``` -------------------------------- ### Blazor URL Parameter Handling Source: https://github.com/mono/skiasharp.extended/blob/main/samples/SkiaSharpDemo.Blazor/wwwroot/index.html This JavaScript code snippet modifies the browser's history to correctly handle URL parameters, specifically replacing '~and~' with '&' for proper parsing. ```javascript (function (l) { if (l.search[1] === '/') { var decoded = l.search.slice(1).split('&').map(function (s) { return s.replace(/~and~/g, '&'); }).join('?'); window.history.replaceState(null, null, l.pathname.slice(0, -1) + decoded + l.hash); } }(window.location)); ``` -------------------------------- ### Register SkiaSharp Handler in MAUI Source: https://github.com/mono/skiasharp.extended/blob/main/docs/index.md Register the SkiaSharp handler in your .NET MAUI application's MauiProgram.cs file to enable SkiaSharp functionality. ```csharp public static MauiApp CreateMauiApp() { var builder = MauiApp.CreateBuilder(); builder .UseMauiApp() .UseSkiaSharp(); // Add this line return builder.Build(); } ``` -------------------------------- ### Calculate Geometric Properties Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/geometry.md Utility methods for geometric calculations, including finding a point on a circle and calculating polygon area. ```csharp // Get a point on a circle var point = SKGeometry.CirclePoint(radius: 100, radians: Math.PI / 4); // Calculate polygon area var points = new[] { new SKPoint(0, 0), new SKPoint(100, 0), new SKPoint(50, 100) }; var area = SKGeometry.Area(points); ``` -------------------------------- ### Compare Pixels Including Alpha Channel Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/pixel-comparer.md Compares images including the alpha channel by setting CompareAlpha to true in SKPixelComparerOptions. This affects error calculations and normalization of metrics. ```csharp var options = new SKPixelComparerOptions { CompareAlpha = true }; var result = SKPixelComparer.Compare(expected, actual, options); Console.WriteLine($"Channels compared: {result.ChannelCount}"); // 4 Console.WriteLine($"MAE: {result.MeanAbsoluteError}"); // Normalized over RGBA ``` -------------------------------- ### Control Path Direction Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/geometry.md Set the winding order (Clockwise or CounterClockwise) for generated paths. This is useful for path operations. ```csharp // Clockwise (default) var cwPath = SKGeometry.CreateSquarePath(50, SKPathDirection.Clockwise); // Counter-clockwise var ccwPath = SKGeometry.CreateSquarePath(50, SKPathDirection.CounterClockwise); ``` -------------------------------- ### GitHub Pages SPA Redirect Script Source: https://github.com/mono/skiasharp.extended/blob/main/samples/SkiaSharpDemo.Blazor/wwwroot/404.html This JavaScript code converts the URL path into a query string for index.html to enable SPA routing on GitHub Pages. It calculates the number of segments in the base href and reconstructs the URL with the path as a query parameter. ```javascript var segmentCount = 2; var l = window.location; l.replace( l.protocol + '//' + l.hostname + (l.port ? ':' + l.port : '') + l.pathname.split('/').slice(0, 1 + segmentCount).join('/') + '/?/' + l.pathname.slice(1).split('/').slice(segmentCount).join('/').replace(/&/g, '~and~') + (l.search ? '&' + l.search.slice(1).replace(/&/g, '~and~') : '') + l.hash ); ``` -------------------------------- ### Generate Difference Mask Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/pixel-comparer.md Generates a black-and-white mask image highlighting differences between two images. White pixels indicate differences, and black pixels indicate matching areas. The generated mask is saved as 'diff-mask.png'. ```csharp using var mask = SKPixelComparer.GenerateDifferenceMask("expected.png", "actual.png"); // Encode and save the mask using var data = mask.Encode(SKEncodedImageFormat.Png, 100); File.WriteAllBytes("diff-mask.png", data.ToArray()); ``` -------------------------------- ### Add SKLottieView to XAML Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/lottie.md Include the SKLottieView in your XAML markup to display an animation. Set the 'Source' property to the animation JSON file and optionally configure 'RepeatCount', 'WidthRequest', and 'HeightRequest'. ```xml ``` -------------------------------- ### MAUI Value Converter for BlurHash Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/blurhash.md A custom IValueConverter for MAUI to decode BlurHash strings directly in XAML bindings. It allows setting the desired width and height for the placeholder. ```csharp using System.Globalization; using SkiaSharp; using SkiaSharp.Extended; using SkiaSharp.Views.Maui.Controls; public class BlurHashConverter : IValueConverter { public int Width { get; set; } = 32; public int Height { get; set; } = 32; public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) { if (value is string hash && !string.IsNullOrEmpty(hash)) { var bitmap = SKBlurHash.DeserializeBitmap(hash, Width, Height); return (SKBitmapImageSource)bitmap; } return null; } public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) => throw new NotImplementedException(); } ``` -------------------------------- ### Generate Difference Mask on Comparison Failure Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/pixel-comparer.md Generates and saves a difference mask when an image comparison fails. This mask aids in diagnosing the specific changes that occurred. ```csharp if (result.ErrorPixelCount > 0) { using var diffMask = SKPixelComparer.GenerateDifferenceMask(expected, actual); using var encoded = diffMask.Encode(SKEncodedImageFormat.Png, 100); File.WriteAllBytes("test-output/diff-mask.png", encoded.ToArray()); } ``` -------------------------------- ### Confetti Particle Lifecycle Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/confetti.md Manage the lifespan of confetti particles and enable fading effects before they disappear. The `IsComplete` property indicates when all particles have finished their lifecycle. ```csharp var system = new SKConfettiSystem { Lifetime = 3.0, // Particles live for 3 seconds FadeOut = true // Gradually fade before disappearing }; // Handle completion confettiView.IsComplete // true when all particles are gone ``` -------------------------------- ### Configure Lottie Animation Repeat Modes Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/lottie.md Control how the Lottie animation repeats using the 'RepeatCount' and 'RepeatMode' properties in XAML. 'RepeatCount' defines the number of plays (0 for once, -1 for infinite), and 'RepeatMode' can be 'Restart' or 'Reverse' for ping-pong effect. ```xml ``` -------------------------------- ### Confetti Motion Control - Velocity and Spin Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/confetti.md Control the initial speed, speed limit, and rotation of confetti particles. This allows for dynamic launch effects and spin animations. ```csharp var system = new SKConfettiSystem { // Initial launch speed range MinimumInitialVelocity = 100, MaximumInitialVelocity = 300, // Speed limit MaximumVelocity = 500, // Spin rate MinimumRotationVelocity = -90, MaximumRotationVelocity = 90 }; ``` -------------------------------- ### Add SKConfettiView to XAML Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/confetti.md Include the SKConfettiView control in your XAML markup to display confetti effects. Ensure the SkiaSharp.Extended.UI.Maui namespace is correctly imported. ```xml ``` -------------------------------- ### Draw Shapes Directly on Canvas Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/geometry.md Utilizes canvas extension methods to draw various shapes without explicitly creating SKPath objects. Requires SkiaSharp.Extended. ```csharp using SkiaSharp; using SkiaSharp.Extended; // Draw shapes directly on a canvas canvas.DrawStar(100, 100, outerRadius: 50, innerRadius: 20, points: 5, paint); canvas.DrawRegularPolygon(200, 100, radius: 40, points: 6, paint); canvas.DrawTriangle(300, 100, radius: 40, paint); ``` -------------------------------- ### Generate Mask with Summed Tolerance Mode Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/pixel-comparer.md Generates a difference mask using summed tolerance mode, where the sum of channel differences is compared against the tolerance. Pixels are either fully counted as errors or fully excluded. ```csharp // Mask with sum-based semantics var options = new SKPixelComparerOptions { TolerancePerChannel = false }; var result = SKPixelComparer.Compare(expected, actual, mask, options); ``` -------------------------------- ### Drawing SVG on Canvas Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/svg-migration.md Illustrates how to draw an SVG picture onto a SkiaSharp canvas. This code snippet shows the calculation for scaling the SVG to fit the canvas dimensions. ```csharp // Drawing the SVG picture if (svg?.Picture != null) { canvas.Clear(SKColors.White); // Calculate scaling to fit canvas var canvasMin = Math.Min(width, height); var svgMax = Math.Max(svg.Picture.CullRect.Width, svg.Picture.CullRect.Height); var scale = canvasMin / svgMax; var matrix = SKMatrix.CreateScale(scale, scale); canvas.DrawPicture(svg.Picture, matrix); } ``` -------------------------------- ### Custom Confetti Shapes Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/confetti.md Define the shapes of confetti particles using built-in shapes like circles and squares, or create custom shapes using paths or a custom SKConfettiShape implementation. ```csharp Shapes = { new SKConfettiCircleShape(), new SKConfettiSquareShape(), new SKConfettiOvalShape { HeightRatio = 0.5 }, new SKConfettiRectShape { HeightRatio = 0.3 } } ``` ```csharp Shapes = { new SKConfettiPathShape(SKGeometry.CreateRegularStarPath(20, 10, 5)) } ``` ```csharp public class HeartShape : SKConfettiShape { protected override void OnDraw(SKCanvas canvas, SKPaint paint, float size) { using var path = new SKPath(); // Draw heart shape... canvas.DrawPath(path, paint); } } ``` -------------------------------- ### Customize SKLottieView Control Template Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/lottie.md Override the control template of SKLottieView to customize the rendering surface. You can use either SKCanvasView (software rendering) or SKGLView (GPU-accelerated rendering) by naming the drawing surface PART_DrawingSurface. ```xml ``` -------------------------------- ### Confetti Motion Control - Launch Direction Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/confetti.md Specify the angle range for particle emission to control the direction and spread of the confetti. This is useful for creating focused or dispersed effects. ```csharp // Full 360° explosion (default) StartAngle = 0; EndAngle = 360; // Upward cone from top emitter EmitterBounds = SKConfettiEmitterBounds.Top; StartAngle = 45; EndAngle = 135; ``` -------------------------------- ### Custom Confetti Colors Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/confetti.md Customize the color palette for confetti particles by providing a list of SKColor objects. This can be done in C# code or directly in XAML. ```csharp // Custom color palette var system = new SKConfettiSystem { Colors = { Colors.Red, Colors.Gold, Colors.Blue, Colors.Green } }; ``` ```xml ``` -------------------------------- ### Confetti Emitter Bounds Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/confetti.md Define the area from which particles are emitted using SKConfettiEmitterBounds. This controls the origin of the confetti, such as the center, top, or a specific point. ```csharp // From the center of the view EmitterBounds = SKConfettiEmitterBounds.Center; // From the top edge (falling down) EmitterBounds = SKConfettiEmitterBounds.Top; // From a specific point EmitterBounds = SKConfettiEmitterBounds.Point(100, 200); // From both sides confettiView.Systems.Add(new SKConfettiSystem { EmitterBounds = SKConfettiEmitterBounds.Left }); confettiView.Systems.Add(new SKConfettiSystem { EmitterBounds = SKConfettiEmitterBounds.Right }); ``` -------------------------------- ### Confetti Motion Control - Gravity Source: https://github.com/mono/skiasharp.extended/blob/main/docs/docs/confetti.md Adjust the gravity vector to simulate different environmental effects, such as standard downward gravity, upward drift, or wind effects. ```csharp // Standard gravity (particles fall down) Gravity = new Point(0, 100); // Upward drift Gravity = new Point(0, -50); // Diagonal wind effect Gravity = new Point(50, 100); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.