Exemple #1
0
 public bool IsVisible(Point pt)
 {
     using (PdnGraphicsPath path = CreatePath())
     {
         return(path.IsVisible(pt));
     }
 }
Exemple #2
0
 public PdnRegion CreateRegionRaw()
 {
     using (PdnGraphicsPath path = CreatePath())
     {
         return(new PdnRegion(path));
     }
 }
Exemple #3
0
        // only works if base is empty
        public void SetContinuation(PdnGraphicsPath path, CombineMode combineMode, bool takeOwnership)
        {
            lock (this.syncRoot)
            {
                if (!this.data.basePath.IsEmpty)
                {
                    throw new InvalidOperationException("base path must be empty to use this overload of SetContinuation");
                }

                OnChanging();

                CommitInterimTransform();
                ResetCumulativeTransform();

                this.data.continuationCombineMode = combineMode;

                if (takeOwnership)
                {
                    this.data.continuation.Dispose();
                    this.data.continuation = path;
                }
                else
                {
                    this.data.continuation.Reset();
                    this.data.continuation.AddPath(path, false);
                }

                OnChanged();
            }
        }
Exemple #4
0
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.components != null)
                {
                    this.components.Dispose();
                    this.components = null;
                }

                if (this.selectionTimer != null)
                {
                    this.selectionTimer.Dispose();
                    this.selectionTimer = null;
                }

                if (this.zoomInSelectedPath != null)
                {
                    this.zoomInSelectedPath.Dispose();
                    this.zoomInSelectedPath = null;
                }
            }

            base.Dispose(disposing);
        }
        public static PdnGraphicsPath FromRegion(PdnRegion region)
        {
            Rectangle bounds = region.GetBoundsInt();

            Rectangle[] scans   = region.GetRegionScansReadOnlyInt();
            BitVector2D stencil = new BitVector2D(bounds.Width, bounds.Height);

            for (int i = 0; i < scans.Length; ++i)
            {
                Rectangle rect = scans[i];
                rect.X -= bounds.X;
                rect.Y -= bounds.Y;

                stencil.SetUnchecked(rect, true);
            }

            PdnGraphicsPath path = PathFromStencil(stencil, new Rectangle(0, 0, stencil.Width, stencil.Height));

            using (Matrix matrix = new Matrix())
            {
                matrix.Reset();
                matrix.Translate(bounds.X, bounds.Y);
                path.Transform(matrix);
            }

            return(path);
        }
        public MaskedSurface(Surface source, PdnGraphicsPath path)
        {
            RectangleF boundsF = path.GetBounds();
            Rectangle  bounds  = Utility.RoundRectangle(boundsF);

            Rectangle boundsClipped = Rectangle.Intersect(bounds, source.Bounds);
            Rectangle boundsRead;

            if (bounds != boundsClipped)
            {
                PdnRegion region = new PdnRegion(path);
                region.Intersect(source.Bounds);
                SetPathField(PdnGraphicsPath.FromRegion(region));
                this.region = region;
                boundsRead  = region.GetBoundsInt();
            }
            else
            {
                SetPathField(path.Clone());
                this.region = new PdnRegion(this.path);
                boundsRead  = boundsClipped;
            }

            if (boundsRead.Width > 0 && boundsRead.Height > 0)
            {
                this.surface = new Surface(boundsRead.Size);
                this.surface.CopySurface(source, boundsRead);
            }
            else
            {
                this.surface = null;
            }
        }
        private void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.surface != null)
                {
                    this.surface.Dispose();
                    this.surface = null;
                }

                if (this.region != null)
                {
                    this.region.Dispose();
                    this.region = null;
                }

                if (this.path != null)
                {
                    this.path.Dispose();
                    this.path = null;
                }

                if (this.shadowPath != null)
                {
                    this.shadowPath.Dispose();
                    this.shadowPath = null;
                }
            }

            this.disposed = true;
        }
Exemple #8
0
        private void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.SurfaceReadOnly != null)
                {
                    this.SurfaceReadOnly.Dispose();
                    this.SurfaceReadOnly = null;
                }

                if (this.region != null)
                {
                    this.region.Dispose();
                    this.region = null;
                }

                if (this.path != null)
                {
                    this.path.Dispose();
                    this.path = null;
                }

                if (this.shadowPath != null)
                {
                    this.shadowPath.Dispose();
                    this.shadowPath = null;
                }
            }

            this.IsDisposed = true;
        }
        public PdnGraphicsPath Clone()
        {
            PdnGraphicsPath path = new PdnGraphicsPath((GraphicsPath)gdiPath.Clone());

            path.tooComplex = this.tooComplex;
            return(path);
        }
        public static PdnGraphicsPath Combine(PdnGraphicsPath subjectPath, CombineMode combineMode, PdnGraphicsPath clipPath)
        {
            switch (combineMode)
            {
            case CombineMode.Complement:
                return(Combine(clipPath, CombineMode.Exclude, subjectPath));

            case CombineMode.Replace:
                return(clipPath.Clone());

            case CombineMode.Xor:
            case CombineMode.Intersect:
            case CombineMode.Union:
            case CombineMode.Exclude:
                if (subjectPath.IsEmpty && clipPath.IsEmpty)
                {
                    return(new PdnGraphicsPath());    // empty path
                }
                else if (subjectPath.IsEmpty)
                {
                    switch (combineMode)
                    {
                    case CombineMode.Xor:
                    case CombineMode.Union:
                        return(clipPath.Clone());

                    case CombineMode.Intersect:
                    case CombineMode.Exclude:
                        return(new PdnGraphicsPath());

                    default:
                        throw new InvalidEnumArgumentException();
                    }
                }
                else if (clipPath.IsEmpty)
                {
                    switch (combineMode)
                    {
                    case CombineMode.Exclude:
                    case CombineMode.Xor:
                    case CombineMode.Union:
                        return(subjectPath.Clone());

                    case CombineMode.Intersect:
                        return(new PdnGraphicsPath());

                    default:
                        throw new InvalidEnumArgumentException();
                    }
                }
                else
                {
                    GraphicsPath resultPath = PdnGraphics.ClipPath(subjectPath, combineMode, clipPath);
                    return(new PdnGraphicsPath(resultPath));
                }

            default:
                throw new InvalidEnumArgumentException();
            }
        }
Exemple #11
0
            public void Dispose(bool disposing)
            {
                if (disposing)
                {
                    if (this.basePath != null)
                    {
                        this.basePath.Dispose();
                        this.basePath = null;
                    }

                    if (this.continuation != null)
                    {
                        this.continuation.Dispose();
                        this.continuation = null;
                    }

                    if (this.cumulativeTransform != null)
                    {
                        this.cumulativeTransform.Dispose();
                        this.cumulativeTransform = null;
                    }

                    if (this.interimTransform != null)
                    {
                        this.interimTransform.Dispose();
                        this.interimTransform = null;
                    }
                }
            }
Exemple #12
0
 public bool IsVisible(Point pt)
 {
     using (PdnGraphicsPath path = CreatePath())
     //PdnGraphicsPath path = GetPathReadOnly();
     {
         return(path.IsVisible(pt));
     }
 }
Exemple #13
0
 public PdnRegion CreateRegionRaw()
 {
     using (PdnGraphicsPath path = CreatePath())
     //PdnGraphicsPath path = GetPathReadOnly();
     {
         return(new PdnRegion(path));
     }
 }
