Пример #1
0
        protected override void OnLift(MouseEventArgs e)
        {
            PdnGraphicsPath liftPath   = Selection.CreatePath();
            PdnRegion       liftRegion = Selection.CreateRegion();

            this.ourContext.LiftedPixels = new MaskedSurface(activeLayer.Surface, liftPath);

            HistoryMemento bitmapAction = new BitmapHistoryMemento(
                Name,
                Image,
                DocumentWorkspace,
                ActiveLayerIndex,
                this.ourContext.poLiftedPixelsGuid);

            this.currentHistoryMementos.Add(bitmapAction);

            // If the user is holding down the control key, we want to *copy* the pixels
            // and not "lift and erase"
            if ((ModifierKeys & Keys.Control) == Keys.None)
            {
                ColorBgra fill = AppEnvironment.SecondaryColor;
                fill.A = 0;
                UnaryPixelOp op = new UnaryPixelOps.Constant(fill);
                op.Apply(this.renderArgs.Surface, liftRegion);
            }

            liftRegion.Dispose();
            liftRegion = null;

            liftPath.Dispose();
            liftPath = null;
        }
Пример #2
0
        protected override SegmentedList <PointDouble> CreateShape(SegmentedList <PointDouble> tracePoints)
        {
            RectDouble  num5;
            PointDouble a    = tracePoints[0];
            PointDouble b    = tracePoints[tracePoints.Count - 1];
            PointDouble num3 = new PointDouble(b.X - a.X, b.Y - a.Y);
            double      num4 = Math.Sqrt((num3.X * num3.X) + (num3.Y * num3.Y));

            if ((base.ModifierKeys & Keys.Shift) != Keys.None)
            {
                PointDouble center = new PointDouble((a.X + b.X) / 2.0, (a.Y + b.Y) / 2.0);
                double      num7   = num4 / 2.0;
                num5 = RectDouble.FromCenter(center, (double)(num7 * 2.0));
            }
            else
            {
                num5 = RectDoubleUtil.FromPixelPoints(a, b);
            }
            PdnGraphicsPath path = new PdnGraphicsPath();

            path.AddEllipse(num5.ToGdipRectangleF());
            using (Matrix matrix = new Matrix())
            {
                path.Flatten(matrix, 0.1f);
            }
            SegmentedList <PointDouble> list = new SegmentedList <PointDouble>(path.PathPoints.Select <PointF, PointDouble>(pt => pt.ToDoublePoint()), 7);

            path.Dispose();
            return(list);
        }
Пример #3
0
        private static Surface CreateThumbnail(SurfaceForClipboard surfaceForClipboard)
        {
            const int thumbLength96dpi = 120;
            int       thumbSizeOurDpi  = SystemLayer.UI.ScaleWidth(thumbLength96dpi);

            Surface         surface  = surfaceForClipboard.MaskedSurface.SurfaceReadOnly;
            PdnGraphicsPath maskPath = surfaceForClipboard.MaskedSurface.CreatePath();
            Rectangle       bounds   = surfaceForClipboard.Bounds;

            Surface thumb = CreateThumbnail(surface, maskPath, bounds, thumbSizeOurDpi);

            maskPath.Dispose();

            return(thumb);
        }
