Skip to content
Draft
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
1 change: 1 addition & 0 deletions src/Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

<ItemGroup>
<PackageVersion Include="Avalonia" Version="$(AvaloniaVersion)" />
<PackageVersion Include="SkiaSharp" Version="3.119.0" />

<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
<PackageVersion Include="JetBrains.Annotations" Version="2024.3.0" />
Expand Down
1 change: 1 addition & 0 deletions src/IconPacks.Avalonia/IconPacks.Avalonia.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

<ItemGroup>
<PackageReference Include="Avalonia" />
<PackageReference Include="SkiaSharp" />
</ItemGroup>

<ItemGroup>
Expand Down
98 changes: 98 additions & 0 deletions src/IconPacks.Avalonia/PackIconControlDataFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Threading.Tasks;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using IconPacks.Avalonia.Core;
using IconPacks.Avalonia.BootstrapIcons;
using IconPacks.Avalonia.BoxIcons;
Expand Down Expand Up @@ -42,6 +45,7 @@
using IconPacks.Avalonia.VaadinIcons;
using IconPacks.Avalonia.WeatherIcons;
using IconPacks.Avalonia.Zondicons;
using SkiaSharp;

namespace IconPacks.Avalonia
{
Expand All @@ -57,6 +61,100 @@ static PackIconControlDataFactory()
DataIndex = new Lazy<ReadOnlyDictionary<Enum, string>>(() => new ReadOnlyDictionary<Enum, string>(GetAllIcons()));
}

public static string ProvideSvgPathData(Enum kind)
{
string data = null;
DataIndex.Value?.TryGetValue(kind, out data);

// For some icons we need to flip them
switch (kind)
{
case PackIconBootstrapIconsKind:
case PackIconBoxIconsKind:
case PackIconCodiconsKind:
case PackIconCooliconsKind:
case PackIconEvaIconsKind:
case PackIconFileIconsKind:
case PackIconFontaudioKind:
case PackIconFontistoKind:
case PackIconForkAwesomeKind:
case PackIconJamIconsKind:
case PackIconLucideKind:
case PackIconRPGAwesomeKind:
case PackIconTypiconsKind:
case PackIconVaadinIconsKind:
var skPath = SKPath.ParseSvgPathData(data);
skPath.Transform(SKMatrix.CreateScale(1,-1));
return skPath.ToSvgPathData();

default:
return data;
}
}

public static async Task<Bitmap> GetIconAsBitmapAsync(Enum kind, Color foreground, int width = 48, int height = 48)
{
try
{
await using var ms = new MemoryStream();

await Task.Run(() =>
{
var data = ProvideSvgPathData(kind);
var skPath = SKPath.ParseSvgPathData(data);
var originalBounds = skPath.Bounds;

switch (kind)
{
case PackIconFeatherIconsKind:
originalBounds.Inflate(2f, 2f);
break;
}

if (width < 0) width = (int)(Math.Ceiling(originalBounds.Width));
if (height < 0) height = (int)(Math.Ceiling(originalBounds.Height));

float scale = Math.Min(width / originalBounds.Width, height / originalBounds.Height);


skPath.Transform(SKMatrix.CreateScale(scale, scale));
skPath.Transform(SKMatrix.CreateTranslation(
- skPath.Bounds.Left + (width - skPath.Bounds.Width ) / 2,
- skPath.Bounds.Top + (height - skPath.Bounds.Height ) / 2 ));

var skBitmap = new SKBitmap(width, height, SKColorType.Bgra8888, SKAlphaType.Premul);

using var skCanvas = new SKCanvas(skBitmap);

using var skPaint = new SKPaint();
skPaint.IsAntialias = true;
skPaint.Color = new SKColor(foreground.ToUInt32());

switch (kind)
{
case PackIconFeatherIconsKind:
skPaint.IsStroke = true;
skPaint.StrokeCap = SKStrokeCap.Round;
skPaint.StrokeWidth = 2 * scale;
break;
}

skCanvas.DrawPath(skPath, skPaint);

skBitmap.Encode(ms, SKEncodedImageFormat.Png, 100);

ms.Seek(0, SeekOrigin.Begin);
});

return new Bitmap(ms);
}
catch (Exception e)
{
Console.WriteLine(e);
return null;
}
}

internal static IDictionary<Enum, string> GetAllIcons()
{
var allIcons = new ConcurrentDictionary<Enum, string>();
Expand Down