Exemple #14
0
 public RectangleF GetBoundsF(bool applyInterimTransformation)
 {
     using (PdnGraphicsPath path = this.CreatePath(applyInterimTransformation))
     {
         RectangleF bounds2 = path.GetBounds2();
         return(bounds2);
     }
 }
Exemple #15
0
        public void OnDeserialization(object sender)
        {
            threadPool = new PaintDotNet.Threading.ThreadPool();

            if (this.path != null)
            {
                this.shadowPath = this.path.Clone();
            }
        }
        private PdnGraphicsPath GetPath()
        {
            if (this.path == null)
            {
                SetPathField(PdnGraphicsPath.FromRegion(this.region));
            }

            return(this.shadowPath);
        }
Exemple #17
0
 public Data()
 {
     this.basePath = new PdnGraphicsPath();
     this.continuation = new PdnGraphicsPath();
     this.continuationCombineMode = CombineMode.Xor;
     this.cumulativeTransform = new Matrix();
     this.cumulativeTransform.Reset();
     this.interimTransform = new Matrix();
     this.interimTransform.Reset();            
 }
Exemple #18
0
 public Data()
 {
     this.basePath                = new PdnGraphicsPath();
     this.continuation            = new PdnGraphicsPath();
     this.continuationCombineMode = CombineMode.Xor;
     this.cumulativeTransform     = new Matrix();
     this.cumulativeTransform.Reset();
     this.interimTransform = new Matrix();
     this.interimTransform.Reset();
 }
Exemple #19
0
 public Data()
 {
     BasePath                = new PdnGraphicsPath();
     ContinuationPath        = new PdnGraphicsPath();
     ContinuationCombineMode = CombineMode.Xor;
     CumulativeTransform     = new Matrix();
     CumulativeTransform.Reset();
     InterimTransform = new Matrix();
     InterimTransform.Reset();
 }
Exemple #20
0
        private PdnGraphicsPath GetPath()
        {
            if (this.path == null)
            {
                // TODO: FromRegion() is a VERY expensive call!
                PdnGraphicsPath newPath = PdnGraphicsPath.FromRegion(this.region);
                SetPathField(newPath);
            }

            return(this.shadowPath);
        }
Exemple #21
0
 public PdnGraphicsPath CreatePixelatedPath()
 {
     using (PdnGraphicsPath path = CreatePath())
     {
         using (PdnRegion region = new PdnRegion(path))
         {
             PdnGraphicsPath pixellatedPath = PdnGraphicsPath.FromRegion(region);
             return(pixellatedPath);
         }
     }
 }
Exemple #22
0
        private void DrawSelectionOutline(Graphics g, PdnGraphicsPath outline)
        {
            if (outline == null)
            {
                return;
            }

            if (outlinePen1 == null)
            {
                outlinePen1           = new Pen(Color.FromArgb(160, Color.Black), 1.0f);
                outlinePen1.Alignment = PenAlignment.Outset;
                outlinePen1.LineJoin  = LineJoin.Bevel;
                outlinePen1.Width     = -1;
            }

            if (outlinePen2 == null)
            {
                outlinePen2             = new Pen(Color.White, 1.0f);
                outlinePen2.Alignment   = PenAlignment.Outset;
                outlinePen2.LineJoin    = LineJoin.Bevel;
                outlinePen2.MiterLimit  = 2;
                outlinePen2.Width       = -1;
                outlinePen2.DashStyle   = DashStyle.Dash;
                outlinePen2.DashPattern = new float[] { 4, 4 };
                outlinePen2.Color       = Color.White;
                outlinePen2.DashOffset  = 4.0f;
            }

            PixelOffsetMode oldPOM = g.PixelOffsetMode;

            g.PixelOffsetMode = PixelOffsetMode.None;

            SmoothingMode oldSM = g.SmoothingMode;

            g.SmoothingMode = SmoothingMode.AntiAlias;

            outline.Draw(g, outlinePen1);

            float offset = (float)((double)dancingAntsT / OwnerList.ScaleFactor.Ratio);

            outlinePen2.DashOffset += offset;

            if (whiteOpacity != 0)
            {
                outlinePen2.Color = Color.FromArgb(whiteOpacity, Color.White);
                outline.Draw(g, outlinePen2);
            }

            outlinePen2.DashOffset -= offset;

            g.SmoothingMode   = oldSM;
            g.PixelOffsetMode = oldPOM;
        }
Exemple #23
0
        public PdnGraphicsPath CreatePath(bool applyInterimTransform)
        {
            lock (this.syncRoot)
            {
                PdnGraphicsPath returnPath = PdnGraphicsPath.Combine(this.data.basePath, this.data.continuationCombineMode, this.data.continuation);

                if (applyInterimTransform)
                {
                    returnPath.Transform(this.data.interimTransform);
                }

                return(returnPath);
            }
        }
Exemple #24
0
 public void CommitContinuation()
 {
     lock (this.syncRoot)
     {
         OnChanging();
         this.data.continuation.CloseAllFigures();
         PdnGraphicsPath newBasePath = CreatePath();
         this.data.basePath.Dispose();
         this.data.basePath = newBasePath;
         this.data.continuation.Reset();
         this.data.continuationCombineMode = CombineMode.Xor;
         OnChanged();
     }
 }
Exemple #25
0
        private void DrawSelectionTinting(Graphics g, PdnGraphicsPath outline)
        {
            if (outline == null)
            {
                return;
            }

            CompositingMode oldCM = g.CompositingMode;

            g.CompositingMode = CompositingMode.SourceOver;

            SmoothingMode oldSM = g.SmoothingMode;

            g.SmoothingMode = SmoothingMode.AntiAlias;

            PixelOffsetMode oldPOM = g.PixelOffsetMode;

            g.PixelOffsetMode = PixelOffsetMode.None;

            Region     oldClipRegion = null;
            RectangleF outlineBounds = outline.GetBounds();

            if (outlineBounds.Left < 0 ||
                outlineBounds.Top < 0 ||
                outlineBounds.Right >= this.SourceSize.Width ||
                outlineBounds.Bottom >= this.SourceSize.Height)
            {
                oldClipRegion = g.Clip;

                Region newClipRegion = oldClipRegion.Clone();
                newClipRegion.Intersect(new Rectangle(0, 0, this.SourceSize.Width, this.SourceSize.Height));
                g.Clip = newClipRegion;
                newClipRegion.Dispose();
            }

            g.FillPath(InteriorBrush, outline);

            if (oldClipRegion != null)
            {
                g.Clip = oldClipRegion;
                oldClipRegion.Dispose();
            }

            g.PixelOffsetMode = oldPOM;
            g.SmoothingMode   = oldSM;
            g.CompositingMode = oldCM;
        }
        /// <summary>
        /// Constructs a MaskSurface by copying the given region-of-interest from an Image.
        /// </summary>
        /// <param name="source">The Surface to copy pixels from.</param>
        /// <param name="roi">Defines the Region from which to copy pixels from the Image.</param>
        public MaskedSurface(Surface source, PdnRegion roi)
        {
            PdnRegion roiClipped = (PdnRegion)roi.Clone();

            roiClipped.Intersect(source.Bounds);

            Rectangle boundsClipped = roiClipped.GetBoundsInt();

            this.surface = new Surface(boundsClipped.Size);
            this.surface.Clear(ColorBgra.FromUInt32(0x00ffffff));

            Rectangle rect      = boundsClipped;
            Point     dstOffset = new Point(rect.X - boundsClipped.X, rect.Y - boundsClipped.Y);

            this.surface.CopySurface(source, dstOffset, rect);

            this.region = roiClipped;
            SetPathField(PdnGraphicsPath.FromRegion(this.region));
        }
