Add icon cache

This commit is contained in:
Julien Richard 2022-01-22 13:35:54 +01:00
commit 9e45eb29d6
5 changed files with 52 additions and 19 deletions

View file

@ -11,7 +11,7 @@ namespace Greenshot.Editor.Controls
private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((EmojiControl)d).Source = EmojiRenderer.GetBitmapSource((string)e.NewValue, 48);
((EmojiControl)d).Source = EmojiRenderer.GetIcon((string)e.NewValue);
}
public string Emoji

View file

@ -17,11 +17,15 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Greenshot.Editor.Drawing;
namespace Greenshot.Editor.Controls
{
public static class EmojiData
{
private static Task _init;
public static IEnumerable<Emoji> AllEmoji
=> from g in AllGroups
from e in g.EmojiList
@ -38,13 +42,14 @@ namespace Greenshot.Editor.Controls
public static HashSet<char> MatchStart { get; private set; }
= new HashSet<char>();
// FIXME: should we lazy load this? If the user calls Load() later, then
// this first Load() call will have been for nothing.
static EmojiData() => Load();
public static void Load()
{
ParseEmojiList();
_init = Task.Run(() =>
{
ParseEmojiList();
EmojiRenderer.FillIconCache(AllEmoji.Select(e => e.Text));
});
}
public class Emoji

View file

@ -35,7 +35,7 @@
<Button Background="Transparent" BorderBrush="Transparent"
Margin="0" Click="OnEmojiPicked"
Width="40" Height="40" ToolTip="{Binding Path=Name}">
<controls:EmojiControl Height="24" Emoji="{Binding Path=Text, IsAsync=True}"/>
<controls:EmojiControl Height="24" Emoji="{Binding Path=Text}"/>
</Button>
</DataTemplate>
</ListView.ItemTemplate>
@ -47,7 +47,7 @@
x:Name="VariationButton" Background="Transparent" BorderBrush="Transparent"
Click="OnEmojiPicked" Focusable="False" ToolTip="{Binding Path=Name}">
<Grid>
<controls:EmojiControl Height="24" Margin="4" Emoji="{Binding Path=Text, IsAsync=True}"
<controls:EmojiControl Height="24" Margin="4" Emoji="{Binding Path=Text}"
VerticalAlignment="Center" HorizontalAlignment="Center"/>
<Polygon Visibility="{Binding HasVariations, Converter={StaticResource BoolToVis}}"
Width="6" Height="6" VerticalAlignment="Bottom" HorizontalAlignment="Right"

View file

@ -1,6 +1,9 @@
using System.Drawing;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Media.Imaging;
using SixLabors.Fonts;
using SixLabors.ImageSharp;
@ -9,8 +12,10 @@ using SixLabors.ImageSharp.Drawing.Processing;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using Font = SixLabors.Fonts.Font;
using FontStyle = SixLabors.Fonts.FontStyle;
using Image = System.Drawing.Image;
using TextOptions = SixLabors.Fonts.TextOptions;
namespace Greenshot.Editor.Drawing
{
@ -18,6 +23,8 @@ namespace Greenshot.Editor.Drawing
{
private static SixLabors.Fonts.FontFamily? _fontFamily;
private static ConcurrentDictionary<string, BitmapSource> _iconCache = new ConcurrentDictionary<string, BitmapSource>();
public static Image<Rgba32> GetImage(string emoji, int iconSize)
{
if (_fontFamily == null)
@ -32,12 +39,23 @@ namespace Greenshot.Editor.Drawing
}
var font = _fontFamily.Value.CreateFont(iconSize, FontStyle.Regular);
var image = new Image<Rgba32>(iconSize, iconSize);
var textOptions = new TextOptions(font) { Origin = new SixLabors.ImageSharp.PointF(0, iconSize / 2.0f), HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Center };
RenderEmoji(emoji, font, image);
return image;
}
private static void RenderEmoji(string emoji, Font font, Image<Rgba32> image)
{
var verticalOffset = font.Size * 0.045f;
var textOptions = new TextOptions(font)
{
Origin = new SixLabors.ImageSharp.PointF(0, font.Size / 2.0f - verticalOffset),
HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Center
};
image.Mutate(x => x.DrawText(textOptions, emoji, SixLabors.ImageSharp.Color.Black));
return image;
}
public static Image GetBitmap(string emoji, int iconSize)
@ -82,5 +100,18 @@ namespace Greenshot.Editor.Drawing
return bitmap;
}
public static void FillIconCache(IEnumerable<string> emojis)
{
Parallel.ForEach(emojis, emoji =>
{
GetIcon(emoji);
});
}
public static BitmapSource GetIcon(string emoji)
{
return _iconCache.GetOrAdd(emoji, x => GetBitmapSource(x, 64));
}
}
}

View file

@ -27,6 +27,7 @@ using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Greenshot.Base;
using Greenshot.Base.Controls;
@ -40,6 +41,7 @@ using Greenshot.Base.Interfaces.Forms;
using Greenshot.Base.UnmanagedHelpers;
using Greenshot.Base.UnmanagedHelpers.Structs;
using Greenshot.Editor.Configuration;
using Greenshot.Editor.Controls;
using Greenshot.Editor.Destinations;
using Greenshot.Editor.Drawing;
using Greenshot.Editor.Drawing.Fields;
@ -142,6 +144,9 @@ namespace Greenshot.Editor.Forms
private void Initialize(ISurface surface, bool outputMade)
{
// Compute emojis in background
EmojiData.Load();
EditorList.Add(this);
//
@ -186,14 +191,6 @@ namespace Greenshot.Editor.Forms
// Workaround: As the cursor is (mostly) selected on the surface a funny artifact is visible, this fixes it.
HideToolstripItems();
HideEmojiButtonWhenFontIsNotInstalled();
}
private void HideEmojiButtonWhenFontIsNotInstalled()
{
_emojifontInstalled ??= FontFamily.Families.Any(f => string.Equals(f.Name, "Segoe UI Emoji", StringComparison.OrdinalIgnoreCase));
btnEmoji.Visible = _emojifontInstalled.Value;
}
/// <summary>