File: commonui\System\Drawing\GraphicsContext.cs
Project: ndp\fx\src\System.Drawing.csproj (System.Drawing)

//------------------------------------------------------------------------------
// <copyright file="Graphics.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>                                                                
//------------------------------------------------------------------------------
 
namespace System.Drawing {
    using System;    
    using System.Drawing.Drawing2D;
    using System.Diagnostics;
    using System.Runtime.Versioning;
 
    /// <devdoc>
    ///     Contains information about the context of a Graphics object.
    /// </devdoc>
    internal class GraphicsContext : IDisposable {
        /// <devdoc>
        ///     The state that identifies the context.
        /// </devdoc>
        private int contextState;
 
        /// <devdoc>
        ///     The context's translate transform.
        /// </devdoc>
        private PointF transformOffset;
 
        /// <devdoc>
        ///     The context's clip region.
        /// </devdoc>
        private Region clipRegion;
 
        /// <devdoc>
        ///     The next context up the stack.
        /// </devdoc>
        private GraphicsContext nextContext;
 
        /// <devdoc>
        ///     The previous context down the stack.
        /// </devdoc>
        private GraphicsContext prevContext;
 
        /// <devdoc>
        ///     Flags that determines whether the context was created for a Graphics.Save() operation.
        ///     This kind of contexts are cumulative across subsequent Save() calls so the top context
        ///     info is cumulative.  This is not the same for contexts created for a Graphics.BeginContainer()
        ///     operation, in this case the new context information is reset.  See Graphics.BeginContainer()
        ///     and Graphics.Save() for more information.
        /// </devdoc>
        bool isCumulative;
 
        /// <devdoc>
        ///     Private constructor disallowed.
        /// </devdoc>
        private GraphicsContext() { 
        }
 
        [ResourceExposure(ResourceScope.Process)]
        [ResourceConsumption(ResourceScope.Process)]
        public GraphicsContext(Graphics g) {
            Matrix transform = g.Transform;
            if (!transform.IsIdentity) {
                float[] elements = transform.Elements;
                this.transformOffset.X = elements[4];
                this.transformOffset.Y = elements[5];
            }
            transform.Dispose();
 
            Region clip = g.Clip;
            if (clip.IsInfinite(g)) {
                clip.Dispose();
            }
            else {
                this.clipRegion = clip;
            }
        }
 
        /// <devdoc>
        ///     Disposes this and all contexts up the stack.
        /// </devdoc>
        public void Dispose() {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
 
        /// <devdoc>
        ///     Disposes this and all contexts up the stack.
        /// </devdoc>
        public void Dispose(bool disposing) {
            if (this.nextContext != null) {
                // Dispose all contexts up the stack since they are relative to this one and its state will be invalid.
                this.nextContext.Dispose();
                this.nextContext = null;
            }
 
            if (this.clipRegion != null) {
                this.clipRegion.Dispose();
                this.clipRegion = null;
            }
        }
 
        /// <devdoc>
        ///     The state id representing the GraphicsContext.
        /// </devdoc>
        public int State {
            get {
                return this.contextState;
            }
            set {
                this.contextState = value;
            }
        }
 
        /// <devdoc>
        ///     The translate transform in the GraphicsContext.
        /// </devdoc>
        public PointF TransformOffset {
            get { 
                return this.transformOffset; 
            }
        }
 
        /// <devdoc>
        ///     The clipping region the GraphicsContext.
        /// </devdoc>
        public Region Clip {
            get { 
                return this.clipRegion; 
            }
        }
 
        /// <devdoc>
        ///     The next GraphicsContext object in the stack.
        /// </devdoc>
        public GraphicsContext Next {
            get {
                return this.nextContext;
            }
            set {
                this.nextContext = value;
            }
        }
 
        /// <devdoc>
        ///     The previous GraphicsContext object in the stack.
        /// </devdoc>
        public GraphicsContext Previous {
            get {
                return this.prevContext;
            }
            set {
                this.prevContext = value;
            }
        }
 
        /// <devdoc>
        ///     Determines whether this context is cumulative or not.  See filed for more info.
        /// </devdoc>
        public bool IsCumulative {
            get {
                return this.isCumulative;
            }
            set {
                this.isCumulative = value;
            }
        }
    }
}