diff --git a/Greenshot/Drawing/FreehandContainer.cs b/Greenshot/Drawing/FreehandContainer.cs
index cc574076b..ccff8a690 100644
--- a/Greenshot/Drawing/FreehandContainer.cs
+++ b/Greenshot/Drawing/FreehandContainer.cs
@@ -36,7 +36,10 @@ namespace Greenshot.Drawing {
public class FreehandContainer : DrawableContainer {
private static readonly float [] PointOffset = {0.5f, 0.25f, 0.75f};
- [NonSerialized]
+ [NonSerialized]
+ private readonly object _freehandPathLock = new object();
+
+ [NonSerialized]
private GraphicsPath freehandPath = new GraphicsPath();
private Rectangle myBounds = Rectangle.Empty;
private Point lastMouse = Point.Empty;
@@ -104,15 +107,21 @@ namespace Greenshot.Drawing {
if (GeometryHelper.Distance2D(previousPoint.X, previousPoint.Y, mouseX, mouseY) >= 2*EditorConfig.FreehandSensitivity) {
capturePoints.Add(new Point(mouseX, mouseY));
}
- if (GeometryHelper.Distance2D(lastMouse.X, lastMouse.Y, mouseX, mouseY) >= EditorConfig.FreehandSensitivity) {
- //path.AddCurve(new Point[]{lastMouse, new Point(mouseX, mouseY)});
- freehandPath.AddLine(lastMouse, new Point(mouseX, mouseY));
- lastMouse = new Point(mouseX, mouseY);
- // Only re-calculate the bounds & redraw when we added something to the path
- myBounds = Rectangle.Round(freehandPath.GetBounds());
- Invalidate();
- }
- return true;
+ if (GeometryHelper.Distance2D(lastMouse.X, lastMouse.Y, mouseX, mouseY) < EditorConfig.FreehandSensitivity)
+ {
+ return true;
+ }
+ //path.AddCurve(new Point[]{lastMouse, new Point(mouseX, mouseY)});
+ lastMouse = new Point(mouseX, mouseY);
+ lock (_freehandPathLock)
+ {
+ freehandPath.AddLine(lastMouse, new Point(mouseX, mouseY));
+ // Only re-calculate the bounds & redraw when we added something to the path
+ myBounds = Rectangle.Round(freehandPath.GetBounds());
+ }
+
+ Invalidate();
+ return true;
}
///
@@ -130,25 +139,34 @@ namespace Greenshot.Drawing {
/// Here we recalculate the freehand path by smoothing out the lines with Beziers.
///
private void RecalculatePath() {
- isRecalculated = true;
- // Dispose the previous path, if we have one
- freehandPath?.Dispose();
- freehandPath = new GraphicsPath();
+ lock (_freehandPathLock)
+ {
+ isRecalculated = true;
+ // Dispose the previous path, if we have one
+ freehandPath?.Dispose();
+ freehandPath = new GraphicsPath();
- // Here we can put some cleanup... like losing all the uninteresting points.
- if (capturePoints.Count >= 3) {
- int index = 0;
- while ((capturePoints.Count - 1) % 3 != 0) {
- // duplicate points, first at 50% than 25% than 75%
- capturePoints.Insert((int)(capturePoints.Count*PointOffset[index]), capturePoints[(int)(capturePoints.Count*PointOffset[index++])]);
- }
- freehandPath.AddBeziers(capturePoints.ToArray());
- } else if (capturePoints.Count == 2) {
- freehandPath.AddLine(capturePoints[0], capturePoints[1]);
- }
+ // Here we can put some cleanup... like losing all the uninteresting points.
+ if (capturePoints.Count >= 3)
+ {
+ int index = 0;
+ while ((capturePoints.Count - 1) % 3 != 0)
+ {
+ // duplicate points, first at 50% than 25% than 75%
+ capturePoints.Insert((int)(capturePoints.Count * PointOffset[index]), capturePoints[(int)(capturePoints.Count * PointOffset[index++])]);
+ }
+ freehandPath.AddBeziers(capturePoints.ToArray());
+ }
+ else if (capturePoints.Count == 2)
+ {
+ freehandPath.AddLine(capturePoints[0], capturePoints[1]);
+ }
+
+ // Recalculate the bounds
+ myBounds = Rectangle.Round(freehandPath.GetBounds());
+
+ }
- // Recalculate the bounds
- myBounds = Rectangle.Round(freehandPath.GetBounds());
}
///
@@ -157,41 +175,48 @@ namespace Greenshot.Drawing {
///
///
public override void Draw(Graphics graphics, RenderMode renderMode) {
- graphics.SmoothingMode = SmoothingMode.HighQuality;
+ graphics.SmoothingMode = SmoothingMode.HighQuality;
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphics.CompositingQuality = CompositingQuality.HighQuality;
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
Color lineColor = GetFieldValueAsColor(FieldType.LINE_COLOR);
- using (Pen pen = new Pen(lineColor)) {
+ using (var pen = new Pen(lineColor)) {
pen.Width = lineThickness;
- if (pen.Width > 0) {
- // Make sure the lines are nicely rounded
- pen.EndCap = LineCap.Round;
- pen.StartCap = LineCap.Round;
- pen.LineJoin = LineJoin.Round;
+ if (!(pen.Width > 0))
+ {
+ return;
+ }
+ // Make sure the lines are nicely rounded
+ pen.EndCap = LineCap.Round;
+ pen.StartCap = LineCap.Round;
+ pen.LineJoin = LineJoin.Round;
+ // Move to where we need to draw
+ graphics.TranslateTransform(Left, Top);
+ lock (_freehandPathLock)
+ {
+ if (isRecalculated && Selected && renderMode == RenderMode.EDIT)
+ {
+ DrawSelectionBorder(graphics, pen, freehandPath);
+ }
+ graphics.DrawPath(pen, freehandPath);
+ }
- // Move to where we need to draw
- graphics.TranslateTransform(Left,Top);
- if (isRecalculated && Selected && renderMode == RenderMode.EDIT) {
- DrawSelectionBorder(graphics, pen);
- }
- graphics.DrawPath(pen, freehandPath);
- // Move back, otherwise everything is shifted
- graphics.TranslateTransform(-Left,-Top);
- }
+ // Move back, otherwise everything is shifted
+ graphics.TranslateTransform(-Left,-Top);
}
}
-
- ///
- /// Draw a selectionborder around the freehand path
- ///
- ///
- ///
- protected void DrawSelectionBorder(Graphics graphics, Pen linePen) {
- using (Pen selectionPen = (Pen) linePen.Clone()) {
- using (GraphicsPath selectionPath = (GraphicsPath) freehandPath.Clone()) {
+
+ ///
+ /// Draw a selectionborder around the freehand path
+ ///
+ /// Graphics
+ /// Pen
+ /// GraphicsPath
+ protected static void DrawSelectionBorder(Graphics graphics, Pen linePen, GraphicsPath path) {
+ using (var selectionPen = (Pen) linePen.Clone()) {
+ using (var selectionPath = (GraphicsPath)path.Clone()) {
selectionPen.Width += 5;
selectionPen.Color = Color.FromArgb(120, Color.LightSeaGreen);
graphics.DrawPath(selectionPen, selectionPath);
@@ -218,42 +243,42 @@ namespace Greenshot.Drawing {
}
}
- ///
- /// FreehandContainer are regarded equal if they are of the same type and their paths are equal.
- ///
- ///
- ///
- public override bool Equals(object obj) {
+ ///
+ /// FreehandContainer are regarded equal if they are of the same type and their paths are equal.
+ ///
+ /// object
+ /// bool
+ public override bool Equals(object obj) {
bool ret = false;
- if(obj != null && GetType() == obj.GetType()) {
- FreehandContainer other = obj as FreehandContainer;
- if(other != null && freehandPath.Equals(other.freehandPath)) {
- ret = true;
- }
- }
- return ret;
+ if (obj == null || GetType() != obj.GetType())
+ {
+ return false;
+ }
+ var other = obj as FreehandContainer;
+ if (other != null && Equals(freehandPath, other.freehandPath)) {
+ ret = true;
+ }
+ return ret;
}
public override int GetHashCode() {
- if (freehandPath == null)
+ lock (_freehandPathLock)
{
- return 0;
+ return freehandPath?.GetHashCode() ?? 0;
}
- return freehandPath.GetHashCode();
}
public override bool ClickableAt(int x, int y) {
bool returnValue = base.ClickableAt(x, y);
if (returnValue) {
- if (freehandPath == null)
- {
- return false;
- }
int lineThickness = GetFieldValueAsInt(FieldType.LINE_THICKNESS);
using (var pen = new Pen(Color.White)) {
pen.Width = lineThickness + 10;
- returnValue = freehandPath.IsOutlineVisible(x-Left,y-Top, pen);
- }
+ lock (_freehandPathLock)
+ {
+ returnValue = freehandPath.IsOutlineVisible(x - Left, y - Top, pen);
+ }
+ }
}
return returnValue;
}