├── docs ├── README.md ├── images │ ├── logo.ico │ ├── logo.png │ ├── extended │ │ ├── skblurhash │ │ │ ├── blur.png │ │ │ ├── logo.png │ │ │ ├── blur-small.png │ │ │ └── images.json │ │ └── skpathinterpolation │ │ │ └── interpolation.gif │ └── ui │ │ └── controls │ │ ├── sklottieview │ │ └── lottie.gif │ │ └── skconfettiview │ │ ├── sides-spray.gif │ │ ├── top-stream.gif │ │ └── center-burst.gif ├── .gitignore ├── toc.yml ├── docs │ ├── toc.yml │ ├── skblurhash.md │ ├── skpathinterpolation.md │ ├── skgeometry.md │ └── sklottieview.md ├── docfx.json └── index.md ├── images ├── logo.png ├── PathInterpolation.gif ├── extended │ └── skblurhash │ │ ├── blur.png │ │ ├── logo.png │ │ └── images.json └── controls │ └── skconfettiview │ ├── center-burst.gif │ ├── sides-spray.gif │ └── top-stream.gif ├── source ├── SkiaSharp.Extended.UI.Maui │ ├── README.md │ ├── Controls │ │ ├── Lottie │ │ │ ├── SKLottieRepeatMode.shared.cs │ │ │ ├── SKLottieViewResources.shared.xaml.cs │ │ │ ├── SKLottieAnimationFailedEventArgs.shared.cs │ │ │ ├── SKLottieAnimation.shared.cs │ │ │ ├── SKLottieAnimationLoadedEventArgs.shared.cs │ │ │ ├── SKLottieImageSourceConverter.shared.cs │ │ │ ├── SKLottieViewResources.shared.xaml │ │ │ ├── SKStreamLottieImageSource.shared.cs │ │ │ ├── SKUriLottieImageSource.shared.cs │ │ │ ├── SKLottieImageSource.shared.cs │ │ │ └── SKFileLottieImageSource.shared.cs │ │ ├── Confetti │ │ │ ├── SKConfettiEmitterSide.shared.cs │ │ │ ├── SKConfettiViewResources.shared.xaml.cs │ │ │ ├── SKConfettiPhysics.shared.cs │ │ │ ├── SKConfettiShapeCollection.shared.cs │ │ │ ├── SKConfettiPhysicsCollection.shared.cs │ │ │ ├── SKConfettiColorCollection.shared.cs │ │ │ ├── SKConfettiSystemCollection.shared.cs │ │ │ ├── SKConfettiPhysicsTypeConverter.shared.cs │ │ │ ├── SKConfettiColorCollectionTypeConverter.shared.cs │ │ │ ├── SKConfettiViewResources.shared.xaml │ │ │ ├── SKConfettiEmitterBoundsTypeConverter.shared.cs │ │ │ ├── SKConfettiEmitterBounds.shared.cs │ │ │ ├── SKConfettiParticle.shared.cs │ │ │ └── SKConfettiEmitter.shared.cs │ │ ├── SKSurfaceViewResources.shared.xaml.cs │ │ ├── StringTypeConverter.shared.cs │ │ ├── SKSurfaceViewResources.shared.xaml │ │ ├── SKAnimatedSurfaceView.shared.cs │ │ └── SKSurfaceView.shared.cs │ ├── Utils │ │ ├── PlatformExtensions.shared.cs │ │ ├── SKObjectPool.shared.cs │ │ ├── DebugUtils.shared.cs │ │ ├── ResourceLoader.shared.cs │ │ └── SKFrameCounter.shared.cs │ └── SkiaSharp.Extended.UI.Maui.csproj ├── SkiaSharp.Extended │ ├── README.md │ ├── Comparer │ │ └── SKPixelComparisonResult.cs │ ├── SkiaSharp.Extended.csproj │ ├── BlurHash │ │ ├── SKBlurHashUtils.cs │ │ └── SKBlurHash.cs │ ├── Utils │ │ └── Base83.cs │ └── Geometry │ │ └── SKGeometryExtensions.cs ├── SignList.xml └── Directory.Build.props ├── tests ├── SkiaSharp.Extended.Tests │ ├── xunit.runner.json │ ├── images │ │ ├── BlurHash │ │ │ ├── img1.jpg │ │ │ ├── img2.jpg │ │ │ ├── img3.jpg │ │ │ ├── img4.jpg │ │ │ ├── img5.jpg │ │ │ ├── img6.png │ │ │ └── img7.png │ │ └── Comparer │ │ │ ├── First.jpg │ │ │ ├── First.png │ │ │ ├── Second.jpg │ │ │ ├── Second.png │ │ │ ├── MaskJpg.png │ │ │ └── MaskPng.png │ ├── SkiaSharp.Extended.Tests.csproj │ ├── BlurHash │ │ ├── SKBlurHashTest.cs │ │ ├── SKBlurHashDeserializeTest.cs │ │ └── SKBlurHashSerializerTest.cs │ ├── Utils │ │ └── Base83Test.cs │ └── Geometry │ │ └── SKGeometryTest.cs └── SkiaSharp.Extended.UI.Maui.Tests │ ├── xunit.runner.json │ ├── TestAssets │ └── Images │ │ └── logo.png │ ├── Controls │ ├── Confetti │ │ ├── SKConfettiPhysicsTest.cs │ │ ├── SKConfettiSystemTest.cs │ │ ├── SKConfettiPhysicsTypeConverterTest.cs │ │ ├── SKConfettiColorCollectionTypeConverterTest.cs │ │ ├── SKConfettiEmitterBoundsTypeConverterTest.cs │ │ ├── SKConfettiShapeTest.cs │ │ └── SKConfettiEmitterTest.cs │ ├── Lottie │ │ ├── WaitingLottieView.cs │ │ ├── SKFileLottieImageSourceTest.cs │ │ ├── SKUriLottieImageSourceTest.cs │ │ ├── SKLottieViewExtensions.cs │ │ ├── SKStreamLottieImageSourceTest.cs │ │ ├── SKLottieImageSourceConverterTest.cs │ │ └── SKLottieImageSourceTest.cs │ ├── SKAnimatedSurfaceViewTest.cs │ └── DispatchingBaseTest.cs │ └── SkiaSharp.Extended.UI.Maui.Tests.csproj ├── samples └── SkiaSharpDemo │ ├── Resources │ ├── Fonts │ │ ├── fa-solid-900.ttf │ │ ├── OpenSans-Regular.ttf │ │ └── OpenSans-Semibold.ttf │ ├── Raw │ │ ├── BlurHash │ │ │ ├── img1.jpg │ │ │ ├── img2.jpg │ │ │ ├── img3.jpg │ │ │ ├── img4.jpg │ │ │ ├── img5.jpg │ │ │ ├── img6.png │ │ │ ├── img7.png │ │ │ └── logo.png │ │ ├── AboutAssets.txt │ │ └── SVG │ │ │ └── dashes.svg │ ├── AppIcon │ │ ├── appicon.svg │ │ └── appiconfg.svg │ ├── Splash │ │ └── splash.svg │ └── Styles │ │ └── Colors.xaml │ ├── Properties │ └── launchSettings.json │ ├── AppShell.xaml.cs │ ├── Models │ ├── DemoGroup.cs │ ├── Demo.cs │ └── ExtendedDemos.cs │ ├── Demos │ ├── PlaygroundPage.xaml.cs │ ├── PlaygroundPage.xaml │ ├── Confetti │ │ ├── ConfettiStar.cs │ │ ├── ConfettiPage.xaml.cs │ │ └── ConfettiConfig.cs │ ├── Extended │ │ ├── ShapesPage.xaml │ │ ├── InterpolationPage.xaml │ │ └── ShapesPage.xaml.cs │ ├── Text │ │ ├── RichTextKitPage.xaml │ │ └── RichTextKitPage.xaml.cs │ ├── Svg │ │ ├── SvgPage.xaml │ │ └── SvgPage.xaml.cs │ ├── Lottie │ │ ├── LottiePage.xaml.cs │ │ └── LottiePage.xaml │ └── BlurHash │ │ └── BlurHashPage.xaml │ ├── Views │ ├── BottomTab │ │ ├── BottomTabBarResources.xaml.cs │ │ ├── BottomTab.cs │ │ └── BottomTabCollection.cs │ ├── OptionButtons │ │ ├── OptionButtonsResources.xaml.cs │ │ ├── OptionButtonsResources.xaml │ │ └── OptionButtons.cs │ └── TapLabel.cs │ ├── Platforms │ ├── Android │ │ ├── Resources │ │ │ └── values │ │ │ │ └── colors.xml │ │ ├── MainApplication.cs │ │ ├── AndroidManifest.xml │ │ └── MainActivity.cs │ ├── iOS │ │ ├── AppDelegate.cs │ │ ├── Program.cs │ │ └── Info.plist │ ├── MacCatalyst │ │ ├── AppDelegate.cs │ │ ├── Program.cs │ │ └── Info.plist │ └── Windows │ │ ├── App.xaml │ │ ├── app.manifest │ │ ├── App.xaml.cs │ │ └── Package.appxmanifest │ ├── App.xaml.cs │ ├── AppShell.xaml │ ├── MainPage.xaml.cs │ ├── Converters │ ├── RoundToIntConverter.cs │ ├── RoundToConverter.cs │ └── TimeSpanToDoubleConverter.cs │ ├── MauiProgram.cs │ ├── App.xaml │ ├── MainPage.xaml │ └── SkiaSharpDemo.csproj ├── nuget.config ├── CODE-OF-CONDUCT.md ├── scripts ├── SkiaSharp.Extended-Pack.slnf ├── azure-pipelines-variables.yml ├── SkiaSharp.Extended-Test.slnf └── azure-pipelines-steps-prepare.yml ├── .config ├── tsaoptions.json └── dotnet-tools.json ├── .github ├── dependabot.yml ├── ISSUE_TEMPLATE │ ├── feature_request.md │ ├── new_api_spec.md │ ├── question.md │ └── bug-report.md ├── workflows │ ├── rebase.yml │ └── builds-docs.yml ├── PULL_REQUEST_TEMPLATE.md └── SECURITY.md ├── LICENSE ├── README.md └── azure-pipelines-public.yml /docs/README.md: -------------------------------------------------------------------------------- 1 | View the docs online at https://mono.github.io/SkiaSharp.Extended 2 | -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/images/logo.png -------------------------------------------------------------------------------- /docs/images/logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/docs/images/logo.ico -------------------------------------------------------------------------------- /docs/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/docs/images/logo.png -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/README.md: -------------------------------------------------------------------------------- 1 | This package adds additional SkiaSharp controls to .NET MAUI. 2 | -------------------------------------------------------------------------------- /images/PathInterpolation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/images/PathInterpolation.gif -------------------------------------------------------------------------------- /source/SkiaSharp.Extended/README.md: -------------------------------------------------------------------------------- 1 | This package adds many additional features and utilities for use with SkiaSharp. 2 | -------------------------------------------------------------------------------- /images/extended/skblurhash/blur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/images/extended/skblurhash/blur.png -------------------------------------------------------------------------------- /images/extended/skblurhash/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/images/extended/skblurhash/logo.png -------------------------------------------------------------------------------- /docs/images/extended/skblurhash/blur.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/docs/images/extended/skblurhash/blur.png -------------------------------------------------------------------------------- /docs/images/extended/skblurhash/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/docs/images/extended/skblurhash/logo.png -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.Tests/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /docs/images/extended/skblurhash/blur-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/docs/images/extended/skblurhash/blur-small.png -------------------------------------------------------------------------------- /docs/images/ui/controls/sklottieview/lottie.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/docs/images/ui/controls/sklottieview/lottie.gif -------------------------------------------------------------------------------- /images/controls/skconfettiview/center-burst.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/images/controls/skconfettiview/center-burst.gif -------------------------------------------------------------------------------- /images/controls/skconfettiview/sides-spray.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/images/controls/skconfettiview/sides-spray.gif -------------------------------------------------------------------------------- /images/controls/skconfettiview/top-stream.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/images/controls/skconfettiview/top-stream.gif -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.UI.Maui.Tests/xunit.runner.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json" 3 | } 4 | -------------------------------------------------------------------------------- /docs/images/ui/controls/skconfettiview/sides-spray.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/docs/images/ui/controls/skconfettiview/sides-spray.gif -------------------------------------------------------------------------------- /docs/images/ui/controls/skconfettiview/top-stream.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/docs/images/ui/controls/skconfettiview/top-stream.gif -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Resources/Fonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/samples/SkiaSharpDemo/Resources/Fonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Resources/Raw/BlurHash/img1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/samples/SkiaSharpDemo/Resources/Raw/BlurHash/img1.jpg -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Resources/Raw/BlurHash/img2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/samples/SkiaSharpDemo/Resources/Raw/BlurHash/img2.jpg -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Resources/Raw/BlurHash/img3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/samples/SkiaSharpDemo/Resources/Raw/BlurHash/img3.jpg -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Resources/Raw/BlurHash/img4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/samples/SkiaSharpDemo/Resources/Raw/BlurHash/img4.jpg -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Resources/Raw/BlurHash/img5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/samples/SkiaSharpDemo/Resources/Raw/BlurHash/img5.jpg -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Resources/Raw/BlurHash/img6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/samples/SkiaSharpDemo/Resources/Raw/BlurHash/img6.png -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Resources/Raw/BlurHash/img7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/samples/SkiaSharpDemo/Resources/Raw/BlurHash/img7.png -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Resources/Raw/BlurHash/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/samples/SkiaSharpDemo/Resources/Raw/BlurHash/logo.png -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | ############### 2 | # folder # 3 | ############### 4 | /**/DROP/ 5 | /**/TEMP/ 6 | /**/packages/ 7 | /**/bin/ 8 | /**/obj/ 9 | _site 10 | api/ -------------------------------------------------------------------------------- /docs/images/ui/controls/skconfettiview/center-burst.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/docs/images/ui/controls/skconfettiview/center-burst.gif -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.Tests/images/BlurHash/img1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/tests/SkiaSharp.Extended.Tests/images/BlurHash/img1.jpg -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.Tests/images/BlurHash/img2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/tests/SkiaSharp.Extended.Tests/images/BlurHash/img2.jpg -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.Tests/images/BlurHash/img3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/tests/SkiaSharp.Extended.Tests/images/BlurHash/img3.jpg -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.Tests/images/BlurHash/img4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/tests/SkiaSharp.Extended.Tests/images/BlurHash/img4.jpg -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.Tests/images/BlurHash/img5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/tests/SkiaSharp.Extended.Tests/images/BlurHash/img5.jpg -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.Tests/images/BlurHash/img6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/tests/SkiaSharp.Extended.Tests/images/BlurHash/img6.png -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.Tests/images/BlurHash/img7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/tests/SkiaSharp.Extended.Tests/images/BlurHash/img7.png -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.Tests/images/Comparer/First.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/tests/SkiaSharp.Extended.Tests/images/Comparer/First.jpg -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.Tests/images/Comparer/First.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/tests/SkiaSharp.Extended.Tests/images/Comparer/First.png -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.Tests/images/Comparer/Second.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/tests/SkiaSharp.Extended.Tests/images/Comparer/Second.jpg -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.Tests/images/Comparer/Second.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/tests/SkiaSharp.Extended.Tests/images/Comparer/Second.png -------------------------------------------------------------------------------- /docs/images/extended/skpathinterpolation/interpolation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/docs/images/extended/skpathinterpolation/interpolation.gif -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Resources/Fonts/OpenSans-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/samples/SkiaSharpDemo/Resources/Fonts/OpenSans-Regular.ttf -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Resources/Fonts/OpenSans-Semibold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/samples/SkiaSharpDemo/Resources/Fonts/OpenSans-Semibold.ttf -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.Tests/images/Comparer/MaskJpg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/tests/SkiaSharp.Extended.Tests/images/Comparer/MaskJpg.png -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.Tests/images/Comparer/MaskPng.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/tests/SkiaSharp.Extended.Tests/images/Comparer/MaskPng.png -------------------------------------------------------------------------------- /docs/toc.yml: -------------------------------------------------------------------------------- 1 | items: 2 | 3 | - name: Home 4 | href: docs/ 5 | 6 | - name: API 7 | href: api/ 8 | 9 | - name: GitHub 10 | href: https://github.com/mono/SkiaSharp.Extended/ 11 | -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.UI.Maui.Tests/TestAssets/Images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mono/SkiaSharp.Extended/HEAD/tests/SkiaSharp.Extended.UI.Maui.Tests/TestAssets/Images/logo.png -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "Windows Machine": { 4 | "commandName": "MsixPackage", 5 | "nativeDebugging": false 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/Controls/Lottie/SKLottieRepeatMode.shared.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended.UI.Controls; 2 | 3 | public enum SKLottieRepeatMode 4 | { 5 | Restart, 6 | Reverse 7 | } 8 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/AppShell.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharpDemo; 2 | 3 | public partial class AppShell : Shell 4 | { 5 | public AppShell() 6 | { 7 | InitializeComponent(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Models/DemoGroup.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharpDemo; 2 | 3 | public class DemoGroup : List 4 | { 5 | public DemoGroup(string name) 6 | { 7 | Name = name; 8 | } 9 | 10 | public string Name { get; set; } 11 | } 12 | -------------------------------------------------------------------------------- /images/extended/skblurhash/images.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "name": "SkiaSharp Logo", 3 | "url": "https://raw.githubusercontent.com/mono/SkiaSharp.Extended/main/images/extended/skblurhash/logo.png", 4 | "blurhash": "UjPsYKs:%gx^VsxuM{W=?^X8Mxn$krIoxaoI", 5 | }] 6 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/Utils/PlatformExtensions.shared.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended.UI; 2 | 3 | internal static class PlatformExtensions 4 | { 5 | internal static bool IsLoadedEx(this VisualElement element) => 6 | element.IsLoaded; 7 | } 8 | -------------------------------------------------------------------------------- /docs/images/extended/skblurhash/images.json: -------------------------------------------------------------------------------- 1 | [{ 2 | "name": "SkiaSharp Logo", 3 | "url": "https://raw.githubusercontent.com/mono/SkiaSharp.Extended/main/images/extended/skblurhash/logo.png", 4 | "blurhash": "UjPsYKs:%gx^VsxuM{W=?^X8Mxn$krIoxaoI", 5 | }] 6 | -------------------------------------------------------------------------------- /source/SignList.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Demos/PlaygroundPage.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharpDemo.Demos; 2 | 3 | public partial class PlaygroundPage : ContentPage 4 | { 5 | public PlaygroundPage() 6 | { 7 | InitializeComponent(); 8 | 9 | BindingContext = this; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Views/BottomTab/BottomTabBarResources.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharpDemo.Views; 2 | 3 | public partial class BottomTabBarResources : ResourceDictionary 4 | { 5 | public BottomTabBarResources() 6 | { 7 | InitializeComponent(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Views/OptionButtons/OptionButtonsResources.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharpDemo.Views; 2 | 3 | public partial class OptionButtonsResources : ResourceDictionary 4 | { 5 | public OptionButtonsResources() 6 | { 7 | InitializeComponent(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/Controls/Confetti/SKConfettiEmitterSide.shared.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended.UI.Controls; 2 | 3 | public enum SKConfettiEmitterSide 4 | { 5 | Top, 6 | Left, 7 | Right, 8 | Bottom, 9 | 10 | Center, 11 | 12 | Bounds, 13 | } 14 | -------------------------------------------------------------------------------- /nuget.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Resources/AppIcon/appicon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Platforms/Android/Resources/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #512BD4 4 | #2B0B98 5 | #2B0B98 6 | -------------------------------------------------------------------------------- /CODE-OF-CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | This project has adopted the code of conduct defined by the Contributor Covenant 4 | to clarify expected behavior in our community. 5 | 6 | For more information, see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct). 7 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Platforms/iOS/AppDelegate.cs: -------------------------------------------------------------------------------- 1 | using Foundation; 2 | 3 | namespace SkiaSharpDemo; 4 | 5 | [Register("AppDelegate")] 6 | public class AppDelegate : MauiUIApplicationDelegate 7 | { 8 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 9 | } 10 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Platforms/MacCatalyst/AppDelegate.cs: -------------------------------------------------------------------------------- 1 | using Foundation; 2 | 3 | namespace SkiaSharpDemo; 4 | 5 | [Register("AppDelegate")] 6 | public class AppDelegate : MauiUIApplicationDelegate 7 | { 8 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 9 | } 10 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/Controls/Lottie/SKLottieViewResources.shared.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended.UI.Controls.Themes; 2 | 3 | public partial class SKLottieViewResources : ResourceDictionary 4 | { 5 | public SKLottieViewResources() 6 | { 7 | InitializeComponent(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/Controls/SKSurfaceViewResources.shared.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended.UI.Controls.Themes; 2 | 3 | public partial class SKSurfaceViewResources : ResourceDictionary 4 | { 5 | public SKSurfaceViewResources() 6 | { 7 | InitializeComponent(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /scripts/SkiaSharp.Extended-Pack.slnf: -------------------------------------------------------------------------------- 1 | { 2 | "solution": { 3 | "path": "..\\SkiaSharp.Extended.sln", 4 | "projects": [ 5 | "source\\SkiaSharp.Extended.UI.Maui\\SkiaSharp.Extended.UI.Maui.csproj", 6 | "source\\SkiaSharp.Extended\\SkiaSharp.Extended.csproj", 7 | ] 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/Controls/Confetti/SKConfettiViewResources.shared.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended.UI.Controls.Themes; 2 | 3 | public partial class SKConfettiViewResources : ResourceDictionary 4 | { 5 | public SKConfettiViewResources() 6 | { 7 | InitializeComponent(); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Models/Demo.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | 3 | namespace SkiaSharpDemo; 4 | 5 | public class Demo 6 | { 7 | public string Title { get; set; } 8 | 9 | public string Description { get; set; } 10 | 11 | public SKPath ImagePath { get; set; } 12 | 13 | public Color Color { get; set; } 14 | 15 | public Type PageType { get; set; } 16 | } 17 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Platforms/Windows/App.xaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.config/tsaoptions.json: -------------------------------------------------------------------------------- 1 | { 2 | "codebaseName": "skiasharp.extended_main", 3 | "notificationAliases": [ 4 | "dotnet-maui-eng@microsoft.com" 5 | ], 6 | "instanceUrl": "https://devdiv.visualstudio.com/", 7 | "projectName": "DevDiv", 8 | "areaPath": "DevDiv\\.NET MAUI\\SkiaSharp", 9 | "iterationPath": "DevDiv", 10 | "allTools": true 11 | } 12 | -------------------------------------------------------------------------------- /scripts/azure-pipelines-variables.yml: -------------------------------------------------------------------------------- 1 | variables: 2 | MAJOR_VERSION: 3 3 | BASE_VERSION: 3.1.0 4 | PREVIEW_LABEL: 'preview' 5 | BUILD_NUMBER: $[counter(format('{0}_{1}_{2}', variables['BASE_VERSION'], variables['Build.SourceBranch'], variables['PREVIEW_LABEL']), 1)] 6 | GIT_SHA: $(Build.SourceVersion) 7 | GIT_BRANCH_NAME: $(Build.SourceBranchName) 8 | TeamName: .NET MAUI 9 | -------------------------------------------------------------------------------- /.config/dotnet-tools.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 1, 3 | "isRoot": true, 4 | "tools": { 5 | "cake.tool": { 6 | "version": "5.0.0", 7 | "commands": [ 8 | "dotnet-cake" 9 | ], 10 | "rollForward": false 11 | }, 12 | "docfx": { 13 | "version": "2.74.1", 14 | "commands": [ 15 | "docfx" 16 | ], 17 | "rollForward": false 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.UI.Maui.Tests/Controls/Confetti/SKConfettiPhysicsTest.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace SkiaSharp.Extended.UI.Controls.Tests 4 | { 5 | public class SKConfettiPhysicsTest 6 | { 7 | [Fact] 8 | public void CanCreateInstance() 9 | { 10 | var physics = new SKConfettiPhysics(2, 4); 11 | 12 | Assert.Equal(2, physics.Size); 13 | Assert.Equal(4, physics.Mass); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /docs/docs/toc.yml: -------------------------------------------------------------------------------- 1 | items: 2 | 3 | - name: Overview 4 | href: ../index.md 5 | 6 | - name: SkiaSharp.Extended 7 | - name: SKBlurHash 8 | href: skblurhash.md 9 | - name: SKGeometry 10 | href: skgeometry.md 11 | - name: SKPathInterpolation 12 | href: skpathinterpolation.md 13 | 14 | - name: SkiaSharp.Extended.UI.Maui 15 | - name: SKConfettiView 16 | href: skconfettiview.md 17 | - name: SKLottieView 18 | href: sklottieview.md -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Platforms/Android/MainApplication.cs: -------------------------------------------------------------------------------- 1 | using Android.App; 2 | using Android.Runtime; 3 | 4 | namespace SkiaSharpDemo; 5 | 6 | [Application] 7 | public class MainApplication : MauiApplication 8 | { 9 | public MainApplication(IntPtr handle, JniHandleOwnership ownership) 10 | : base(handle, ownership) 11 | { 12 | } 13 | 14 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 15 | } 16 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/Controls/Confetti/SKConfettiPhysics.shared.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended.UI.Controls; 2 | 3 | [TypeConverter(typeof(Converters.SKConfettiPhysicsTypeConverter))] 4 | public readonly struct SKConfettiPhysics 5 | { 6 | public SKConfettiPhysics(double size, double mass) 7 | { 8 | Size = size; 9 | Mass = mass; 10 | } 11 | 12 | public double Size { get; } 13 | 14 | public double Mass { get; } 15 | } 16 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/Controls/Lottie/SKLottieAnimationFailedEventArgs.shared.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended.UI.Controls; 2 | 3 | public class SKLottieAnimationFailedEventArgs : EventArgs 4 | { 5 | public SKLottieAnimationFailedEventArgs() 6 | { 7 | } 8 | 9 | public SKLottieAnimationFailedEventArgs(Exception? exception) 10 | { 11 | Exception = exception; 12 | } 13 | 14 | public Exception? Exception { get; } 15 | } 16 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/Controls/Lottie/SKLottieAnimation.shared.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended.UI.Controls; 2 | 3 | public class SKLottieAnimation 4 | { 5 | public SKLottieAnimation() 6 | { 7 | } 8 | 9 | public SKLottieAnimation(Skottie.Animation? animation) 10 | { 11 | Animation = animation; 12 | } 13 | 14 | public Skottie.Animation? Animation { get; } 15 | 16 | public bool IsLoaded => Animation is not null; 17 | } 18 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Platforms/iOS/Program.cs: -------------------------------------------------------------------------------- 1 | using ObjCRuntime; 2 | using UIKit; 3 | 4 | namespace SkiaSharpDemo; 5 | 6 | public class Program 7 | { 8 | // This is the main entry point of the application. 9 | static void Main(string[] args) 10 | { 11 | // if you want to use a different Application Delegate class from "AppDelegate" 12 | // you can specify it here. 13 | UIApplication.Main(args, null, typeof(AppDelegate)); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Views/BottomTab/BottomTab.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharpDemo.Views; 2 | 3 | public class BottomTab : ContentView 4 | { 5 | public static readonly BindableProperty TitleProperty = BindableProperty.Create( 6 | nameof(Title), 7 | typeof(string), 8 | typeof(BottomTab), 9 | null); 10 | 11 | public string? Title 12 | { 13 | get => (string?)GetValue(TitleProperty); 14 | set => SetValue(TitleProperty, value); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Platforms/MacCatalyst/Program.cs: -------------------------------------------------------------------------------- 1 | using ObjCRuntime; 2 | using UIKit; 3 | 4 | namespace SkiaSharpDemo; 5 | 6 | public class Program 7 | { 8 | // This is the main entry point of the application. 9 | static void Main(string[] args) 10 | { 11 | // if you want to use a different Application Delegate class from "AppDelegate" 12 | // you can specify it here. 13 | UIApplication.Main(args, null, typeof(AppDelegate)); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Demos/PlaygroundPage.xaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | -------------------------------------------------------------------------------- /scripts/SkiaSharp.Extended-Test.slnf: -------------------------------------------------------------------------------- 1 | { 2 | "solution": { 3 | "path": "..\\SkiaSharp.Extended.sln", 4 | "projects": [ 5 | "source\\SkiaSharp.Extended.UI.Maui\\SkiaSharp.Extended.UI.Maui.csproj", 6 | "source\\SkiaSharp.Extended\\SkiaSharp.Extended.csproj", 7 | "tests\\SkiaSharp.Extended.Tests\\SkiaSharp.Extended.Tests.csproj", 8 | "tests\\SkiaSharp.Extended.UI.Maui.Tests\\SkiaSharp.Extended.UI.Maui.Tests.csproj", 9 | ] 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Platforms/Android/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.UI.Maui.Tests/Controls/Lottie/WaitingLottieView.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended.UI.Controls.Tests; 2 | 3 | class WaitingLottieView : SKLottieView 4 | { 5 | public WaitingLottieView() 6 | { 7 | ResetTask(); 8 | } 9 | 10 | public Task LoadedTask { get; private set; } = null!; 11 | 12 | public void ResetTask() => 13 | LoadedTask = this.WaitForAnimation(); 14 | 15 | public void CallUpdate(TimeSpan deltaTime) => 16 | Update(deltaTime); 17 | } 18 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharpDemo.Views; 2 | 3 | namespace SkiaSharpDemo; 4 | 5 | public partial class App : Application 6 | { 7 | public App() 8 | { 9 | InitializeComponent(); 10 | 11 | Resources.MergedDictionaries.Add(new OptionButtonsResources()); 12 | Resources.MergedDictionaries.Add(new BottomTabBarResources()); 13 | } 14 | 15 | protected override Window CreateWindow(IActivationState? activationState) => 16 | new Window(new AppShell()); 17 | } 18 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Views/BottomTab/BottomTabCollection.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | 3 | namespace SkiaSharpDemo.Views; 4 | 5 | public class BottomTabCollection : ObservableCollection 6 | { 7 | public BottomTabCollection() 8 | { 9 | } 10 | 11 | public BottomTabCollection(IEnumerable collection) 12 | : base(collection) 13 | { 14 | } 15 | 16 | public BottomTabCollection(List list) 17 | : base(list) 18 | { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Platforms/Android/MainActivity.cs: -------------------------------------------------------------------------------- 1 | using Android.App; 2 | using Android.Content.PM; 3 | using Android.OS; 4 | 5 | namespace SkiaSharpDemo; 6 | 7 | [Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)] 8 | public class MainActivity : MauiAppCompatActivity 9 | { 10 | } 11 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/Controls/Confetti/SKConfettiShapeCollection.shared.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended.UI.Controls; 2 | 3 | public class SKConfettiShapeCollection : List 4 | { 5 | public SKConfettiShapeCollection() 6 | { 7 | } 8 | 9 | public SKConfettiShapeCollection(IEnumerable collection) 10 | : base(collection) 11 | { 12 | } 13 | 14 | public SKConfettiShapeCollection(int capacity) 15 | : base(capacity) 16 | { 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/Controls/Confetti/SKConfettiPhysicsCollection.shared.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended.UI.Controls; 2 | 3 | public class SKConfettiPhysicsCollection : List 4 | { 5 | public SKConfettiPhysicsCollection() 6 | { 7 | } 8 | 9 | public SKConfettiPhysicsCollection(IEnumerable collection) 10 | : base(collection) 11 | { 12 | } 13 | 14 | public SKConfettiPhysicsCollection(int capacity) 15 | : base(capacity) 16 | { 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/Controls/Confetti/SKConfettiColorCollection.shared.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended.UI.Controls; 2 | 3 | [TypeConverter(typeof(Converters.SKConfettiColorCollectionTypeConverter))] 4 | public class SKConfettiColorCollection : List 5 | { 6 | public SKConfettiColorCollection() 7 | { 8 | } 9 | 10 | public SKConfettiColorCollection(IEnumerable collection) 11 | : base(collection) 12 | { 13 | } 14 | 15 | public SKConfettiColorCollection(int capacity) 16 | : base(capacity) 17 | { 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/Controls/Confetti/SKConfettiSystemCollection.shared.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.ObjectModel; 2 | 3 | namespace SkiaSharp.Extended.UI.Controls; 4 | 5 | public class SKConfettiSystemCollection : ObservableCollection 6 | { 7 | public SKConfettiSystemCollection() 8 | { 9 | } 10 | 11 | public SKConfettiSystemCollection(IEnumerable collection) 12 | : base(collection) 13 | { 14 | } 15 | 16 | public SKConfettiSystemCollection(List list) 17 | : base(list) 18 | { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /docs/docs/skblurhash.md: -------------------------------------------------------------------------------- 1 | # SKBlurHash 2 | 3 | A **BlurHash** is a compact representation of a placeholder for an image. 4 | 5 | For example, the SkiaSharp logo can be reduced to a tiny string: 6 | 7 | ```text 8 | LjPsbRxG%gx^aJxuM|W=?^X8Mxn$ 9 | ``` 10 | 11 | | Original (79.7 KB) | BlurHash (36 bytes) | 12 | | :-------------------: | :-------------------: | 13 | | ![Original][orig-img] | ![BlurHash][blur-img] | 14 | 15 | 16 | ## Methods 17 | 18 | TODO 19 | 20 | [orig-img]: ../images/extended/skblurhash/logo.png 21 | [blur-img]: ../images/extended/skblurhash/blur.png 22 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/Controls/Confetti/SKConfettiPhysicsTypeConverter.shared.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended.UI.Controls.Converters; 2 | 3 | public class SKConfettiPhysicsTypeConverter : StringTypeConverter 4 | { 5 | protected override object? ConvertFromStringCore(string? value) 6 | { 7 | if (value == null) 8 | return null; 9 | 10 | value = value?.Trim(); 11 | 12 | var pointConverter = new PointTypeConverter(); 13 | var point = (Point)pointConverter.ConvertFromInvariantString(value); 14 | return new SKConfettiPhysics(point.X, point.Y); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Demos/Confetti/ConfettiStar.cs: -------------------------------------------------------------------------------- 1 | using SkiaSharp; 2 | using SkiaSharp.Extended; 3 | using SkiaSharp.Extended.UI.Controls; 4 | 5 | namespace SkiaSharpDemo.Demos; 6 | 7 | public class ConfettiStar : SKConfettiShape 8 | { 9 | public ConfettiStar(int points) 10 | { 11 | Points = points; 12 | } 13 | 14 | public int Points { get; } 15 | 16 | protected override void OnDraw(SKCanvas canvas, SKPaint paint, float size) 17 | { 18 | using var star = SKGeometry.CreateRegularStarPath(size, size / 2, Points); 19 | 20 | canvas.DrawPath(star, paint); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended/Comparer/SKPixelComparisonResult.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended 2 | { 3 | public class SKPixelComparisonResult 4 | { 5 | public SKPixelComparisonResult(int totalPixels, int errorPixelCount, int absoluteError) 6 | { 7 | TotalPixels = totalPixels; 8 | ErrorPixelCount = errorPixelCount; 9 | AbsoluteError = absoluteError; 10 | } 11 | 12 | public int TotalPixels { get; } 13 | 14 | public int ErrorPixelCount { get; } 15 | 16 | public double ErrorPixelPercentage => 17 | (double)ErrorPixelCount / TotalPixels; 18 | 19 | public int AbsoluteError { get; } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/Utils/SKObjectPool.shared.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Concurrent; 2 | 3 | namespace SkiaSharp.Extended.UI; 4 | 5 | internal class SKObjectPool 6 | { 7 | private readonly ConcurrentBag objects; 8 | private readonly Func generator; 9 | 10 | public SKObjectPool(Func objectGenerator) 11 | { 12 | generator = objectGenerator ?? throw new ArgumentNullException(nameof(objectGenerator)); 13 | objects = new ConcurrentBag(); 14 | } 15 | 16 | public T Get() => 17 | objects.TryTake(out var item) ? item : generator(); 18 | 19 | public void Return(T item) => 20 | objects.Add(item); 21 | } 22 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Demos/Extended/ShapesPage.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/AppShell.xaml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Demos/Text/RichTextKitPage.xaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.UI.Maui.Tests/Controls/Confetti/SKConfettiSystemTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace SkiaSharp.Extended.UI.Controls.Tests 5 | { 6 | public class SKConfettiSystemTest 7 | { 8 | [Fact] 9 | public void DefaultIsNotComplete() 10 | { 11 | var system = new SKConfettiSystem(); 12 | 13 | Assert.True(system.IsAnimationEnabled); 14 | Assert.False(system.IsComplete); 15 | } 16 | 17 | [Fact] 18 | public void NotEnabledIsStillNotComplete() 19 | { 20 | var system = new SKConfettiSystem(); 21 | system.IsAnimationEnabled = false; 22 | 23 | Assert.False(system.IsAnimationEnabled); 24 | Assert.False(system.IsComplete); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/MainPage.xaml.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharpDemo; 2 | 3 | public partial class MainPage : ContentPage 4 | { 5 | public MainPage() 6 | { 7 | InitializeComponent(); 8 | 9 | Demos = ExtendedDemos.GetAllDemos(); 10 | 11 | BindingContext = this; 12 | } 13 | 14 | public List Demos { get; } 15 | 16 | private void OnSelectionChanged(object sender, SelectionChangedEventArgs e) 17 | { 18 | if (e.CurrentSelection.FirstOrDefault() is Demo demo) 19 | { 20 | NavigateTo(demo); 21 | collectionView.SelectedItem = null; 22 | } 23 | } 24 | 25 | private void NavigateTo(Demo demo) 26 | { 27 | var page = Activator.CreateInstance(demo.PageType) as Page; 28 | 29 | Navigation.PushAsync(page); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Resources/Raw/AboutAssets.txt: -------------------------------------------------------------------------------- 1 | Any raw assets you want to be deployed with your application can be placed in 2 | this directory (and child directories). Deployment of the asset to your application 3 | is automatically handled by the following `MauiAsset` Build Action within your `.csproj`. 4 | 5 | 6 | 7 | These files will be deployed with you package and will be accessible using Essentials: 8 | 9 | async Task LoadMauiAsset() 10 | { 11 | using var stream = await FileSystem.OpenAppPackageFileAsync("AboutAssets.txt"); 12 | using var reader = new StreamReader(stream); 13 | 14 | var contents = reader.ReadToEnd(); 15 | } 16 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended/SkiaSharp.Extended.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0;net9.0 5 | SkiaSharp.Extended 6 | SkiaSharp.Extended 7 | 8 | 9 | 10 | 11 | SkiaSharp.Extended 12 | SkiaSharp.Extended 13 | This package adds many additional features and utilities for use with SkiaSharp. 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/Controls/Confetti/SKConfettiColorCollectionTypeConverter.shared.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended.UI.Controls.Converters; 2 | 3 | public class SKConfettiColorCollectionTypeConverter : StringTypeConverter 4 | { 5 | protected override object? ConvertFromStringCore(string? value) 6 | { 7 | if (value == null) 8 | return null; 9 | 10 | value = value?.Trim(); 11 | var parts = value?.Split(','); 12 | 13 | if (parts == null) 14 | return null; 15 | 16 | var colors = new SKConfettiColorCollection(); 17 | var colConv = new ColorTypeConverter(); 18 | 19 | foreach (var part in parts) 20 | { 21 | var c = colConv.ConvertFromInvariantString(part); 22 | colors.Add((Color)c); 23 | } 24 | 25 | return colors; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Converters/RoundToIntConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | 3 | namespace SkiaSharpDemo.Converters; 4 | 5 | public class RoundToIntConverter : IValueConverter 6 | { 7 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => 8 | value switch 9 | { 10 | double d => d, 11 | int i => (double)i, 12 | _ => throw new ArgumentException("Value was not an integer or double.", nameof(value)), 13 | }; 14 | 15 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => 16 | value switch 17 | { 18 | double d => (int)Math.Round(d), 19 | int i => i, 20 | _ => throw new ArgumentException("Value was not an integer or double.", nameof(value)), 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "nuget" 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | groups: 13 | SkiaSharp: 14 | patterns: 15 | - "SkiaSharp" 16 | - "SkiaSharp.*" 17 | - "HarfBuzzSharp" 18 | - "HarfBuzzSharp.*" 19 | xunit: 20 | patterns: 21 | - "xunit" 22 | - "xunit.*" 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FEATURE] " 5 | labels: feature-request 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | 12 | 13 | 14 | **Describe the solution you'd like** 15 | 16 | 17 | 18 | **Describe alternatives you've considered** 19 | 20 | 21 | 22 | **Additional context** 23 | 24 | 25 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Platforms/Windows/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | true/PM 12 | PerMonitorV2, PerMonitor 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/Controls/Lottie/SKLottieAnimationLoadedEventArgs.shared.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended.UI.Controls; 2 | 3 | public class SKLottieAnimationLoadedEventArgs : EventArgs 4 | { 5 | public SKLottieAnimationLoadedEventArgs(Size size, TimeSpan duration, double fps) 6 | { 7 | Size = size; 8 | Duration = duration; 9 | Fps = fps; 10 | } 11 | 12 | public Size Size { get; } 13 | 14 | public TimeSpan Duration { get; } 15 | 16 | public double Fps { get; } 17 | 18 | internal static SKLottieAnimationLoadedEventArgs Create(Skottie.Animation animation) 19 | { 20 | var s = animation.Size; 21 | var size = new Size(s.Width, s.Height); 22 | var duration = animation.Duration; 23 | var fps = animation.Fps; 24 | 25 | return new SKLottieAnimationLoadedEventArgs(size, duration, fps); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Converters/RoundToConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | 3 | namespace SkiaSharpDemo.Converters; 4 | 5 | public class RoundToConverter : IValueConverter 6 | { 7 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => 8 | value switch 9 | { 10 | double d => d, 11 | _ => throw new ArgumentException("Value was not a double.", nameof(value)), 12 | }; 13 | 14 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 15 | { 16 | if (parameter == null || !int.TryParse(parameter.ToString(), out var decimals)) 17 | decimals = 0; 18 | 19 | return value switch 20 | { 21 | double d => Math.Round(d, decimals), 22 | _ => throw new ArgumentException("Value was not a double.", nameof(value)), 23 | }; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Converters/TimeSpanToDoubleConverter.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | 3 | namespace SkiaSharpDemo.Converters; 4 | 5 | public class TimeSpanToDoubleConverter : IValueConverter 6 | { 7 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => 8 | value switch 9 | { 10 | TimeSpan ts => ts.TotalMilliseconds == 0 && parameter is not null 11 | ? double.Parse(parameter.ToString()) 12 | : ts.TotalMilliseconds, 13 | _ => throw new ArgumentException("Value was not a TimeSpan.", nameof(value)), 14 | }; 15 | 16 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => 17 | value switch 18 | { 19 | double d => TimeSpan.FromMilliseconds(d), 20 | _ => throw new ArgumentException("Value was not a double.", nameof(value)), 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Platforms/Windows/App.xaml.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.UI.Xaml; 2 | 3 | // To learn more about WinUI, the WinUI project structure, 4 | // and more about our project templates, see: http://aka.ms/winui-project-info. 5 | 6 | namespace SkiaSharpDemo.WinUI; 7 | 8 | /// 9 | /// Provides application-specific behavior to supplement the default Application class. 10 | /// 11 | public partial class App : MauiWinUIApplication 12 | { 13 | /// 14 | /// Initializes the singleton application object. This is the first line of authored code 15 | /// executed, and as such is the logical equivalent of main() or WinMain(). 16 | /// 17 | public App() 18 | { 19 | this.InitializeComponent(); 20 | } 21 | 22 | protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp(); 23 | } 24 | 25 | -------------------------------------------------------------------------------- /.github/workflows/rebase.yml: -------------------------------------------------------------------------------- 1 | name: Automatic Rebase 2 | 3 | on: 4 | issue_comment: 5 | types: [created] 6 | 7 | permissions: 8 | pull-requests: write 9 | contents: write 10 | 11 | jobs: 12 | rebase: 13 | name: Rebase 14 | runs-on: ubuntu-latest 15 | if: github.event.issue.pull_request != '' && startsWith(github.event.comment.body, '/rebase') 16 | steps: 17 | - name: Checkout the latest code 18 | uses: actions/checkout@v2 19 | with: 20 | token: ${{ secrets.GITHUB_TOKEN }} 21 | fetch-depth: 0 # otherwise, you will fail to push refs to dest repo 22 | - name: Automatic Rebase 23 | uses: cirrus-actions/rebase@1.7 24 | with: 25 | autosquash: ${{ startsWith(github.event.comment.body, '/rebase-squash') }} 26 | env: 27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 28 | -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.UI.Maui.Tests/Controls/SKAnimatedSurfaceViewTest.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace SkiaSharp.Extended.UI.Controls.Tests; 4 | 5 | public class SKAnimatedSurfaceViewTest : DispatchingBaseTest 6 | { 7 | [Theory] 8 | [InlineData(true)] 9 | [InlineData(false)] 10 | public async Task DoesNotLeak(bool animate) 11 | { 12 | var weak = Setup(animate); 13 | 14 | await Task.Yield(); 15 | 16 | GC.Collect(); 17 | GC.WaitForPendingFinalizers(); 18 | 19 | Assert.False(weak.IsAlive); 20 | 21 | static WeakReference Setup(bool animate) 22 | { 23 | var view = new SKAnimatedSurfaceView(); 24 | var window = new Window 25 | { 26 | Page = new ContentPage 27 | { 28 | Content = view 29 | } 30 | }; 31 | 32 | if (animate) 33 | { 34 | view.IsAnimationEnabled = true; 35 | } 36 | 37 | return new WeakReference(view); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /source/SkiaSharp.Extended.UI.Maui/Controls/Lottie/SKLottieImageSourceConverter.shared.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended.UI.Controls.Converters; 2 | 3 | public sealed class SKLottieImageSourceConverter : StringTypeConverter 4 | { 5 | protected override object? ConvertFromStringCore(string? value) 6 | { 7 | if (string.IsNullOrEmpty(value)) 8 | throw new InvalidOperationException($"Cannot convert \"{value}\" into {typeof(SKLottieImageSource)}"); 9 | 10 | if (Uri.TryCreate(value, UriKind.Absolute, out var uri) && uri.Scheme != "file") 11 | return SKLottieImageSource.FromUri(uri); 12 | 13 | return SKLottieImageSource.FromFile(value!); 14 | } 15 | 16 | protected override string? ConvertToStringCore(object? value) => 17 | value switch 18 | { 19 | SKFileLottieImageSource fis => fis.File, 20 | SKUriLottieImageSource uis => uis.Uri?.ToString(), 21 | _ => throw new NotSupportedException() 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /tests/SkiaSharp.Extended.UI.Maui.Tests/Controls/Lottie/SKFileLottieImageSourceTest.cs: -------------------------------------------------------------------------------- 1 | namespace SkiaSharp.Extended.UI.Controls.Tests; 2 | 3 | public class SKFileLottieImageSourceTest : SKLottieImageSourceTest 4 | { 5 | private const string TrophyJson = "TestAssets/Lottie/trophy.json"; 6 | private const string LoloJson = "TestAssets/Lottie/lolo.json"; 7 | 8 | protected override SKFileLottieImageSource CreateEmptyImageSource() => 9 | new SKFileLottieImageSource { }; 10 | 11 | protected override SKFileLottieImageSource CreateCompleteImageSource() => 12 | new SKFileLottieImageSource { File = TrophyJson }; 13 | 14 | protected override void UpdateImageSource(SKFileLottieImageSource imageSource, bool first) => 15 | imageSource.File = first ? TrophyJson : LoloJson; 16 | 17 | protected override void ResetImageSource(SKFileLottieImageSource imageSource) => 18 | imageSource.File = null; 19 | } 20 | -------------------------------------------------------------------------------- /samples/SkiaSharpDemo/Demos/Extended/InterpolationPage.xaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 |