Пример #4
0
        public override HistoryMemento OnExecute(IHistoryWorkspace historyWorkspace)
        {
            if (historyWorkspace.Selection.IsEmpty)
            {
                return(null);
            }
            else
            {
                SelectionHistoryMemento sha = new SelectionHistoryMemento(
                    StaticName,
                    StaticImage,
                    historyWorkspace);

                //PdnGraphicsPath selectedPath = historyWorkspace.Selection.GetPathReadOnly();
                PdnGraphicsPath selectedPath = historyWorkspace.Selection.CreatePath();

                PdnGraphicsPath boundsOutline = new PdnGraphicsPath();
                boundsOutline.AddRectangle(historyWorkspace.Document.Bounds);

                PdnGraphicsPath clippedPath  = PdnGraphicsPath.Combine(selectedPath, CombineMode.Intersect, boundsOutline);
                PdnGraphicsPath invertedPath = PdnGraphicsPath.Combine(clippedPath, CombineMode.Xor, boundsOutline);

                selectedPath.Dispose();
                selectedPath = null;

                clippedPath.Dispose();
                clippedPath = null;

                EnterCriticalRegion();
                historyWorkspace.Selection.PerformChanging();
                historyWorkspace.Selection.Reset();
                historyWorkspace.Selection.SetContinuation(invertedPath, CombineMode.Replace, true);
                historyWorkspace.Selection.CommitContinuation();
                historyWorkspace.Selection.PerformChanged();

                boundsOutline.Dispose();
                boundsOutline = null;

                return(sha);
            }
        }
Пример #5
0
        public override HistoryMemento OnExecute(IHistoryWorkspace historyWorkspace)
        {
            if (historyWorkspace.Selection.IsEmpty)
            {
                return null;
            }
            else
            {
                SelectionHistoryMemento sha = new SelectionHistoryMemento(
                    StaticName,
                    StaticImage,
                    historyWorkspace);

                //PdnGraphicsPath selectedPath = historyWorkspace.Selection.GetPathReadOnly();
                PdnGraphicsPath selectedPath = historyWorkspace.Selection.CreatePath();

                PdnGraphicsPath boundsOutline = new PdnGraphicsPath();
                boundsOutline.AddRectangle(historyWorkspace.Document.Bounds);

                PdnGraphicsPath clippedPath = PdnGraphicsPath.Combine(selectedPath, CombineMode.Intersect, boundsOutline);
                PdnGraphicsPath invertedPath = PdnGraphicsPath.Combine(clippedPath, CombineMode.Xor, boundsOutline);

                selectedPath.Dispose();
                selectedPath = null;

                clippedPath.Dispose();
                clippedPath = null;

                EnterCriticalRegion();
                historyWorkspace.Selection.PerformChanging();
                historyWorkspace.Selection.Reset();
                historyWorkspace.Selection.SetContinuation(invertedPath, CombineMode.Replace, true);
                historyWorkspace.Selection.CommitContinuation();
                historyWorkspace.Selection.PerformChanged();

                boundsOutline.Dispose();
                boundsOutline = null;

                return sha;
            }
        }
Пример #6
0
        protected override List <PointF> CreateShape(List <Point> tracePoints)
        {
            Point a   = tracePoints[0];
            Point b   = tracePoints[tracePoints.Count - 1];
            Point dir = new Point(b.X - a.X, b.Y - a.Y);
            float len = (float)Math.Sqrt(dir.X * dir.X + dir.Y * dir.Y);

            RectangleF rectF;

            if ((ModifierKeys & Keys.Shift) != 0)
            {
                PointF center = new PointF((float)(a.X + b.X) / 2.0f, (float)(a.Y + b.Y) / 2.0f);
                float  radius = len / 2;
                rectF = Rectangle.Truncate(Utility.RectangleFromCenter(center, radius));
            }
            else
            {
                rectF = Utility.PointsToRectangle(a, b);
            }

            Rectangle       rect = Utility.RoundRectangle(rectF);
            PdnGraphicsPath path = new PdnGraphicsPath();

            path.AddEllipse(rect);

            // Avoid asymmetrical circles where the left or right side of the ellipse has a pixel jutting out
            using (Matrix m = new Matrix())
            {
                m.Reset();
                m.Translate(-0.5f, -0.5f, MatrixOrder.Append);
                path.Transform(m);
            }

            path.Flatten(Utility.IdentityMatrix, 0.1f);

            PointF[] pointsF = path.PathPoints;
            path.Dispose();

            return(new List <PointF>(pointsF));
        }
