mirror of
https://github.com/greenshot/greenshot
synced 2025-08-22 06:23:24 -07:00
Created a custom task for generating emoji data, although this works in general, the next build doesn't.
This commit is contained in:
parent
128436eafd
commit
2cc72e32ad
7 changed files with 243 additions and 209 deletions
178
src/Greenshot.BuildTasks/EmojiDataTask.cs
Normal file
178
src/Greenshot.BuildTasks/EmojiDataTask.cs
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Greenshot.Editor.Controls.Emoji;
|
||||||
|
using SixLabors.Fonts.Unicode;
|
||||||
|
using Task = Microsoft.Build.Utilities.Task;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
using Microsoft.Build.Framework;
|
||||||
|
|
||||||
|
namespace Greenshot.BuildTasks;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A custom task to generate the emoji data we need for the picker.
|
||||||
|
/// This is based upon code from Sam Hocevar, the license is here:
|
||||||
|
/// Emoji.Wpf — Emoji support for WPF
|
||||||
|
///
|
||||||
|
/// Copyright © 2017—2021 Sam Hocevar <sam@hocevar.net>
|
||||||
|
///
|
||||||
|
/// This library is free software. It comes without any warranty, to
|
||||||
|
/// the extent permitted by applicable law. You can redistribute it
|
||||||
|
/// and/or modify it under the terms of the Do What the Fuck You Want
|
||||||
|
/// to Public License, Version 2, as published by the WTFPL Task Force.
|
||||||
|
/// See http://www.wtfpl.net/ for more details.
|
||||||
|
/// </summary>
|
||||||
|
public class EmojiDataTask : Task
|
||||||
|
{
|
||||||
|
private static readonly Regex MatchGroup = new(@"^# group: (.*)", RegexOptions.Compiled);
|
||||||
|
private static readonly Regex MatchSubgroup = new(@"^# subgroup: (.*)", RegexOptions.Compiled);
|
||||||
|
private static readonly Regex MatchSequence = new(@"^([0-9a-fA-F ]+[0-9a-fA-F]).*; *([-a-z]*) *# [^ ]* (E[0-9.]* )?(.*)", RegexOptions.Compiled);
|
||||||
|
|
||||||
|
private static string ToColonSyntax(string s) => Regex.Replace(s.Trim().ToLowerInvariant(), "[^a-z0-9]+", "-");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the output file
|
||||||
|
/// </summary>
|
||||||
|
[Required]
|
||||||
|
public string OutputFilename { get; set; }
|
||||||
|
|
||||||
|
//The name of the namespace where the class is going to be generated
|
||||||
|
[Required]
|
||||||
|
public string EmojiTestTxtFile { get; set; }
|
||||||
|
|
||||||
|
public override bool Execute()
|
||||||
|
{
|
||||||
|
var data = ParseEmojiList(EmojiTestTxtFile);
|
||||||
|
if (!data.Groups.Any())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Log.LogMessage($"Creating file {OutputFilename}");
|
||||||
|
var x = new XmlSerializer(typeof(Emojis));
|
||||||
|
using var writer = new XmlTextWriter(OutputFilename, Encoding.UTF8);
|
||||||
|
x.Serialize(writer, data);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static Emojis ParseEmojiList(string emojiTestTxtFile)
|
||||||
|
{
|
||||||
|
var result = new Emojis();
|
||||||
|
var lookupByName = new Dictionary<string, Emojis.Emoji>();
|
||||||
|
var qualifiedLut = new Dictionary<string, string>();
|
||||||
|
Emojis.Group currentGroup = null;
|
||||||
|
Emojis.Group currentSubgroup = null;
|
||||||
|
|
||||||
|
foreach (var line in ReadLines(emojiTestTxtFile))
|
||||||
|
{
|
||||||
|
var m = MatchGroup.Match(line);
|
||||||
|
if (m.Success)
|
||||||
|
{
|
||||||
|
currentGroup = new Emojis.Group { Name = m.Groups[1].ToString() };
|
||||||
|
result.Groups.Add(currentGroup);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
m = MatchSubgroup.Match(line);
|
||||||
|
if (m.Success)
|
||||||
|
{
|
||||||
|
currentSubgroup = new Emojis.Group { Name = m.Groups[1].ToString() };
|
||||||
|
currentGroup?.SubGroups?.Add(currentSubgroup);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
m = MatchSequence.Match(line);
|
||||||
|
if (!m.Success)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
string sequence = m.Groups[1].ToString();
|
||||||
|
string name = m.Groups[4].ToString();
|
||||||
|
|
||||||
|
string text = string.Join("", sequence.Split(' ').Select(c => char.ConvertFromUtf32(Convert.ToInt32(c, 16))));
|
||||||
|
|
||||||
|
// If there is already a differently-qualified version of this character, skip it.
|
||||||
|
// FIXME: this only works well if fully-qualified appears first in the list.
|
||||||
|
var unqualified = text.Replace("\ufe0f", "");
|
||||||
|
if (qualifiedLut.ContainsKey(unqualified))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix simple fully-qualified emojis
|
||||||
|
if (CodePoint.GetCodePointCount(text.AsSpan()) == 2)
|
||||||
|
{
|
||||||
|
text = text.TrimEnd('\ufe0f');
|
||||||
|
}
|
||||||
|
|
||||||
|
qualifiedLut[unqualified] = text;
|
||||||
|
|
||||||
|
var emoji = new Emojis.Emoji { Text = text };
|
||||||
|
|
||||||
|
lookupByName[ToColonSyntax(name)] = emoji;
|
||||||
|
|
||||||
|
// Get the left part of the name and check whether we’re a variation of an existing
|
||||||
|
// 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
|
||||||
|
if (name.Contains(":") && lookupByName.TryGetValue(ToColonSyntax(name.Split(':')[0]), out var parentEmoji))
|
||||||
|
{
|
||||||
|
parentEmoji.Variations.Add(emoji);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
currentSubgroup?.Emojis?.Add(emoji);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the Component group. Not sure we want to have the skin tones in the picker.
|
||||||
|
result.Groups.RemoveAll(g => g.Name == "Component");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This reads the specified file into lines
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="file">string</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="FileNotFoundException"></exception>
|
||||||
|
private static IEnumerable<string> ReadLines(string file)
|
||||||
|
{
|
||||||
|
if (!File.Exists(file))
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException($"Can't find {file}");
|
||||||
|
}
|
||||||
|
|
||||||
|
using var stream = new FileStream(file, FileMode.Open, FileAccess.Read);
|
||||||
|
using var reader = new StreamReader(stream, Encoding.UTF8);
|
||||||
|
while (reader.ReadLine() is { } line)
|
||||||
|
{
|
||||||
|
yield return line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj
Normal file
9
src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Build.Utilities.Core" version="17.3.2" />
|
||||||
|
<PackageReference Include="SixLabors.ImageSharp.Drawing" version="1.0.0-beta15" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Greenshot.Editor\Greenshot.Editor.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
|
@ -1,67 +1,37 @@
|
||||||
//
|
/*
|
||||||
// Emoji.Wpf — Emoji support for WPF
|
* Greenshot - a free and open source screenshot tool
|
||||||
//
|
* Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom
|
||||||
// Copyright © 2017—2021 Sam Hocevar <sam@hocevar.net>
|
*
|
||||||
//
|
* For more information see: https://getgreenshot.org/
|
||||||
// This library is free software. It comes without any warranty, to
|
* The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
|
||||||
// the extent permitted by applicable law. You can redistribute it
|
*
|
||||||
// and/or modify it under the terms of the Do What the Fuck You Want
|
* This program is free software: you can redistribute it and/or modify
|
||||||
// to Public License, Version 2, as published by the WTFPL Task Force.
|
* it under the terms of the GNU General Public License as published by
|
||||||
// See http://www.wtfpl.net/ for more details.
|
* 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;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
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;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Greenshot.Editor.Controls.Emoji
|
namespace Greenshot.Editor.Controls.Emoji
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This class processes the emoji-test.txt to generate a list of possible emoji depending ony skin tone and hairstyle.
|
/// This class processes the emoji-test.txt extract, as was generated in a build task, so it can show a list of possible emoji depending on skin tone and hairstyle.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class EmojiData
|
public static class EmojiData
|
||||||
{
|
{
|
||||||
private const string EmojisXmlFilePath = "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})+");
|
|
||||||
|
|
||||||
private static readonly Regex MatchGroup = new(@"^# group: (.*)", RegexOptions.Compiled);
|
|
||||||
private static readonly Regex MatchSubgroup = new(@"^# subgroup: (.*)", RegexOptions.Compiled);
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
"🏻", // light skin tone
|
|
||||||
"🏼", // medium-light skin tone
|
|
||||||
"🏽", // medium skin tone
|
|
||||||
"🏾", // medium-dark skin tone
|
|
||||||
"🏿", // dark skin tone
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly List<string> HairStyleComponents = new()
|
|
||||||
{
|
|
||||||
"🦰", // red hair
|
|
||||||
"🦱", // curly hair
|
|
||||||
"🦳", // white hair
|
|
||||||
"🦲", // bald
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly Regex MatchSkinTone = new($"({string.Join("|", SkinToneComponents)})", RegexOptions.Compiled);
|
|
||||||
private static readonly Regex MatchHairStyle = new($"({string.Join("|", HairStyleComponents)})", RegexOptions.Compiled);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
public static Emojis Data { get; private set; } = new();
|
public static Emojis Data { get; private set; } = new();
|
||||||
|
|
||||||
|
@ -73,144 +43,10 @@ namespace Greenshot.Editor.Controls.Emoji
|
||||||
{
|
{
|
||||||
Data = (Emojis)x.Deserialize(new XmlTextReader(EmojisXmlFilePath));
|
Data = (Emojis)x.Deserialize(new XmlTextReader(EmojisXmlFilePath));
|
||||||
}
|
}
|
||||||
#if RELEASE
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new NotSupportedException($"Missing {EmojisXmlFilePath}, can't load ");
|
throw new NotSupportedException($"Missing {EmojisXmlFilePath}, can't load ");
|
||||||
}
|
}
|
||||||
#elif DEBUG
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// To be removed
|
|
||||||
ParseEmojiList();
|
|
||||||
if (Data.Groups.Any())
|
|
||||||
{
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
var lookupByName = new Dictionary<string, Emojis.Emoji>();
|
|
||||||
|
|
||||||
var qualifiedLut = new Dictionary<string, string>();
|
|
||||||
var allText = new List<string>();
|
|
||||||
|
|
||||||
Emojis.Group currentGroup = null;
|
|
||||||
Emojis.Group currentSubgroup = null;
|
|
||||||
|
|
||||||
foreach (var line in EmojiDescriptionLines())
|
|
||||||
{
|
|
||||||
var m = MatchGroup.Match(line);
|
|
||||||
if (m.Success)
|
|
||||||
{
|
|
||||||
currentGroup = new Emojis.Group { Name = m.Groups[1].ToString() };
|
|
||||||
Data.Groups.Add(currentGroup);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
m = MatchSubgroup.Match(line);
|
|
||||||
if (m.Success)
|
|
||||||
{
|
|
||||||
currentSubgroup = new Emojis.Group { Name = m.Groups[1].ToString() };
|
|
||||||
currentGroup?.SubGroups?.Add(currentSubgroup);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
m = MatchSequence.Match(line);
|
|
||||||
if (!m.Success)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
string sequence = m.Groups[1].ToString();
|
|
||||||
string name = m.Groups[4].ToString();
|
|
||||||
|
|
||||||
string text = string.Join("", sequence.Split(' ').Select(c => char.ConvertFromUtf32(Convert.ToInt32(c, 16))));
|
|
||||||
bool hasModifier = false;
|
|
||||||
|
|
||||||
// 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 (!MatchFamily.Match(text).Success)
|
|
||||||
{
|
|
||||||
// Construct a regex to replace e.g. "🏻" with "(🏻|🏼|🏽|🏾|🏿)" in a big
|
|
||||||
// regex so that we can match all variations of this Emoji even if they are
|
|
||||||
// not in the standard.
|
|
||||||
bool hasNonfirstModifier = false;
|
|
||||||
var regexText = MatchSkinTone.Replace(
|
|
||||||
MatchHairStyle.Replace(text, (x) =>
|
|
||||||
{
|
|
||||||
hasModifier = true;
|
|
||||||
hasNonfirstModifier |= x.Value != HairStyleComponents[0];
|
|
||||||
return MatchHairStyle.ToString();
|
|
||||||
}), (x) =>
|
|
||||||
{
|
|
||||||
hasModifier = true;
|
|
||||||
hasNonfirstModifier |= x.Value != SkinToneComponents[0];
|
|
||||||
return MatchSkinTone.ToString();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!hasNonfirstModifier)
|
|
||||||
{
|
|
||||||
allText.Add(hasModifier ? regexText : text);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there is already a differently-qualified version of this character, skip it.
|
|
||||||
// FIXME: this only works well if fully-qualified appears first in the list.
|
|
||||||
var unqualified = text.Replace("\ufe0f", "");
|
|
||||||
if (qualifiedLut.ContainsKey(unqualified))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fix simple fully-qualified emojis
|
|
||||||
if (CodePoint.GetCodePointCount(text.AsSpan()) == 2)
|
|
||||||
{
|
|
||||||
text = text.TrimEnd('\ufe0f');
|
|
||||||
}
|
|
||||||
|
|
||||||
qualifiedLut[unqualified] = text;
|
|
||||||
|
|
||||||
var emoji = new Emojis.Emoji { Text = text};
|
|
||||||
|
|
||||||
lookupByName[ToColonSyntax(name)] = emoji;
|
|
||||||
|
|
||||||
// Get the left part of the name and check whether we’re a variation of an existing
|
|
||||||
// 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
|
|
||||||
if (name.Contains(":") && lookupByName.TryGetValue(ToColonSyntax(name.Split(':')[0]), out var parentEmoji))
|
|
||||||
{
|
|
||||||
parentEmoji.Variations.Add(emoji);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
currentSubgroup?.Emojis?.Add(emoji);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the Component group. Not sure we want to have the skin tones in the picker.
|
|
||||||
Data.Groups.RemoveAll(g => g.Name == "Component");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<string> EmojiDescriptionLines()
|
|
||||||
{
|
|
||||||
var exeDirectory = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location);
|
|
||||||
var emojiTestFile = Path.Combine(exeDirectory, EmojisTestFile);
|
|
||||||
if (!File.Exists(emojiTestFile))
|
|
||||||
{
|
|
||||||
throw new FileNotFoundException($"Can't find {emojiTestFile}, bad installation?");
|
|
||||||
}
|
|
||||||
using var fileStream = new FileStream(emojiTestFile, FileMode.Open, FileAccess.Read);
|
|
||||||
using var gzStream = new GZipStream(fileStream, CompressionMode.Decompress);
|
|
||||||
using var streamReader = new StreamReader(gzStream);
|
|
||||||
return streamReader.ReadToEnd().Split('\r', '\n');
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -26,20 +26,22 @@ using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace Greenshot.Editor.Controls.Emoji;
|
namespace Greenshot.Editor.Controls.Emoji;
|
||||||
|
|
||||||
|
[XmlRoot("Es")]
|
||||||
public class Emojis
|
public class Emojis
|
||||||
{
|
{
|
||||||
[XmlElement(ElementName = "Group")]
|
[XmlArray(ElementName = "Gs")]
|
||||||
public List<Group> Groups { get; set; } = new();
|
public List<Group> Groups { get; set; } = new();
|
||||||
|
|
||||||
|
[XmlType("G")]
|
||||||
public class Group
|
public class Group
|
||||||
{
|
{
|
||||||
[XmlAttribute]
|
[XmlAttribute(AttributeName= "N")]
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
[XmlElement(ElementName = "Group")]
|
[XmlArray(ElementName = "Sg")]
|
||||||
public List<Group> SubGroups { get; set; } = new();
|
public List<Group> SubGroups { get; set; } = new();
|
||||||
|
|
||||||
[XmlElement(ElementName = "Emoji")]
|
[XmlArray(ElementName = "Es")]
|
||||||
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 IEnumerable<IEnumerable<Emoji>> EmojiChunkList => new ChunkHelper<Emoji>(EmojiList, 8);
|
||||||
|
@ -49,12 +51,13 @@ public class Emojis
|
||||||
public IEnumerable<Emoji> EmojiList => SubGroups.SelectMany(s => s.Emojis);
|
public IEnumerable<Emoji> EmojiList => SubGroups.SelectMany(s => s.Emojis);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[XmlType("E")]
|
||||||
public class Emoji
|
public class Emoji
|
||||||
{
|
{
|
||||||
[XmlAttribute]
|
[XmlAttribute(AttributeName = "T")]
|
||||||
public string Text { get; set; }
|
public string Text { get; set; }
|
||||||
|
|
||||||
[XmlArray]
|
[XmlArray(ElementName = "V")]
|
||||||
public List<Emoji> Variations { get; set; } = new();
|
public List<Emoji> Variations { get; set; } = new();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -15,11 +15,6 @@
|
||||||
<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>
|
|
||||||
|
|
||||||
<Target Name="CompressTwemojiMozillaTtfResource" BeforeTargets="BeforeBuild" Condition="!Exists('Drawing\Emoji\TwemojiMozilla.ttf.gz')">
|
<Target Name="CompressTwemojiMozillaTtfResource" BeforeTargets="BeforeBuild" Condition="!Exists('Drawing\Emoji\TwemojiMozilla.ttf.gz')">
|
||||||
<GZipTask InputFile="Drawing\Emoji\TwemojiMozilla.ttf"
|
<GZipTask InputFile="Drawing\Emoji\TwemojiMozilla.ttf"
|
||||||
OutputFile="Drawing\Emoji\TwemojiMozilla.ttf.gz" />
|
OutputFile="Drawing\Emoji\TwemojiMozilla.ttf.gz" />
|
||||||
|
@ -99,10 +94,6 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ContentWithTargetPath Include="Controls\Emoji\emoji-test.txt.gz">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
<TargetPath>emoji-test.txt.gz</TargetPath>
|
|
||||||
</ContentWithTargetPath>
|
|
||||||
<ContentWithTargetPath Include="Drawing\Emoji\TwemojiMozilla.ttf.gz">
|
<ContentWithTargetPath Include="Drawing\Emoji\TwemojiMozilla.ttf.gz">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
<TargetPath>TwemojiMozilla.ttf.gz</TargetPath>
|
<TargetPath>TwemojiMozilla.ttf.gz</TargetPath>
|
||||||
|
|
|
@ -1,21 +1,22 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 16
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 16.0.29728.190
|
VisualStudioVersion = 17.3.32929.385
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot", "Greenshot\Greenshot.csproj", "{CD642BF4-D815-4D67-A0B5-C69F0B8231AF}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot", "Greenshot\Greenshot.csproj", "{CD642BF4-D815-4D67-A0B5-C69F0B8231AF}"
|
||||||
ProjectSection(ProjectDependencies) = postProject
|
ProjectSection(ProjectDependencies) = postProject
|
||||||
{92599C09-FF29-4ABD-B6E6-C48ECD781BAB} = {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}
|
{1893A2E4-A78A-4713-A8E7-E70058DABEE0} = {1893A2E4-A78A-4713-A8E7-E70058DABEE0}
|
||||||
{19FEEF09-313F-43C7-819D-F1BCA782B08B} = {19FEEF09-313F-43C7-819D-F1BCA782B08B}
|
{19FEEF09-313F-43C7-819D-F1BCA782B08B} = {19FEEF09-313F-43C7-819D-F1BCA782B08B}
|
||||||
|
{25C870BE-22BB-4CB8-B274-95DC481F53A7} = {25C870BE-22BB-4CB8-B274-95DC481F53A7}
|
||||||
|
{47F23C86-604E-4CC3-8767-B3D4088F30BB} = {47F23C86-604E-4CC3-8767-B3D4088F30BB}
|
||||||
|
{697CF066-9077-4F22-99D9-D989CCE7282B} = {697CF066-9077-4F22-99D9-D989CCE7282B}
|
||||||
|
{7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E} = {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}
|
||||||
|
{80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50} = {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}
|
||||||
|
{92599C09-FF29-4ABD-B6E6-C48ECD781BAB} = {92599C09-FF29-4ABD-B6E6-C48ECD781BAB}
|
||||||
{9801F62C-540F-4BFE-9211-6405DEDE563B} = {9801F62C-540F-4BFE-9211-6405DEDE563B}
|
{9801F62C-540F-4BFE-9211-6405DEDE563B} = {9801F62C-540F-4BFE-9211-6405DEDE563B}
|
||||||
{9C0ECC4C-7807-4111-916A-4F57BB29788A} = {9C0ECC4C-7807-4111-916A-4F57BB29788A}
|
{9C0ECC4C-7807-4111-916A-4F57BB29788A} = {9C0ECC4C-7807-4111-916A-4F57BB29788A}
|
||||||
{C3052651-598A-44E2-AAB3-2E41311D50F9} = {C3052651-598A-44E2-AAB3-2E41311D50F9}
|
|
||||||
{7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E} = {7EC72A5A-D73A-4B4B-9CA1-2216C7D92D5E}
|
|
||||||
{697CF066-9077-4F22-99D9-D989CCE7282B} = {697CF066-9077-4F22-99D9-D989CCE7282B}
|
|
||||||
{47F23C86-604E-4CC3-8767-B3D4088F30BB} = {47F23C86-604E-4CC3-8767-B3D4088F30BB}
|
|
||||||
{80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50} = {80D8DEB9-94E3-4876-8CCA-2DF1ED5F2C50}
|
|
||||||
{AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12} = {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}
|
{AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12} = {AD7CFFE2-40E7-46CF-A172-D48CF7AE9A12}
|
||||||
{1893A2E4-A78A-4713-A8E7-E70058DABEE0} = {1893A2E4-A78A-4713-A8E7-E70058DABEE0}
|
{C3052651-598A-44E2-AAB3-2E41311D50F9} = {C3052651-598A-44E2-AAB3-2E41311D50F9}
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Base", "Greenshot.Base\Greenshot.Base.csproj", "{5B924697-4DCD-4F98-85F1-105CB84B7341}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Base", "Greenshot.Base\Greenshot.Base.csproj", "{5B924697-4DCD-4F98-85F1-105CB84B7341}"
|
||||||
|
@ -52,6 +53,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Editor", "Greenshot.Editor\Greenshot.Editor.csproj", "{148D3C8B-D6EC-4A7D-80E9-243A81F19DD2}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Editor", "Greenshot.Editor\Greenshot.Editor.csproj", "{148D3C8B-D6EC-4A7D-80E9-243A81F19DD2}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Greenshot.BuildTasks", "Greenshot.BuildTasks\Greenshot.BuildTasks.csproj", "{25C870BE-22BB-4CB8-B274-95DC481F53A7}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -172,6 +175,14 @@ Global
|
||||||
{148D3C8B-D6EC-4A7D-80E9-243A81F19DD2}.Release|Any CPU.Build.0 = Release|Any CPU
|
{148D3C8B-D6EC-4A7D-80E9-243A81F19DD2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{148D3C8B-D6EC-4A7D-80E9-243A81F19DD2}.Release|x86.ActiveCfg = Release|Any CPU
|
{148D3C8B-D6EC-4A7D-80E9-243A81F19DD2}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{148D3C8B-D6EC-4A7D-80E9-243A81F19DD2}.Release|x86.Build.0 = Release|Any CPU
|
{148D3C8B-D6EC-4A7D-80E9-243A81F19DD2}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{25C870BE-22BB-4CB8-B274-95DC481F53A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{25C870BE-22BB-4CB8-B274-95DC481F53A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{25C870BE-22BB-4CB8-B274-95DC481F53A7}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{25C870BE-22BB-4CB8-B274-95DC481F53A7}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{25C870BE-22BB-4CB8-B274-95DC481F53A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{25C870BE-22BB-4CB8-B274-95DC481F53A7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{25C870BE-22BB-4CB8-B274-95DC481F53A7}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{25C870BE-22BB-4CB8-B274-95DC481F53A7}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
|
@ -65,6 +65,12 @@
|
||||||
</Task>
|
</Task>
|
||||||
</UsingTask>
|
</UsingTask>
|
||||||
|
|
||||||
|
<UsingTask TaskName="EmojiDataTask" AssemblyFile="..\Greenshot.BuildTasks\bin\Debug\net472\Greenshot.BuildTasks.dll" />
|
||||||
|
|
||||||
|
<Target Name="GenerateEmojiTestTxtFile" BeforeTargets="BeforeBuild">
|
||||||
|
<EmojiDataTask EmojiTestTxtFile="..\Greenshot.Editor\Controls\Emoji\emoji-test.txt" OutputFilename="$(SolutionDir)$(SolutionName)\$(OutDir)\emojis.xml" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
<Target Name="Generate hashes" BeforeTargets="PostBuildEvent">
|
<Target Name="Generate hashes" BeforeTargets="PostBuildEvent">
|
||||||
<GetFileHash Files="@(FilesToHash)" Algorithm="SHA256" HashEncoding="hex">
|
<GetFileHash Files="@(FilesToHash)" Algorithm="SHA256" HashEncoding="hex">
|
||||||
<Output TaskParameter="Items" ItemName="FilesWithHashes" />
|
<Output TaskParameter="Items" ItemName="FilesWithHashes" />
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue