mirror of
https://github.com/greenshot/greenshot
synced 2025-08-14 02:37:03 -07:00
Moving back to trunk!
git-svn-id: http://svn.code.sf.net/p/greenshot/code/trunk@1602 7dccd23d-a4a3-4e1f-8c07-b4c1b4018ab4
This commit is contained in:
parent
ad265b2c54
commit
8d458998a1
332 changed files with 17647 additions and 9466 deletions
|
@ -20,15 +20,29 @@
|
|||
*/
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
using Greenshot.Drawing;
|
||||
|
||||
namespace Greenshot.Helpers {
|
||||
/// <summary>
|
||||
/// Offers a few helper functions for scaling/aligning an element with another element
|
||||
/// </summary>
|
||||
public class ScaleHelper {
|
||||
private ScaleHelper() {
|
||||
public static class ScaleHelper {
|
||||
|
||||
[Flags]
|
||||
public enum ScaleOptions {
|
||||
/// <summary>
|
||||
/// Scale a rectangle in two our four directions, mirrored at it's center coordinates
|
||||
/// </summary>
|
||||
Centered = 0x01,
|
||||
/// <summary>
|
||||
/// Scale a rectangle maintaining it's aspect ratio
|
||||
/// </summary>
|
||||
Rational = 0x02
|
||||
}
|
||||
|
||||
private static readonly log4net.ILog LOG = log4net.LogManager.GetLogger(typeof(ScaleHelper));
|
||||
|
||||
/// <summary>
|
||||
/// calculates the Size an element must be resized to, in order to fit another element, keeping aspect ratio
|
||||
/// </summary>
|
||||
|
@ -41,8 +55,6 @@ namespace Greenshot.Helpers {
|
|||
float hFactor = targetSize.Height/currentSize.Height;
|
||||
|
||||
float factor = crop ? Math.Max(wFactor, hFactor) : Math.Min(wFactor, hFactor);
|
||||
//System.Diagnostics.Debug.WriteLine(currentSize.Width+"..."+targetSize.Width);
|
||||
//System.Diagnostics.Debug.WriteLine(wFactor+"..."+hFactor+">>>"+factor);
|
||||
return new SizeF(currentSize.Width * factor, currentSize.Height * factor);
|
||||
}
|
||||
|
||||
|
@ -101,5 +113,260 @@ namespace Greenshot.Helpers {
|
|||
RectangleF newRect = new RectangleF(new Point(0,0), newSize);
|
||||
return GetAlignedRectangle(newRect, targetRect, alignment);
|
||||
}
|
||||
|
||||
public static void RationalScale(ref RectangleF originalRectangle, int resizeHandlePosition, PointF resizeHandleCoords) {
|
||||
Scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords, ScaleOptions.Rational);
|
||||
}
|
||||
|
||||
public static void CenteredScale(ref RectangleF originalRectangle, int resizeHandlePosition, PointF resizeHandleCoords) {
|
||||
Scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords, ScaleOptions.Centered);
|
||||
}
|
||||
|
||||
public static void Scale(ref RectangleF originalRectangle, int resizeHandlePosition, PointF resizeHandleCoords) {
|
||||
Scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords, 0x0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates target size of a given rectangle scaled by dragging one of its handles (corners)
|
||||
/// </summary>
|
||||
/// <param name="originalRectangle">bounds of the current rectangle, scaled values will be written to this reference</param>
|
||||
/// <param name="resizeHandlePosition">position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT</param>
|
||||
/// <param name="resizeHandleCoords">coordinates of the used handle/gripper</param>
|
||||
/// <param name="options">ScaleOptions to use when scaling</param>
|
||||
public static void Scale(ref RectangleF originalRectangle, int resizeHandlePosition, PointF resizeHandleCoords, ScaleOptions options) {
|
||||
if(options == null) {
|
||||
options = GetScaleOptions();
|
||||
}
|
||||
|
||||
if((options & ScaleOptions.Rational) == ScaleOptions.Rational) {
|
||||
adjustCoordsForRationalScale(originalRectangle, resizeHandlePosition, ref resizeHandleCoords);
|
||||
}
|
||||
|
||||
if((options & ScaleOptions.Centered) == ScaleOptions.Centered) {
|
||||
// store center coordinates of rectangle
|
||||
float rectCenterX = originalRectangle.Left + originalRectangle.Width / 2;
|
||||
float rectCenterY = originalRectangle.Top + originalRectangle.Height / 2;
|
||||
// scale rectangle using handle coordinates
|
||||
scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords);
|
||||
// mirror handle coordinates via rectangle center coordinates
|
||||
resizeHandleCoords.X -= 2 * (resizeHandleCoords.X - rectCenterX);
|
||||
resizeHandleCoords.Y -= 2 * (resizeHandleCoords.Y - rectCenterY);
|
||||
// scale again with opposing handle and mirrored coordinates
|
||||
resizeHandlePosition = (resizeHandlePosition + 4) % 8;
|
||||
scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords);
|
||||
} else {
|
||||
scale(ref originalRectangle, resizeHandlePosition, resizeHandleCoords);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calculates target size of a given rectangle scaled by dragging one of its handles (corners)
|
||||
/// </summary>
|
||||
/// <param name="originalRectangle">bounds of the current rectangle, scaled values will be written to this reference</param>
|
||||
/// <param name="resizeHandlePosition">position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT</param>
|
||||
/// <param name="resizeHandleCoords">coordinates of the used handle/gripper</param>
|
||||
private static void scale(ref RectangleF originalRectangle, int resizeHandlePosition, PointF resizeHandleCoords) {
|
||||
switch(resizeHandlePosition) {
|
||||
|
||||
case Gripper.POSITION_TOP_LEFT:
|
||||
originalRectangle.Width = originalRectangle.Left + originalRectangle.Width - resizeHandleCoords.X;
|
||||
originalRectangle.Height = originalRectangle.Top + originalRectangle.Height - resizeHandleCoords.Y;
|
||||
originalRectangle.X = resizeHandleCoords.X;
|
||||
originalRectangle.Y = resizeHandleCoords.Y;
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_TOP_CENTER:
|
||||
originalRectangle.Height = originalRectangle.Top + originalRectangle.Height - resizeHandleCoords.Y;
|
||||
originalRectangle.Y = resizeHandleCoords.Y;
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_TOP_RIGHT:
|
||||
originalRectangle.Width = resizeHandleCoords.X - originalRectangle.Left;
|
||||
originalRectangle.Height = originalRectangle.Top + originalRectangle.Height - resizeHandleCoords.Y;
|
||||
originalRectangle.Y = resizeHandleCoords.Y;
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_MIDDLE_LEFT:
|
||||
originalRectangle.Width = originalRectangle.Left + originalRectangle.Width - resizeHandleCoords.X;
|
||||
originalRectangle.X = resizeHandleCoords.X;
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_MIDDLE_RIGHT:
|
||||
originalRectangle.Width = resizeHandleCoords.X - originalRectangle.Left;
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_BOTTOM_LEFT:
|
||||
originalRectangle.Width = originalRectangle.Left + originalRectangle.Width - resizeHandleCoords.X;
|
||||
originalRectangle.Height = resizeHandleCoords.Y - originalRectangle.Top;
|
||||
originalRectangle.X = resizeHandleCoords.X;
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_BOTTOM_CENTER:
|
||||
originalRectangle.Height = resizeHandleCoords.Y - originalRectangle.Top;
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_BOTTOM_RIGHT:
|
||||
originalRectangle.Width = resizeHandleCoords.X - originalRectangle.Left;
|
||||
originalRectangle.Height = resizeHandleCoords.Y - originalRectangle.Top;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException("Position cannot be handled: "+resizeHandlePosition);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adjusts resizeHandleCoords so that aspect ratio is kept after resizing a given rectangle with provided arguments
|
||||
/// </summary>
|
||||
/// <param name="originalRectangle">bounds of the current rectangle</param>
|
||||
/// <param name="resizeHandlePosition">position of the handle/gripper being used for resized, see constants in Gripper.cs, e.g. Gripper.POSITION_TOP_LEFT</param>
|
||||
/// <param name="resizeHandleCoords">coordinates of the used handle/gripper, adjusted coordinates will be written to this reference</param>
|
||||
private static void adjustCoordsForRationalScale(RectangleF originalRectangle, int resizeHandlePosition, ref PointF resizeHandleCoords) {
|
||||
float originalRatio = originalRectangle.Width / originalRectangle.Height;
|
||||
float newWidth, newHeight, newRatio;
|
||||
switch(resizeHandlePosition) {
|
||||
|
||||
case Gripper.POSITION_TOP_LEFT:
|
||||
newWidth = originalRectangle.Right - resizeHandleCoords.X;
|
||||
newHeight = originalRectangle.Bottom - resizeHandleCoords.Y;
|
||||
newRatio = newWidth / newHeight;
|
||||
if(newRatio > originalRatio) { // FIXME
|
||||
resizeHandleCoords.X = originalRectangle.Right - newHeight * originalRatio;
|
||||
} else if(newRatio < originalRatio) {
|
||||
resizeHandleCoords.Y = originalRectangle.Bottom - newWidth / originalRatio;
|
||||
}
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_TOP_RIGHT:
|
||||
newWidth = resizeHandleCoords.X - originalRectangle.Left;
|
||||
newHeight = originalRectangle.Bottom - resizeHandleCoords.Y;
|
||||
newRatio = newWidth / newHeight;
|
||||
if(newRatio > originalRatio) { // FIXME
|
||||
resizeHandleCoords.X = newHeight * originalRatio + originalRectangle.Left;
|
||||
} else if(newRatio < originalRatio) {
|
||||
resizeHandleCoords.Y = originalRectangle.Bottom - newWidth / originalRatio;
|
||||
}
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_BOTTOM_LEFT:
|
||||
newWidth = originalRectangle.Right - resizeHandleCoords.X;
|
||||
newHeight = resizeHandleCoords.Y - originalRectangle.Top;
|
||||
newRatio = newWidth / newHeight;
|
||||
if(newRatio > originalRatio) {
|
||||
resizeHandleCoords.X = originalRectangle.Right - newHeight * originalRatio;
|
||||
} else if(newRatio < originalRatio) {
|
||||
resizeHandleCoords.Y = newWidth / originalRatio + originalRectangle.Top;
|
||||
}
|
||||
break;
|
||||
|
||||
case Gripper.POSITION_BOTTOM_RIGHT:
|
||||
newWidth = resizeHandleCoords.X - originalRectangle.Left;
|
||||
newHeight = resizeHandleCoords.Y - originalRectangle.Top;
|
||||
newRatio = newWidth / newHeight;
|
||||
if(newRatio > originalRatio) {
|
||||
resizeHandleCoords.X = newHeight * originalRatio + originalRectangle.Left;
|
||||
} else if(newRatio < originalRatio) {
|
||||
resizeHandleCoords.Y = newWidth / originalRatio + originalRectangle.Top;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Scale(Rectangle boundsBeforeResize, int cursorX, int cursorY, ref RectangleF boundsAfterResize) {
|
||||
Scale(boundsBeforeResize, cursorX, cursorY, ref boundsAfterResize, null);
|
||||
}
|
||||
|
||||
public static void Scale(Rectangle boundsBeforeResize, int cursorX, int cursorY, ref RectangleF boundsAfterResize, IDoubleProcessor angleRoundBehavior) {
|
||||
|
||||
Scale(boundsBeforeResize, Gripper.POSITION_TOP_LEFT, cursorX, cursorY, ref boundsAfterResize, angleRoundBehavior);
|
||||
}
|
||||
|
||||
public static void Scale(Rectangle boundsBeforeResize, int gripperPosition, int cursorX, int cursorY, ref RectangleF boundsAfterResize, IDoubleProcessor angleRoundBehavior) {
|
||||
|
||||
ScaleHelper.ScaleOptions opts = ScaleHelper.GetScaleOptions();
|
||||
|
||||
bool rationalScale = (opts & ScaleHelper.ScaleOptions.Rational) == ScaleHelper.ScaleOptions.Rational;
|
||||
bool centeredScale = (opts & ScaleHelper.ScaleOptions.Centered) == ScaleHelper.ScaleOptions.Centered;
|
||||
|
||||
if(rationalScale) {
|
||||
double angle = GeometryHelper.Angle2D(boundsBeforeResize.X, boundsBeforeResize.Y, cursorX, cursorY);
|
||||
|
||||
if(angleRoundBehavior != null) {
|
||||
angle = angleRoundBehavior.Process(angle);
|
||||
}
|
||||
|
||||
int dist = GeometryHelper.Distance2D(boundsBeforeResize.X, boundsBeforeResize.Y, cursorX, cursorY);
|
||||
|
||||
boundsAfterResize.Width = (int)Math.Round(dist * Math.Cos(angle / 180 * Math.PI));
|
||||
boundsAfterResize.Height = (int)Math.Round(dist * Math.Sin(angle / 180 * Math.PI));
|
||||
}
|
||||
|
||||
if(centeredScale) {
|
||||
float wdiff = boundsAfterResize.Width - boundsBeforeResize.Width;
|
||||
float hdiff = boundsAfterResize.Height - boundsBeforeResize.Height;
|
||||
boundsAfterResize.Width += wdiff;
|
||||
boundsAfterResize.Height += hdiff;
|
||||
boundsAfterResize.X -= wdiff;
|
||||
boundsAfterResize.Y -= hdiff;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// <returns>the current ScaleOptions depending on modifier keys held down</returns>
|
||||
public static ScaleHelper.ScaleOptions GetScaleOptions() {
|
||||
bool anchorAtCenter = (Control.ModifierKeys & Keys.Control) != 0;
|
||||
bool maintainAspectRatio = ((Control.ModifierKeys & Keys.Shift) != 0);
|
||||
ScaleHelper.ScaleOptions opts = 0x0;
|
||||
if(anchorAtCenter) opts |= ScaleHelper.ScaleOptions.Centered;
|
||||
if(maintainAspectRatio) opts |= ScaleHelper.ScaleOptions.Rational;
|
||||
return opts;
|
||||
}
|
||||
|
||||
public interface IDoubleProcessor {
|
||||
double Process(double d);
|
||||
}
|
||||
|
||||
public class ShapeAngleRoundBehavior : IDoubleProcessor {
|
||||
public static ShapeAngleRoundBehavior Instance = new ShapeAngleRoundBehavior();
|
||||
private ShapeAngleRoundBehavior() {}
|
||||
public double Process(double angle) {
|
||||
return Math.Round((angle+45)/90)*90 - 45;
|
||||
}
|
||||
}
|
||||
public class LineAngleRoundBehavior : IDoubleProcessor {
|
||||
public static LineAngleRoundBehavior Instance = new LineAngleRoundBehavior();
|
||||
private LineAngleRoundBehavior() {}
|
||||
public double Process(double angle) {
|
||||
return Math.Round(angle/15)*15;
|
||||
}
|
||||
}
|
||||
public class FixedAngleRoundBehavior : IDoubleProcessor {
|
||||
private double fixedAngle;
|
||||
public FixedAngleRoundBehavior(double fixedAngle) {
|
||||
this.fixedAngle = fixedAngle;
|
||||
}
|
||||
public double Process(double angle) {
|
||||
return this.fixedAngle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*public static int FindGripperPostition(float anchorX, float anchorY, float gripperX, float gripperY) {
|
||||
if(gripperY > anchorY) {
|
||||
if(gripperX > anchorY) return Gripper.POSITION_BOTTOM_RIGHT;
|
||||
else return Gripper.POSITION_BOTTOM_LEFT;
|
||||
} else {
|
||||
if(gripperX > anchorY) return Gripper.POSITION_TOP_RIGHT;
|
||||
else return Gripper.POSITION_TOP_LEFT;
|
||||
}
|
||||
}*/
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue