mirror of
https://github.com/greenshot/greenshot
synced 2025-08-22 06:23:24 -07:00
Added gz support, and improved upon some additional code.
This commit is contained in:
parent
2f556b44d1
commit
84be12b826
7 changed files with 148 additions and 183 deletions
|
@ -10,4 +10,22 @@
|
||||||
<Message Text="Processing: $(ProjectDir)$(ProjectName).Credentials.template" Importance="high"/>
|
<Message Text="Processing: $(ProjectDir)$(ProjectName).Credentials.template" Importance="high"/>
|
||||||
<TemplateFile Template="$(ProjectDir)$(ProjectName).Credentials.template" OutputFilename="$(ProjectDir)$(ProjectName).Credentials.cs" Tokens="@(Tokens)" />
|
<TemplateFile Template="$(ProjectDir)$(ProjectName).Credentials.template" OutputFilename="$(ProjectDir)$(ProjectName).Credentials.cs" Tokens="@(Tokens)" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
|
<UsingTask TaskName="GZipTask" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
|
||||||
|
<ParameterGroup>
|
||||||
|
<InputFile ParameterType="System.String" Required="true" />
|
||||||
|
<OutputFile ParameterType="System.String" Required="true" />
|
||||||
|
</ParameterGroup>
|
||||||
|
<Task>
|
||||||
|
<Reference Include="System.IO.Compression" />
|
||||||
|
<Using Namespace="System.IO.Compression" />
|
||||||
|
<Code Type="Fragment" Language="cs"><![CDATA[
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(OutputFile));
|
||||||
|
var data = File.ReadAllBytes(InputFile);
|
||||||
|
using (var s = new FileStream(OutputFile, FileMode.Create))
|
||||||
|
using (var gs = new GZipStream(s, CompressionMode.Compress, false))
|
||||||
|
gs.Write(data, 0, data.Length);
|
||||||
|
]]></Code>
|
||||||
|
</Task>
|
||||||
|
</UsingTask>
|
||||||
</Project>
|
</Project>
|
|
@ -1,69 +0,0 @@
|
||||||
/*
|
|
||||||
* Greenshot - a free and open source screenshot tool
|
|
||||||
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
|
||||||
*
|
|
||||||
* For more information see: https://getgreenshot.org/
|
|
||||||
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 1 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace Greenshot.Editor.Controls.Emoji;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// This seems to enumerate multiple IEnumerables.
|
|
||||||
/// TODO: Replace this with LINQ
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T"></typeparam>
|
|
||||||
internal sealed class ChunkHelper<T> : IEnumerable<IEnumerable<T>>
|
|
||||||
{
|
|
||||||
private readonly IEnumerable<T> _elements;
|
|
||||||
private readonly int _size;
|
|
||||||
private bool _hasMore;
|
|
||||||
|
|
||||||
public ChunkHelper(IEnumerable<T> elements, int size)
|
|
||||||
{
|
|
||||||
_elements = elements;
|
|
||||||
_size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerator<IEnumerable<T>> GetEnumerator()
|
|
||||||
{
|
|
||||||
using var enumerator = _elements.GetEnumerator();
|
|
||||||
_hasMore = enumerator.MoveNext();
|
|
||||||
while (_hasMore)
|
|
||||||
{
|
|
||||||
yield return GetNextBatch(enumerator).ToList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<T> GetNextBatch(IEnumerator<T> enumerator)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < _size; ++i)
|
|
||||||
{
|
|
||||||
yield return enumerator.Current;
|
|
||||||
_hasMore = enumerator.MoveNext();
|
|
||||||
if (!_hasMore)
|
|
||||||
{
|
|
||||||
yield break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
||||||
}
|
|
|
@ -11,15 +11,18 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
|
#if DEBUG
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
using SixLabors.Fonts.Unicode;
|
using SixLabors.Fonts.Unicode;
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace Greenshot.Editor.Controls.Emoji
|
namespace Greenshot.Editor.Controls.Emoji
|
||||||
{
|
{
|
||||||
|
@ -28,27 +31,17 @@ namespace Greenshot.Editor.Controls.Emoji
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class EmojiData
|
public static class EmojiData
|
||||||
{
|
{
|
||||||
private const string FilePath = "emojis.xml";
|
private const string EmojisXmlFilePath = "emojis.xml";
|
||||||
|
private const string EmojisTestFile = @"emoji-test.txt.gz";
|
||||||
|
#if DEBUG
|
||||||
|
private const string Adult = "(👨|👩)(🏻|🏼|🏽|🏾|🏿)?";
|
||||||
|
private const string Child = "(👦|👧|👶)(🏻|🏼|🏽|🏾|🏿)?";
|
||||||
|
private static readonly Regex MatchFamily = new($"{Adult}(\u200d{Adult})*(\u200d{Child})+");
|
||||||
|
|
||||||
public static Emojis Data { get; private set; } = new Emojis();
|
private static readonly Regex MatchGroup = new(@"^# group: (.*)", RegexOptions.Compiled);
|
||||||
|
private static readonly Regex MatchSubgroup = new(@"^# subgroup: (.*)", RegexOptions.Compiled);
|
||||||
public static void Load()
|
private static readonly Regex MatchSequence = new(@"^([0-9a-fA-F ]+[0-9a-fA-F]).*; *([-a-z]*) *# [^ ]* (E[0-9.]* )?(.*)", RegexOptions.Compiled);
|
||||||
{
|
private static readonly List<string> SkinToneComponents = new()
|
||||||
var x = new XmlSerializer(typeof(Emojis));
|
|
||||||
|
|
||||||
if (File.Exists(FilePath))
|
|
||||||
{
|
|
||||||
Data = (Emojis)x.Deserialize(new XmlTextReader(FilePath));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// To be removed
|
|
||||||
ParseEmojiList();
|
|
||||||
x.Serialize(new XmlTextWriter(FilePath, Encoding.UTF8), Data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly List<string> SkinToneComponents = new List<string>
|
|
||||||
{
|
{
|
||||||
"🏻", // light skin tone
|
"🏻", // light skin tone
|
||||||
"🏼", // medium-light skin tone
|
"🏼", // medium-light skin tone
|
||||||
|
@ -57,7 +50,7 @@ namespace Greenshot.Editor.Controls.Emoji
|
||||||
"🏿", // dark skin tone
|
"🏿", // dark skin tone
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly List<string> HairStyleComponents = new List<string>
|
private static readonly List<string> HairStyleComponents = new()
|
||||||
{
|
{
|
||||||
"🦰", // red hair
|
"🦰", // red hair
|
||||||
"🦱", // curly hair
|
"🦱", // curly hair
|
||||||
|
@ -65,21 +58,43 @@ namespace Greenshot.Editor.Controls.Emoji
|
||||||
"🦲", // bald
|
"🦲", // bald
|
||||||
};
|
};
|
||||||
|
|
||||||
private static string ToColonSyntax(string s)
|
private static readonly Regex MatchSkinTone = new($"({string.Join("|", SkinToneComponents)})", RegexOptions.Compiled);
|
||||||
=> Regex.Replace(s.Trim().ToLowerInvariant(), "[^a-z0-9]+", "-");
|
private static readonly Regex MatchHairStyle = new($"({string.Join("|", HairStyleComponents)})", RegexOptions.Compiled);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public static Emojis Data { get; private set; } = new();
|
||||||
|
|
||||||
|
public static void Load()
|
||||||
|
{
|
||||||
|
var x = new XmlSerializer(typeof(Emojis));
|
||||||
|
|
||||||
|
if (File.Exists(EmojisXmlFilePath))
|
||||||
|
{
|
||||||
|
Data = (Emojis)x.Deserialize(new XmlTextReader(EmojisXmlFilePath));
|
||||||
|
}
|
||||||
|
#if RELEASE
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new NotSupportedException($"Missing {EmojisXmlFilePath}, can't load ");
|
||||||
|
}
|
||||||
|
#elif DEBUG
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// To be removed
|
||||||
|
ParseEmojiList();
|
||||||
|
x.Serialize(new XmlTextWriter(EmojisXmlFilePath, Encoding.UTF8), Data);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
private static string ToColonSyntax(string s) => Regex.Replace(s.Trim().ToLowerInvariant(), "[^a-z0-9]+", "-");
|
||||||
|
|
||||||
private static void ParseEmojiList()
|
private static void ParseEmojiList()
|
||||||
{
|
{
|
||||||
var lookupByName = new Dictionary<string, Emojis.Emoji>();
|
var lookupByName = new Dictionary<string, Emojis.Emoji>();
|
||||||
var matchGroup = new Regex(@"^# group: (.*)");
|
|
||||||
var matchSubgroup = new Regex(@"^# subgroup: (.*)");
|
|
||||||
var matchSequence = new Regex(@"^([0-9a-fA-F ]+[0-9a-fA-F]).*; *([-a-z]*) *# [^ ]* (E[0-9.]* )?(.*)");
|
|
||||||
var matchSkinTone = new Regex($"({string.Join("|", SkinToneComponents)})");
|
|
||||||
var matchHairStyle = new Regex($"({string.Join("|", HairStyleComponents)})");
|
|
||||||
|
|
||||||
var adult = "(👨|👩)(🏻|🏼|🏽|🏾|🏿)?";
|
|
||||||
var child = "(👦|👧|👶)(🏻|🏼|🏽|🏾|🏿)?";
|
|
||||||
var matchFamily = new Regex($"{adult}(\u200d{adult})*(\u200d{child})+");
|
|
||||||
|
|
||||||
var qualifiedLut = new Dictionary<string, string>();
|
var qualifiedLut = new Dictionary<string, string>();
|
||||||
var allText = new List<string>();
|
var allText = new List<string>();
|
||||||
|
@ -89,7 +104,7 @@ namespace Greenshot.Editor.Controls.Emoji
|
||||||
|
|
||||||
foreach (var line in EmojiDescriptionLines())
|
foreach (var line in EmojiDescriptionLines())
|
||||||
{
|
{
|
||||||
var m = matchGroup.Match(line);
|
var m = MatchGroup.Match(line);
|
||||||
if (m.Success)
|
if (m.Success)
|
||||||
{
|
{
|
||||||
currentGroup = new Emojis.Group { Name = m.Groups[1].ToString() };
|
currentGroup = new Emojis.Group { Name = m.Groups[1].ToString() };
|
||||||
|
@ -97,85 +112,82 @@ namespace Greenshot.Editor.Controls.Emoji
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
m = matchSubgroup.Match(line);
|
m = MatchSubgroup.Match(line);
|
||||||
if (m.Success)
|
if (m.Success)
|
||||||
{
|
{
|
||||||
currentSubgroup = new Emojis.Group { Name = m.Groups[1].ToString() };
|
currentSubgroup = new Emojis.Group { Name = m.Groups[1].ToString() };
|
||||||
currentGroup.SubGroups.Add(currentSubgroup);
|
currentGroup?.SubGroups?.Add(currentSubgroup);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
m = matchSequence.Match(line);
|
m = MatchSequence.Match(line);
|
||||||
if (m.Success)
|
if (!m.Success)
|
||||||
{
|
{
|
||||||
string sequence = m.Groups[1].ToString();
|
continue;
|
||||||
string name = m.Groups[4].ToString();
|
}
|
||||||
|
string sequence = m.Groups[1].ToString();
|
||||||
|
string name = m.Groups[4].ToString();
|
||||||
|
|
||||||
string text = string.Join("", from n in sequence.Split(' ')
|
string text = string.Join("", sequence.Split(' ').Select(c => char.ConvertFromUtf32(Convert.ToInt32(c, 16))));
|
||||||
select char.ConvertFromUtf32(Convert.ToInt32(n, 16)));
|
bool hasModifier = false;
|
||||||
bool has_modifier = false;
|
|
||||||
|
|
||||||
if (matchFamily.Match(text).Success)
|
// If this is a family emoji, no need to add it to our big matching
|
||||||
{
|
// regex, since the match_family regex is already included.
|
||||||
// If this is a family emoji, no need to add it to our big matching
|
if (!MatchFamily.Match(text).Success)
|
||||||
// regex, since the match_family regex is already included.
|
{
|
||||||
}
|
// Construct a regex to replace e.g. "🏻" with "(🏻|🏼|🏽|🏾|🏿)" in a big
|
||||||
else
|
// regex so that we can match all variations of this Emoji even if they are
|
||||||
{
|
// not in the standard.
|
||||||
// Construct a regex to replace e.g. "🏻" with "(🏻|🏼|🏽|🏾|🏿)" in a big
|
bool hasNonfirstModifier = false;
|
||||||
// regex so that we can match all variations of this Emoji even if they are
|
var regexText = MatchSkinTone.Replace(
|
||||||
// not in the standard.
|
MatchHairStyle.Replace(text, (x) =>
|
||||||
bool hasNonfirstModifier = false;
|
|
||||||
var regexText = matchSkinTone.Replace(
|
|
||||||
matchHairStyle.Replace(text, (x) =>
|
|
||||||
{
|
|
||||||
has_modifier = true;
|
|
||||||
hasNonfirstModifier |= x.Value != HairStyleComponents[0];
|
|
||||||
return matchHairStyle.ToString();
|
|
||||||
}), (x) =>
|
|
||||||
{
|
|
||||||
has_modifier = true;
|
|
||||||
hasNonfirstModifier |= x.Value != SkinToneComponents[0];
|
|
||||||
return matchSkinTone.ToString();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!hasNonfirstModifier)
|
|
||||||
{
|
{
|
||||||
allText.Add(has_modifier ? regexText : text);
|
hasModifier = true;
|
||||||
}
|
hasNonfirstModifier |= x.Value != HairStyleComponents[0];
|
||||||
}
|
return MatchHairStyle.ToString();
|
||||||
|
}), (x) =>
|
||||||
|
{
|
||||||
|
hasModifier = true;
|
||||||
|
hasNonfirstModifier |= x.Value != SkinToneComponents[0];
|
||||||
|
return MatchSkinTone.ToString();
|
||||||
|
});
|
||||||
|
|
||||||
// If there is already a differently-qualified version of this character, skip it.
|
if (!hasNonfirstModifier)
|
||||||
// FIXME: this only works well if fully-qualified appears first in the list.
|
|
||||||
var unqualified = text.Replace("\ufe0f", "");
|
|
||||||
if (qualifiedLut.ContainsKey(unqualified))
|
|
||||||
{
|
{
|
||||||
continue;
|
allText.Add(hasModifier ? regexText : text);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Fix simple fully-qualified emojis
|
// If there is already a differently-qualified version of this character, skip it.
|
||||||
if (CodePoint.GetCodePointCount(text.AsSpan()) == 2)
|
// FIXME: this only works well if fully-qualified appears first in the list.
|
||||||
{
|
var unqualified = text.Replace("\ufe0f", "");
|
||||||
text = text.TrimEnd('\ufe0f');
|
if (qualifiedLut.ContainsKey(unqualified))
|
||||||
}
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
qualifiedLut[unqualified] = text;
|
// Fix simple fully-qualified emojis
|
||||||
|
if (CodePoint.GetCodePointCount(text.AsSpan()) == 2)
|
||||||
|
{
|
||||||
|
text = text.TrimEnd('\ufe0f');
|
||||||
|
}
|
||||||
|
|
||||||
var emoji = new Emojis.Emoji { Name = name, Text = text, };
|
qualifiedLut[unqualified] = text;
|
||||||
|
|
||||||
lookupByName[ToColonSyntax(name)] = emoji;
|
var emoji = new Emojis.Emoji { Name = name, Text = text};
|
||||||
|
|
||||||
// Get the left part of the name and check whether we’re a variation of an existing
|
lookupByName[ToColonSyntax(name)] = emoji;
|
||||||
// emoji. If so, append to that emoji. Otherwise, add to current subgroup.
|
|
||||||
// FIXME: does not work properly because variations can appear before the generic emoji
|
// Get the left part of the name and check whether we’re a variation of an existing
|
||||||
if (name.Contains(":") && lookupByName.TryGetValue(ToColonSyntax(name.Split(':')[0]), out var parent_emoji))
|
// emoji. If so, append to that emoji. Otherwise, add to current subgroup.
|
||||||
{
|
// FIXME: does not work properly because variations can appear before the generic emoji
|
||||||
parent_emoji.Variations.Add(emoji);
|
if (name.Contains(":") && lookupByName.TryGetValue(ToColonSyntax(name.Split(':')[0]), out var parentEmoji))
|
||||||
}
|
{
|
||||||
else
|
parentEmoji.Variations.Add(emoji);
|
||||||
{
|
}
|
||||||
currentSubgroup.Emojis.Add(emoji);
|
else
|
||||||
}
|
{
|
||||||
|
currentSubgroup?.Emojis?.Add(emoji);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,14 +198,16 @@ namespace Greenshot.Editor.Controls.Emoji
|
||||||
private static IEnumerable<string> EmojiDescriptionLines()
|
private static IEnumerable<string> EmojiDescriptionLines()
|
||||||
{
|
{
|
||||||
var exeDirectory = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location);
|
var exeDirectory = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location);
|
||||||
var emojiTestFile = Path.Combine(exeDirectory, @"emoji-test.txt");
|
var emojiTestFile = Path.Combine(exeDirectory, EmojisTestFile);
|
||||||
if (!File.Exists(emojiTestFile))
|
if (!File.Exists(emojiTestFile))
|
||||||
{
|
{
|
||||||
throw new FileNotFoundException($"Can't find {emojiTestFile}, bad installation?");
|
throw new FileNotFoundException($"Can't find {emojiTestFile}, bad installation?");
|
||||||
}
|
}
|
||||||
using var fileStream = new FileStream(emojiTestFile, FileMode.Open, FileAccess.Read);
|
using var fileStream = new FileStream(emojiTestFile, FileMode.Open, FileAccess.Read);
|
||||||
|
using var gzStream = new GZipStream(fileStream, CompressionMode.Decompress);
|
||||||
using var streamReader = new StreamReader(fileStream);
|
using var streamReader = new StreamReader(fileStream);
|
||||||
return streamReader.ReadToEnd().Split('\r', '\n');
|
return streamReader.ReadToEnd().Split('\r', '\n');
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -42,14 +42,7 @@ public class Emojis
|
||||||
[XmlElement(ElementName = "Emoji")]
|
[XmlElement(ElementName = "Emoji")]
|
||||||
public List<Emoji> Emojis { get; set; } = new();
|
public List<Emoji> Emojis { get; set; } = new();
|
||||||
|
|
||||||
public IEnumerable<IEnumerable<Emoji>> EmojiChunkList => new ChunkHelper<Emoji>(EmojiList, 8);
|
|
||||||
|
|
||||||
public string Icon => SubGroups.FirstOrDefault()?.Emojis.FirstOrDefault()?.Text;
|
public string Icon => SubGroups.FirstOrDefault()?.Emojis.FirstOrDefault()?.Text;
|
||||||
|
|
||||||
public IEnumerable<Emoji> EmojiList
|
|
||||||
=> from s in SubGroups
|
|
||||||
from e in s.Emojis
|
|
||||||
select e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Emoji
|
public class Emoji
|
||||||
|
|
|
@ -153,7 +153,10 @@ namespace Greenshot.Editor.Drawing.Emoji
|
||||||
protected override Image ComputeBitmap()
|
protected override Image ComputeBitmap()
|
||||||
{
|
{
|
||||||
var iconSize = Math.Min(Bounds.Width, Bounds.Height);
|
var iconSize = Math.Min(Bounds.Width, Bounds.Height);
|
||||||
if (iconSize <= 0) return null;
|
if (iconSize <= 0)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var image = EmojiRenderer.GetBitmap(Emoji, iconSize);
|
var image = EmojiRenderer.GetBitmap(Emoji, iconSize);
|
||||||
if (RotationAngle != 0)
|
if (RotationAngle != 0)
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using SixLabors.Fonts;
|
using SixLabors.Fonts;
|
||||||
using SixLabors.ImageSharp;
|
using SixLabors.ImageSharp;
|
||||||
|
@ -35,9 +36,9 @@ namespace Greenshot.Editor.Drawing.Emoji
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static class EmojiRenderer
|
internal static class EmojiRenderer
|
||||||
{
|
{
|
||||||
private static readonly FontCollection _fontCollection = new FontCollection();
|
private static readonly FontCollection TwemojiFontCollection = new();
|
||||||
|
|
||||||
private static readonly Lazy<FontFamily> _twemojiFontFamily = new Lazy<FontFamily>(() =>
|
private static readonly Lazy<FontFamily> TwemojiFontFamily = new(() =>
|
||||||
{
|
{
|
||||||
var exeDirectory = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location);
|
var exeDirectory = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location);
|
||||||
var twemojiFontFile = Path.Combine(exeDirectory, "TwemojiMozilla.ttf");
|
var twemojiFontFile = Path.Combine(exeDirectory, "TwemojiMozilla.ttf");
|
||||||
|
@ -47,8 +48,8 @@ namespace Greenshot.Editor.Drawing.Emoji
|
||||||
}
|
}
|
||||||
|
|
||||||
using var fileStream = new FileStream(twemojiFontFile, FileMode.Open, FileAccess.Read);
|
using var fileStream = new FileStream(twemojiFontFile, FileMode.Open, FileAccess.Read);
|
||||||
_fontCollection.Add(fileStream);
|
TwemojiFontCollection.Add(fileStream);
|
||||||
_fontCollection.TryGet("Twemoji Mozilla", out var fontFamily);
|
TwemojiFontCollection.TryGet("Twemoji Mozilla", out var fontFamily);
|
||||||
return fontFamily;
|
return fontFamily;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -62,7 +63,7 @@ namespace Greenshot.Editor.Drawing.Emoji
|
||||||
|
|
||||||
private static void RenderEmoji(string emoji, int iconSize, Image image)
|
private static void RenderEmoji(string emoji, int iconSize, Image image)
|
||||||
{
|
{
|
||||||
var fontFamily = _twemojiFontFamily.Value;
|
var fontFamily = TwemojiFontFamily.Value;
|
||||||
var font = fontFamily.CreateFont(iconSize, FontStyle.Regular);
|
var font = fontFamily.CreateFont(iconSize, FontStyle.Regular);
|
||||||
var verticalOffset = font.Size * 0.045f;
|
var verticalOffset = font.Size * 0.045f;
|
||||||
var textOptions = new TextOptions(font)
|
var textOptions = new TextOptions(font)
|
||||||
|
|
|
@ -15,6 +15,11 @@
|
||||||
<ProjectReference Include="..\Greenshot.Base\Greenshot.Base.csproj" />
|
<ProjectReference Include="..\Greenshot.Base\Greenshot.Base.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Target Name="CompressEmojiTxtResource" BeforeTargets="BeforeBuild" Condition="!Exists('Controls\Emoji\emoji-test.txt.gz')">
|
||||||
|
<GZipTask InputFile="Controls\Emoji\emoji-test.txt"
|
||||||
|
OutputFile="Controls\Emoji\emoji-test.txt.gz" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Update="Controls\BindableToolStripButton.cs">
|
<Compile Update="Controls\BindableToolStripButton.cs">
|
||||||
<SubType>Component</SubType>
|
<SubType>Component</SubType>
|
||||||
|
@ -89,9 +94,9 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ContentWithTargetPath Include="Controls\Emoji\emoji-test.txt">
|
<ContentWithTargetPath Include="Controls\Emoji\emoji-test.txt.gz">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
<TargetPath>emoji-test.txt</TargetPath>
|
<TargetPath>emoji-test.txt.gz</TargetPath>
|
||||||
</ContentWithTargetPath>
|
</ContentWithTargetPath>
|
||||||
<ContentWithTargetPath Include="Drawing\Emoji\TwemojiMozilla.ttf">
|
<ContentWithTargetPath Include="Drawing\Emoji\TwemojiMozilla.ttf">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue