EraserTool.cs 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. using PaintDotNet.Measurement.HistoryMementos;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Drawing;
  5. using System.Drawing.Drawing2D;
  6. using System.Windows.Forms;
  7. namespace PaintDotNet.Measurement.Tools
  8. {
  9. public class EraserTool : Tool
  10. {
  11. private bool mouseDown;
  12. private MouseButtons mouseButton;
  13. private List<Rectangle> savedRects;
  14. private Point lastMouseXY;
  15. private RenderArgs renderArgs;
  16. private BitmapLayer bitmapLayer;
  17. private Cursor cursorMouseDown;
  18. private Cursor cursorMouseUp;
  19. private BrushPreviewRenderer previewRenderer;
  20. protected override void OnMouseEnter()
  21. {
  22. this.previewRenderer.Visible = true;
  23. base.OnMouseEnter();
  24. }
  25. protected override void OnMouseLeave()
  26. {
  27. this.previewRenderer.Visible = false;
  28. base.OnMouseLeave();
  29. }
  30. protected override void OnActivate()
  31. {
  32. base.OnActivate();
  33. // cursor-transitions
  34. this.cursorMouseUp = new Cursor(PdnResources.GetResourceStream("Cursors.EraserToolCursor.cur"));
  35. this.cursorMouseDown = new Cursor(PdnResources.GetResourceStream("Cursors.EraserToolCursorMouseDown.cur"));
  36. this.Cursor = cursorMouseUp;
  37. this.savedRects = new List<Rectangle>();
  38. if (ActiveLayer != null)
  39. {
  40. bitmapLayer = (BitmapLayer)ActiveLayer;
  41. renderArgs = new RenderArgs(bitmapLayer.Surface);
  42. }
  43. else
  44. {
  45. bitmapLayer = null;
  46. renderArgs = null;
  47. }
  48. this.previewRenderer = new BrushPreviewRenderer(this.RendererList);
  49. this.RendererList.Add(this.previewRenderer, false);
  50. }
  51. protected override void OnDeactivate()
  52. {
  53. base.OnDeactivate();
  54. if (cursorMouseUp != null)
  55. {
  56. cursorMouseUp.Dispose();
  57. cursorMouseUp = null;
  58. }
  59. if (cursorMouseDown != null)
  60. {
  61. cursorMouseDown.Dispose();
  62. cursorMouseDown = null;
  63. }
  64. if (mouseDown)
  65. {
  66. OnMouseUp(new MouseEventArgs(mouseButton, 0, lastMouseXY.X, lastMouseXY.Y, 0));
  67. }
  68. this.RendererList.Remove(this.previewRenderer);
  69. this.previewRenderer.Dispose();
  70. this.previewRenderer = null;
  71. this.savedRects.Clear();
  72. if (renderArgs != null)
  73. {
  74. renderArgs.Dispose();
  75. renderArgs = null;
  76. }
  77. bitmapLayer = null;
  78. }
  79. protected override void OnMouseDown(MouseEventArgs e)
  80. {
  81. base.OnMouseDown(e);
  82. this.Cursor = this.cursorMouseDown;
  83. if (((e.Button & MouseButtons.Left) == MouseButtons.Left) ||
  84. ((e.Button & MouseButtons.Right) == MouseButtons.Right))
  85. {
  86. this.previewRenderer.Visible = false;
  87. mouseDown = true;
  88. mouseButton = e.Button;
  89. lastMouseXY.X = e.X;
  90. lastMouseXY.Y = e.Y;
  91. PdnRegion clipRegion = Selection.CreateRegion();
  92. renderArgs.Graphics.SetClip(clipRegion.GetRegionReadOnly(), CombineMode.Replace);
  93. clipRegion.Dispose();
  94. OnMouseMove(e);
  95. }
  96. }
  97. protected override void OnMouseUp(MouseEventArgs e)
  98. {
  99. base.OnMouseUp(e);
  100. Cursor = cursorMouseUp;
  101. if (mouseDown)
  102. {
  103. OnMouseMove(e);
  104. this.previewRenderer.Visible = true;
  105. mouseDown = false;
  106. if (this.savedRects.Count > 0)
  107. {
  108. Rectangle[] savedScans = this.savedRects.ToArray();
  109. PdnRegion saveMeRegion = Utility.RectanglesToRegion(savedScans);
  110. HistoryMemento ha = new BitmapHistoryMemento(Name, Image, DocumentWorkspace,
  111. ActiveLayerIndex, saveMeRegion, this.ScratchSurface);
  112. //HistoryStack.PushNewMemento(ha);
  113. saveMeRegion.Dispose();
  114. this.savedRects.Clear();
  115. ClearSavedMemory();
  116. }
  117. }
  118. }
  119. protected override void OnMouseMove(MouseEventArgs e)
  120. {
  121. base.OnMouseMove(e);
  122. if (mouseDown && ((e.Button & mouseButton) != MouseButtons.None))
  123. {
  124. int alpha;
  125. if (e.Button == MouseButtons.Left)
  126. {
  127. alpha = AppEnvironment.GetPrimaryColorA();//.A;
  128. }
  129. else
  130. {
  131. alpha = AppEnvironment.GetSecondaryColorA();//.A;
  132. }
  133. Pen pen = AppEnvironment.PenInfo().CreatePen(AppEnvironment.BrushInfo(),
  134. Color.FromArgb(alpha, 0, 0, 0), Color.FromArgb(alpha, 0, 0, 0));
  135. Point a = lastMouseXY;
  136. Point b = new Point(e.X, e.Y);
  137. Rectangle saveRect = Utility.PointsToRectangle(a, b);
  138. saveRect.Inflate((int)Math.Ceiling(pen.Width), (int)Math.Ceiling(pen.Width));
  139. if (renderArgs.Graphics.SmoothingMode == SmoothingMode.AntiAlias)
  140. {
  141. saveRect.Inflate(1, 1);
  142. }
  143. saveRect.Intersect(ActiveLayer.Bounds);
  144. // drawing outside of the canvas is a no-op, so don't do anything in that case!
  145. // also make sure we're within the clip region
  146. if (saveRect.Width > 0 && saveRect.Height > 0 && renderArgs.Graphics.IsVisible(saveRect))
  147. {
  148. SaveRegion(null, saveRect);
  149. this.savedRects.Add(saveRect);
  150. if (AppEnvironment.AntiAliasing())
  151. {
  152. renderArgs.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
  153. }
  154. else
  155. {
  156. renderArgs.Graphics.SmoothingMode = SmoothingMode.None;
  157. }
  158. new UnaryPixelOps.InvertWithAlpha().Apply(renderArgs.Surface, saveRect);
  159. renderArgs.Graphics.CompositingMode = CompositingMode.SourceOver;
  160. if (pen.Width > 1)
  161. {
  162. renderArgs.Graphics.PixelOffsetMode = PixelOffsetMode.Half;
  163. }
  164. else
  165. {
  166. renderArgs.Graphics.PixelOffsetMode = PixelOffsetMode.None;
  167. }
  168. pen.EndCap = LineCap.Round;
  169. pen.StartCap = LineCap.Round;
  170. renderArgs.Graphics.DrawLine(pen, a, b);
  171. renderArgs.Graphics.FillEllipse(pen.Brush, a.X - pen.Width / 2.0f, a.Y - pen.Width / 2.0f, pen.Width, pen.Width);
  172. new UnaryPixelOps.InvertWithAlpha().Apply(renderArgs.Surface, saveRect);
  173. new BinaryPixelOps.SetColorChannels().Apply(renderArgs.Surface, saveRect.Location,
  174. ScratchSurface, saveRect.Location, saveRect.Size);
  175. bitmapLayer.Invalidate(saveRect);
  176. Update();
  177. }
  178. lastMouseXY = b;
  179. pen.Dispose();
  180. }
  181. else
  182. {
  183. this.previewRenderer.BrushLocation = new Point(e.X, e.Y);
  184. this.previewRenderer.BrushSize = AppEnvironment.PenInfo().Width / 2.0f;
  185. }
  186. }
  187. public EraserTool(IDocumentWorkspace documentWorkspace)
  188. : base(documentWorkspace,
  189. PdnResources.GetImageResource("Icons.EraserToolIcon.png"),
  190. PdnResources.GetString("EraserTool.Name"),
  191. PdnResources.GetString("EraserTool.HelpText"), //"Click and drag to erase a portion of the image",
  192. 'e',
  193. false,
  194. ToolBarConfigItems.Pen | ToolBarConfigItems.Antialiasing)
  195. {
  196. }
  197. }
  198. }