Exemple #27
0
        /// <summary>
        /// When we zoom in, we want to "stair-step" the selected path.
        /// </summary>
        /// <returns></returns>
        private PdnGraphicsPath GetZoomInPath()
        {
            lock (this.SyncRoot)
            {
                if (this.zoomInSelectedPath == null)
                {
                    if (this.selectedPath == null)
                    {
                        this.zoomInSelectedPath = new PdnGraphicsPath();
                    }
                    else
                    {
                        this.zoomInSelectedPath = this.selection.CreatePixelatedPath();
                    }
                }

                return(this.zoomInSelectedPath);
            }
        }
Exemple #28
0
        private void DrawSelection(Graphics gdiG, PdnGraphicsPath outline)
        {
            if (outline == null)
            {
                return;
            }

            float ratio = (float)OwnerList.ScaleFactor.Ratio;

            gdiG.ScaleTransform(ratio, ratio);

            if (EnableSelectionTinting)
            {
                PdnGraphicsPath outline2;

                if (invertedTinting)
                {
                    outline2 = (PdnGraphicsPath)outline.Clone();
                    outline2.AddRectangle(new Rectangle(-1, -1, this.SourceSize.Width + 1, this.SourceSize.Height + 1));
                    outline2.CloseAllFigures();
                }
                else
                {
                    outline2 = outline;
                }

                DrawSelectionTinting(gdiG, outline2);

                if (invertedTinting)
                {
                    outline2.Dispose();
                }
            }

            if (EnableSelectionOutline)
            {
                DrawSelectionOutline(gdiG, outline);
            }

            gdiG.ScaleTransform(1 / ratio, 1 / ratio);
        }
Exemple #29
0
        public override void RenderToGraphics(Graphics g, Point offset)
        {
            double start = timer.GetTickCountDouble();

            lock (SyncRoot)
            {
                PdnGraphicsPath path = GetAppropriateRenderPath();

                if (path == null || path.IsEmpty)
                {
                    this.render = false; // will be reset next time selection changes
                }
                else
                {
                    g.TranslateTransform(-offset.X, -offset.Y);
                    DrawSelection(g, path);
                }

                double end = timer.GetTickCountDouble();
                this.renderTime += (end - start);
            }
        }
Exemple #30
0
        /// <summary>
        /// Constructs a MaskSurface by copying the given region-of-interest from an Image.
        /// </summary>
        /// <param name="source">The Surface to copy pixels from.</param>
        /// <param name="roi">Defines the Region from which to copy pixels from the Image.</param>
        public MaskedSurface(Surface source, PdnRegion roi)
        {
            PdnRegion roiClipped = (PdnRegion)roi.Clone();

            roiClipped.Intersect(source.Bounds);

            Rectangle boundsClipped = roiClipped.GetBoundsInt();

            this.SurfaceReadOnly = new Surface(boundsClipped.Size);
            this.SurfaceReadOnly.Clear(ColorBgra.FromUInt32(0x00ffffff));

            Rectangle rect      = boundsClipped;
            Point     dstOffset = new Point(rect.X - boundsClipped.X, rect.Y - boundsClipped.Y);

            this.SurfaceReadOnly.CopySurface(source, dstOffset, rect);

            this.region = roiClipped;
            // TODO: FromRegion() is a VERY expensive call for what we are doing!
            PdnGraphicsPath newPath = PdnGraphicsPath.FromRegion(this.region);

            SetPathField(newPath);
        }
        /// <summary>
        /// Creates a graphics path from the given stencil buffer. It should be filled with 'true' values
        /// to indicate the areas that should be outlined.
        /// </summary>
        /// <param name="stencil">The stencil buffer to read from. NOTE: The contents of this will be destroyed when this method returns.</param>
        /// <param name="bounds">The bounding box within the stencil buffer to limit discovery to.</param>
        /// <returns>A PdnGraphicsPath with traces that outline the various areas from the given stencil buffer.</returns>
        public unsafe static PdnGraphicsPath PathFromStencil(IBitVector2D stencil, Rectangle bounds)
        {
            if (stencil.IsEmpty)
            {
                return(new PdnGraphicsPath());
            }

            PdnGraphicsPath ret   = new PdnGraphicsPath();
            Point           start = bounds.Location;
            Vector <Point>  pts   = new Vector <Point>();
            int             count = 0;

            // find all islands
            while (true)
            {
                bool startFound = false;

                while (true)
                {
                    if (stencil[start])
                    {
                        startFound = true;
                        break;
                    }

                    ++start.X;

                    if (start.X >= bounds.Right)
                    {
                        ++start.Y;
                        start.X = bounds.Left;

                        if (start.Y >= bounds.Bottom)
                        {
                            break;
                        }
                    }
                }

                if (!startFound)
                {
                    break;
                }

                pts.Clear();
                Point last  = new Point(start.X, start.Y + 1);
                Point curr  = new Point(start.X, start.Y);
                Point next  = curr;
                Point left  = Point.Empty;
                Point right = Point.Empty;

                // trace island outline
                while (true)
                {
                    left.X = ((curr.X - last.X) + (curr.Y - last.Y) + 2) / 2 + curr.X - 1;
                    left.Y = ((curr.Y - last.Y) - (curr.X - last.X) + 2) / 2 + curr.Y - 1;

                    right.X = ((curr.X - last.X) - (curr.Y - last.Y) + 2) / 2 + curr.X - 1;
                    right.Y = ((curr.Y - last.Y) + (curr.X - last.X) + 2) / 2 + curr.Y - 1;

                    if (bounds.Contains(left) && stencil[left])
                    {
                        // go left
                        next.X += curr.Y - last.Y;
                        next.Y -= curr.X - last.X;
                    }
                    else if (bounds.Contains(right) && stencil[right])
                    {
                        // go straight
                        next.X += curr.X - last.X;
                        next.Y += curr.Y - last.Y;
                    }
                    else
                    {
                        // turn right
                        next.X -= curr.Y - last.Y;
                        next.Y += curr.X - last.X;
                    }

                    if (Math.Sign(next.X - curr.X) != Math.Sign(curr.X - last.X) ||
                        Math.Sign(next.Y - curr.Y) != Math.Sign(curr.Y - last.Y))
                    {
                        pts.Add(curr);
                        ++count;
                    }

                    last = curr;
                    curr = next;

                    if (next.X == start.X && next.Y == start.Y)
                    {
                        break;
                    }
                }

                Point[]    points = pts.ToArray();
                Scanline[] scans  = Utility.GetScans(points);

                foreach (Scanline scan in scans)
                {
                    stencil.Invert(scan);
                }

                ret.AddLines(points);
                ret.CloseFigure();
            }

            return(ret);
        }
