Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,8 @@ jobs:
- name: Restore
run: dotnet restore

- name: Build
run: dotnet build -c Release --no-restore -p:VersionSuffix="${{ env.VERSION_SUFFIX }}"

- name: Pack
run: dotnet pack -c Release --no-build -p:VersionSuffix="${{ env.VERSION_SUFFIX }}" -o artifacts/packages
run: dotnet pack -c Release --no-restore -p:VersionSuffix="${{ env.VERSION_SUFFIX }}" -o artifacts/packages

- name: Upload NuGet packages
uses: actions/upload-artifact@v4
Expand Down
5 changes: 1 addition & 4 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -126,11 +126,8 @@ jobs:
- name: Restore
run: dotnet restore

- name: Build
run: dotnet build -c Release --no-restore

- name: Pack
run: dotnet pack -c Release --no-build -o artifacts/packages
run: dotnet pack -c Release --no-restore -o artifacts/packages

- name: Upload NuGet packages
uses: actions/upload-artifact@v4
Expand Down
2 changes: 2 additions & 0 deletions Svg.Skia.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
<Project Path="src/Svg.Editor.Svg/Svg.Editor.Svg.csproj" />
<Project Path="src/Svg.CodeGen.Skia/Svg.CodeGen.Skia.csproj" />
<Project Path="src/Svg.Controls.Avalonia/Svg.Controls.Avalonia.csproj" />
<Project Path="src/Svg.Controls.Skia.Uno/Svg.Controls.Skia.Uno.csproj" />
<Project Path="src/Svg.Controls.Skia.Avalonia/Svg.Controls.Skia.Avalonia.csproj" />
<Project Path="src/Svg.Model/Svg.Model.csproj" />
<Project Path="src/Svg.Skia/Svg.Skia.csproj" />
Expand All @@ -87,6 +88,7 @@
<Project Path="tests/ShimSkiaSharp.UnitTests/ShimSkiaSharp.UnitTests.csproj" />
<Project Path="tests/Svg.Controls.Avalonia.UnitTests/Svg.Controls.Avalonia.UnitTests.csproj" />
<Project Path="tests/Svg.Controls.Skia.Avalonia.UnitTests/Svg.Controls.Skia.Avalonia.UnitTests.csproj" />
<Project Path="tests/Svg.Controls.Skia.Uno.UnitTests/Svg.Controls.Skia.Uno.UnitTests.csproj" />
<Project Path="tests/Svg.Editor.Skia.Avalonia.UnitTests/Svg.Editor.Skia.Avalonia.UnitTests.csproj" />
<Project Path="tests/Svg.Editor.Skia.UnitTests/Svg.Editor.Skia.UnitTests.csproj" />
<Project Path="tests/Svg.Editor.Svg.UnitTests/Svg.Editor.Svg.UnitTests.csproj" />
Expand Down
8 changes: 4 additions & 4 deletions build/SkiaSharp.Native.v3.props
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="SkiaSharp.NativeAssets.Linux" VersionOverride="3.119.0" />
<PackageReference Include="SkiaSharp.NativeAssets.Win32" VersionOverride="3.119.0" />
<PackageReference Include="SkiaSharp.NativeAssets.macOS" VersionOverride="3.119.0" />
<PackageReference Include="SkiaSharp.NativeAssets.WebAssembly" VersionOverride="3.119.0" />
<PackageReference Include="SkiaSharp.NativeAssets.Linux" VersionOverride="3.119.1" />
<PackageReference Include="SkiaSharp.NativeAssets.Win32" VersionOverride="3.119.1" />
<PackageReference Include="SkiaSharp.NativeAssets.macOS" VersionOverride="3.119.1" />
<PackageReference Include="SkiaSharp.NativeAssets.WebAssembly" VersionOverride="3.119.1" />
</ItemGroup>
</Project>
2 changes: 1 addition & 1 deletion build/SkiaSharp.v3.props
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="SkiaSharp" VersionOverride="3.119.0" />
<PackageReference Include="SkiaSharp" VersionOverride="3.119.1" />
</ItemGroup>
</Project>
3 changes: 3 additions & 0 deletions global.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,8 @@
"version": "10.0.100",
"rollForward": "latestMinor",
"allowPrerelease": true
},
"msbuild-sdks": {
"Uno.Sdk": "6.5.31"
}
}
11 changes: 11 additions & 0 deletions samples/UnoSvgSkiaSample/App.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Application x:Class="UnoSvgSkiaSample.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
38 changes: 38 additions & 0 deletions samples/UnoSvgSkiaSample/App.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Uno.Resizetizer;

