From be8997119798f0919c519612bccfd5647bb323e8 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sun, 9 Jan 2022 18:05:39 +0100 Subject: [PATCH 01/61] New "Emoji" object in editor --- .../Interfaces/Drawing/Container.cs | 5 + src/Greenshot.Base/Interfaces/DrawingModes.cs | 3 +- src/Greenshot.Base/Interfaces/ISurface.cs | 1 + .../Drawing/EmojiContainer.cs | 191 ++++++++++++++++++ .../Drawing/ImageContainer.cs | 19 +- src/Greenshot.Editor/Drawing/Surface.cs | 14 +- .../Forms/ImageEditorForm.Designer.cs | 27 ++- src/Greenshot.Editor/Forms/ImageEditorForm.cs | 8 +- .../Forms/ImageEditorForm.resx | 3 + src/Greenshot.Editor/Greenshot.Editor.csproj | 7 + .../Resources/btnEmoji.Image.bmp | Bin 0 -> 3382 bytes src/Greenshot/Languages/language-en-US.xml | 3 +- 12 files changed, 262 insertions(+), 19 deletions(-) create mode 100644 src/Greenshot.Editor/Drawing/EmojiContainer.cs create mode 100644 src/Greenshot.Editor/Resources/btnEmoji.Image.bmp diff --git a/src/Greenshot.Base/Interfaces/Drawing/Container.cs b/src/Greenshot.Base/Interfaces/Drawing/Container.cs index 7eb595fdf..1fc35eeb2 100644 --- a/src/Greenshot.Base/Interfaces/Drawing/Container.cs +++ b/src/Greenshot.Base/Interfaces/Drawing/Container.cs @@ -135,6 +135,11 @@ namespace Greenshot.Base.Interfaces.Drawing void Load(string filename); } + public interface IEmojiContainer : IDrawableContainer + { + string Emoji { get; set; } + } + public interface ICursorContainer : IDrawableContainer { Cursor Cursor { get; set; } diff --git a/src/Greenshot.Base/Interfaces/DrawingModes.cs b/src/Greenshot.Base/Interfaces/DrawingModes.cs index cd84aea4f..d406038c5 100644 --- a/src/Greenshot.Base/Interfaces/DrawingModes.cs +++ b/src/Greenshot.Base/Interfaces/DrawingModes.cs @@ -35,6 +35,7 @@ namespace Greenshot.Base.Interfaces Bitmap, Path, SpeechBubble, - StepLabel + StepLabel, + Emoji } } \ No newline at end of file diff --git a/src/Greenshot.Base/Interfaces/ISurface.cs b/src/Greenshot.Base/Interfaces/ISurface.cs index 7b8d6884e..ca0ee3a48 100644 --- a/src/Greenshot.Base/Interfaces/ISurface.cs +++ b/src/Greenshot.Base/Interfaces/ISurface.cs @@ -93,6 +93,7 @@ namespace Greenshot.Base.Interfaces IImageContainer AddImageContainer(string filename, int x, int y); ICursorContainer AddCursorContainer(string filename, int x, int y); IIconContainer AddIconContainer(string filename, int x, int y); + IEmojiContainer AddEmojiContainer(string emoji, int x, int y, int size); long SaveElementsToStream(Stream stream); void LoadElementsFromStream(Stream stream); diff --git a/src/Greenshot.Editor/Drawing/EmojiContainer.cs b/src/Greenshot.Editor/Drawing/EmojiContainer.cs new file mode 100644 index 000000000..cd419d79a --- /dev/null +++ b/src/Greenshot.Editor/Drawing/EmojiContainer.cs @@ -0,0 +1,191 @@ +/* + * 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 . + */ + +using System; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Runtime.Serialization; +using System.Windows; +using System.Windows.Forms; +using System.Windows.Forms.Integration; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using Greenshot.Base.Interfaces.Drawing; +using Greenshot.Editor.Drawing.Adorners; +using Greenshot.Editor.Helpers; +using log4net; +using Point = System.Drawing.Point; +using Size = System.Windows.Size; + +namespace Greenshot.Editor.Drawing +{ + /// + /// Description of EmojiContainer. + /// + [Serializable] + public class EmojiContainer : DrawableContainer, IEmojiContainer + { + private static readonly ILog Log = LogManager.GetLogger(typeof(IconContainer)); + + [NonSerialized] private System.Windows.Controls.Image _image; + + private int _rotateAngle; + private string _emoji; + + public string Emoji + { + get => _emoji; + set + { + _emoji = value; + if (_image != null) + { + global::Emoji.Wpf.Image.SetSource(_image, Emoji); + } + } + } + + public EmojiContainer(Surface parent) : this(parent, "🙂", size: 64) + { + } + + public EmojiContainer(Surface parent, string emoji, int size) : base(parent) + { + Emoji = emoji; + Width = size; + Height = size; + Init(); + } + + public override void OnDoubleClick() + { + var host = new ElementHost(); + host.Dock = DockStyle.None; + var rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); + host.Width = rect.Width; + host.Height = rect.Height; + host.Left = rect.Left; + host.Top = rect.Top; + + var picker = new Emoji.Wpf.Picker { Selection = Emoji }; + picker.Picked += (o, args) => + { + Emoji = args.Emoji; + _parent.Controls.Remove(host); + + }; + host.Child = picker; + + if (_parent != null) + { + _parent.KeysLocked = true; + _parent.Controls.Add(host); + } + + host.Show(); + host.Focus(); + } + + protected override void OnDeserialized(StreamingContext streamingContext) + { + base.OnDeserialized(streamingContext); + Init(); + } + + private void Init() + { + CreateDefaultAdorners(); + + // Create WPF control + _image = new System.Windows.Controls.Image(); + global::Emoji.Wpf.Image.SetSource(_image, Emoji); + } + + public override void Transform(System.Drawing.Drawing2D.Matrix matrix) + { + _rotateAngle += CalculateAngle(matrix); + _rotateAngle %= 360; + base.Transform(matrix); + } + + public override void Draw(Graphics graphics, RenderMode rm) + { + graphics.SmoothingMode = SmoothingMode.HighQuality; + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + graphics.CompositingQuality = CompositingQuality.HighQuality; + graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + + var rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); + + var iconSize = Math.Min(rect.Width, rect.Height); + + if (iconSize > 0) + { + _image.Measure(new Size(iconSize, iconSize)); + _image.Arrange(new Rect(0, 0, iconSize, iconSize)); + + var renderTargetBitmap = new RenderTargetBitmap(iconSize, iconSize, 96, 96, PixelFormats.Pbgra32); + renderTargetBitmap.Render(_image); + + using var bitmap = BitmapFromSource(renderTargetBitmap); + + if (_rotateAngle != 0) + { + graphics.DrawImage(RotateImage(bitmap, _rotateAngle), Bounds); + return; + } + + graphics.DrawImage(bitmap, Bounds); + } + } + private Bitmap BitmapFromSource(BitmapSource bitmapSource) + { + var src = new FormatConvertedBitmap(); + src.BeginInit(); + src.Source = bitmapSource; + src.DestinationFormat = PixelFormats.Bgra32; + src.EndInit(); + + var bitmap = new Bitmap(src.PixelWidth, src.PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb); + var data = bitmap.LockBits(new Rectangle(new Point(0, 0), bitmap.Size), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); + src.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride); + bitmap.UnlockBits(data); + + return bitmap; + } + + private static Image RotateImage(Image img, float rotationAngle) + { + var bitmap = new Bitmap(img.Width, img.Height); + + using var gfx = Graphics.FromImage(bitmap); + gfx.InterpolationMode = InterpolationMode.HighQualityBicubic; + + gfx.TranslateTransform((float)bitmap.Width / 2, (float)bitmap.Height / 2); + gfx.RotateTransform(rotationAngle); + gfx.TranslateTransform(-(float)bitmap.Width / 2, -(float)bitmap.Height / 2); + + gfx.DrawImage(img, new Point(0, 0)); + + return bitmap; + } + } +} \ No newline at end of file diff --git a/src/Greenshot.Editor/Drawing/ImageContainer.cs b/src/Greenshot.Editor/Drawing/ImageContainer.cs index a46b0dae5..5ccf01c4e 100644 --- a/src/Greenshot.Editor/Drawing/ImageContainer.cs +++ b/src/Greenshot.Editor/Drawing/ImageContainer.cs @@ -179,16 +179,19 @@ namespace Greenshot.Editor.Drawing /// public override void Transform(Matrix matrix) { - int rotateAngle = CalculateAngle(matrix); - // we currently assume only one transformation has been made. - if (rotateAngle != 0) + if (image != null) { - Log.DebugFormat("Rotating element with {0} degrees.", rotateAngle); - DisposeShadow(); - using var tmpMatrix = new Matrix(); - using (image) + int rotateAngle = CalculateAngle(matrix); + // we currently assume only one transformation has been made. + if (rotateAngle != 0) { - image = ImageHelper.ApplyEffect(image, new RotateEffect(rotateAngle), tmpMatrix); + Log.DebugFormat("Rotating element with {0} degrees.", rotateAngle); + DisposeShadow(); + using var tmpMatrix = new Matrix(); + using (image) + { + image = ImageHelper.ApplyEffect(image, new RotateEffect(rotateAngle), tmpMatrix); + } } } diff --git a/src/Greenshot.Editor/Drawing/Surface.cs b/src/Greenshot.Editor/Drawing/Surface.cs index 7fd7485d0..644718598 100644 --- a/src/Greenshot.Editor/Drawing/Surface.cs +++ b/src/Greenshot.Editor/Drawing/Surface.cs @@ -1,4 +1,4 @@ -/* +/* * Greenshot - a free and open source screenshot tool * Copyright (C) 2007-2021 Thomas Braun, Jens Klingen, Robin Krom * @@ -748,6 +748,9 @@ namespace Greenshot.Editor.Drawing case DrawingModes.None: _undrawnElement = null; break; + case DrawingModes.Emoji: + _undrawnElement = new EmojiContainer(this); + break; } if (_undrawnElement != null) @@ -802,6 +805,15 @@ namespace Greenshot.Editor.Drawing return iconContainer; } + public IEmojiContainer AddEmojiContainer(string emoji, int x, int y, int size) + { + var iconContainer = new EmojiContainer(this, emoji, size); + iconContainer.Left = x; + iconContainer.Top = y; + AddElement(iconContainer); + return iconContainer; + } + public ICursorContainer AddCursorContainer(Cursor cursor, int x, int y) { CursorContainer cursorContainer = new CursorContainer(this) diff --git a/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs b/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs index 82fecf559..938068f8e 100644 --- a/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs +++ b/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs @@ -70,7 +70,8 @@ namespace Greenshot.Editor.Forms { this.btnText = new GreenshotToolStripButton(); this.btnSpeechBubble = new GreenshotToolStripButton(); this.btnStepLabel = new GreenshotToolStripButton(); - this.toolStripSeparator14 = new System.Windows.Forms.ToolStripSeparator(); + this.btnEmoji = new GreenshotToolStripButton(); + this.toolStripSeparator14 = new System.Windows.Forms.ToolStripSeparator(); this.btnHighlight = new GreenshotToolStripButton(); this.btnObfuscate = new GreenshotToolStripButton(); this.toolStripSplitButton1 = new GreenshotToolStripDropDownButton(); @@ -334,8 +335,9 @@ namespace Greenshot.Editor.Forms { this.btnText, this.btnSpeechBubble, this.btnStepLabel, + this.btnEmoji, this.toolStripSeparator14, - this.btnHighlight, + this.btnHighlight, this.btnObfuscate, this.toolStripSplitButton1, this.toolStripSeparator13, @@ -443,10 +445,20 @@ namespace Greenshot.Editor.Forms { this.btnStepLabel.LanguageKey = "editor_counter"; this.btnStepLabel.Name = "btnStepLabel"; this.btnStepLabel.Click += new System.EventHandler(this.BtnStepLabelClick); - // - // toolStripSeparator14 - // - this.toolStripSeparator14.Name = "toolStripSeparator14"; + // + // btnStepEmoji + // + this.btnEmoji.CheckOnClick = true; + this.btnEmoji.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.btnEmoji.Image = ((System.Drawing.Image)(resources.GetObject("btnEmoji.Image"))); + this.btnEmoji.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnEmoji.LanguageKey = "editor_emoji"; + this.btnEmoji.Name = "btnEmoji"; + this.btnEmoji.Click += new System.EventHandler(this.BtnEmojiClick); + // + // toolStripSeparator14 + // + this.toolStripSeparator14.Name = "toolStripSeparator14"; // // btnHighlight // @@ -1928,7 +1940,8 @@ namespace Greenshot.Editor.Forms { private GreenshotToolStripButton btnText; private GreenshotToolStripButton btnSpeechBubble; private GreenshotToolStripButton btnStepLabel; - private GreenshotToolStripMenuItem drawLineToolStripMenuItem; + private GreenshotToolStripButton btnEmoji; + private GreenshotToolStripMenuItem drawLineToolStripMenuItem; private GreenshotToolStripButton btnLine; private GreenshotToolStripButton btnSettings; private GreenshotToolStripButton btnHelp; diff --git a/src/Greenshot.Editor/Forms/ImageEditorForm.cs b/src/Greenshot.Editor/Forms/ImageEditorForm.cs index e3b65b980..20b4de8cb 100644 --- a/src/Greenshot.Editor/Forms/ImageEditorForm.cs +++ b/src/Greenshot.Editor/Forms/ImageEditorForm.cs @@ -269,7 +269,7 @@ namespace Greenshot.Editor.Forms _toolbarButtons = new[] { - btnCursor, btnRect, btnEllipse, btnText, btnLine, btnArrow, btnFreehand, btnHighlight, btnObfuscate, btnCrop, btnStepLabel, btnSpeechBubble + btnCursor, btnRect, btnEllipse, btnText, btnLine, btnArrow, btnFreehand, btnHighlight, btnObfuscate, btnCrop, btnStepLabel, btnSpeechBubble, btnEmoji }; //toolbarDropDownButtons = new ToolStripDropDownButton[]{btnBlur, btnPixeliate, btnTextHighlighter, btnAreaHighlighter, btnMagnifier}; @@ -655,6 +655,12 @@ namespace Greenshot.Editor.Forms RefreshFieldControls(); } + private void BtnEmojiClick(object sender, EventArgs e) + { + _surface.DrawingMode = DrawingModes.Emoji; + RefreshFieldControls(); + } + private void BtnLineClick(object sender, EventArgs e) { _surface.DrawingMode = DrawingModes.Line; diff --git a/src/Greenshot.Editor/Forms/ImageEditorForm.resx b/src/Greenshot.Editor/Forms/ImageEditorForm.resx index 57fe2f2c7..63524f930 100644 --- a/src/Greenshot.Editor/Forms/ImageEditorForm.resx +++ b/src/Greenshot.Editor/Forms/ImageEditorForm.resx @@ -1107,4 +1107,7 @@ 782, 17 + + ..\Resources\btnEmoji.Image.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/src/Greenshot.Editor/Greenshot.Editor.csproj b/src/Greenshot.Editor/Greenshot.Editor.csproj index 768bdb99d..601a9f38d 100644 --- a/src/Greenshot.Editor/Greenshot.Editor.csproj +++ b/src/Greenshot.Editor/Greenshot.Editor.csproj @@ -4,6 +4,9 @@ PreserveNewest + + + @@ -81,4 +84,8 @@ ImageEditorForm.cs + + + + \ No newline at end of file diff --git a/src/Greenshot.Editor/Resources/btnEmoji.Image.bmp b/src/Greenshot.Editor/Resources/btnEmoji.Image.bmp new file mode 100644 index 0000000000000000000000000000000000000000..fa6bf1b076793830904adce758867d9a57163a1a GIT binary patch literal 3382 zcmc(gzm6m|5Qpm|q#jO!XK+YJbZJ``(IjP@p#N1sr&YkRU^W+I$pn;2}bS3##df!cf(aNr?Af(!-fxZe)zA@+MO8C#&X##df!dN6aNr?Af(!*} zOHsgqhX@HW6sY!`rR1<4A|%LApth6+9C(P3AVY!LQW0?AAwq%-1!_xGz=4Md2{II@ ztq9M#IPef5L52dg6(``pLxcnw3e;A-fCCQ^5@aY)TZsY=JVZ#4p+IdV2{`Z&Awh-$ zwUsR3z(a%t846V1Q2_@YA|%M|&#ko|z7so7k=Dd&qhpSC;D0H{n-D~nt8laX_w|oK z_P5h%-sV3}w|fbP_n(T{NjPouwsKKv{|e9Fz5l0>>DAR~CbO#V%`q%fd$PP)-fBt} zW3*?H>(9%fJyCA1CX=1hk9BmRW&g20gl#72Y+1GKoxa|6cpPxJR)Ow8TW!q2r?+m` zHy;M<#1y6)O%EC==H>1(U|J?Jtt7^bMY_c&e%&^?Jf(1_I-Ow-p@sJT2%k?&yDyWN zc(vRcZHKJmP&MfJ>0Td>sw9SnKdcW*-yNw=ug>~u(H$bUh9C`8Ut7$u;k>}jn}@;m zyv}_H9Sfaz-?v_bJeJ9t^StF%rB*`LZM`K70MzXbOu`rFvKkQP<|??bP*$!^q0GUF)S?8M1+OyY2UD z`ex+l`Iyv&Fec;`=$&~B;}zq8x=3%~c#(UK)+>$J5&DJDt@{NO)_JCS?TG z>AIiQyuI1CUU)!l3IXa~RZ15_yK1|hx5J6rXVXSCf{v=q5}`vR+&#STETCzqOj)OU z^cm2~^yOza9Bk0m*C^GYzQ9ib~V&+x%t-1K{&L&!b9HGBA@<)ndGSV zt)B`TvWh)D-uqafO=0N|OV7G$=r&!w8jsmoc44O_{Ki?^Dw>{CUmhLIg<8A2YyP8; f6EV~Au=o4pqxmP?>97xrEMb56bm}KU|NGG2fasv9 literal 0 HcmV?d00001 diff --git a/src/Greenshot/Languages/language-en-US.xml b/src/Greenshot/Languages/language-en-US.xml index 3db9fbf0e..09570f11f 100644 --- a/src/Greenshot/Languages/language-en-US.xml +++ b/src/Greenshot/Languages/language-en-US.xml @@ -305,8 +305,9 @@ All Greenshot features still work directly from the tray icon context menu witho Add counter (I) Add speechbubble (S) + Add emoji - Resize + Resize Resize settings Maintain aspect ratio Width From 3705bc8655c8db9e1fd52328de3e3f560235a34c Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sun, 9 Jan 2022 19:15:51 +0100 Subject: [PATCH 02/61] Update icon --- src/Greenshot.Editor/Forms/ImageEditorForm.resx | 2 +- .../Resources/btnEmoji.Image.png | Bin 0 -> 1464 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 src/Greenshot.Editor/Resources/btnEmoji.Image.png diff --git a/src/Greenshot.Editor/Forms/ImageEditorForm.resx b/src/Greenshot.Editor/Forms/ImageEditorForm.resx index 63524f930..d89c06507 100644 --- a/src/Greenshot.Editor/Forms/ImageEditorForm.resx +++ b/src/Greenshot.Editor/Forms/ImageEditorForm.resx @@ -1108,6 +1108,6 @@ 782, 17 - ..\Resources\btnEmoji.Image.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + ..\Resources\btnEmoji.Image.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a \ No newline at end of file diff --git a/src/Greenshot.Editor/Resources/btnEmoji.Image.png b/src/Greenshot.Editor/Resources/btnEmoji.Image.png new file mode 100644 index 0000000000000000000000000000000000000000..e11114bfe09e4a50ff7ac7c732f727365ce8f915 GIT binary patch literal 1464 zcmV;p1xNacP)?BU?*c3>dq?Ae~btou=zsL?Ey+~RlDpU$ZA^hA#q6h@?MI)*p z`2q=u#6=NOEu{h#NQ8t$DiEl|4N-#~iP&vT6{V@|2F3qtdw0FN{=WI);@h}{;Fh_Y zqj%0ZbM(IRj_?kvI7~h`_KV`6Ho6;V3qi1nUa<8r?ySBjL?ibcE>$p}Ptchv~_8>>4%g4-vQ@ z(M^qnvJMPs|Bbz*b#6y}9bX+~>Dnb$ri%OS`%-!n0azL#kI^r*-23I;p!eb|l#3O- zb11E8+189Pnh@S@+&f39SivU_Z8XhWo6*|gD_6OB=}#A2-5mYk6N^=oR_9nt*Jpa2 z--WkTW+&!(_WQqFAKf>8{1rO7+R;V>V69_za-L_ucQ;05_t5dcgMI&cdF&YQb17aX z-_*8e)wCYQ`Yp^&%`@14j;{_pN`6z0YN^JVr+&xRfAj^m?`%VW*{MYa`_FEOQGS-< z>sMI5F;h@J$bOxF56(qYii-^PpW|x-57W7`g)MCn9Xp#jKJYMu{pYAG7AY5t4ECSp z_`oA{>}*akJDNE@@W?tQkf-^*y9w6qm&KRW51KkZbV`~&j&q(`IVRT&UtE;m|Sxj4@sFDe|+I-qqOR_t23x%9LemWP!NJ!!@IXRrVt8+ zK=5k-z zUO&$1PO#jC&O0{QJJ5nNha9+0n7IHZz7l1C?kjnA*4#S)>E9RvoKv_ zZZ6Bxax2-*@8jr^A*6B5WG&1Z8_T$gJl<*$s7#OXk;evDnHc4b(IG~MZ;{Cxq9}vX z8c;ZEiR&@-RZo;{<+I;Bg%sNP^XbR&NvduMf?eZPV`F_W8#$~^MU>?__2oHwzxXZW z@h1tvN z;I|2D6+U+435+r5D09b)t4&H*?>*&8g`wa4jPdh7;qd1SJ_fCY@@x#K5q~A)>(g9&=`8y` z3cGe|1Yxc0S(uDZeB$KFWdWG_{nosg_`Fe>zO~h~yH`gouZ=mX)$mTHM?Nof_h@=P zY}TLL*@@bPu%?b4IJsP1AMBgwT6?0b9}UhB*9{^tH{%(9#nE+XGm%wyBu~$qr4DPUa)-!PgRCCw9IS2+Sa4BKi!m7ecozpEO-z2h8NsEPrzka4I@0~wpBAzkE5Ih7YsY3$Nn3i{e)ly7#$(}IA zJa^#aa`pfERoq^${bF0*TE8E{K_qm0AKJVHZ^MF17!OWeRH8->Jhimpx8>hv|Gmu? S9Km`30000 Date: Fri, 14 Jan 2022 10:06:47 +0100 Subject: [PATCH 03/61] Fix installer --- installer/innosetup/setup.iss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/installer/innosetup/setup.iss b/installer/innosetup/setup.iss index 449cf2014..b4d7b878d 100644 --- a/installer/innosetup/setup.iss +++ b/installer/innosetup/setup.iss @@ -30,6 +30,9 @@ Source: {#ReleaseDir}\Svg.dll; DestDir: {app}; Components: greenshot; Flags: ove Source: {#ReleaseDir}\Fizzler.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\HtmlAgilityPack.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\Newtonsoft.Json.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion +Source: {#ReleaseDir}\Emoji.Wpf.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion +Source: {#ReleaseDir}\Typography.GlyphLayout.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion +Source: {#ReleaseDir}\Typography.OpenFont.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#GreenshotProjectDir}\log4net.xml; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion Source: {#ReleaseDir}\checksum.SHA256; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion ;Source: ..\greenshot-defaults.ini; DestDir: {app}; Flags: overwritereadonly ignoreversion replacesameversion From 9d9ef126199bfe9f38649bab925ca66f147b9707 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Fri, 14 Jan 2022 10:08:13 +0100 Subject: [PATCH 04/61] Misc improvements --- .../Drawing/EmojiContainer.cs | 98 ++++++++++++++----- 1 file changed, 73 insertions(+), 25 deletions(-) diff --git a/src/Greenshot.Editor/Drawing/EmojiContainer.cs b/src/Greenshot.Editor/Drawing/EmojiContainer.cs index cd419d79a..568251659 100644 --- a/src/Greenshot.Editor/Drawing/EmojiContainer.cs +++ b/src/Greenshot.Editor/Drawing/EmojiContainer.cs @@ -29,7 +29,6 @@ using System.Windows.Forms.Integration; using System.Windows.Media; using System.Windows.Media.Imaging; using Greenshot.Base.Interfaces.Drawing; -using Greenshot.Editor.Drawing.Adorners; using Greenshot.Editor.Helpers; using log4net; using Point = System.Drawing.Point; @@ -46,8 +45,9 @@ namespace Greenshot.Editor.Drawing private static readonly ILog Log = LogManager.GetLogger(typeof(IconContainer)); [NonSerialized] private System.Windows.Controls.Image _image; + [NonSerialized] private ElementHost _emojiPicker; + [NonSerialized] private bool _firstSelection = true; - private int _rotateAngle; private string _emoji; public string Emoji @@ -77,33 +77,53 @@ namespace Greenshot.Editor.Drawing public override void OnDoubleClick() { - var host = new ElementHost(); - host.Dock = DockStyle.None; - var rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); - host.Width = rect.Width; - host.Height = rect.Height; - host.Left = rect.Left; - host.Top = rect.Top; + ShowEmojiPicker(); + } - var picker = new Emoji.Wpf.Picker { Selection = Emoji }; - picker.Picked += (o, args) => + private void ShowEmojiPicker() + { + if (_emojiPicker == null) { - Emoji = args.Emoji; - _parent.Controls.Remove(host); + var picker = new Emoji.Wpf.Picker(); + picker.Picked += (_, args) => + { + Emoji = args.Emoji; + Invalidate(); + }; - }; - host.Child = picker; + _emojiPicker = new ElementHost(); + _emojiPicker.Dock = DockStyle.None; + _emojiPicker.Child = picker; + } + + var emojiPickerChild = ((Emoji.Wpf.Picker)_emojiPicker.Child); + emojiPickerChild.Selection = Emoji; + + var absRectangle = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); + var displayRectangle = Parent.ToSurfaceCoordinates(absRectangle); + _emojiPicker.Width = 0; // Trick to hide the picker's button + _emojiPicker.Height = displayRectangle.Height; + _emojiPicker.Left = displayRectangle.Left; + _emojiPicker.Top = displayRectangle.Top; if (_parent != null) { _parent.KeysLocked = true; - _parent.Controls.Add(host); + _parent.Controls.Add(_emojiPicker); } - host.Show(); - host.Focus(); + emojiPickerChild.ShowPopup = true; } + private void HideEmojiPicker() + { + if (_parent != null && _emojiPicker != null) + { + _parent.Controls.Remove(_emojiPicker); + } + } + + protected override void OnDeserialized(StreamingContext streamingContext) { base.OnDeserialized(streamingContext); @@ -113,17 +133,28 @@ namespace Greenshot.Editor.Drawing private void Init() { CreateDefaultAdorners(); - + // Create WPF control _image = new System.Windows.Controls.Image(); global::Emoji.Wpf.Image.SetSource(_image, Emoji); + + PropertyChanged += OnPropertyChanged; } - public override void Transform(System.Drawing.Drawing2D.Matrix matrix) + private void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { - _rotateAngle += CalculateAngle(matrix); - _rotateAngle %= 360; - base.Transform(matrix); + if (e.PropertyName.Equals(nameof(Selected))) + { + if (!Selected) + { + HideEmojiPicker(); + } + else if (Status == EditStatus.IDLE && _firstSelection) + { + ShowEmojiPicker(); + _firstSelection = false; + } + } } public override void Draw(Graphics graphics, RenderMode rm) @@ -147,15 +178,32 @@ namespace Greenshot.Editor.Drawing using var bitmap = BitmapFromSource(renderTargetBitmap); - if (_rotateAngle != 0) + var rotationAngle = GetRotationAngle(); + if (rotationAngle != 0) { - graphics.DrawImage(RotateImage(bitmap, _rotateAngle), Bounds); + graphics.DrawImage(RotateImage(bitmap, rotationAngle), Bounds); return; } graphics.DrawImage(bitmap, Bounds); } } + + private int GetRotationAngle() + { + int rotationAngle = 0; + if (Width < 0) + { + rotationAngle = Height > 0 ? 90 : 180; + } + else if (Height < 0) + { + rotationAngle = 270; + } + + return rotationAngle; + } + private Bitmap BitmapFromSource(BitmapSource bitmapSource) { var src = new FormatConvertedBitmap(); From 0d15124cae44354163a4cd9617445d7646d816e8 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Fri, 14 Jan 2022 10:14:08 +0100 Subject: [PATCH 05/61] Use "emoji" --- src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs | 2 +- src/Greenshot/Languages/language-en-US.xml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs b/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs index 938068f8e..ebcf30031 100644 --- a/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs +++ b/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs @@ -452,7 +452,7 @@ namespace Greenshot.Editor.Forms { this.btnEmoji.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; this.btnEmoji.Image = ((System.Drawing.Image)(resources.GetObject("btnEmoji.Image"))); this.btnEmoji.ImageTransparentColor = System.Drawing.Color.Magenta; - this.btnEmoji.LanguageKey = "editor_emoji"; + this.btnEmoji.Text = "Emoji"; this.btnEmoji.Name = "btnEmoji"; this.btnEmoji.Click += new System.EventHandler(this.BtnEmojiClick); // diff --git a/src/Greenshot/Languages/language-en-US.xml b/src/Greenshot/Languages/language-en-US.xml index 09570f11f..3db9fbf0e 100644 --- a/src/Greenshot/Languages/language-en-US.xml +++ b/src/Greenshot/Languages/language-en-US.xml @@ -305,9 +305,8 @@ All Greenshot features still work directly from the tray icon context menu witho Add counter (I) Add speechbubble (S) - Add emoji - Resize + Resize Resize settings Maintain aspect ratio Width From aac7354a6e85d344d6c4afcc11965e8b0a4e2516 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Fri, 14 Jan 2022 14:21:18 +0100 Subject: [PATCH 06/61] Fixes --- installer/innosetup/setup.iss | 1 + .../Drawing/EmojiContainer.cs | 58 ++++++------ src/Greenshot.Editor/Forms/ImageEditorForm.cs | 91 ++++++++++--------- 3 files changed, 79 insertions(+), 71 deletions(-) diff --git a/installer/innosetup/setup.iss b/installer/innosetup/setup.iss index b4d7b878d..6c5345c69 100644 --- a/installer/innosetup/setup.iss +++ b/installer/innosetup/setup.iss @@ -33,6 +33,7 @@ Source: {#ReleaseDir}\Newtonsoft.Json.dll; DestDir: {app}; Components: greenshot Source: {#ReleaseDir}\Emoji.Wpf.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\Typography.GlyphLayout.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\Typography.OpenFont.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion +Source: {#ReleaseDir}\Stfu.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#GreenshotProjectDir}\log4net.xml; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion Source: {#ReleaseDir}\checksum.SHA256; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion ;Source: ..\greenshot-defaults.ini; DestDir: {app}; Flags: overwritereadonly ignoreversion replacesameversion diff --git a/src/Greenshot.Editor/Drawing/EmojiContainer.cs b/src/Greenshot.Editor/Drawing/EmojiContainer.cs index 568251659..b4153709f 100644 --- a/src/Greenshot.Editor/Drawing/EmojiContainer.cs +++ b/src/Greenshot.Editor/Drawing/EmojiContainer.cs @@ -44,8 +44,11 @@ namespace Greenshot.Editor.Drawing { private static readonly ILog Log = LogManager.GetLogger(typeof(IconContainer)); + [NonSerialized] private static EmojiContainer _currentContainer; + [NonSerialized] private static ElementHost _emojiPickerHost; + [NonSerialized] private static Emoji.Wpf.Picker _emojiPicker; + [NonSerialized] private System.Windows.Controls.Image _image; - [NonSerialized] private ElementHost _emojiPicker; [NonSerialized] private bool _firstSelection = true; private string _emoji; @@ -82,44 +85,45 @@ namespace Greenshot.Editor.Drawing private void ShowEmojiPicker() { - if (_emojiPicker == null) - { - var picker = new Emoji.Wpf.Picker(); - picker.Picked += (_, args) => - { - Emoji = args.Emoji; - Invalidate(); - }; + _currentContainer = this; - _emojiPicker = new ElementHost(); - _emojiPicker.Dock = DockStyle.None; - _emojiPicker.Child = picker; - } - - var emojiPickerChild = ((Emoji.Wpf.Picker)_emojiPicker.Child); - emojiPickerChild.Selection = Emoji; + CreatePickerControl(); var absRectangle = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); var displayRectangle = Parent.ToSurfaceCoordinates(absRectangle); - _emojiPicker.Width = 0; // Trick to hide the picker's button - _emojiPicker.Height = displayRectangle.Height; - _emojiPicker.Left = displayRectangle.Left; - _emojiPicker.Top = displayRectangle.Top; + _emojiPickerHost.Width = 0; // Trick to hide the picker's button + _emojiPickerHost.Height = displayRectangle.Height; + _emojiPickerHost.Left = displayRectangle.Left; + _emojiPickerHost.Top = displayRectangle.Top; - if (_parent != null) + _emojiPicker.Selection = Emoji; + _emojiPicker.ShowPopup = true; + } + + private void CreatePickerControl() + { + if (_emojiPickerHost == null) { - _parent.KeysLocked = true; - _parent.Controls.Add(_emojiPicker); - } + _emojiPicker = new Emoji.Wpf.Picker(); + _emojiPicker.Picked += (_, args) => + { + _currentContainer.Emoji = args.Emoji; + _currentContainer.Invalidate(); + }; - emojiPickerChild.ShowPopup = true; + _emojiPickerHost = new ElementHost(); + _emojiPickerHost.Dock = DockStyle.None; + _emojiPickerHost.Child = _emojiPicker; + + _parent.Controls.Add(_emojiPickerHost); + } } private void HideEmojiPicker() { - if (_parent != null && _emojiPicker != null) + if (_emojiPicker != null) { - _parent.Controls.Remove(_emojiPicker); + _emojiPicker.ShowPopup = false; } } diff --git a/src/Greenshot.Editor/Forms/ImageEditorForm.cs b/src/Greenshot.Editor/Forms/ImageEditorForm.cs index 20b4de8cb..94adc751b 100644 --- a/src/Greenshot.Editor/Forms/ImageEditorForm.cs +++ b/src/Greenshot.Editor/Forms/ImageEditorForm.cs @@ -321,37 +321,37 @@ namespace Greenshot.Editor.Forms /// private void AddDestinations() { - Invoke((MethodInvoker) delegate - { - // Create export buttons - foreach (IDestination destination in DestinationHelper.GetAllDestinations()) - { - if (destination.Priority <= 2) - { - continue; - } + Invoke((MethodInvoker)delegate + { + // Create export buttons + foreach (IDestination destination in DestinationHelper.GetAllDestinations()) + { + if (destination.Priority <= 2) + { + continue; + } - if (!destination.IsActive) - { - continue; - } + if (!destination.IsActive) + { + continue; + } - if (destination.DisplayIcon == null) - { - continue; - } + if (destination.DisplayIcon == null) + { + continue; + } - try - { - AddDestinationButton(destination); - } - catch (Exception addingException) - { - Log.WarnFormat("Problem adding destination {0}", destination.Designation); - Log.Warn("Exception: ", addingException); - } - } - }); + try + { + AddDestinationButton(destination); + } + catch (Exception addingException) + { + Log.WarnFormat("Problem adding destination {0}", destination.Designation); + Log.Warn("Exception: ", addingException); + } + } + }); } private void AddDestinationButton(IDestination toolstripDestination) @@ -579,6 +579,9 @@ namespace Greenshot.Editor.Forms case DrawingModes.Path: SetButtonChecked(btnFreehand); break; + case DrawingModes.Emoji: + SetButtonChecked(btnEmoji); + break; } } @@ -611,7 +614,7 @@ namespace Greenshot.Editor.Forms private void BtnPrintClick(object sender, EventArgs e) { // The BeginInvoke is a solution for the printdialog not having focus - BeginInvoke((MethodInvoker) delegate { DestinationHelper.ExportCapture(true, WellKnownDestinations.Printer, _surface, _surface.CaptureDetails); }); + BeginInvoke((MethodInvoker)delegate { DestinationHelper.ExportCapture(true, WellKnownDestinations.Printer, _surface, _surface.CaptureDetails); }); } private void CloseToolStripMenuItemClick(object sender, EventArgs e) @@ -1270,9 +1273,9 @@ namespace Greenshot.Editor.Forms textVerticalAlignmentButton.Visible = props.HasFieldValue(FieldType.TEXT_VERTICAL_ALIGNMENT); shadowButton.Visible = props.HasFieldValue(FieldType.SHADOW); counterLabel.Visible = counterUpDown.Visible = props.HasFieldValue(FieldType.FLAGS) - && ((FieldFlag) props.GetFieldValue(FieldType.FLAGS) & FieldFlag.COUNTER) == FieldFlag.COUNTER; + && ((FieldFlag)props.GetFieldValue(FieldType.FLAGS) & FieldFlag.COUNTER) == FieldFlag.COUNTER; btnConfirm.Visible = btnCancel.Visible = props.HasFieldValue(FieldType.FLAGS) - && ((FieldFlag) props.GetFieldValue(FieldType.FLAGS) & FieldFlag.CONFIRMABLE) == FieldFlag.CONFIRMABLE; + && ((FieldFlag)props.GetFieldValue(FieldType.FLAGS) & FieldFlag.CONFIRMABLE) == FieldFlag.CONFIRMABLE; obfuscateModeButton.Visible = props.HasFieldValue(FieldType.PREPARED_FILTER_OBFUSCATE); highlightModeButton.Visible = props.HasFieldValue(FieldType.PREPARED_FILTER_HIGHLIGHT); @@ -1302,11 +1305,11 @@ namespace Greenshot.Editor.Forms Image icon; if (stepLabels <= 20) { - icon = (Image) resources.GetObject($"btnStepLabel{stepLabels:00}.Image"); + icon = (Image)resources.GetObject($"btnStepLabel{stepLabels:00}.Image"); } else { - icon = (Image) resources.GetObject("btnStepLabel20+.Image"); + icon = (Image)resources.GetObject("btnStepLabel20+.Image"); } btnStepLabel.Image = icon; @@ -1315,7 +1318,7 @@ namespace Greenshot.Editor.Forms FieldAggregator props = _surface.FieldAggregator; // if a confirmable element is selected, we must disable most of the controls // since we demand confirmation or cancel for confirmable element - if (props.HasFieldValue(FieldType.FLAGS) && ((FieldFlag) props.GetFieldValue(FieldType.FLAGS) & FieldFlag.CONFIRMABLE) == FieldFlag.CONFIRMABLE) + if (props.HasFieldValue(FieldType.FLAGS) && ((FieldFlag)props.GetFieldValue(FieldType.FLAGS) & FieldFlag.CONFIRMABLE) == FieldFlag.CONFIRMABLE) { // disable most controls if (!_controlsDisabledDueToConfirmable) @@ -1506,14 +1509,14 @@ namespace Greenshot.Editor.Forms return; } - clickedDestination = (IDestination) clickedControl.Tag; + clickedDestination = (IDestination)clickedControl.Tag; } else { if (sender is ToolStripMenuItem item) { ToolStripMenuItem clickedMenuItem = item; - clickedDestination = (IDestination) clickedMenuItem.Tag; + clickedDestination = (IDestination)clickedMenuItem.Tag; } } @@ -1550,17 +1553,17 @@ namespace Greenshot.Editor.Forms private void Insert_window_toolstripmenuitemMouseEnter(object sender, EventArgs e) { - ToolStripMenuItem captureWindowMenuItem = (ToolStripMenuItem) sender; + ToolStripMenuItem captureWindowMenuItem = (ToolStripMenuItem)sender; var mainForm = SimpleServiceProvider.Current.GetInstance(); mainForm.AddCaptureWindowMenuItems(captureWindowMenuItem, Contextmenu_window_Click); } private void Contextmenu_window_Click(object sender, EventArgs e) { - ToolStripMenuItem clickedItem = (ToolStripMenuItem) sender; + ToolStripMenuItem clickedItem = (ToolStripMenuItem)sender; try { - WindowDetails windowToCapture = (WindowDetails) clickedItem.Tag; + WindowDetails windowToCapture = (WindowDetails)clickedItem.Tag; ICapture capture = new Capture(); using (Graphics graphics = Graphics.FromHwnd(Handle)) { @@ -1575,8 +1578,8 @@ namespace Greenshot.Editor.Forms capture = captureHelper.CaptureWindow(windowToCapture, capture, coreConfiguration.WindowCaptureMode); if (capture?.CaptureDetails != null && capture.Image != null) { - ((Bitmap) capture.Image).SetResolution(capture.CaptureDetails.DpiX, capture.CaptureDetails.DpiY); - _surface.AddImageContainer((Bitmap) capture.Image, 100, 100); + ((Bitmap)capture.Image).SetResolution(capture.CaptureDetails.DpiX, capture.CaptureDetails.DpiY); + _surface.AddImageContainer((Bitmap)capture.Image, 100, 100); } Activate(); @@ -1756,7 +1759,7 @@ namespace Greenshot.Editor.Forms var canvas = Surface as Control; Size canvasSize = canvas.Size; Size currentClientSize = panel1.ClientSize; - Panel panel = (Panel) canvas?.Parent; + Panel panel = (Panel)canvas?.Parent; if (panel == null) { return; @@ -1849,8 +1852,8 @@ namespace Greenshot.Editor.Forms private void ZoomSetValueMenuItemClick(object sender, EventArgs e) { - var senderMenuItem = (ToolStripMenuItem) sender; - var nextValue = Fraction.Parse((string) senderMenuItem.Tag); + var senderMenuItem = (ToolStripMenuItem)sender; + var nextValue = Fraction.Parse((string)senderMenuItem.Tag); ZoomSetValue(nextValue); } From 4a635c409f731788698c67fc82e1cea23e6745f1 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Fri, 14 Jan 2022 14:28:00 +0100 Subject: [PATCH 07/61] Hide button --- src/Greenshot.Editor/Forms/ImageEditorForm.cs | 23 ++++++++++++++----- 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/Greenshot.Editor/Forms/ImageEditorForm.cs b/src/Greenshot.Editor/Forms/ImageEditorForm.cs index 94adc751b..ba470ec56 100644 --- a/src/Greenshot.Editor/Forms/ImageEditorForm.cs +++ b/src/Greenshot.Editor/Forms/ImageEditorForm.cs @@ -25,6 +25,7 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Drawing.Imaging; using System.IO; +using System.Linq; using System.Threading; using System.Windows.Forms; using Greenshot.Base; @@ -183,6 +184,16 @@ 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() + { + if (!FontFamily.Families.Any(f => string.Equals(f.Name, "Segoe UI Emoji", StringComparison.OrdinalIgnoreCase))) + { + btnEmoji.Visible = false; + } } /// @@ -1201,7 +1212,7 @@ namespace Greenshot.Editor.Forms private void StatusLabelClicked(object sender, MouseEventArgs e) { - ToolStrip ss = (StatusStrip) ((ToolStripStatusLabel) sender).Owner; + ToolStrip ss = (StatusStrip)((ToolStripStatusLabel)sender).Owner; ss.ContextMenuStrip?.Show(ss, e.X, e.Y); } @@ -1366,7 +1377,7 @@ namespace Greenshot.Editor.Forms private void ArrowHeadsToolStripMenuItemClick(object sender, EventArgs e) { - _surface.FieldAggregator.GetField(FieldType.ARROWHEADS).Value = (ArrowContainer.ArrowHeadCombination) ((ToolStripMenuItem) sender).Tag; + _surface.FieldAggregator.GetField(FieldType.ARROWHEADS).Value = (ArrowContainer.ArrowHeadCombination)((ToolStripMenuItem)sender).Tag; } private void EditToolStripMenuItemClick(object sender, EventArgs e) @@ -1866,7 +1877,7 @@ namespace Greenshot.Editor.Forms var imageSize = Surface.Image.Size; static bool isFit(Fraction scale, int source, int boundary) - => (int) (source * scale) <= boundary; + => (int)(source * scale) <= boundary; var nextIndex = Array.FindLastIndex( ZOOM_VALUES, @@ -1928,7 +1939,7 @@ namespace Greenshot.Editor.Forms AlignCanvasPositionAfterResize(); // Update zoom controls - zoomStatusDropDownBtn.Text = ((int) (100 * (double) value)).ToString() + "%"; + zoomStatusDropDownBtn.Text = ((int)(100 * (double)value)).ToString() + "%"; var valueString = value.ToString(); foreach (var item in zoomMenuStrip.Items) { @@ -1942,8 +1953,8 @@ namespace Greenshot.Editor.Forms rc = surface.GetVisibleRectangle(); size = surface.Size; panel.AutoScrollPosition = new Point( - (int) (horizontalCenter * size.Width) - rc.Width / 2, - (int) (verticalCenter * size.Height) - rc.Height / 2 + (int)(horizontalCenter * size.Width) - rc.Width / 2, + (int)(verticalCenter * size.Height) - rc.Height / 2 ); } } From 25fc135b2ec294ae2f8c014a16e0c7e176873ea3 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Fri, 14 Jan 2022 15:35:25 +0100 Subject: [PATCH 08/61] Fix picker with multiple editors --- src/Greenshot.Editor/Drawing/EmojiContainer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Greenshot.Editor/Drawing/EmojiContainer.cs b/src/Greenshot.Editor/Drawing/EmojiContainer.cs index b4153709f..2dfeb2484 100644 --- a/src/Greenshot.Editor/Drawing/EmojiContainer.cs +++ b/src/Greenshot.Editor/Drawing/EmojiContainer.cs @@ -89,6 +89,8 @@ namespace Greenshot.Editor.Drawing CreatePickerControl(); + _parent.Controls.Add(_emojiPickerHost); + var absRectangle = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); var displayRectangle = Parent.ToSurfaceCoordinates(absRectangle); _emojiPickerHost.Width = 0; // Trick to hide the picker's button @@ -114,8 +116,6 @@ namespace Greenshot.Editor.Drawing _emojiPickerHost = new ElementHost(); _emojiPickerHost.Dock = DockStyle.None; _emojiPickerHost.Child = _emojiPicker; - - _parent.Controls.Add(_emojiPickerHost); } } From f57691e5f343d4173cc07d53187e91968cc04b9d Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Fri, 14 Jan 2022 17:22:49 +0100 Subject: [PATCH 09/61] Revert formatting changes --- src/Greenshot.Editor/Forms/ImageEditorForm.cs | 100 +++++++++--------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/src/Greenshot.Editor/Forms/ImageEditorForm.cs b/src/Greenshot.Editor/Forms/ImageEditorForm.cs index ba470ec56..d717b3953 100644 --- a/src/Greenshot.Editor/Forms/ImageEditorForm.cs +++ b/src/Greenshot.Editor/Forms/ImageEditorForm.cs @@ -332,37 +332,37 @@ namespace Greenshot.Editor.Forms /// private void AddDestinations() { - Invoke((MethodInvoker)delegate - { - // Create export buttons - foreach (IDestination destination in DestinationHelper.GetAllDestinations()) - { - if (destination.Priority <= 2) - { - continue; - } + Invoke((MethodInvoker) delegate + { + // Create export buttons + foreach (IDestination destination in DestinationHelper.GetAllDestinations()) + { + if (destination.Priority <= 2) + { + continue; + } - if (!destination.IsActive) - { - continue; - } + if (!destination.IsActive) + { + continue; + } - if (destination.DisplayIcon == null) - { - continue; - } + if (destination.DisplayIcon == null) + { + continue; + } - try - { - AddDestinationButton(destination); - } - catch (Exception addingException) - { - Log.WarnFormat("Problem adding destination {0}", destination.Designation); - Log.Warn("Exception: ", addingException); - } - } - }); + try + { + AddDestinationButton(destination); + } + catch (Exception addingException) + { + Log.WarnFormat("Problem adding destination {0}", destination.Designation); + Log.Warn("Exception: ", addingException); + } + } + }); } private void AddDestinationButton(IDestination toolstripDestination) @@ -625,7 +625,7 @@ namespace Greenshot.Editor.Forms private void BtnPrintClick(object sender, EventArgs e) { // The BeginInvoke is a solution for the printdialog not having focus - BeginInvoke((MethodInvoker)delegate { DestinationHelper.ExportCapture(true, WellKnownDestinations.Printer, _surface, _surface.CaptureDetails); }); + BeginInvoke((MethodInvoker) delegate { DestinationHelper.ExportCapture(true, WellKnownDestinations.Printer, _surface, _surface.CaptureDetails); }); } private void CloseToolStripMenuItemClick(object sender, EventArgs e) @@ -1212,7 +1212,7 @@ namespace Greenshot.Editor.Forms private void StatusLabelClicked(object sender, MouseEventArgs e) { - ToolStrip ss = (StatusStrip)((ToolStripStatusLabel)sender).Owner; + ToolStrip ss = (StatusStrip) ((ToolStripStatusLabel) sender).Owner; ss.ContextMenuStrip?.Show(ss, e.X, e.Y); } @@ -1284,9 +1284,9 @@ namespace Greenshot.Editor.Forms textVerticalAlignmentButton.Visible = props.HasFieldValue(FieldType.TEXT_VERTICAL_ALIGNMENT); shadowButton.Visible = props.HasFieldValue(FieldType.SHADOW); counterLabel.Visible = counterUpDown.Visible = props.HasFieldValue(FieldType.FLAGS) - && ((FieldFlag)props.GetFieldValue(FieldType.FLAGS) & FieldFlag.COUNTER) == FieldFlag.COUNTER; + && ((FieldFlag) props.GetFieldValue(FieldType.FLAGS) & FieldFlag.COUNTER) == FieldFlag.COUNTER; btnConfirm.Visible = btnCancel.Visible = props.HasFieldValue(FieldType.FLAGS) - && ((FieldFlag)props.GetFieldValue(FieldType.FLAGS) & FieldFlag.CONFIRMABLE) == FieldFlag.CONFIRMABLE; + && ((FieldFlag) props.GetFieldValue(FieldType.FLAGS) & FieldFlag.CONFIRMABLE) == FieldFlag.CONFIRMABLE; obfuscateModeButton.Visible = props.HasFieldValue(FieldType.PREPARED_FILTER_OBFUSCATE); highlightModeButton.Visible = props.HasFieldValue(FieldType.PREPARED_FILTER_HIGHLIGHT); @@ -1316,11 +1316,11 @@ namespace Greenshot.Editor.Forms Image icon; if (stepLabels <= 20) { - icon = (Image)resources.GetObject($"btnStepLabel{stepLabels:00}.Image"); + icon = (Image) resources.GetObject($"btnStepLabel{stepLabels:00}.Image"); } else { - icon = (Image)resources.GetObject("btnStepLabel20+.Image"); + icon = (Image) resources.GetObject("btnStepLabel20+.Image"); } btnStepLabel.Image = icon; @@ -1329,7 +1329,7 @@ namespace Greenshot.Editor.Forms FieldAggregator props = _surface.FieldAggregator; // if a confirmable element is selected, we must disable most of the controls // since we demand confirmation or cancel for confirmable element - if (props.HasFieldValue(FieldType.FLAGS) && ((FieldFlag)props.GetFieldValue(FieldType.FLAGS) & FieldFlag.CONFIRMABLE) == FieldFlag.CONFIRMABLE) + if (props.HasFieldValue(FieldType.FLAGS) && ((FieldFlag) props.GetFieldValue(FieldType.FLAGS) & FieldFlag.CONFIRMABLE) == FieldFlag.CONFIRMABLE) { // disable most controls if (!_controlsDisabledDueToConfirmable) @@ -1377,7 +1377,7 @@ namespace Greenshot.Editor.Forms private void ArrowHeadsToolStripMenuItemClick(object sender, EventArgs e) { - _surface.FieldAggregator.GetField(FieldType.ARROWHEADS).Value = (ArrowContainer.ArrowHeadCombination)((ToolStripMenuItem)sender).Tag; + _surface.FieldAggregator.GetField(FieldType.ARROWHEADS).Value = (ArrowContainer.ArrowHeadCombination) ((ToolStripMenuItem) sender).Tag; } private void EditToolStripMenuItemClick(object sender, EventArgs e) @@ -1520,14 +1520,14 @@ namespace Greenshot.Editor.Forms return; } - clickedDestination = (IDestination)clickedControl.Tag; + clickedDestination = (IDestination) clickedControl.Tag; } else { if (sender is ToolStripMenuItem item) { ToolStripMenuItem clickedMenuItem = item; - clickedDestination = (IDestination)clickedMenuItem.Tag; + clickedDestination = (IDestination) clickedMenuItem.Tag; } } @@ -1564,17 +1564,17 @@ namespace Greenshot.Editor.Forms private void Insert_window_toolstripmenuitemMouseEnter(object sender, EventArgs e) { - ToolStripMenuItem captureWindowMenuItem = (ToolStripMenuItem)sender; + ToolStripMenuItem captureWindowMenuItem = (ToolStripMenuItem) sender; var mainForm = SimpleServiceProvider.Current.GetInstance(); mainForm.AddCaptureWindowMenuItems(captureWindowMenuItem, Contextmenu_window_Click); } private void Contextmenu_window_Click(object sender, EventArgs e) { - ToolStripMenuItem clickedItem = (ToolStripMenuItem)sender; + ToolStripMenuItem clickedItem = (ToolStripMenuItem) sender; try { - WindowDetails windowToCapture = (WindowDetails)clickedItem.Tag; + WindowDetails windowToCapture = (WindowDetails) clickedItem.Tag; ICapture capture = new Capture(); using (Graphics graphics = Graphics.FromHwnd(Handle)) { @@ -1589,8 +1589,8 @@ namespace Greenshot.Editor.Forms capture = captureHelper.CaptureWindow(windowToCapture, capture, coreConfiguration.WindowCaptureMode); if (capture?.CaptureDetails != null && capture.Image != null) { - ((Bitmap)capture.Image).SetResolution(capture.CaptureDetails.DpiX, capture.CaptureDetails.DpiY); - _surface.AddImageContainer((Bitmap)capture.Image, 100, 100); + ((Bitmap) capture.Image).SetResolution(capture.CaptureDetails.DpiX, capture.CaptureDetails.DpiY); + _surface.AddImageContainer((Bitmap) capture.Image, 100, 100); } Activate(); @@ -1770,7 +1770,7 @@ namespace Greenshot.Editor.Forms var canvas = Surface as Control; Size canvasSize = canvas.Size; Size currentClientSize = panel1.ClientSize; - Panel panel = (Panel)canvas?.Parent; + Panel panel = (Panel) canvas?.Parent; if (panel == null) { return; @@ -1863,8 +1863,8 @@ namespace Greenshot.Editor.Forms private void ZoomSetValueMenuItemClick(object sender, EventArgs e) { - var senderMenuItem = (ToolStripMenuItem)sender; - var nextValue = Fraction.Parse((string)senderMenuItem.Tag); + var senderMenuItem = (ToolStripMenuItem) sender; + var nextValue = Fraction.Parse((string) senderMenuItem.Tag); ZoomSetValue(nextValue); } @@ -1877,7 +1877,7 @@ namespace Greenshot.Editor.Forms var imageSize = Surface.Image.Size; static bool isFit(Fraction scale, int source, int boundary) - => (int)(source * scale) <= boundary; + => (int) (source * scale) <= boundary; var nextIndex = Array.FindLastIndex( ZOOM_VALUES, @@ -1939,7 +1939,7 @@ namespace Greenshot.Editor.Forms AlignCanvasPositionAfterResize(); // Update zoom controls - zoomStatusDropDownBtn.Text = ((int)(100 * (double)value)).ToString() + "%"; + zoomStatusDropDownBtn.Text = ((int) (100 * (double) value)).ToString() + "%"; var valueString = value.ToString(); foreach (var item in zoomMenuStrip.Items) { @@ -1953,8 +1953,8 @@ namespace Greenshot.Editor.Forms rc = surface.GetVisibleRectangle(); size = surface.Size; panel.AutoScrollPosition = new Point( - (int)(horizontalCenter * size.Width) - rc.Width / 2, - (int)(verticalCenter * size.Height) - rc.Height / 2 + (int) (horizontalCenter * size.Width) - rc.Width / 2, + (int) (verticalCenter * size.Height) - rc.Height / 2 ); } } From ef32359c4b447da23f1a5f6298a42f018f40d3b7 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Fri, 14 Jan 2022 17:24:07 +0100 Subject: [PATCH 10/61] Delete .bmp --- .../Resources/btnEmoji.Image.bmp | Bin 3382 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/Greenshot.Editor/Resources/btnEmoji.Image.bmp diff --git a/src/Greenshot.Editor/Resources/btnEmoji.Image.bmp b/src/Greenshot.Editor/Resources/btnEmoji.Image.bmp deleted file mode 100644 index fa6bf1b076793830904adce758867d9a57163a1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3382 zcmc(gzm6m|5Qpm|q#jO!XK+YJbZJ``(IjP@p#N1sr&YkRU^W+I$pn;2}bS3##df!cf(aNr?Af(!-fxZe)zA@+MO8C#&X##df!dN6aNr?Af(!*} zOHsgqhX@HW6sY!`rR1<4A|%LApth6+9C(P3AVY!LQW0?AAwq%-1!_xGz=4Md2{II@ ztq9M#IPef5L52dg6(``pLxcnw3e;A-fCCQ^5@aY)TZsY=JVZ#4p+IdV2{`Z&Awh-$ zwUsR3z(a%t846V1Q2_@YA|%M|&#ko|z7so7k=Dd&qhpSC;D0H{n-D~nt8laX_w|oK z_P5h%-sV3}w|fbP_n(T{NjPouwsKKv{|e9Fz5l0>>DAR~CbO#V%`q%fd$PP)-fBt} zW3*?H>(9%fJyCA1CX=1hk9BmRW&g20gl#72Y+1GKoxa|6cpPxJR)Ow8TW!q2r?+m` zHy;M<#1y6)O%EC==H>1(U|J?Jtt7^bMY_c&e%&^?Jf(1_I-Ow-p@sJT2%k?&yDyWN zc(vRcZHKJmP&MfJ>0Td>sw9SnKdcW*-yNw=ug>~u(H$bUh9C`8Ut7$u;k>}jn}@;m zyv}_H9Sfaz-?v_bJeJ9t^StF%rB*`LZM`K70MzXbOu`rFvKkQP<|??bP*$!^q0GUF)S?8M1+OyY2UD z`ex+l`Iyv&Fec;`=$&~B;}zq8x=3%~c#(UK)+>$J5&DJDt@{NO)_JCS?TG z>AIiQyuI1CUU)!l3IXa~RZ15_yK1|hx5J6rXVXSCf{v=q5}`vR+&#STETCzqOj)OU z^cm2~^yOza9Bk0m*C^GYzQ9ib~V&+x%t-1K{&L&!b9HGBA@<)ndGSV zt)B`TvWh)D-uqafO=0N|OV7G$=r&!w8jsmoc44O_{Ki?^Dw>{CUmhLIg<8A2YyP8; f6EV~Au=o4pqxmP?>97xrEMb56bm}KU|NGG2fasv9 From dbb472f9acd71cff152dce0ee111de0cbe718460 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Fri, 14 Jan 2022 17:26:15 +0100 Subject: [PATCH 11/61] Fix tabs --- .../Forms/ImageEditorForm.Designer.cs | 74 +++++++++---------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs b/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs index ebcf30031..fc1872013 100644 --- a/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs +++ b/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs @@ -70,8 +70,8 @@ namespace Greenshot.Editor.Forms { this.btnText = new GreenshotToolStripButton(); this.btnSpeechBubble = new GreenshotToolStripButton(); this.btnStepLabel = new GreenshotToolStripButton(); - this.btnEmoji = new GreenshotToolStripButton(); - this.toolStripSeparator14 = new System.Windows.Forms.ToolStripSeparator(); + this.btnEmoji = new GreenshotToolStripButton(); + this.toolStripSeparator14 = new System.Windows.Forms.ToolStripSeparator(); this.btnHighlight = new GreenshotToolStripButton(); this.btnObfuscate = new GreenshotToolStripButton(); this.toolStripSplitButton1 = new GreenshotToolStripDropDownButton(); @@ -234,8 +234,8 @@ namespace Greenshot.Editor.Forms { // // topToolStripContainer // - this.topToolStripContainer.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.topToolStripContainer.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.topToolStripContainer.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.topToolStripContainer.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; // // topToolStripContainer.BottomToolStripPanel // @@ -337,7 +337,7 @@ namespace Greenshot.Editor.Forms { this.btnStepLabel, this.btnEmoji, this.toolStripSeparator14, - this.btnHighlight, + this.btnHighlight, this.btnObfuscate, this.toolStripSplitButton1, this.toolStripSeparator13, @@ -445,20 +445,20 @@ namespace Greenshot.Editor.Forms { this.btnStepLabel.LanguageKey = "editor_counter"; this.btnStepLabel.Name = "btnStepLabel"; this.btnStepLabel.Click += new System.EventHandler(this.BtnStepLabelClick); - // - // btnStepEmoji - // - this.btnEmoji.CheckOnClick = true; - this.btnEmoji.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; - this.btnEmoji.Image = ((System.Drawing.Image)(resources.GetObject("btnEmoji.Image"))); - this.btnEmoji.ImageTransparentColor = System.Drawing.Color.Magenta; - this.btnEmoji.Text = "Emoji"; - this.btnEmoji.Name = "btnEmoji"; - this.btnEmoji.Click += new System.EventHandler(this.BtnEmojiClick); - // - // toolStripSeparator14 - // - this.toolStripSeparator14.Name = "toolStripSeparator14"; + // + // btnStepEmoji + // + this.btnEmoji.CheckOnClick = true; + this.btnEmoji.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; + this.btnEmoji.Image = ((System.Drawing.Image)(resources.GetObject("btnEmoji.Image"))); + this.btnEmoji.ImageTransparentColor = System.Drawing.Color.Magenta; + this.btnEmoji.Text = "Emoji"; + this.btnEmoji.Name = "btnEmoji"; + this.btnEmoji.Click += new System.EventHandler(this.BtnEmojiClick); + // + // toolStripSeparator14 + // + this.toolStripSeparator14.Name = "toolStripSeparator14"; // // btnHighlight // @@ -770,20 +770,20 @@ namespace Greenshot.Editor.Forms { this.addTextBoxToolStripMenuItem.LanguageKey = "editor_drawtextbox"; this.addTextBoxToolStripMenuItem.Name = "addTextBoxToolStripMenuItem"; this.addTextBoxToolStripMenuItem.Click += new System.EventHandler(this.AddTextBoxToolStripMenuItemClick); - // - // addSpeechBubbleToolStripMenuItem - // - this.addSpeechBubbleToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnSpeechBubble.Image"))); - this.addSpeechBubbleToolStripMenuItem.LanguageKey = "editor_speechbubble"; - this.addSpeechBubbleToolStripMenuItem.Name = "addSpeechBubbleToolStripMenuItem"; - this.addSpeechBubbleToolStripMenuItem.Click += new System.EventHandler(this.AddSpeechBubbleToolStripMenuItemClick); - // - // addCounterToolStripMenuItem - // - this.addCounterToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnStepLabel01.Image"))); - this.addCounterToolStripMenuItem.LanguageKey = "editor_counter"; - this.addCounterToolStripMenuItem.Name = "addCounterToolStripMenuItem"; - this.addCounterToolStripMenuItem.Click += new System.EventHandler(this.AddCounterToolStripMenuItemClick); + // + // addSpeechBubbleToolStripMenuItem + // + this.addSpeechBubbleToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnSpeechBubble.Image"))); + this.addSpeechBubbleToolStripMenuItem.LanguageKey = "editor_speechbubble"; + this.addSpeechBubbleToolStripMenuItem.Name = "addSpeechBubbleToolStripMenuItem"; + this.addSpeechBubbleToolStripMenuItem.Click += new System.EventHandler(this.AddSpeechBubbleToolStripMenuItemClick); + // + // addCounterToolStripMenuItem + // + this.addCounterToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("btnStepLabel01.Image"))); + this.addCounterToolStripMenuItem.LanguageKey = "editor_counter"; + this.addCounterToolStripMenuItem.Name = "addCounterToolStripMenuItem"; + this.addCounterToolStripMenuItem.Click += new System.EventHandler(this.AddCounterToolStripMenuItemClick); // // toolStripSeparator8 // @@ -1827,8 +1827,8 @@ namespace Greenshot.Editor.Forms { // // ImageEditorForm // - this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; this.ClientSize = new System.Drawing.Size(785, 485); this.Controls.Add(this.topToolStripContainer); this.KeyPreview = true; @@ -1940,8 +1940,8 @@ namespace Greenshot.Editor.Forms { private GreenshotToolStripButton btnText; private GreenshotToolStripButton btnSpeechBubble; private GreenshotToolStripButton btnStepLabel; - private GreenshotToolStripButton btnEmoji; - private GreenshotToolStripMenuItem drawLineToolStripMenuItem; + private GreenshotToolStripButton btnEmoji; + private GreenshotToolStripMenuItem drawLineToolStripMenuItem; private GreenshotToolStripButton btnLine; private GreenshotToolStripButton btnSettings; private GreenshotToolStripButton btnHelp; From 59372d39303140ffb763295f8d43aa2839ec5d0a Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Fri, 14 Jan 2022 18:22:14 +0100 Subject: [PATCH 12/61] Clean --- .../Drawing/EmojiContainer.cs | 43 ++++++++++++------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/src/Greenshot.Editor/Drawing/EmojiContainer.cs b/src/Greenshot.Editor/Drawing/EmojiContainer.cs index 2dfeb2484..a477e1b2f 100644 --- a/src/Greenshot.Editor/Drawing/EmojiContainer.cs +++ b/src/Greenshot.Editor/Drawing/EmojiContainer.cs @@ -24,13 +24,15 @@ using System.Drawing; using System.Drawing.Drawing2D; using System.Runtime.Serialization; using System.Windows; +using System.Windows.Controls.Primitives; using System.Windows.Forms; using System.Windows.Forms.Integration; using System.Windows.Media; using System.Windows.Media.Imaging; +using Emoji.Wpf; using Greenshot.Base.Interfaces.Drawing; using Greenshot.Editor.Helpers; -using log4net; +using Image = System.Drawing.Image; using Point = System.Drawing.Point; using Size = System.Windows.Size; @@ -42,14 +44,12 @@ namespace Greenshot.Editor.Drawing [Serializable] public class EmojiContainer : DrawableContainer, IEmojiContainer { - private static readonly ILog Log = LogManager.GetLogger(typeof(IconContainer)); - [NonSerialized] private static EmojiContainer _currentContainer; [NonSerialized] private static ElementHost _emojiPickerHost; - [NonSerialized] private static Emoji.Wpf.Picker _emojiPicker; + [NonSerialized] private static Picker _emojiPicker; [NonSerialized] private System.Windows.Controls.Image _image; - [NonSerialized] private bool _firstSelection = true; + [NonSerialized] private bool _justCreated = true; private string _emoji; @@ -99,14 +99,14 @@ namespace Greenshot.Editor.Drawing _emojiPickerHost.Top = displayRectangle.Top; _emojiPicker.Selection = Emoji; - _emojiPicker.ShowPopup = true; + _emojiPicker.ShowPopup(true); } private void CreatePickerControl() { if (_emojiPickerHost == null) { - _emojiPicker = new Emoji.Wpf.Picker(); + _emojiPicker = new Picker(); _emojiPicker.Picked += (_, args) => { _currentContainer.Emoji = args.Emoji; @@ -121,13 +121,9 @@ namespace Greenshot.Editor.Drawing private void HideEmojiPicker() { - if (_emojiPicker != null) - { - _emojiPicker.ShowPopup = false; - } + _emojiPicker?.ShowPopup(false); } - protected override void OnDeserialized(StreamingContext streamingContext) { base.OnDeserialized(streamingContext); @@ -138,7 +134,7 @@ namespace Greenshot.Editor.Drawing { CreateDefaultAdorners(); - // Create WPF control + // Create WPF control that will be used to render the emoji _image = new System.Windows.Controls.Image(); global::Emoji.Wpf.Image.SetSource(_image, Emoji); @@ -153,10 +149,11 @@ namespace Greenshot.Editor.Drawing { HideEmojiPicker(); } - else if (Status == EditStatus.IDLE && _firstSelection) + else if (Status == EditStatus.IDLE && _justCreated) { + // Show picker just after creation ShowEmojiPicker(); - _firstSelection = false; + _justCreated = false; } } } @@ -195,7 +192,7 @@ namespace Greenshot.Editor.Drawing private int GetRotationAngle() { - int rotationAngle = 0; + var rotationAngle = 0; if (Width < 0) { rotationAngle = Height > 0 ? 90 : 180; @@ -240,4 +237,18 @@ namespace Greenshot.Editor.Drawing return bitmap; } } + + internal static class PickerExtensions + { + public static void ShowPopup(this Picker picker, bool show) + { + foreach (var child in picker.Children) + { + if (child is ToggleButton button) + { + button.IsChecked = show; + } + } + } + } } \ No newline at end of file From 238a43f216d8b49fa66fffd262d7b4c1c6a61bae Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Fri, 14 Jan 2022 18:35:19 +0100 Subject: [PATCH 13/61] Fix installation --- installer/innosetup/setup.iss | 1 - 1 file changed, 1 deletion(-) diff --git a/installer/innosetup/setup.iss b/installer/innosetup/setup.iss index 6c5345c69..b4d7b878d 100644 --- a/installer/innosetup/setup.iss +++ b/installer/innosetup/setup.iss @@ -33,7 +33,6 @@ Source: {#ReleaseDir}\Newtonsoft.Json.dll; DestDir: {app}; Components: greenshot Source: {#ReleaseDir}\Emoji.Wpf.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\Typography.GlyphLayout.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\Typography.OpenFont.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion -Source: {#ReleaseDir}\Stfu.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#GreenshotProjectDir}\log4net.xml; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion Source: {#ReleaseDir}\checksum.SHA256; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion ;Source: ..\greenshot-defaults.ini; DestDir: {app}; Flags: overwritereadonly ignoreversion replacesameversion From 8d1ac3b4ba385ff888609c44b9332e5a79f0b17e Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sat, 15 Jan 2022 09:02:18 +0100 Subject: [PATCH 14/61] One picker by surface --- src/Greenshot.Editor/Drawing/EmojiContainer.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Greenshot.Editor/Drawing/EmojiContainer.cs b/src/Greenshot.Editor/Drawing/EmojiContainer.cs index a477e1b2f..5845447dc 100644 --- a/src/Greenshot.Editor/Drawing/EmojiContainer.cs +++ b/src/Greenshot.Editor/Drawing/EmojiContainer.cs @@ -22,6 +22,7 @@ using System; using System.Drawing; using System.Drawing.Drawing2D; +using System.Linq; using System.Runtime.Serialization; using System.Windows; using System.Windows.Controls.Primitives; @@ -87,9 +88,7 @@ namespace Greenshot.Editor.Drawing { _currentContainer = this; - CreatePickerControl(); - - _parent.Controls.Add(_emojiPickerHost); + GetOrCreatePickerControl(); var absRectangle = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); var displayRectangle = Parent.ToSurfaceCoordinates(absRectangle); @@ -102,8 +101,10 @@ namespace Greenshot.Editor.Drawing _emojiPicker.ShowPopup(true); } - private void CreatePickerControl() + private void GetOrCreatePickerControl() { + // Create one picker control by surface + _emojiPickerHost = _parent.Controls.Find("EmojiPickerHost", false).OfType().FirstOrDefault(); if (_emojiPickerHost == null) { _emojiPicker = new Picker(); @@ -116,6 +117,9 @@ namespace Greenshot.Editor.Drawing _emojiPickerHost = new ElementHost(); _emojiPickerHost.Dock = DockStyle.None; _emojiPickerHost.Child = _emojiPicker; + _emojiPickerHost.Name = "EmojiPickerHost"; + + _parent.Controls.Add(_emojiPickerHost); } } From 0c5abe915c9a20b1950659081d53c274d6479532 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sat, 15 Jan 2022 09:05:04 +0100 Subject: [PATCH 15/61] Add shortcut --- src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs | 2 +- src/Greenshot.Editor/Forms/ImageEditorForm.cs | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs b/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs index fc1872013..693ec1647 100644 --- a/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs +++ b/src/Greenshot.Editor/Forms/ImageEditorForm.Designer.cs @@ -452,7 +452,7 @@ namespace Greenshot.Editor.Forms { this.btnEmoji.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; this.btnEmoji.Image = ((System.Drawing.Image)(resources.GetObject("btnEmoji.Image"))); this.btnEmoji.ImageTransparentColor = System.Drawing.Color.Magenta; - this.btnEmoji.Text = "Emoji"; + this.btnEmoji.Text = "Emoji (M)"; this.btnEmoji.Name = "btnEmoji"; this.btnEmoji.Click += new System.EventHandler(this.BtnEmojiClick); // diff --git a/src/Greenshot.Editor/Forms/ImageEditorForm.cs b/src/Greenshot.Editor/Forms/ImageEditorForm.cs index d717b3953..98ab0c16d 100644 --- a/src/Greenshot.Editor/Forms/ImageEditorForm.cs +++ b/src/Greenshot.Editor/Forms/ImageEditorForm.cs @@ -988,6 +988,9 @@ namespace Greenshot.Editor.Forms case Keys.C: BtnCropClick(sender, e); break; + case Keys.M: + BtnEmojiClick(sender, e); + break; } } else if (e.Modifiers.Equals(Keys.Control)) From 66703b5ae33f808cec03f0d3db1dddf1f85ff921 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sun, 16 Jan 2022 10:19:50 +0100 Subject: [PATCH 16/61] Review fixes --- .../Drawing/EmojiContainer.cs | 3 ++- .../Drawing/ImageContainer.cs | 25 +++++++++++-------- src/Greenshot.Editor/Forms/ImageEditorForm.cs | 8 +++--- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/Greenshot.Editor/Drawing/EmojiContainer.cs b/src/Greenshot.Editor/Drawing/EmojiContainer.cs index 5845447dc..abe33f8e6 100644 --- a/src/Greenshot.Editor/Drawing/EmojiContainer.cs +++ b/src/Greenshot.Editor/Drawing/EmojiContainer.cs @@ -186,7 +186,8 @@ namespace Greenshot.Editor.Drawing var rotationAngle = GetRotationAngle(); if (rotationAngle != 0) { - graphics.DrawImage(RotateImage(bitmap, rotationAngle), Bounds); + using var newBitmap = RotateImage(bitmap, rotationAngle); + graphics.DrawImage(RotateImage(newBitmap, rotationAngle), Bounds); return; } diff --git a/src/Greenshot.Editor/Drawing/ImageContainer.cs b/src/Greenshot.Editor/Drawing/ImageContainer.cs index 5ccf01c4e..bc37d38d5 100644 --- a/src/Greenshot.Editor/Drawing/ImageContainer.cs +++ b/src/Greenshot.Editor/Drawing/ImageContainer.cs @@ -179,19 +179,22 @@ namespace Greenshot.Editor.Drawing /// public override void Transform(Matrix matrix) { - if (image != null) + if (image == null) { - int rotateAngle = CalculateAngle(matrix); - // we currently assume only one transformation has been made. - if (rotateAngle != 0) + base.Transform(matrix); + return; + } + + int rotateAngle = CalculateAngle(matrix); + // we currently assume only one transformation has been made. + if (rotateAngle != 0) + { + Log.DebugFormat("Rotating element with {0} degrees.", rotateAngle); + DisposeShadow(); + using var tmpMatrix = new Matrix(); + using (image) { - Log.DebugFormat("Rotating element with {0} degrees.", rotateAngle); - DisposeShadow(); - using var tmpMatrix = new Matrix(); - using (image) - { - image = ImageHelper.ApplyEffect(image, new RotateEffect(rotateAngle), tmpMatrix); - } + image = ImageHelper.ApplyEffect(image, new RotateEffect(rotateAngle), tmpMatrix); } } diff --git a/src/Greenshot.Editor/Forms/ImageEditorForm.cs b/src/Greenshot.Editor/Forms/ImageEditorForm.cs index 98ab0c16d..318b2a530 100644 --- a/src/Greenshot.Editor/Forms/ImageEditorForm.cs +++ b/src/Greenshot.Editor/Forms/ImageEditorForm.cs @@ -65,6 +65,8 @@ namespace Greenshot.Editor.Forms private static readonly List EditorList = new List(); + private static bool? _emojifontInstalled; + private Surface _surface; private GreenshotToolStripButton[] _toolbarButtons; @@ -190,10 +192,8 @@ namespace Greenshot.Editor.Forms private void HideEmojiButtonWhenFontIsNotInstalled() { - if (!FontFamily.Families.Any(f => string.Equals(f.Name, "Segoe UI Emoji", StringComparison.OrdinalIgnoreCase))) - { - btnEmoji.Visible = false; - } + _emojifontInstalled ??= FontFamily.Families.Any(f => string.Equals(f.Name, "Segoe UI Emoji", StringComparison.OrdinalIgnoreCase)); + btnEmoji.Visible = _emojifontInstalled.Value; } /// From 4ff9f2a0ecbca7f3c770ca13102a739479047cc5 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sun, 16 Jan 2022 15:35:26 +0100 Subject: [PATCH 17/61] Revert to old rotation system --- .../Drawing/EmojiContainer.cs | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/Greenshot.Editor/Drawing/EmojiContainer.cs b/src/Greenshot.Editor/Drawing/EmojiContainer.cs index abe33f8e6..ea4faf6b7 100644 --- a/src/Greenshot.Editor/Drawing/EmojiContainer.cs +++ b/src/Greenshot.Editor/Drawing/EmojiContainer.cs @@ -34,6 +34,7 @@ using Emoji.Wpf; using Greenshot.Base.Interfaces.Drawing; using Greenshot.Editor.Helpers; using Image = System.Drawing.Image; +using Matrix = System.Drawing.Drawing2D.Matrix; using Point = System.Drawing.Point; using Size = System.Windows.Size; @@ -53,6 +54,7 @@ namespace Greenshot.Editor.Drawing [NonSerialized] private bool _justCreated = true; private string _emoji; + private int _rotationAngle; public string Emoji { @@ -145,6 +147,14 @@ namespace Greenshot.Editor.Drawing PropertyChanged += OnPropertyChanged; } + public override void Transform(Matrix matrix) + { + _rotationAngle += CalculateAngle(matrix); + _rotationAngle %= 360; + + base.Transform(matrix); + } + private void OnPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { if (e.PropertyName.Equals(nameof(Selected))) @@ -183,11 +193,10 @@ namespace Greenshot.Editor.Drawing using var bitmap = BitmapFromSource(renderTargetBitmap); - var rotationAngle = GetRotationAngle(); - if (rotationAngle != 0) + if (_rotationAngle != 0) { - using var newBitmap = RotateImage(bitmap, rotationAngle); - graphics.DrawImage(RotateImage(newBitmap, rotationAngle), Bounds); + using var newBitmap = RotateImage(bitmap, _rotationAngle); + graphics.DrawImage(newBitmap, Bounds); return; } @@ -195,21 +204,6 @@ namespace Greenshot.Editor.Drawing } } - private int GetRotationAngle() - { - var rotationAngle = 0; - if (Width < 0) - { - rotationAngle = Height > 0 ? 90 : 180; - } - else if (Height < 0) - { - rotationAngle = 270; - } - - return rotationAngle; - } - private Bitmap BitmapFromSource(BitmapSource bitmapSource) { var src = new FormatConvertedBitmap(); From 33dd2b7a27fd00330ecdc10a2d9f7035494871d6 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sun, 16 Jan 2022 15:47:27 +0100 Subject: [PATCH 18/61] Update --- src/Greenshot.Base/Core/ImageHelper.cs | 44 ++++++++++++++ .../Drawing/EmojiContainer.cs | 59 ++++++------------- 2 files changed, 62 insertions(+), 41 deletions(-) diff --git a/src/Greenshot.Base/Core/ImageHelper.cs b/src/Greenshot.Base/Core/ImageHelper.cs index 60d846eac..e0d9dc731 100644 --- a/src/Greenshot.Base/Core/ImageHelper.cs +++ b/src/Greenshot.Base/Core/ImageHelper.cs @@ -1803,5 +1803,49 @@ namespace Greenshot.Base.Core return returnImage; } + + + /// + /// Rotate the image + /// + /// Input image + /// Angle in degrees + /// Rotated image + public static Image Rotate(this Image image, float rotationAngle) + { + var bitmap = new Bitmap(image.Width, image.Height); + + using var gfx = Graphics.FromImage(bitmap); + gfx.InterpolationMode = InterpolationMode.HighQualityBicubic; + + gfx.TranslateTransform((float)bitmap.Width / 2, (float)bitmap.Height / 2); + gfx.RotateTransform(rotationAngle); + gfx.TranslateTransform(-(float)bitmap.Width / 2, -(float)bitmap.Height / 2); + + gfx.DrawImage(image, new Point(0, 0)); + + return bitmap; + } + + /// + /// Returns a bitmap from a WPF bitmap source + /// + /// + /// Winforms bitmap + public static Bitmap ToBitmap(this System.Windows.Media.Imaging.BitmapSource bitmapSource) + { + var src = new System.Windows.Media.Imaging.FormatConvertedBitmap(); + src.BeginInit(); + src.Source = bitmapSource; + src.DestinationFormat = System.Windows.Media.PixelFormats.Bgra32; + src.EndInit(); + + var bitmap = new Bitmap(src.PixelWidth, src.PixelHeight, PixelFormat.Format32bppArgb); + var data = bitmap.LockBits(new Rectangle(new Point(0, 0), bitmap.Size), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb); + src.CopyPixels(System.Windows.Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride); + bitmap.UnlockBits(data); + + return bitmap; + } } } \ No newline at end of file diff --git a/src/Greenshot.Editor/Drawing/EmojiContainer.cs b/src/Greenshot.Editor/Drawing/EmojiContainer.cs index ea4faf6b7..334088deb 100644 --- a/src/Greenshot.Editor/Drawing/EmojiContainer.cs +++ b/src/Greenshot.Editor/Drawing/EmojiContainer.cs @@ -31,6 +31,7 @@ using System.Windows.Forms.Integration; using System.Windows.Media; using System.Windows.Media.Imaging; using Emoji.Wpf; +using Greenshot.Base.Core; using Greenshot.Base.Interfaces.Drawing; using Greenshot.Editor.Helpers; using Image = System.Drawing.Image; @@ -182,59 +183,35 @@ namespace Greenshot.Editor.Drawing var rect = GuiRectangle.GetGuiRectangle(Left, Top, Width, Height); var iconSize = Math.Min(rect.Width, rect.Height); - if (iconSize > 0) { - _image.Measure(new Size(iconSize, iconSize)); - _image.Arrange(new Rect(0, 0, iconSize, iconSize)); - - var renderTargetBitmap = new RenderTargetBitmap(iconSize, iconSize, 96, 96, PixelFormats.Pbgra32); - renderTargetBitmap.Render(_image); - - using var bitmap = BitmapFromSource(renderTargetBitmap); - - if (_rotationAngle != 0) - { - using var newBitmap = RotateImage(bitmap, _rotationAngle); - graphics.DrawImage(newBitmap, Bounds); - return; - } - + using var bitmap = GetBitmap(iconSize); graphics.DrawImage(bitmap, Bounds); } } - private Bitmap BitmapFromSource(BitmapSource bitmapSource) + private Image GetBitmap(int iconSize) { - var src = new FormatConvertedBitmap(); - src.BeginInit(); - src.Source = bitmapSource; - src.DestinationFormat = PixelFormats.Bgra32; - src.EndInit(); + _image.Measure(new Size(iconSize, iconSize)); + _image.Arrange(new Rect(0, 0, iconSize, iconSize)); - var bitmap = new Bitmap(src.PixelWidth, src.PixelHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - var data = bitmap.LockBits(new Rectangle(new Point(0, 0), bitmap.Size), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); - src.CopyPixels(Int32Rect.Empty, data.Scan0, data.Height * data.Stride, data.Stride); - bitmap.UnlockBits(data); + var renderTargetBitmap = new RenderTargetBitmap(iconSize, iconSize, 96, 96, PixelFormats.Pbgra32); + renderTargetBitmap.Render(_image); + + var bitmap = renderTargetBitmap.ToBitmap(); + + if (_rotationAngle != 0) + { + var newBitmap = bitmap.Rotate( _rotationAngle); + bitmap.Dispose(); + + return newBitmap; + } return bitmap; } - private static Image RotateImage(Image img, float rotationAngle) - { - var bitmap = new Bitmap(img.Width, img.Height); - - using var gfx = Graphics.FromImage(bitmap); - gfx.InterpolationMode = InterpolationMode.HighQualityBicubic; - - gfx.TranslateTransform((float)bitmap.Width / 2, (float)bitmap.Height / 2); - gfx.RotateTransform(rotationAngle); - gfx.TranslateTransform(-(float)bitmap.Width / 2, -(float)bitmap.Height / 2); - - gfx.DrawImage(img, new Point(0, 0)); - - return bitmap; - } + } internal static class PickerExtensions From 076a8d23bd502186b56786d0260b4e16d134a787 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sun, 16 Jan 2022 16:04:04 +0100 Subject: [PATCH 19/61] Add bitmap cache --- .../Drawing/EmojiContainer.cs | 37 ++++++++++++++++--- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/Greenshot.Editor/Drawing/EmojiContainer.cs b/src/Greenshot.Editor/Drawing/EmojiContainer.cs index 334088deb..79d88ca59 100644 --- a/src/Greenshot.Editor/Drawing/EmojiContainer.cs +++ b/src/Greenshot.Editor/Drawing/EmojiContainer.cs @@ -36,7 +36,6 @@ using Greenshot.Base.Interfaces.Drawing; using Greenshot.Editor.Helpers; using Image = System.Drawing.Image; using Matrix = System.Drawing.Drawing2D.Matrix; -using Point = System.Drawing.Point; using Size = System.Windows.Size; namespace Greenshot.Editor.Drawing @@ -53,6 +52,7 @@ namespace Greenshot.Editor.Drawing [NonSerialized] private System.Windows.Controls.Image _image; [NonSerialized] private bool _justCreated = true; + [NonSerialized] private Image _cachedImage = null; private string _emoji; private int _rotationAngle; @@ -148,11 +148,23 @@ namespace Greenshot.Editor.Drawing PropertyChanged += OnPropertyChanged; } + protected override void Dispose(bool disposing) + { + if (disposing) + { + ResetCachedBitmap(); + } + + base.Dispose(disposing); + } + public override void Transform(Matrix matrix) { _rotationAngle += CalculateAngle(matrix); _rotationAngle %= 360; + ResetCachedBitmap(); + base.Transform(matrix); } @@ -185,12 +197,23 @@ namespace Greenshot.Editor.Drawing var iconSize = Math.Min(rect.Width, rect.Height); if (iconSize > 0) { - using var bitmap = GetBitmap(iconSize); - graphics.DrawImage(bitmap, Bounds); + if (_cachedImage == null) + { + // First draw or cache was invalidated + _cachedImage = ComputeBitmap(iconSize); + } + else if (iconSize != _cachedImage.Width) + { + // The elements was resized => recompute + _cachedImage.Dispose(); + _cachedImage = ComputeBitmap(iconSize); + } + + graphics.DrawImage(_cachedImage, Bounds); } } - private Image GetBitmap(int iconSize) + private Image ComputeBitmap(int iconSize) { _image.Measure(new Size(iconSize, iconSize)); _image.Arrange(new Rect(0, 0, iconSize, iconSize)); @@ -211,7 +234,11 @@ namespace Greenshot.Editor.Drawing return bitmap; } - + private void ResetCachedBitmap() + { + _cachedImage?.Dispose(); + _cachedImage = null; + } } internal static class PickerExtensions From fde1539ac56240b4e574920ff5236d675b3ca4a8 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Mon, 17 Jan 2022 09:52:06 +0100 Subject: [PATCH 20/61] Update --- src/Greenshot.Base/Core/ImageHelper.cs | 61 ++++++------------- .../Drawing/EmojiContainer.cs | 34 ++++------- 2 files changed, 30 insertions(+), 65 deletions(-) diff --git a/src/Greenshot.Base/Core/ImageHelper.cs b/src/Greenshot.Base/Core/ImageHelper.cs index e0d9dc731..28dbe8a80 100644 --- a/src/Greenshot.Base/Core/ImageHelper.cs +++ b/src/Greenshot.Base/Core/ImageHelper.cs @@ -156,7 +156,7 @@ namespace Greenshot.Base.Core PropertyItem item = image.GetPropertyItem(ExifOrientationId); - ExifOrientations orientation = (ExifOrientations) item.Value[0]; + ExifOrientations orientation = (ExifOrientations)item.Value[0]; // Orient the image. switch (orientation) { @@ -187,7 +187,7 @@ namespace Greenshot.Base.Core } // Set the orientation to be normal, as we rotated the image. - item.Value[0] = (byte) ExifOrientations.TopLeft; + item.Value[0] = (byte)ExifOrientations.TopLeft; image.SetPropertyItem(item); } catch (Exception orientEx) @@ -355,7 +355,7 @@ namespace Greenshot.Base.Core // Bottom Left // Top Right // Bottom Right - using (IFastBitmap fastBitmap = FastBitmap.Create((Bitmap) image)) + using (IFastBitmap fastBitmap = FastBitmap.Create((Bitmap)image)) { // find biggest area foreach (Point checkPoint in checkPoints) @@ -419,7 +419,7 @@ namespace Greenshot.Base.Core try { byte[] srcBuf = new byte[iconStream.Length]; - iconStream.Read(srcBuf, 0, (int) iconStream.Length); + iconStream.Read(srcBuf, 0, (int)iconStream.Length); int iCount = BitConverter.ToInt16(srcBuf, 4); for (int iIndex = 0; iIndex < iCount; iIndex++) { @@ -568,8 +568,8 @@ namespace Greenshot.Base.Core using (var path = new GraphicsPath()) { Random random = new Random(); - int horizontalRegions = (int) Math.Round((float) sourceImage.Width / horizontalToothRange); - int verticalRegions = (int) Math.Round((float) sourceImage.Height / verticalToothRange); + int horizontalRegions = (int)Math.Round((float)sourceImage.Width / horizontalToothRange); + int verticalRegions = (int)Math.Round((float)sourceImage.Height / verticalToothRange); Point topLeft = new Point(0, 0); Point topRight = new Point(sourceImage.Width, 0); @@ -1028,7 +1028,7 @@ namespace Greenshot.Base.Core } Rectangle shadowRectangle = new Rectangle(new Point(shadowSize, shadowSize), sourceBitmap.Size); - ApplyColorMatrix((Bitmap) sourceBitmap, Rectangle.Empty, returnImage, shadowRectangle, maskMatrix); + ApplyColorMatrix((Bitmap)sourceBitmap, Rectangle.Empty, returnImage, shadowRectangle, maskMatrix); // blur "shadow", apply to whole new image if (useGdiBlur) @@ -1069,7 +1069,7 @@ namespace Greenshot.Base.Core /// Negative bitmap public static Bitmap CreateNegative(Image sourceImage) { - Bitmap clone = (Bitmap) Clone(sourceImage); + Bitmap clone = (Bitmap)Clone(sourceImage); ColorMatrix invertMatrix = new ColorMatrix(new[] { new float[] @@ -1289,7 +1289,7 @@ namespace Greenshot.Base.Core sourceImage.VerticalResolution); using (ImageAttributes adjustAttributes = CreateAdjustAttributes(brightness, contrast, gamma)) { - ApplyImageAttributes((Bitmap) sourceImage, Rectangle.Empty, newBitmap, Rectangle.Empty, adjustAttributes); + ApplyImageAttributes((Bitmap)sourceImage, Rectangle.Empty, newBitmap, Rectangle.Empty, adjustAttributes); } return newBitmap; @@ -1302,7 +1302,7 @@ namespace Greenshot.Base.Core /// Bitmap with grayscale public static Image CreateGrayscale(Image sourceImage) { - Bitmap clone = (Bitmap) Clone(sourceImage); + Bitmap clone = (Bitmap)Clone(sourceImage); ColorMatrix grayscaleMatrix = new ColorMatrix(new[] { new[] @@ -1352,7 +1352,7 @@ namespace Greenshot.Base.Core { if (sourceImage is Metafile) { - return (Image) sourceImage.Clone(); + return (Image)sourceImage.Clone(); } return CloneArea(sourceImage, Rectangle.Empty, PixelFormat.DontCare); @@ -1599,7 +1599,7 @@ namespace Greenshot.Base.Core toCount &= 0xffffff; } - using IFastBitmap bb = FastBitmap.Create((Bitmap) sourceImage); + using IFastBitmap bb = FastBitmap.Create((Bitmap)sourceImage); for (int y = 0; y < bb.Height; y++) { for (int x = 0; x < bb.Width; x++) @@ -1636,11 +1636,11 @@ namespace Greenshot.Base.Core int destX = 0; int destY = 0; - var nPercentW = newWidth / (float) sourceImage.Width; - var nPercentH = newHeight / (float) sourceImage.Height; + var nPercentW = newWidth / (float)sourceImage.Width; + var nPercentH = newHeight / (float)sourceImage.Height; if (maintainAspectRatio) { - if ((int) nPercentW == 1) + if ((int)nPercentW == 1) { nPercentW = nPercentH; if (canvasUseNewSize) @@ -1648,7 +1648,7 @@ namespace Greenshot.Base.Core destX = Math.Max(0, Convert.ToInt32((newWidth - sourceImage.Width * nPercentW) / 2)); } } - else if ((int) nPercentH == 1) + else if ((int)nPercentH == 1) { nPercentH = nPercentW; if (canvasUseNewSize) @@ -1656,7 +1656,7 @@ namespace Greenshot.Base.Core destY = Math.Max(0, Convert.ToInt32((newHeight - sourceImage.Height * nPercentH) / 2)); } } - else if ((int) nPercentH != 0 && nPercentH < nPercentW) + else if ((int)nPercentH != 0 && nPercentH < nPercentW) { nPercentW = nPercentH; if (canvasUseNewSize) @@ -1690,12 +1690,12 @@ namespace Greenshot.Base.Core if (maintainAspectRatio && canvasUseNewSize) { newImage = CreateEmpty(newWidth, newHeight, sourceImage.PixelFormat, backgroundColor, sourceImage.HorizontalResolution, sourceImage.VerticalResolution); - matrix?.Scale((float) newWidth / sourceImage.Width, (float) newHeight / sourceImage.Height, MatrixOrder.Append); + matrix?.Scale((float)newWidth / sourceImage.Width, (float)newHeight / sourceImage.Height, MatrixOrder.Append); } else { newImage = CreateEmpty(destWidth, destHeight, sourceImage.PixelFormat, backgroundColor, sourceImage.HorizontalResolution, sourceImage.VerticalResolution); - matrix?.Scale((float) destWidth / sourceImage.Width, (float) destHeight / sourceImage.Height, MatrixOrder.Append); + matrix?.Scale((float)destWidth / sourceImage.Width, (float)destHeight / sourceImage.Height, MatrixOrder.Append); } using (Graphics graphics = Graphics.FromImage(newImage)) @@ -1804,29 +1804,6 @@ namespace Greenshot.Base.Core return returnImage; } - - /// - /// Rotate the image - /// - /// Input image - /// Angle in degrees - /// Rotated image - public static Image Rotate(this Image image, float rotationAngle) - { - var bitmap = new Bitmap(image.Width, image.Height); - - using var gfx = Graphics.FromImage(bitmap); - gfx.InterpolationMode = InterpolationMode.HighQualityBicubic; - - gfx.TranslateTransform((float)bitmap.Width / 2, (float)bitmap.Height / 2); - gfx.RotateTransform(rotationAngle); - gfx.TranslateTransform(-(float)bitmap.Width / 2, -(float)bitmap.Height / 2); - - gfx.DrawImage(image, new Point(0, 0)); - - return bitmap; - } - /// /// Returns a bitmap from a WPF bitmap source /// diff --git a/src/Greenshot.Editor/Drawing/EmojiContainer.cs b/src/Greenshot.Editor/Drawing/EmojiContainer.cs index 79d88ca59..19e232afe 100644 --- a/src/Greenshot.Editor/Drawing/EmojiContainer.cs +++ b/src/Greenshot.Editor/Drawing/EmojiContainer.cs @@ -50,7 +50,6 @@ namespace Greenshot.Editor.Drawing [NonSerialized] private static ElementHost _emojiPickerHost; [NonSerialized] private static Picker _emojiPicker; - [NonSerialized] private System.Windows.Controls.Image _image; [NonSerialized] private bool _justCreated = true; [NonSerialized] private Image _cachedImage = null; @@ -63,10 +62,7 @@ namespace Greenshot.Editor.Drawing set { _emoji = value; - if (_image != null) - { - global::Emoji.Wpf.Image.SetSource(_image, Emoji); - } + ResetCachedBitmap(); } } @@ -141,10 +137,6 @@ namespace Greenshot.Editor.Drawing { CreateDefaultAdorners(); - // Create WPF control that will be used to render the emoji - _image = new System.Windows.Controls.Image(); - global::Emoji.Wpf.Image.SetSource(_image, Emoji); - PropertyChanged += OnPropertyChanged; } @@ -215,23 +207,19 @@ namespace Greenshot.Editor.Drawing private Image ComputeBitmap(int iconSize) { - _image.Measure(new Size(iconSize, iconSize)); - _image.Arrange(new Rect(0, 0, iconSize, iconSize)); + // Create WPF control that will be used to render the emoji + var image = new System.Windows.Controls.Image(); + global::Emoji.Wpf.Image.SetSource(image, Emoji); + + image.RenderTransformOrigin = new System.Windows.Point(0.5, 0.5); + image.RenderTransform = new RotateTransform(_rotationAngle); + image.Measure(new Size(iconSize, iconSize)); + image.Arrange(new Rect(0, 0, iconSize, iconSize)); var renderTargetBitmap = new RenderTargetBitmap(iconSize, iconSize, 96, 96, PixelFormats.Pbgra32); - renderTargetBitmap.Render(_image); + renderTargetBitmap.Render(image); - var bitmap = renderTargetBitmap.ToBitmap(); - - if (_rotationAngle != 0) - { - var newBitmap = bitmap.Rotate( _rotationAngle); - bitmap.Dispose(); - - return newBitmap; - } - - return bitmap; + return renderTargetBitmap.ToBitmap(); } private void ResetCachedBitmap() From 69fcb22df26ff86ac01b7d5683ac71a0601162ea Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sat, 22 Jan 2022 10:55:49 +0100 Subject: [PATCH 21/61] Use SixLabor.Fonts for rendering --- src/Greenshot.Editor/Controls/EmojiControl.cs | 23 + src/Greenshot.Editor/Controls/EmojiData.cs | 281 + .../Controls/EmojiPicker.xaml | 129 + .../Controls/EmojiPicker.xaml.cs | 123 + .../Drawing/EmojiContainer.cs | 24 +- src/Greenshot.Editor/Drawing/EmojiRenderer.cs | 86 + src/Greenshot.Editor/Greenshot.Editor.csproj | 11 +- .../Resources/TwemojiMozilla.ttf | Bin 0 -> 1437964 bytes src/Greenshot.Editor/Resources/emoji-test.txt | 4879 +++++++++++++++++ src/SixLabors.Fonts.dll | Bin 0 -> 335872 bytes src/SixLabors.ImageSharp.Drawing.dll | Bin 0 -> 175104 bytes 11 files changed, 5536 insertions(+), 20 deletions(-) create mode 100644 src/Greenshot.Editor/Controls/EmojiControl.cs create mode 100644 src/Greenshot.Editor/Controls/EmojiData.cs create mode 100644 src/Greenshot.Editor/Controls/EmojiPicker.xaml create mode 100644 src/Greenshot.Editor/Controls/EmojiPicker.xaml.cs create mode 100644 src/Greenshot.Editor/Drawing/EmojiRenderer.cs create mode 100644 src/Greenshot.Editor/Resources/TwemojiMozilla.ttf create mode 100644 src/Greenshot.Editor/Resources/emoji-test.txt create mode 100644 src/SixLabors.Fonts.dll create mode 100644 src/SixLabors.ImageSharp.Drawing.dll diff --git a/src/Greenshot.Editor/Controls/EmojiControl.cs b/src/Greenshot.Editor/Controls/EmojiControl.cs new file mode 100644 index 000000000..d9667a080 --- /dev/null +++ b/src/Greenshot.Editor/Controls/EmojiControl.cs @@ -0,0 +1,23 @@ +using System; +using System.Windows; +using System.Windows.Controls; +using Greenshot.Editor.Drawing; + +namespace Greenshot.Editor.Controls +{ + internal class EmojiControl : Image + { + public static readonly DependencyProperty EmojiProperty = DependencyProperty.Register("Emoji", typeof(string), typeof(EmojiControl), new PropertyMetadata(default(string), PropertyChangedCallback)); + + private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ((EmojiControl)d).Source = EmojiRenderer.GetBitmapSource((string)e.NewValue, 48); + } + + public string Emoji + { + get { return (string)GetValue(EmojiProperty); } + set { SetValue(EmojiProperty, value); } + } + } +} diff --git a/src/Greenshot.Editor/Controls/EmojiData.cs b/src/Greenshot.Editor/Controls/EmojiData.cs new file mode 100644 index 000000000..e1ae58e4e --- /dev/null +++ b/src/Greenshot.Editor/Controls/EmojiData.cs @@ -0,0 +1,281 @@ +// +// Emoji.Wpf — Emoji support for WPF +// +// Copyright © 2017—2021 Sam Hocevar +// +// 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. +// + +using System; +using System.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text.RegularExpressions; + +namespace Greenshot.Editor.Controls +{ + public static class EmojiData + { + public static IEnumerable AllEmoji + => from g in AllGroups + from e in g.EmojiList + select e; + + public static IList AllGroups { get; private set; } + + public static IDictionary LookupByText { get; private set; } + = new Dictionary(); + public static IDictionary LookupByName { get; private set; } + = new Dictionary(); + + public static Regex MatchOne { get; private set; } + public static HashSet MatchStart { get; private set; } + = new HashSet(); + + // 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(); + } + + public class Emoji + { + public string Name { get; set; } + public string Text { get; set; } + public bool HasVariations => VariationList.Count > 0; + + public Group Group => SubGroup.Group; + public SubGroup SubGroup; + + public IList VariationList { get; } = new List(); + } + + public class SubGroup + { + public string Name { get; set; } + public Group Group; + + public IList EmojiList { get; } = new List(); + } + + public class Group + { + public string Name { get; set; } + public string Icon => SubGroups.FirstOrDefault()?.EmojiList.FirstOrDefault()?.Text; + + public IList SubGroups { get; } = new List(); + + public int EmojiCount + => SubGroups.Select(s => s.EmojiList.Count).Sum(); + + public IEnumerable> EmojiChunkList + => new ChunkHelper(EmojiList, 8); + + public IEnumerable EmojiList + => from s in SubGroups + from e in s.EmojiList + select e; + } + + private static string m_match_one_string; + + // FIXME: this could be read directly from emoji-test.txt.gz + private static List SkinToneComponents = new List + { + "🏻", // light skin tone + "🏼", // medium-light skin tone + "🏽", // medium skin tone + "🏾", // medium-dark skin tone + "🏿", // dark skin tone + }; + + private static List HairStyleComponents = new List + { + "🦰", // red hair + "🦱", // curly hair + "🦳", // white hair + "🦲", // bald + }; + + private static string ToColonSyntax(string s) + => Regex.Replace(s.Trim().ToLowerInvariant(), "[^a-z0-9]+", "-"); + + private static void ParseEmojiList() + { + var match_group = new Regex(@"^# group: (.*)"); + var match_subgroup = new Regex(@"^# subgroup: (.*)"); + var match_sequence = new Regex(@"^([0-9a-fA-F ]+[0-9a-fA-F]).*; *([-a-z]*) *# [^ ]* (E[0-9.]* )?(.*)"); + var match_skin_tone = new Regex($"({string.Join("|", SkinToneComponents)})"); + var match_hair_style = new Regex($"({string.Join("|", HairStyleComponents)})"); + + var adult = "(👨|👩)(🏻|🏼|🏽|🏾|🏿)?"; + var child = "(👦|👧|👶)(🏻|🏼|🏽|🏾|🏿)?"; + var match_family = new Regex($"{adult}(\u200d{adult})*(\u200d{child})+"); + + var qualified_lut = new Dictionary(); + var list = new List(); + var alltext = new List(); + + Group current_group = null; + SubGroup current_subgroup = null; + + foreach (var line in EmojiDescriptionLines()) + { + var m = match_group.Match(line); + if (m.Success) + { + current_group = new Group { Name = m.Groups[1].ToString() }; + list.Add(current_group); + continue; + } + + m = match_subgroup.Match(line); + if (m.Success) + { + current_subgroup = new SubGroup { Name = m.Groups[1].ToString(), Group = current_group }; + current_group.SubGroups.Add(current_subgroup); + continue; + } + + m = match_sequence.Match(line); + if (m.Success) + { + string sequence = m.Groups[1].ToString(); + string name = m.Groups[4].ToString(); + + string text = string.Join("", from n in sequence.Split(' ') + select char.ConvertFromUtf32(Convert.ToInt32(n, 16))); + bool has_modifier = false; + + if (match_family.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. + } + else + { + // 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 has_nonfirst_modifier = false; + var regex_text = match_skin_tone.Replace( + match_hair_style.Replace(text, (x) => + { + has_modifier = true; + has_nonfirst_modifier |= x.Value != HairStyleComponents[0]; + return match_hair_style.ToString(); + }), (x) => + { + has_modifier = true; + has_nonfirst_modifier |= x.Value != SkinToneComponents[0]; + return match_skin_tone.ToString(); + }); + + if (!has_nonfirst_modifier) + alltext.Add(has_modifier ? regex_text : 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 (qualified_lut.ContainsKey(unqualified)) + continue; + + qualified_lut[unqualified] = text; + + var emoji = new Emoji + { + Name = name, + Text = text, + SubGroup = current_subgroup, + }; + // FIXME: this prevents LookupByText from working with the unqualified version + LookupByText[text] = emoji; + LookupByName[ToColonSyntax(name)] = emoji; + MatchStart.Add(text[0]); + + // 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 parent_emoji)) + { + if (parent_emoji.VariationList.Count == 0) + parent_emoji.VariationList.Add(parent_emoji); + parent_emoji.VariationList.Add(emoji); + } + else + current_subgroup.EmojiList.Add(emoji); + } + } + + // Remove the Component group. Not sure we want to have the skin tones in the picker. + list.RemoveAll(g => g.Name == "Component"); + AllGroups = list; + + // Make U+fe0f optional in the regex so that we can match any combination. + // FIXME: this is the starting point to implement variation selectors. + var sortedtext = alltext.OrderByDescending(x => x.Length); + var match_other = string.Join("|", sortedtext) + .Replace("*", "[*]") + .Replace("\ufe0f", "\ufe0f?"); + + // Build a regex that matches any Emoji + m_match_one_string = match_family.ToString() + "|" + match_other; + MatchOne = new Regex("(" + m_match_one_string + ")"); + } + + private static IEnumerable EmojiDescriptionLines() + { + using var stream = Assembly.GetCallingAssembly().GetManifestResourceStream("Greenshot.Editor.Resources.emoji-test.txt"); + using var streamReader = new StreamReader(stream); + return streamReader.ReadToEnd().Split('\r', '\n'); + } + } + + sealed class ChunkHelper : IEnumerable> + { + public ChunkHelper(IEnumerable elements, int size) + { + m_elements = elements; + m_size = size; + } + + public IEnumerator> GetEnumerator() + { + using (var enumerator = m_elements.GetEnumerator()) + { + m_has_more = enumerator.MoveNext(); + while (m_has_more) + yield return GetNextBatch(enumerator).ToList(); + } + } + + private IEnumerable GetNextBatch(IEnumerator enumerator) + { + for (int i = 0; i < m_size; ++i) + { + yield return enumerator.Current; + m_has_more = enumerator.MoveNext(); + if (!m_has_more) + yield break; + } + } + + IEnumerator IEnumerable.GetEnumerator() + => GetEnumerator(); + + private readonly IEnumerable m_elements; + private readonly int m_size; + private bool m_has_more; + } +} + diff --git a/src/Greenshot.Editor/Controls/EmojiPicker.xaml b/src/Greenshot.Editor/Controls/EmojiPicker.xaml new file mode 100644 index 000000000..c24961597 --- /dev/null +++ b/src/Greenshot.Editor/Controls/EmojiPicker.xaml @@ -0,0 +1,129 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Greenshot.Editor/Controls/EmojiPicker.xaml.cs b/src/Greenshot.Editor/Controls/EmojiPicker.xaml.cs new file mode 100644 index 000000000..fc255b4a5 --- /dev/null +++ b/src/Greenshot.Editor/Controls/EmojiPicker.xaml.cs @@ -0,0 +1,123 @@ +// +// Emoji.Wpf — Emoji support for WPF +// +// Copyright © 2017—2021 Sam Hocevar +// +// This program 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. +// + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Controls.Primitives; +using System.Windows.Input; + +namespace Greenshot.Editor.Controls +{ + public class EmojiPickedEventArgs : EventArgs + { + public EmojiPickedEventArgs() { } + public EmojiPickedEventArgs(string emoji) => Emoji = emoji; + + public string Emoji; + } + + public delegate void EmojiPickedEventHandler(object sender, EmojiPickedEventArgs e); + + /// + /// Interaction logic for Picker.xaml + /// + public partial class EmojiPicker : StackPanel + { + public EmojiPicker() + { + InitializeComponent(); + } + + public IList EmojiGroups => EmojiData.AllGroups; + + // Backwards compatibility for when the backend was a TextBlock. + public double FontSize + { + get => Image.Height * 0.75; + set => Image.Height = value / 0.75; + } + + public event PropertyChangedEventHandler SelectionChanged; + + public event EmojiPickedEventHandler Picked; + + private static void OnSelectionPropertyChanged(DependencyObject source, + DependencyPropertyChangedEventArgs e) + { + (source as EmojiPicker)?.OnSelectionChanged(e.NewValue as string); + } + + public string Selection + { + get => (string)GetValue(SelectionProperty); + set => SetValue(SelectionProperty, value); + } + + private void OnSelectionChanged(string s) + { + var is_disabled = string.IsNullOrEmpty(s); + Image.Emoji = is_disabled ? "???" : s; + Image.Opacity = is_disabled ? 0.3 : 1.0; + SelectionChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Selection))); + } + + private void OnEmojiPicked(object sender, RoutedEventArgs e) + { + if (sender is Control control && control.DataContext is EmojiData.Emoji emoji) + { + if (emoji.VariationList.Count == 0 || sender is Button) + { + Selection = emoji.Text; + Button_INTERNAL.IsChecked = false; + e.Handled = true; + Picked?.Invoke(this, new EmojiPickedEventArgs(Selection)); + } + } + } + + public static readonly DependencyProperty SelectionProperty = DependencyProperty.Register( + nameof(Selection), typeof(string), typeof(EmojiPicker), + new FrameworkPropertyMetadata("☺", OnSelectionPropertyChanged)); + + private void OnPopupKeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Escape && sender is Popup popup) + { + popup.IsOpen = false; + e.Handled = true; + } + } + + private void OnPopupLoaded(object sender, RoutedEventArgs e) + { + if (!(sender is Popup popup)) + return; + + var child = popup.Child; + IInputElement old_focus = null; + child.Focusable = true; + child.IsVisibleChanged += (o, ea) => + { + if (child.IsVisible) + { + old_focus = Keyboard.FocusedElement; + Keyboard.Focus(child); + } + }; + + popup.Closed += (o, ea) => Keyboard.Focus(old_focus); + } + } +} diff --git a/src/Greenshot.Editor/Drawing/EmojiContainer.cs b/src/Greenshot.Editor/Drawing/EmojiContainer.cs index 19e232afe..bbfdf1990 100644 --- a/src/Greenshot.Editor/Drawing/EmojiContainer.cs +++ b/src/Greenshot.Editor/Drawing/EmojiContainer.cs @@ -30,9 +30,9 @@ using System.Windows.Forms; using System.Windows.Forms.Integration; using System.Windows.Media; using System.Windows.Media.Imaging; -using Emoji.Wpf; using Greenshot.Base.Core; using Greenshot.Base.Interfaces.Drawing; +using Greenshot.Editor.Controls; using Greenshot.Editor.Helpers; using Image = System.Drawing.Image; using Matrix = System.Drawing.Drawing2D.Matrix; @@ -48,7 +48,7 @@ namespace Greenshot.Editor.Drawing { [NonSerialized] private static EmojiContainer _currentContainer; [NonSerialized] private static ElementHost _emojiPickerHost; - [NonSerialized] private static Picker _emojiPicker; + [NonSerialized] private static EmojiPicker _emojiPicker; [NonSerialized] private bool _justCreated = true; [NonSerialized] private Image _cachedImage = null; @@ -106,7 +106,7 @@ namespace Greenshot.Editor.Drawing _emojiPickerHost = _parent.Controls.Find("EmojiPickerHost", false).OfType().FirstOrDefault(); if (_emojiPickerHost == null) { - _emojiPicker = new Picker(); + _emojiPicker = new EmojiPicker(); _emojiPicker.Picked += (_, args) => { _currentContainer.Emoji = args.Emoji; @@ -207,19 +207,7 @@ namespace Greenshot.Editor.Drawing private Image ComputeBitmap(int iconSize) { - // Create WPF control that will be used to render the emoji - var image = new System.Windows.Controls.Image(); - global::Emoji.Wpf.Image.SetSource(image, Emoji); - - image.RenderTransformOrigin = new System.Windows.Point(0.5, 0.5); - image.RenderTransform = new RotateTransform(_rotationAngle); - image.Measure(new Size(iconSize, iconSize)); - image.Arrange(new Rect(0, 0, iconSize, iconSize)); - - var renderTargetBitmap = new RenderTargetBitmap(iconSize, iconSize, 96, 96, PixelFormats.Pbgra32); - renderTargetBitmap.Render(image); - - return renderTargetBitmap.ToBitmap(); + return EmojiRenderer.GetBitmap(Emoji, iconSize); } private void ResetCachedBitmap() @@ -231,9 +219,9 @@ namespace Greenshot.Editor.Drawing internal static class PickerExtensions { - public static void ShowPopup(this Picker picker, bool show) + public static void ShowPopup(this EmojiPicker emojiPicker, bool show) { - foreach (var child in picker.Children) + foreach (var child in emojiPicker.Children) { if (child is ToggleButton button) { diff --git a/src/Greenshot.Editor/Drawing/EmojiRenderer.cs b/src/Greenshot.Editor/Drawing/EmojiRenderer.cs new file mode 100644 index 000000000..d36bbab22 --- /dev/null +++ b/src/Greenshot.Editor/Drawing/EmojiRenderer.cs @@ -0,0 +1,86 @@ +using System.Drawing; +using System.IO; +using System.Reflection; +using System.Windows.Media.Imaging; +using SixLabors.Fonts; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Advanced; +using SixLabors.ImageSharp.Drawing.Processing; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using FontStyle = SixLabors.Fonts.FontStyle; +using Image = System.Drawing.Image; + +namespace Greenshot.Editor.Drawing +{ + internal static class EmojiRenderer + { + private static SixLabors.Fonts.FontFamily? _fontFamily; + + public static Image GetImage(string emoji, int iconSize) + { + if (_fontFamily == null) + { + using var stream = Assembly.GetCallingAssembly().GetManifestResourceStream("Greenshot.Editor.Resources.TwemojiMozilla.ttf"); + var fontCollection = new FontCollection(); + fontCollection.Add(stream); + if (fontCollection.TryGet("Twemoji Mozilla", out var fontFamily)) + { + _fontFamily = fontFamily; + } + } + + var font = _fontFamily.Value.CreateFont(iconSize, FontStyle.Regular); + var image = new Image(iconSize, iconSize); + + var textOptions = new TextOptions(font) { Origin = new SixLabors.ImageSharp.PointF(0, iconSize / 2.0f), 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) + { + using var image = GetImage(emoji, iconSize); + return image.ToBitmap(); + } + + public static BitmapSource GetBitmapSource(string emoji, int iconSize) + { + using var image = GetImage(emoji, iconSize); + return image.ToBitmapSource(); + } + + public static Bitmap ToBitmap(this Image image) + { + using var memoryStream = new MemoryStream(); + + var imageEncoder = image.GetConfiguration().ImageFormatsManager.FindEncoder(PngFormat.Instance); + image.Save(memoryStream, imageEncoder); + + memoryStream.Seek(0, SeekOrigin.Begin); + + return new Bitmap(memoryStream); + } + + public static BitmapSource ToBitmapSource(this Image image) + { + using var memoryStream = new MemoryStream(); + + var imageEncoder = image.GetConfiguration().ImageFormatsManager.FindEncoder(PngFormat.Instance); + image.Save(memoryStream, imageEncoder); + + memoryStream.Seek(0, SeekOrigin.Begin); + + var bitmap = new BitmapImage(); + bitmap.BeginInit(); + bitmap.StreamSource = memoryStream; + bitmap.CacheOption = BitmapCacheOption.OnLoad; + bitmap.EndInit(); + bitmap.Freeze(); + + return bitmap; + } + } +} diff --git a/src/Greenshot.Editor/Greenshot.Editor.csproj b/src/Greenshot.Editor/Greenshot.Editor.csproj index 601a9f38d..da3979874 100644 --- a/src/Greenshot.Editor/Greenshot.Editor.csproj +++ b/src/Greenshot.Editor/Greenshot.Editor.csproj @@ -5,7 +5,7 @@ - + @@ -83,9 +83,16 @@ ImageEditorForm.cs + + - + + ..\SixLabors.Fonts.dll + + + ..\SixLabors.ImageSharp.Drawing.dll + \ No newline at end of file diff --git a/src/Greenshot.Editor/Resources/TwemojiMozilla.ttf b/src/Greenshot.Editor/Resources/TwemojiMozilla.ttf new file mode 100644 index 0000000000000000000000000000000000000000..75ddc213ff8fc6d84167f7bb9d1b787ce40160a4 GIT binary patch literal 1437964 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 z zqxZ$EcFcjJ7g+=ILxUGm!#Ml=kggEu3X#qj)oax|KIxyAu50Txk$efrN4?i@hX{jacN z<-Wq14La;#%bsIP{NLSlPhUT8(IzvPH!R{4%-lhDyYw`b#cG7G;xM1Ou)<;cl)C$- z^mNAN_7;9ZDVCCf6THc*)tUQ91B^ zbS6&KWIM;ymHl#ajPMv=Hl6@XgGJ(?YtgBD8otYhaTIDUaE# zb$o&4I#n|V+B~VY`LLSRfweI8(2A&eG_xzc!tLEx!Her=YxPixz}63GZYJ#^@ijy6 zcyF|K(G3<<&nK&&a;a)Jv$`z2t4yAgSRH>D&(#H&X*S(xdmr8oLe~#D&9r-w+ow4j zOM2qc^@H!>$VG&n1oNf8=-RcmPb6)gMI1YtXoK!!cu^zPQb|)oJ{NE6!Dcf6es7|r zU2x`s+|-iqA$7DF$o`XRu46-y&AsOoOVuri(A`?i*TG1>ESG zoND)bq>E;*ue|CGq>HzD`Oz1(#=0V>m&#mcO?*4Rl-gk(+f_5&^mI*tR7hX*>W+u5 zwYgZ0O+@Qnm*22!skHtBoGO@M#!ydhwAYiJA{Tc4Q{{&ia(|TnaC&|^mP&WSbp^2o z$wos{XKa&A1YEgyFS;Pl?q&onG#p!O(1%yZqrGV{_eN@_D@S(_)_n^-{rv>8clS7w z*)1E-J(&FQ@EVL3va$;=I!?Rjb;9V~hFQp5$}F-qQtQ1DxeGnvF#gFs=#gQar@x%X zdBeL|BYTnc^g`*&$&n3=ITh>xci~e&$uVeC3hlfW%dT41NIfQ#JArjg7uGaRCBY8i zNXlHyTGv?BdsgO@)qWacRgHcP&0yZ@&iNeXYid9J=*fQUH!SAu)5HbY)En@f8iD?8 zWUhEO^0=E&vHkoV{5RTo)_&G=1Z$aRXuE1lX7Q~1>&JN3mG;-s-?gkCRpIY#VLnq$ z%YDb5zy{`SMaI{)(ce$xzs9 zZs2|+{7*-6sl*oXtUI!)ShQ?x&y75#o}M5xsL8ZI5E{o$h-nKQ9i6@4TIW|fI;0|_ z*=9C-#QUgoF*C_i>3Yj|tSz_4LT#7N=%XGclssNgWH#g&- zozy#l_Y0Bn7pJ69tyc|K?<@;WRKuC^qc>T0SkE)+o=^(Bszu?XhpfUU?T)ri;92`? z0ku#+LibhFf@zHIq`080r#$rJ?%C*3uAM#snMI+=KbR=AeO~SU z29k2VJo0i%6rk3a z@1fWhf}a;)%~kifzho5K#$L?_?2+vwor}8G&_ZgJ!Z~^4-UHKE_qzq`(q!3v#RV@T z=-K|1IUcL0vKm1tH%T1!b2=qt(Oo)`;(S8dx9+f|rm6It)(G~hC(*0@c(1FV$Ap;+ zs}&>c@J-NL*g`XbxCv;4_5ke@NS%puxj%fxs+ZvVplP8{$vIr@t*d|zT3a5!3!M8cy&J1RSqtwEQZ4Q z{JloGfW8M*)h2K zsO$Hd=fwSVdDWKGP`b`24E0W+e z#ZGgv6F!#x0ZlcMInmX4btkW*w5s;@IY#%#^|ZuuoR)Z$n)l%xOBeGBNg1!`4fs}Y zKB~Eq`fBefK*D;`;Kb$C{2Tsf1t?;a^JZT~FSVn4>>MgL^=8xc+iBeA^JXzmdU`=a zx_2Iq_xX)!PiQpI?;k|-9$x|uO8Ka#c{QmfA*IE<)6q=#9@Gk@GiPd~HFU?ffHd02 zy%;-GJN~>(Bf(B^rPS4D)l_axQyX1GKDE$l+ce*sq%Y7!dJ%>?axAd@9k*r$+nlN- zwC5-#wMQx!9W&ijG*;_fZ_`pcsPtXfAC3E&^nDlwG``+0HO|hdwW#2odRR&!jDA?a z`l;^tYDrqkiF-KpFJNa>y{>BN5zbshtw25BUOL}gXQxiUXHlA}iMns9^SNMX>a(tL z))Qwd2|2Y~9c7g#oe4a~$fNqMV}{xz{oc(rB(4YQRjEg;ZMm2}r2eR$#`>07$anZD zpP{FP;2TcaYv{BW9$;%MrJfTlqRsU@f!3PcDLB?Xr`)MT{IIX;hb9uQW6(m%cYpMK z5p#iSR2IC8CWZPO+FRUbs!N$wsK>bydpe!ks86|pIf%}%7`b`Mq;_gezQ+d|Vb5ku zh`o<;l*;L^drzN4)|xK(F<;0#?3`BMw|vBS_BNy4PB^M$^g8|JW&7h6Z8QQt@8F|z zq7>>Aj!&#Q(jA#U&K_)EY`%_OE8xsHJwYVW~wDsopWo0 zu5jpy!IPKz1&y>&4ODcD&}S{T7i(@2_EQ#5dRj&ERG internal static class EmojiRenderer { - private static readonly FontCollection _fontCollection = new FontCollection(); + private static readonly FontCollection TwemojiFontCollection = new(); - private static readonly Lazy _twemojiFontFamily = new Lazy(() => + private static readonly Lazy TwemojiFontFamily = new(() => { var exeDirectory = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location); 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); - _fontCollection.Add(fileStream); - _fontCollection.TryGet("Twemoji Mozilla", out var fontFamily); + TwemojiFontCollection.Add(fileStream); + TwemojiFontCollection.TryGet("Twemoji Mozilla", out var fontFamily); return fontFamily; }); @@ -62,7 +63,7 @@ namespace Greenshot.Editor.Drawing.Emoji 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 verticalOffset = font.Size * 0.045f; var textOptions = new TextOptions(font) diff --git a/src/Greenshot.Editor/Greenshot.Editor.csproj b/src/Greenshot.Editor/Greenshot.Editor.csproj index 6a3069383..affaf81c7 100644 --- a/src/Greenshot.Editor/Greenshot.Editor.csproj +++ b/src/Greenshot.Editor/Greenshot.Editor.csproj @@ -15,6 +15,11 @@ + + + + Component @@ -89,9 +94,9 @@ - + PreserveNewest - emoji-test.txt + emoji-test.txt.gz PreserveNewest From 52d122eb132e15a1d8ba1583d458487b407b4e68 Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Tue, 25 Oct 2022 22:28:45 +0200 Subject: [PATCH 42/61] Gotten some files back, in the end they were referenced from the xaml --- .../Controls/Emoji/ChunkHelper.cs | 69 +++++++ .../Controls/Emoji/EmojiPicker.xaml | 2 +- .../Controls/Emoji/EmojiPicker.xaml.cs | 181 +++++++++--------- src/Greenshot.Editor/Controls/Emoji/Emojis.cs | 4 + .../Drawing/Emoji/EmojiContainer.cs | 12 +- 5 files changed, 176 insertions(+), 92 deletions(-) create mode 100644 src/Greenshot.Editor/Controls/Emoji/ChunkHelper.cs diff --git a/src/Greenshot.Editor/Controls/Emoji/ChunkHelper.cs b/src/Greenshot.Editor/Controls/Emoji/ChunkHelper.cs new file mode 100644 index 000000000..d4aa24002 --- /dev/null +++ b/src/Greenshot.Editor/Controls/Emoji/ChunkHelper.cs @@ -0,0 +1,69 @@ +/* + * 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 . + */ + +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +namespace Greenshot.Editor.Controls.Emoji; + +/// +/// This seems to enumerate multiple IEnumerables. +/// TODO: Replace this with LINQ +/// +/// +internal sealed class ChunkHelper : IEnumerable> +{ + private readonly IEnumerable _elements; + private readonly int _size; + private bool _hasMore; + + public ChunkHelper(IEnumerable elements, int size) + { + _elements = elements; + _size = size; + } + + public IEnumerator> GetEnumerator() + { + using var enumerator = _elements.GetEnumerator(); + _hasMore = enumerator.MoveNext(); + while (_hasMore) + { + yield return GetNextBatch(enumerator).ToList(); + } + } + + private IEnumerable GetNextBatch(IEnumerator enumerator) + { + for (int i = 0; i < _size; ++i) + { + yield return enumerator.Current; + _hasMore = enumerator.MoveNext(); + if (!_hasMore) + { + yield break; + } + } + } + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); +} \ No newline at end of file diff --git a/src/Greenshot.Editor/Controls/Emoji/EmojiPicker.xaml b/src/Greenshot.Editor/Controls/Emoji/EmojiPicker.xaml index ddbb78b2d..349515ce1 100644 --- a/src/Greenshot.Editor/Controls/Emoji/EmojiPicker.xaml +++ b/src/Greenshot.Editor/Controls/Emoji/EmojiPicker.xaml @@ -1,4 +1,4 @@ - +/// The event which is created when the emoji is picked +/// +public class EmojiPickedEventArgs : EventArgs { - /// - /// The event which is created when the emoji is picked - /// - public class EmojiPickedEventArgs : EventArgs - { - public EmojiPickedEventArgs() { } - public EmojiPickedEventArgs(string emoji) => Emoji = emoji; + public EmojiPickedEventArgs() { } + public EmojiPickedEventArgs(string emoji) => Emoji = emoji; - public string Emoji; + public string Emoji; +} + +public delegate void EmojiPickedEventHandler(object sender, EmojiPickedEventArgs e); + +/// +/// Interaction logic for Picker.xaml +/// +public partial class EmojiPicker : StackPanel +{ + public EmojiPicker() + { + InitializeComponent(); } - public delegate void EmojiPickedEventHandler(object sender, EmojiPickedEventArgs e); + public IList EmojiGroups => EmojiData.Data.Groups; - /// - /// Interaction logic for Picker.xaml - /// - public partial class EmojiPicker : StackPanel + // Backwards compatibility for when the backend was a TextBlock. + public double FontSize { - public EmojiPicker() + get => Image.Height * 0.75; + set => Image.Height = value / 0.75; + } + + public event PropertyChangedEventHandler SelectionChanged; + + public event EmojiPickedEventHandler Picked; + + private static void OnSelectionPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) + { + (source as EmojiPicker)?.OnSelectionChanged(e.NewValue as string); + } + + public string Selection + { + get => (string)GetValue(SelectionProperty); + set => SetValue(SelectionProperty, value); + } + + private void OnSelectionChanged(string s) + { + var isDisabled = string.IsNullOrEmpty(s); + Image.Emoji = isDisabled ? "???" : s; + Image.Opacity = isDisabled ? 0.3 : 1.0; + SelectionChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Selection))); + } + + private void OnEmojiPicked(object sender, RoutedEventArgs e) + { + if (sender is not Control { DataContext: Emojis.Emoji emoji }) { - InitializeComponent(); + return; } - public IList EmojiGroups => EmojiData.Data.Groups; - - // Backwards compatibility for when the backend was a TextBlock. - public double FontSize + if (emoji.Variations.Count != 0 && sender is not Button) { - get => Image.Height * 0.75; - set => Image.Height = value / 0.75; + return; } - public event PropertyChangedEventHandler SelectionChanged; + Selection = emoji.Text; + Button_INTERNAL.IsChecked = false; + e.Handled = true; + Picked?.Invoke(this, new EmojiPickedEventArgs(Selection)); + } - public event EmojiPickedEventHandler Picked; + public static readonly DependencyProperty SelectionProperty = DependencyProperty.Register( + nameof(Selection), typeof(string), typeof(EmojiPicker), + new FrameworkPropertyMetadata("☺", OnSelectionPropertyChanged)); - private static void OnSelectionPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e) + private void OnPopupKeyDown(object sender, KeyEventArgs e) + { + if (e.Key != Key.Escape || sender is not Popup popup) return; + popup.IsOpen = false; + e.Handled = true; + } + + private void OnPopupLoaded(object sender, RoutedEventArgs e) + { + if (sender is not Popup popup) return; + + var child = popup.Child; + IInputElement oldFocus = null; + child.Focusable = true; + child.IsVisibleChanged += (o, ea) => { - (source as EmojiPicker)?.OnSelectionChanged(e.NewValue as string); - } + if (!child.IsVisible) return; + oldFocus = Keyboard.FocusedElement; + Keyboard.Focus(child); + }; - public string Selection + popup.Closed += (o, ea) => Keyboard.Focus(oldFocus); + } + + public void ShowPopup(bool show) + { + foreach (var child in Children) { - get => (string)GetValue(SelectionProperty); - set => SetValue(SelectionProperty, value); - } - - private void OnSelectionChanged(string s) - { - var isDisabled = string.IsNullOrEmpty(s); - Image.Emoji = isDisabled ? "???" : s; - Image.Opacity = isDisabled ? 0.3 : 1.0; - SelectionChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Selection))); - } - - private void OnEmojiPicked(object sender, RoutedEventArgs e) - { - if (sender is not Control { DataContext: Emojis.Emoji emoji }) return; - if (emoji.Variations.Count != 0 && sender is not Button) return; - - Selection = emoji.Text; - Button_INTERNAL.IsChecked = false; - e.Handled = true; - Picked?.Invoke(this, new EmojiPickedEventArgs(Selection)); - } - - public static readonly DependencyProperty SelectionProperty = DependencyProperty.Register( - nameof(Selection), typeof(string), typeof(EmojiPicker), - new FrameworkPropertyMetadata("☺", OnSelectionPropertyChanged)); - - private void OnPopupKeyDown(object sender, KeyEventArgs e) - { - if (e.Key != Key.Escape || sender is not Popup popup) return; - popup.IsOpen = false; - e.Handled = true; - } - - private void OnPopupLoaded(object sender, RoutedEventArgs e) - { - if (sender is not Popup popup) return; - - var child = popup.Child; - IInputElement oldFocus = null; - child.Focusable = true; - child.IsVisibleChanged += (o, ea) => + if (child is ToggleButton button) { - if (!child.IsVisible) return; - oldFocus = Keyboard.FocusedElement; - Keyboard.Focus(child); - }; - - popup.Closed += (o, ea) => Keyboard.Focus(oldFocus); - } - - public void ShowPopup(bool show) - { - foreach (var child in Children) - { - if (child is ToggleButton button) - { - button.IsChecked = show; - } + button.IsChecked = show; } } } -} +} \ No newline at end of file diff --git a/src/Greenshot.Editor/Controls/Emoji/Emojis.cs b/src/Greenshot.Editor/Controls/Emoji/Emojis.cs index ff1c74971..95b8a2f8b 100644 --- a/src/Greenshot.Editor/Controls/Emoji/Emojis.cs +++ b/src/Greenshot.Editor/Controls/Emoji/Emojis.cs @@ -42,7 +42,11 @@ public class Emojis [XmlElement(ElementName = "Emoji")] public List Emojis { get; set; } = new(); + public IEnumerable> EmojiChunkList => new ChunkHelper(EmojiList, 8); + public string Icon => SubGroups.FirstOrDefault()?.Emojis.FirstOrDefault()?.Text; + + public IEnumerable EmojiList => SubGroups.SelectMany(s => s.Emojis); } public class Emoji diff --git a/src/Greenshot.Editor/Drawing/Emoji/EmojiContainer.cs b/src/Greenshot.Editor/Drawing/Emoji/EmojiContainer.cs index ecd6202b3..6d91b8ddb 100644 --- a/src/Greenshot.Editor/Drawing/Emoji/EmojiContainer.cs +++ b/src/Greenshot.Editor/Drawing/Emoji/EmojiContainer.cs @@ -26,7 +26,7 @@ using System.Windows.Forms; using System.Windows.Forms.Integration; using Greenshot.Base.Core; using Greenshot.Base.Interfaces.Drawing; -using Greenshot.Editor.Controls; +using Greenshot.Editor.Controls.Emoji; using Greenshot.Editor.Helpers; using Image = System.Drawing.Image; @@ -95,7 +95,10 @@ namespace Greenshot.Editor.Drawing.Emoji // Create one picker control by surface // TODO: This is not ideal, as we need to controls from the surface, should replace this with a different solution. _emojiPickerHost = _parent.Controls.Find("EmojiPickerHost", false).OfType().FirstOrDefault(); - if (_emojiPickerHost != null) return; + if (_emojiPickerHost != null) + { + return; + } _emojiPicker = new EmojiPicker(); _emojiPicker.Picked += (_, args) => @@ -136,7 +139,10 @@ namespace Greenshot.Editor.Drawing.Emoji /// PropertyChangedEventArgs private void OnPropertyChanged(object sender, PropertyChangedEventArgs e) { - if (!e.PropertyName.Equals(nameof(Selected))) return; + if (!e.PropertyName.Equals(nameof(Selected))) + { + return; + } if (!Selected) { From e4d7283b3babed261f6654a80c0af6488ebda763 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Wed, 26 Oct 2022 11:36:45 +0200 Subject: [PATCH 43/61] Fix parsing --- .gitignore | 5 ++++- src/Greenshot.Editor/Controls/Emoji/EmojiData.cs | 7 +++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 3afd2d7ab..2744ea1bb 100644 --- a/.gitignore +++ b/.gitignore @@ -214,4 +214,7 @@ ModelManifest.xml *.credentials.cs # Rider files -.idea \ No newline at end of file +.idea + +# Files compressed during the build +*.gz \ No newline at end of file diff --git a/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs b/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs index b01951026..0b80e1d94 100644 --- a/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs +++ b/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs @@ -83,7 +83,10 @@ namespace Greenshot.Editor.Controls.Emoji { // To be removed ParseEmojiList(); - x.Serialize(new XmlTextWriter(EmojisXmlFilePath, Encoding.UTF8), Data); + if (Data.Groups.Any()) + { + x.Serialize(new XmlTextWriter(EmojisXmlFilePath, Encoding.UTF8), Data); + } } #endif } @@ -205,7 +208,7 @@ namespace Greenshot.Editor.Controls.Emoji } 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(gzStream); return streamReader.ReadToEnd().Split('\r', '\n'); } #endif From 4e36be535bffaddf1db55974394c31fd64b91758 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Wed, 26 Oct 2022 12:01:40 +0200 Subject: [PATCH 44/61] Remove name on emoji + remove empty Variations in Emojis.xml --- src/Greenshot.Editor/Controls/Emoji/EmojiData.cs | 2 +- src/Greenshot.Editor/Controls/Emoji/EmojiPicker.xaml | 4 ++-- src/Greenshot.Editor/Controls/Emoji/Emojis.cs | 10 +++++++--- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs b/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs index 0b80e1d94..a1772b871 100644 --- a/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs +++ b/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs @@ -177,7 +177,7 @@ namespace Greenshot.Editor.Controls.Emoji qualifiedLut[unqualified] = text; - var emoji = new Emojis.Emoji { Name = name, Text = text}; + var emoji = new Emojis.Emoji { Text = text}; lookupByName[ToColonSyntax(name)] = emoji; diff --git a/src/Greenshot.Editor/Controls/Emoji/EmojiPicker.xaml b/src/Greenshot.Editor/Controls/Emoji/EmojiPicker.xaml index 349515ce1..4410e0ee7 100644 --- a/src/Greenshot.Editor/Controls/Emoji/EmojiPicker.xaml +++ b/src/Greenshot.Editor/Controls/Emoji/EmojiPicker.xaml @@ -35,7 +35,7 @@ @@ -46,7 +46,7 @@ + Click="OnEmojiPicked" Focusable="False" > diff --git a/src/Greenshot.Editor/Controls/Emoji/Emojis.cs b/src/Greenshot.Editor/Controls/Emoji/Emojis.cs index 95b8a2f8b..039dfaaf8 100644 --- a/src/Greenshot.Editor/Controls/Emoji/Emojis.cs +++ b/src/Greenshot.Editor/Controls/Emoji/Emojis.cs @@ -51,14 +51,18 @@ public class Emojis public class Emoji { - [XmlAttribute] - public string Name { get; set; } - [XmlAttribute] public string Text { get; set; } [XmlArray] public List Variations { get; set; } = new(); + + /// + /// Xml trick so that the Xml serializer does not output the 'Variations' element when the emoji has no variation + /// (see https://learn.microsoft.com/en-us/dotnet/api/system.xml.serialization.xmlserializer#controlling-generated-xml) + /// + [XmlIgnore] + public bool VariationsSpecified => HasVariations; public bool HasVariations => Variations.Count > 0; From 128436eafda8c83ed89b23f761f21422f239d994 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Wed, 26 Oct 2022 13:00:25 +0200 Subject: [PATCH 45/61] Compress TwemojiMozilla --- installer/innosetup/setup.iss | 4 ++-- .../Drawing/Emoji/EmojiRenderer.cs | 21 +++++++++++++++++-- src/Greenshot.Editor/Greenshot.Editor.csproj | 9 ++++++-- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/installer/innosetup/setup.iss b/installer/innosetup/setup.iss index d85dd60f9..e82377008 100644 --- a/installer/innosetup/setup.iss +++ b/installer/innosetup/setup.iss @@ -38,8 +38,8 @@ Source: {#ReleaseDir}\System.Memory.dll; DestDir: {app}; Components: greenshot; Source: {#ReleaseDir}\System.Numerics.Vectors.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\System.Runtime.CompilerServices.Unsafe.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\System.Buffers.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion -Source: {#ReleaseDir}\TwemojiMozilla.ttf; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion -Source: {#ReleaseDir}\emoji-test.txt; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion +Source: {#ReleaseDir}\TwemojiMozilla.ttf.gz; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion +Source: {#ReleaseDir}\emoji-test.txt.gz; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#GreenshotProjectDir}\log4net.xml; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion Source: {#ReleaseDir}\checksum.SHA256; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion ;Source: ..\greenshot-defaults.ini; DestDir: {app}; Flags: overwritereadonly ignoreversion replacesameversion diff --git a/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs b/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs index fcb0f422a..dc215f2c0 100644 --- a/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs +++ b/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs @@ -20,6 +20,7 @@ */ using System; +using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Reflection; @@ -41,15 +42,31 @@ namespace Greenshot.Editor.Drawing.Emoji private static readonly Lazy TwemojiFontFamily = new(() => { var exeDirectory = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location); - var twemojiFontFile = Path.Combine(exeDirectory, "TwemojiMozilla.ttf"); + var twemojiFontFile = Path.Combine(exeDirectory, "TwemojiMozilla.ttf.gz"); if (!File.Exists(twemojiFontFile)) { throw new FileNotFoundException($"Can't find {twemojiFontFile}, bad installation?"); } + Stopwatch sw = new(); + sw.Start(); using var fileStream = new FileStream(twemojiFontFile, FileMode.Open, FileAccess.Read); - TwemojiFontCollection.Add(fileStream); + using var gzStream = new GZipStream(fileStream, CompressionMode.Decompress); + using var memoryStream = new MemoryStream(); + gzStream.CopyTo(memoryStream); + memoryStream.Seek(0, SeekOrigin.Begin); + sw.Stop(); + + Console.WriteLine($"Uncompress .ttf: {sw.ElapsedMilliseconds} ms"); + + sw.Reset(); + sw.Start(); + TwemojiFontCollection.Add(memoryStream); TwemojiFontCollection.TryGet("Twemoji Mozilla", out var fontFamily); + sw.Stop(); + + Console.WriteLine($"Parse .ttf: {sw.ElapsedMilliseconds} ms"); + return fontFamily; }); diff --git a/src/Greenshot.Editor/Greenshot.Editor.csproj b/src/Greenshot.Editor/Greenshot.Editor.csproj index affaf81c7..b4c743cb5 100644 --- a/src/Greenshot.Editor/Greenshot.Editor.csproj +++ b/src/Greenshot.Editor/Greenshot.Editor.csproj @@ -20,6 +20,11 @@ OutputFile="Controls\Emoji\emoji-test.txt.gz" /> + + + + Component @@ -98,9 +103,9 @@ PreserveNewest emoji-test.txt.gz - + PreserveNewest - TwemojiMozilla.ttf + TwemojiMozilla.ttf.gz \ No newline at end of file From 2cc72e32ad376de2a86cf3c735ada9c9368684cc Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Fri, 28 Oct 2022 00:04:55 +0200 Subject: [PATCH 46/61] Created a custom task for generating emoji data, although this works in general, the next build doesn't. --- src/Greenshot.BuildTasks/EmojiDataTask.cs | 178 +++++++++++++++ .../Greenshot.BuildTasks.csproj | 9 + .../Controls/Emoji/EmojiData.cs | 206 ++---------------- src/Greenshot.Editor/Controls/Emoji/Emojis.cs | 15 +- src/Greenshot.Editor/Greenshot.Editor.csproj | 9 - src/Greenshot.sln | 29 ++- src/Greenshot/Greenshot.csproj | 6 + 7 files changed, 243 insertions(+), 209 deletions(-) create mode 100644 src/Greenshot.BuildTasks/EmojiDataTask.cs create mode 100644 src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj diff --git a/src/Greenshot.BuildTasks/EmojiDataTask.cs b/src/Greenshot.BuildTasks/EmojiDataTask.cs new file mode 100644 index 000000000..f046c6559 --- /dev/null +++ b/src/Greenshot.BuildTasks/EmojiDataTask.cs @@ -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 . + */ + +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; + +/// +/// 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 +/// +/// 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. +/// +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]+", "-"); + + /// + /// The name of the output file + /// + [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(); + var qualifiedLut = new Dictionary(); + 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; + } + + /// + /// This reads the specified file into lines + /// + /// string + /// + /// + private static IEnumerable 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; + } + } +} \ No newline at end of file diff --git a/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj b/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj new file mode 100644 index 000000000..9fa6da494 --- /dev/null +++ b/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs b/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs index a1772b871..b54bea4bb 100644 --- a/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs +++ b/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs @@ -1,67 +1,37 @@ -// -// Emoji.Wpf — Emoji support for WPF -// -// Copyright © 2017—2021 Sam Hocevar -// -// 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. -// +/* + * 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 . + */ using System; using System.IO; -using System.Text.RegularExpressions; using System.Xml; 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 { /// - /// 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. /// public static class EmojiData { 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 SkinToneComponents = new() - { - "🏻", // light skin tone - "🏼", // medium-light skin tone - "🏽", // medium skin tone - "🏾", // medium-dark skin tone - "🏿", // dark skin tone - }; - - private static readonly List 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(); @@ -73,144 +43,10 @@ namespace Greenshot.Editor.Controls.Emoji { 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(); - 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(); - - var qualifiedLut = new Dictionary(); - var allText = new List(); - - 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 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 } } \ No newline at end of file diff --git a/src/Greenshot.Editor/Controls/Emoji/Emojis.cs b/src/Greenshot.Editor/Controls/Emoji/Emojis.cs index 039dfaaf8..4314718b0 100644 --- a/src/Greenshot.Editor/Controls/Emoji/Emojis.cs +++ b/src/Greenshot.Editor/Controls/Emoji/Emojis.cs @@ -26,20 +26,22 @@ using System.Xml.Serialization; namespace Greenshot.Editor.Controls.Emoji; +[XmlRoot("Es")] public class Emojis { - [XmlElement(ElementName = "Group")] + [XmlArray(ElementName = "Gs")] public List Groups { get; set; } = new(); + [XmlType("G")] public class Group { - [XmlAttribute] + [XmlAttribute(AttributeName= "N")] public string Name { get; set; } - [XmlElement(ElementName = "Group")] + [XmlArray(ElementName = "Sg")] public List SubGroups { get; set; } = new(); - [XmlElement(ElementName = "Emoji")] + [XmlArray(ElementName = "Es")] public List Emojis { get; set; } = new(); public IEnumerable> EmojiChunkList => new ChunkHelper(EmojiList, 8); @@ -49,12 +51,13 @@ public class Emojis public IEnumerable EmojiList => SubGroups.SelectMany(s => s.Emojis); } + [XmlType("E")] public class Emoji { - [XmlAttribute] + [XmlAttribute(AttributeName = "T")] public string Text { get; set; } - [XmlArray] + [XmlArray(ElementName = "V")] public List Variations { get; set; } = new(); /// public static class EmojiData { - private const string EmojisXmlFilePath = "emojis.xml"; + private const string EmojisXmlFilePath = "emojis.xml.gz"; public static Emojis Data { get; private set; } = new(); @@ -41,7 +42,12 @@ namespace Greenshot.Editor.Controls.Emoji if (File.Exists(EmojisXmlFilePath)) { - Data = (Emojis)x.Deserialize(new XmlTextReader(EmojisXmlFilePath)); + using var fileStream = new FileStream(EmojisXmlFilePath, FileMode.Open, FileAccess.Read); + using var gzStream = new GZipStream(fileStream, CompressionMode.Decompress); + using var memoryStream = new MemoryStream(); + gzStream.CopyTo(memoryStream); + memoryStream.Seek(0, SeekOrigin.Begin); + Data = (Emojis)x.Deserialize(new XmlTextReader(memoryStream)); } else { diff --git a/src/Greenshot/Greenshot.csproj b/src/Greenshot/Greenshot.csproj index f9978f8fd..2141eac1d 100644 --- a/src/Greenshot/Greenshot.csproj +++ b/src/Greenshot/Greenshot.csproj @@ -70,6 +70,7 @@ + From 31532b4c586941d95ad2b352cd5345cb07ce89d8 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sat, 12 Aug 2023 16:47:48 +0200 Subject: [PATCH 52/61] Fix installer --- installer/innosetup/setup.iss | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/installer/innosetup/setup.iss b/installer/innosetup/setup.iss index 482c26d85..99ffaf749 100644 --- a/installer/innosetup/setup.iss +++ b/installer/innosetup/setup.iss @@ -38,8 +38,8 @@ Source: {#ReleaseDir}\System.Memory.dll; DestDir: {app}; Components: greenshot; Source: {#ReleaseDir}\System.Numerics.Vectors.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\System.Runtime.CompilerServices.Unsafe.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\System.Buffers.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion -Source: {#ReleaseDir}\TwemojiMozilla.ttf.gz; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion -Source: {#ReleaseDir}\emojis.xml; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion +Source: {#ReleaseDir}\Twemoji.Mozilla.ttf.gz; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion +Source: {#ReleaseDir}\emojis.xml.gz; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#GreenshotProjectDir}\log4net.xml; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion Source: {#ReleaseDir}\checksum.SHA256; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion ;Source: ..\greenshot-defaults.ini; DestDir: {app}; Flags: overwritereadonly ignoreversion replacesameversion From 9372ac53315466ac37cf823fc8776713d63d6966 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sat, 12 Aug 2023 17:07:37 +0200 Subject: [PATCH 53/61] Cleanup --- src/Greenshot.Base/Interfaces/ISurface.cs | 1 - src/Greenshot.Editor/Drawing/DrawableContainer.cs | 2 +- src/Greenshot.Editor/Drawing/Emoji/EmojiContainer.cs | 6 +----- src/Greenshot.Editor/Drawing/Surface.cs | 12 ++++++------ 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/Greenshot.Base/Interfaces/ISurface.cs b/src/Greenshot.Base/Interfaces/ISurface.cs index b739813ce..27f07c3aa 100644 --- a/src/Greenshot.Base/Interfaces/ISurface.cs +++ b/src/Greenshot.Base/Interfaces/ISurface.cs @@ -99,7 +99,6 @@ namespace Greenshot.Base.Interfaces IImageContainer AddImageContainer(string filename, int x, int y); ICursorContainer AddCursorContainer(string filename, int x, int y); IIconContainer AddIconContainer(string filename, int x, int y); - IEmojiContainer AddEmojiContainer(string emoji, int x, int y, int size); long SaveElementsToStream(Stream stream); void LoadElementsFromStream(Stream stream); diff --git a/src/Greenshot.Editor/Drawing/DrawableContainer.cs b/src/Greenshot.Editor/Drawing/DrawableContainer.cs index 33bc228c0..cac23dc3a 100644 --- a/src/Greenshot.Editor/Drawing/DrawableContainer.cs +++ b/src/Greenshot.Editor/Drawing/DrawableContainer.cs @@ -534,7 +534,7 @@ namespace Greenshot.Editor.Drawing _boundsAfterResize = new NativeRectFloat(_boundsBeforeResize.Left, _boundsBeforeResize.Top, x - _boundsAfterResize.Left, y - _boundsAfterResize.Top); var scaleOptions = (this as IHaveScaleOptions)?.GetScaleOptions(); - _boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, x, y,GetAngleRoundProcessor(), scaleOptions); + _boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, x, y, GetAngleRoundProcessor(), scaleOptions); // apply scaled bounds to this DrawableContainer ApplyBounds(_boundsAfterResize); diff --git a/src/Greenshot.Editor/Drawing/Emoji/EmojiContainer.cs b/src/Greenshot.Editor/Drawing/Emoji/EmojiContainer.cs index 6d91b8ddb..0206b6655 100644 --- a/src/Greenshot.Editor/Drawing/Emoji/EmojiContainer.cs +++ b/src/Greenshot.Editor/Drawing/Emoji/EmojiContainer.cs @@ -56,11 +56,7 @@ namespace Greenshot.Editor.Drawing.Emoji } } - public EmojiContainer(Surface parent) : this(parent, "🙂", size: 64) - { - } - - public EmojiContainer(Surface parent, string emoji, int size) : base(parent) + public EmojiContainer(Surface parent, string emoji, int size = 64) : base(parent) { Emoji = emoji; Width = size; diff --git a/src/Greenshot.Editor/Drawing/Surface.cs b/src/Greenshot.Editor/Drawing/Surface.cs index 32fdb938f..95fcf9e60 100644 --- a/src/Greenshot.Editor/Drawing/Surface.cs +++ b/src/Greenshot.Editor/Drawing/Surface.cs @@ -28,7 +28,7 @@ using System.Drawing.Imaging; using System.IO; using System.Linq; using System.Runtime.Serialization.Formatters.Binary; -using System.ServiceModel.Security; +using System.ServiceModel.Security; using System.Windows.Forms; using Dapplo.Windows.Common.Extensions; using Dapplo.Windows.Common.Structs; @@ -42,7 +42,7 @@ using Greenshot.Base.Interfaces.Drawing.Adorners; using Greenshot.Editor.Configuration; using Greenshot.Editor.Drawing.Emoji; using Greenshot.Editor.Drawing.Fields; -using Greenshot.Editor.Helpers; +using Greenshot.Editor.Helpers; using Greenshot.Editor.Memento; using log4net; @@ -735,9 +735,9 @@ namespace Greenshot.Editor.Drawing SelectElements(loadedElements); FieldAggregator.BindElements(loadedElements); } - catch (SecurityAccessDeniedException) - { - throw; + catch (SecurityAccessDeniedException) + { + throw; } catch (Exception e) { @@ -800,7 +800,7 @@ namespace Greenshot.Editor.Drawing _undrawnElement = null; break; case DrawingModes.Emoji: - _undrawnElement = new EmojiContainer(this); + _undrawnElement = new EmojiContainer(this, "🙂"); break; } From f6ca02b4368684228f12b0a3b128d95ba8135129 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sat, 12 Aug 2023 17:13:04 +0200 Subject: [PATCH 54/61] Fix scaling --- src/Greenshot.Editor/Helpers/ScaleHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Greenshot.Editor/Helpers/ScaleHelper.cs b/src/Greenshot.Editor/Helpers/ScaleHelper.cs index bc4bd361e..ab489889e 100644 --- a/src/Greenshot.Editor/Helpers/ScaleHelper.cs +++ b/src/Greenshot.Editor/Helpers/ScaleHelper.cs @@ -202,7 +202,7 @@ namespace Greenshot.Editor.Helpers { // scaled rectangle (ratio) would be taller than original // keep width and tweak height to maintain aspect ratio - newSize = newSize.ChangeWidth(selectedSize.Width / originalRatio * flippedRatioSign); + newSize = newSize.ChangeHeight(selectedSize.Width / originalRatio * flippedRatioSign); } return newSize; From c1c9cfb46b213c04ea2a20925480143b278bbe68 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sat, 12 Aug 2023 18:04:44 +0200 Subject: [PATCH 55/61] Remove .gzip compression --- installer/innosetup/setup.iss | 4 ++-- .../Controls/Emoji/EmojiData.cs | 9 ++------- .../Drawing/Emoji/EmojiRenderer.cs | 19 ++----------------- src/Greenshot.Editor/Greenshot.Editor.csproj | 9 ++------- src/Greenshot/Greenshot.csproj | 1 - 5 files changed, 8 insertions(+), 34 deletions(-) diff --git a/installer/innosetup/setup.iss b/installer/innosetup/setup.iss index 99ffaf749..72b513d64 100644 --- a/installer/innosetup/setup.iss +++ b/installer/innosetup/setup.iss @@ -38,8 +38,8 @@ Source: {#ReleaseDir}\System.Memory.dll; DestDir: {app}; Components: greenshot; Source: {#ReleaseDir}\System.Numerics.Vectors.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\System.Runtime.CompilerServices.Unsafe.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\System.Buffers.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion -Source: {#ReleaseDir}\Twemoji.Mozilla.ttf.gz; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion -Source: {#ReleaseDir}\emojis.xml.gz; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion +Source: {#ReleaseDir}\Twemoji.Mozilla.ttf; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion +Source: {#ReleaseDir}\emojis.xml; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#GreenshotProjectDir}\log4net.xml; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion Source: {#ReleaseDir}\checksum.SHA256; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion ;Source: ..\greenshot-defaults.ini; DestDir: {app}; Flags: overwritereadonly ignoreversion replacesameversion diff --git a/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs b/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs index 3f1ade1cc..cec1a532d 100644 --- a/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs +++ b/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs @@ -32,7 +32,7 @@ namespace Greenshot.Editor.Controls.Emoji /// public static class EmojiData { - private const string EmojisXmlFilePath = "emojis.xml.gz"; + private const string EmojisXmlFilePath = "emojis.xml"; public static Emojis Data { get; private set; } = new(); @@ -42,12 +42,7 @@ namespace Greenshot.Editor.Controls.Emoji if (File.Exists(EmojisXmlFilePath)) { - using var fileStream = new FileStream(EmojisXmlFilePath, FileMode.Open, FileAccess.Read); - using var gzStream = new GZipStream(fileStream, CompressionMode.Decompress); - using var memoryStream = new MemoryStream(); - gzStream.CopyTo(memoryStream); - memoryStream.Seek(0, SeekOrigin.Begin); - Data = (Emojis)x.Deserialize(new XmlTextReader(memoryStream)); + Data = (Emojis)x.Deserialize(new XmlTextReader(EmojisXmlFilePath)); } else { diff --git a/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs b/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs index ca5b78d99..4674c24a2 100644 --- a/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs +++ b/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs @@ -42,30 +42,15 @@ namespace Greenshot.Editor.Drawing.Emoji private static readonly Lazy TwemojiFontFamily = new(() => { var exeDirectory = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location); - var twemojiFontFile = Path.Combine(exeDirectory, "Twemoji.Mozilla.ttf.gz"); + var twemojiFontFile = Path.Combine(exeDirectory, "Twemoji.Mozilla.ttf"); if (!File.Exists(twemojiFontFile)) { throw new FileNotFoundException($"Can't find {twemojiFontFile}, bad installation?"); } - Stopwatch sw = new(); - sw.Start(); using var fileStream = new FileStream(twemojiFontFile, FileMode.Open, FileAccess.Read); - using var gzStream = new GZipStream(fileStream, CompressionMode.Decompress); - using var memoryStream = new MemoryStream(); - gzStream.CopyTo(memoryStream); - memoryStream.Seek(0, SeekOrigin.Begin); - sw.Stop(); - - Console.WriteLine($"Uncompress .ttf: {sw.ElapsedMilliseconds} ms"); - - sw.Reset(); - sw.Start(); - TwemojiFontCollection.Add(memoryStream); + TwemojiFontCollection.Add(fileStream); TwemojiFontCollection.TryGet("Twemoji Mozilla", out var fontFamily); - sw.Stop(); - - Console.WriteLine($"Parse .ttf: {sw.ElapsedMilliseconds} ms"); return fontFamily; }); diff --git a/src/Greenshot.Editor/Greenshot.Editor.csproj b/src/Greenshot.Editor/Greenshot.Editor.csproj index b1a19fa6e..62fbbd83b 100644 --- a/src/Greenshot.Editor/Greenshot.Editor.csproj +++ b/src/Greenshot.Editor/Greenshot.Editor.csproj @@ -15,11 +15,6 @@ - - - - Component @@ -94,9 +89,9 @@ - + PreserveNewest - Twemoji.Mozilla.ttf.gz + Twemoji.Mozilla.ttf \ No newline at end of file diff --git a/src/Greenshot/Greenshot.csproj b/src/Greenshot/Greenshot.csproj index 2141eac1d..f9978f8fd 100644 --- a/src/Greenshot/Greenshot.csproj +++ b/src/Greenshot/Greenshot.csproj @@ -70,7 +70,6 @@ - From b5e546258593375b210cff5ffa37149f4da12a5f Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sat, 12 Aug 2023 18:37:01 +0200 Subject: [PATCH 56/61] Tweak emoji rendering --- src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs b/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs index 4674c24a2..214ebb029 100644 --- a/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs +++ b/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs @@ -66,11 +66,11 @@ namespace Greenshot.Editor.Drawing.Emoji private static void RenderEmoji(string emoji, int iconSize, Image image) { var fontFamily = TwemojiFontFamily.Value; - var font = fontFamily.CreateFont(iconSize, FontStyle.Regular); + var font = fontFamily.CreateFont(iconSize * 0.95f, FontStyle.Regular); var verticalOffset = font.Size * 0.045f; var textOptions = new TextOptions(font) { - Origin = new PointF(font.Size / 2.0f, font.Size / 2.0f + verticalOffset), + Origin = new PointF(iconSize / 2.0f, iconSize / 2.0f + verticalOffset), HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; From 817a1d80c1d5d9c04ca22ce7c136972ebe1b339b Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Mon, 14 Aug 2023 15:37:59 +0200 Subject: [PATCH 57/61] SixLabors.ImageSharp.Drawing@1.0.0 --- src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs | 2 +- src/Greenshot.Editor/Greenshot.Editor.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs b/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs index 214ebb029..af31e0173 100644 --- a/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs +++ b/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs @@ -68,7 +68,7 @@ namespace Greenshot.Editor.Drawing.Emoji var fontFamily = TwemojiFontFamily.Value; var font = fontFamily.CreateFont(iconSize * 0.95f, FontStyle.Regular); var verticalOffset = font.Size * 0.045f; - var textOptions = new TextOptions(font) + var textOptions = new RichTextOptions(font) { Origin = new PointF(iconSize / 2.0f, iconSize / 2.0f + verticalOffset), HorizontalAlignment = HorizontalAlignment.Center, diff --git a/src/Greenshot.Editor/Greenshot.Editor.csproj b/src/Greenshot.Editor/Greenshot.Editor.csproj index 62fbbd83b..e0b75512a 100644 --- a/src/Greenshot.Editor/Greenshot.Editor.csproj +++ b/src/Greenshot.Editor/Greenshot.Editor.csproj @@ -8,7 +8,7 @@ - + From 5e7b5162d9b118387f6a9a33b4e758a27d9a269d Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sat, 26 Aug 2023 18:29:48 +0200 Subject: [PATCH 58/61] Fix diff for ScaleHelper --- src/Greenshot.Editor/Helpers/ScaleHelper.cs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Greenshot.Editor/Helpers/ScaleHelper.cs b/src/Greenshot.Editor/Helpers/ScaleHelper.cs index ab489889e..8e4a76a13 100644 --- a/src/Greenshot.Editor/Helpers/ScaleHelper.cs +++ b/src/Greenshot.Editor/Helpers/ScaleHelper.cs @@ -33,7 +33,7 @@ namespace Greenshot.Editor.Helpers /// public static class ScaleHelper { - /// + /// /// calculates the Size an element must be resized to, in order to fit another element, keeping aspect ratio /// /// the size of the element to be resized @@ -215,14 +215,15 @@ namespace Greenshot.Editor.Helpers /// int /// int /// IDoubleProcessor - /// ScaleOptionsProcessor + /// ScaleOptions /// NativeRectFloat - public static NativeRectFloat Scale(NativeRect boundsBeforeResize, int cursorX, int cursorY, IDoubleProcessor angleRoundBehavior, ScaleOptions? options = null) + public static NativeRectFloat Scale(NativeRect boundsBeforeResize, int cursorX, int cursorY, IDoubleProcessor angleRoundBehavior, ScaleOptions? scaleOptions = null) { - options ??= GetScaleOptions(); + scaleOptions ??= GetScaleOptions(); + NativeRectFloat result = boundsBeforeResize; - bool rationalScale = (options & ScaleOptions.Rational) == ScaleOptions.Rational; - bool centeredScale = (options & ScaleOptions.Centered) == ScaleOptions.Centered; + bool rationalScale = (scaleOptions & ScaleOptions.Rational) == ScaleOptions.Rational; + bool centeredScale = (scaleOptions & ScaleOptions.Centered) == ScaleOptions.Centered; if (rationalScale) { @@ -260,5 +261,5 @@ namespace Greenshot.Editor.Helpers if (maintainAspectRatio) opts |= ScaleOptions.Rational; return opts; } - } + } } \ No newline at end of file From 50fb6e65ab5c7c3076a43fc9fad051b8bbaea437 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sun, 27 Aug 2023 09:35:43 +0200 Subject: [PATCH 59/61] Remove GZip task --- src/Directory.Build.targets | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/Directory.Build.targets b/src/Directory.Build.targets index 68bf0563f..f2ce406a1 100644 --- a/src/Directory.Build.targets +++ b/src/Directory.Build.targets @@ -10,22 +10,4 @@ - - - - - - - - - - - - \ No newline at end of file From b12ace28e4b918860f98fd83c36b902e60c9b654 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sat, 11 Nov 2023 19:01:40 +0100 Subject: [PATCH 60/61] Fix .xml loading --- src/Greenshot.Base/Core/EnvironmentInfo.cs | 7 +++++++ src/Greenshot.Base/Core/Language.cs | 2 +- src/Greenshot.Editor/Controls/Emoji/EmojiData.cs | 4 ++-- src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs | 4 ++-- 4 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/Greenshot.Base/Core/EnvironmentInfo.cs b/src/Greenshot.Base/Core/EnvironmentInfo.cs index 30811fb69..0d163326e 100644 --- a/src/Greenshot.Base/Core/EnvironmentInfo.cs +++ b/src/Greenshot.Base/Core/EnvironmentInfo.cs @@ -20,6 +20,7 @@ */ using System; +using System.IO; using System.Reflection; using System.Runtime.InteropServices; using System.Text; @@ -265,6 +266,12 @@ namespace Greenshot.Base.Core return exceptionText.ToString(); } + + /// + /// Returns the directory where the application is located + /// + public static string GetApplicationFolder() + => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); } /// diff --git a/src/Greenshot.Base/Core/Language.cs b/src/Greenshot.Base/Core/Language.cs index 4627a10fc..8794ff54d 100644 --- a/src/Greenshot.Base/Core/Language.cs +++ b/src/Greenshot.Base/Core/Language.cs @@ -73,7 +73,7 @@ namespace Greenshot.Base.Core try { - string applicationFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + string applicationFolder = EnvironmentInfo.GetApplicationFolder(); // PAF Path if (applicationFolder != null) diff --git a/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs b/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs index cec1a532d..8b634f684 100644 --- a/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs +++ b/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs @@ -21,9 +21,9 @@ using System; using System.IO; -using System.IO.Compression; using System.Xml; using System.Xml.Serialization; +using Greenshot.Base.Core; namespace Greenshot.Editor.Controls.Emoji { @@ -32,7 +32,7 @@ namespace Greenshot.Editor.Controls.Emoji /// public static class EmojiData { - private const string EmojisXmlFilePath = "emojis.xml"; + private static readonly string EmojisXmlFilePath = Path.Combine(EnvironmentInfo.GetApplicationFolder(), "emojis.xml"); public static Emojis Data { get; private set; } = new(); diff --git a/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs b/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs index af31e0173..fa50059a1 100644 --- a/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs +++ b/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs @@ -24,6 +24,7 @@ using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Reflection; +using Greenshot.Base.Core; using SixLabors.Fonts; using SixLabors.ImageSharp; using SixLabors.ImageSharp.Drawing.Processing; @@ -41,8 +42,7 @@ namespace Greenshot.Editor.Drawing.Emoji private static readonly Lazy TwemojiFontFamily = new(() => { - var exeDirectory = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location); - var twemojiFontFile = Path.Combine(exeDirectory, "Twemoji.Mozilla.ttf"); + var twemojiFontFile = Path.Combine(EnvironmentInfo.GetApplicationFolder(), "Twemoji.Mozilla.ttf"); if (!File.Exists(twemojiFontFile)) { throw new FileNotFoundException($"Can't find {twemojiFontFile}, bad installation?"); From 3eb07ff4a5c031b9b25afc1266333c0aeafc5a4e Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sun, 16 Mar 2025 08:23:01 +0100 Subject: [PATCH 61/61] SixLabors.ImageSharp.Drawing@1.0.0 in BuildTask too --- src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj b/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj index f17e1ec78..b394a7fd4 100644 --- a/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj +++ b/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj @@ -7,7 +7,7 @@ all runtime - + diff --git a/src/Greenshot.Editor/Greenshot.Editor.csproj b/src/Greenshot.Editor/Greenshot.Editor.csproj index b4c743cb5..37825ea1e 100644 --- a/src/Greenshot.Editor/Greenshot.Editor.csproj +++ b/src/Greenshot.Editor/Greenshot.Editor.csproj @@ -15,11 +15,6 @@ - - - - @@ -99,10 +94,6 @@ - - PreserveNewest - emoji-test.txt.gz - PreserveNewest TwemojiMozilla.ttf.gz diff --git a/src/Greenshot.sln b/src/Greenshot.sln index 91ddf4314..cdb9f6565 100644 --- a/src/Greenshot.sln +++ b/src/Greenshot.sln @@ -1,21 +1,22 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29728.190 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32929.385 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot", "Greenshot\Greenshot.csproj", "{CD642BF4-D815-4D67-A0B5-C69F0B8231AF}" 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} + {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} {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} - {1893A2E4-A78A-4713-A8E7-E70058DABEE0} = {1893A2E4-A78A-4713-A8E7-E70058DABEE0} + {C3052651-598A-44E2-AAB3-2E41311D50F9} = {C3052651-598A-44E2-AAB3-2E41311D50F9} EndProjectSection EndProject 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 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Greenshot.Editor", "Greenshot.Editor\Greenshot.Editor.csproj", "{148D3C8B-D6EC-4A7D-80E9-243A81F19DD2}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Greenshot.BuildTasks", "Greenshot.BuildTasks\Greenshot.BuildTasks.csproj", "{25C870BE-22BB-4CB8-B274-95DC481F53A7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution 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|x86.ActiveCfg = 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 GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/Greenshot/Greenshot.csproj b/src/Greenshot/Greenshot.csproj index fc4dd90d1..5d7356e18 100644 --- a/src/Greenshot/Greenshot.csproj +++ b/src/Greenshot/Greenshot.csproj @@ -65,6 +65,12 @@ + + + + + + From 011e21a3f40d434995a40a0812f3935fec4d121b Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Fri, 28 Oct 2022 09:51:20 +0200 Subject: [PATCH 47/61] This fixes the Emoji feature, the emojis.xml is generated and added to the installer. --- installer/innosetup/setup.iss | 2 +- src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj | 5 ++++- src/Greenshot/Greenshot.csproj | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/installer/innosetup/setup.iss b/installer/innosetup/setup.iss index e82377008..31a0035f2 100644 --- a/installer/innosetup/setup.iss +++ b/installer/innosetup/setup.iss @@ -39,7 +39,7 @@ Source: {#ReleaseDir}\System.Numerics.Vectors.dll; DestDir: {app}; Components: g Source: {#ReleaseDir}\System.Runtime.CompilerServices.Unsafe.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\System.Buffers.dll; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#ReleaseDir}\TwemojiMozilla.ttf.gz; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion -Source: {#ReleaseDir}\emoji-test.txt.gz; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion +Source: {#ReleaseDir}\emojis.xml; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion Source: {#GreenshotProjectDir}\log4net.xml; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion Source: {#ReleaseDir}\checksum.SHA256; DestDir: {app}; Components: greenshot; Flags: overwritereadonly ignoreversion replacesameversion ;Source: ..\greenshot-defaults.ini; DestDir: {app}; Flags: overwritereadonly ignoreversion replacesameversion diff --git a/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj b/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj index 9fa6da494..4b229e7d7 100644 --- a/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj +++ b/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj @@ -1,9 +1,12 @@  - + + + + \ No newline at end of file diff --git a/src/Greenshot/Greenshot.csproj b/src/Greenshot/Greenshot.csproj index 5d7356e18..53ff2fe71 100644 --- a/src/Greenshot/Greenshot.csproj +++ b/src/Greenshot/Greenshot.csproj @@ -65,7 +65,7 @@ - + From 34b96294773840b031065ff52a281cace6416b11 Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Fri, 28 Oct 2022 14:00:23 +0200 Subject: [PATCH 48/61] Build task does not depend on Greenshot.Editor.csproj anymore --- src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj | 9 +++++++-- src/Greenshot.Editor/Controls/Emoji/Emojis.cs | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj b/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj index 4b229e7d7..c29263448 100644 --- a/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj +++ b/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj @@ -1,10 +1,15 @@  + + $(DefineConstants);GREENSHOT_BUILDTASKS + - + - + + Emojis.cs + diff --git a/src/Greenshot.Editor/Controls/Emoji/Emojis.cs b/src/Greenshot.Editor/Controls/Emoji/Emojis.cs index 4314718b0..22be775db 100644 --- a/src/Greenshot.Editor/Controls/Emoji/Emojis.cs +++ b/src/Greenshot.Editor/Controls/Emoji/Emojis.cs @@ -44,11 +44,13 @@ public class Emojis [XmlArray(ElementName = "Es")] public List Emojis { get; set; } = new(); +#if !GREENSHOT_BUILDTASKS public IEnumerable> EmojiChunkList => new ChunkHelper(EmojiList, 8); public string Icon => SubGroups.FirstOrDefault()?.Emojis.FirstOrDefault()?.Text; public IEnumerable EmojiList => SubGroups.SelectMany(s => s.Emojis); +#endif } [XmlType("E")] From e9eabf966c0be6de47f26c962026eca55c51d82f Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Mon, 31 Oct 2022 17:46:21 +0100 Subject: [PATCH 49/61] Cleaning a bit the MsBuild task --- src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj | 8 ++++---- src/Greenshot/Greenshot.csproj | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj b/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj index c29263448..f17e1ec78 100644 --- a/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj +++ b/src/Greenshot.BuildTasks/Greenshot.BuildTasks.csproj @@ -3,7 +3,10 @@ $(DefineConstants);GREENSHOT_BUILDTASKS - + + all + runtime + @@ -11,7 +14,4 @@ Emojis.cs - - - \ No newline at end of file diff --git a/src/Greenshot/Greenshot.csproj b/src/Greenshot/Greenshot.csproj index 53ff2fe71..f9978f8fd 100644 --- a/src/Greenshot/Greenshot.csproj +++ b/src/Greenshot/Greenshot.csproj @@ -33,6 +33,7 @@ + @@ -65,7 +66,7 @@ - + From c1dcf94956e57efa97a2394b1306b250d1fdb23c Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sat, 12 Aug 2023 15:24:43 +0200 Subject: [PATCH 50/61] Twemoji 14.0 --- .../Controls/Emoji/emoji-test.txt | 156 +++++++++++++++--- .../Drawing/Emoji/EmojiRenderer.cs | 2 +- ...TwemojiMozilla.ttf => Twemoji.Mozilla.ttf} | Bin 1437964 -> 1474284 bytes src/Greenshot.Editor/Greenshot.Editor.csproj | 8 +- 4 files changed, 139 insertions(+), 27 deletions(-) rename src/Greenshot.Editor/Drawing/Emoji/{TwemojiMozilla.ttf => Twemoji.Mozilla.ttf} (67%) diff --git a/src/Greenshot.Editor/Controls/Emoji/emoji-test.txt b/src/Greenshot.Editor/Controls/Emoji/emoji-test.txt index d3c6d12bd..dd5493366 100644 --- a/src/Greenshot.Editor/Controls/Emoji/emoji-test.txt +++ b/src/Greenshot.Editor/Controls/Emoji/emoji-test.txt @@ -1,11 +1,11 @@ # emoji-test.txt -# Date: 2020-09-12, 22:19:50 GMT -# © 2020 Unicode®, Inc. +# Date: 2021-08-26, 17:22:23 GMT +# © 2021 Unicode®, Inc. # Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries. # For terms of use, see http://www.unicode.org/terms_of_use.html # # Emoji Keyboard/Display Test Data for UTS #51 -# Version: 13.1 +# Version: 14.0 # # For documentation and usage, see http://www.unicode.org/reports/tr51 # @@ -43,6 +43,7 @@ 1F602 ; fully-qualified # 😂 E0.6 face with tears of joy 1F642 ; fully-qualified # 🙂 E1.0 slightly smiling face 1F643 ; fully-qualified # 🙃 E1.0 upside-down face +1FAE0 ; fully-qualified # 🫠 E14.0 melting face 1F609 ; fully-qualified # 😉 E0.6 winking face 1F60A ; fully-qualified # 😊 E0.6 smiling face with smiling eyes 1F607 ; fully-qualified # 😇 E1.0 smiling face with halo @@ -68,10 +69,13 @@ 1F911 ; fully-qualified # 🤑 E1.0 money-mouth face # subgroup: face-hand -1F917 ; fully-qualified # 🤗 E1.0 hugging face +1F917 ; fully-qualified # 🤗 E1.0 smiling face with open hands 1F92D ; fully-qualified # 🤭 E5.0 face with hand over mouth +1FAE2 ; fully-qualified # 🫢 E14.0 face with open eyes and hand over mouth +1FAE3 ; fully-qualified # 🫣 E14.0 face with peeking eye 1F92B ; fully-qualified # 🤫 E5.0 shushing face 1F914 ; fully-qualified # 🤔 E1.0 thinking face +1FAE1 ; fully-qualified # 🫡 E14.0 saluting face # subgroup: face-neutral-skeptical 1F910 ; fully-qualified # 🤐 E1.0 zipper-mouth face @@ -79,6 +83,7 @@ 1F610 ; fully-qualified # 😐 E0.7 neutral face 1F611 ; fully-qualified # 😑 E1.0 expressionless face 1F636 ; fully-qualified # 😶 E1.0 face without mouth +1FAE5 ; fully-qualified # 🫥 E14.0 dotted line face 1F636 200D 1F32B FE0F ; fully-qualified # 😶‍🌫️ E13.1 face in clouds 1F636 200D 1F32B ; minimally-qualified # 😶‍🌫 E13.1 face in clouds 1F60F ; fully-qualified # 😏 E0.6 smirking face @@ -105,7 +110,7 @@ 1F975 ; fully-qualified # 🥵 E11.0 hot face 1F976 ; fully-qualified # 🥶 E11.0 cold face 1F974 ; fully-qualified # 🥴 E11.0 woozy face -1F635 ; fully-qualified # 😵 E0.6 knocked-out face +1F635 ; fully-qualified # 😵 E0.6 face with crossed-out eyes 1F635 200D 1F4AB ; fully-qualified # 😵‍💫 E13.1 face with spiral eyes 1F92F ; fully-qualified # 🤯 E5.0 exploding head @@ -121,6 +126,7 @@ # subgroup: face-concerned 1F615 ; fully-qualified # 😕 E1.0 confused face +1FAE4 ; fully-qualified # 🫤 E14.0 face with diagonal mouth 1F61F ; fully-qualified # 😟 E1.0 worried face 1F641 ; fully-qualified # 🙁 E1.0 slightly frowning face 2639 FE0F ; fully-qualified # ☹️ E0.7 frowning face @@ -130,6 +136,7 @@ 1F632 ; fully-qualified # 😲 E0.6 astonished face 1F633 ; fully-qualified # 😳 E0.6 flushed face 1F97A ; fully-qualified # 🥺 E11.0 pleading face +1F979 ; fully-qualified # 🥹 E14.0 face holding back tears 1F626 ; fully-qualified # 😦 E1.0 frowning face with open mouth 1F627 ; fully-qualified # 😧 E1.0 anguished face 1F628 ; fully-qualified # 😨 E0.6 fearful face @@ -232,8 +239,8 @@ 1F4AD ; fully-qualified # 💭 E1.0 thought balloon 1F4A4 ; fully-qualified # 💤 E0.6 zzz -# Smileys & Emotion subtotal: 170 -# Smileys & Emotion subtotal: 170 w/o modifiers +# Smileys & Emotion subtotal: 177 +# Smileys & Emotion subtotal: 177 w/o modifiers # group: People & Body @@ -269,6 +276,30 @@ 1F596 1F3FD ; fully-qualified # 🖖🏽 E1.0 vulcan salute: medium skin tone 1F596 1F3FE ; fully-qualified # 🖖🏾 E1.0 vulcan salute: medium-dark skin tone 1F596 1F3FF ; fully-qualified # 🖖🏿 E1.0 vulcan salute: dark skin tone +1FAF1 ; fully-qualified # 🫱 E14.0 rightwards hand +1FAF1 1F3FB ; fully-qualified # 🫱🏻 E14.0 rightwards hand: light skin tone +1FAF1 1F3FC ; fully-qualified # 🫱🏼 E14.0 rightwards hand: medium-light skin tone +1FAF1 1F3FD ; fully-qualified # 🫱🏽 E14.0 rightwards hand: medium skin tone +1FAF1 1F3FE ; fully-qualified # 🫱🏾 E14.0 rightwards hand: medium-dark skin tone +1FAF1 1F3FF ; fully-qualified # 🫱🏿 E14.0 rightwards hand: dark skin tone +1FAF2 ; fully-qualified # 🫲 E14.0 leftwards hand +1FAF2 1F3FB ; fully-qualified # 🫲🏻 E14.0 leftwards hand: light skin tone +1FAF2 1F3FC ; fully-qualified # 🫲🏼 E14.0 leftwards hand: medium-light skin tone +1FAF2 1F3FD ; fully-qualified # 🫲🏽 E14.0 leftwards hand: medium skin tone +1FAF2 1F3FE ; fully-qualified # 🫲🏾 E14.0 leftwards hand: medium-dark skin tone +1FAF2 1F3FF ; fully-qualified # 🫲🏿 E14.0 leftwards hand: dark skin tone +1FAF3 ; fully-qualified # 🫳 E14.0 palm down hand +1FAF3 1F3FB ; fully-qualified # 🫳🏻 E14.0 palm down hand: light skin tone +1FAF3 1F3FC ; fully-qualified # 🫳🏼 E14.0 palm down hand: medium-light skin tone +1FAF3 1F3FD ; fully-qualified # 🫳🏽 E14.0 palm down hand: medium skin tone +1FAF3 1F3FE ; fully-qualified # 🫳🏾 E14.0 palm down hand: medium-dark skin tone +1FAF3 1F3FF ; fully-qualified # 🫳🏿 E14.0 palm down hand: dark skin tone +1FAF4 ; fully-qualified # 🫴 E14.0 palm up hand +1FAF4 1F3FB ; fully-qualified # 🫴🏻 E14.0 palm up hand: light skin tone +1FAF4 1F3FC ; fully-qualified # 🫴🏼 E14.0 palm up hand: medium-light skin tone +1FAF4 1F3FD ; fully-qualified # 🫴🏽 E14.0 palm up hand: medium skin tone +1FAF4 1F3FE ; fully-qualified # 🫴🏾 E14.0 palm up hand: medium-dark skin tone +1FAF4 1F3FF ; fully-qualified # 🫴🏿 E14.0 palm up hand: dark skin tone # subgroup: hand-fingers-partial 1F44C ; fully-qualified # 👌 E0.6 OK hand @@ -302,6 +333,12 @@ 1F91E 1F3FD ; fully-qualified # 🤞🏽 E3.0 crossed fingers: medium skin tone 1F91E 1F3FE ; fully-qualified # 🤞🏾 E3.0 crossed fingers: medium-dark skin tone 1F91E 1F3FF ; fully-qualified # 🤞🏿 E3.0 crossed fingers: dark skin tone +1FAF0 ; fully-qualified # 🫰 E14.0 hand with index finger and thumb crossed +1FAF0 1F3FB ; fully-qualified # 🫰🏻 E14.0 hand with index finger and thumb crossed: light skin tone +1FAF0 1F3FC ; fully-qualified # 🫰🏼 E14.0 hand with index finger and thumb crossed: medium-light skin tone +1FAF0 1F3FD ; fully-qualified # 🫰🏽 E14.0 hand with index finger and thumb crossed: medium skin tone +1FAF0 1F3FE ; fully-qualified # 🫰🏾 E14.0 hand with index finger and thumb crossed: medium-dark skin tone +1FAF0 1F3FF ; fully-qualified # 🫰🏿 E14.0 hand with index finger and thumb crossed: dark skin tone 1F91F ; fully-qualified # 🤟 E5.0 love-you gesture 1F91F 1F3FB ; fully-qualified # 🤟🏻 E5.0 love-you gesture: light skin tone 1F91F 1F3FC ; fully-qualified # 🤟🏼 E5.0 love-you gesture: medium-light skin tone @@ -359,6 +396,12 @@ 261D 1F3FD ; fully-qualified # ☝🏽 E1.0 index pointing up: medium skin tone 261D 1F3FE ; fully-qualified # ☝🏾 E1.0 index pointing up: medium-dark skin tone 261D 1F3FF ; fully-qualified # ☝🏿 E1.0 index pointing up: dark skin tone +1FAF5 ; fully-qualified # 🫵 E14.0 index pointing at the viewer +1FAF5 1F3FB ; fully-qualified # 🫵🏻 E14.0 index pointing at the viewer: light skin tone +1FAF5 1F3FC ; fully-qualified # 🫵🏼 E14.0 index pointing at the viewer: medium-light skin tone +1FAF5 1F3FD ; fully-qualified # 🫵🏽 E14.0 index pointing at the viewer: medium skin tone +1FAF5 1F3FE ; fully-qualified # 🫵🏾 E14.0 index pointing at the viewer: medium-dark skin tone +1FAF5 1F3FF ; fully-qualified # 🫵🏿 E14.0 index pointing at the viewer: dark skin tone # subgroup: hand-fingers-closed 1F44D ; fully-qualified # 👍 E0.6 thumbs up @@ -411,6 +454,12 @@ 1F64C 1F3FD ; fully-qualified # 🙌🏽 E1.0 raising hands: medium skin tone 1F64C 1F3FE ; fully-qualified # 🙌🏾 E1.0 raising hands: medium-dark skin tone 1F64C 1F3FF ; fully-qualified # 🙌🏿 E1.0 raising hands: dark skin tone +1FAF6 ; fully-qualified # 🫶 E14.0 heart hands +1FAF6 1F3FB ; fully-qualified # 🫶🏻 E14.0 heart hands: light skin tone +1FAF6 1F3FC ; fully-qualified # 🫶🏼 E14.0 heart hands: medium-light skin tone +1FAF6 1F3FD ; fully-qualified # 🫶🏽 E14.0 heart hands: medium skin tone +1FAF6 1F3FE ; fully-qualified # 🫶🏾 E14.0 heart hands: medium-dark skin tone +1FAF6 1F3FF ; fully-qualified # 🫶🏿 E14.0 heart hands: dark skin tone 1F450 ; fully-qualified # 👐 E0.6 open hands 1F450 1F3FB ; fully-qualified # 👐🏻 E1.0 open hands: light skin tone 1F450 1F3FC ; fully-qualified # 👐🏼 E1.0 open hands: medium-light skin tone @@ -424,6 +473,31 @@ 1F932 1F3FE ; fully-qualified # 🤲🏾 E5.0 palms up together: medium-dark skin tone 1F932 1F3FF ; fully-qualified # 🤲🏿 E5.0 palms up together: dark skin tone 1F91D ; fully-qualified # 🤝 E3.0 handshake +1F91D 1F3FB ; fully-qualified # 🤝🏻 E3.0 handshake: light skin tone +1F91D 1F3FC ; fully-qualified # 🤝🏼 E3.0 handshake: medium-light skin tone +1F91D 1F3FD ; fully-qualified # 🤝🏽 E3.0 handshake: medium skin tone +1F91D 1F3FE ; fully-qualified # 🤝🏾 E3.0 handshake: medium-dark skin tone +1F91D 1F3FF ; fully-qualified # 🤝🏿 E3.0 handshake: dark skin tone +1FAF1 1F3FB 200D 1FAF2 1F3FC ; fully-qualified # 🫱🏻‍🫲🏼 E14.0 handshake: light skin tone, medium-light skin tone +1FAF1 1F3FB 200D 1FAF2 1F3FD ; fully-qualified # 🫱🏻‍🫲🏽 E14.0 handshake: light skin tone, medium skin tone +1FAF1 1F3FB 200D 1FAF2 1F3FE ; fully-qualified # 🫱🏻‍🫲🏾 E14.0 handshake: light skin tone, medium-dark skin tone +1FAF1 1F3FB 200D 1FAF2 1F3FF ; fully-qualified # 🫱🏻‍🫲🏿 E14.0 handshake: light skin tone, dark skin tone +1FAF1 1F3FC 200D 1FAF2 1F3FB ; fully-qualified # 🫱🏼‍🫲🏻 E14.0 handshake: medium-light skin tone, light skin tone +1FAF1 1F3FC 200D 1FAF2 1F3FD ; fully-qualified # 🫱🏼‍🫲🏽 E14.0 handshake: medium-light skin tone, medium skin tone +1FAF1 1F3FC 200D 1FAF2 1F3FE ; fully-qualified # 🫱🏼‍🫲🏾 E14.0 handshake: medium-light skin tone, medium-dark skin tone +1FAF1 1F3FC 200D 1FAF2 1F3FF ; fully-qualified # 🫱🏼‍🫲🏿 E14.0 handshake: medium-light skin tone, dark skin tone +1FAF1 1F3FD 200D 1FAF2 1F3FB ; fully-qualified # 🫱🏽‍🫲🏻 E14.0 handshake: medium skin tone, light skin tone +1FAF1 1F3FD 200D 1FAF2 1F3FC ; fully-qualified # 🫱🏽‍🫲🏼 E14.0 handshake: medium skin tone, medium-light skin tone +1FAF1 1F3FD 200D 1FAF2 1F3FE ; fully-qualified # 🫱🏽‍🫲🏾 E14.0 handshake: medium skin tone, medium-dark skin tone +1FAF1 1F3FD 200D 1FAF2 1F3FF ; fully-qualified # 🫱🏽‍🫲🏿 E14.0 handshake: medium skin tone, dark skin tone +1FAF1 1F3FE 200D 1FAF2 1F3FB ; fully-qualified # 🫱🏾‍🫲🏻 E14.0 handshake: medium-dark skin tone, light skin tone +1FAF1 1F3FE 200D 1FAF2 1F3FC ; fully-qualified # 🫱🏾‍🫲🏼 E14.0 handshake: medium-dark skin tone, medium-light skin tone +1FAF1 1F3FE 200D 1FAF2 1F3FD ; fully-qualified # 🫱🏾‍🫲🏽 E14.0 handshake: medium-dark skin tone, medium skin tone +1FAF1 1F3FE 200D 1FAF2 1F3FF ; fully-qualified # 🫱🏾‍🫲🏿 E14.0 handshake: medium-dark skin tone, dark skin tone +1FAF1 1F3FF 200D 1FAF2 1F3FB ; fully-qualified # 🫱🏿‍🫲🏻 E14.0 handshake: dark skin tone, light skin tone +1FAF1 1F3FF 200D 1FAF2 1F3FC ; fully-qualified # 🫱🏿‍🫲🏼 E14.0 handshake: dark skin tone, medium-light skin tone +1FAF1 1F3FF 200D 1FAF2 1F3FD ; fully-qualified # 🫱🏿‍🫲🏽 E14.0 handshake: dark skin tone, medium skin tone +1FAF1 1F3FF 200D 1FAF2 1F3FE ; fully-qualified # 🫱🏿‍🫲🏾 E14.0 handshake: dark skin tone, medium-dark skin tone 1F64F ; fully-qualified # 🙏 E0.6 folded hands 1F64F 1F3FB ; fully-qualified # 🙏🏻 E1.0 folded hands: light skin tone 1F64F 1F3FC ; fully-qualified # 🙏🏼 E1.0 folded hands: medium-light skin tone @@ -501,6 +575,7 @@ 1F441 ; unqualified # 👁 E0.7 eye 1F445 ; fully-qualified # 👅 E0.6 tongue 1F444 ; fully-qualified # 👄 E0.6 mouth +1FAE6 ; fully-qualified # 🫦 E14.0 biting lip # subgroup: person 1F476 ; fully-qualified # 👶 E0.6 baby @@ -1472,6 +1547,12 @@ 1F477 1F3FE 200D 2640 ; minimally-qualified # 👷🏾‍♀ E4.0 woman construction worker: medium-dark skin tone 1F477 1F3FF 200D 2640 FE0F ; fully-qualified # 👷🏿‍♀️ E4.0 woman construction worker: dark skin tone 1F477 1F3FF 200D 2640 ; minimally-qualified # 👷🏿‍♀ E4.0 woman construction worker: dark skin tone +1FAC5 ; fully-qualified # 🫅 E14.0 person with crown +1FAC5 1F3FB ; fully-qualified # 🫅🏻 E14.0 person with crown: light skin tone +1FAC5 1F3FC ; fully-qualified # 🫅🏼 E14.0 person with crown: medium-light skin tone +1FAC5 1F3FD ; fully-qualified # 🫅🏽 E14.0 person with crown: medium skin tone +1FAC5 1F3FE ; fully-qualified # 🫅🏾 E14.0 person with crown: medium-dark skin tone +1FAC5 1F3FF ; fully-qualified # 🫅🏿 E14.0 person with crown: dark skin tone 1F934 ; fully-qualified # 🤴 E3.0 prince 1F934 1F3FB ; fully-qualified # 🤴🏻 E3.0 prince: light skin tone 1F934 1F3FC ; fully-qualified # 🤴🏼 E3.0 prince: medium-light skin tone @@ -1592,6 +1673,18 @@ 1F930 1F3FD ; fully-qualified # 🤰🏽 E3.0 pregnant woman: medium skin tone 1F930 1F3FE ; fully-qualified # 🤰🏾 E3.0 pregnant woman: medium-dark skin tone 1F930 1F3FF ; fully-qualified # 🤰🏿 E3.0 pregnant woman: dark skin tone +1FAC3 ; fully-qualified # 🫃 E14.0 pregnant man +1FAC3 1F3FB ; fully-qualified # 🫃🏻 E14.0 pregnant man: light skin tone +1FAC3 1F3FC ; fully-qualified # 🫃🏼 E14.0 pregnant man: medium-light skin tone +1FAC3 1F3FD ; fully-qualified # 🫃🏽 E14.0 pregnant man: medium skin tone +1FAC3 1F3FE ; fully-qualified # 🫃🏾 E14.0 pregnant man: medium-dark skin tone +1FAC3 1F3FF ; fully-qualified # 🫃🏿 E14.0 pregnant man: dark skin tone +1FAC4 ; fully-qualified # 🫄 E14.0 pregnant person +1FAC4 1F3FB ; fully-qualified # 🫄🏻 E14.0 pregnant person: light skin tone +1FAC4 1F3FC ; fully-qualified # 🫄🏼 E14.0 pregnant person: medium-light skin tone +1FAC4 1F3FD ; fully-qualified # 🫄🏽 E14.0 pregnant person: medium skin tone +1FAC4 1F3FE ; fully-qualified # 🫄🏾 E14.0 pregnant person: medium-dark skin tone +1FAC4 1F3FF ; fully-qualified # 🫄🏿 E14.0 pregnant person: dark skin tone 1F931 ; fully-qualified # 🤱 E5.0 breast-feeding 1F931 1F3FB ; fully-qualified # 🤱🏻 E5.0 breast-feeding: light skin tone 1F931 1F3FC ; fully-qualified # 🤱🏼 E5.0 breast-feeding: medium-light skin tone @@ -1862,6 +1955,7 @@ 1F9DF 200D 2642 ; minimally-qualified # 🧟‍♂ E5.0 man zombie 1F9DF 200D 2640 FE0F ; fully-qualified # 🧟‍♀️ E5.0 woman zombie 1F9DF 200D 2640 ; minimally-qualified # 🧟‍♀ E5.0 woman zombie +1F9CC ; fully-qualified # 🧌 E14.0 troll # subgroup: person-activity 1F486 ; fully-qualified # 💆 E0.6 person getting massage @@ -3168,8 +3262,8 @@ 1FAC2 ; fully-qualified # 🫂 E13.0 people hugging 1F463 ; fully-qualified # 👣 E0.6 footprints -# People & Body subtotal: 2899 -# People & Body subtotal: 494 w/o modifiers +# People & Body subtotal: 2986 +# People & Body subtotal: 506 w/o modifiers # group: Component @@ -3304,6 +3398,7 @@ 1F988 ; fully-qualified # 🦈 E3.0 shark 1F419 ; fully-qualified # 🐙 E0.6 octopus 1F41A ; fully-qualified # 🐚 E0.6 spiral shell +1FAB8 ; fully-qualified # 🪸 E14.0 coral # subgroup: animal-bug 1F40C ; fully-qualified # 🐌 E0.6 snail @@ -3329,6 +3424,7 @@ 1F490 ; fully-qualified # 💐 E0.6 bouquet 1F338 ; fully-qualified # 🌸 E0.6 cherry blossom 1F4AE ; fully-qualified # 💮 E0.6 white flower +1FAB7 ; fully-qualified # 🪷 E14.0 lotus 1F3F5 FE0F ; fully-qualified # 🏵️ E0.7 rosette 1F3F5 ; unqualified # 🏵 E0.7 rosette 1F339 ; fully-qualified # 🌹 E0.6 rose @@ -3353,9 +3449,11 @@ 1F341 ; fully-qualified # 🍁 E0.6 maple leaf 1F342 ; fully-qualified # 🍂 E0.6 fallen leaf 1F343 ; fully-qualified # 🍃 E0.6 leaf fluttering in wind +1FAB9 ; fully-qualified # 🪹 E14.0 empty nest +1FABA ; fully-qualified # 🪺 E14.0 nest with eggs -# Animals & Nature subtotal: 147 -# Animals & Nature subtotal: 147 w/o modifiers +# Animals & Nature subtotal: 151 +# Animals & Nature subtotal: 151 w/o modifiers # group: Food & Drink @@ -3396,6 +3494,7 @@ 1F9C5 ; fully-qualified # 🧅 E12.0 onion 1F344 ; fully-qualified # 🍄 E0.6 mushroom 1F95C ; fully-qualified # 🥜 E3.0 peanuts +1FAD8 ; fully-qualified # 🫘 E14.0 beans 1F330 ; fully-qualified # 🌰 E0.6 chestnut # subgroup: food-prepared @@ -3491,6 +3590,7 @@ 1F37B ; fully-qualified # 🍻 E0.6 clinking beer mugs 1F942 ; fully-qualified # 🥂 E3.0 clinking glasses 1F943 ; fully-qualified # 🥃 E3.0 tumbler glass +1FAD7 ; fully-qualified # 🫗 E14.0 pouring liquid 1F964 ; fully-qualified # 🥤 E5.0 cup with straw 1F9CB ; fully-qualified # 🧋 E13.0 bubble tea 1F9C3 ; fully-qualified # 🧃 E12.0 beverage box @@ -3504,10 +3604,11 @@ 1F374 ; fully-qualified # 🍴 E0.6 fork and knife 1F944 ; fully-qualified # 🥄 E3.0 spoon 1F52A ; fully-qualified # 🔪 E0.6 kitchen knife +1FAD9 ; fully-qualified # 🫙 E14.0 jar 1F3FA ; fully-qualified # 🏺 E1.0 amphora -# Food & Drink subtotal: 131 -# Food & Drink subtotal: 131 w/o modifiers +# Food & Drink subtotal: 134 +# Food & Drink subtotal: 134 w/o modifiers # group: Travel & Places @@ -3597,6 +3698,7 @@ 2668 FE0F ; fully-qualified # ♨️ E0.6 hot springs 2668 ; unqualified # ♨ E0.6 hot springs 1F3A0 ; fully-qualified # 🎠 E0.6 carousel horse +1F6DD ; fully-qualified # 🛝 E14.0 playground slide 1F3A1 ; fully-qualified # 🎡 E0.6 ferris wheel 1F3A2 ; fully-qualified # 🎢 E0.6 roller coaster 1F488 ; fully-qualified # 💈 E0.6 barber pole @@ -3652,6 +3754,7 @@ 1F6E2 FE0F ; fully-qualified # 🛢️ E0.7 oil drum 1F6E2 ; unqualified # 🛢 E0.7 oil drum 26FD ; fully-qualified # ⛽ E0.6 fuel pump +1F6DE ; fully-qualified # 🛞 E14.0 wheel 1F6A8 ; fully-qualified # 🚨 E0.6 police car light 1F6A5 ; fully-qualified # 🚥 E0.6 horizontal traffic light 1F6A6 ; fully-qualified # 🚦 E1.0 vertical traffic light @@ -3660,6 +3763,7 @@ # subgroup: transport-water 2693 ; fully-qualified # ⚓ E0.6 anchor +1F6DF ; fully-qualified # 🛟 E14.0 ring buoy 26F5 ; fully-qualified # ⛵ E0.6 sailboat 1F6F6 ; fully-qualified # 🛶 E3.0 canoe 1F6A4 ; fully-qualified # 🚤 E0.6 speedboat @@ -3797,8 +3901,8 @@ 1F4A7 ; fully-qualified # 💧 E0.6 droplet 1F30A ; fully-qualified # 🌊 E0.6 water wave -# Travel & Places subtotal: 264 -# Travel & Places subtotal: 264 w/o modifiers +# Travel & Places subtotal: 267 +# Travel & Places subtotal: 267 w/o modifiers # group: Activities @@ -3874,6 +3978,7 @@ 1F52E ; fully-qualified # 🔮 E0.6 crystal ball 1FA84 ; fully-qualified # 🪄 E13.0 magic wand 1F9FF ; fully-qualified # 🧿 E11.0 nazar amulet +1FAAC ; fully-qualified # 🪬 E14.0 hamsa 1F3AE ; fully-qualified # 🎮 E0.6 video game 1F579 FE0F ; fully-qualified # 🕹️ E0.7 joystick 1F579 ; unqualified # 🕹 E0.7 joystick @@ -3882,6 +3987,7 @@ 1F9E9 ; fully-qualified # 🧩 E11.0 puzzle piece 1F9F8 ; fully-qualified # 🧸 E11.0 teddy bear 1FA85 ; fully-qualified # 🪅 E13.0 piñata +1FAA9 ; fully-qualified # 🪩 E14.0 mirror ball 1FA86 ; fully-qualified # 🪆 E13.0 nesting dolls 2660 FE0F ; fully-qualified # ♠️ E0.6 spade suit 2660 ; unqualified # ♠ E0.6 spade suit @@ -3907,8 +4013,8 @@ 1F9F6 ; fully-qualified # 🧶 E11.0 yarn 1FAA2 ; fully-qualified # 🪢 E13.0 knot -# Activities subtotal: 95 -# Activities subtotal: 95 w/o modifiers +# Activities subtotal: 97 +# Activities subtotal: 97 w/o modifiers # group: Objects @@ -4009,6 +4115,7 @@ # subgroup: computer 1F50B ; fully-qualified # 🔋 E0.6 battery +1FAAB ; fully-qualified # 🪫 E14.0 low battery 1F50C ; fully-qualified # 🔌 E0.6 electric plug 1F4BB ; fully-qualified # 💻 E0.6 laptop 1F5A5 FE0F ; fully-qualified # 🖥️ E0.7 desktop computer @@ -4207,7 +4314,9 @@ 1FA78 ; fully-qualified # 🩸 E12.0 drop of blood 1F48A ; fully-qualified # 💊 E0.6 pill 1FA79 ; fully-qualified # 🩹 E12.0 adhesive bandage +1FA7C ; fully-qualified # 🩼 E14.0 crutch 1FA7A ; fully-qualified # 🩺 E12.0 stethoscope +1FA7B ; fully-qualified # 🩻 E14.0 x-ray # subgroup: household 1F6AA ; fully-qualified # 🚪 E0.6 door @@ -4232,6 +4341,7 @@ 1F9FB ; fully-qualified # 🧻 E11.0 roll of paper 1FAA3 ; fully-qualified # 🪣 E13.0 bucket 1F9FC ; fully-qualified # 🧼 E11.0 soap +1FAE7 ; fully-qualified # 🫧 E14.0 bubbles 1FAA5 ; fully-qualified # 🪥 E13.0 toothbrush 1F9FD ; fully-qualified # 🧽 E11.0 sponge 1F9EF ; fully-qualified # 🧯 E11.0 fire extinguisher @@ -4246,9 +4356,10 @@ 26B1 ; unqualified # ⚱ E1.0 funeral urn 1F5FF ; fully-qualified # 🗿 E0.6 moai 1FAA7 ; fully-qualified # 🪧 E13.0 placard +1FAAA ; fully-qualified # 🪪 E14.0 identification card -# Objects subtotal: 299 -# Objects subtotal: 299 w/o modifiers +# Objects subtotal: 304 +# Objects subtotal: 304 w/o modifiers # group: Symbols @@ -4409,6 +4520,7 @@ 2795 ; fully-qualified # ➕ E0.6 plus 2796 ; fully-qualified # ➖ E0.6 minus 2797 ; fully-qualified # ➗ E0.6 divide +1F7F0 ; fully-qualified # 🟰 E14.0 heavy equals sign 267E FE0F ; fully-qualified # ♾️ E11.0 infinity 267E ; unqualified # ♾ E11.0 infinity @@ -4581,8 +4693,8 @@ 1F533 ; fully-qualified # 🔳 E0.6 white square button 1F532 ; fully-qualified # 🔲 E0.6 black square button -# Symbols subtotal: 301 -# Symbols subtotal: 301 w/o modifiers +# Symbols subtotal: 302 +# Symbols subtotal: 302 w/o modifiers # group: Flags @@ -4871,7 +4983,7 @@ # Flags subtotal: 275 w/o modifiers # Status Counts -# fully-qualified : 3512 +# fully-qualified : 3624 # minimally-qualified : 817 # unqualified : 252 # component : 9 diff --git a/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs b/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs index dc215f2c0..ca5b78d99 100644 --- a/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs +++ b/src/Greenshot.Editor/Drawing/Emoji/EmojiRenderer.cs @@ -42,7 +42,7 @@ namespace Greenshot.Editor.Drawing.Emoji private static readonly Lazy TwemojiFontFamily = new(() => { var exeDirectory = Path.GetDirectoryName(Assembly.GetCallingAssembly().Location); - var twemojiFontFile = Path.Combine(exeDirectory, "TwemojiMozilla.ttf.gz"); + var twemojiFontFile = Path.Combine(exeDirectory, "Twemoji.Mozilla.ttf.gz"); if (!File.Exists(twemojiFontFile)) { throw new FileNotFoundException($"Can't find {twemojiFontFile}, bad installation?"); diff --git a/src/Greenshot.Editor/Drawing/Emoji/TwemojiMozilla.ttf b/src/Greenshot.Editor/Drawing/Emoji/Twemoji.Mozilla.ttf similarity index 67% rename from src/Greenshot.Editor/Drawing/Emoji/TwemojiMozilla.ttf rename to src/Greenshot.Editor/Drawing/Emoji/Twemoji.Mozilla.ttf index 75ddc213ff8fc6d84167f7bb9d1b787ce40160a4..9f45178e9deffd5c71d15ab8dea6132202063282 100644 GIT binary patch delta 258411 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≫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
0t2VW9Kn{DtP!eFxx(IRmS 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 - + @@ -94,9 +94,9 @@ - + PreserveNewest - TwemojiMozilla.ttf.gz + Twemoji.Mozilla.ttf.gz \ No newline at end of file From 12b42774de887bdfbb7d1cfe73090e0623284d5d Mon Sep 17 00:00:00 2001 From: Julien Richard Date: Sat, 12 Aug 2023 16:43:09 +0200 Subject: [PATCH 51/61] Compress Emojis.xml too --- src/Greenshot.Editor/Controls/Emoji/EmojiData.cs | 10 ++++++++-- src/Greenshot/Greenshot.csproj | 1 + 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs b/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs index b54bea4bb..3f1ade1cc 100644 --- a/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs +++ b/src/Greenshot.Editor/Controls/Emoji/EmojiData.cs @@ -21,6 +21,7 @@ using System; using System.IO; +using System.IO.Compression; using System.Xml; using System.Xml.Serialization; @@ -31,7 +32,7 @@ namespace Greenshot.Editor.Controls.Emoji ///