Exemple #32
0
        public PdnGraphicsPath CreatePath(bool applyInterimTransform)
        {
            lock (this.syncRoot)
            {
                PdnGraphicsPath returnPath;

                switch (this.data.continuationCombineMode)
                {
                    case CombineMode.Complement:
                    case CombineMode.Intersect:
                        throw new NotSupportedException("Complement and Intersect are not supported");

                    case CombineMode.Replace:
                        returnPath = this.data.continuation.Clone();
                        break;

                    case CombineMode.Xor:
                        returnPath = this.data.basePath.Clone();
                        returnPath.CloseAllFigures();
                        returnPath.AddPath(this.data.continuation, false);
                        break;

                    case CombineMode.Union:
                        if (this.data.basePath.IsEmpty)
                        {
                            goto case CombineMode.Replace;
                        }
                        else
                        {
                            using (PdnRegion baseRegion = new PdnRegion(this.data.basePath))
                            {
                                using (PdnRegion continuationRegion = new PdnRegion(this.data.continuation))
                                {
                                    returnPath = PdnGraphicsPath.FromRegions(baseRegion, CombineMode.Union, continuationRegion);
                                }
                            }
                        }

                        break;

                    case CombineMode.Exclude:
                        if (this.data.basePath.IsEmpty)
                        {
                            returnPath = new PdnGraphicsPath();
                        }
                        else
                        {
                            using (PdnRegion baseRegion = new PdnRegion(this.data.basePath))
                            {
                                using (PdnRegion continuationRegion = new PdnRegion(this.data.continuation))
                                {
                                    returnPath = PdnGraphicsPath.FromRegions(baseRegion, CombineMode.Exclude, continuationRegion);
                                }
                            }
                        }

                        break;

                    default:
                        throw new InvalidEnumArgumentException();
                }

                if (applyInterimTransform)
                {
                    returnPath.Transform(this.data.interimTransform);
                }

                return returnPath;
            }
        }
        /// <summary>
        /// Found on Google Groups when searching for "Region.Union" while looking
        /// for bugs:
        /// ---
        /// Hello,
        /// 
        /// I did not run your code, but I know Region.Union is flawed in both 1.0 and
        /// 1.1, so I assume it is in the gdi+ unmanged code dll.  The best workaround,
        /// in terms of speed, is to use a PdnGraphicsPath, but it must be a path with
        /// FillMode = FillMode.Winding. You add the rectangles to the path, then you do
        /// union onto an empty region with the path. The important point is to do only
        /// one union call on a given empty region. We created a "super region" object
        /// to hide all these bugs and optimize clipping operations. In fact, it is much
        /// faster to use the path than to call Region.Union for each rectangle.
        /// 
        /// Too bad about Region.Union. A lot of people will hit this bug, as it is
        /// essential in high-performance animation.
        /// 
        /// Regards,
        /// Frank Hileman
        /// Prodige Software Corporation
        /// ---
        /// </summary>
        /// <param name="rectsF"></param>
        /// <param name="startIndex"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static PdnRegion RectanglesToRegion(RectangleF[] rectsF, int startIndex, int length)
        {
            PdnRegion region;

            if (rectsF == null || rectsF.Length == 0 || length == 0)
            {
                region = PdnRegion.CreateEmpty();
            }
            else
            {
                using (PdnGraphicsPath path = new PdnGraphicsPath())
                {
                    path.FillMode = FillMode.Winding;

                    if (startIndex == 0 && length == rectsF.Length)
                    {
                        path.AddRectangles(rectsF);
                    }
                    else
                    {
                        for (int i = startIndex; i < startIndex + length; ++i)
                        {
                            path.AddRectangle(rectsF[i]);
                        }
                    }

                    region = new PdnRegion(path);
                }
            }

            return region;
        }
Exemple #34
0
 public PdnRegion(PdnGraphicsPath pdnPath)
     : this(pdnPath.GetRegionCache())
 {
 }
Exemple #35
0
        public static PdnGraphicsPath FromRegion(PdnRegion region)
        {
            Rectangle[] scans = region.GetRegionScansReadOnlyInt();

            if (scans.Length == 1)
            {
                PdnGraphicsPath path = new PdnGraphicsPath();
                path.AddRectangle(scans[0]);
                path.CloseFigure();
                return path;
            }
            else
            {
                Rectangle bounds = region.GetBoundsInt();
                BitVector2D stencil = new BitVector2D(bounds.Width, bounds.Height);

                for (int i = 0; i < scans.Length; ++i)
                {
                    Rectangle rect = scans[i];
                    rect.X -= bounds.X;
                    rect.Y -= bounds.Y;

                    stencil.SetUnchecked(rect, true);
                }

                PdnGraphicsPath path = PathFromStencil(stencil, new Rectangle(0, 0, stencil.Width, stencil.Height));

                using (Matrix matrix = new Matrix())
                {
                    matrix.Reset();
                    matrix.Translate(bounds.X, bounds.Y);
                    path.Transform(matrix);
                }

                return path;
            }
        }
Exemple #36
0
        /// <summary>
        /// Creates a graphics path from the given stencil buffer. It should be filled with 'true' values
        /// to indicate the areas that should be outlined.
        /// </summary>
        /// <param name="stencil">The stencil buffer to read from. NOTE: The contents of this will be destroyed when this method returns.</param>
        /// <param name="bounds">The bounding box within the stencil buffer to limit discovery to.</param>
        /// <returns>A PdnGraphicsPath with traces that outline the various areas from the given stencil buffer.</returns>
        public unsafe static PdnGraphicsPath PathFromStencil(IBitVector2D stencil, Rectangle bounds)
        {
            if (stencil.IsEmpty)
            {
                return new PdnGraphicsPath();
            }

            PdnGraphicsPath ret = new PdnGraphicsPath();
            Point start = bounds.Location;
            Vector<Point> pts = new Vector<Point>();
            int count = 0;

            // find all islands
            while (true) 
            {
                bool startFound = false;

                while (true)
                {
                    if (stencil[start])
                    {
                        startFound = true;
                        break;
                    }

                    ++start.X;

                    if (start.X >= bounds.Right)
                    {
                        ++start.Y;
                        start.X = bounds.Left;

                        if (start.Y >= bounds.Bottom)
                        {
                            break;
                        }
                    }
                }
            
                if (!startFound)
                {
                    break;
                }

                pts.Clear();
                Point last = new Point(start.X, start.Y + 1);
                Point curr = new Point(start.X, start.Y);
                Point next = curr;
                Point left = Point.Empty;
                Point right = Point.Empty;
            
                // trace island outline
                while (true)
                {
                    left.X = ((curr.X - last.X) + (curr.Y - last.Y) + 2) / 2 + curr.X - 1;
                    left.Y = ((curr.Y - last.Y) - (curr.X - last.X) + 2) / 2 + curr.Y - 1;

                    right.X = ((curr.X - last.X) - (curr.Y - last.Y) + 2) / 2 + curr.X - 1;
                    right.Y = ((curr.Y - last.Y) + (curr.X - last.X) + 2) / 2 + curr.Y - 1;

                    if (bounds.Contains(left) && stencil[left])
                    {
                        // go left
                        next.X += curr.Y - last.Y;
                        next.Y -= curr.X - last.X;
                    }
                    else if (bounds.Contains(right) && stencil[right])
                    {
                        // go straight
                        next.X += curr.X - last.X;
                        next.Y += curr.Y - last.Y;
                    }
                    else
                    {
                        // turn right
                        next.X -= curr.Y - last.Y;
                        next.Y += curr.X - last.X;
                    }

                    if (Math.Sign(next.X - curr.X) != Math.Sign(curr.X - last.X) ||
                        Math.Sign(next.Y - curr.Y) != Math.Sign(curr.Y - last.Y))
                    {
                        pts.Add(curr);
                        ++count;
                    }

                    last = curr;
                    curr = next;

                    if (next.X == start.X && next.Y == start.Y)
                    {
                        break;
                    }
                }

                Point[] points = pts.ToArray();
                Scanline[] scans = Utility.GetScans(points);

                foreach (Scanline scan in scans)
                {
                    stencil.Invert(scan);
                }

                ret.AddLines(points);
                ret.CloseFigure();
            }

            return ret;
        }
        private void DrawSelectionTinting(Graphics g, PdnGraphicsPath outline)
        {
            if (outline == null)
            {
                return;
            }

            CompositingMode oldCM = g.CompositingMode;
            g.CompositingMode = CompositingMode.SourceOver;

            SmoothingMode oldSM = g.SmoothingMode;
            g.SmoothingMode = SmoothingMode.AntiAlias;

            PixelOffsetMode oldPOM = g.PixelOffsetMode;
            g.PixelOffsetMode = PixelOffsetMode.None;

            Region oldClipRegion = null;
            RectangleF outlineBounds = outline.GetBounds();

            if (outlineBounds.Left < 0 ||
                outlineBounds.Top < 0 ||
                outlineBounds.Right >= this.SourceSize.Width ||
                outlineBounds.Bottom >= this.SourceSize.Height)
            {
                oldClipRegion = g.Clip;

                Region newClipRegion = oldClipRegion.Clone();
                newClipRegion.Intersect(new Rectangle(0, 0, this.SourceSize.Width, this.SourceSize.Height));
                g.Clip = newClipRegion;
                newClipRegion.Dispose();
            }
             
            g.FillPath(InteriorBrush, outline);

            if (oldClipRegion != null)
            {
                g.Clip = oldClipRegion;
                oldClipRegion.Dispose();
            }

            g.PixelOffsetMode = oldPOM;
            g.SmoothingMode = oldSM;
            g.CompositingMode = oldCM;
        }
