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

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

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Security;

namespace PaintDotNet{
    /// <summary>
    /// Designed as a proxy to the GDI+ Region class, while allowing for a
    /// replacement that won't break code. The main reason for having this
    /// right now is to work around some bugs in System.Drawing.Region,
    /// especially the memory leak in GetRegionScans().
    /// </summary>
    [Serializable]
    public sealed class PdnRegion
        : ISerializable,
          IDisposable
    {
        private object lockObject = new object();
        private Region gdiRegion;
        private bool changed = true;
        private int cachedArea = -1;
        private Rectangle cachedBounds = Rectangle.Empty;
        private RectangleF[] cachedRectsF = null;
        private Rectangle[] cachedRects = null;

        public object SyncRoot
        {
            get
            {
                return lockObject;
            }
        }

        public int GetArea()
        {
            lock (SyncRoot)
            {
                int theCachedArea = cachedArea;

                if (theCachedArea == -1)
                {
                    int ourCachedArea = 0;

                    foreach (Rectangle rect in GetRegionScansReadOnlyInt())
                    {
                        try
                        {
                            ourCachedArea += rect.Width * rect.Height;
                        }

                        catch (System.OverflowException)
                        {
                            ourCachedArea = int.MaxValue;
                            break;
                        }
                    }

                    cachedArea = ourCachedArea;
                    return ourCachedArea;
                }
                else
                {
                    return theCachedArea;
                }
            }
        }

        private bool IsChanged()
        {
            return this.changed;
        }

        private void Changed()
        {
            lock (SyncRoot)
            {
                this.changed = true;
                this.cachedArea = -1;
                this.cachedBounds = Rectangle.Empty;
            }
        }

        private void ResetChanged()
        {
            lock (SyncRoot)
            {
                this.changed = false;
            }
        }

        public PdnRegion()
        {
            this.gdiRegion = new Region();
        }

        public PdnRegion(GraphicsPath path)
        {
            this.gdiRegion = new Region(path);
        }

        public PdnRegion(PdnGraphicsPath pdnPath)
            : this(pdnPath.GetRegionCache())
        {
        }

        public PdnRegion(Rectangle rect)
        {
            this.gdiRegion = new Region(rect);
        }

        public PdnRegion(RectangleF rectF)
        {
            this.gdiRegion = new Region(rectF);
        }

        public PdnRegion(RegionData regionData)
        {
            this.gdiRegion = new Region(regionData);
        }

        public PdnRegion(Region region, bool takeOwnership)
        {
            if (takeOwnership)
            {
                this.gdiRegion = region;
            }
            else
            {
                this.gdiRegion = region.Clone();
            }
        }

        public PdnRegion(Region region)
            : this(region, false)
        {
        }

        private PdnRegion(PdnRegion pdnRegion)
        {
            lock (pdnRegion.SyncRoot)
            {
                this.gdiRegion = pdnRegion.gdiRegion.Clone();
                this.changed = pdnRegion.changed;
                this.cachedArea = pdnRegion.cachedArea;
                this.cachedRectsF = pdnRegion.cachedRectsF; 
                this.cachedRects = pdnRegion.cachedRects;
            }
        }

        // This constructor is used by WrapRegion. The boolean parameter is just
        // there because we already have a parameterless contructor
        private PdnRegion(bool sentinel)
        {
        }

        public static PdnRegion CreateEmpty()
        {
            PdnRegion region = new PdnRegion();
            region.MakeEmpty();
            return region;
        }

        public static PdnRegion WrapRegion(Region region)
        {
            PdnRegion pdnRegion = new PdnRegion(false);
            pdnRegion.gdiRegion = region;
            return pdnRegion;
        }

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (this.disposed)
            {
                throw new ObjectDisposedException("PdnRegion");
            }

            RegionData regionData;

            lock (SyncRoot)
            {
                regionData = this.gdiRegion.GetRegionData();
            }

            byte[] data = regionData.Data;
            info.AddValue("data", data);
        }

        public PdnRegion(SerializationInfo info, StreamingContext context)
        {
            byte[] data = (byte[])info.GetValue("data", typeof(byte[]));

            using (Region region = new Region())
            {
                RegionData regionData = region.GetRegionData();
                regionData.Data = data;
                this.gdiRegion = new Region(regionData);
            }

            this.lockObject = new object();
            this.cachedArea = -1;
            this.cachedBounds = Rectangle.Empty;
            this.changed = true;
            this.cachedRects = null;
            this.cachedRectsF = null;
        }