Пример #7
0
        protected override List<PointF> CreateShape(List<Point> tracePoints)
        {
            Point a = tracePoints[0];
            Point b = tracePoints[tracePoints.Count - 1];
            Point dir = new Point(b.X - a.X, b.Y - a.Y);
            float len = (float)Math.Sqrt(dir.X * dir.X + dir.Y * dir.Y);

            RectangleF rectF;

            if ((ModifierKeys & Keys.Shift) != 0)
            {
                PointF center = new PointF((float)(a.X + b.X) / 2.0f, (float)(a.Y + b.Y) / 2.0f);
                float radius = len / 2;
                rectF = Rectangle.Truncate(Utility.RectangleFromCenter(center, radius));
            }
            else
            {
                rectF = Utility.PointsToRectangle(a, b);
            }

            Rectangle rect = Utility.RoundRectangle(rectF);
            PdnGraphicsPath path = new PdnGraphicsPath();
            path.AddEllipse(rect);

            // Avoid asymmetrical circles where the left or right side of the ellipse has a pixel jutting out
            using (Matrix m = new Matrix())
            {
                m.Reset();
                m.Translate(-0.5f, -0.5f, MatrixOrder.Append);
                path.Transform(m);
            }

            path.Flatten(Utility.IdentityMatrix, 0.1f);

            PointF[] pointsF = path.PathPoints;
            path.Dispose();

            return new List<PointF>(pointsF);
        }
