RecoloringTool.cs :  » GUI » Paint.net » PaintDotNet » Tools » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » GUI » Paint.net 
Paint.net » PaintDotNet » Tools » RecoloringTool.cs
/////////////////////////////////////////////////////////////////////////////////
// Paint.NET                                                                   //
// Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors.     //
// Portions Copyright (C) Microsoft Corporation. All Rights Reserved.          //
// See src/Resources/Files/License.txt for full licensing and attribution      //
// details.                                                                    //
// .                                                                           //
/////////////////////////////////////////////////////////////////////////////////

using PaintDotNet.HistoryMementos;
using System;
using System.Collections;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace PaintDotNet.Tools{
    internal class RecolorTool 
        : Tool
    {
        private bool mouseDown;

        private Point lastMouseXY;
        private MouseButtons mouseButton;
        private RenderArgs renderArgs;
        private BitmapLayer bitmapLayer;
        private ArrayList savedSurfaces;
        private BrushPreviewRenderer previewRenderer;

        private float penWidth;
        private int ceilingPenWidth;
        private int halfPenWidth;
        private ColorBgra colorToReplace;
        private ColorBgra colorReplacing;
        private Cursor cursorMouseDown;
        private Cursor cursorMouseUp;
        private Cursor cursorMouseDownPickColor;
        private Cursor cursorMouseDownAdjustColor;

        // private ColorBgra replacementDiff;
        private static ColorBgra colorToleranceBasis = ColorBgra.FromBgra(0x20, 0x20, 0x20, 0x00);
        private PdnRegion clipRegion;
        private UserBlendOps.NormalBlendOp blendOp = new UserBlendOps.NormalBlendOp();
        private bool hasDrawn;
        private Keys modifierDown;

        // AA stuff
        private BitVector2D isPointAlreadyAA;
        private Surface aaPoints;

        public ColorBgra AAPoints(int x, int y)
        {
            return aaPoints[x, y];
        }

        public void AAPointsAdd(int x, int y, ColorBgra color)
        {
            aaPoints[x, y] = color;
            isPointAlreadyAA[x, y] = true;
        }

        public void AAPointsRemove(int x, int y)
        {
            isPointAlreadyAA[x, y] = false;
        }

        private bool IsPointAlreadyAntiAliased(int x, int y)
        {
            return isPointAlreadyAA[x, y];
        }

        private bool IsPointAlreadyAntiAliased(Point pt)
        {
            return IsPointAlreadyAntiAliased(pt.X, pt.Y);
        }

        // RenderArgs specifically for a brush mask
        private RenderArgs brushRenderArgs;

        private int myTolerance;

        private bool IsColorInTolerance(ColorBgra colorA, ColorBgra colorB)
        {
            return Utility.ColorDifference(colorA, colorB) <= myTolerance;
        }

        private void RestrictTolerance()
        {
            int difference = Utility.ColorDifference(colorReplacing, colorToReplace);

            if (myTolerance > difference)
            {
                myTolerance = difference;
            }
        }

        protected override void OnMouseEnter()
        {
            this.previewRenderer.Visible = true;
            base.OnMouseEnter();
        }

        protected override void OnMouseLeave()
        {
            this.previewRenderer.Visible = false;
            base.OnMouseLeave();
        }

        protected override void OnActivate()
        {
            base.OnActivate();

            // initialize any state information you need
            cursorMouseUp = new Cursor(PdnResources.GetResourceStream("Cursors.RecoloringToolCursor.cur"));
            cursorMouseDown = new Cursor(PdnResources.GetResourceStream("Cursors.GenericToolCursorMouseDown.cur"));
            cursorMouseDownPickColor = new Cursor(PdnResources.GetResourceStream("Cursors.RecoloringToolCursorPickColor.cur"));
            cursorMouseDownAdjustColor = new Cursor(PdnResources.GetResourceStream("Cursors.RecoloringToolCursorAdjustColor.cur"));

            this.previewRenderer = new BrushPreviewRenderer(this.RendererList);
            this.RendererList.Add(this.previewRenderer, false);

            Cursor = cursorMouseUp;
            mouseDown = false;

            // fetch colors from workspace palette
            this.colorToReplace = this.AppEnvironment.PrimaryColor;
            this.colorReplacing = this.AppEnvironment.SecondaryColor;

            this.aaPoints = this.ScratchSurface;
            this.isPointAlreadyAA = new BitVector2D(aaPoints.Width, aaPoints.Height);

            if (savedSurfaces != null)
            {
                foreach (PlacedSurface ps in savedSurfaces)
                {
                    ps.Dispose();
                }
            }

            savedSurfaces = new ArrayList();

            if (ActiveLayer != null)
            {
                bitmapLayer = (BitmapLayer)ActiveLayer;
                renderArgs = new RenderArgs(bitmapLayer.Surface);
            }
            else
            {
                bitmapLayer = null;
                renderArgs = null;
            }
        }

        protected override void OnDeactivate()
        {
            base.OnDeactivate();

            if (mouseDown)
            {
                OnMouseUp(new MouseEventArgs(mouseButton, 0, lastMouseXY.X, lastMouseXY.Y, 0));
            }

            this.RendererList.Remove(this.previewRenderer);
            this.previewRenderer.Dispose();
            this.previewRenderer = null;

            if (savedSurfaces != null)
            {
                if (savedSurfaces != null)
                {
                    foreach (PlacedSurface ps in savedSurfaces)
                    {
                        ps.Dispose();
                    }
                }

                savedSurfaces.Clear();
                savedSurfaces = null;
            }

            renderArgs.Dispose();;
            renderArgs = null;

            aaPoints = null;
            renderArgs = null;
            bitmapLayer = null;

            if (clipRegion != null)
            {
                clipRegion.Dispose();
                clipRegion = null;
            }


            if (cursorMouseUp != null)
            {
                cursorMouseUp.Dispose();
                cursorMouseUp = null;
            }

            if (cursorMouseDown != null)
            {
                cursorMouseDown.Dispose();
                cursorMouseDown = null;
            }

            if (cursorMouseDownPickColor != null)
            {
                cursorMouseDownPickColor.Dispose();
                cursorMouseDownPickColor = null;
            }

            if (cursorMouseDownAdjustColor != null)
            {
                cursorMouseDownAdjustColor.Dispose();
                cursorMouseDownAdjustColor = null;
            }
        }

        private ColorBgra LiftColor(int x, int y)
        {
            return ((BitmapLayer)ActiveLayer).Surface[x, y];
        }

        /// <summary>
        /// Picks up the color under the mouse and assigns to the forecolor (or backcolor).
        /// If assigning to the forecolor, the backcolor will be adjusted respective to the
        /// difference of the old forecolor versus the new forecolor.
        /// </summary>
        /// <param name="e"></param>
        private void AdjustDrawingColor(MouseEventArgs e)
        {
            ColorBgra oldColor;

            if (BtnDownMouseLeft(e))
            {
                oldColor = this.AppEnvironment.PrimaryColor;
                PickColor(e);

                this.AppEnvironment.SecondaryColor = AdjustColorDifference(oldColor, 
                    this.AppEnvironment.PrimaryColor, this.AppEnvironment.SecondaryColor);
            }

            if (BtnDownMouseRight(e))
            {
                oldColor = this.AppEnvironment.SecondaryColor;
                PickColor(e);

                this.AppEnvironment.PrimaryColor = AdjustColorDifference(oldColor, 
                    this.AppEnvironment.SecondaryColor, this.AppEnvironment.PrimaryColor);
            }
        }

        private byte AdjustColorByte(byte oldByte, byte newByte, byte basisByte)
        {
            if (oldByte > newByte)
            {
                return Utility.ClampToByte(basisByte - (oldByte - newByte));
            }
            else
            {
                return Utility.ClampToByte(basisByte + (newByte - oldByte));
            }
        }

        /// <summary>
        /// Returns a ColorBgra shift by the difference between oldcolor and newcolor but using 
        /// basisColor as the basis.
        /// </summary>
        /// <param name="oldcolor"></param>
        /// <param name="newcolor"></param>
        /// <param name="shiftColor"></param>
        /// <returns></returns>
        private ColorBgra AdjustColorDifference(ColorBgra oldColor, ColorBgra newColor, ColorBgra basisColor) 
        {
            ColorBgra returnColor;

            // eliminate testing for the "equal to" case
            returnColor = basisColor;

            returnColor.B = AdjustColorByte(oldColor.B, newColor.B, basisColor.B);
            returnColor.G = AdjustColorByte(oldColor.G, newColor.G, basisColor.G);
            returnColor.R = AdjustColorByte(oldColor.R, newColor.R, basisColor.R);

            return returnColor;
        }

        private void PickColor(MouseEventArgs e)
        {
            if (!DocumentWorkspace.Document.Bounds.Contains(e.X, e.Y))
            {
                return;
            }

            // if we managed to get here without any mouse buttons down
            // we return promptly.
            if (BtnDownMouseLeft(e) || BtnDownMouseRight(e))
            {
                // since the above statement exits if one or the other
                if (BtnDownMouseLeft(e))
                {
                    colorReplacing = LiftColor(e.X, e.Y);
                    colorReplacing.A = this.AppEnvironment.PrimaryColor.A;
                    this.AppEnvironment.PrimaryColor = colorReplacing;
                }
                else
                {
                    colorToReplace = LiftColor(e.X, e.Y);
                    colorToReplace.A = this.AppEnvironment.SecondaryColor.A;
                    this.AppEnvironment.SecondaryColor = colorToReplace;
                }
            }
            else
            {
                return;
            }

            // before assigned the newly lifted color, we preserve the
            // alpha from the user's selected color.
        }

        private RenderArgs RenderCircleBrush()
        {
            // create pen mask surface
            Surface brushSurface = new Surface(ceilingPenWidth, ceilingPenWidth);
            brushSurface.Clear((ColorBgra)0);
            RenderArgs brush = new RenderArgs(brushSurface);

            if (AppEnvironment.AntiAliasing)
            {
                brush.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            }
            else
            {
                brush.Graphics.SmoothingMode = SmoothingMode.None;
            }

            if (AppEnvironment.AntiAliasing)
            {
                if (penWidth > 2)
                {
                    penWidth = penWidth - 1.0f;
                }
                else
                {
                    penWidth = penWidth / 2;
                }
            }
            else
            {
                if (penWidth <= 1.0f)
                {
                    brush.Surface[1, 1] = ColorBgra.Black;
                }
                else
                {
                    penWidth = (float)Math.Round(penWidth + 1.0f);
                }
            }

            using (Brush testBrush = new SolidBrush(System.Drawing.Color.Black))
            {
                brush.Graphics.FillEllipse(testBrush, 0.0f, 0.0f, penWidth, penWidth);
            }

            return brush;
        }

        private unsafe void DrawOverPoints(Point start, Point finish, ColorBgra colorToReplaceWith, ColorBgra colorBeingReplaced)
        {
            ColorBgra colorAdjusted = ColorBgra.FromColor(Color.Empty);
            byte dstAlpha;
            ColorBgra colorLifted;
            Rectangle[] rectSelRegions;
            Rectangle rectBrushArea;
            Rectangle rectBrushRelativeOffset = new Rectangle(0, 0, 0, 0);
            
            // special condition for a canvas with no active selection
            // create an array of rectangles with a single rectangle 
            // specifying the size of the canvas
            if (Selection.IsEmpty)
            {
                rectSelRegions = new Rectangle[] { DocumentWorkspace.Document.Bounds };
            }
            else
            {
                rectSelRegions = clipRegion.GetRegionScansReadOnlyInt();
            }

            // code ripped off from clone stamp tool
            Point direction = new Point(finish.X - start.X, finish.Y - start.Y);
            float length = Utility.Magnitude(direction);
            float bw = AppEnvironment.PenInfo.Width / 2;

            float fInc;
            if (length == 0.0f)
            {
                fInc = float.PositiveInfinity;
            }
            else
            {
                fInc = (float)Math.Sqrt(bw) / length;
            }

            // iterate through all points in the linear stroke
            for (float f = 0; f < 1; f += fInc) 
            {
                PointF q = new PointF(finish.X * (1 - f) + f * start.X, 
                                      finish.Y * (1 - f) + f * start.Y);

                Point p = Point.Round(q);

                // iterate through all rectangles
                foreach (Rectangle rectSel in rectSelRegions)
                {
                    // set the perimeter values for the rectBrushRegion rectangle
                    // so the area can be intersected with the active
                    // selection individual recSelRegion rectangle.
                    rectBrushArea = new Rectangle(p.X - halfPenWidth, p.Y - halfPenWidth, ceilingPenWidth, ceilingPenWidth);

                    // test the intersection...
                    // the perimeter values of rectBrushRegion (above)
                    // may calculate negative but
                    // *should* always be clipped to acceptable values by
                    // by the following intersection.
                    if (rectBrushArea.IntersectsWith(rectSel))
                    {
                        // a valid intersection was found.
                        // prune the brush rectangle to fit the intersection.
                        rectBrushArea.Intersect(rectSel);
                        for (int y = rectBrushArea.Top; y < rectBrushArea.Bottom; y++)
                        {
                            // create a new rectangle for an offset relative to the 
                            // the brush mask
                            rectBrushRelativeOffset.X = Math.Max(rectSel.X - (p.X - halfPenWidth), 0); 
                            rectBrushRelativeOffset.Y = Math.Max(rectSel.Y - (p.Y - halfPenWidth), 0);
                            rectBrushRelativeOffset.Size = rectBrushArea.Size;
                            
                            ColorBgra *srcBgra;
                            ColorBgra *dstBgra;

                            try 
                            {

                                // get the source address of the first pixel from the brush mask.
                                srcBgra = (ColorBgra *)brushRenderArgs.Surface.GetPointAddress(rectBrushRelativeOffset.Left,
                                    rectBrushRelativeOffset.Y + (y - rectBrushArea.Y));
                            
                                // get the address of the pixel we want to change on the canvas.
                                dstBgra = (ColorBgra *)renderArgs.Surface.GetPointAddress(rectBrushArea.Left, y);
                            }

                            catch
                            {
                                return;
                            }
                            
                            for (int x = rectBrushArea.Left; x < rectBrushArea.Right; x++)
                            {
                                if (srcBgra->A != 0)
                                {
                                    colorLifted = *dstBgra;

                                    // hasDrawn is set if a pixel endures color replacement so that 
                                    // the placed surface will be left alone, otherwise, the placed
                                    // surface will be discarded
                                    // adjust the channel color up and down based on the difference calculated
                                    // from the source.  These values are clamped to a byte.  It's possible
                                    // that the new color is too dark or too bright to take the whole range 

                                    bool boolCIT = this.IsColorInTolerance(colorLifted, colorBeingReplaced);
                                    bool boolPAAA = false;

                                    if (AppEnvironment.AntiAliasing)
                                    {
                                        boolPAAA = this.IsPointAlreadyAntiAliased(x, y);
                                    }

                                    if (boolCIT || boolPAAA)
                                    {
                                        if (boolPAAA)
                                        {
                                            colorAdjusted = (ColorBgra)AAPoints(x, y);

                                            if (penWidth < 2.0f)
                                            {
                                                colorAdjusted.B = Utility.ClampToByte(colorToReplaceWith.B + (colorAdjusted.B - colorBeingReplaced.B));
                                                colorAdjusted.G = Utility.ClampToByte(colorToReplaceWith.G + (colorAdjusted.G - colorBeingReplaced.G));
                                                colorAdjusted.R = Utility.ClampToByte(colorToReplaceWith.R + (colorAdjusted.R - colorBeingReplaced.R));
                                                colorAdjusted.A = Utility.ClampToByte(colorToReplaceWith.A + (colorAdjusted.A - colorBeingReplaced.A));
                                            }
                                        }
                                        else
                                        {
                                            colorAdjusted.B = Utility.ClampToByte(colorLifted.B + (colorToReplaceWith.B - colorBeingReplaced.B));
                                            colorAdjusted.G = Utility.ClampToByte(colorLifted.G + (colorToReplaceWith.G - colorBeingReplaced.G));
                                            colorAdjusted.R = Utility.ClampToByte(colorLifted.R + (colorToReplaceWith.R - colorBeingReplaced.R));
                                            colorAdjusted.A = Utility.ClampToByte(colorLifted.A + (colorToReplaceWith.A - colorBeingReplaced.A));
                                        }

                                        if ((srcBgra->A != 255) && AppEnvironment.AntiAliasing)
                                        {
                                            colorAdjusted.A = srcBgra->A;
                                            dstAlpha = dstBgra->A;
                                            *dstBgra = blendOp.Apply(*dstBgra, colorAdjusted);
                                            dstBgra->A = dstAlpha;

                                            if (!this.IsPointAlreadyAntiAliased(x, y))
                                            {
                                                AAPointsAdd(x, y, colorAdjusted);
                                            }
                                        }
                                        else
                                        {
                                            colorAdjusted.A = (*dstBgra).A;
                                            *dstBgra = colorAdjusted;

                                            if (boolPAAA)
                                            {
                                               AAPointsRemove(x, y);
                                            }
                                        }
                                        
                                        hasDrawn = true;
                                    }
                                }

                                ++srcBgra;
                                ++dstBgra;
                            }
                        }
                    }
                }
            }
        }

        private bool KeyDownShiftOnly()
        {
            return ModifierKeys == Keys.Shift;
        }

        private bool KeyDownControlOnly()
        {
            return ModifierKeys == Keys.Control;
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            if ((modifierDown == Keys.Control) || 
                (modifierDown == Keys.Shift))
            {
                return;
            }
            else
            {
                if (!mouseDown)
                {
                    if (KeyDownControlOnly())
                    {
                        Cursor = cursorMouseDownPickColor;
                    }
                    else if (KeyDownShiftOnly())
                    {
                        Cursor = cursorMouseDownAdjustColor;
                    }
                    else
                    {
                        base.OnKeyDown(e);
                    }
                }
            }
        }

        protected override void OnKeyUp(KeyEventArgs e)
        {
            if (!KeyDownControlOnly() && !KeyDownShiftOnly())
            {
                if (!mouseDown)
                {
                    modifierDown = 0;
                    Cursor = cursorMouseUp;
                }
            }

            base.OnKeyUp(e);
        }

        /// <summary>
        /// Button down mouse left.  Returns true if only the left mouse button is depressed.
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        private bool BtnDownMouseLeft(MouseEventArgs e)
        {
            return(e.Button == MouseButtons.Left);
        }

        /// <summary>
        /// Button down mouse right.  Returns true if only the right mouse is depressed.
        /// </summary>
        /// <param name="e"></param>
        /// <returns></returns>
        private bool BtnDownMouseRight(MouseEventArgs e)
        {
            return(e.Button == MouseButtons.Right);
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            base.OnMouseDown(e);

            if (mouseDown)
            {
                return;
            }

            if (BtnDownMouseLeft(e) || BtnDownMouseRight(e))
            {
                this.previewRenderer.Visible = false;

                mouseDown = true;
                Cursor = cursorMouseDown;
                
                if ((!KeyDownControlOnly()) && (!KeyDownShiftOnly()))
                {
                    mouseButton = e.Button;
                
                    lastMouseXY.X = e.X;
                    lastMouseXY.Y = e.Y;

                    // parses and establishes the active selection area
                    if (clipRegion != null)
                    {
                        clipRegion.Dispose();
                        clipRegion = null;
                    }

                    clipRegion = Selection.CreateRegion();
                    renderArgs.Graphics.SetClip(clipRegion.GetRegionReadOnly(), CombineMode.Replace);

                    // find the replacement color and the color to replace
                    colorReplacing = AppEnvironment.PrimaryColor;
                    colorToReplace = AppEnvironment.SecondaryColor;
                    penWidth = AppEnvironment.PenInfo.Width;

                    // get the pen width find the ceiling integer of half of the pen width
                    ceilingPenWidth = (int)Math.Max(Math.Ceiling(penWidth), 3);

                    // used only for cursor positioning
                    halfPenWidth    = (int)Math.Ceiling(penWidth / 2.0f);

                    // set hasDrawn to false since nothing has been drawn       
                    hasDrawn = false;

                    // render the circle via GDI+ so the AA techniques can precisely
                    // mimic GDI+.
                    this.brushRenderArgs = RenderCircleBrush(); 

                    // establish tolerance
                    myTolerance = (int)(AppEnvironment.Tolerance * 256);

                    // restrict tolerance so no overlap is permitted
                    RestrictTolerance();
                    OnMouseMove(e);
                }
                else
                {
                    modifierDown = ModifierKeys;
                    OnMouseMove(e);
                }
            }
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            base.OnMouseUp(e);

            if (!KeyDownShiftOnly() && !KeyDownControlOnly())
            {
                Cursor = cursorMouseUp;
            }

            if (mouseDown)
            {
                this.previewRenderer.Visible = true;

                OnMouseMove(e);

                if (savedSurfaces.Count > 0)
                {
                    PdnRegion saveMeRegion = new PdnRegion();
                    saveMeRegion.MakeEmpty();

                    foreach (PlacedSurface pi1 in savedSurfaces)
                    {
                        saveMeRegion.Union(pi1.Bounds);
                    }

                    PdnRegion simplifiedRegion = Utility.SimplifyAndInflateRegion(saveMeRegion);

                    using (IrregularSurface weDrewThis = new IrregularSurface(renderArgs.Surface, simplifiedRegion))
                    {
                        for (int i = savedSurfaces.Count - 1; i >= 0; --i)
                        {
                            PlacedSurface ps = (PlacedSurface)savedSurfaces[i];
                            ps.Draw(renderArgs.Surface);
                            ps.Dispose();
                        }

                        savedSurfaces.Clear();

                        if (hasDrawn)
                        {
                            HistoryMemento ha = new BitmapHistoryMemento(Name, Image, DocumentWorkspace, 
                                ActiveLayerIndex, simplifiedRegion);

                            weDrewThis.Draw(bitmapLayer.Surface);
                            HistoryStack.PushNewMemento(ha);
                        }
                    }
                }

                mouseDown = false;
                modifierDown = 0;
            }

            if (brushRenderArgs != null)
            {
                if (brushRenderArgs.Surface != null)
                {
                    brushRenderArgs.Surface.Dispose();
                }
            }
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            base.OnMouseMove(e);

            this.previewRenderer.BrushLocation = new Point(e.X, e.Y);
            this.previewRenderer.BrushSize = AppEnvironment.PenInfo.Width / 2.0f;

            if (mouseDown)
            {
                if (BtnDownMouseLeft(e) || BtnDownMouseRight(e))
                {
                    if (modifierDown == 0)
                    {
                        // if the primary and secondary colors are identical,
                        // return...there's no point in committing any action
                        if (colorReplacing == colorToReplace)
                        {
                            return;
                        }

                        // get our start and end coordinates, since we need
                        // to trace along an action line -- the user will expect this behavior
                        // if we don't, it'll look like a tin can riddled with bullet holes
                        Point pointStartCorner = lastMouseXY;          // start point
                        Point pointEndCorner = new Point(e.X, e.Y);  // end point

                        // create the rectangle with the 'a' and 'b' points above
                        Rectangle inspectionRect = 
                            Utility.PointsToRectangle(pointStartCorner, pointEndCorner);

                        // inflate the region to address account for the pen width
                        // then intersect with the Workspace to "clip" the boundary
                        // the total area of the clipped rectangle includes the
                        // width of the pen surrounding the points limited by either
                        // the canvas perimeter or the selection outline
                        inspectionRect.Inflate(1 + ceilingPenWidth / 2, 1 + ceilingPenWidth / 2);
                        inspectionRect.Intersect(ActiveLayer.Bounds);

                        // Enforce the selection area restrictions.
                        // If within the selection area restrictions, build an image history
                        bool gotWidth = inspectionRect.Width  > 0;
                        bool gotHeight = inspectionRect.Height > 0;
                        bool isInClip = renderArgs.Graphics.IsVisible(inspectionRect);

                        if ((gotWidth) && (gotHeight) && (isInClip))
                        {
                            PlacedSurface savedPS = new PlacedSurface(renderArgs.Surface, inspectionRect);
                            savedSurfaces.Add(savedPS);

                            renderArgs.Graphics.CompositingMode = CompositingMode.SourceOver;
                    
                            // check the mouse buttons and if we've made it this far, at least
                            // one of the mouse buttons (left|right) was depressed
                            if (BtnDownMouseLeft(e))
                            {
                                this.DrawOverPoints(pointStartCorner, pointEndCorner, colorReplacing, colorToReplace);
                            }
                            else
                            {
                                this.DrawOverPoints(pointStartCorner, pointEndCorner, colorToReplace, colorReplacing);
                            }

                            bitmapLayer.Invalidate(inspectionRect);
                            Update();
                        }

                        // update the lastMouseXY so we know how to "connect the dots"
                        lastMouseXY = pointEndCorner;
                    }
                    else
                    {
                        switch (modifierDown & (Keys.Control | Keys.Shift))
                        {
                            case Keys.Control: 
                                PickColor(e);
                                break;

                            case Keys.Shift: 
                                AdjustDrawingColor(e);
                                break;

                            default: 
                                break;
                        }
                    }
                }
            }
        }

        public RecolorTool(DocumentWorkspace documentWorkspace)
            : base(documentWorkspace,
                   PdnResources.GetImageResource("Icons.RecoloringToolIcon.png"),
                   PdnResources.GetString("RecolorTool.Name"), 
                   PdnResources.GetString("RecolorTool.HelpText"),
                   'r',
                   false,
                   ToolBarConfigItems.Pen | ToolBarConfigItems.Antialiasing | ToolBarConfigItems.Tolerance)
        {
        }
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.