diff --git a/binding/Binding/SKCanvas.cs b/binding/Binding/SKCanvas.cs index 29e1062f6d..2310f6a98e 100644 --- a/binding/Binding/SKCanvas.cs +++ b/binding/Binding/SKCanvas.cs @@ -9,6 +9,8 @@ public unsafe class SKCanvas : SKObject { private const int PatchCornerCount = 4; private const int PatchCubicsCount = 12; + private const double RadiansCircle = 2.0 * Math.PI; + private const double DegreesCircle = 360.0; internal SKCanvas (IntPtr handle, bool owns) : base (handle, owns) @@ -117,11 +119,17 @@ public void RestoreToCount (int count) public void Translate (float dx, float dy) { + if (dx == 0 && dy == 0) + return; + SkiaApi.sk_canvas_translate (Handle, dx, dy); } public void Translate (SKPoint point) { + if (point.IsEmpty) + return; + SkiaApi.sk_canvas_translate (Handle, point.X, point.Y); } @@ -129,21 +137,33 @@ public void Translate (SKPoint point) public void Scale (float s) { + if (s == 1) + return; + SkiaApi.sk_canvas_scale (Handle, s, s); } public void Scale (float sx, float sy) { + if (sx == 1 && sy == 1) + return; + SkiaApi.sk_canvas_scale (Handle, sx, sy); } public void Scale (SKPoint size) { + if (size.IsEmpty) + return; + SkiaApi.sk_canvas_scale (Handle, size.X, size.Y); } public void Scale (float sx, float sy, float px, float py) { + if (sx == 1 && sy == 1) + return; + Translate (px, py); Scale (sx, sy); Translate (-px, -py); @@ -153,16 +173,25 @@ public void Scale (float sx, float sy, float px, float py) public void RotateDegrees (float degrees) { + if (degrees % DegreesCircle == 0) + return; + SkiaApi.sk_canvas_rotate_degrees (Handle, degrees); } public void RotateRadians (float radians) { + if (radians % RadiansCircle == 0) + return; + SkiaApi.sk_canvas_rotate_radians (Handle, radians); } public void RotateDegrees (float degrees, float px, float py) { + if (degrees % DegreesCircle == 0) + return; + Translate (px, py); RotateDegrees (degrees); Translate (-px, -py); @@ -170,6 +199,9 @@ public void RotateDegrees (float degrees, float px, float py) public void RotateRadians (float radians, float px, float py) { + if (radians % RadiansCircle == 0) + return; + Translate (px, py); RotateRadians (radians); Translate (-px, -py); @@ -179,11 +211,17 @@ public void RotateRadians (float radians, float px, float py) public void Skew (float sx, float sy) { + if (sx == 0 && sy == 0) + return; + SkiaApi.sk_canvas_skew (Handle, sx, sy); } public void Skew (SKPoint skew) { + if (skew.IsEmpty) + return; + SkiaApi.sk_canvas_skew (Handle, skew.X, skew.Y); } diff --git a/build.cake b/build.cake index 7e63bbd47c..4450a73ab0 100644 --- a/build.cake +++ b/build.cake @@ -424,6 +424,8 @@ Task ("samples") { "tvos", isMac }, { "uwp", isWin }, { "winui", isWin }, + { "wapproj", isWin }, + { "msix", isWin }, { "watchos", isMac }, { "wpf", isWin }, }; @@ -433,6 +435,7 @@ Task ("samples") { "tvos", "iPhoneSimulator" }, { "uwp", "x86" }, { "winui", "x64" }, + { "wapproj", "x64" }, { "watchos", "iPhoneSimulator" }, { "xamarin.forms.mac", "iPhone" }, { "xamarin.forms.windows", "x86" }, @@ -458,8 +461,12 @@ Task ("samples") buildPlatform = platformMatrix [platform]; } + Information ($"Building {sln} ({platform})..."); + RunNuGetRestorePackagesConfig (sln); RunMSBuild (sln, platform: buildPlatform); + } else { + Information ($"Skipping {sln} ({platform})..."); } } diff --git a/samples/Basic/Android/SkiaSharpSample/MainActivity.cs b/samples/Basic/Android/SkiaSharpSample/MainActivity.cs index d20c110346..33b78dd500 100644 --- a/samples/Basic/Android/SkiaSharpSample/MainActivity.cs +++ b/samples/Basic/Android/SkiaSharpSample/MainActivity.cs @@ -40,13 +40,6 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) // the the canvas and properties var canvas = e.Surface.Canvas; - // get the screen density for scaling - var scale = Resources.DisplayMetrics.Density; - var scaledSize = new SKSize(e.Info.Width / scale, e.Info.Height / scale); - - // handle the device screen density - canvas.Scale(scale); - // make sure the canvas is blank canvas.Clear(SKColors.White); @@ -59,7 +52,7 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) TextAlign = SKTextAlign.Center, TextSize = 24 }; - var coord = new SKPoint(scaledSize.Width / 2, (scaledSize.Height + paint.TextSize) / 2); + var coord = new SKPoint(e.Info.Width / 2, (e.Info.Height + paint.TextSize) / 2); canvas.DrawText("SkiaSharp", coord, paint); } } diff --git a/samples/Basic/Android/SkiaSharpSample/Resources/layout/main.xml b/samples/Basic/Android/SkiaSharpSample/Resources/layout/main.xml index 54a7c78897..bafc84ba08 100644 --- a/samples/Basic/Android/SkiaSharpSample/Resources/layout/main.xml +++ b/samples/Basic/Android/SkiaSharpSample/Resources/layout/main.xml @@ -1,10 +1,12 @@ \ No newline at end of file diff --git a/samples/Basic/Desktop/SkiaSharpSample/Form1.cs b/samples/Basic/Desktop/SkiaSharpSample/Form1.cs index d92531e196..f0b2f26e99 100644 --- a/samples/Basic/Desktop/SkiaSharpSample/Form1.cs +++ b/samples/Basic/Desktop/SkiaSharpSample/Form1.cs @@ -17,13 +17,6 @@ private void skiaView_PaintSurface(object sender, SKPaintSurfaceEventArgs e) // the the canvas and properties var canvas = e.Surface.Canvas; - // get the screen density for scaling - var scale = 1f; - var scaledSize = new SKSize(e.Info.Width / scale, e.Info.Height / scale); - - // handle the device screen density - canvas.Scale(scale); - // make sure the canvas is blank canvas.Clear(SKColors.White); @@ -36,7 +29,7 @@ private void skiaView_PaintSurface(object sender, SKPaintSurfaceEventArgs e) TextAlign = SKTextAlign.Center, TextSize = 24 }; - var coord = new SKPoint(scaledSize.Width / 2, (scaledSize.Height + paint.TextSize) / 2); + var coord = new SKPoint(e.Info.Width / 2, (e.Info.Height + paint.TextSize) / 2); canvas.DrawText("SkiaSharp", coord, paint); } } diff --git a/samples/Basic/ElmSharp/SkiaSharpSample/App.cs b/samples/Basic/ElmSharp/SkiaSharpSample/App.cs index e9706251be..d1ed044d14 100644 --- a/samples/Basic/ElmSharp/SkiaSharpSample/App.cs +++ b/samples/Basic/ElmSharp/SkiaSharpSample/App.cs @@ -33,6 +33,7 @@ private void Initialize() window.Show(); var skiaView = new SKCanvasView(window); + skiaView.IgnorePixelScaling = true; skiaView.PaintSurface += OnPaintSurface; skiaView.Show(); @@ -43,18 +44,9 @@ private void Initialize() private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) { - var skiaView = sender as SKCanvasView; - // the the canvas and properties var canvas = e.Surface.Canvas; - // get the screen density for scaling - var scale = (float)ScalingInfo.ScalingFactor; - var scaledSize = new SKSize(e.Info.Width / scale, e.Info.Height / scale); - - // handle the device screen density - canvas.Scale(scale); - // make sure the canvas is blank canvas.Clear(SKColors.White); @@ -67,7 +59,7 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) TextAlign = SKTextAlign.Center, TextSize = 24 }; - var coord = new SKPoint(scaledSize.Width / 2, (scaledSize.Height + paint.TextSize) / 2); + var coord = new SKPoint(e.Info.Width / 2, (e.Info.Height + paint.TextSize) / 2); canvas.DrawText("SkiaSharp", coord, paint); } diff --git a/samples/Basic/Gtk/SkiaSharpSample/MainWindow.cs b/samples/Basic/Gtk/SkiaSharpSample/MainWindow.cs index c4cb253047..25df721681 100644 --- a/samples/Basic/Gtk/SkiaSharpSample/MainWindow.cs +++ b/samples/Basic/Gtk/SkiaSharpSample/MainWindow.cs @@ -24,13 +24,6 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) // the the canvas and properties var canvas = e.Surface.Canvas; - // get the screen density for scaling - var scale = 1f; - var scaledSize = new SKSize(e.Info.Width / scale, e.Info.Height / scale); - - // handle the device screen density - canvas.Scale(scale); - // make sure the canvas is blank canvas.Clear(SKColors.White); @@ -43,7 +36,7 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) TextAlign = SKTextAlign.Center, TextSize = 24 }; - var coord = new SKPoint(scaledSize.Width / 2, (scaledSize.Height + paint.TextSize) / 2); + var coord = new SKPoint(e.Info.Width / 2, (e.Info.Height + paint.TextSize) / 2); canvas.DrawText("SkiaSharp", coord, paint); } } diff --git a/samples/Basic/Gtk3/SkiaSharpSample/MainWindow.cs b/samples/Basic/Gtk3/SkiaSharpSample/MainWindow.cs index 85db2741e9..7b134e1e88 100644 --- a/samples/Basic/Gtk3/SkiaSharpSample/MainWindow.cs +++ b/samples/Basic/Gtk3/SkiaSharpSample/MainWindow.cs @@ -37,13 +37,6 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) // the the canvas and properties var canvas = e.Surface.Canvas; - // get the screen density for scaling - var scale = 1f; - var scaledSize = new SKSize(e.Info.Width / scale, e.Info.Height / scale); - - // handle the device screen density - canvas.Scale(scale); - // make sure the canvas is blank canvas.Clear(SKColors.White); @@ -56,7 +49,7 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) TextAlign = SKTextAlign.Center, TextSize = 24 }; - var coord = new SKPoint(scaledSize.Width / 2, (scaledSize.Height + paint.TextSize) / 2); + var coord = new SKPoint(e.Info.Width / 2, (e.Info.Height + paint.TextSize) / 2); canvas.DrawText("SkiaSharp", coord, paint); } } diff --git a/samples/Basic/Maui/SkiaSharpSample/MainPage.xaml b/samples/Basic/Maui/SkiaSharpSample/MainPage.xaml index 8196245545..5ef3452d49 100644 --- a/samples/Basic/Maui/SkiaSharpSample/MainPage.xaml +++ b/samples/Basic/Maui/SkiaSharpSample/MainPage.xaml @@ -5,6 +5,7 @@ BackgroundColor="White"> + EnableTouchEvents="True" Touch="OnTouch" + IgnorePixelScaling="True" /> diff --git a/samples/Basic/Maui/SkiaSharpSample/MainPage.xaml.cs b/samples/Basic/Maui/SkiaSharpSample/MainPage.xaml.cs index 01dabda179..4d79f460db 100644 --- a/samples/Basic/Maui/SkiaSharpSample/MainPage.xaml.cs +++ b/samples/Basic/Maui/SkiaSharpSample/MainPage.xaml.cs @@ -30,12 +30,6 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) // the the canvas and properties var canvas = e.Surface.Canvas; - // get the screen density for scaling - var scale = (float)(e.Info.Width / skiaView.Width); - - // handle the device screen density - canvas.Scale(scale); - // make sure the canvas is blank canvas.Clear(SKColors.White); @@ -51,8 +45,8 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) // adjust the location based on the pointer var coord = (touchLocation is SKPoint loc) - ? new SKPoint(loc.X / scale, loc.Y / scale) - : new SKPoint((float)skiaView.Width / 2, ((float)skiaView.Height + paint.TextSize) / 2); + ? new SKPoint(loc.X, loc.Y) + : new SKPoint(e.Info.Width / 2, (e.Info.Height + paint.TextSize) / 2); // draw some text canvas.DrawText("SkiaSharp", coord, paint); diff --git a/samples/Basic/Maui/SkiaSharpSample/SkiaSharpSample.csproj b/samples/Basic/Maui/SkiaSharpSample/SkiaSharpSample.csproj index d73503c2ea..093907d8ed 100644 --- a/samples/Basic/Maui/SkiaSharpSample/SkiaSharpSample.csproj +++ b/samples/Basic/Maui/SkiaSharpSample/SkiaSharpSample.csproj @@ -4,13 +4,14 @@ net6.0-ios;net6.0-maccatalyst;net6.0-android $(TargetFrameworks);net6.0-windows10.0.19041 Exe + true true + true SkiaSharpSample SkiaSharpSample com.companyname.SkiaSharpSample 1.0 1 - true 9.0 True @@ -39,10 +40,9 @@ - - true - bin\$(Configuration)\net6.0-windows10.0.19041\win-x64\SkiaSharpSample.build.appxrecipe - win-x64 + + WinExe + win-x64 diff --git a/samples/Basic/NetCore/WPF/SkiaSharpSample/MainWindow.xaml b/samples/Basic/NetCore/WPF/SkiaSharpSample/MainWindow.xaml index 3f575d521e..b6e5bc0dc0 100644 --- a/samples/Basic/NetCore/WPF/SkiaSharpSample/MainWindow.xaml +++ b/samples/Basic/NetCore/WPF/SkiaSharpSample/MainWindow.xaml @@ -8,6 +8,6 @@ mc:Ignorable="d" Title="SkiaSharp" Height="350" Width="525" Icon="/icon.ico"> - + diff --git a/samples/Basic/NetCore/WPF/SkiaSharpSample/MainWindow.xaml.cs b/samples/Basic/NetCore/WPF/SkiaSharpSample/MainWindow.xaml.cs index 62e7013dd0..d88701e671 100644 --- a/samples/Basic/NetCore/WPF/SkiaSharpSample/MainWindow.xaml.cs +++ b/samples/Basic/NetCore/WPF/SkiaSharpSample/MainWindow.xaml.cs @@ -17,13 +17,6 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) // the the canvas and properties var canvas = e.Surface.Canvas; - // get the screen density for scaling - var scale = (float)PresentationSource.FromVisual(this).CompositionTarget.TransformToDevice.M11; - var scaledSize = new SKSize(e.Info.Width / scale, e.Info.Height / scale); - - // handle the device screen density - canvas.Scale(scale); - // make sure the canvas is blank canvas.Clear(SKColors.White); @@ -36,7 +29,7 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) TextAlign = SKTextAlign.Center, TextSize = 24 }; - var coord = new SKPoint(scaledSize.Width / 2, (scaledSize.Height + paint.TextSize) / 2); + var coord = new SKPoint(e.Info.Width / 2, (e.Info.Height + paint.TextSize) / 2); canvas.DrawText("SkiaSharp", coord, paint); } } diff --git a/samples/Basic/Tizen/SkiaSharpSample/MainPage.xaml b/samples/Basic/Tizen/SkiaSharpSample/MainPage.xaml index 8262aa4a07..503f2539d0 100644 --- a/samples/Basic/Tizen/SkiaSharpSample/MainPage.xaml +++ b/samples/Basic/Tizen/SkiaSharpSample/MainPage.xaml @@ -5,6 +5,6 @@ xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms" x:Class="SkiaSharpSample.MainPage"> - + \ No newline at end of file diff --git a/samples/Basic/Tizen/SkiaSharpSample/MainPage.xaml.cs b/samples/Basic/Tizen/SkiaSharpSample/MainPage.xaml.cs index e4de500285..9e28553c84 100644 --- a/samples/Basic/Tizen/SkiaSharpSample/MainPage.xaml.cs +++ b/samples/Basic/Tizen/SkiaSharpSample/MainPage.xaml.cs @@ -17,12 +17,6 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) // the the canvas and properties var canvas = e.Surface.Canvas; - // get the screen density for scaling - var scale = (float)(e.Info.Width / skiaView.Width); - - // handle the device screen density - canvas.Scale(scale); - // make sure the canvas is blank canvas.Clear(SKColors.White); @@ -35,7 +29,7 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) TextAlign = SKTextAlign.Center, TextSize = 24 }; - var coord = new SKPoint((float)skiaView.Width / 2, ((float)skiaView.Height + paint.TextSize) / 2); + var coord = new SKPoint(e.Info.Width / 2, (e.Info.Height + paint.TextSize) / 2); canvas.DrawText("SkiaSharp", coord, paint); } } diff --git a/samples/Basic/UWP/SkiaSharpSample/MainPage.xaml b/samples/Basic/UWP/SkiaSharpSample/MainPage.xaml index b79b1d4d76..1f64c92196 100644 --- a/samples/Basic/UWP/SkiaSharpSample/MainPage.xaml +++ b/samples/Basic/UWP/SkiaSharpSample/MainPage.xaml @@ -8,6 +8,6 @@ xmlns:skia="using:SkiaSharp.Views.UWP" mc:Ignorable="d"> - + diff --git a/samples/Basic/UWP/SkiaSharpSample/MainPage.xaml.cs b/samples/Basic/UWP/SkiaSharpSample/MainPage.xaml.cs index c07b0a0c77..037002c2fc 100644 --- a/samples/Basic/UWP/SkiaSharpSample/MainPage.xaml.cs +++ b/samples/Basic/UWP/SkiaSharpSample/MainPage.xaml.cs @@ -1,5 +1,4 @@ -using Windows.Graphics.Display; -using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls; using SkiaSharp; using SkiaSharp.Views.UWP; @@ -18,14 +17,6 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) // the the canvas and properties var canvas = e.Surface.Canvas; - // get the screen density for scaling - var display = DisplayInformation.GetForCurrentView(); - var scale = display.LogicalDpi / 96.0f; - var scaledSize = new SKSize(e.Info.Width / scale, e.Info.Height / scale); - - // handle the device screen density - canvas.Scale(scale); - // make sure the canvas is blank canvas.Clear(SKColors.White); @@ -38,7 +29,7 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) TextAlign = SKTextAlign.Center, TextSize = 24 }; - var coord = new SKPoint(scaledSize.Width / 2, (scaledSize.Height + paint.TextSize) / 2); + var coord = new SKPoint(e.Info.Width / 2, (e.Info.Height + paint.TextSize) / 2); canvas.DrawText("SkiaSharp", coord, paint); } } diff --git a/samples/Basic/Uno/SkiaSharpSample.Shared/MainPage.xaml b/samples/Basic/Uno/SkiaSharpSample.Shared/MainPage.xaml index b79b1d4d76..8a7a085eda 100644 --- a/samples/Basic/Uno/SkiaSharpSample.Shared/MainPage.xaml +++ b/samples/Basic/Uno/SkiaSharpSample.Shared/MainPage.xaml @@ -7,7 +7,9 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:skia="using:SkiaSharp.Views.UWP" mc:Ignorable="d"> + - + + diff --git a/samples/Basic/Uno/SkiaSharpSample.Shared/MainPage.xaml.cs b/samples/Basic/Uno/SkiaSharpSample.Shared/MainPage.xaml.cs index c07b0a0c77..25cb7d40e3 100644 --- a/samples/Basic/Uno/SkiaSharpSample.Shared/MainPage.xaml.cs +++ b/samples/Basic/Uno/SkiaSharpSample.Shared/MainPage.xaml.cs @@ -18,14 +18,6 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) // the the canvas and properties var canvas = e.Surface.Canvas; - // get the screen density for scaling - var display = DisplayInformation.GetForCurrentView(); - var scale = display.LogicalDpi / 96.0f; - var scaledSize = new SKSize(e.Info.Width / scale, e.Info.Height / scale); - - // handle the device screen density - canvas.Scale(scale); - // make sure the canvas is blank canvas.Clear(SKColors.White); @@ -38,7 +30,7 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) TextAlign = SKTextAlign.Center, TextSize = 24 }; - var coord = new SKPoint(scaledSize.Width / 2, (scaledSize.Height + paint.TextSize) / 2); + var coord = new SKPoint(e.Info.Width / 2, (e.Info.Height + paint.TextSize) / 2); canvas.DrawText("SkiaSharp", coord, paint); } } diff --git a/samples/Basic/WPF/SkiaSharpSample/MainWindow.xaml b/samples/Basic/WPF/SkiaSharpSample/MainWindow.xaml index 2315240773..438f4065c1 100644 --- a/samples/Basic/WPF/SkiaSharpSample/MainWindow.xaml +++ b/samples/Basic/WPF/SkiaSharpSample/MainWindow.xaml @@ -8,6 +8,6 @@ mc:Ignorable="d" Title="SkiaSharp" Height="350" Width="525" Icon="icon.ico"> - + diff --git a/samples/Basic/WPF/SkiaSharpSample/MainWindow.xaml.cs b/samples/Basic/WPF/SkiaSharpSample/MainWindow.xaml.cs index 62e7013dd0..d88701e671 100644 --- a/samples/Basic/WPF/SkiaSharpSample/MainWindow.xaml.cs +++ b/samples/Basic/WPF/SkiaSharpSample/MainWindow.xaml.cs @@ -17,13 +17,6 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) // the the canvas and properties var canvas = e.Surface.Canvas; - // get the screen density for scaling - var scale = (float)PresentationSource.FromVisual(this).CompositionTarget.TransformToDevice.M11; - var scaledSize = new SKSize(e.Info.Width / scale, e.Info.Height / scale); - - // handle the device screen density - canvas.Scale(scale); - // make sure the canvas is blank canvas.Clear(SKColors.White); @@ -36,7 +29,7 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) TextAlign = SKTextAlign.Center, TextSize = 24 }; - var coord = new SKPoint(scaledSize.Width / 2, (scaledSize.Height + paint.TextSize) / 2); + var coord = new SKPoint(e.Info.Width / 2, (e.Info.Height + paint.TextSize) / 2); canvas.DrawText("SkiaSharp", coord, paint); } } diff --git a/samples/Basic/WinUI/Msix/SkiaSharpSample.sln b/samples/Basic/WinUI/Msix/SkiaSharpSample.sln new file mode 100644 index 0000000000..1768be4c36 --- /dev/null +++ b/samples/Basic/WinUI/Msix/SkiaSharpSample.sln @@ -0,0 +1,41 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31709.45 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharpSample", "SkiaSharpSample\SkiaSharpSample.csproj", "{71668276-ECDD-49EC-9406-27A9D2676139}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp", "..\..\..\..\binding\SkiaSharp\SkiaSharp.csproj", "{EA2AC287-6FEF-415D-BD33-01287DD11574}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SkiaSharp.Views.WinUI", "..\..\..\..\source\SkiaSharp.Views.WinUI\SkiaSharp.Views.WinUI\SkiaSharp.Views.WinUI.csproj", "{B9E319D8-0A0E-471C-BD01-8015655FBD99}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {71668276-ECDD-49EC-9406-27A9D2676139}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {71668276-ECDD-49EC-9406-27A9D2676139}.Debug|Any CPU.Build.0 = Debug|Any CPU + {71668276-ECDD-49EC-9406-27A9D2676139}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {71668276-ECDD-49EC-9406-27A9D2676139}.Release|Any CPU.ActiveCfg = Release|Any CPU + {71668276-ECDD-49EC-9406-27A9D2676139}.Release|Any CPU.Build.0 = Release|Any CPU + {71668276-ECDD-49EC-9406-27A9D2676139}.Release|Any CPU.Deploy.0 = Release|Any CPU + {EA2AC287-6FEF-415D-BD33-01287DD11574}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA2AC287-6FEF-415D-BD33-01287DD11574}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA2AC287-6FEF-415D-BD33-01287DD11574}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA2AC287-6FEF-415D-BD33-01287DD11574}.Release|Any CPU.Build.0 = Release|Any CPU + {B9E319D8-0A0E-471C-BD01-8015655FBD99}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B9E319D8-0A0E-471C-BD01-8015655FBD99}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B9E319D8-0A0E-471C-BD01-8015655FBD99}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {B9E319D8-0A0E-471C-BD01-8015655FBD99}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B9E319D8-0A0E-471C-BD01-8015655FBD99}.Release|Any CPU.Build.0 = Release|Any CPU + {B9E319D8-0A0E-471C-BD01-8015655FBD99}.Release|Any CPU.Deploy.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F5AABA3E-0272-4E88-A2B4-BD422E83400E} + EndGlobalSection +EndGlobal diff --git a/samples/Basic/WinUI/Desktop/SkiaSharpSample/App.xaml b/samples/Basic/WinUI/Msix/SkiaSharpSample/App.xaml similarity index 100% rename from samples/Basic/WinUI/Desktop/SkiaSharpSample/App.xaml rename to samples/Basic/WinUI/Msix/SkiaSharpSample/App.xaml diff --git a/samples/Basic/WinUI/Desktop/SkiaSharpSample/App.xaml.cs b/samples/Basic/WinUI/Msix/SkiaSharpSample/App.xaml.cs similarity index 100% rename from samples/Basic/WinUI/Desktop/SkiaSharpSample/App.xaml.cs rename to samples/Basic/WinUI/Msix/SkiaSharpSample/App.xaml.cs diff --git a/samples/Basic/WinUI/Desktop/SkiaSharpSample.Package/Images/LockScreenLogo.scale-200.png b/samples/Basic/WinUI/Msix/SkiaSharpSample/Images/LockScreenLogo.scale-200.png similarity index 100% rename from samples/Basic/WinUI/Desktop/SkiaSharpSample.Package/Images/LockScreenLogo.scale-200.png rename to samples/Basic/WinUI/Msix/SkiaSharpSample/Images/LockScreenLogo.scale-200.png diff --git a/samples/Basic/WinUI/Desktop/SkiaSharpSample.Package/Images/SplashScreen.scale-200.png b/samples/Basic/WinUI/Msix/SkiaSharpSample/Images/SplashScreen.scale-200.png similarity index 100% rename from samples/Basic/WinUI/Desktop/SkiaSharpSample.Package/Images/SplashScreen.scale-200.png rename to samples/Basic/WinUI/Msix/SkiaSharpSample/Images/SplashScreen.scale-200.png diff --git a/samples/Basic/WinUI/Desktop/SkiaSharpSample.Package/Images/Square150x150Logo.scale-200.png b/samples/Basic/WinUI/Msix/SkiaSharpSample/Images/Square150x150Logo.scale-200.png similarity index 100% rename from samples/Basic/WinUI/Desktop/SkiaSharpSample.Package/Images/Square150x150Logo.scale-200.png rename to samples/Basic/WinUI/Msix/SkiaSharpSample/Images/Square150x150Logo.scale-200.png diff --git a/samples/Basic/WinUI/Desktop/SkiaSharpSample.Package/Images/Square44x44Logo.scale-200.png b/samples/Basic/WinUI/Msix/SkiaSharpSample/Images/Square44x44Logo.scale-200.png similarity index 100% rename from samples/Basic/WinUI/Desktop/SkiaSharpSample.Package/Images/Square44x44Logo.scale-200.png rename to samples/Basic/WinUI/Msix/SkiaSharpSample/Images/Square44x44Logo.scale-200.png diff --git a/samples/Basic/WinUI/Desktop/SkiaSharpSample.Package/Images/Square44x44Logo.targetsize-24_altform-unplated.png b/samples/Basic/WinUI/Msix/SkiaSharpSample/Images/Square44x44Logo.targetsize-24_altform-unplated.png similarity index 100% rename from samples/Basic/WinUI/Desktop/SkiaSharpSample.Package/Images/Square44x44Logo.targetsize-24_altform-unplated.png rename to samples/Basic/WinUI/Msix/SkiaSharpSample/Images/Square44x44Logo.targetsize-24_altform-unplated.png diff --git a/samples/Basic/WinUI/Desktop/SkiaSharpSample.Package/Images/StoreLogo.png b/samples/Basic/WinUI/Msix/SkiaSharpSample/Images/StoreLogo.png similarity index 100% rename from samples/Basic/WinUI/Desktop/SkiaSharpSample.Package/Images/StoreLogo.png rename to samples/Basic/WinUI/Msix/SkiaSharpSample/Images/StoreLogo.png diff --git a/samples/Basic/WinUI/Desktop/SkiaSharpSample.Package/Images/Wide310x150Logo.scale-200.png b/samples/Basic/WinUI/Msix/SkiaSharpSample/Images/Wide310x150Logo.scale-200.png similarity index 100% rename from samples/Basic/WinUI/Desktop/SkiaSharpSample.Package/Images/Wide310x150Logo.scale-200.png rename to samples/Basic/WinUI/Msix/SkiaSharpSample/Images/Wide310x150Logo.scale-200.png diff --git a/samples/Basic/WinUI/Desktop/SkiaSharpSample/MainWindow.xaml b/samples/Basic/WinUI/Msix/SkiaSharpSample/MainWindow.xaml similarity index 84% rename from samples/Basic/WinUI/Desktop/SkiaSharpSample/MainWindow.xaml rename to samples/Basic/WinUI/Msix/SkiaSharpSample/MainWindow.xaml index 97823c096a..02b9c81e48 100644 --- a/samples/Basic/WinUI/Desktop/SkiaSharpSample/MainWindow.xaml +++ b/samples/Basic/WinUI/Msix/SkiaSharpSample/MainWindow.xaml @@ -8,6 +8,6 @@ xmlns:skia="using:SkiaSharp.Views.Windows" mc:Ignorable="d"> - + diff --git a/samples/Basic/WinUI/Desktop/SkiaSharpSample/MainWindow.xaml.cs b/samples/Basic/WinUI/Msix/SkiaSharpSample/MainWindow.xaml.cs similarity index 66% rename from samples/Basic/WinUI/Desktop/SkiaSharpSample/MainWindow.xaml.cs rename to samples/Basic/WinUI/Msix/SkiaSharpSample/MainWindow.xaml.cs index 9a4d6f10f1..384df70201 100644 --- a/samples/Basic/WinUI/Desktop/SkiaSharpSample/MainWindow.xaml.cs +++ b/samples/Basic/WinUI/Msix/SkiaSharpSample/MainWindow.xaml.cs @@ -16,13 +16,6 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) // the the canvas and properties var canvas = e.Surface.Canvas; - // get the screen density for scaling - var scale = (float)((SKXamlCanvas)sender).XamlRoot.RasterizationScale; - var scaledSize = new SKSize(e.Info.Width / scale, e.Info.Height / scale); - - // handle the device screen density - canvas.Scale(scale); - // make sure the canvas is blank canvas.Clear(SKColors.White); @@ -35,7 +28,7 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) TextAlign = SKTextAlign.Center, TextSize = 24 }; - var coord = new SKPoint(scaledSize.Width / 2, (scaledSize.Height + paint.TextSize) / 2); + var coord = new SKPoint(e.Info.Width / 2, (e.Info.Height + paint.TextSize) / 2); canvas.DrawText("SkiaSharp", coord, paint); } } diff --git a/samples/Basic/WinUI/Desktop/SkiaSharpSample.Package/Package.appxmanifest b/samples/Basic/WinUI/Msix/SkiaSharpSample/Package.appxmanifest similarity index 100% rename from samples/Basic/WinUI/Desktop/SkiaSharpSample.Package/Package.appxmanifest rename to samples/Basic/WinUI/Msix/SkiaSharpSample/Package.appxmanifest diff --git a/samples/Basic/WinUI/Msix/SkiaSharpSample/Properties/launchSettings.json b/samples/Basic/WinUI/Msix/SkiaSharpSample/Properties/launchSettings.json new file mode 100644 index 0000000000..af97d49d15 --- /dev/null +++ b/samples/Basic/WinUI/Msix/SkiaSharpSample/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Windows Machine": { + "commandName": "MsixPackage", + "nativeDebugging": true + } + } +} \ No newline at end of file diff --git a/samples/Basic/WinUI/Msix/SkiaSharpSample/SkiaSharpSample.csproj b/samples/Basic/WinUI/Msix/SkiaSharpSample/SkiaSharpSample.csproj new file mode 100644 index 0000000000..8f982cb11b --- /dev/null +++ b/samples/Basic/WinUI/Msix/SkiaSharpSample/SkiaSharpSample.csproj @@ -0,0 +1,39 @@ + + + + WinExe + net5.0-windows10.0.19041.0 + 10.0.17763.0 + SkiaSharpSample + app.manifest + true + win10-x86;win10-x64;win10-arm64 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/Basic/WinUI/Desktop/SkiaSharpSample/app.manifest b/samples/Basic/WinUI/Msix/SkiaSharpSample/app.manifest similarity index 100% rename from samples/Basic/WinUI/Desktop/SkiaSharpSample/app.manifest rename to samples/Basic/WinUI/Msix/SkiaSharpSample/app.manifest diff --git a/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/LockScreenLogo.scale-200.png b/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/LockScreenLogo.scale-200.png new file mode 100644 index 0000000000..735f57adb5 Binary files /dev/null and b/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/LockScreenLogo.scale-200.png differ diff --git a/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/SplashScreen.scale-200.png b/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/SplashScreen.scale-200.png new file mode 100644 index 0000000000..023e7f1fed Binary files /dev/null and b/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/SplashScreen.scale-200.png differ diff --git a/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/Square150x150Logo.scale-200.png b/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/Square150x150Logo.scale-200.png new file mode 100644 index 0000000000..af49fec1a5 Binary files /dev/null and b/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/Square150x150Logo.scale-200.png differ diff --git a/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/Square44x44Logo.scale-200.png b/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/Square44x44Logo.scale-200.png new file mode 100644 index 0000000000..ce342a2ec8 Binary files /dev/null and b/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/Square44x44Logo.scale-200.png differ diff --git a/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/Square44x44Logo.targetsize-24_altform-unplated.png b/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 0000000000..f6c02ce97e Binary files /dev/null and b/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/Square44x44Logo.targetsize-24_altform-unplated.png differ diff --git a/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/StoreLogo.png b/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/StoreLogo.png new file mode 100644 index 0000000000..7385b56c0e Binary files /dev/null and b/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/StoreLogo.png differ diff --git a/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/Wide310x150Logo.scale-200.png b/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/Wide310x150Logo.scale-200.png new file mode 100644 index 0000000000..288995b397 Binary files /dev/null and b/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Images/Wide310x150Logo.scale-200.png differ diff --git a/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Package.appxmanifest b/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Package.appxmanifest new file mode 100644 index 0000000000..6a45ae6324 --- /dev/null +++ b/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/Package.appxmanifest @@ -0,0 +1,48 @@ + + + + + + + + SkiaSharpSample + matthew + Images\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/Basic/WinUI/Desktop/SkiaSharpSample.Package/SkiaSharpSample.Package.wapproj b/samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/SkiaSharpSample.Package.wapproj similarity index 100% rename from samples/Basic/WinUI/Desktop/SkiaSharpSample.Package/SkiaSharpSample.Package.wapproj rename to samples/Basic/WinUI/WapProj/SkiaSharpSample.Package/SkiaSharpSample.Package.wapproj diff --git a/samples/Basic/WinUI/Desktop/SkiaSharpSample.sln b/samples/Basic/WinUI/WapProj/SkiaSharpSample.sln similarity index 100% rename from samples/Basic/WinUI/Desktop/SkiaSharpSample.sln rename to samples/Basic/WinUI/WapProj/SkiaSharpSample.sln diff --git a/samples/Basic/WinUI/WapProj/SkiaSharpSample/App.xaml b/samples/Basic/WinUI/WapProj/SkiaSharpSample/App.xaml new file mode 100644 index 0000000000..4ef7c6d3af --- /dev/null +++ b/samples/Basic/WinUI/WapProj/SkiaSharpSample/App.xaml @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/samples/Basic/WinUI/WapProj/SkiaSharpSample/App.xaml.cs b/samples/Basic/WinUI/WapProj/SkiaSharpSample/App.xaml.cs new file mode 100644 index 0000000000..bd738d2ee9 --- /dev/null +++ b/samples/Basic/WinUI/WapProj/SkiaSharpSample/App.xaml.cs @@ -0,0 +1,20 @@ +using Microsoft.UI.Xaml; + +namespace SkiaSharpSample +{ + public partial class App : Application + { + private Window window; + + public App() + { + InitializeComponent(); + } + + protected override void OnLaunched(LaunchActivatedEventArgs args) + { + window = new MainWindow(); + window.Activate(); + } + } +} diff --git a/samples/Basic/WinUI/WapProj/SkiaSharpSample/MainWindow.xaml b/samples/Basic/WinUI/WapProj/SkiaSharpSample/MainWindow.xaml new file mode 100644 index 0000000000..02b9c81e48 --- /dev/null +++ b/samples/Basic/WinUI/WapProj/SkiaSharpSample/MainWindow.xaml @@ -0,0 +1,13 @@ + + + + + diff --git a/samples/Basic/WinUI/WapProj/SkiaSharpSample/MainWindow.xaml.cs b/samples/Basic/WinUI/WapProj/SkiaSharpSample/MainWindow.xaml.cs new file mode 100644 index 0000000000..384df70201 --- /dev/null +++ b/samples/Basic/WinUI/WapProj/SkiaSharpSample/MainWindow.xaml.cs @@ -0,0 +1,35 @@ +using Microsoft.UI.Xaml; +using SkiaSharp; +using SkiaSharp.Views.Windows; + +namespace SkiaSharpSample +{ + public sealed partial class MainWindow : Window + { + public MainWindow() + { + InitializeComponent(); + } + + private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) + { + // the the canvas and properties + var canvas = e.Surface.Canvas; + + // make sure the canvas is blank + canvas.Clear(SKColors.White); + + // draw some text + var paint = new SKPaint + { + Color = SKColors.Black, + IsAntialias = true, + Style = SKPaintStyle.Fill, + TextAlign = SKTextAlign.Center, + TextSize = 24 + }; + var coord = new SKPoint(e.Info.Width / 2, (e.Info.Height + paint.TextSize) / 2); + canvas.DrawText("SkiaSharp", coord, paint); + } + } +} diff --git a/samples/Basic/WinUI/Desktop/SkiaSharpSample/SkiaSharpSample.csproj b/samples/Basic/WinUI/WapProj/SkiaSharpSample/SkiaSharpSample.csproj similarity index 100% rename from samples/Basic/WinUI/Desktop/SkiaSharpSample/SkiaSharpSample.csproj rename to samples/Basic/WinUI/WapProj/SkiaSharpSample/SkiaSharpSample.csproj diff --git a/samples/Basic/WinUI/WapProj/SkiaSharpSample/app.manifest b/samples/Basic/WinUI/WapProj/SkiaSharpSample/app.manifest new file mode 100644 index 0000000000..3b144ccbc6 --- /dev/null +++ b/samples/Basic/WinUI/WapProj/SkiaSharpSample/app.manifest @@ -0,0 +1,15 @@ + + + + + + + + true/PM + PerMonitorV2, PerMonitor + + + diff --git a/samples/Basic/Xamarin.Forms/SkiaSharpSample/MainPage.xaml b/samples/Basic/Xamarin.Forms/SkiaSharpSample/MainPage.xaml index 927b86c405..9863bc0695 100644 --- a/samples/Basic/Xamarin.Forms/SkiaSharpSample/MainPage.xaml +++ b/samples/Basic/Xamarin.Forms/SkiaSharpSample/MainPage.xaml @@ -5,6 +5,8 @@ x:Class="SkiaSharpSample.MainPage" Title="SkiaSharp"> - + \ No newline at end of file diff --git a/samples/Basic/Xamarin.Forms/SkiaSharpSample/MainPage.xaml.cs b/samples/Basic/Xamarin.Forms/SkiaSharpSample/MainPage.xaml.cs index e4de500285..ec28197732 100644 --- a/samples/Basic/Xamarin.Forms/SkiaSharpSample/MainPage.xaml.cs +++ b/samples/Basic/Xamarin.Forms/SkiaSharpSample/MainPage.xaml.cs @@ -7,27 +7,35 @@ namespace SkiaSharpSample { public partial class MainPage : ContentPage { + private SKPoint? touchLocation; + public MainPage() { InitializeComponent(); } + private void OnTouch(object sender, SKTouchEventArgs e) + { + if (e.InContact) + touchLocation = e.Location; + else + touchLocation = null; + + skiaView.InvalidateSurface(); + + e.Handled = true; + } + private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) { // the the canvas and properties var canvas = e.Surface.Canvas; - // get the screen density for scaling - var scale = (float)(e.Info.Width / skiaView.Width); - - // handle the device screen density - canvas.Scale(scale); - // make sure the canvas is blank canvas.Clear(SKColors.White); - // draw some text - var paint = new SKPaint + // decide what the text looks like + using var paint = new SKPaint { Color = SKColors.Black, IsAntialias = true, @@ -35,7 +43,13 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) TextAlign = SKTextAlign.Center, TextSize = 24 }; - var coord = new SKPoint((float)skiaView.Width / 2, ((float)skiaView.Height + paint.TextSize) / 2); + + // adjust the location based on the pointer + var coord = (touchLocation is SKPoint loc) + ? new SKPoint(loc.X, loc.Y) + : new SKPoint(e.Info.Width / 2, (e.Info.Height + paint.TextSize) / 2); + + // draw some text canvas.DrawText("SkiaSharp", coord, paint); } } diff --git a/samples/Basic/iOS/SkiaSharpSample/ViewController.cs b/samples/Basic/iOS/SkiaSharpSample/ViewController.cs index 3b812df25d..1759170dec 100644 --- a/samples/Basic/iOS/SkiaSharpSample/ViewController.cs +++ b/samples/Basic/iOS/SkiaSharpSample/ViewController.cs @@ -17,6 +17,7 @@ public override void ViewDidLoad() { base.ViewDidLoad(); + skiaView.IgnorePixelScaling = true; skiaView.PaintSurface += OnPaintSurface; } @@ -25,12 +26,6 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) // the the canvas and properties var canvas = e.Surface.Canvas; - // get the screen density for scaling - var scale = (float)skiaView.ContentScaleFactor; - - // handle the device screen density - canvas.Scale(scale); - // make sure the canvas is blank canvas.Clear(SKColors.White); @@ -43,7 +38,7 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) TextAlign = SKTextAlign.Center, TextSize = 24 }; - var coord = new SKPoint((float)skiaView.Bounds.Width / 2, ((float)skiaView.Bounds.Height + paint.TextSize) / 2); + var coord = new SKPoint(e.Info.Width / 2, (e.Info.Height + paint.TextSize) / 2); canvas.DrawText("SkiaSharp", coord, paint); } } diff --git a/samples/Basic/macOS/SkiaSharpSample/ViewController.cs b/samples/Basic/macOS/SkiaSharpSample/ViewController.cs index fa9add2e40..246172a85a 100644 --- a/samples/Basic/macOS/SkiaSharpSample/ViewController.cs +++ b/samples/Basic/macOS/SkiaSharpSample/ViewController.cs @@ -17,6 +17,7 @@ public override void ViewDidLoad() { base.ViewDidLoad(); + skiaView.IgnorePixelScaling = true; skiaView.PaintSurface += OnPaintSurface; } @@ -25,12 +26,6 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) // the the canvas and properties var canvas = e.Surface.Canvas; - // get the screen density for scaling - var scale = (float)skiaView.Window.BackingScaleFactor; - - // handle the device screen density - canvas.Scale(scale); - // make sure the canvas is blank canvas.Clear(SKColors.White); @@ -43,7 +38,7 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) TextAlign = SKTextAlign.Center, TextSize = 24 }; - var coord = new SKPoint((float)skiaView.Bounds.Width / 2, ((float)skiaView.Bounds.Height + paint.TextSize) / 2); + var coord = new SKPoint(e.Info.Width / 2, (e.Info.Height + paint.TextSize) / 2); canvas.DrawText("SkiaSharp", coord, paint); } } diff --git a/samples/Basic/tvOS/SkiaSharpSample/ViewController.cs b/samples/Basic/tvOS/SkiaSharpSample/ViewController.cs index 3c4a7a571b..7275b5b704 100644 --- a/samples/Basic/tvOS/SkiaSharpSample/ViewController.cs +++ b/samples/Basic/tvOS/SkiaSharpSample/ViewController.cs @@ -17,6 +17,7 @@ public override void ViewDidLoad() { base.ViewDidLoad(); + skiaView.IgnorePixelScaling = true; skiaView.PaintSurface += OnPaintSurface; } @@ -25,12 +26,6 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) // the the canvas and properties var canvas = e.Surface.Canvas; - // get the screen density for scaling - var scale = (float)skiaView.ContentScaleFactor; - - // handle the device screen density - canvas.Scale(scale); - // make sure the canvas is blank canvas.Clear(SKColors.White); @@ -43,7 +38,7 @@ private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e) TextAlign = SKTextAlign.Center, TextSize = 48 }; - var coord = new SKPoint((float)skiaView.Bounds.Width / 2, ((float)skiaView.Bounds.Height + paint.TextSize) / 2); + var coord = new SKPoint(e.Info.Width / 2, (e.Info.Height + paint.TextSize) / 2); canvas.DrawText("SkiaSharp", coord, paint); } } diff --git a/scripts/Docker/wasm/build-local.sh b/scripts/Docker/wasm/build-local.sh index b9076ca5db..92dd21978c 100644 --- a/scripts/Docker/wasm/build-local.sh +++ b/scripts/Docker/wasm/build-local.sh @@ -4,12 +4,17 @@ set -e DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" VERSION_ARGS="" +EMSCRIPTEN_VERSION=2.0.23 if [ "$1" ]; then VERSION_ARGS="--build-arg EMSCRIPTEN_VERSION=$1" + EMSCRIPTEN_VERSION=$1 fi (cd $DIR && docker build --tag skiasharp-wasm $VERSION_ARGS .) (cd $DIR/../../../ && \ docker run --rm --name skiasharp-wasm --volume $(pwd):/work skiasharp-wasm /bin/bash -c "\ dotnet tool restore && \ - dotnet cake --target=externals-wasm --emscriptenVersion=$1") + dotnet cake --target=externals-wasm --emscriptenVersion=$EMSCRIPTEN_VERSION") + +# sudo chown -R $(id -u):$(id -g) . +# (cd samples/Basic/Uno/SkiaSharpSample.Wasm/bin/Debug/netstandard2.0/dist && python3 server.py) diff --git a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Native.Shared/SKCanvasViewRendererBase.cs b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Native.Shared/SKCanvasViewRendererBase.cs index e4f9935e5f..cd29c8eb7a 100644 --- a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Native.Shared/SKCanvasViewRendererBase.cs +++ b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Native.Shared/SKCanvasViewRendererBase.cs @@ -273,7 +273,7 @@ private void OnPaintSurface(object sender, SKNativePaintSurfaceEventArgs e) var controller = Element as ISKCanvasViewController; // the control is being repainted, let the user know - controller?.OnPaintSurface(new SKPaintSurfaceEventArgs(e.Surface, e.Info)); + controller?.OnPaintSurface(new SKPaintSurfaceEventArgs(e.Surface, e.Info, e.RawInfo)); } private void OnSurfaceInvalidated(object sender, EventArgs eventArgs) diff --git a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Shared/SKPaintSurfaceEventArgs.cs b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Shared/SKPaintSurfaceEventArgs.cs index cec4788bfe..f82fde8693 100644 --- a/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Shared/SKPaintSurfaceEventArgs.cs +++ b/source/SkiaSharp.Views.Forms/SkiaSharp.Views.Forms.Shared/SKPaintSurfaceEventArgs.cs @@ -15,13 +15,21 @@ namespace SkiaSharp.Views.Forms public class SKPaintSurfaceEventArgs : EventArgs { public SKPaintSurfaceEventArgs(SKSurface surface, SKImageInfo info) + : this(surface, info, info) + { + } + + public SKPaintSurfaceEventArgs(SKSurface surface, SKImageInfo info, SKImageInfo rawInfo) { Surface = surface; Info = info; + RawInfo = rawInfo; } - public SKSurface Surface { get; private set; } + public SKSurface Surface { get; } + + public SKImageInfo Info { get; } - public SKImageInfo Info { get; private set; } + public SKImageInfo RawInfo { get; } } } diff --git a/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Android/SKXamlCanvas.Android.cs b/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Android/SKXamlCanvas.Android.cs index c2719d77d1..930f1066c0 100644 --- a/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Android/SKXamlCanvas.Android.cs +++ b/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Android/SKXamlCanvas.Android.cs @@ -18,33 +18,12 @@ public SKXamlCanvas() partial void DoUnloaded() => surfaceFactory.Dispose(); - private SKSize GetCanvasSize() => - surfaceFactory.Info.Size; - private void DoInvalidate() { - UpdateCanvasSize((int)ActualWidth, (int)ActualHeight); + surfaceFactory.UpdateCanvasSize((int)(ActualWidth * Dpi), (int)(ActualHeight * Dpi)); base.Invalidate(); } - private void UpdateCanvasSize(int w, int h) - { - if (designMode) - return; - - if (!IgnorePixelScaling) - { - var display = DisplayInformation.GetForCurrentView(); - var scale = display.LogicalDpi / 96.0f; - - surfaceFactory.UpdateCanvasSize((int)(w * scale), (int)(h * scale)); - } - else - { - surfaceFactory.UpdateCanvasSize(w, h); - } - } - protected override void OnDraw(Canvas canvas) { base.OnDraw(canvas); @@ -62,10 +41,25 @@ protected override void OnDraw(Canvas canvas) // create a skia surface var surface = surfaceFactory.CreateSurface(out var info); if (surface == null) + { + CanvasSize = SKSize.Empty; return; + } + + var userVisibleSize = IgnorePixelScaling + ? new SKSizeI((int)ActualWidth, (int)ActualHeight) + : info.Size; + CanvasSize = userVisibleSize; + + if (IgnorePixelScaling) + { + var skiaCanvas = surface.Canvas; + skiaCanvas.Scale((float)Dpi); + skiaCanvas.Save(); + } // draw using SkiaSharp - OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info)); + OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info.WithSize(userVisibleSize), info)); // draw the surface to the view surfaceFactory.DrawSurface(surface, canvas); diff --git a/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Mac/SKXamlCanvas.macOS.cs b/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Mac/SKXamlCanvas.macOS.cs index 19a31a54c3..b86d03b1a3 100644 --- a/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Mac/SKXamlCanvas.macOS.cs +++ b/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Mac/SKXamlCanvas.macOS.cs @@ -20,9 +20,6 @@ public SKXamlCanvas() partial void DoUnloaded() => drawable?.Dispose(); - private SKSize GetCanvasSize() => - drawable?.Info.Size ?? SKSize.Empty; - private void DoInvalidate() => NeedsDisplay = true; @@ -34,14 +31,30 @@ public override void DrawRect(CGRect dirtyRect) return; // create the skia context - using var surface = drawable.CreateSurface(Bounds, IgnorePixelScaling ? 1 : Window.BackingScaleFactor, out var info); + using var surface = drawable.CreateSurface(Bounds, Window.BackingScaleFactor, out var info); if (info.Width == 0 || info.Height == 0) + { + CanvasSize = SKSize.Empty; return; + } + + var userVisibleSize = IgnorePixelScaling + ? new SKSizeI((int)Bounds.Width, (int)Bounds.Height) + : info.Size; + + CanvasSize = userVisibleSize; + + if (IgnorePixelScaling) + { + var skiaCanvas = surface.Canvas; + skiaCanvas.Scale((float)Window.BackingScaleFactor); + skiaCanvas.Save(); + } using var ctx = NSGraphicsContext.CurrentContext.CGContext; // draw on the image using SKiaSharp - OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info)); + OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info.WithSize(userVisibleSize), info)); // draw the surface to the context drawable.DrawSurface(ctx, Bounds, info, surface); diff --git a/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Reference/SKXamlCanvas.Reference.cs b/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Reference/SKXamlCanvas.Reference.cs index 9c0ecdf832..ddb5974b16 100644 --- a/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Reference/SKXamlCanvas.Reference.cs +++ b/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Reference/SKXamlCanvas.Reference.cs @@ -13,8 +13,6 @@ public SKXamlCanvas() partial void DoUnloaded() => throw new NotImplementedException(); - private SKSize GetCanvasSize() => throw new NotImplementedException(); - private void DoInvalidate() => throw new NotImplementedException(); } } diff --git a/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Skia/SKXamlCanvas.Skia.cs b/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Skia/SKXamlCanvas.Skia.cs index 0a5711d5eb..dae8a64b3d 100644 --- a/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Skia/SKXamlCanvas.Skia.cs +++ b/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Skia/SKXamlCanvas.Skia.cs @@ -23,9 +23,6 @@ public SKXamlCanvas() partial void DoUnloaded() => FreeBitmap(); - private SKSize GetCanvasSize() => - new SKSize(pixelWidth, pixelHeight); - private void DoInvalidate() { if (designMode) @@ -35,13 +32,26 @@ private void DoInvalidate() return; if (ActualWidth <= 0 || ActualHeight <= 0) + { + CanvasSize = SKSize.Empty; return; + } - var info = CreateBitmap(); + var info = CreateBitmap(out var unscaledSize, out var dpi); using (var surface = SKSurface.Create(info, pixelsHandle.AddrOfPinnedObject(), info.RowBytes)) { - OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info)); + var userVisibleSize = IgnorePixelScaling ? unscaledSize : info.Size; + CanvasSize = userVisibleSize; + + if (IgnorePixelScaling) + { + var canvas = surface.Canvas; + canvas.Scale(dpi); + canvas.Save(); + } + + OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info.WithSize(userVisibleSize), info)); } // This implementation is not fast enough, and providing the original pixel buffer @@ -57,29 +67,9 @@ private void DoInvalidate() bitmap.Invalidate(); } - private SKSizeI CreateSize() + private SKImageInfo CreateBitmap(out SKSizeI unscaledSize, out float dpi) { - var w = ActualWidth; - var h = ActualHeight; - - if (!IsPositive(w) || !IsPositive(h)) - return SKSizeI.Empty; - - if (IgnorePixelScaling) - return new SKSizeI((int)w, (int)h); - - var dpi = Dpi; - return new SKSizeI((int)(w * dpi), (int)(h * dpi)); - - static bool IsPositive(double value) - { - return !double.IsNaN(value) && !double.IsInfinity(value) && value > 0; - } - } - - private SKImageInfo CreateBitmap() - { - var size = CreateSize(); + var size = CreateSize(out unscaledSize, out dpi); var info = new SKImageInfo(size.Width, size.Height, SKImageInfo.PlatformColorType, SKAlphaType.Premul); if (bitmap?.PixelWidth != info.Width || bitmap?.PixelHeight != info.Height) @@ -94,19 +84,9 @@ private SKImageInfo CreateBitmap() ImageSource = bitmap, AlignmentX = AlignmentX.Left, AlignmentY = AlignmentY.Top, - Stretch = Stretch.None + Stretch = Stretch.Fill }; - if (!IgnorePixelScaling) - { - var scale = 1.0 / Dpi; - brush.Transform = new ScaleTransform - { - ScaleX = scale, - ScaleY = scale - }; - } - Background = brush; } diff --git a/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Wasm/SKXamlCanvas.Wasm.cs b/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Wasm/SKXamlCanvas.Wasm.cs index 01c8968c27..6bff1829db 100644 --- a/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Wasm/SKXamlCanvas.Wasm.cs +++ b/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.Wasm/SKXamlCanvas.Wasm.cs @@ -22,9 +22,6 @@ public SKXamlCanvas() partial void DoUnloaded() => FreeBitmap(); - private SKSize GetCanvasSize() => - new SKSize(pixelWidth, pixelHeight); - private void DoInvalidate() { if (designMode) @@ -34,33 +31,36 @@ private void DoInvalidate() return; if (ActualWidth <= 0 || ActualHeight <= 0) - return; - - int width, height; - if (IgnorePixelScaling) - { - width = (int)ActualWidth; - height = (int)ActualHeight; - } - else { - width = (int)(ActualWidth * Dpi); - height = (int)(ActualHeight * Dpi); + CanvasSize = SKSize.Empty; + return; } - var info = new SKImageInfo(width, height, SKImageInfo.PlatformColorType, SKAlphaType.Opaque); - CreateBitmap(info); + var info = CreateBitmap(out var unscaledSize, out var dpi); using (var surface = SKSurface.Create(info, pixelsHandle.AddrOfPinnedObject(), info.RowBytes)) { - OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info)); + var userVisibleSize = IgnorePixelScaling ? unscaledSize : info.Size; + CanvasSize = userVisibleSize; + + if (IgnorePixelScaling) + { + var canvas = surface.Canvas; + canvas.Scale(dpi); + canvas.Save(); + } + + OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info.WithSize(userVisibleSize), info)); } WebAssemblyRuntime.InvokeJS($"SkiaSharp.Views.UWP.SKXamlCanvas.invalidateCanvas({pixelsHandle.AddrOfPinnedObject()}, \"{this.GetHtmlId()}\", {info.Width}, {pixelHeight});"); } - private unsafe void CreateBitmap(SKImageInfo info) + private SKImageInfo CreateBitmap(out SKSizeI unscaledSize, out float dpi) { + var size = CreateSize(out unscaledSize, out dpi); + var info = new SKImageInfo(size.Width, size.Height, SKImageInfo.PlatformColorType, SKAlphaType.Opaque); + if (pixels == null || pixelWidth != info.Width || pixelHeight != info.Height) { FreeBitmap(); @@ -70,6 +70,8 @@ private unsafe void CreateBitmap(SKImageInfo info) pixelWidth = info.Width; pixelHeight = info.Height; } + + return info; } private void FreeBitmap() diff --git a/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.iOS/SKXamlCanvas.iOS.cs b/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.iOS/SKXamlCanvas.iOS.cs index f28880a582..13e120cb88 100644 --- a/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.iOS/SKXamlCanvas.iOS.cs +++ b/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno.iOS/SKXamlCanvas.iOS.cs @@ -20,9 +20,6 @@ public SKXamlCanvas() partial void DoUnloaded() => drawable?.Dispose(); - private SKSize GetCanvasSize() => - drawable?.Info.Size ?? SKSize.Empty; - private void DoInvalidate() => SetNeedsDisplay(); @@ -34,14 +31,30 @@ public override void Draw(CGRect dirtyRect) return; // create the skia context - using var surface = drawable.CreateSurface(Bounds, IgnorePixelScaling ? 1 : ContentScaleFactor, out var info); + using var surface = drawable.CreateSurface(Bounds, ContentScaleFactor, out var info); if (info.Width == 0 || info.Height == 0) + { + CanvasSize = SKSize.Empty; return; + } + + var userVisibleSize = IgnorePixelScaling + ? new SKSizeI((int)Bounds.Width, (int)Bounds.Height) + : info.Size; + + CanvasSize = userVisibleSize; + + if (IgnorePixelScaling) + { + var skiaCanvas = surface.Canvas; + skiaCanvas.Scale((float)ContentScaleFactor); + skiaCanvas.Save(); + } using var ctx = UIGraphics.GetCurrentContext(); // draw on the image using SKiaSharp - OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info)); + OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info.WithSize(userVisibleSize), info)); // draw the surface to the context drawable.DrawSurface(ctx, Bounds, info, surface); diff --git a/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno/SKXamlCanvas.cs b/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno/SKXamlCanvas.cs index f7ecedd183..6d8855ede8 100644 --- a/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno/SKXamlCanvas.cs +++ b/source/SkiaSharp.Views.Uno/SkiaSharp.Views.Uno/SKXamlCanvas.cs @@ -10,6 +10,8 @@ namespace SkiaSharp.Views.UWP { public partial class SKXamlCanvas : Canvas { + private const float DpiBase = 96.0f; + private static readonly DependencyProperty ProxyVisibilityProperty = DependencyProperty.Register( "ProxyVisibility", @@ -45,7 +47,7 @@ private void Initialize() SetBinding(ProxyVisibilityProperty, binding); } - public SKSize CanvasSize => GetCanvasSize(); + public SKSize CanvasSize { get; private set; } public bool IgnorePixelScaling { @@ -77,7 +79,7 @@ private static void OnVisibilityChanged(DependencyObject d, DependencyPropertyCh private void OnDpiChanged(DisplayInformation sender, object args = null) { - Dpi = sender.LogicalDpi / 96.0f; + Dpi = sender.LogicalDpi / DpiBase; Invalidate(); } @@ -123,5 +125,26 @@ public new async void Invalidate() partial void DoLoaded(); partial void DoUnloaded(); + + private SKSizeI CreateSize(out SKSizeI unscaledSize, out float dpi) + { + unscaledSize = SKSizeI.Empty; + dpi = (float)Dpi; + + var w = ActualWidth; + var h = ActualHeight; + + if (!IsPositive(w) || !IsPositive(h)) + return SKSizeI.Empty; + + unscaledSize = new SKSizeI((int)w, (int)h); + return new SKSizeI((int)(w * dpi), (int)(h * dpi)); + + static bool IsPositive(double value) + { + return !double.IsNaN(value) && !double.IsInfinity(value) && value > 0; + } + } + } } diff --git a/source/SkiaSharp.Views/SkiaSharp.Views.Android/Resources/values/attrs.xml b/source/SkiaSharp.Views/SkiaSharp.Views.Android/Resources/values/attrs.xml new file mode 100644 index 0000000000..8631a9be33 --- /dev/null +++ b/source/SkiaSharp.Views/SkiaSharp.Views.Android/Resources/values/attrs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/source/SkiaSharp.Views/SkiaSharp.Views.Android/SKCanvasView.cs b/source/SkiaSharp.Views/SkiaSharp.Views.Android/SKCanvasView.cs index 6939ebae13..df5da61680 100644 --- a/source/SkiaSharp.Views/SkiaSharp.Views.Android/SKCanvasView.cs +++ b/source/SkiaSharp.Views/SkiaSharp.Views.Android/SKCanvasView.cs @@ -13,6 +13,7 @@ public class SKCanvasView : View private bool ignorePixelScaling; private bool designMode; private SurfaceFactory surfaceFactory; + private float density; public SKCanvasView(Context context) : base(context) @@ -23,13 +24,13 @@ public SKCanvasView(Context context) public SKCanvasView(Context context, IAttributeSet attrs) : base(context, attrs) { - Initialize(); + Initialize(attrs); } public SKCanvasView(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr) { - Initialize(); + Initialize(attrs); } protected SKCanvasView(IntPtr javaReference, JniHandleOwnership transfer) @@ -38,21 +39,37 @@ protected SKCanvasView(IntPtr javaReference, JniHandleOwnership transfer) Initialize(); } - private void Initialize() + private void Initialize(IAttributeSet attrs = null) { designMode = !Extensions.IsValidEnvironment; surfaceFactory = new SurfaceFactory(); + density = Resources.DisplayMetrics.Density; + + if (attrs != null) + { + using var a = Context.ObtainStyledAttributes(attrs, Resource.Styleable.SKCanvasView); + + var N = a.IndexCount; + for (var i = 0; i < N; ++i) + { + var attr = a.GetIndex(i); + if (attr == Resource.Styleable.SKCanvasView_ignorePixelScaling) + IgnorePixelScaling = a.GetBoolean(attr, false); + } + + a.Recycle(); + } } - public SKSize CanvasSize => surfaceFactory.Info.Size; + public SKSize CanvasSize { get; private set; } public bool IgnorePixelScaling { - get { return ignorePixelScaling; } + get => ignorePixelScaling; set { ignorePixelScaling = value; - UpdateCanvasSize(Width, Height); + surfaceFactory.UpdateCanvasSize(Width, Height); Invalidate(); } } @@ -74,10 +91,26 @@ protected override void OnDraw(Canvas canvas) // create a skia surface var surface = surfaceFactory.CreateSurface(out var info); if (surface == null) + { + CanvasSize = SKSize.Empty; return; + } + + var userVisibleSize = IgnorePixelScaling + ? new SKSizeI((int)(info.Width / density), (int)(info.Height / density)) + : info.Size; + + CanvasSize = userVisibleSize; + + if (IgnorePixelScaling) + { + var skiaCanvas = surface.Canvas; + skiaCanvas.Scale(density); + skiaCanvas.Save(); + } // draw using SkiaSharp - OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info)); + OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info.WithSize(userVisibleSize), info)); #pragma warning disable CS0618 // Type or member is obsolete OnDraw(surface, info); #pragma warning restore CS0618 // Type or member is obsolete @@ -91,7 +124,7 @@ protected override void OnSizeChanged(int w, int h, int oldw, int oldh) base.OnSizeChanged(w, h, oldw, oldh); // update the info with the new sizes - UpdateCanvasSize(w, h); + surfaceFactory.UpdateCanvasSize(w, h); } public event EventHandler PaintSurface; @@ -118,7 +151,7 @@ protected override void OnAttachedToWindow() { base.OnAttachedToWindow(); - UpdateCanvasSize(Width, Height); + surfaceFactory.UpdateCanvasSize(Width, Height); Invalidate(); } @@ -128,8 +161,5 @@ protected override void Dispose(bool disposing) base.Dispose(disposing); } - - private void UpdateCanvasSize(int w, int h) => - surfaceFactory.UpdateCanvasSize(w, h, IgnorePixelScaling ? Resources.DisplayMetrics.Density : 1); } } diff --git a/source/SkiaSharp.Views/SkiaSharp.Views.Android/SkiaSharp.Views.Android.csproj b/source/SkiaSharp.Views/SkiaSharp.Views.Android/SkiaSharp.Views.Android.csproj index e97c291059..0eb6e9feea 100644 --- a/source/SkiaSharp.Views/SkiaSharp.Views.Android/SkiaSharp.Views.Android.csproj +++ b/source/SkiaSharp.Views/SkiaSharp.Views.Android/SkiaSharp.Views.Android.csproj @@ -12,4 +12,7 @@ + + + \ No newline at end of file diff --git a/source/SkiaSharp.Views/SkiaSharp.Views.Apple/SKCanvasLayer.cs b/source/SkiaSharp.Views/SkiaSharp.Views.Apple/SKCanvasLayer.cs index a895bd8bf6..51642e3dc1 100644 --- a/source/SkiaSharp.Views/SkiaSharp.Views.Apple/SKCanvasLayer.cs +++ b/source/SkiaSharp.Views/SkiaSharp.Views.Apple/SKCanvasLayer.cs @@ -30,11 +30,11 @@ public SKCanvasLayer() [Obsolete("Use PaintSurface instead.")] public ISKCanvasLayerDelegate SKDelegate { get; set; } - public SKSize CanvasSize => drawable.Info.Size; + public SKSize CanvasSize { get; private set; } public bool IgnorePixelScaling { - get { return ignorePixelScaling; } + get => ignorePixelScaling; set { ignorePixelScaling = value; @@ -47,13 +47,29 @@ public override void DrawInContext(CGContext ctx) base.DrawInContext(ctx); // create the skia context - using (var surface = drawable.CreateSurface(Bounds, IgnorePixelScaling ? 1 : ContentsScale, out var info)) + using (var surface = drawable.CreateSurface(Bounds, ContentsScale, out var info)) { if (info.Width == 0 || info.Height == 0) + { + CanvasSize = SKSize.Empty; return; + } + + var userVisibleSize = IgnorePixelScaling + ? new SKSizeI((int)Bounds.Width, (int)Bounds.Height) + : info.Size; + + CanvasSize = userVisibleSize; + + if (IgnorePixelScaling) + { + var skiaCanvas = surface.Canvas; + skiaCanvas.Scale((float)ContentsScale); + skiaCanvas.Save(); + } // draw on the image using SKiaSharp - OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info)); + OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info.WithSize(userVisibleSize), info)); #pragma warning disable CS0618 // Type or member is obsolete DrawInSurface(surface, info); SKDelegate?.DrawInSurface(surface, info); diff --git a/source/SkiaSharp.Views/SkiaSharp.Views.AppleiOS/SKCanvasView.cs b/source/SkiaSharp.Views/SkiaSharp.Views.AppleiOS/SKCanvasView.cs index 7209ee81bf..750ab1c526 100644 --- a/source/SkiaSharp.Views/SkiaSharp.Views.AppleiOS/SKCanvasView.cs +++ b/source/SkiaSharp.Views/SkiaSharp.Views.AppleiOS/SKCanvasView.cs @@ -66,11 +66,11 @@ private void Initialize() drawable = new SKCGSurfaceFactory(); } - public SKSize CanvasSize => drawable?.Info.Size ?? SKSize.Empty; + public SKSize CanvasSize { get; private set; } public bool IgnorePixelScaling { - get { return ignorePixelScaling; } + get => ignorePixelScaling; set { ignorePixelScaling = value; @@ -86,15 +86,31 @@ public override void Draw(CGRect rect) return; // create the skia context - using (var surface = drawable.CreateSurface(Bounds, IgnorePixelScaling ? 1 : ContentScaleFactor, out var info)) + using (var surface = drawable.CreateSurface(Bounds, ContentScaleFactor, out var info)) { if (info.Width == 0 || info.Height == 0) + { + CanvasSize = SKSize.Empty; return; + } + + var userVisibleSize = IgnorePixelScaling + ? new SKSizeI((int)Bounds.Width, (int)Bounds.Height) + : info.Size; + + CanvasSize = userVisibleSize; + + if (IgnorePixelScaling) + { + var skiaCanvas = surface.Canvas; + skiaCanvas.Scale((float)ContentScaleFactor); + skiaCanvas.Save(); + } using (var ctx = UIGraphics.GetCurrentContext()) { // draw on the image using SKiaSharp - OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info)); + OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info.WithSize(userVisibleSize), info)); #pragma warning disable CS0618 // Type or member is obsolete DrawInSurface(surface, info); #pragma warning restore CS0618 // Type or member is obsolete diff --git a/source/SkiaSharp.Views/SkiaSharp.Views.Mac/SKCanvasView.cs b/source/SkiaSharp.Views/SkiaSharp.Views.Mac/SKCanvasView.cs index 6e900773ef..4c4456621f 100644 --- a/source/SkiaSharp.Views/SkiaSharp.Views.Mac/SKCanvasView.cs +++ b/source/SkiaSharp.Views/SkiaSharp.Views.Mac/SKCanvasView.cs @@ -43,11 +43,11 @@ private void Initialize() drawable = new SKCGSurfaceFactory(); } - public SKSize CanvasSize => drawable.Info.Size; + public SKSize CanvasSize { get; private set; } public bool IgnorePixelScaling { - get { return ignorePixelScaling; } + get => ignorePixelScaling; set { ignorePixelScaling = value; @@ -73,15 +73,31 @@ public override void DrawRect(CGRect dirtyRect) base.DrawRect(dirtyRect); // create the skia context - using (var surface = drawable.CreateSurface(Bounds, IgnorePixelScaling ? 1 : Window.BackingScaleFactor, out var info)) + using (var surface = drawable.CreateSurface(Bounds, Window.BackingScaleFactor, out var info)) { if (info.Width == 0 || info.Height == 0) + { + CanvasSize = SKSize.Empty; return; + } + + var userVisibleSize = IgnorePixelScaling + ? new SKSizeI((int)Bounds.Width, (int)Bounds.Height) + : info.Size; + + CanvasSize = userVisibleSize; + + if (IgnorePixelScaling) + { + var skiaCanvas = surface.Canvas; + skiaCanvas.Scale((float)Window.BackingScaleFactor); + skiaCanvas.Save(); + } using (var ctx = NSGraphicsContext.CurrentContext.CGContext) { // draw on the image using SKiaSharp - OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info)); + OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info.WithSize(userVisibleSize), info)); #pragma warning disable CS0618 // Type or member is obsolete DrawInSurface(surface, info); #pragma warning restore CS0618 // Type or member is obsolete diff --git a/source/SkiaSharp.Views/SkiaSharp.Views.Shared/SKPaintSurfaceEventArgs.cs b/source/SkiaSharp.Views/SkiaSharp.Views.Shared/SKPaintSurfaceEventArgs.cs index 835ef31fff..18fb260586 100644 --- a/source/SkiaSharp.Views/SkiaSharp.Views.Shared/SKPaintSurfaceEventArgs.cs +++ b/source/SkiaSharp.Views/SkiaSharp.Views.Shared/SKPaintSurfaceEventArgs.cs @@ -23,13 +23,21 @@ namespace SkiaSharp.Views.Windows public class SKPaintSurfaceEventArgs : EventArgs { public SKPaintSurfaceEventArgs(SKSurface surface, SKImageInfo info) + : this(surface, info, info) + { + } + + public SKPaintSurfaceEventArgs(SKSurface surface, SKImageInfo info, SKImageInfo rawInfo) { Surface = surface; Info = info; + RawInfo = rawInfo; } - public SKSurface Surface { get; private set; } + public SKSurface Surface { get; } + + public SKImageInfo Info { get; } - public SKImageInfo Info { get; private set; } + public SKImageInfo RawInfo { get; } } } diff --git a/source/SkiaSharp.Views/SkiaSharp.Views.Tizen/CustomRenderingView.cs b/source/SkiaSharp.Views/SkiaSharp.Views.Tizen/CustomRenderingView.cs index ccafd29804..528aea874c 100644 --- a/source/SkiaSharp.Views/SkiaSharp.Views.Tizen/CustomRenderingView.cs +++ b/source/SkiaSharp.Views/SkiaSharp.Views.Tizen/CustomRenderingView.cs @@ -61,6 +61,8 @@ protected virtual void DestroyNativeResources() protected abstract SKSizeI GetSurfaceSize(); + protected virtual SKSizeI GetRawSurfaceSize() => GetSurfaceSize(); + protected virtual void CreateDrawingSurface() { // empty on purpose @@ -113,7 +115,7 @@ protected void OnResized() // recreate the drawing surface to match the new size DestroyDrawingSurface(); - var size = GetSurfaceSize(); + var size = GetRawSurfaceSize(); Evas.evas_object_image_size_set(evasImage, size.Width, size.Height); CreateDrawingSurface(); diff --git a/source/SkiaSharp.Views/SkiaSharp.Views.Tizen/SKCanvasView.cs b/source/SkiaSharp.Views/SkiaSharp.Views.Tizen/SKCanvasView.cs index dfdcd7a5b8..1c2f608cda 100755 --- a/source/SkiaSharp.Views/SkiaSharp.Views.Tizen/SKCanvasView.cs +++ b/source/SkiaSharp.Views/SkiaSharp.Views.Tizen/SKCanvasView.cs @@ -8,6 +8,7 @@ public class SKCanvasView : CustomRenderingView { private bool ignorePixelScaling; private SKImageInfo info; + private SKSizeI canvasSize; public SKCanvasView(EvasObject parent) : base(parent) @@ -17,20 +18,23 @@ public SKCanvasView(EvasObject parent) public bool IgnorePixelScaling { - get { return ignorePixelScaling; } + get => ignorePixelScaling; set { if (ignorePixelScaling != value) { ignorePixelScaling = value; OnResized(); + Invalidate(); } } } public event EventHandler PaintSurface; - protected override SKSizeI GetSurfaceSize() => info.Size; + protected override SKSizeI GetSurfaceSize() => canvasSize; + + protected override SKSizeI GetRawSurfaceSize() => info.Size; protected virtual void OnDrawFrame(SKPaintSurfaceEventArgs e) { @@ -45,8 +49,15 @@ protected sealed override void OnDrawFrame() // draw directly into the EFL image data using (var surface = SKSurface.Create(info, Evas.evas_object_image_data_get(evasImage, true), info.RowBytes)) { + if (IgnorePixelScaling) + { + var skiaCanvas = surface.Canvas; + skiaCanvas.Scale((float)ScalingInfo.ScalingFactor); + skiaCanvas.Save(); + } + // draw using SkiaSharp - OnDrawFrame(new SKPaintSurfaceEventArgs(surface, info)); + OnDrawFrame(new SKPaintSurfaceEventArgs(surface, info.WithSize(canvasSize), info)); surface.Canvas.Flush(); } } @@ -56,15 +67,18 @@ protected sealed override bool UpdateSurfaceSize(Rect geometry) var w = info.Width; var h = info.Height; + info.Width = geometry.Width; + info.Height = geometry.Height; + if (IgnorePixelScaling) { - info.Width = (int)ScalingInfo.FromPixel(geometry.Width); - info.Height = (int)ScalingInfo.FromPixel(geometry.Height); + canvasSize.Width = (int)ScalingInfo.FromPixel(geometry.Width); + canvasSize.Height = (int)ScalingInfo.FromPixel(geometry.Height); } else { - info.Width = geometry.Width; - info.Height = geometry.Height; + canvasSize.Width = geometry.Width; + canvasSize.Height = geometry.Height; } return (w != info.Width || h != info.Height); diff --git a/source/SkiaSharp.Views/SkiaSharp.Views.Tizen/ScalingInfo.cs b/source/SkiaSharp.Views/SkiaSharp.Views.Tizen/ScalingInfo.cs index 95dcc29f04..b06517deef 100644 --- a/source/SkiaSharp.Views/SkiaSharp.Views.Tizen/ScalingInfo.cs +++ b/source/SkiaSharp.Views/SkiaSharp.Views.Tizen/ScalingInfo.cs @@ -23,14 +23,21 @@ public static class ScalingInfo // allows to convert pixels to Android-style device-independent pixels private static readonly Lazy scalingFactor = new Lazy(() => dpi.Value / 160.0); + private static double? scalingFactorOverride; + public static string Profile => profile.Value; public static int Dpi => dpi.Value; - public static double ScalingFactor => scalingFactor.Value; + public static double ScalingFactor => scalingFactorOverride ?? scalingFactor.Value; public static double FromPixel(double v) => v / ScalingFactor; public static double ToPixel(double v) => v * ScalingFactor; + + public static void SetScalingFactor(double? scalingFactor) + { + scalingFactorOverride = scalingFactor; + } } } diff --git a/source/SkiaSharp.Views/SkiaSharp.Views.UWP/SKXamlCanvas.cs b/source/SkiaSharp.Views/SkiaSharp.Views.UWP/SKXamlCanvas.cs index 80df1ac743..e6e4330aa1 100644 --- a/source/SkiaSharp.Views/SkiaSharp.Views.UWP/SKXamlCanvas.cs +++ b/source/SkiaSharp.Views/SkiaSharp.Views.UWP/SKXamlCanvas.cs @@ -26,6 +26,8 @@ namespace SkiaSharp.Views.UWP { public partial class SKXamlCanvas : Canvas { + private const float DpiBase = 96.0f; + private static readonly DependencyProperty ProxyVisibilityProperty = DependencyProperty.Register( "ProxyVisibility", @@ -65,7 +67,7 @@ public SKXamlCanvas() SetBinding(ProxyVisibilityProperty, binding); } - public SKSize CanvasSize => bitmap == null ? SKSize.Empty : new SKSize(bitmap.PixelWidth, bitmap.PixelHeight); + public SKSize CanvasSize { get; private set; } public bool IgnorePixelScaling { @@ -105,7 +107,7 @@ private void OnXamlRootChanged(XamlRoot xamlRoot = null, XamlRootChangedEventArg #else private void OnDpiChanged(DisplayInformation sender, object args = null) { - Dpi = sender.LogicalDpi / 96.0f; + Dpi = sender.LogicalDpi / DpiBase; Invalidate(); } #endif @@ -165,30 +167,43 @@ private void DoInvalidate() if (!isVisible) return; - var info = CreateBitmap(); + var info = CreateBitmap(out var unscaledSize, out var dpi); if (info.Width <= 0 || info.Height <= 0) + { + CanvasSize = SKSize.Empty; return; + } + + var userVisibleSize = IgnorePixelScaling ? unscaledSize : info.Size; + CanvasSize = userVisibleSize; using (var surface = SKSurface.Create(info, pixels, info.RowBytes)) { - OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info)); + if (IgnorePixelScaling) + { + var canvas = surface.Canvas; + canvas.Scale(dpi); + canvas.Save(); + } + + OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info.WithSize(userVisibleSize), info)); } bitmap.Invalidate(); } - private SKSizeI CreateSize() + private SKSizeI CreateSize(out SKSizeI unscaledSize, out float dpi) { + unscaledSize = SKSizeI.Empty; + dpi = (float)Dpi; + var w = ActualWidth; var h = ActualHeight; if (!IsPositive(w) || !IsPositive(h)) return SKSizeI.Empty; - if (IgnorePixelScaling) - return new SKSizeI((int)w, (int)h); - - var dpi = Dpi; + unscaledSize = new SKSizeI((int)w, (int)h); return new SKSizeI((int)(w * dpi), (int)(h * dpi)); static bool IsPositive(double value) @@ -197,9 +212,9 @@ static bool IsPositive(double value) } } - private SKImageInfo CreateBitmap() + private SKImageInfo CreateBitmap(out SKSizeI unscaledSize, out float dpi) { - var size = CreateSize(); + var size = CreateSize(out unscaledSize, out dpi); var info = new SKImageInfo(size.Width, size.Height, SKImageInfo.PlatformColorType, SKAlphaType.Premul); if (bitmap?.PixelWidth != info.Width || bitmap?.PixelHeight != info.Height) @@ -215,17 +230,8 @@ private SKImageInfo CreateBitmap() ImageSource = bitmap, AlignmentX = AlignmentX.Left, AlignmentY = AlignmentY.Top, - Stretch = Stretch.None + Stretch = Stretch.Fill }; - if (!IgnorePixelScaling) - { - var scale = 1.0 / Dpi; - brush.Transform = new ScaleTransform - { - ScaleX = scale, - ScaleY = scale - }; - } Background = brush; } diff --git a/source/SkiaSharp.Views/SkiaSharp.Views.WPF/SKElement.cs b/source/SkiaSharp.Views/SkiaSharp.Views.WPF/SKElement.cs index f09579e952..dffd1c153e 100644 --- a/source/SkiaSharp.Views/SkiaSharp.Views.WPF/SKElement.cs +++ b/source/SkiaSharp.Views/SkiaSharp.Views.WPF/SKElement.cs @@ -15,6 +15,8 @@ namespace SkiaSharp.Views.WPF [DefaultProperty("Name")] public class SKElement : FrameworkElement { + private const double BitmapDpi = 96.0; + private readonly bool designMode; private WriteableBitmap bitmap; @@ -25,15 +27,11 @@ public SKElement() designMode = DesignerProperties.GetIsInDesignMode(this); } - [Bindable(false)] - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - [EditorBrowsable(EditorBrowsableState.Never)] - public SKSize CanvasSize => bitmap == null ? SKSize.Empty : new SKSize(bitmap.PixelWidth, bitmap.PixelHeight); + public SKSize CanvasSize { get; private set; } public bool IgnorePixelScaling { - get { return ignorePixelScaling; } + get => ignorePixelScaling; set { ignorePixelScaling = value; @@ -54,7 +52,11 @@ protected override void OnRender(DrawingContext drawingContext) if (Visibility != Visibility.Visible || PresentationSource.FromVisual(this) == null) return; - var size = CreateSize(out var scaleX, out var scaleY); + var size = CreateSize(out var unscaledSize, out var scaleX, out var scaleY); + var userVisibleSize = IgnorePixelScaling ? unscaledSize : size; + + CanvasSize = userVisibleSize; + if (size.Width <= 0 || size.Height <= 0) return; @@ -63,14 +65,21 @@ protected override void OnRender(DrawingContext drawingContext) // reset the bitmap if the size has changed if (bitmap == null || info.Width != bitmap.PixelWidth || info.Height != bitmap.PixelHeight) { - bitmap = new WriteableBitmap(info.Width, size.Height, 96 * scaleX, 96 * scaleY, PixelFormats.Pbgra32, null); + bitmap = new WriteableBitmap(info.Width, size.Height, BitmapDpi * scaleX, BitmapDpi * scaleY, PixelFormats.Pbgra32, null); } // draw on the bitmap bitmap.Lock(); using (var surface = SKSurface.Create(info, bitmap.BackBuffer, bitmap.BackBufferStride)) { - OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info)); + if (IgnorePixelScaling) + { + var canvas = surface.Canvas; + canvas.Scale(scaleX, scaleY); + canvas.Save(); + } + + OnPaintSurface(new SKPaintSurfaceEventArgs(surface, info.WithSize(userVisibleSize), info)); } // draw the bitmap to the screen @@ -92,10 +101,11 @@ protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) InvalidateVisual(); } - private SKSizeI CreateSize(out double scaleX, out double scaleY) + private SKSizeI CreateSize(out SKSizeI unscaledSize, out float scaleX, out float scaleY) { - scaleX = 1.0; - scaleY = 1.0; + unscaledSize = SKSizeI.Empty; + scaleX = 1.0f; + scaleY = 1.0f; var w = ActualWidth; var h = ActualHeight; @@ -103,12 +113,11 @@ private SKSizeI CreateSize(out double scaleX, out double scaleY) if (!IsPositive(w) || !IsPositive(h)) return SKSizeI.Empty; - if (IgnorePixelScaling) - return new SKSizeI((int)w, (int)h); + unscaledSize = new SKSizeI((int)w, (int)h); var m = PresentationSource.FromVisual(this).CompositionTarget.TransformToDevice; - scaleX = m.M11; - scaleY = m.M22; + scaleX = (float)m.M11; + scaleY = (float)m.M22; return new SKSizeI((int)(w * scaleX), (int)(h * scaleY)); bool IsPositive(double value) diff --git a/source/SkiaSharp.Views/SkiaSharp.Views.WindowsForms/SKControl.cs b/source/SkiaSharp.Views/SkiaSharp.Views.WindowsForms/SKControl.cs index fe03b2ce9c..d3653ad1c3 100644 --- a/source/SkiaSharp.Views/SkiaSharp.Views.WindowsForms/SKControl.cs +++ b/source/SkiaSharp.Views/SkiaSharp.Views.WindowsForms/SKControl.cs @@ -22,10 +22,6 @@ public SKControl() designMode = DesignMode || LicenseManager.UsageMode == LicenseUsageMode.Designtime; } - [Bindable(false)] - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - [EditorBrowsable(EditorBrowsableState.Never)] public SKSize CanvasSize => bitmap == null ? SKSize.Empty : new SKSize(bitmap.Width, bitmap.Height); [Category("Appearance")] diff --git a/source/SkiaSharp.Views/SkiaSharp.Views.WindowsForms/SKGLControl.cs b/source/SkiaSharp.Views/SkiaSharp.Views.WindowsForms/SKGLControl.cs index 78255f66e4..7f7f6d8713 100644 --- a/source/SkiaSharp.Views/SkiaSharp.Views.WindowsForms/SKGLControl.cs +++ b/source/SkiaSharp.Views/SkiaSharp.Views.WindowsForms/SKGLControl.cs @@ -49,16 +49,8 @@ private void Initialize() ResizeRedraw = true; } - [Bindable(false)] - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - [EditorBrowsable(EditorBrowsableState.Never)] public SKSize CanvasSize => lastSize; - [Bindable(false)] - [Browsable(false)] - [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] - [EditorBrowsable(EditorBrowsableState.Never)] public GRContext GRContext => grContext; [Category("Appearance")] diff --git a/source/SkiaSharp.Views/SkiaSharp.Views/SkiaSharp.Views.csproj b/source/SkiaSharp.Views/SkiaSharp.Views/SkiaSharp.Views.csproj index 44e321423d..ac1c291923 100644 --- a/source/SkiaSharp.Views/SkiaSharp.Views/SkiaSharp.Views.csproj +++ b/source/SkiaSharp.Views/SkiaSharp.Views/SkiaSharp.Views.csproj @@ -41,6 +41,7 @@ + @@ -69,6 +70,7 @@ +