Skip to content

Commit

Permalink
Remove GDI+ & new QRCode Impl & Add Skia
Browse files Browse the repository at this point in the history
  • Loading branch information
AigioL committed Sep 16, 2021
1 parent f983569 commit 86088db
Show file tree
Hide file tree
Showing 15 changed files with 213 additions and 83 deletions.
2 changes: 2 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
<PackageVersion Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.1.1" />
<PackageVersion Include="Portable.BouncyCastle" Version="1.8.10" />
<PackageVersion Include="QRCoder" Version="1.4.1" />
<PackageVersion Include="Net.Codecrete.QrCodeGenerator" Version="2.0.0-rc.1" />
<PackageVersion Include="DnsClient" Version="1.5.0" />
<PackageVersion Include="Fleck" Version="1.2.0" />
<PackageVersion Include="Gameloop.Vdf" Version="0.6.1" />
Expand Down Expand Up @@ -118,6 +119,7 @@
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="5.0.9" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Tools" Version="5.0.9" />
<PackageVersion Include="Swashbuckle.AspNetCore" Version="6.2.1" />
<PackageVersion Include="SkiaSharp" Version="2.80.3" />
</ItemGroup>
<ItemGroup Condition=" $(DefineConstants.Contains('_HAVE_XF_')) ">
<PackageVersion Include="Xamarin.AndroidX.AppCompat" Version="1.2.0.7" />
Expand Down
1 change: 1 addition & 0 deletions README.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ Read what we [milestones](https://github.com/SteamTools-Team/SteamTools/mileston
* [AspNet.Security.OAuth.Providers](https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers)
* [ZXing.Net](https://github.com/micjahn/ZXing.Net)
* [QRCoder](https://github.com/codebude/QRCoder)
* [QR Code Generator for .NET](https://github.com/manuelbl/QrCodeGenerator)
* [React](https://github.com/facebook/react)
* [Ant Design](https://github.com/ant-design/ant-design)
* [Ant Design Blazor](https://github.com/ant-design-blazor/ant-design-blazor)
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ OS | Version | Architectures |
* [AspNet.Security.OAuth.Providers](https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers)
* [ZXing.Net](https://github.com/micjahn/ZXing.Net)
* [QRCoder](https://github.com/codebude/QRCoder)
* [QR Code Generator for .NET](https://github.com/manuelbl/QrCodeGenerator)
* [React](https://github.com/facebook/react)
* [Ant Design](https://github.com/ant-design/ant-design)
* [Ant Design Blazor](https://github.com/ant-design-blazor/ant-design-blazor)
Expand Down
2 changes: 1 addition & 1 deletion references/Titanium-Web-Proxy
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,31 @@ namespace System.Application.Services.Implementation
{
internal sealed class AvaloniaFontManagerImpl : FontManagerImpl
{
bool useGdiPlusFirst;
public AvaloniaFontManagerImpl(bool useGdiPlusFirst)
public static bool UseGdiPlusFirst { get; set; }

public AvaloniaFontManagerImpl(IDesktopPlatformService platformService) : base(platformService)
{
this.useGdiPlusFirst = useGdiPlusFirst;
}

public sealed override IReadOnlyCollection<KeyValuePair<string, string>> GetFonts()
{
IReadOnlyCollection<KeyValuePair<string, string>> fonts;

if (useGdiPlusFirst)
if (UseGdiPlusFirst)
{
try
{
fonts = IFontManager.GetFontsByGdiPlus();
var fonts = platformService.GetFontsByGdiPlus();
if (fonts.Any()) return fonts;
}
catch
{
useGdiPlusFirst = false;
return GetFonts();
}
UseGdiPlusFirst = false;
return GetFonts();
}
else
{
fonts = GetFontsByAvalonia();
return GetFontsByAvalonia();
}

return fonts;
}

static IReadOnlyCollection<KeyValuePair<string, string>> GetFontsByAvalonia()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ public static IServiceCollection TryAddFilePickerPlatformService(this IServiceCo

public static IServiceCollection AddFontManager(this IServiceCollection services, bool useGdiPlusFirst)
{
services.AddSingleton<IFontManager>(new AvaloniaFontManagerImpl(useGdiPlusFirst));
AvaloniaFontManagerImpl.UseGdiPlusFirst = useGdiPlusFirst;
services.AddSingleton<IFontManager, AvaloniaFontManagerImpl>();
return services;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
using System.Application.Models;
using System.Application.UI;
using System.Application.UI.Resx;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Text;
using System.IO;
using System.Linq;
using System.Management;
Expand Down Expand Up @@ -315,6 +318,16 @@ public bool SetAsSystemProxy(bool state, IPAddress? ip, int port)
}
return true;
}

public IReadOnlyCollection<KeyValuePair<string, string>> GetFontsByGdiPlus()
{
// https://docs.microsoft.com/zh-cn/typography/font-list
var culture = R.Culture;
InstalledFontCollection ifc = new();
var list = ifc.Families.Where(x => x.IsStyleAvailable(FontStyle.Regular)).Select(x => KeyValuePair.Create(x.GetName(culture.LCID), x.GetName(1033))).ToList();
list.Insert(0, IFontManager.Default);
return list;
}
}
}
#pragma warning restore CA1416 // 验证平台兼容性
2 changes: 1 addition & 1 deletion src/ST.Client.Desktop/ST.Client.Desktop.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
<PackageReference Include="StatefulModel.Standard" />
<!--<PackageReference Include="Titanium.Web.Proxy" />-->
<PackageReference Include="System.CommandLine" />
<PackageReference Include="System.Drawing.Common" />
<!--<PackageReference Include="System.Drawing.Common" />-->
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" />
</ItemGroup>

Expand Down
27 changes: 14 additions & 13 deletions src/ST.Client.Desktop/Services/IFontManager.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
using System.Application.UI.Resx;
using System.Collections.Generic;
#if !__MOBILE__
using System.Drawing;
using System.Drawing.Text;
using System.Linq;
using System.Runtime.Versioning;
#endif

namespace System.Application.Services
Expand All @@ -12,25 +10,28 @@ public interface IFontManager
{
public static IFontManager Instance => DI.Get<IFontManager>();

protected static KeyValuePair<string, string> Default { get; } = KeyValuePair.Create(AppResources.Default, "Default");
public static KeyValuePair<string, string> Default { get; } = KeyValuePair.Create(AppResources.Default, "Default");

IReadOnlyCollection<KeyValuePair<string, string>> GetFonts();
}

protected static IReadOnlyCollection<KeyValuePair<string, string>> GetFontsByGdiPlus()
{
partial interface
#if !__MOBILE__
// https://docs.microsoft.com/zh-cn/typography/font-list
var culture = R.Culture;
InstalledFontCollection ifc = new();
var list = ifc.Families.Where(x => x.IsStyleAvailable(FontStyle.Regular)).Select(x => KeyValuePair.Create(x.GetName(culture.LCID), x.GetName(1033))).ToList();
list.Insert(0, IFontManager.Default);
return list;
IDesktopPlatformService
#else
IMobilePlatformService
#endif
{
/// <summary>
/// 由 GDI+ 实现的获取当前系统字体数组,仅在 Windows 平台上实现,其他平台将返回空数组
/// </summary>
/// <returns></returns>
public IReadOnlyCollection<KeyValuePair<string, string>> GetFontsByGdiPlus()
{
// Common7\IDE\ReferenceAssemblies\Microsoft\Framework\MonoAndroid\v1.0\Facades\System.Drawing.Common.dll
// System.Drawing.Text.InstalledFontCollection
// throw new PlatformNotSupportedException();
return Array.Empty<KeyValuePair<string, string>>();
#endif
}
}
}
14 changes: 13 additions & 1 deletion src/ST.Client.Desktop/Services/Implementation/FontManagerImpl.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
using System.Collections.Generic;
#if !__MOBILE__
using IPlatformService2 = System.Application.Services.IDesktopPlatformService;
#else
using IPlatformService2 = System.Application.Services.IMobilePlatformService;
#endif

namespace System.Application.Services.Implementation
{
public class FontManagerImpl : IFontManager
{
protected readonly IPlatformService2 platformService;

public FontManagerImpl(IPlatformService2 platformService)
{
this.platformService = platformService;
}

public virtual IReadOnlyCollection<KeyValuePair<string, string>> GetFonts()
{
var fonts = IFontManager.GetFontsByGdiPlus();
var fonts = platformService.GetFontsByGdiPlus();
return fonts;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/ST.Client.Mobile/Services/IMobilePlatformService.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace System.Application.Services
{
public interface IMobilePlatformService : IPlatformService
public partial interface IMobilePlatformService : IPlatformService
{
protected new const string TAG = "MobilePlatformS";

Expand Down
3 changes: 2 additions & 1 deletion src/ST.Client/ST.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="QRCoder" />
<PackageReference Include="SkiaSharp" />
<PackageReference Include="Net.Codecrete.QrCodeGenerator" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* QR code generator library (.NET)
*
* Copyright (c) Manuel Bleichenbacher (MIT License)
* https://github.com/manuelbl/QrCodeGenerator
*
*/

using SkiaSharp;
using System;

namespace Net.Codecrete.QrCodeGenerator
{
public static class QrCodeBitmapExtensions
{
/// <inheritdoc cref="ToBitmap(QrCode, int, int)"/>
/// <param name="background">The background color.</param>
/// <param name="foreground">The foreground color.</param>
public static SKBitmap ToBitmap(this QrCode qrCode, int scale, int border, SKColor foreground, SKColor background)
{
// check arguments
if (scale <= 0)
{
throw new ArgumentOutOfRangeException(nameof(scale), "Value out of range");
}
if (border < 0)
{
throw new ArgumentOutOfRangeException(nameof(border), "Value out of range");
}

int size = qrCode.Size;
int dim = (size + border * 2) * scale;

if (dim > short.MaxValue)
{
throw new ArgumentOutOfRangeException(nameof(scale), "Scale or border too large");
}

// create bitmap
SKBitmap bitmap = new SKBitmap(dim, dim, SKColorType.Argb4444, SKAlphaType.Premul);

using (SKCanvas canvas = new SKCanvas(bitmap))
{
// draw background
using (SKPaint paint = new SKPaint { Color = background })
{
canvas.DrawRect(0, 0, dim, dim, paint);
}

// draw modules
using (SKPaint paint = new SKPaint { Color = foreground })
{
for (int y = 0; y < size; y++)
{
for (int x = 0; x < size; x++)
{
if (qrCode.GetModule(x, y))
{
canvas.DrawRect((x + border) * scale, (y + border) * scale, scale, scale, paint);
}
}
}
}
}

return bitmap;
}
}
}
32 changes: 32 additions & 0 deletions src/ST.Client/UI/QRCodeHelper.Net.Codecrete.QrCodeGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Net.Codecrete.QrCodeGenerator;
using SkiaSharp;
using System.IO;

namespace System.Application.UI
{
public static partial class QRCodeHelper
{
public static (QRCodeCreateResult result, Stream? stream, Exception? exception) Create(byte[] bytes, QrCode.Ecc? level = null)
{
level ??= QrCode.Ecc.Low;
try
{
var qrCode = QrCode.EncodeBinary(bytes, level); // Make the QR code symbol

int scale = 10, border = 4;
using SKBitmap bitmap = qrCode.ToBitmap(scale, border, SKColors.Black, SKColors.Transparent);
SKData data = bitmap.Encode(SKEncodedImageFormat.Png, 90);

return (QRCodeCreateResult.Success, data.AsStream(true), null);
}
catch (DataTooLongException e)
{
return (QRCodeCreateResult.DataTooLong, null, e);
}
catch (Exception e)
{
return (QRCodeCreateResult.Exception, null, e);
}
}
}
}
Loading

0 comments on commit 86088db

Please sign in to comment.