Exemple #38
0
        public static PdnGraphicsPath Combine(PdnGraphicsPath subjectPath, CombineMode combineMode, PdnGraphicsPath clipPath)
        {
            switch (combineMode)
            {
                case CombineMode.Complement:
                    return Combine(clipPath, CombineMode.Exclude, subjectPath);

                case CombineMode.Replace:
                    return clipPath.Clone();

                case CombineMode.Xor:
                case CombineMode.Intersect:
                case CombineMode.Union:
                case CombineMode.Exclude:
                    if (subjectPath.IsEmpty && clipPath.IsEmpty)
                    {
                        return new PdnGraphicsPath(); // empty path
                    }
                    else if (subjectPath.IsEmpty)
                    {
                        switch (combineMode)
                        {
                            case CombineMode.Xor:
                            case CombineMode.Union:
                                return clipPath.Clone();

                            case CombineMode.Intersect:
                            case CombineMode.Exclude:
                                return new PdnGraphicsPath();

                            default:
                                throw new InvalidEnumArgumentException();
                        }
                    }
                    else if (clipPath.IsEmpty)
                    {
                        switch (combineMode)
                        {
                            case CombineMode.Exclude:
                            case CombineMode.Xor:
                            case CombineMode.Union:
                                return subjectPath.Clone();

                            case CombineMode.Intersect:
                                return new PdnGraphicsPath();

                            default:
                                throw new InvalidEnumArgumentException();
                        }
                    }
                    else
                    {
                        GraphicsPath resultPath = PdnGraphics.ClipPath(subjectPath, combineMode, clipPath);
                        return new PdnGraphicsPath(resultPath);
                    }

                default:
                    throw new InvalidEnumArgumentException();
            }
        }
Exemple #39
0
        // only works if base is empty 
        public void SetContinuation(PdnGraphicsPath path, CombineMode combineMode, bool takeOwnership)
        {
            lock (this.syncRoot)
            {
                if (!this.data.basePath.IsEmpty)
                {
                    throw new InvalidOperationException("base path must be empty to use this overload of SetContinuation");
                }

                OnChanging();

                CommitInterimTransform();
                ResetCumulativeTransform();

                this.data.continuationCombineMode = combineMode;

                if (takeOwnership)
                {
                    this.data.continuation.Dispose();
                    this.data.continuation = path;
                }
                else
                {
                    this.data.continuation.Reset();
                    this.data.continuation.AddPath(path, false);
                }

                OnChanged();
            }
        }
 public GraphicsPathWrapper(PdnGraphicsPath path)
 {
     points = (PointF[])path.PathPoints.Clone();
     types = (byte[])path.PathTypes.Clone();
     fillMode = path.FillMode;
 }
 public PdnGraphicsPath Clone()
 {
     PdnGraphicsPath path = new PdnGraphicsPath((GraphicsPath)gdiPath.Clone());
     path.tooComplex = this.tooComplex;
     return path;
 }
        private void OnSelectionChanged(object sender, EventArgs e)
        {
            this.render = true;
            PdnGraphicsPath path = this.selection.CreatePath(); //this.selection.GetPathReadOnly();

            if (this.selectedPath == null)
            {
                Invalidate();
            }
            else
            {
                this.selectedPath.Dispose(); //
                this.selectedPath = null;
            }

            bool fullInvalidate = false;
            this.selectedPath = path;

            // HACK: Sometimes the selection leaves behind artifacts. So do a full invalidate
            //       every 1 second.
            if (this.selectedPath.PointCount > 10 && (DateTime.Now - lastFullInvalidate > new TimeSpan(0, 0, 0, 1, 0)))
            {
                fullInvalidate = true;
            }

            // if we're moving to a simpler selection region ...
            if (this.selectedPath == null)// || this.selectedPath.PointCount == 0)
            {   
                // then invalidate everything
                fullInvalidate = true;
            }
            else
            {   
                // otherwise, be intelligent about it and only redraw the 'new' area
                PdnRegion xorMe = new PdnRegion(this.selectedPath);
                selectionRedrawInterior.Xor(xorMe);
                xorMe.Dispose();
            }

            float ratio = 1.0f / (float)OwnerList.ScaleFactor.Ratio;
            int ratioInt = (int)Math.Ceiling(ratio);

            if (this.Visible && (this.EnableSelectionOutline || this.EnableSelectionTinting))
            {
                using (PdnRegion simplified = Utility.SimplifyAndInflateRegion(selectionRedrawInterior, Utility.DefaultSimplificationFactor, 2 * ratioInt))
                {
                    Invalidate(simplified);
                }
            }

            if (fullInvalidate)
            {
                Rectangle rect = Rectangle.Inflate(Rectangle.Truncate(selectionRedrawOutline.GetBounds2()), 1, 1);
                Invalidate(rect);
                lastFullInvalidate = DateTime.Now;
            }
            

            this.selectionRedrawInterior.Dispose();
            this.selectionRedrawInterior = null;

            if (this.zoomInSelectedPath != null)
            {
                this.zoomInSelectedPath.Dispose();
                this.zoomInSelectedPath = null;
            }

            this.simplifiedRegionForTimer = null;

            // prepare for next call
            if (this.selectedPath != null && !this.selectedPath.IsEmpty)
            {
                this.selectionRedrawOutline = (PdnGraphicsPath)this.selectedPath.Clone();
                this.selectionRedrawInterior = new PdnRegion(this.selectedPath);
            }
            else
            {
                if (invertedTinting)
                {
                    this.selectionRedrawInterior = new PdnRegion(new Rectangle(0, 0, this.SourceSize.Width, this.SourceSize.Height));
                }
                else
                {
                    this.selectionRedrawInterior = new PdnRegion();
                    this.selectionRedrawInterior.MakeEmpty();
                }

                Invalidate();
                this.selectionRedrawOutline = new PdnGraphicsPath();
            }
        }
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.components != null) 
                {
                    this.components.Dispose();
                    this.components = null;
                }

                if (this.selectionTimer != null)
                {
                    this.selectionTimer.Dispose();
                    this.selectionTimer = null;
                }

                if (this.zoomInSelectedPath != null)
                {
                    this.zoomInSelectedPath.Dispose();
                    this.zoomInSelectedPath = null;
                }
            }

            base.Dispose (disposing);
        }