namespace UnoSvgSkiaSample;

public sealed partial class App : Application
{
public App()
{
InitializeComponent();
}

private Window? MainWindow { get; set; }

protected override void OnLaunched(LaunchActivatedEventArgs args)
{
MainWindow = new Window();

if (MainWindow.Content is not Frame rootFrame)
{
rootFrame = new Frame();
MainWindow.Content = rootFrame;
rootFrame.NavigationFailed += OnNavigationFailed;
}

if (rootFrame.Content is null)
{
rootFrame.Navigate(typeof(MainPage), args.Arguments);
}

MainWindow.SetWindowIcon();
MainWindow.Activate();
}

private static void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
{
throw new InvalidOperationException($"Failed to load {e.SourcePageType.FullName}: {e.Exception}");
}
}
3 changes: 3 additions & 0 deletions samples/UnoSvgSkiaSample/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
global using Microsoft.UI.Xaml;
global using Microsoft.UI.Xaml.Controls;
global using Microsoft.UI.Xaml.Input;
104 changes: 104 additions & 0 deletions samples/UnoSvgSkiaSample/MainPage.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<Page x:Class="UnoSvgSkiaSample.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:svg="using:Uno.Svg.Skia"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<svg:SvgSource x:Key="TigerSource" Path="/Assets/__tiger.svg" />
</Page.Resources>

<ScrollViewer>
<StackPanel Spacing="20" Padding="24" MaxWidth="960">
<TextBlock Text="Svg.Controls.Skia.Uno"
FontSize="28"
FontWeight="SemiBold" />
<TextBlock Text="This sample mirrors the Avalonia SVG control API where it fits Uno, with direct SKCanvasElement rendering, reusable SvgSource resources, CSS restyling, hit testing, zoom, pan, wireframe, and filter toggles."
TextWrapping="WrapWholeWords" />

<Border Padding="16" BorderThickness="1" CornerRadius="12">
<StackPanel Spacing="12">
<TextBlock Text="Asset Load via Path" FontSize="18" FontWeight="SemiBold" />
<svg:Svg Path="/Assets/__tiger.svg"
Height="240"
Stretch="Uniform"
EnableCache="True" />
</StackPanel>
</Border>

<Border Padding="16" BorderThickness="1" CornerRadius="12">
<StackPanel Spacing="12">
<TextBlock Text="Inline SVG via Source" FontSize="18" FontWeight="SemiBold" />
<svg:Svg Source="{x:Bind InlineSvg}"
Height="140"
Stretch="Uniform" />
</StackPanel>
</Border>

<Border Padding="16" BorderThickness="1" CornerRadius="12">
<StackPanel Spacing="12">
<TextBlock Text="Reusable SvgSource Resource" FontSize="18" FontWeight="SemiBold" />
<svg:Svg SvgSource="{StaticResource TigerSource}"
Height="200"
Stretch="UniformToFill" />
</StackPanel>
</Border>

<Border Padding="16" BorderThickness="1" CornerRadius="12">
<StackPanel Spacing="12">
<TextBlock Text="Runtime CSS Restyling" FontSize="18" FontWeight="SemiBold" />
<svg:Svg x:Name="StyledSvg"
Source="{x:Bind StyledSvgMarkup}"
Height="180"
Stretch="Uniform" />
<StackPanel Orientation="Horizontal" Spacing="12">
<Button Content="Swap Theme" Click="OnSwapThemeClick" />
<TextBlock x:Name="CssStatusText"
VerticalAlignment="Center"
Text="Current theme: cobalt" />
</StackPanel>
</StackPanel>
</Border>