Пример #8
0
        private void OnMouseMoveImpl(MouseEventArgs e, StringBuilder sbLogger)
        {
            if (!this.tracking)
            {
                sbLogger.Append("1 ");
                Cursor cursor = this.moveToolCursor;

                for (int i = 0; i < this.moveNubs.Length; ++i)
                {
                    sbLogger.Append("2 ");
                    MoveNubRenderer nub = this.moveNubs[i];
                    sbLogger.Append("3 ");

                    if (nub.Visible && nub.IsPointTouching(new Point(e.X, e.Y), true))
                    {
                        sbLogger.Append("4 ");
                        cursor = this.handCursor;
                        break;
                    }
                }

                this.Cursor = cursor;
                sbLogger.Append("5 ");
            }
            else
            {
                sbLogger.Append("6 ");
                if (this.context.currentMode != Mode.Translate)
                {
                    sbLogger.Append("7 ");
                    this.Cursor = this.handCursorMouseDown;
                }

                sbLogger.Append("8 ");
                Point newMouseXY = new Point(e.X, e.Y);
                Point newOffset  = new Point(newMouseXY.X - context.startMouseXY.X, newMouseXY.Y - context.startMouseXY.Y);

                PreRender();

                this.dontDrop = true;

                sbLogger.Append("9 ");
                Selection.PerformChanging();

                using (Matrix translateMatrix = new Matrix())
                {
                    RectangleF rect;
                    translateMatrix.Reset();

                    if (this.context.baseTransform != null)
                    {
                        Selection.SetInterimTransform(this.context.baseTransform);
                    }

                    Matrix interim = Selection.GetInterimTransformCopy();

                    switch (this.context.currentMode)
                    {
                    case Mode.Translate:
                        translateMatrix.Translate((float)newOffset.X, (float)newOffset.Y, MatrixOrder.Append);
                        break;

                    case Mode.Rotate:
                        rect = this.context.liftedBounds;
                        PointF center = new PointF(rect.X + (rect.Width / 2.0f), rect.Y + (rect.Height / 2.0f));
                        center = Utility.TransformOnePoint(interim, center);
                        double theta1     = Math.Atan2(context.startMouseXY.Y - center.Y, context.startMouseXY.X - center.X);
                        double theta2     = Math.Atan2(e.Y - center.Y, e.X - center.X);
                        double thetaDelta = theta2 - theta1;
                        this.angleDelta = (float)(thetaDelta * (180.0f / Math.PI));
                        float angle = this.context.startAngle + this.angleDelta;

                        if ((ModifierKeys & Keys.Shift) != 0)
                        {
                            angle      = ConstrainAngle(angle);
                            angleDelta = angle - this.context.startAngle;
                        }

                        translateMatrix.RotateAt(angleDelta, center, MatrixOrder.Append);
                        this.rotateNub.Location = center;
                        this.rotateNub.Angle    = this.context.startAngle + angleDelta;
                        break;

                    case Mode.Scale:
                        PointF xyAxes = GetEdgeVector(this.context.startEdge);
                        PointF xAxis  = new PointF(xyAxes.X, 0);
                        PointF yAxis  = new PointF(0, xyAxes.Y);
                        PointF edgeX  = Utility.TransformOneVector(interim, xAxis);
                        PointF edgeY  = Utility.TransformOneVector(interim, yAxis);
                        PointF edgeXN = Utility.NormalizeVector2(edgeX);
                        PointF edgeYN = Utility.NormalizeVector2(edgeY);

                        PointF xu;
                        float  xulen;
                        PointF xv;
                        Utility.GetProjection((PointF)newOffset, edgeXN, out xu, out xulen, out xv);

                        PointF yu;
                        float  yulen;
                        PointF yv;
                        Utility.GetProjection((PointF)newOffset, edgeYN, out yu, out yulen, out yv);

                        PdnGraphicsPath startPath2 = this.context.startPath.Clone();
                        RectangleF      sp2Bounds  = startPath2.GetBounds();

                        PointF sp2BoundsCenter = new PointF((sp2Bounds.Left + sp2Bounds.Right) / 2.0f,
                                                            (sp2Bounds.Top + sp2Bounds.Bottom) / 2.0f);

                        float tAngle    = Utility.GetAngleOfTransform(interim);
                        bool  isFlipped = Utility.IsTransformFlipped(interim);

                        using (Matrix spm = new Matrix())
                        {
                            spm.Reset();
                            spm.RotateAt(-tAngle, sp2BoundsCenter, MatrixOrder.Append);
                            translateMatrix.RotateAt(-tAngle, sp2BoundsCenter, MatrixOrder.Append);
                            startPath2.Transform(spm);
                        }

                        RectangleF spBounds2 = startPath2.GetBounds();

                        startPath2.Dispose();
                        startPath2 = null;

                        float xTranslate;
                        float yTranslate;
                        bool  allowConstrain;

                        Edge theEdge = this.context.startEdge;

                        // If the transform is flipped, then GetTransformAngle will return 180 degrees
                        // even though no rotation has actually taken place. Thus we have to scratch
                        // our head and go "hmm, let's make some adjustments to this." Otherwise stretching
                        // the top and bottom nubs goes in the wrong direction.
                        if (isFlipped)
                        {
                            theEdge = FlipEdgeVertically(theEdge);
                        }

                        switch (theEdge)
                        {
                        default:
                            throw new InvalidEnumArgumentException();

                        case Edge.TopLeft:
                            allowConstrain = true;
                            xTranslate     = -spBounds2.X - spBounds2.Width;
                            yTranslate     = -spBounds2.Y - spBounds2.Height;
                            break;

                        case Edge.Top:
                            allowConstrain = false;
                            xTranslate     = 0;
                            yTranslate     = -spBounds2.Y - spBounds2.Height;
                            break;

                        case Edge.TopRight:
                            allowConstrain = true;
                            xTranslate     = -spBounds2.X;
                            yTranslate     = -spBounds2.Y - spBounds2.Height;
                            break;

                        case Edge.Left:
                            allowConstrain = false;
                            xTranslate     = -spBounds2.X - spBounds2.Width;
                            yTranslate     = 0;
                            break;

                        case Edge.Right:
                            allowConstrain = false;
                            xTranslate     = -spBounds2.X;
                            yTranslate     = 0;
                            break;

                        case Edge.BottomLeft:
                            allowConstrain = true;
                            xTranslate     = -spBounds2.X - spBounds2.Width;
                            yTranslate     = -spBounds2.Y;
                            break;

                        case Edge.Bottom:
                            allowConstrain = false;
                            xTranslate     = 0;
                            yTranslate     = -spBounds2.Y;
                            break;

                        case Edge.BottomRight:
                            allowConstrain = true;
                            xTranslate     = -spBounds2.X;
                            yTranslate     = -spBounds2.Y;
                            break;
                        }

                        translateMatrix.Translate(xTranslate, yTranslate, MatrixOrder.Append);

                        float newWidth  = spBounds2.Width + xulen;
                        float newHeight = spBounds2.Height + yulen;
                        float xScale    = newWidth / spBounds2.Width;
                        float yScale    = newHeight / spBounds2.Height;

                        if (allowConstrain && (this.ModifierKeys & Keys.Shift) != 0)
                        {
                            ConstrainScaling(this.context.liftedBounds, spBounds2.Width, spBounds2.Height,
                                             newWidth, newHeight, out xScale, out yScale);
                        }

                        translateMatrix.Scale(xScale, yScale, MatrixOrder.Append);
                        translateMatrix.Translate(-xTranslate, -yTranslate, MatrixOrder.Append);
                        translateMatrix.RotateAt(+tAngle, sp2BoundsCenter, MatrixOrder.Append);

                        break;

                    default:
                        throw new InvalidEnumArgumentException();
                    }

                    this.context.deltaTransform.Reset();
                    this.context.deltaTransform.Multiply(this.context.liftTransform, MatrixOrder.Append);
                    this.context.deltaTransform.Multiply(translateMatrix, MatrixOrder.Append);

                    translateMatrix.Multiply(this.context.baseTransform, MatrixOrder.Prepend);

                    Selection.SetInterimTransform(translateMatrix);

                    interim.Dispose();
                    interim = null;
                }

                // advertise our angle of rotation to any host (i.e. mainform) that might want to use that information
                this.hostShouldShowAngle = this.rotateNub.Visible;
                this.hostAngle           = -this.rotateNub.Angle;

                Selection.PerformChanged();
                dontDrop = false;

                Render(newOffset, true);
                Update();

                sbLogger.Append("a ");
                this.context.offset = newOffset;

                sbLogger.Append("b ");

                if (this.enableOutline)
                {
                    DocumentWorkspace.ResetOutlineWhiteOpacity();
                }

                sbLogger.Append("c ");
            }

            sbLogger.Append("d ");
        }