Exemple #44
0
            public void Dispose(bool disposing)
            {
                if (disposing)
                {
                    if (this.basePath != null)
                    {
                        this.basePath.Dispose();
                        this.basePath = null;
                    }

                    if (this.continuation != null)
                    {
                        this.continuation.Dispose();
                        this.continuation = null;
                    }

                    if (this.cumulativeTransform != null)
                    {
                        this.cumulativeTransform.Dispose();
                        this.cumulativeTransform = null;
                    }

                    if (this.interimTransform != null)
                    {
                        this.interimTransform.Dispose();
                        this.interimTransform = null;
                    }
                }
            }
Exemple #45
0
        static void Main(string[] args)
        {
            for (int i = 0; i < args.Length; i++)
            {
                switch (args[i])
                {
                    case "/proc":
                        if (i + 1 == args.Length)
                        {
                            Console.WriteLine("Use /proc <N> to specify number of processors");
                            return;
                        }

                        int numProcs;

                        if (Int32.TryParse(args[i + 1], out numProcs))
                        {
                            // only increment i if successful b/c we're going to continue the run
                            // with the default # of processors and don't want to automatically 
                            // eat the next parameter.
                            ++i;
                            Processor.LogicalCpuCount = numProcs;
                        }
                        else
                        {
                            Console.WriteLine("You must specify a integer for /proc <N>, continuing with default");
                        }
                        break;

                    case "/image":
                        if (i + 1 == args.Length)
                        {
                            Console.WriteLine("Use /image <filename> to specify a file to perform benchmark with");
                            return;
                        }

                        ++i;
                        benchmarkImageName = args[i];

                        if (!System.IO.File.Exists(benchmarkImageName))
                        {
                            Console.WriteLine("Specified image doesn't exist");
                            return;
                        }
                        break;

                    case "/tsv":
                        useTsvOutput = true;
                        break;

                    case "/?":
                        PrintHelp();
                        return;

                    default:
                        break;
                }
            }

            //Processor.LogicalCpuCount = 1;
            Console.WriteLine("PdnBench v" + PdnInfo.GetVersion());
            Console.WriteLine("Running in " + (8 * Marshal.SizeOf(typeof(IntPtr))) + "-bit mode on Windows " +
                Environment.OSVersion.Version.ToString() + " " +
                OS.Revision + (OS.Revision.Length > 0 ? " " : string.Empty) +
                OS.Type + " " +
                Processor.NativeArchitecture.ToString().ToLower());

            Console.WriteLine("Processor: " + Processor.LogicalCpuCount + "x \"" + Processor.CpuName + "\" @ ~" + GetCpuSpeed() + " MHz");
            Console.WriteLine("Memory: " + ((Memory.TotalPhysicalBytes / 1024) / 1024) + " MB");
            Console.WriteLine();

            Console.WriteLine("Using " + Processor.LogicalCpuCount + " threads.");

            ArrayList benchmarks = new ArrayList();

            Document document;

            Console.Write("Loading image ... ");

            Stream imageStream = null;
            try
            {
                imageStream = (defaultImageName == benchmarkImageName) ?
                    Assembly.GetExecutingAssembly().GetManifestResourceStream(benchmarkImageName) :
                    new FileStream(benchmarkImageName, FileMode.Open);

                JpegFileType jft = new JpegFileType();
                document = jft.Load(imageStream);
            }

            finally
            {
                if (imageStream != null)
                {
                    imageStream.Dispose();
                }
            }

            Console.WriteLine("(" + document.Width + " x " + document.Height + ") done");

            Surface surface = ((BitmapLayer)document.Layers[0]).Surface;

#if EFFECTS
            for (double i = 0; i < (2 * Math.PI); i += 70.0 * ((2 * Math.PI) / 360.0))
            {
                benchmarks.Add(
                    new EffectBenchmark("Rotate/Zoom at " + ((i * 180.0) / Math.PI).ToString("F2") + " degrees",
                    3,
                    new PaintDotNet.Effects.RotateZoomEffect(),
                    new PaintDotNet.Effects.RotateZoomEffectConfigToken(
                        true,
                        (float)(Math.PI * 0.3f),
                        (float)((Math.PI * -0.4) + i),
                        50,
                        0.5f,
                        new PointF(-0.2f, 0.3f),
                        false,
                        true),
                        surface));
            }

            for (int i = 1; i <= 4; i += 3)
            {
                for (int j = 10; j < 100; j += 75)
                {
                    benchmarks.Add(
                        new EffectBenchmark(
                            "Oil Painting, brush size = " + i + ", coarseness = " + j,
                            1,
                            new OilPaintingEffect(),
                            new TwoAmountsConfigToken(i, j),
                            surface));
                }
            }

            for (int i = 2; i <= 50; i += i)
            {
                benchmarks.Add(
                    new EffectBenchmark(
                        "Blur with radius of " + i,
                        1,
                        new BlurEffect(),
                        new AmountEffectConfigToken(i),
                        surface));
            }

            for (int i = 1; i <= 4; i += 3)
            {
                benchmarks.Add(
                    new EffectBenchmark(
                        "Sharpen with value of " + i,
                        1,
                        new SharpenEffect(),
                        new AmountEffectConfigToken(i),
                        surface));
            }

            benchmarks.Add(
                new EffectBenchmark(
                    "Auto-Levels",
                    50,
                    new AutoLevelEffect(),
                    null,
                    surface));

            for (int i = 81; i >= 5; i /= 3)
            {
                benchmarks.Add(
                    new EffectBenchmark(
                        "Clouds, roughness = " + i,
                        2,
                        new CloudsEffect(),
                        new CloudsEffectConfigToken(50, i, 12345, new UserBlendOps.NormalBlendOp()),
                        surface));
            }

            for (int i = 4; i <= 64; i *= 4)
            {
                benchmarks.Add(
                    new EffectBenchmark(
                        "Median, radius " + i,
                        1,
                        new MedianEffect(),
                        new TwoAmountsConfigToken(/*radius*/i, /*roughness*/50),
                        surface));
            }

            for (int i = 4; i <= 64; i *= 4)
            {
                benchmarks.Add(
                   new EffectBenchmark(
                       "Unfocus, radius " + i,
                       1,
                       new UnfocusEffect(),
                       new AmountEffectConfigToken(i),
                        surface));
            }

            benchmarks.Add(
                new EffectBenchmark(
                    "Motion Blur, Horizontal",
                    1,
                    new MotionBlurEffect(),
                    new MotionBlurEffectConfigToken(0, 100, true),
                        surface));

            benchmarks.Add(
                new EffectBenchmark(
                    "Motion Blur, Vertical",
                    1,
                    new MotionBlurEffect(),
                    new MotionBlurEffectConfigToken(90, 100, true),
                        surface));

#endif

            Surface dst = new Surface(surface.Width * 4, surface.Height * 4);

#if RESIZE
            // Resize benchmarks
            for (int i = 1; i < 8; i += 2)
            {
                int newWidth = i * (dst.Width / 8);
                int newHeight = i * (dst.Height / 8);

                Surface dstWindow = dst.CreateWindow(new Rectangle(0, 0, newWidth, newHeight));
                benchmarks.Add(new ResizeBenchmark("Resize from " + surface.Width + "x" + surface.Height + " to " + newWidth + "x" + newHeight, surface, dstWindow));
                benchmarks.Add(new ResizeBenchmark("Resize from " + newWidth + "x" + newHeight + " to " + surface.Width + "x" + surface.Height, dstWindow, surface));
            }
#endif

#if GRADIENT
            // Gradient benchmarks
            benchmarks.Add(new GradientBenchmark(
                "Linear reflected gradient @ " + dst.Width + "x" + dst.Height + " (5x)",
                dst,
                new GradientRenderers.LinearReflected(false, new UserBlendOps.NormalBlendOp()),
                2));

            benchmarks.Add(new GradientBenchmark(
                "Conical gradient @ " + dst.Width + "x" + dst.Height + " (5x)",
                dst,
                new GradientRenderers.Conical(false, new UserBlendOps.NormalBlendOp()),
                2));

            benchmarks.Add(new GradientBenchmark(
                "Radial gradient @ " + dst.Width + "x" + dst.Height + " (5x)",
                dst,
                new GradientRenderers.Radial(false, new UserBlendOps.NormalBlendOp()),
                2));
#endif

#if COMPOSITION
            // Composition benchmarks
            Document doc1 = new Document(surface.Size);
            BitmapLayer layer1 = Layer.CreateBackgroundLayer(doc1.Width, doc1.Height);
            layer1.Surface.CopySurface(surface);
            doc1.Layers.Add(layer1);
            doc1.Layers.Add(layer1.Clone());
            doc1.Layers.Add(layer1.Clone());
            doc1.Layers.Add(layer1.Clone());

            benchmarks.Add(new CompositionBenchmark("Compositing one layer, Normal blend mode, 255 opacity (" + CompositionBenchmark.Iterations + "x)",
                doc1,
                surface,
                delegate(int layerIndex, Layer layer)
                {
                    if (layerIndex == 0)
                    {
                        layer.Visible = true;
                        layer.Opacity = 255;
                        ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp());
                    }
                    else
                    {
                        layer.Visible = false;
                    }
                }));

            benchmarks.Add(new CompositionBenchmark("Compositing one layer, Normal blend mode, 128 opacity (" + CompositionBenchmark.Iterations + "x)",
                doc1,
                surface,
                delegate(int layerIndex, Layer layer)
                {
                    if (layerIndex == 0)
                    {
                        layer.Visible = true;
                        layer.Opacity = 128;
                        ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp());
                    }
                    else
                    {
                        layer.Visible = false;
                    }
                }));

            benchmarks.Add(new CompositionBenchmark("Compositing four layers, Normal blend mode, 255 opacity (" + CompositionBenchmark.Iterations + "x)",
                doc1,
                surface,
                delegate(int layerIndex, Layer layer)
                {
                    layer.Visible = true;
                    layer.Opacity = 255;
                    ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp());
                }));

            benchmarks.Add(new CompositionBenchmark("Compositing four layers, Normal blend mode, 255 (layer 0) and 128 (layer 1-3) opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface,
                delegate(int layerIndex, Layer layer)
                {
                    layer.Visible = true;
                    layer.Opacity = 128;
                    ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp());
                }));

            benchmarks.Add(new CompositionBenchmark("Compositing four layers, Normal blend mode, 128 opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface,
                delegate(int layerIndex, Layer layer)
                {
                    layer.Visible = true;
                    layer.Opacity = 128;
                    ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp());
                }));

            benchmarks.Add(new CompositionBenchmark("Compositing three layers, Normal+Multiply+Overlay blending, 150+255+170 opacity (" + CompositionBenchmark.Iterations + "x)", doc1, surface,
                delegate(int layerIndex, Layer layer)
                {
                    if (layerIndex == 0)
                    {
                        layer.Visible = true;
                        layer.Opacity = 150;
                        ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.NormalBlendOp());
                    }
                    else if (layerIndex == 1)
                    {
                        layer.Visible = true;
                        layer.Opacity = 255;
                        ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.MultiplyBlendOp());
                    }
                    else if (layerIndex == 2)
                    {
                        layer.Visible = true;
                        layer.Opacity = 170;
                        ((BitmapLayer)layer).SetBlendOp(new UserBlendOps.OverlayBlendOp());
                    }
                    else
                    {
                        layer.Visible = false;
                    }
                }));
