New "Emoji" object in editor

This commit is contained in:
Julien Richard 2022-01-09 18:05:39 +01:00
commit be89971197
12 changed files with 262 additions and 19 deletions

View file

@ -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; }

View file

@ -35,6 +35,7 @@ namespace Greenshot.Base.Interfaces
Bitmap,
Path,
SpeechBubble,
StepLabel
StepLabel,
Emoji
}
}

View file

@ -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);

View file

@ -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 <https://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Description of EmojiContainer.
/// </summary>
[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;
}
}
}

View file

@ -178,6 +178,8 @@ namespace Greenshot.Editor.Drawing
/// </summary>
/// <param name="matrix"></param>
public override void Transform(Matrix matrix)
{
if (image != null)
{
int rotateAngle = CalculateAngle(matrix);
// we currently assume only one transformation has been made.
@ -191,6 +193,7 @@ namespace Greenshot.Editor.Drawing
image = ImageHelper.ApplyEffect(image, new RotateEffect(rotateAngle), tmpMatrix);
}
}
}
base.Transform(matrix);
}

View file

@ -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)

View file

@ -70,6 +70,7 @@ 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.btnHighlight = new GreenshotToolStripButton();
this.btnObfuscate = new GreenshotToolStripButton();
@ -334,6 +335,7 @@ namespace Greenshot.Editor.Forms {
this.btnText,
this.btnSpeechBubble,
this.btnStepLabel,
this.btnEmoji,
this.toolStripSeparator14,
this.btnHighlight,
this.btnObfuscate,
@ -444,6 +446,16 @@ namespace Greenshot.Editor.Forms {
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.LanguageKey = "editor_emoji";
this.btnEmoji.Name = "btnEmoji";
this.btnEmoji.Click += new System.EventHandler(this.BtnEmojiClick);
//
// toolStripSeparator14
//
this.toolStripSeparator14.Name = "toolStripSeparator14";
@ -1928,6 +1940,7 @@ namespace Greenshot.Editor.Forms {
private GreenshotToolStripButton btnText;
private GreenshotToolStripButton btnSpeechBubble;
private GreenshotToolStripButton btnStepLabel;
private GreenshotToolStripButton btnEmoji;
private GreenshotToolStripMenuItem drawLineToolStripMenuItem;
private GreenshotToolStripButton btnLine;
private GreenshotToolStripButton btnSettings;

View file

@ -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;

View file

@ -1107,4 +1107,7 @@
<metadata name="zoomMenuStrip.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>782, 17</value>
</metadata>
<data name="btnEmoji.Image" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\btnEmoji.Image.bmp;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>

View file

@ -4,6 +4,9 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Emoji.Wpf" Version="0.3.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Greenshot.Base\Greenshot.Base.csproj" />
@ -81,4 +84,8 @@
<DependentUpon>ImageEditorForm.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Folder Include="Resources\" />
</ItemGroup>
</Project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View file

@ -305,6 +305,7 @@ All Greenshot features still work directly from the tray icon context menu witho
<resource name="editor_counter">Add counter (I)</resource>
<resource name="editor_speechbubble">Add speechbubble (S)</resource>
<resource name="editor_emoji">Add emoji</resource>
<resource name="editor_resize">Resize</resource>
<resource name="editor_resize_settings">Resize settings</resource>