Пример #9
0
        protected void RenderShape()
        {
            // create the Pen we will use to draw with
            Pen       outlinePen    = null;
            Brush     interiorBrush = null;
            PenInfo   pi            = AppEnvironment.PenInfo;
            BrushInfo bi            = AppEnvironment.BrushInfo;

            ColorBgra primary   = AppEnvironment.PrimaryColor;
            ColorBgra secondary = AppEnvironment.SecondaryColor;

            if (!ForceShapeDrawType && AppEnvironment.ShapeDrawType == ShapeDrawType.Interior)
            {
                Utility.Swap(ref primary, ref secondary);
            }

            // Initialize pens and brushes to the correct colors
            if ((mouseButton & MouseButtons.Left) == MouseButtons.Left)
            {
                outlinePen    = pi.CreatePen(AppEnvironment.BrushInfo, primary.ToColor(), secondary.ToColor());
                interiorBrush = bi.CreateBrush(secondary.ToColor(), primary.ToColor());
            }
            else if ((mouseButton & MouseButtons.Right) == MouseButtons.Right)
            {
                outlinePen    = pi.CreatePen(AppEnvironment.BrushInfo, secondary.ToColor(), primary.ToColor());
                interiorBrush = bi.CreateBrush(primary.ToColor(), secondary.ToColor());
            }

            if (!this.UseDashStyle)
            {
                outlinePen.DashStyle = DashStyle.Solid;
            }

            outlinePen.LineJoin   = LineJoin.MiterClipped;
            outlinePen.MiterLimit = 2;

            // redraw the old saveSurface
            if (interiorSaveRegion != null)
            {
                RestoreRegion(interiorSaveRegion);
                interiorSaveRegion.Dispose();
                interiorSaveRegion = null;
            }

            if (outlineSaveRegion != null)
            {
                RestoreRegion(outlineSaveRegion);
                outlineSaveRegion.Dispose();
                outlineSaveRegion = null;
            }

            // anti-aliasing? Don't mind if I do
            if (AppEnvironment.AntiAliasing)
            {
                renderArgs.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            }
            else
            {
                renderArgs.Graphics.SmoothingMode = SmoothingMode.None;
            }

            // also set the pixel offset mode
            renderArgs.Graphics.PixelOffsetMode = GetPixelOffsetMode();

            // figure out how we're going to draw
            ShapeDrawType drawType;

            if (ForceShapeDrawType)
            {
                drawType = ForcedShapeDrawType;
            }
            else
            {
                drawType = AppEnvironment.ShapeDrawType;
            }

            // get the region we want to save
            points = this.TrimShapePath(points);
            PointF[]        pointsArray = points.ToArray();
            PdnGraphicsPath shapePath   = CreateShapePath(pointsArray);

            if (shapePath != null)
            {
                // create non-optimized interior region
                PdnRegion interiorRegion = new PdnRegion(shapePath);

                // create non-optimized outline region
                PdnRegion outlineRegion;

                using (PdnGraphicsPath outlinePath = (PdnGraphicsPath)shapePath.Clone())
                {
                    try
                    {
                        outlinePath.Widen(outlinePen);
                        outlineRegion = new PdnRegion(outlinePath);
                    }

                    // Sometimes GDI+ gets cranky if we have a very small shape (e.g. all points
                    // are coincident).
                    catch (OutOfMemoryException)
                    {
                        outlineRegion = new PdnRegion(shapePath);
                    }
                }

                // create optimized outlineRegion for purposes of rendering, if it is possible to do so
                // shapes will often provide an "optimized" region that circumvents the fact that
                // we'd otherwise get a region that encompasses the outline *and* the interior, thus
                // slowing rendering significantly in many cases.
                RectangleF[] optimizedOutlineRegion = GetOptimizedShapeOutlineRegion(pointsArray, shapePath);
                PdnRegion    invalidOutlineRegion;

                if (optimizedOutlineRegion != null)
                {
                    Utility.InflateRectanglesInPlace(optimizedOutlineRegion, (int)(outlinePen.Width + 2));
                    invalidOutlineRegion = Utility.RectanglesToRegion(optimizedOutlineRegion);
                }
                else
                {
                    invalidOutlineRegion = Utility.SimplifyAndInflateRegion(outlineRegion, Utility.DefaultSimplificationFactor, (int)(outlinePen.Width + 2));
                }

                // create optimized interior region
                PdnRegion invalidInteriorRegion = Utility.SimplifyAndInflateRegion(interiorRegion, Utility.DefaultSimplificationFactor, 3);

                PdnRegion invalidRegion = new PdnRegion();
                invalidRegion.MakeEmpty();

                // set up alpha blending
                renderArgs.Graphics.CompositingMode = AppEnvironment.GetCompositingMode();

                SaveRegion(invalidOutlineRegion, invalidOutlineRegion.GetBoundsInt());
                this.outlineSaveRegion = invalidOutlineRegion;
                if ((drawType & ShapeDrawType.Outline) != 0)
                {
                    shapePath.Draw(renderArgs.Graphics, outlinePen);
                }

                invalidRegion.Union(invalidOutlineRegion);

                // draw shape
                if ((drawType & ShapeDrawType.Interior) != 0)
                {
                    SaveRegion(invalidInteriorRegion, invalidInteriorRegion.GetBoundsInt());
                    this.interiorSaveRegion = invalidInteriorRegion;
                    renderArgs.Graphics.FillPath(interiorBrush, shapePath);
                    invalidRegion.Union(invalidInteriorRegion);
                }
                else
                {
                    invalidInteriorRegion.Dispose();
                    invalidInteriorRegion = null;
                }

                bitmapLayer.Invalidate(invalidRegion);

                invalidRegion.Dispose();
                invalidRegion = null;

                outlineRegion.Dispose();
                outlineRegion = null;

                interiorRegion.Dispose();
                interiorRegion = null;
            }

            Update();

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

            outlinePen.Dispose();
            interiorBrush.Dispose();
        }