#endif

#if TRANSFORM
            // Transform benchmarks
            Matrix m = new Matrix();
            m.Reset();

            MaskedSurface msSimple = new MaskedSurface(surface, new PdnRegion(surface.Bounds)); // simple masked surface

            PdnRegion complexRegion = new PdnRegion(surface.Bounds);

            // cut 4 holes in region 1 to form a complex clipping surface
            for (int x = -1; x < 3; ++x)
            {
                for (int y = -1; y < 3; ++y)
                {
                    int left = (1 + (x * 3)) * (surface.Width / 6);
                    int top = (1 + (x * 3)) * (surface.Height / 6);
                    int right = (2 + (x * 3)) * (surface.Width / 6);
                    int bottom = (2 + (x * 3)) * (surface.Height / 6);

                    Rectangle rect = Rectangle.FromLTRB(left, top, right, bottom);
                    PdnGraphicsPath path = new PdnGraphicsPath();
                    path.AddEllipse(rect);
                    complexRegion.Exclude(path);
                }
            }

            MaskedSurface msComplex = new MaskedSurface(surface, complexRegion);

            benchmarks.Add(new TransformBenchmark("Transform simple surface, no transform, nearest neighbor resampling (" + TransformBenchmark.Iterations + "x)",
                surface,
                msSimple,
                m,
                false));

            benchmarks.Add(new TransformBenchmark("Transform complex surface, no transform, nearest neighbor resampling (" + TransformBenchmark.Iterations + "x)",
                surface,
                msSimple,
                m,
                false));

            benchmarks.Add(new TransformBenchmark("Transform simple surface, no transform, bilinear resampling (" + TransformBenchmark.Iterations + "x)",
                surface,
                msSimple,
                m,
                true));

            benchmarks.Add(new TransformBenchmark("Transform complex surface, no transform, bilinear resampling (" + TransformBenchmark.Iterations + "x)",
                surface,
                msSimple,
                m,
                true));

            Matrix m2 = m.Clone();
            m2.RotateAt(45.0f, new PointF(surface.Width / 2, surface.Height / 2));

            benchmarks.Add(new TransformBenchmark("Transform simple surface, 45 deg. rotation about center, bilinear resampling (" + TransformBenchmark.Iterations + "x)",
                surface,
                msSimple,
                m2,
                true));

            benchmarks.Add(new TransformBenchmark("Transform complex surface, 45 deg. rotation about center, bilinear resampling (" + TransformBenchmark.Iterations + "x)",
                surface,
                msSimple,
                m2,
                true));

            Matrix m3 = m.Clone();
            m3.Scale(0.5f, 0.75f);

            benchmarks.Add(new TransformBenchmark("Transform simple surface, 50% x-scaling 75% y-scaling, bilinear resampling (" + TransformBenchmark.Iterations + "x)",
                surface,
                msSimple,
                m3,
                true));

            benchmarks.Add(new TransformBenchmark("Transform complex surface, 50% x-scaling 75% y-scaling, bilinear resampling (" + TransformBenchmark.Iterations + "x)",
                surface,
                msSimple,
                m3,
                true));