<Border Padding="16" BorderThickness="1" CornerRadius="12">
<StackPanel Spacing="12">
<TextBlock Text="Zoom, Pan, and Hit Testing" FontSize="18" FontWeight="SemiBold" />
<svg:Svg x:Name="InteractiveSvg"
Path="/Assets/__AJ_Digital_Camera.svg"
Height="260"
Stretch="Uniform"
PointerPressed="OnInteractiveSvgPointerPressed" />
<StackPanel Orientation="Horizontal" Spacing="8">
<Button Content="Zoom In" Click="OnZoomInClick" />
<Button Content="Zoom Out" Click="OnZoomOutClick" />
<Button Content="Pan Left" Click="OnPanLeftClick" />
<Button Content="Pan Right" Click="OnPanRightClick" />
<Button Content="Pan Up" Click="OnPanUpClick" />
<Button Content="Pan Down" Click="OnPanDownClick" />
<Button Content="Reset View" Click="OnResetViewClick" />
</StackPanel>
<TextBlock x:Name="HitTestStatusText"
Text="Tap the camera SVG to inspect hit-tested elements."
TextWrapping="WrapWholeWords" />
</StackPanel>
</Border>

<Border Padding="16" BorderThickness="1" CornerRadius="12">
<StackPanel Spacing="12">
<TextBlock Text="Wireframe and Filter Toggle" FontSize="18" FontWeight="SemiBold" />
<svg:Svg x:Name="FilterSvg"
Source="{x:Bind FilterSvgMarkup}"
Height="180"
Stretch="Uniform" />
<StackPanel Orientation="Horizontal" Spacing="18">
<CheckBox Content="Wireframe"
Checked="OnWireframeChanged"
Unchecked="OnWireframeChanged" />
<CheckBox Content="Disable Filters"
Checked="OnDisableFiltersChanged"
Unchecked="OnDisableFiltersChanged" />
</StackPanel>
</StackPanel>
</Border>
</StackPanel>
</ScrollViewer>
</Page>
116 changes: 116 additions & 0 deletions samples/UnoSvgSkiaSample/MainPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
using System.Linq;
using Svg;

namespace UnoSvgSkiaSample;