Пример #10
0
        public bool PerformAction()
        {
            bool success = true;

            if (this.documentWorkspace.Selection.IsEmpty ||
                !(this.documentWorkspace.ActiveLayer is BitmapLayer))
            {
                return(false);
            }

            try
            {
                using (new WaitCursorChanger(this.documentWorkspace))
                {
                    Utility.GCFullCollect();
                    PdnRegion           selectionRegion     = this.documentWorkspace.Selection.CreateRegion();
                    PdnGraphicsPath     selectionOutline    = this.documentWorkspace.Selection.CreatePath();
                    BitmapLayer         activeLayer         = (BitmapLayer)this.documentWorkspace.ActiveLayer;
                    RenderArgs          renderArgs          = new RenderArgs(activeLayer.Surface);
                    MaskedSurface       maskedSurface       = new MaskedSurface(renderArgs.Surface, selectionOutline);
                    SurfaceForClipboard surfaceForClipboard = new SurfaceForClipboard(maskedSurface);
                    Rectangle           selectionBounds     = Utility.GetRegionBounds(selectionRegion);

                    if (selectionBounds.Width > 0 && selectionBounds.Height > 0)
                    {
                        Surface copySurface      = new Surface(selectionBounds.Width, selectionBounds.Height);
                        Bitmap  copyBitmap       = copySurface.CreateAliasedBitmap();
                        Bitmap  copyOpaqueBitmap = new Bitmap(copySurface.Width, copySurface.Height, PixelFormat.Format24bppRgb);

                        using (Graphics copyBitmapGraphics = Graphics.FromImage(copyBitmap))
                        {
                            copyBitmapGraphics.Clear(Color.White);
                        }

                        maskedSurface.Draw(copySurface, -selectionBounds.X, -selectionBounds.Y);

                        using (Graphics copyOpaqueBitmapGraphics = Graphics.FromImage(copyOpaqueBitmap))
                        {
                            copyOpaqueBitmapGraphics.Clear(Color.White);
                            copyOpaqueBitmapGraphics.DrawImage(copyBitmap, 0, 0);
                        }

                        DataObject dataObject = new DataObject();

                        dataObject.SetData(DataFormats.Bitmap, copyOpaqueBitmap);
                        dataObject.SetData(surfaceForClipboard);

                        int retryCount = 2;

                        while (retryCount >= 0)
                        {
                            try
                            {
                                using (new WaitCursorChanger(this.documentWorkspace))
                                {
                                    Clipboard.SetDataObject(dataObject, true);
                                }

                                break;
                            }

                            catch
                            {
                                if (retryCount == 0)
                                {
                                    success = false;
                                    Utility.ErrorBox(this.documentWorkspace,
                                                     PdnResources.GetString("CopyAction.Error.TransferToClipboard"));
                                }
                                else
                                {
                                    Thread.Sleep(200);
                                }
                            }

                            finally
                            {
                                --retryCount;
                            }
                        }

                        copySurface.Dispose();
                        copyBitmap.Dispose();
                        copyOpaqueBitmap.Dispose();
                    }

                    selectionRegion.Dispose();
                    selectionOutline.Dispose();
                    renderArgs.Dispose();
                    maskedSurface.Dispose();
                }
            }

            catch (OutOfMemoryException)
            {
                success = false;
                Utility.ErrorBox(this.documentWorkspace, PdnResources.GetString("CopyAction.Error.OutOfMemory"));
            }

            catch (Exception)
            {
                success = false;
                Utility.ErrorBox(this.documentWorkspace, PdnResources.GetString("CopyAction.Error.Generic"));
            }

            Utility.GCFullCollect();
            return(success);
        }