#endif

#if BLIT
            // Blit benchmarks
            benchmarks.Add(new ZoomOutBlitBenchmark("Zoom out, rotated grid multisampling, 66% (" + ZoomOutBlitBenchmark.IterationCount + "x)",
                surface,
                dst,
                new Size((surface.Width * 2) / 3, (surface.Height * 2) / 3)));

            benchmarks.Add(new ZoomOutBlitBenchmark("Zoom out, rotated grid multisampling, 28% (" + ZoomOutBlitBenchmark.IterationCount + "x)",
                surface,
                dst,
                new Size((surface.Width * 28) / 100, (surface.Height * 28) / 100)));

            benchmarks.Add(new ZoomOneToOneBlitBenchmark("Zoom 1:1, straight blit (" + ZoomOneToOneBlitBenchmark.IterationCount + "x)",
                surface,
                dst.CreateWindow(new Rectangle(0, 0, surface.Width, surface.Height))));
#endif

            // Run benchmarks!
            Timing timing = new Timing();
            ulong start = timing.GetTickCount();

            foreach (Benchmark benchmark in benchmarks)
            {
                Console.Write(benchmark.Name + (useTsvOutput ? "\t" : " ... "));
                TimeSpan timeSpan = benchmark.Execute();
                Console.WriteLine(" " + timeSpan.TotalMilliseconds.ToString() + (useTsvOutput ? "\t" : "") + " milliseconds");

                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();
                GC.WaitForPendingFinalizers();
            }

            ulong end = timing.GetTickCount();

            Console.WriteLine();
            Console.WriteLine("Total time: " + (useTsvOutput ? "\t" : "") + (end - start).ToString() + (useTsvOutput ? "\t" : "") + " milliseconds");
            Console.WriteLine();
        }
 private void SetPathField(PdnGraphicsPath newPath)
 {
     this.path = newPath;
     this.shadowPath = newPath.Clone();
 }
        /// <summary>
        /// When we zoom in, we want to "stair-step" the selected path.
        /// </summary>
        /// <returns></returns>
        private PdnGraphicsPath GetZoomInPath()
        {
            lock (this.SyncRoot)
            {
                if (this.zoomInSelectedPath == null)
                {
                    if (this.selectedPath == null)
                    {
                        this.zoomInSelectedPath = new PdnGraphicsPath();
                    }
                    else
                    {
                        this.zoomInSelectedPath = this.selection.CreatePixelatedPath();
                    }
                }

                return this.zoomInSelectedPath;
            }
        }
        public MaskedSurface(Surface source, PdnGraphicsPath path)
        {
            RectangleF boundsF = path.GetBounds();
            Rectangle bounds = Utility.RoundRectangle(boundsF);

            Rectangle boundsClipped = Rectangle.Intersect(bounds, source.Bounds);
            Rectangle boundsRead;

            if (bounds != boundsClipped)
            {
                PdnRegion region = new PdnRegion(path);
                region.Intersect(source.Bounds);
                SetPathField(PdnGraphicsPath.FromRegion(region));
                this.region = region;
                boundsRead = region.GetBoundsInt();
            }
            else
            {
                SetPathField(path.Clone());
                this.region = new PdnRegion(this.path);
                boundsRead = boundsClipped;
            }

            if (boundsRead.Width > 0 && boundsRead.Height > 0)
            {
                this.surface = new Surface(boundsRead.Size);
                this.surface.CopySurface(source, boundsRead);
            }
            else
            {
                this.surface = null;
            }
        }
        private void DrawSelectionOutline(Graphics g, PdnGraphicsPath outline)
        {
            if (outline == null)
            {
                return;
            }

            if (outlinePen1 == null)
            {
                outlinePen1 = new Pen(Color.FromArgb(160, Color.Black), 1.0f);
                outlinePen1.Alignment = PenAlignment.Outset;
                outlinePen1.LineJoin = LineJoin.Bevel;
                outlinePen1.Width = -1;
            }

            if (outlinePen2 == null)
            {
                outlinePen2 = new Pen(Color.White, 1.0f);
                outlinePen2.Alignment = PenAlignment.Outset;
                outlinePen2.LineJoin = LineJoin.Bevel;
                outlinePen2.MiterLimit = 2;
                outlinePen2.Width = -1;
                outlinePen2.DashStyle = DashStyle.Dash;
                outlinePen2.DashPattern = new float[] { 4, 4 };
                outlinePen2.Color = Color.White;
                outlinePen2.DashOffset = 4.0f;
            }

            PixelOffsetMode oldPOM = g.PixelOffsetMode;
            g.PixelOffsetMode = PixelOffsetMode.None;
            
            SmoothingMode oldSM = g.SmoothingMode;
            g.SmoothingMode = SmoothingMode.AntiAlias;

            outline.Draw(g, outlinePen1);

            float offset = (float)((double)dancingAntsT / OwnerList.ScaleFactor.Ratio);
            outlinePen2.DashOffset += offset;

            if (whiteOpacity != 0)
            {
                outlinePen2.Color = Color.FromArgb(whiteOpacity, Color.White);
                outline.Draw(g, outlinePen2);
            }

            outlinePen2.DashOffset -= offset;

            g.SmoothingMode = oldSM;
            g.PixelOffsetMode = oldPOM;
        }
        public void OnDeserialization(object sender)
        {
            threadPool = new PaintDotNet.Threading.ThreadPool();

            if (this.path != null)
            {
                this.shadowPath = this.path.Clone();
            }
        }
        private void DrawSelection(Graphics gdiG, PdnGraphicsPath outline)
        {
            if (outline == null)
            {
                return;
            }

            float ratio = (float)OwnerList.ScaleFactor.Ratio;
            gdiG.ScaleTransform(ratio, ratio);

            if (EnableSelectionTinting)
            {
                PdnGraphicsPath outline2;

                if (invertedTinting)
                {
                    outline2 = (PdnGraphicsPath)outline.Clone();
                    outline2.AddRectangle(new Rectangle(-1, -1, this.SourceSize.Width + 1, this.SourceSize.Height + 1));
                    outline2.CloseAllFigures();
                }
                else
                {
                    outline2 = outline;
                }

                DrawSelectionTinting(gdiG, outline2);

                if (invertedTinting)
                {
                    outline2.Dispose();
                }
            }

            if (EnableSelectionOutline)
            {
                DrawSelectionOutline(gdiG, outline);
            }

            gdiG.ScaleTransform(1 / ratio, 1 / ratio);
        }
        private void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (this.surface != null)
                {
                    this.surface.Dispose();
                    this.surface = null;
                }

                if (this.region != null)
                {
                    this.region.Dispose();
                    this.region = null;
                }

                if (this.path != null)
                {
                    this.path.Dispose();
                    this.path = null;
                }

                if (this.shadowPath != null)
                {
                    this.shadowPath.Dispose();
                    this.shadowPath = null;
                }
            }

            this.disposed = true;
        }