public sealed partial class MainPage : Page
{
private bool _useWarmTheme;

public MainPage()
{
InitializeComponent();
StyledSvg.CurrentCss = ColdCss;
}

public string InlineSvg =>
"""
<svg width="260" height="120" viewBox="0 0 260 120" xmlns="http://www.w3.org/2000/svg">
<rect x="8" y="8" width="244" height="104" rx="24" fill="#0f172a" />
<circle cx="56" cy="60" r="24" fill="#38bdf8" />
<path d="M96 82 L130 28 L164 82 Z" fill="#f59e0b" />
<rect x="182" y="32" width="42" height="56" rx="14" fill="#34d399" />
</svg>
""";

public string StyledSvgMarkup =>
"""
<svg width="220" height="180" viewBox="0 0 220 180" xmlns="http://www.w3.org/2000/svg">
<rect x="12" y="12" width="196" height="156" rx="26" fill="#f8fafc" />
<circle class="accent" cx="72" cy="88" r="34" />
<path class="outline" d="M120 128 L162 48 L186 128 Z" fill="none" />
<rect class="accent" x="122" y="62" width="44" height="18" rx="9" />
</svg>
""";

public string FilterSvgMarkup =>
"""
<svg width="260" height="160" viewBox="0 0 260 160" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="blurred-glow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="6" />
</filter>
</defs>
<rect x="12" y="12" width="236" height="136" rx="24" fill="#111827" />
<circle cx="86" cy="82" r="30" fill="#22c55e" filter="url(#blurred-glow)" />
<circle cx="86" cy="82" r="24" fill="#4ade80" />
<rect x="138" y="54" width="66" height="56" rx="18" fill="#f97316" filter="url(#blurred-glow)" />
<rect x="146" y="62" width="50" height="40" rx="14" fill="#fb923c" />
</svg>
""";

private const string ColdCss = ".accent { fill: #2563eb; } .outline { stroke: #0f172a; stroke-width: 4; }";
private const string WarmCss = ".accent { fill: #ef4444; } .outline { stroke: #7c2d12; stroke-width: 4; }";

private void OnSwapThemeClick(object sender, RoutedEventArgs e)
{
_useWarmTheme = !_useWarmTheme;
StyledSvg.CurrentCss = _useWarmTheme ? WarmCss : ColdCss;
CssStatusText.Text = $"Current theme: {(_useWarmTheme ? "ember" : "cobalt")}";
}

private void OnZoomInClick(object sender, RoutedEventArgs e)
{
InteractiveSvg.ZoomToPoint(InteractiveSvg.Zoom * 1.2, new Windows.Foundation.Point(200, 130));
}

private void OnZoomOutClick(object sender, RoutedEventArgs e)
{
InteractiveSvg.ZoomToPoint(InteractiveSvg.Zoom / 1.2, new Windows.Foundation.Point(200, 130));
}

private void OnPanLeftClick(object sender, RoutedEventArgs e) => InteractiveSvg.PanX -= 20;

private void OnPanRightClick(object sender, RoutedEventArgs e) => InteractiveSvg.PanX += 20;

private void OnPanUpClick(object sender, RoutedEventArgs e) => InteractiveSvg.PanY -= 20;

private void OnPanDownClick(object sender, RoutedEventArgs e) => InteractiveSvg.PanY += 20;

private void OnResetViewClick(object sender, RoutedEventArgs e)
{
InteractiveSvg.Zoom = 1.0;
InteractiveSvg.PanX = 0.0;
InteractiveSvg.PanY = 0.0;
HitTestStatusText.Text = "Tap the camera SVG to inspect hit-tested elements.";
}

private void OnInteractiveSvgPointerPressed(object sender, PointerRoutedEventArgs e)
{
var point = e.GetCurrentPoint(InteractiveSvg).Position;
var hits = InteractiveSvg.HitTestElements(point).ToArray();

if (hits.Length == 0)
{
HitTestStatusText.Text = $"No SVG elements hit at ({point.X:F0}, {point.Y:F0}).";
return;
}

var labels = hits
.Select(static element => !string.IsNullOrWhiteSpace(element.ID) ? $"#{element.ID}" : element.GetType().Name)
.Distinct(StringComparer.Ordinal)
.Take(3);

HitTestStatusText.Text = $"Hit {hits.Length} element(s): {string.Join(", ", labels)}";
}

private void OnWireframeChanged(object sender, RoutedEventArgs e)
{
FilterSvg.Wireframe = sender is CheckBox { IsChecked: true };
}

private void OnDisableFiltersChanged(object sender, RoutedEventArgs e)
{
FilterSvg.DisableFilters = sender is CheckBox { IsChecked: true };
}
}
31 changes: 31 additions & 0 deletions samples/UnoSvgSkiaSample/Package.appxmanifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<Package
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
IgnorableNamespaces="uap rescap">

<Identity />
<Properties />

<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17763.0" MaxVersionTested="10.0.26100.0" />
<TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.17763.0" MaxVersionTested="10.0.26100.0" />
</Dependencies>

<Resources>
<Resource Language="x-generate" />
</Resources>

<Applications>
<Application Id="App"
Executable="$targetnametoken$.exe"
EntryPoint="$targetentrypoint$">
<uap:VisualElements />
</Application>
</Applications>

<Capabilities>
<rescap:Capability Name="runFullTrust" />
</Capabilities>
</Package>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:allowBackup="true" android:supportsRtl="true"></application>
</manifest>
Loading
Loading