        public PdnRegion Clone()
        {
            return new PdnRegion(this);
        }

        ~PdnRegion()
        {
            Dispose(false);
        }

        private bool disposed = false;

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    lock (SyncRoot)
                    {
                        gdiRegion.Dispose();
                        gdiRegion = null;
                    }
                }

                disposed = true;
            }
        }

        public Region GetRegionReadOnly()
        {
            return this.gdiRegion;
        }

        public void Complement(GraphicsPath path)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Complement(path);
            }
        }

        public void Complement(Rectangle rect)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Complement(rect);
            }
        }

        public void Complement(RectangleF rectF)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Complement(rectF);
            }
        }

        public void Complement(Region region)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Complement(region);
            }
        }

        public void Complement(PdnRegion region2)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Complement(region2.gdiRegion);
            }
        }

        public void Exclude(GraphicsPath path)
        {
            lock (SyncRoot)
            {
                gdiRegion.Exclude(path);
            }
        }

        public void Exclude(Rectangle rect)
        {
            lock (SyncRoot)
            {
                gdiRegion.Exclude(rect);
            }
        }

        public void Exclude(RectangleF rectF)
        {
            lock (SyncRoot)
            {
                gdiRegion.Exclude(rectF);
            }
        }

        public void Exclude(Region region)
        {
            lock (SyncRoot)
            {
                gdiRegion.Exclude(region);
            }
        }

        public void Exclude(PdnRegion region2)
        {
            lock (SyncRoot)
            {
                gdiRegion.Exclude(region2.gdiRegion);
            }
        }

        public RectangleF GetBounds(Graphics g)
        {
            lock (SyncRoot)
            {
                return gdiRegion.GetBounds(g);
            }
        }

        public RectangleF GetBounds()
        {
            lock (SyncRoot)
            {
                using (SystemLayer.NullGraphics nullGraphics = new SystemLayer.NullGraphics())
                {
                    return gdiRegion.GetBounds(nullGraphics.Graphics);
                }
            }
        }

        public Rectangle GetBoundsInt()
        {
            Rectangle bounds;

            lock (SyncRoot)
            {
                bounds = this.cachedBounds;

                if (bounds == Rectangle.Empty)
                {
                    Rectangle[] rects = GetRegionScansReadOnlyInt();
            
                    if (rects.Length == 0)
                    {
                        return Rectangle.Empty;
                    }

                    bounds = rects[0];

                    for (int i = 1; i < rects.Length; ++i)
                    {
                        bounds = Rectangle.Union(bounds, rects[i]);
                    }

                    this.cachedBounds = bounds;
                }
            }

            return bounds;
        }

        public RegionData GetRegionData()
        {
            lock (SyncRoot)
            {
                return gdiRegion.GetRegionData();
            }
        }

        public RectangleF[] GetRegionScans()
        {
            return (RectangleF[])GetRegionScansReadOnly().Clone();
        }

        /// <summary>
        /// This is an optimized version of GetRegionScans that returns a reference to the array
        /// that is used to cache the region scans. This mitigates performance when this array
        /// is requested many times on an unmodified PdnRegion.
        /// Thus, by using this method you are promising to not modify the array that is returned.
        /// </summary>
        /// <returns></returns>
        public RectangleF[] GetRegionScansReadOnly()
        {
            lock (this.SyncRoot)
            {
                if (this.changed)
                {
                    UpdateCachedRegionScans();
                }

                if (this.cachedRectsF == null)
                {
                    this.cachedRectsF = new RectangleF[cachedRects.Length];

                    for (int i = 0; i < this.cachedRectsF.Length; ++i)
                    {
                        this.cachedRectsF[i] = (RectangleF)this.cachedRects[i];
                    }
                }

                return this.cachedRectsF;
            }
        }

        public Rectangle[] GetRegionScansInt()
        {
            return (Rectangle[])GetRegionScansReadOnlyInt().Clone();
        }

        public Rectangle[] GetRegionScansReadOnlyInt()
        {
            lock (this.SyncRoot)
            {
                if (this.changed)
                {
                    UpdateCachedRegionScans();
                }

                return this.cachedRects;
            }
        }

        private unsafe void UpdateCachedRegionScans()
        {
            // Assumes we are in a lock(SyncRoot){} block
            SystemLayer.PdnGraphics.GetRegionScans(this.gdiRegion, out cachedRects, out cachedArea);
            this.cachedRectsF = null; // only update this when specifically asked for it
        }
                
        public void Intersect(GraphicsPath path)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Intersect(path);
            }
        }

        public void Intersect(Rectangle rect)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Intersect(rect);
            }
        }

        public void Intersect(RectangleF rectF)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Intersect(rectF);
            }
        }

        public void Intersect(Region region)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Intersect(region);
            }
        }

        public void Intersect(PdnRegion region2)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Intersect(region2.gdiRegion);
            }
        }

        public bool IsEmpty(Graphics g)
        {
            lock (SyncRoot)
            {
                return gdiRegion.IsEmpty(g);
            }
        }

        public bool IsEmpty()
        {
            return GetArea() == 0;
        }

        public bool IsInfinite(Graphics g)
        {
            lock (SyncRoot)
            {
                return gdiRegion.IsInfinite(g);
            }
        }

        public bool IsVisible(Point point)
        {
            lock (SyncRoot)
            {
                return gdiRegion.IsVisible(point);
            }
        }

        public bool IsVisible(PointF pointF)
        {
            lock (SyncRoot)
            {
                return gdiRegion.IsVisible(pointF);
            }
        }

        public bool IsVisible(Rectangle rect)
        {
            lock (SyncRoot)
            {
                return gdiRegion.IsVisible(rect);
            }
        }

        public bool IsVisible(RectangleF rectF)
        {
            lock (SyncRoot)
            {
                return gdiRegion.IsVisible(rectF);
            }
        }

        public bool IsVisible(Point point, Graphics g)
        {
            lock (SyncRoot)
            {
                return gdiRegion.IsVisible(point, g);
            }
        }
        
        public bool IsVisible(PointF pointF, Graphics g)
        {
            lock (SyncRoot)
            {
                return gdiRegion.IsVisible(pointF, g);
            }
        }

        public bool IsVisible(Rectangle rect, Graphics g)
        {
            lock (SyncRoot)
            {
                return gdiRegion.IsVisible(rect, g);
            }
        }

        public bool IsVisible(RectangleF rectF, Graphics g)
        {
            lock (SyncRoot)
            {
                return gdiRegion.IsVisible(rectF, g);
            }
        }

        public bool IsVisible(float x, float y)
        {
            lock (SyncRoot)
            {
                return gdiRegion.IsVisible(x, y);
            }
        }

        public bool IsVisible(int x, int y, Graphics g)
        {
            lock (SyncRoot)
            {
                return gdiRegion.IsVisible(x, y, g);
            }
        }

        public bool IsVisible(float x, float y, Graphics g)
        {
            lock (SyncRoot)
            {
                return gdiRegion.IsVisible(x, y, g);
            }
        }

        public bool IsVisible(int x, int y, int width, int height)
        {
            lock (SyncRoot)
            {
                return gdiRegion.IsVisible(x, y, width, height);
            }
        }

        public bool IsVisible(float x, float y, float width, float height)
        {
            lock (SyncRoot)
            {
                return gdiRegion.IsVisible(x, y, width, height);
            }
        }

        public bool IsVisible(int x, int y, int width, int height, Graphics g)
        {
            lock (SyncRoot)
            {
                return gdiRegion.IsVisible(x, y, width, height, g);
            }
        }

        public bool IsVisible(float x, float y, float width, float height, Graphics g)
        {
            lock (SyncRoot)
            {
                return gdiRegion.IsVisible(x, y, width, height, g);
            }
        }

        public void MakeEmpty()
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.MakeEmpty();
            }
        }

        public void MakeInfinite()
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.MakeInfinite();
            }
        }

        public void Transform(Matrix matrix)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Transform(matrix);
            }
        }

        public void Union(GraphicsPath path)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Union(path);
            }
        }

        public void Union(Rectangle rect)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Union(rect);
            }
        }

        public void Union(RectangleF rectF)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Union(rectF);
            }
        }

        public void Union(RectangleF[] rectsF)
        {
            lock (SyncRoot)
            {
                Changed();

                using (PdnRegion tempRegion = Utility.RectanglesToRegion(rectsF))
                {
                    this.Union(tempRegion);
                }
            }
        }

        public void Union(Region region)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Union(region);
            }
        }

        public void Union(PdnRegion region2)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Union(region2.gdiRegion);
            }
        }

        public void Xor(Rectangle rect)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Xor(rect);
            }
        }

        public void Xor(RectangleF rectF)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Xor(rectF);
            }
        }

        public void Xor(Region region)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Xor(region);
            }
        }

        public void Xor(PdnRegion region2)
        {
            lock (SyncRoot)
            {
                Changed();
                gdiRegion.Xor(region2.gdiRegion);
            }
        }
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.