From 94591e5b1414c0dd9ee97843476795dd4802672e Mon Sep 17 00:00:00 2001 From: Robin Krom Date: Thu, 14 Apr 2022 11:58:52 +0200 Subject: [PATCH] Small fixes to the VectorGraphicsContainer, to align it with the possible coming EmojiContainer. Still having issues with Scaling code, this needs to be fixed. [skip ci] --- src/Greenshot.Base/Greenshot.Base.csproj | 14 +++--- src/Greenshot.Editor/Drawing/CropContainer.cs | 2 +- .../Drawing/DrawableContainer.cs | 2 +- .../Drawing/VectorGraphicsContainer.cs | 49 ++++++++++++++++--- src/Greenshot.Editor/Helpers/ScaleHelper.cs | 47 +++++++++--------- 5 files changed, 75 insertions(+), 39 deletions(-) diff --git a/src/Greenshot.Base/Greenshot.Base.csproj b/src/Greenshot.Base/Greenshot.Base.csproj index 169bd9395..805098491 100644 --- a/src/Greenshot.Base/Greenshot.Base.csproj +++ b/src/Greenshot.Base/Greenshot.Base.csproj @@ -6,15 +6,15 @@ - - - - - - + + + + + + - + diff --git a/src/Greenshot.Editor/Drawing/CropContainer.cs b/src/Greenshot.Editor/Drawing/CropContainer.cs index 2aee4252f..d450e9dd2 100644 --- a/src/Greenshot.Editor/Drawing/CropContainer.cs +++ b/src/Greenshot.Editor/Drawing/CropContainer.cs @@ -250,7 +250,7 @@ namespace Greenshot.Editor.Drawing break; } } - _boundsAfterResize = ScaleHelper.Scale(_boundsBeforeResize, x, y, GetAngleRoundProcessor()); + _boundsAfterResize = ScaleHelper.Scale(_boundsBeforeResize, Positions.TopLeft, x, y, GetAngleRoundProcessor()); // apply scaled bounds to this DrawableContainer ApplyBounds(_boundsAfterResize); diff --git a/src/Greenshot.Editor/Drawing/DrawableContainer.cs b/src/Greenshot.Editor/Drawing/DrawableContainer.cs index be4638164..c9737f9e3 100644 --- a/src/Greenshot.Editor/Drawing/DrawableContainer.cs +++ b/src/Greenshot.Editor/Drawing/DrawableContainer.cs @@ -533,7 +533,7 @@ namespace Greenshot.Editor.Drawing // reset "workbench" rectangle to current bounds _boundsAfterResize = new NativeRectFloat(_boundsBeforeResize.Left, _boundsBeforeResize.Top, x - _boundsAfterResize.Left, y - _boundsAfterResize.Top); - _boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, x, y, GetAngleRoundProcessor()); + _boundsAfterResize = ScaleHelper.Scale(_boundsAfterResize, Positions.TopLeft, x, y, GetAngleRoundProcessor()); // apply scaled bounds to this DrawableContainer ApplyBounds(_boundsAfterResize); diff --git a/src/Greenshot.Editor/Drawing/VectorGraphicsContainer.cs b/src/Greenshot.Editor/Drawing/VectorGraphicsContainer.cs index 0c467c0b8..45238caaf 100644 --- a/src/Greenshot.Editor/Drawing/VectorGraphicsContainer.cs +++ b/src/Greenshot.Editor/Drawing/VectorGraphicsContainer.cs @@ -25,6 +25,7 @@ using System.Drawing.Drawing2D; using System.Runtime.Serialization; using Greenshot.Base.Interfaces; using Greenshot.Base.Interfaces.Drawing; +using Greenshot.Editor.Drawing.Adorners; namespace Greenshot.Editor.Drawing { @@ -35,28 +36,54 @@ namespace Greenshot.Editor.Drawing [Serializable] public abstract class VectorGraphicsContainer : DrawableContainer { - protected int RotationAngle; + private int _rotationAngle; + protected int RotationAngle + { + get => _rotationAngle; + set => _rotationAngle = value; + } /// /// This is the cached version of the bitmap, pre-rendered to save performance - /// Do not serialized, it can be rebuild with some other information. + /// Do not serialized, it can be rebuild with other information. /// [NonSerialized] private Image _cachedImage; + /// + /// Constructor takes care of calling Init + /// + /// ISurface public VectorGraphicsContainer(ISurface parent) : base(parent) { Init(); } + /// + /// Make sure Init is called after deserializing + /// + /// StreamingContext protected override void OnDeserialized(StreamingContext streamingContext) { base.OnDeserialized(streamingContext); Init(); } - private void Init() + /// + /// Init is called after creating the instance, and from OnDeserialized + /// This is the place to generate your adorners + /// + protected virtual void Init() { - CreateDefaultAdorners(); + // Check if the adorners are already defined! + if (Adorners.Count > 0) + { + return; + } + + Adorners.Add(new ResizeAdorner(this, Positions.TopLeft)); + Adorners.Add(new ResizeAdorner(this, Positions.TopRight)); + Adorners.Add(new ResizeAdorner(this, Positions.BottomLeft)); + Adorners.Add(new ResizeAdorner(this, Positions.BottomRight)); } /// @@ -96,7 +123,10 @@ namespace Greenshot.Editor.Drawing } _cachedImage ??= ComputeBitmap(); - + if (_cachedImage == null) + { + return; + } graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; graphics.CompositingQuality = CompositingQuality.HighQuality; @@ -106,9 +136,16 @@ namespace Greenshot.Editor.Drawing graphics.DrawImage(_cachedImage, Bounds); } + /// + /// Implement this to compute the new bitmap according to the size of the container + /// + /// Image protected abstract Image ComputeBitmap(); - private void ResetCachedBitmap() + /// + /// Dispose of the cached bitmap, forcing the code to regenerate it + /// + protected void ResetCachedBitmap() { _cachedImage?.Dispose(); _cachedImage = null; diff --git a/src/Greenshot.Editor/Helpers/ScaleHelper.cs b/src/Greenshot.Editor/Helpers/ScaleHelper.cs index 4f4e7dc7a..63f25d0a0 100644 --- a/src/Greenshot.Editor/Helpers/ScaleHelper.cs +++ b/src/Greenshot.Editor/Helpers/ScaleHelper.cs @@ -58,7 +58,7 @@ namespace Greenshot.Editor.Helpers /// the size of the element to be resized /// the target size of the element /// in case the aspect ratio of currentSize and targetSize differs: shall the scaled size fit into targetSize (i.e. that one of its dimensions is smaller - false) or vice versa (true) - /// a new SizeF object indicating the width and height the element should be scaled to + /// NativeSizeFloat object indicating the width and height the element should be scaled to public static NativeSizeFloat GetScaledSize(NativeSizeFloat currentSize, NativeSizeFloat targetSize, bool crop) { float wFactor = targetSize.Width / currentSize.Width; @@ -71,10 +71,10 @@ namespace Greenshot.Editor.Helpers /// /// calculates the position of an element depending on the desired alignment within a RectangleF /// - /// the bounds of the element to be aligned - /// the rectangle reference for alignment of the element + /// NativeRectFloat the bounds of the element to be aligned + /// NativeRectFloat with the rectangle for alignment of the element /// the System.Drawing.ContentAlignment value indicating how the element is to be aligned should the width or height differ from targetSize - /// a new RectangleF object with Location aligned aligned to targetRect + /// NativeRectFloat object with Location aligned aligned to targetRect public static NativeRectFloat GetAlignedRectangle(NativeRectFloat currentRect, NativeRectFloat targetRect, ContentAlignment alignment) { var newRect = new NativeRectFloat(targetRect.Location, currentRect.Size); @@ -96,9 +96,9 @@ namespace Greenshot.Editor.Helpers /// /// Calculates target size of a given rectangle scaled by dragging one of its handles (corners) /// - /// bounds of the current rectangle - /// position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT - /// coordinates of the used handle/gripper + /// NativeRectFloat bounds of the current rectangle + /// Positions with the position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT + /// NativePointFloat coordinates of the used handle/gripper /// ScaleOptions to use when scaling /// NativeRectFloat scaled originalRectangle public static NativeRectFloat Scale(NativeRectFloat originalRectangle, Positions resizeHandlePosition, NativePointFloat resizeHandleCoords, ScaleOptions? options) @@ -134,9 +134,9 @@ namespace Greenshot.Editor.Helpers /// /// Calculates target size of a given rectangle scaled by dragging one of its handles (corners) /// - /// bounds of the current rectangle - /// position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT - /// coordinates of the used handle/gripper + /// NativeRectFloat bounds of the current rectangle + /// Positions with the position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT + /// NativePointFloat with coordinates of the used handle/gripper /// NativeRectFloat with the scaled originalRectangle private static NativeRectFloat Scale(NativeRectFloat originalRectangle, Positions resizeHandlePosition, NativePointFloat resizeHandleCoords) { @@ -158,9 +158,9 @@ namespace Greenshot.Editor.Helpers /// To avoid objects growing near infinity unexpectedly in certain combinations, the adjustment will choose the /// option resulting in the smaller rectangle. /// - /// bounds of the current rectangle - /// position of the handle/gripper being used for resized, see Position - /// coordinates of the used handle/gripper + /// NativeRectFloat with the bounds of the current rectangle + /// Positions with the position of the handle/gripper being used for resized, see Position + /// NativePointFloat with coordinates of the used handle/gripper /// NativePointFloat with the adjusted coordinates private static NativePointFloat AdjustCoordsForRationalScale(NativeRectFloat originalRectangle, Positions resizeHandlePosition, NativePointFloat resizeHandleCoords) { @@ -203,7 +203,7 @@ namespace Greenshot.Editor.Helpers /// /// NativeSizeFloat to be considered for keeping aspect ratio /// NativeSizeFloat selection size (i.e. the size we'd produce if we wouldn't keep aspect ratio) - /// + /// NativeSizeFloat private static NativeSizeFloat GetNewSizeForRationalScale(NativeSizeFloat originalSize, NativeSizeFloat selectedSize) { NativeSizeFloat newSize = selectedSize; @@ -227,16 +227,15 @@ namespace Greenshot.Editor.Helpers return newSize; } - public static NativeRectFloat Scale(NativeRect boundsBeforeResize, int cursorX, int cursorY) - { - return Scale(boundsBeforeResize, cursorX, cursorY, null); - } - - public static NativeRectFloat Scale(NativeRect boundsBeforeResize, int cursorX, int cursorY, IDoubleProcessor angleRoundBehavior) - { - return Scale(boundsBeforeResize, Positions.TopLeft, cursorX, cursorY, angleRoundBehavior); - } - + /// + /// Scale the boundsBeforeResize with the specified position and new location, using the angle angleRoundBehavior + /// + /// NativeRect + /// Positions + /// int + /// int + /// IDoubleProcessor + /// NativeRectFloat public static NativeRectFloat Scale(NativeRect boundsBeforeResize, Positions gripperPosition, int cursorX, int cursorY, IDoubleProcessor angleRoundBehavior) { ScaleOptions opts = GetScaleOptions();