DrawingDrawingContext.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Core / CSharp / System / Windows / Media / DrawingDrawingContext.cs / 1 / DrawingDrawingContext.cs

                             
//----------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// Description: Creates a Drawing representation of the Draw calls made
//              to this DrawingContext. 
// 
// History:
// 
//  2004/11/19 : timothyc - Repurposed DrawingDrawingContext from being the
//              DrawingContext that populates a legacy Drawing to the
//              DrawingContext that creates a DrawingGroup.
// 
//---------------------------------------------------------------------------
 
using MS.Internal; 
using System;
using System.Collections.Generic; 
using System.Diagnostics;
using System.Security.Permissions;
using System.Windows;
using System.Windows.Media; 
using System.Windows.Media.Animation;
using System.Windows.Media.Composition; 
using System.Windows.Media.Effects; 
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D; 
using System.Windows.Threading;

using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID; 

namespace System.Windows.Media 
{ 
    /// 
    /// Creates DrawingGroup content to represent the Draw calls made to this DrawingContext 
    /// 
    internal class DrawingDrawingContext : DrawingContext
    {
        #region Constructors 

        ///  
        /// Default DrawingDrawingContext constructor. 
        /// 
        internal DrawingDrawingContext() 
        {
        }

        #endregion Constructors 

        #region Public Methods 
 
        /// 
        ///     DrawLine - 
        ///     Draws a line with the specified pen.
        ///     Note that this API does not accept a Brush, as there is no area to fill.
        /// 
        ///  The Pen with which to stroke the line.  
        ///  The start Point for the line. 
        ///  The end Point for the line.  
        public override void DrawLine( 
            Pen pen,
            Point point0, 
            Point point1)
        {

        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("DrawLine(const)");
        #endif 
 
            // Forward call to the animate version with null animations
            DrawLine(pen, point0, null, point1, null); 
        }

        /// 
        ///     DrawLine - 
        ///     Draws a line with the specified pen.
        ///     Note that this API does not accept a Brush, as there is no area to fill. 
        ///  
        ///  The Pen with which to stroke the line. 
        ///  The start Point for the line.  
        ///  Optional AnimationClock for point0. 
        ///  The end Point for the line. 
        ///  Optional AnimationClock for point1. 
        public override void DrawLine( 
            Pen pen,
            Point point0, 
            AnimationClock point0Animations, 
            Point point1,
            AnimationClock point1Animations) 
        {

        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("DrawLine(animate)"); 
        #endif
 
            // 
            // Verify that parameters & state are valid
            // 

            VerifyApiNonstructuralChange();

            if (pen == null) 
            {
                return; 
            } 

            // 
            // Create a geometry & add animations if they exist
            //

            // Instantiate the geometry 
            LineGeometry geometry = new LineGeometry(point0, point1);
 
            // 
            // We may need to opt-out of inheritance through the new Freezable.
            // This is controlled by this.CanBeInheritanceContext. 
            //

            geometry.CanBeInheritanceContext = CanBeInheritanceContext;
 
            // Setup the geometries freezable-related state
            SetupNewFreezable( 
                geometry, 
                (point0Animations == null) && // Freeze if animations are null
                (point1Animations == null) 
                );

            // Add animations to the geometry
            if (point0Animations != null) 
            {
                geometry.ApplyAnimationClock(LineGeometry.StartPointProperty, point0Animations); 
            } 

            if(point1Animations != null) 
            {
                geometry.ApplyAnimationClock(LineGeometry.EndPointProperty, point1Animations);
            }
 
            //
            // Add Drawing to the Drawing graph 
            // 

            AddNewGeometryDrawing(null, pen, geometry); 
        }
        /// 
        ///     DrawRectangle -
        ///     Draw a rectangle with the provided Brush and/or Pen. 
        ///     If both the Brush and Pen are null this call is a no-op.
        ///  
        ///  
        ///     The Brush with which to fill the rectangle.
        ///     This is optional, and can be null, in which case no fill is performed. 
        /// 
        /// 
        ///     The Pen with which to stroke the rectangle.
        ///     This is optional, and can be null, in which case no stroke is performed. 
        /// 
        ///  The Rect to fill and/or stroke.  
        public override void DrawRectangle( 
            Brush brush,
            Pen pen, 
            Rect rectangle)
        {

        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("DrawRectangle(const)");
        #endif 
 
            // Forward call to the animate version with null animations
            DrawRectangle(brush, pen, rectangle, null); 
        }

        /// 
        ///     DrawRectangle - 
        ///     Draw a rectangle with the provided Brush and/or Pen.
        ///     If both the Brush and Pen are null this call is a no-op. 
        ///  
        /// 
        ///     The Brush with which to fill the rectangle. 
        ///     This is optional, and can be null, in which case no fill is performed.
        /// 
        /// 
        ///     The Pen with which to stroke the rectangle. 
        ///     This is optional, and can be null, in which case no stroke is performed.
        ///  
        ///  The Rect to fill and/or stroke.  
        ///  Optional AnimationClock for rectangle. 
        public override void DrawRectangle( 
            Brush brush,
            Pen pen,
            Rect rectangle,
            AnimationClock rectangleAnimations) 
        {
 
        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("DrawRectangle(animate)");
        #endif 

            //
            // Verify that parameters & state are valid
            // 

            VerifyApiNonstructuralChange(); 
 
            if ((brush == null) && (pen == null))
            { 
                return;
            }

            // 
            // Create a geometry & add animations if they exist
            // 
 
            // Instantiate the geometry
            RectangleGeometry geometry = new RectangleGeometry(rectangle); 

            //
            // We may need to opt-out of inheritance through the new Freezable.
            // This is controlled by this.CanBeInheritanceContext. 
            //
 
            geometry.CanBeInheritanceContext = CanBeInheritanceContext; 

            // Setup the geometries freezable-related state 
            SetupNewFreezable(
                geometry,
                (rectangleAnimations == null) // Freeze if there are no animations
                ); 

            // Add animations to the geometry 
            if (rectangleAnimations != null) 
            {
                geometry.ApplyAnimationClock(RectangleGeometry.RectProperty, rectangleAnimations); 
            }

            //
            // Add Drawing to the Drawing graph 
            //
 
            AddNewGeometryDrawing(brush, pen, geometry); 
        }
 
        /// 
        ///     DrawRoundedRectangle -
        ///     Draw a rounded rectangle with the provided Brush and/or Pen.
        ///     If both the Brush and Pen are null this call is a no-op. 
        /// 
        ///  
        ///     The Brush with which to fill the rectangle. 
        ///     This is optional, and can be null, in which case no fill is performed.
        ///  
        /// 
        ///     The Pen with which to stroke the rectangle.
        ///     This is optional, and can be null, in which case no stroke is performed.
        ///  
        ///  The Rect to fill and/or stroke. 
        ///  
        ///     The radius in the X dimension of the rounded corners of this 
        ///     rounded Rect.  This value will be clamped to the range [0..rectangle.Width/2]
        ///  
        /// 
        ///     The radius in the Y dimension of the rounded corners of this
        ///     rounded Rect.  This value will be clamped to the range [0..rectangle.Height/2].
        ///  
        public override void DrawRoundedRectangle(
            Brush brush, 
            Pen pen, 
            Rect rectangle,
            Double radiusX, 
            Double radiusY)
        {

        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("DrawRoundedRectangle(const)");
        #endif 
 
            // Forward call to the animate version with null animations
            DrawRoundedRectangle(brush, pen, rectangle, null, radiusX, null, radiusY, null); 
        }

        /// 
        ///     DrawRoundedRectangle - 
        ///     Draw a rounded rectangle with the provided Brush and/or Pen.
        ///     If both the Brush and Pen are null this call is a no-op. 
        ///  
        /// 
        ///     The Brush with which to fill the rectangle. 
        ///     This is optional, and can be null, in which case no fill is performed.
        /// 
        /// 
        ///     The Pen with which to stroke the rectangle. 
        ///     This is optional, and can be null, in which case no stroke is performed.
        ///  
        ///  The Rect to fill and/or stroke.  
        ///  Optional AnimationClock for rectangle. 
        ///  
        ///     The radius in the X dimension of the rounded corners of this
        ///     rounded Rect.  This value will be clamped to the range [0..rectangle.Width/2]
        /// 
        ///  Optional AnimationClock for radiusX.  
        /// 
        ///     The radius in the Y dimension of the rounded corners of this 
        ///     rounded Rect.  This value will be clamped to the range [0..rectangle.Height/2]. 
        /// 
        ///  Optional AnimationClock for radiusY.  
        public override void DrawRoundedRectangle(
            Brush brush,
            Pen pen,
            Rect rectangle, 
            AnimationClock rectangleAnimations,
            Double radiusX, 
            AnimationClock radiusXAnimations, 
            Double radiusY,
            AnimationClock radiusYAnimations) 
        {

        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("DrawRoundedRectangle(animate)"); 
        #endif
 
            // 
            // Verify that parameters & state are valid
            // 

            VerifyApiNonstructuralChange();

            if ((brush == null) && (pen == null)) 
            {
                return; 
            } 

            // 
            // Create a geometry & add animations if they exist
            //

            // Instantiate the geometry 
            RectangleGeometry geometry = new RectangleGeometry(rectangle, radiusX, radiusY);
 
            // 
            // We may need to opt-out of inheritance through the new Freezable.
            // This is controlled by this.CanBeInheritanceContext. 
            //

            geometry.CanBeInheritanceContext = CanBeInheritanceContext;
 
            // Setup the geometries freezable-related state
            SetupNewFreezable( 
                geometry, 
                (rectangleAnimations == null) &&    // Freeze if animations are null
                (radiusXAnimations == null) && 
                (radiusYAnimations == null)
                );

            // Add animations to the geometry 
            if (rectangleAnimations != null)
            { 
                geometry.ApplyAnimationClock(RectangleGeometry.RectProperty, rectangleAnimations); 
            }
 
            if (radiusXAnimations != null)
            {
                geometry.ApplyAnimationClock(RectangleGeometry.RadiusXProperty, radiusXAnimations);
            } 

            if (radiusYAnimations != null) 
            { 
                geometry.ApplyAnimationClock(RectangleGeometry.RadiusYProperty, radiusYAnimations);
            } 

            //
            // Add Drawing to the Drawing graph
            // 

            AddNewGeometryDrawing(brush, pen, geometry); 
        } 

        ///  
        ///     DrawEllipse -
        ///     Draw an ellipse with the provided Brush and/or Pen.
        ///     If both the Brush and Pen are null this call is a no-op.
        ///  
        /// 
        ///     The Brush with which to fill the ellipse. 
        ///     This is optional, and can be null, in which case no fill is performed. 
        /// 
        ///  
        ///     The Pen with which to stroke the ellipse.
        ///     This is optional, and can be null, in which case no stroke is performed.
        /// 
        ///  
        ///     The center of the ellipse to fill and/or stroke.
        ///  
        ///  
        ///     The radius in the X dimension of the ellipse.
        ///     The absolute value of the radius provided will be used. 
        /// 
        /// 
        ///     The radius in the Y dimension of the ellipse.
        ///     The absolute value of the radius provided will be used. 
        /// 
        public override void DrawEllipse( 
            Brush brush, 
            Pen pen,
            Point center, 
            Double radiusX,
            Double radiusY)
        {
 
        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("DrawEllipse(const)"); 
        #endif 

            // Forward call to the animate version with null animations 
            DrawEllipse(brush, pen, center, null, radiusX, null, radiusY, null);
        }

        ///  
        ///     DrawEllipse -
        ///     Draw an ellipse with the provided Brush and/or Pen. 
        ///     If both the Brush and Pen are null this call is a no-op. 
        /// 
        ///  
        ///     The Brush with which to fill the ellipse.
        ///     This is optional, and can be null, in which case no fill is performed.
        /// 
        ///  
        ///     The Pen with which to stroke the ellipse.
        ///     This is optional, and can be null, in which case no stroke is performed. 
        ///  
        /// 
        ///     The center of the ellipse to fill and/or stroke. 
        /// 
        ///  Optional AnimationClock for center. 
        /// 
        ///     The radius in the X dimension of the ellipse. 
        ///     The absolute value of the radius provided will be used.
        ///  
        ///  Optional AnimationClock for radiusX.  
        /// 
        ///     The radius in the Y dimension of the ellipse. 
        ///     The absolute value of the radius provided will be used.
        /// 
        ///  Optional AnimationClock for radiusY. 
        public override void DrawEllipse( 
            Brush brush,
            Pen pen, 
            Point center, 
            AnimationClock centerAnimations,
            Double radiusX, 
            AnimationClock radiusXAnimations,
            Double radiusY,
            AnimationClock radiusYAnimations)
        { 

        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("DrawEllipse(animate)"); 
        #endif
 
            //
            // Verify that parameters & state are valid
            //
 
            VerifyApiNonstructuralChange();
 
            if ((brush == null) && (pen == null)) 
            {
                return; 
            }

            //
            // Create a geometry & add animations if they exist 
            //
 
            // Instantiate the geometry 
            EllipseGeometry geometry = new EllipseGeometry(center, radiusX, radiusY);
 
            //
            // We may need to opt-out of inheritance through the new Freezable.
            // This is controlled by this.CanBeInheritanceContext.
            // 

            geometry.CanBeInheritanceContext = CanBeInheritanceContext; 
 
            // Setup the geometries freezable-related state
            SetupNewFreezable( 
                geometry,
                (centerAnimations == null) && // Freeze if there are no animations
                (radiusXAnimations == null) &&
                (radiusYAnimations == null) 
                );
 
            // Add animations to the geometry 
            if (centerAnimations != null)
            { 
                geometry.ApplyAnimationClock(EllipseGeometry.CenterProperty, centerAnimations);
            }

            if (radiusXAnimations != null) 
            {
                geometry.ApplyAnimationClock(EllipseGeometry.RadiusXProperty, radiusXAnimations); 
            } 

            if (radiusYAnimations != null) 
            {
                geometry.ApplyAnimationClock(EllipseGeometry.RadiusYProperty, radiusYAnimations);
            }
 
            //
            // Add Drawing to the Drawing graph 
            // 

            AddNewGeometryDrawing(brush, pen, geometry); 
        }
        /// 
        ///     DrawGeometry -
        ///     Draw a Geometry with the provided Brush and/or Pen. 
        ///     If both the Brush and Pen are null this call is a no-op.
        ///  
        ///  
        ///     The Brush with which to fill the Geometry.
        ///     This is optional, and can be null, in which case no fill is performed. 
        /// 
        /// 
        ///     The Pen with which to stroke the Geometry.
        ///     This is optional, and can be null, in which case no stroke is performed. 
        /// 
        ///  The Geometry to fill and/or stroke.  
        public override void DrawGeometry( 
            Brush brush,
            Pen pen, 
            Geometry geometry)
        {

        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("DrawGeometry(const)");
        #endif 
 
            //
            // Create a drawing & add animations if they exist 
            //

            VerifyApiNonstructuralChange();
 
            if (((brush == null) && (pen == null)) || (geometry == null))
            { 
                return; 
            }
 
            AddNewGeometryDrawing(brush, pen, geometry);
        }

        ///  
        ///     DrawImage -
        ///     Draw an Image into the region specified by the Rect. 
        ///     The Image will potentially be stretched and distorted to fit the Rect. 
        ///     For more fine grained control, consider filling a Rect with an ImageBrush via
        ///     DrawRectangle. 
        /// 
        ///  The ImageSource to draw. 
        /// 
        ///     The Rect into which the ImageSource will be fit. 
        /// 
        public override void DrawImage( 
            ImageSource imageSource, 
            Rect rectangle)
        { 

        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("DrawImage(const)");
        #endif 

            // Forward call to the animate version with null animations 
            DrawImage(imageSource, rectangle, null); 
        }
 
        /// 
        ///     DrawImage -
        ///     Draw an Image into the region specified by the Rect.
        ///     The Image will potentially be stretched and distorted to fit the Rect. 
        ///     For more fine grained control, consider filling a Rect with an ImageBrush via
        ///     DrawRectangle. 
        ///  
        ///  The ImageSource to draw. 
        ///  
        ///     The Rect into which the ImageSource will be fit.
        /// 
        ///  Optional AnimationClock for rectangle. 
        public override void DrawImage( 
            ImageSource imageSource,
            Rect rectangle, 
            AnimationClock rectangleAnimations) 
        {
 
        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("DrawImage(animate)");
        #endif
 
            //
            // Verify that parameters & state are valid 
            // 

            VerifyApiNonstructuralChange(); 

            if (imageSource == null)
            {
                return; 
            }
 
            // 
            // Create a drawing & add animations if they exist
            // 

            ImageDrawing imageDrawing = new ImageDrawing();

            // 
            // We may need to opt-out of inheritance through the new Freezable.
            // This is controlled by this.CanBeInheritanceContext. 
            // 

            imageDrawing.CanBeInheritanceContext = CanBeInheritanceContext; 

            imageDrawing.ImageSource = imageSource;
            imageDrawing.Rect = rectangle;
 
            SetupNewFreezable(
                imageDrawing, 
                (null == rectangleAnimations) && // Freeze if there are no animations 
                imageSource.IsFrozen            // and the bitmap source is frozen
                ); 

            if (rectangleAnimations != null)
            {
                imageDrawing.ApplyAnimationClock(ImageDrawing.RectProperty, rectangleAnimations); 
            }
 
            AddDrawing(imageDrawing); 
        }
        ///  
        ///     DrawDrawing -
        ///     Draw a Drawing.
        ///     For more fine grained control, consider filling a Rect with an DrawingBrush via
        ///     DrawRect. 
        /// 
        ///  The Drawing to draw.  
        public override void DrawDrawing( 
            Drawing drawing)
        { 

        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("DrawDrawing(const)");
        #endif 

            // 
            // Verify that parameters & state are valid 
            //
 
            VerifyApiNonstructuralChange();

            if (drawing == null)
            { 
                return;
            } 
 
            //
            // Add the Drawing to the children collection 
            //

            AddDrawing(drawing);
        } 

        ///  
        ///     DrawVideo - 
        ///     Draw a Video into the region specified by the Rect.
        ///     The Video will potentially be stretched and distorted to fit the Rect. 
        ///     For more fine grained control, consider filling a Rect with an VideoBrush via
        ///     DrawRectangle.
        /// 
        ///  The MediaPlayer to draw.  
        /// 
        ///     The Rect into which the MediaPlayer will be fit. 
        ///  
        public override void DrawVideo(
            MediaPlayer player, 
            Rect rectangle)
        {

        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("DrawVideo(const)");
        #endif 
 
            // Forward to non-animate version with null animations
            DrawVideo(player, rectangle, null); 
        }

        /// 
        ///     DrawVideo - 
        ///     Draw a Video into the region specified by the Rect.
        ///     The Video will potentially be stretched and distorted to fit the Rect. 
        ///     For more fine grained control, consider filling a Rect with an VideoBrush via 
        ///     DrawRectangle.
        ///  
        ///  The MediaPlayer to draw. 
        /// 
        ///     The Rect into which the MediaPlayer will be fit.
        ///  
        ///  Optional AnimationClock for rectangle. 
        public override void DrawVideo( 
            MediaPlayer player, 
            Rect rectangle,
            AnimationClock rectangleAnimations) 
        {

        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("DrawVideo(animate)"); 
        #endif
 
            // 
            // Verify that parameters & state are valid
            // 

            VerifyApiNonstructuralChange();

            if (player == null) 
            {
                return; 
            } 

            // 
            // Create a drawing & add animations if they exist
            //

            VideoDrawing videoDrawing = new VideoDrawing(); 

            // 
            // We may need to opt-out of inheritance through the new Freezable. 
            // This is controlled by this.CanBeInheritanceContext.
            // 

            videoDrawing.CanBeInheritanceContext = CanBeInheritanceContext;

            videoDrawing.Player = player; 
            videoDrawing.Rect = rectangle;
 
            SetupNewFreezable( 
                videoDrawing,
                false   // Don't ever freeze a VideoDrawing because it would 
                        // lose it's MediaPlayer
                );

            if (rectangleAnimations != null) 
            {
                videoDrawing.ApplyAnimationClock(VideoDrawing.RectProperty, rectangleAnimations); 
            } 

            AddDrawing(videoDrawing); 
        }

        /// 
        ///     DrawScene3D - 
        ///     Draw a Scene3D (internal object encapsulating a 3D scene)
        ///  
        ///  The Scene3D to draw.  
        internal override void DrawScene3D(
            Scene3D scene3D) 
        {
            // DrawingGroup's do not support DrawScene3D.  DrawScene3D is an internal
            // method only used by RetainedVisual3D, which always represents
            // it's content using RenderData (which does support DrawScene3D). 
            Debug.Assert(false);
        } 
 
        /// 
        ///     PushClip - 
        ///     Push a clip region, which will apply to all drawing primitives until the
        ///     corresponding Pop call.
        /// 
        ///  The Geometry to which we will clip.  
        public override void PushClip(
            Geometry clipGeometry) 
        { 

        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("PushClip(const)");
        #endif

            // 
            // Verify that parameters & state are valid
            // 
 
            VerifyApiNonstructuralChange();
 
            //
            // Instantiate a new drawing group and set it as the _currentDrawingGroup
            //
 
            PushNewDrawingGroup();
 
            // 
            // Set the clip on the new DrawingGroup
            // 

            _currentDrawingGroup.ClipGeometry = clipGeometry;
        }
 
        public override void PushOpacityMask(Brush brush)
        { 
 
        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("PushOpacityMask(const)"); 
        #endif

            //
            // Verify this object's state 
            //
            VerifyApiNonstructuralChange(); 
 
            //
            // Instantiate a new drawing group and set it as the _currentDrawingGroup 
            //
            PushNewDrawingGroup();

            // 
            // Set the opacity mask
            // 
            _currentDrawingGroup.OpacityMask = brush; 
        }
 
        /// 
        ///     PushOpacity -
        ///     Push an opacity which will blend the composite of all drawing primitives added
        ///     until the corresponding Pop call. 
        /// 
        ///  
        ///     The opacity with which to blend - 0 is transparent, 1 is opaque. 
        /// 
        public override void PushOpacity( 
            Double opacity
            )
        {
 
        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("PushOpacity(const)"); 
        #endif 

            // Forward to the animate version with null animations 
            PushOpacity(opacity, null);
        }

        ///  
        ///     PushOpacity -
        ///     Push an opacity which will blend the composite of all drawing primitives added 
        ///     until the corresponding Pop call. 
        /// 
        ///  
        ///     The opacity with which to blend - 0 is transparent, 1 is opaque.
        /// 
        ///  Optional AnimationClock for opacity. 
        public override void PushOpacity( 
            Double opacity,
            AnimationClock opacityAnimations) 
        { 

        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("PushOpacity(animate)");
        #endif

            // 
            // Verify this object's state
            // 
 
            VerifyApiNonstructuralChange();
 
            //
            // Instantiate a new drawing group and set it as the _currentDrawingGroup
            //
 
            PushNewDrawingGroup();
 
            // 
            // Set the opacity & opacity animations on the new DrawingGroup
            // 

            _currentDrawingGroup.Opacity = opacity;

            if (null != opacityAnimations) 
            {
                _currentDrawingGroup.ApplyAnimationClock(DrawingGroup.OpacityProperty, opacityAnimations); 
            } 
        }
        ///  
        ///     PushTransform -
        ///     Push a Transform which will apply to all drawing operations until the corresponding
        ///     Pop.
        ///  
        ///  The Transform to push. 
        public override void PushTransform( 
            Transform transform) 
        {
 
        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("PushTransform(const)");
        #endif
 
            //
            // Verify that parameters & state are valid 
            // 

            VerifyApiNonstructuralChange(); 

            //
            // Instantiate a new drawing group and set it as the _currentDrawingGroup
            // 

            PushNewDrawingGroup(); 
 
            //
            // Set the transform on the new DrawingGroup 
            //

            _currentDrawingGroup.Transform = transform;
        } 

        ///  
        ///     PushGuidelineSet - 
        ///     Push a set of guidelines which should be applied
        ///     to all drawing operations until the 
        ///     corresponding Pop.
        /// 
        ///  The GuidelineSet to push. 
        public override void PushGuidelineSet( 
            GuidelineSet guidelines)
        { 
 
#if DEBUG
            MediaTrace.DrawingContextOp.Trace("PushGuidelineSet"); 
#endif

            //
            // Verify that parameters & state are valid 
            //
 
            VerifyApiNonstructuralChange(); 

            // 
            // Instantiate a new drawing group and set it as the _currentDrawingGroup
            //

            PushNewDrawingGroup(); 

            // 
            // Set the guideline collection on the new DrawingGroup 
            //
 
            _currentDrawingGroup.GuidelineSet = guidelines;
        }

        ///  
        ///     PushGuidelineY1 -
        ///     Explicitly push one horizontal guideline. 
        ///  
        ///  The coordinate of leading guideline. 
        internal override void PushGuidelineY1( 
            Double coordinate)
        {

#if DEBUG 
            MediaTrace.DrawingContextOp.Trace("PushGuidelineY1");
#endif 
 
            //
            // Verify that parameters & state are valid 
            //

            VerifyApiNonstructuralChange();
 
            //
            // Instantiate a new drawing group and set it as the _currentDrawingGroup 
            // 

            PushNewDrawingGroup(); 

            //
            // Convert compact record to generic GuidelineSet.
            // 

            GuidelineSet guidelineCollection = new GuidelineSet( 
                null,                           // x guidelines 
                new double[] { coordinate, 0 }, // y guidelines
                true                            // dynamic flag 
                );
            guidelineCollection.Freeze();

            // 
            // Set the guideline collection on the new DrawingGroup
            // 
 
            _currentDrawingGroup.GuidelineSet = guidelineCollection;
        } 

        /// 
        ///     PushGuidelineY2 -
        ///     Explicitly push a pair of horizontal guidelines. 
        /// 
        ///  The coordinate of leading guideline.  
        ///  
        ///     The offset from leading guideline to driven guideline.
        ///  
        internal override void PushGuidelineY2(
            Double leadingCoordinate,
            Double offsetToDrivenCoordinate)
        { 

#if DEBUG 
            MediaTrace.DrawingContextOp.Trace("PushGuidelineY2"); 
#endif
 
            //
            // Verify that parameters & state are valid
            //
 
            VerifyApiNonstructuralChange();
 
            // 
            // Instantiate a new drawing group and set it as the _currentDrawingGroup
            // 

            PushNewDrawingGroup();

            // 
            // Convert compact record to generic GuidelineSet.
            // 
 
            GuidelineSet guidelineCollection = new GuidelineSet(
                null,                                   // x guidelines 
                new double[]
                    {
                        leadingCoordinate,
                        offsetToDrivenCoordinate 
                    }, // y guidelines
                true                                    // dynamic flag 
                ); 
            guidelineCollection.Freeze();
 
            //
            // Set the guideline collection on the new DrawingGroup
            //
 
            _currentDrawingGroup.GuidelineSet = guidelineCollection;
        } 
 
        /// 
        ///     PushEffect - 
        ///     Push a BitmapEffect which will apply to all drawing operations until the
        ///     corresponding Pop.
        /// 
        ///  The BitmapEffect to push.  
        ///  The BitmapEffectInput. 
        public override void PushEffect( 
            BitmapEffect effect, 
            BitmapEffectInput effectInput)
        { 

#if DEBUG
            MediaTrace.DrawingContextOp.Trace("PushEffect(const)");
#endif 

            // 
            // Verify that parameters & state are valid 
            //
 
            VerifyApiNonstructuralChange();

            //
            // Instantiate a new drawing group and set it as the _currentDrawingGroup 
            //
 
            PushNewDrawingGroup(); 

            // 
            // Set the transform on the new DrawingGroup
            //

            _currentDrawingGroup.BitmapEffect = effect; 
            _currentDrawingGroup.BitmapEffectInput = (effectInput != null) ?
                                                        effectInput : new BitmapEffectInput(); 
 
        }
 
        /// 
        /// Pop
        /// 
        public override void Pop() 
        {
 
        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("Pop");
        #endif 

            VerifyApiNonstructuralChange();

            // Verify that Pop hasn't been called too many times 
            if ( (_previousDrawingGroupStack == null) ||
                 (_previousDrawingGroupStack.Count == 0)) 
            { 
                throw new InvalidOperationException(SR.Get(SRID.DrawingContext_TooManyPops));
            } 

            // Restore the previous value of the current drawing group
            _currentDrawingGroup = _previousDrawingGroupStack.Pop();
        } 

        ///  
        /// Draw a GlyphRun. 
        /// 
        /// Foreground brush to draw GlyphRun with.  
        ///  The GlyphRun to draw. 
        /// 
        /// This call is illegal if this object has already been closed or disposed.
        ///  
        public override void DrawGlyphRun(Brush foregroundBrush, GlyphRun glyphRun)
        { 
#if DEBUG 
            MediaTrace.DrawingContextOp.Trace("DrawGlyphRun(constant)");
#endif 

            //
            // Verify that parameters & state are valid
            // 

            VerifyApiNonstructuralChange(); 
 
            if (foregroundBrush == null || glyphRun == null)
            { 
                return;
            }

            // Add a GlyphRunDrawing to the Drawing graph 

            GlyphRunDrawing glyphRunDrawing = new GlyphRunDrawing(); 
 
            //
            // We may need to opt-out of inheritance through the new Freezable. 
            // This is controlled by this.CanBeInheritanceContext.
            //

            glyphRunDrawing.CanBeInheritanceContext = CanBeInheritanceContext; 

            glyphRunDrawing.ForegroundBrush = foregroundBrush; 
            glyphRunDrawing.GlyphRun = glyphRun; 

            SetupNewFreezable( 
                glyphRunDrawing,
                foregroundBrush.IsFrozen
                );
 
            AddDrawing(glyphRunDrawing);
        } 
 
        /// 
        /// Dispose() closes this DrawingContext for any further additions, and 
        /// returns it's content to the object that created it.
        /// 
        /// 
        /// Further Draw/Push/Pop calls to this DrawingContext will result in an 
        /// exception.  This method also matches any outstanding Push calls with
        /// a cooresponding Pop.  Calling Close after this object has been closed 
        /// or Disposed will also result in an exception. 
        /// 
        ///  
        /// This call is illegal if this object has already been Closed.
        /// 
        public override void Close()
        { 
            // Throw an exception if this object has already been closed/disposed.
            VerifyNotDisposed(); 
 
            // Close this object
            ((IDisposable)this).Dispose(); 
        }

        /// 
        /// Dispose() closes this DrawingContext for any further additions, and 
        /// returns it's content to the object that created it.
        ///  
        ///  
        /// Further Draw/Push/Pop calls to this DrawingContext will result in an
        /// exception.  This method also matches any outstanding Push calls with 
        /// a cooresponding Pop.  Multiple calls to Dispose will not result in
        /// an exception.
        /// 
        protected override void DisposeCore() 
        {
            // Dispose may be called multiple times without throwing 
            // an exception. 
            if (!_disposed)
            { 
                //
                // Match any outstanding Push calls with a Pop
                //
 
                if (_previousDrawingGroupStack != null)
                { 
                    int stackCount = _previousDrawingGroupStack.Count; 
                    for (int i = 0; i < stackCount; i++)
                    { 
                        Pop();
                    }
                }
 
                //
                // Call CloseCore with the root DrawingGroup's children 
                // 

                DrawingCollection rootChildren; 

                if (_currentDrawingGroup != null)
                 {
                    // If we created a root DrawingGroup because multiple elements 
                    // exist at the root level, provide it's Children collection
                    // directly. 
                    rootChildren = _currentDrawingGroup.Children; 
                }
                else 
                {
                    // Create a new DrawingCollection if we didn't create a
                    // root DrawingGroup because the root level only contained
                    // a single child. 
                    //
                    // This collection is needed by DrawingGroup.Open because 
                    // Open always replaces it's Children collection.  It isn't 
                    // strictly needed for Append, but always using a collection
                    // simplifies the TransactionalAppend implementation (i.e., 
                    // a seperate implemention isn't needed for a single element)
                    rootChildren = new DrawingCollection();

                    // 
                    // We may need to opt-out of inheritance through the new Freezable.
                    // This is controlled by this.CanBeInheritanceContext. 
                    // 

                    rootChildren.CanBeInheritanceContext = CanBeInheritanceContext; 

                    if (_rootDrawing != null)
                    {
                        rootChildren.Add(_rootDrawing); 
                    }
                } 
 
                // Inform our derived classes that Close was called
                CloseCore(rootChildren); 

                _disposed = true;
            }
        } 

        #endregion Public Methods 
 
        #region Protected Methods
 
        /// 
        /// Called during Close/Dispose when the content created this DrawingContext
        /// needs to be committed.
        ///  
        /// 
        ///     Collection containing the Drawing elements created with this 
        ///     DrawingContext. 
        /// 
        ///  
        ///     This will only be called once (at most) per instance.
        /// 
        protected virtual void CloseCore(DrawingCollection rootDrawingGroupChildren)
        { 
            // Default implementation is a no-op
        } 
 
        /// 
        /// Verifies that the DrawingContext is being referenced from the 
        /// appropriate UIContext, and that the object hasn't been disposed
        /// 
        protected override void VerifyApiNonstructuralChange()
        { 
            base.VerifyApiNonstructuralChange();
 
            VerifyNotDisposed(); 
        }
 
        #endregion Protected Methods

        #region Internal Properties
 
        /// 
        /// Determines whether this DrawingContext should connect inheritance contexts 
        /// to DependencyObjects which are passed to its methods. 
        /// This property is modeled after DependencyObject.CanBeInheritanceContext.
        /// Defaults to true. 
        /// NOTE: This is currently only respected by DrawingDrawingContext and sub-classes.
        /// 
        internal bool CanBeInheritanceContext
        { 
            get
            { 
                return _canBeInheritanceContext; 
            }
 
            set
            {
                _canBeInheritanceContext = value;
            } 
        }
 
        #endregion Internal Properties 

        #region Private Methods 

        /// 
        /// Throws an exception if this object is already disposed.
        ///  
        private void VerifyNotDisposed()
        { 
            if (_disposed) 
            {
                throw new ObjectDisposedException("DrawingDrawingContext"); 
            }
        }

        ///  
        /// Freezes the given freezable if the fFreeze flag is true.  Used by
        /// the various drawing methods to freeze resources if there is no 
        /// chance the user might attempt to mutate it. 
        /// (i.e., there are no animations and the dependant properties are
        /// null or themselves frozen.) 
        /// 
        private Freezable SetupNewFreezable(Freezable newFreezable, bool fFreeze)
        {
            if (fFreeze) 
            {
                newFreezable.Freeze(); 
            } 

            return newFreezable; 
        }

        /// 
        /// Contains the functionality common to GeometryDrawing operations of 
        /// instantiating the GeometryDrawing, setting it's Freezable state,
        /// and Adding it to the Drawing Graph. 
        ///  
        private void AddNewGeometryDrawing(Brush brush, Pen pen, Geometry geometry)
        { 
            Debug.Assert(geometry != null);

            // Instantiate the GeometryDrawing
            GeometryDrawing geometryDrawing = new GeometryDrawing(); 

            // 
            // We may need to opt-out of inheritance through the new Freezable. 
            // This is controlled by this.CanBeInheritanceContext.
            // 

            geometryDrawing.CanBeInheritanceContext = CanBeInheritanceContext;

            geometryDrawing.Brush = brush; 
            geometryDrawing.Pen = pen;
            geometryDrawing.Geometry = geometry; 
 
            // Setup it's Freezeable-related state
            SetupNewFreezable( 
                geometryDrawing,
                ((brush == null) || (brush.IsFrozen)) &&    // Freeze if the brush is frozen
                ((pen == null) || (pen.IsFrozen)) &&        // and the pen is frozen
                (geometry.IsFrozen)                         // and the geometry is frozen 
                );
 
            // Add it to the drawing graph 
            AddDrawing(geometryDrawing);
        } 

        /// 
        /// Creates a new DrawingGroup for a Push* call by setting the
        /// _currentDrawingGroup to a newly instantiated DrawingGroup, 
        /// and saving the previous _currentDrawingGroup value on the
        /// _previousDrawingGroupStack. 
        ///  
        private void PushNewDrawingGroup()
        { 
            // Instantiate a new drawing group
            DrawingGroup drawingGroup = new DrawingGroup();

            // 
            // We may need to opt-out of inheritance through the new Freezable.
            // This is controlled by this.CanBeInheritanceContext. 
            // 

            drawingGroup.CanBeInheritanceContext = CanBeInheritanceContext; 

            // Setup it's freezable state
            SetupNewFreezable(
                    drawingGroup, 
                    false // Don't freeze, DrawingGroup's may contain unfrozen children/properties
                    ); 
 
            // Add it to the drawing graph, like any other Drawing
            AddDrawing(drawingGroup); 

            // Lazily allocate the stack when it is needed because many uses
            // of DrawingDrawingContext will have a depth of one.
            if (null == _previousDrawingGroupStack) 
            {
                _previousDrawingGroupStack = new Stack(2); 
            } 

            // Save the previous _currentDrawingGroup value. 
            //
            // If this is the first call, the value of _currentDrawingGroup
            // will be null because AddDrawing doesn't create a _currentDrawingGroup
            // for the first drawing.  Having null on the stack is valid, and simply 
            // denotes that this new DrawingGroup is the first child in the root
            // DrawingGroup.  It is also possible for the first value on the stack 
            // to be non-null, which means that the root DrawingGroup has other 
            // children.
            _previousDrawingGroupStack.Push(_currentDrawingGroup); 

            // Set this drawing group as the current one so that subsequent drawing's
            // are added as it's children until Pop is called.
            _currentDrawingGroup = drawingGroup; 
        }
 
        ///  
        /// Adds a new Drawing to the DrawingGraph.
        /// 
        /// This method avoids creating a DrawingGroup for the common case
        /// where only a single child exists in the root DrawingGroup.
        /// 
        private void AddDrawing(Drawing newDrawing) 
        {
            Debug.Assert(newDrawing != null); 
 
            if (_rootDrawing == null)
            { 
                // When a DrawingGroup is set, it should be made the root if
                // a root drawing didnt exist.
                Debug.Assert(_currentDrawingGroup == null);
 
                // If this is the first Drawing being added, avoid creating a DrawingGroup
                // and set this drawing as the root drawing.  This optimizes the common 
                // case where only a single child exists in the root DrawingGroup. 
                _rootDrawing = newDrawing;
            } 
            else if (_currentDrawingGroup == null)
            {
                // When the second drawing is added at the root level, set a
                // DrawingGroup as the root and add both drawings to it. 

                // Instantiate the DrawingGroup 
                _currentDrawingGroup = new DrawingGroup(); 

                // 
                // We may need to opt-out of inheritance through the new Freezable.
                // This is controlled by this.CanBeInheritanceContext.
                //
 
                _currentDrawingGroup.CanBeInheritanceContext = CanBeInheritanceContext;
 
                SetupNewFreezable( 
                    _currentDrawingGroup,
                    false // Don't freeze DrawingGroups, subsequent Draw calls may modify them 
                    );

                // Add both Children
                _currentDrawingGroup.Children.Add(_rootDrawing); 
                _currentDrawingGroup.Children.Add(newDrawing);
 
                // Set the new DrawingGroup as the current 
                _rootDrawing = _currentDrawingGroup;
            } 
            else
            {
                // If there already is a current drawing group, then simply add
                // the new drawing too it. 
                _currentDrawingGroup.Children.Add(newDrawing);
            } 
        } 

        #endregion Private Methods 

        #region Fields

        // Root drawing created by this DrawingContext. 
        //
        // If there is only a single child of the root DrawingGroup, _rootDrawing 
        // will reference the single child, and the root _currentDrawingGroup 
        // value will be null.  Otherwise, _rootDrawing will reference the
        // root DrawingGroup, and be the same value as the root _currentDrawingGroup. 
        //
        // Either way, _rootDrawing always references the root drawing.
        protected Drawing _rootDrawing;
 
        // Current DrawingGroup that new children are added to
        protected DrawingGroup _currentDrawingGroup; 
 
        // Previous values of _currentDrawingGroup
        private Stack _previousDrawingGroupStack; 

        // Has Dispose() or Close() been called?
        private bool _disposed;
 
        // Determines whether this DrawingContext should connect inheritance contexts
        // to DependencyObjects which are passed to its methods. 
        private bool _canBeInheritanceContext = true; 
        #endregion Fields
    } 
}


 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
 
//----------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// Description: Creates a Drawing representation of the Draw calls made
//              to this DrawingContext. 
// 
// History:
// 
//  2004/11/19 : timothyc - Repurposed DrawingDrawingContext from being the
//              DrawingContext that populates a legacy Drawing to the
//              DrawingContext that creates a DrawingGroup.
// 
//---------------------------------------------------------------------------
 
using MS.Internal; 
using System;
using System.Collections.Generic; 
using System.Diagnostics;
using System.Security.Permissions;
using System.Windows;
using System.Windows.Media; 
using System.Windows.Media.Animation;
using System.Windows.Media.Composition; 
using System.Windows.Media.Effects; 
using System.Windows.Media.Imaging;
using System.Windows.Media.Media3D; 
using System.Windows.Threading;

using SR=MS.Internal.PresentationCore.SR;
using SRID=MS.Internal.PresentationCore.SRID; 

namespace System.Windows.Media 
{ 
    /// 
    /// Creates DrawingGroup content to represent the Draw calls made to this DrawingContext 
    /// 
    internal class DrawingDrawingContext : DrawingContext
    {
        #region Constructors 

        ///  
        /// Default DrawingDrawingContext constructor. 
        /// 
        internal DrawingDrawingContext() 
        {
        }

        #endregion Constructors 

        #region Public Methods 
 
        /// 
        ///     DrawLine - 
        ///     Draws a line with the specified pen.
        ///     Note that this API does not accept a Brush, as there is no area to fill.
        /// 
        ///  The Pen with which to stroke the line.  
        ///  The start Point for the line. 
        ///  The end Point for the line.  
        public override void DrawLine( 
            Pen pen,
            Point point0, 
            Point point1)
        {

        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("DrawLine(const)");
        #endif 
 
            // Forward call to the animate version with null animations
            DrawLine(pen, point0, null, point1, null); 
        }

        /// 
        ///     DrawLine - 
        ///     Draws a line with the specified pen.
        ///     Note that this API does not accept a Brush, as there is no area to fill. 
        ///  
        ///  The Pen with which to stroke the line. 
        ///  The start Point for the line.  
        ///  Optional AnimationClock for point0. 
        ///  The end Point for the line. 
        ///  Optional AnimationClock for point1. 
        public override void DrawLine( 
            Pen pen,
            Point point0, 
            AnimationClock point0Animations, 
            Point point1,
            AnimationClock point1Animations) 
        {

        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("DrawLine(animate)"); 
        #endif
 
            // 
            // Verify that parameters & state are valid
            // 

            VerifyApiNonstructuralChange();

            if (pen == null) 
            {
                return; 
            } 

            // 
            // Create a geometry & add animations if they exist
            //

            // Instantiate the geometry 
            LineGeometry geometry = new LineGeometry(point0, point1);
 
            // 
            // We may need to opt-out of inheritance through the new Freezable.
            // This is controlled by this.CanBeInheritanceContext. 
            //

            geometry.CanBeInheritanceContext = CanBeInheritanceContext;
 
            // Setup the geometries freezable-related state
            SetupNewFreezable( 
                geometry, 
                (point0Animations == null) && // Freeze if animations are null
                (point1Animations == null) 
                );

            // Add animations to the geometry
            if (point0Animations != null) 
            {
                geometry.ApplyAnimationClock(LineGeometry.StartPointProperty, point0Animations); 
            } 

            if(point1Animations != null) 
            {
                geometry.ApplyAnimationClock(LineGeometry.EndPointProperty, point1Animations);
            }
 
            //
            // Add Drawing to the Drawing graph 
            // 

            AddNewGeometryDrawing(null, pen, geometry); 
        }
        /// 
        ///     DrawRectangle -
        ///     Draw a rectangle with the provided Brush and/or Pen. 
        ///     If both the Brush and Pen are null this call is a no-op.
        ///  
        ///  
        ///     The Brush with which to fill the rectangle.
        ///     This is optional, and can be null, in which case no fill is performed. 
        /// 
        /// 
        ///     The Pen with which to stroke the rectangle.
        ///     This is optional, and can be null, in which case no stroke is performed. 
        /// 
        ///  The Rect to fill and/or stroke.  
        public override void DrawRectangle( 
            Brush brush,
            Pen pen, 
            Rect rectangle)
        {

        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("DrawRectangle(const)");
        #endif 
 
            // Forward call to the animate version with null animations
            DrawRectangle(brush, pen, rectangle, null); 
        }

        /// 
        ///     DrawRectangle - 
        ///     Draw a rectangle with the provided Brush and/or Pen.
        ///     If both the Brush and Pen are null this call is a no-op. 
        ///  
        /// 
        ///     The Brush with which to fill the rectangle. 
        ///     This is optional, and can be null, in which case no fill is performed.
        /// 
        /// 
        ///     The Pen with which to stroke the rectangle. 
        ///     This is optional, and can be null, in which case no stroke is performed.
        ///  
        ///  The Rect to fill and/or stroke.  
        ///  Optional AnimationClock for rectangle. 
        public override void DrawRectangle( 
            Brush brush,
            Pen pen,
            Rect rectangle,
            AnimationClock rectangleAnimations) 
        {
 
        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("DrawRectangle(animate)");
        #endif 

            //
            // Verify that parameters & state are valid
            // 

            VerifyApiNonstructuralChange(); 
 
            if ((brush == null) && (pen == null))
            { 
                return;
            }

            // 
            // Create a geometry & add animations if they exist
            // 
 
            // Instantiate the geometry
            RectangleGeometry geometry = new RectangleGeometry(rectangle); 

            //
            // We may need to opt-out of inheritance through the new Freezable.
            // This is controlled by this.CanBeInheritanceContext. 
            //
 
            geometry.CanBeInheritanceContext = CanBeInheritanceContext; 

            // Setup the geometries freezable-related state 
            SetupNewFreezable(
                geometry,
                (rectangleAnimations == null) // Freeze if there are no animations
                ); 

            // Add animations to the geometry 
            if (rectangleAnimations != null) 
            {
                geometry.ApplyAnimationClock(RectangleGeometry.RectProperty, rectangleAnimations); 
            }

            //
            // Add Drawing to the Drawing graph 
            //
 
            AddNewGeometryDrawing(brush, pen, geometry); 
        }
 
        /// 
        ///     DrawRoundedRectangle -
        ///     Draw a rounded rectangle with the provided Brush and/or Pen.
        ///     If both the Brush and Pen are null this call is a no-op. 
        /// 
        ///  
        ///     The Brush with which to fill the rectangle. 
        ///     This is optional, and can be null, in which case no fill is performed.
        ///  
        /// 
        ///     The Pen with which to stroke the rectangle.
        ///     This is optional, and can be null, in which case no stroke is performed.
        ///  
        ///  The Rect to fill and/or stroke. 
        ///  
        ///     The radius in the X dimension of the rounded corners of this 
        ///     rounded Rect.  This value will be clamped to the range [0..rectangle.Width/2]
        ///  
        /// 
        ///     The radius in the Y dimension of the rounded corners of this
        ///     rounded Rect.  This value will be clamped to the range [0..rectangle.Height/2].
        ///  
        public override void DrawRoundedRectangle(
            Brush brush, 
            Pen pen, 
            Rect rectangle,
            Double radiusX, 
            Double radiusY)
        {

        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("DrawRoundedRectangle(const)");
        #endif 
 
            // Forward call to the animate version with null animations
            DrawRoundedRectangle(brush, pen, rectangle, null, radiusX, null, radiusY, null); 
        }

        /// 
        ///     DrawRoundedRectangle - 
        ///     Draw a rounded rectangle with the provided Brush and/or Pen.
        ///     If both the Brush and Pen are null this call is a no-op. 
        ///  
        /// 
        ///     The Brush with which to fill the rectangle. 
        ///     This is optional, and can be null, in which case no fill is performed.
        /// 
        /// 
        ///     The Pen with which to stroke the rectangle. 
        ///     This is optional, and can be null, in which case no stroke is performed.
        ///  
        ///  The Rect to fill and/or stroke.  
        ///  Optional AnimationClock for rectangle. 
        ///  
        ///     The radius in the X dimension of the rounded corners of this
        ///     rounded Rect.  This value will be clamped to the range [0..rectangle.Width/2]
        /// 
        ///  Optional AnimationClock for radiusX.  
        /// 
        ///     The radius in the Y dimension of the rounded corners of this 
        ///     rounded Rect.  This value will be clamped to the range [0..rectangle.Height/2]. 
        /// 
        ///  Optional AnimationClock for radiusY.  
        public override void DrawRoundedRectangle(
            Brush brush,
            Pen pen,
            Rect rectangle, 
            AnimationClock rectangleAnimations,
            Double radiusX, 
            AnimationClock radiusXAnimations, 
            Double radiusY,
            AnimationClock radiusYAnimations) 
        {

        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("DrawRoundedRectangle(animate)"); 
        #endif
 
            // 
            // Verify that parameters & state are valid
            // 

            VerifyApiNonstructuralChange();

            if ((brush == null) && (pen == null)) 
            {
                return; 
            } 

            // 
            // Create a geometry & add animations if they exist
            //

            // Instantiate the geometry 
            RectangleGeometry geometry = new RectangleGeometry(rectangle, radiusX, radiusY);
 
            // 
            // We may need to opt-out of inheritance through the new Freezable.
            // This is controlled by this.CanBeInheritanceContext. 
            //

            geometry.CanBeInheritanceContext = CanBeInheritanceContext;
 
            // Setup the geometries freezable-related state
            SetupNewFreezable( 
                geometry, 
                (rectangleAnimations == null) &&    // Freeze if animations are null
                (radiusXAnimations == null) && 
                (radiusYAnimations == null)
                );

            // Add animations to the geometry 
            if (rectangleAnimations != null)
            { 
                geometry.ApplyAnimationClock(RectangleGeometry.RectProperty, rectangleAnimations); 
            }
 
            if (radiusXAnimations != null)
            {
                geometry.ApplyAnimationClock(RectangleGeometry.RadiusXProperty, radiusXAnimations);
            } 

            if (radiusYAnimations != null) 
            { 
                geometry.ApplyAnimationClock(RectangleGeometry.RadiusYProperty, radiusYAnimations);
            } 

            //
            // Add Drawing to the Drawing graph
            // 

            AddNewGeometryDrawing(brush, pen, geometry); 
        } 

        ///  
        ///     DrawEllipse -
        ///     Draw an ellipse with the provided Brush and/or Pen.
        ///     If both the Brush and Pen are null this call is a no-op.
        ///  
        /// 
        ///     The Brush with which to fill the ellipse. 
        ///     This is optional, and can be null, in which case no fill is performed. 
        /// 
        ///  
        ///     The Pen with which to stroke the ellipse.
        ///     This is optional, and can be null, in which case no stroke is performed.
        /// 
        ///  
        ///     The center of the ellipse to fill and/or stroke.
        ///  
        ///  
        ///     The radius in the X dimension of the ellipse.
        ///     The absolute value of the radius provided will be used. 
        /// 
        /// 
        ///     The radius in the Y dimension of the ellipse.
        ///     The absolute value of the radius provided will be used. 
        /// 
        public override void DrawEllipse( 
            Brush brush, 
            Pen pen,
            Point center, 
            Double radiusX,
            Double radiusY)
        {
 
        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("DrawEllipse(const)"); 
        #endif 

            // Forward call to the animate version with null animations 
            DrawEllipse(brush, pen, center, null, radiusX, null, radiusY, null);
        }

        ///  
        ///     DrawEllipse -
        ///     Draw an ellipse with the provided Brush and/or Pen. 
        ///     If both the Brush and Pen are null this call is a no-op. 
        /// 
        ///  
        ///     The Brush with which to fill the ellipse.
        ///     This is optional, and can be null, in which case no fill is performed.
        /// 
        ///  
        ///     The Pen with which to stroke the ellipse.
        ///     This is optional, and can be null, in which case no stroke is performed. 
        ///  
        /// 
        ///     The center of the ellipse to fill and/or stroke. 
        /// 
        ///  Optional AnimationClock for center. 
        /// 
        ///     The radius in the X dimension of the ellipse. 
        ///     The absolute value of the radius provided will be used.
        ///  
        ///  Optional AnimationClock for radiusX.  
        /// 
        ///     The radius in the Y dimension of the ellipse. 
        ///     The absolute value of the radius provided will be used.
        /// 
        ///  Optional AnimationClock for radiusY. 
        public override void DrawEllipse( 
            Brush brush,
            Pen pen, 
            Point center, 
            AnimationClock centerAnimations,
            Double radiusX, 
            AnimationClock radiusXAnimations,
            Double radiusY,
            AnimationClock radiusYAnimations)
        { 

        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("DrawEllipse(animate)"); 
        #endif
 
            //
            // Verify that parameters & state are valid
            //
 
            VerifyApiNonstructuralChange();
 
            if ((brush == null) && (pen == null)) 
            {
                return; 
            }

            //
            // Create a geometry & add animations if they exist 
            //
 
            // Instantiate the geometry 
            EllipseGeometry geometry = new EllipseGeometry(center, radiusX, radiusY);
 
            //
            // We may need to opt-out of inheritance through the new Freezable.
            // This is controlled by this.CanBeInheritanceContext.
            // 

            geometry.CanBeInheritanceContext = CanBeInheritanceContext; 
 
            // Setup the geometries freezable-related state
            SetupNewFreezable( 
                geometry,
                (centerAnimations == null) && // Freeze if there are no animations
                (radiusXAnimations == null) &&
                (radiusYAnimations == null) 
                );
 
            // Add animations to the geometry 
            if (centerAnimations != null)
            { 
                geometry.ApplyAnimationClock(EllipseGeometry.CenterProperty, centerAnimations);
            }

            if (radiusXAnimations != null) 
            {
                geometry.ApplyAnimationClock(EllipseGeometry.RadiusXProperty, radiusXAnimations); 
            } 

            if (radiusYAnimations != null) 
            {
                geometry.ApplyAnimationClock(EllipseGeometry.RadiusYProperty, radiusYAnimations);
            }
 
            //
            // Add Drawing to the Drawing graph 
            // 

            AddNewGeometryDrawing(brush, pen, geometry); 
        }
        /// 
        ///     DrawGeometry -
        ///     Draw a Geometry with the provided Brush and/or Pen. 
        ///     If both the Brush and Pen are null this call is a no-op.
        ///  
        ///  
        ///     The Brush with which to fill the Geometry.
        ///     This is optional, and can be null, in which case no fill is performed. 
        /// 
        /// 
        ///     The Pen with which to stroke the Geometry.
        ///     This is optional, and can be null, in which case no stroke is performed. 
        /// 
        ///  The Geometry to fill and/or stroke.  
        public override void DrawGeometry( 
            Brush brush,
            Pen pen, 
            Geometry geometry)
        {

        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("DrawGeometry(const)");
        #endif 
 
            //
            // Create a drawing & add animations if they exist 
            //

            VerifyApiNonstructuralChange();
 
            if (((brush == null) && (pen == null)) || (geometry == null))
            { 
                return; 
            }
 
            AddNewGeometryDrawing(brush, pen, geometry);
        }

        ///  
        ///     DrawImage -
        ///     Draw an Image into the region specified by the Rect. 
        ///     The Image will potentially be stretched and distorted to fit the Rect. 
        ///     For more fine grained control, consider filling a Rect with an ImageBrush via
        ///     DrawRectangle. 
        /// 
        ///  The ImageSource to draw. 
        /// 
        ///     The Rect into which the ImageSource will be fit. 
        /// 
        public override void DrawImage( 
            ImageSource imageSource, 
            Rect rectangle)
        { 

        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("DrawImage(const)");
        #endif 

            // Forward call to the animate version with null animations 
            DrawImage(imageSource, rectangle, null); 
        }
 
        /// 
        ///     DrawImage -
        ///     Draw an Image into the region specified by the Rect.
        ///     The Image will potentially be stretched and distorted to fit the Rect. 
        ///     For more fine grained control, consider filling a Rect with an ImageBrush via
        ///     DrawRectangle. 
        ///  
        ///  The ImageSource to draw. 
        ///  
        ///     The Rect into which the ImageSource will be fit.
        /// 
        ///  Optional AnimationClock for rectangle. 
        public override void DrawImage( 
            ImageSource imageSource,
            Rect rectangle, 
            AnimationClock rectangleAnimations) 
        {
 
        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("DrawImage(animate)");
        #endif
 
            //
            // Verify that parameters & state are valid 
            // 

            VerifyApiNonstructuralChange(); 

            if (imageSource == null)
            {
                return; 
            }
 
            // 
            // Create a drawing & add animations if they exist
            // 

            ImageDrawing imageDrawing = new ImageDrawing();

            // 
            // We may need to opt-out of inheritance through the new Freezable.
            // This is controlled by this.CanBeInheritanceContext. 
            // 

            imageDrawing.CanBeInheritanceContext = CanBeInheritanceContext; 

            imageDrawing.ImageSource = imageSource;
            imageDrawing.Rect = rectangle;
 
            SetupNewFreezable(
                imageDrawing, 
                (null == rectangleAnimations) && // Freeze if there are no animations 
                imageSource.IsFrozen            // and the bitmap source is frozen
                ); 

            if (rectangleAnimations != null)
            {
                imageDrawing.ApplyAnimationClock(ImageDrawing.RectProperty, rectangleAnimations); 
            }
 
            AddDrawing(imageDrawing); 
        }
        ///  
        ///     DrawDrawing -
        ///     Draw a Drawing.
        ///     For more fine grained control, consider filling a Rect with an DrawingBrush via
        ///     DrawRect. 
        /// 
        ///  The Drawing to draw.  
        public override void DrawDrawing( 
            Drawing drawing)
        { 

        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("DrawDrawing(const)");
        #endif 

            // 
            // Verify that parameters & state are valid 
            //
 
            VerifyApiNonstructuralChange();

            if (drawing == null)
            { 
                return;
            } 
 
            //
            // Add the Drawing to the children collection 
            //

            AddDrawing(drawing);
        } 

        ///  
        ///     DrawVideo - 
        ///     Draw a Video into the region specified by the Rect.
        ///     The Video will potentially be stretched and distorted to fit the Rect. 
        ///     For more fine grained control, consider filling a Rect with an VideoBrush via
        ///     DrawRectangle.
        /// 
        ///  The MediaPlayer to draw.  
        /// 
        ///     The Rect into which the MediaPlayer will be fit. 
        ///  
        public override void DrawVideo(
            MediaPlayer player, 
            Rect rectangle)
        {

        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("DrawVideo(const)");
        #endif 
 
            // Forward to non-animate version with null animations
            DrawVideo(player, rectangle, null); 
        }

        /// 
        ///     DrawVideo - 
        ///     Draw a Video into the region specified by the Rect.
        ///     The Video will potentially be stretched and distorted to fit the Rect. 
        ///     For more fine grained control, consider filling a Rect with an VideoBrush via 
        ///     DrawRectangle.
        ///  
        ///  The MediaPlayer to draw. 
        /// 
        ///     The Rect into which the MediaPlayer will be fit.
        ///  
        ///  Optional AnimationClock for rectangle. 
        public override void DrawVideo( 
            MediaPlayer player, 
            Rect rectangle,
            AnimationClock rectangleAnimations) 
        {

        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("DrawVideo(animate)"); 
        #endif
 
            // 
            // Verify that parameters & state are valid
            // 

            VerifyApiNonstructuralChange();

            if (player == null) 
            {
                return; 
            } 

            // 
            // Create a drawing & add animations if they exist
            //

            VideoDrawing videoDrawing = new VideoDrawing(); 

            // 
            // We may need to opt-out of inheritance through the new Freezable. 
            // This is controlled by this.CanBeInheritanceContext.
            // 

            videoDrawing.CanBeInheritanceContext = CanBeInheritanceContext;

            videoDrawing.Player = player; 
            videoDrawing.Rect = rectangle;
 
            SetupNewFreezable( 
                videoDrawing,
                false   // Don't ever freeze a VideoDrawing because it would 
                        // lose it's MediaPlayer
                );

            if (rectangleAnimations != null) 
            {
                videoDrawing.ApplyAnimationClock(VideoDrawing.RectProperty, rectangleAnimations); 
            } 

            AddDrawing(videoDrawing); 
        }

        /// 
        ///     DrawScene3D - 
        ///     Draw a Scene3D (internal object encapsulating a 3D scene)
        ///  
        ///  The Scene3D to draw.  
        internal override void DrawScene3D(
            Scene3D scene3D) 
        {
            // DrawingGroup's do not support DrawScene3D.  DrawScene3D is an internal
            // method only used by RetainedVisual3D, which always represents
            // it's content using RenderData (which does support DrawScene3D). 
            Debug.Assert(false);
        } 
 
        /// 
        ///     PushClip - 
        ///     Push a clip region, which will apply to all drawing primitives until the
        ///     corresponding Pop call.
        /// 
        ///  The Geometry to which we will clip.  
        public override void PushClip(
            Geometry clipGeometry) 
        { 

        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("PushClip(const)");
        #endif

            // 
            // Verify that parameters & state are valid
            // 
 
            VerifyApiNonstructuralChange();
 
            //
            // Instantiate a new drawing group and set it as the _currentDrawingGroup
            //
 
            PushNewDrawingGroup();
 
            // 
            // Set the clip on the new DrawingGroup
            // 

            _currentDrawingGroup.ClipGeometry = clipGeometry;
        }
 
        public override void PushOpacityMask(Brush brush)
        { 
 
        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("PushOpacityMask(const)"); 
        #endif

            //
            // Verify this object's state 
            //
            VerifyApiNonstructuralChange(); 
 
            //
            // Instantiate a new drawing group and set it as the _currentDrawingGroup 
            //
            PushNewDrawingGroup();

            // 
            // Set the opacity mask
            // 
            _currentDrawingGroup.OpacityMask = brush; 
        }
 
        /// 
        ///     PushOpacity -
        ///     Push an opacity which will blend the composite of all drawing primitives added
        ///     until the corresponding Pop call. 
        /// 
        ///  
        ///     The opacity with which to blend - 0 is transparent, 1 is opaque. 
        /// 
        public override void PushOpacity( 
            Double opacity
            )
        {
 
        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("PushOpacity(const)"); 
        #endif 

            // Forward to the animate version with null animations 
            PushOpacity(opacity, null);
        }

        ///  
        ///     PushOpacity -
        ///     Push an opacity which will blend the composite of all drawing primitives added 
        ///     until the corresponding Pop call. 
        /// 
        ///  
        ///     The opacity with which to blend - 0 is transparent, 1 is opaque.
        /// 
        ///  Optional AnimationClock for opacity. 
        public override void PushOpacity( 
            Double opacity,
            AnimationClock opacityAnimations) 
        { 

        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("PushOpacity(animate)");
        #endif

            // 
            // Verify this object's state
            // 
 
            VerifyApiNonstructuralChange();
 
            //
            // Instantiate a new drawing group and set it as the _currentDrawingGroup
            //
 
            PushNewDrawingGroup();
 
            // 
            // Set the opacity & opacity animations on the new DrawingGroup
            // 

            _currentDrawingGroup.Opacity = opacity;

            if (null != opacityAnimations) 
            {
                _currentDrawingGroup.ApplyAnimationClock(DrawingGroup.OpacityProperty, opacityAnimations); 
            } 
        }
        ///  
        ///     PushTransform -
        ///     Push a Transform which will apply to all drawing operations until the corresponding
        ///     Pop.
        ///  
        ///  The Transform to push. 
        public override void PushTransform( 
            Transform transform) 
        {
 
        #if DEBUG
            MediaTrace.DrawingContextOp.Trace("PushTransform(const)");
        #endif
 
            //
            // Verify that parameters & state are valid 
            // 

            VerifyApiNonstructuralChange(); 

            //
            // Instantiate a new drawing group and set it as the _currentDrawingGroup
            // 

            PushNewDrawingGroup(); 
 
            //
            // Set the transform on the new DrawingGroup 
            //

            _currentDrawingGroup.Transform = transform;
        } 

        ///  
        ///     PushGuidelineSet - 
        ///     Push a set of guidelines which should be applied
        ///     to all drawing operations until the 
        ///     corresponding Pop.
        /// 
        ///  The GuidelineSet to push. 
        public override void PushGuidelineSet( 
            GuidelineSet guidelines)
        { 
 
#if DEBUG
            MediaTrace.DrawingContextOp.Trace("PushGuidelineSet"); 
#endif

            //
            // Verify that parameters & state are valid 
            //
 
            VerifyApiNonstructuralChange(); 

            // 
            // Instantiate a new drawing group and set it as the _currentDrawingGroup
            //

            PushNewDrawingGroup(); 

            // 
            // Set the guideline collection on the new DrawingGroup 
            //
 
            _currentDrawingGroup.GuidelineSet = guidelines;
        }

        ///  
        ///     PushGuidelineY1 -
        ///     Explicitly push one horizontal guideline. 
        ///  
        ///  The coordinate of leading guideline. 
        internal override void PushGuidelineY1( 
            Double coordinate)
        {

#if DEBUG 
            MediaTrace.DrawingContextOp.Trace("PushGuidelineY1");
#endif 
 
            //
            // Verify that parameters & state are valid 
            //

            VerifyApiNonstructuralChange();
 
            //
            // Instantiate a new drawing group and set it as the _currentDrawingGroup 
            // 

            PushNewDrawingGroup(); 

            //
            // Convert compact record to generic GuidelineSet.
            // 

            GuidelineSet guidelineCollection = new GuidelineSet( 
                null,                           // x guidelines 
                new double[] { coordinate, 0 }, // y guidelines
                true                            // dynamic flag 
                );
            guidelineCollection.Freeze();

            // 
            // Set the guideline collection on the new DrawingGroup
            // 
 
            _currentDrawingGroup.GuidelineSet = guidelineCollection;
        } 

        /// 
        ///     PushGuidelineY2 -
        ///     Explicitly push a pair of horizontal guidelines. 
        /// 
        ///  The coordinate of leading guideline.  
        ///  
        ///     The offset from leading guideline to driven guideline.
        ///  
        internal override void PushGuidelineY2(
            Double leadingCoordinate,
            Double offsetToDrivenCoordinate)
        { 

#if DEBUG 
            MediaTrace.DrawingContextOp.Trace("PushGuidelineY2"); 
#endif
 
            //
            // Verify that parameters & state are valid
            //
 
            VerifyApiNonstructuralChange();
 
            // 
            // Instantiate a new drawing group and set it as the _currentDrawingGroup
            // 

            PushNewDrawingGroup();

            // 
            // Convert compact record to generic GuidelineSet.
            // 
 
            GuidelineSet guidelineCollection = new GuidelineSet(
                null,                                   // x guidelines 
                new double[]
                    {
                        leadingCoordinate,
                        offsetToDrivenCoordinate 
                    }, // y guidelines
                true                                    // dynamic flag 
                ); 
            guidelineCollection.Freeze();
 
            //
            // Set the guideline collection on the new DrawingGroup
            //
 
            _currentDrawingGroup.GuidelineSet = guidelineCollection;
        } 
 
        /// 
        ///     PushEffect - 
        ///     Push a BitmapEffect which will apply to all drawing operations until the
        ///     corresponding Pop.
        /// 
        ///  The BitmapEffect to push.  
        ///  The BitmapEffectInput. 
        public override void PushEffect( 
            BitmapEffect effect, 
            BitmapEffectInput effectInput)
        { 

#if DEBUG
            MediaTrace.DrawingContextOp.Trace("PushEffect(const)");
#endif 

            // 
            // Verify that parameters & state are valid 
            //
 
            VerifyApiNonstructuralChange();

            //
            // Instantiate a new drawing group and set it as the _currentDrawingGroup 
            //
 
            PushNewDrawingGroup(); 

            // 
            // Set the transform on the new DrawingGroup
            //

            _currentDrawingGroup.BitmapEffect = effect; 
            _currentDrawingGroup.BitmapEffectInput = (effectInput != null) ?
                                                        effectInput : new BitmapEffectInput(); 
 
        }
 
        /// 
        /// Pop
        /// 
        public override void Pop() 
        {
 
        #if DEBUG 
            MediaTrace.DrawingContextOp.Trace("Pop");
        #endif 

            VerifyApiNonstructuralChange();

            // Verify that Pop hasn't been called too many times 
            if ( (_previousDrawingGroupStack == null) ||
                 (_previousDrawingGroupStack.Count == 0)) 
            { 
                throw new InvalidOperationException(SR.Get(SRID.DrawingContext_TooManyPops));
            } 

            // Restore the previous value of the current drawing group
            _currentDrawingGroup = _previousDrawingGroupStack.Pop();
        } 

        ///  
        /// Draw a GlyphRun. 
        /// 
        /// Foreground brush to draw GlyphRun with.  
        ///  The GlyphRun to draw. 
        /// 
        /// This call is illegal if this object has already been closed or disposed.
        ///  
        public override void DrawGlyphRun(Brush foregroundBrush, GlyphRun glyphRun)
        { 
#if DEBUG 
            MediaTrace.DrawingContextOp.Trace("DrawGlyphRun(constant)");
#endif 

            //
            // Verify that parameters & state are valid
            // 

            VerifyApiNonstructuralChange(); 
 
            if (foregroundBrush == null || glyphRun == null)
            { 
                return;
            }

            // Add a GlyphRunDrawing to the Drawing graph 

            GlyphRunDrawing glyphRunDrawing = new GlyphRunDrawing(); 
 
            //
            // We may need to opt-out of inheritance through the new Freezable. 
            // This is controlled by this.CanBeInheritanceContext.
            //

            glyphRunDrawing.CanBeInheritanceContext = CanBeInheritanceContext; 

            glyphRunDrawing.ForegroundBrush = foregroundBrush; 
            glyphRunDrawing.GlyphRun = glyphRun; 

            SetupNewFreezable( 
                glyphRunDrawing,
                foregroundBrush.IsFrozen
                );
 
            AddDrawing(glyphRunDrawing);
        } 
 
        /// 
        /// Dispose() closes this DrawingContext for any further additions, and 
        /// returns it's content to the object that created it.
        /// 
        /// 
        /// Further Draw/Push/Pop calls to this DrawingContext will result in an 
        /// exception.  This method also matches any outstanding Push calls with
        /// a cooresponding Pop.  Calling Close after this object has been closed 
        /// or Disposed will also result in an exception. 
        /// 
        ///  
        /// This call is illegal if this object has already been Closed.
        /// 
        public override void Close()
        { 
            // Throw an exception if this object has already been closed/disposed.
            VerifyNotDisposed(); 
 
            // Close this object
            ((IDisposable)this).Dispose(); 
        }

        /// 
        /// Dispose() closes this DrawingContext for any further additions, and 
        /// returns it's content to the object that created it.
        ///  
        ///  
        /// Further Draw/Push/Pop calls to this DrawingContext will result in an
        /// exception.  This method also matches any outstanding Push calls with 
        /// a cooresponding Pop.  Multiple calls to Dispose will not result in
        /// an exception.
        /// 
        protected override void DisposeCore() 
        {
            // Dispose may be called multiple times without throwing 
            // an exception. 
            if (!_disposed)
            { 
                //
                // Match any outstanding Push calls with a Pop
                //
 
                if (_previousDrawingGroupStack != null)
                { 
                    int stackCount = _previousDrawingGroupStack.Count; 
                    for (int i = 0; i < stackCount; i++)
                    { 
                        Pop();
                    }
                }
 
                //
                // Call CloseCore with the root DrawingGroup's children 
                // 

                DrawingCollection rootChildren; 

                if (_currentDrawingGroup != null)
                 {
                    // If we created a root DrawingGroup because multiple elements 
                    // exist at the root level, provide it's Children collection
                    // directly. 
                    rootChildren = _currentDrawingGroup.Children; 
                }
                else 
                {
                    // Create a new DrawingCollection if we didn't create a
                    // root DrawingGroup because the root level only contained
                    // a single child. 
                    //
                    // This collection is needed by DrawingGroup.Open because 
                    // Open always replaces it's Children collection.  It isn't 
                    // strictly needed for Append, but always using a collection
                    // simplifies the TransactionalAppend implementation (i.e., 
                    // a seperate implemention isn't needed for a single element)
                    rootChildren = new DrawingCollection();

                    // 
                    // We may need to opt-out of inheritance through the new Freezable.
                    // This is controlled by this.CanBeInheritanceContext. 
                    // 

                    rootChildren.CanBeInheritanceContext = CanBeInheritanceContext; 

                    if (_rootDrawing != null)
                    {
                        rootChildren.Add(_rootDrawing); 
                    }
                } 
 
                // Inform our derived classes that Close was called
                CloseCore(rootChildren); 

                _disposed = true;
            }
        } 

        #endregion Public Methods 
 
        #region Protected Methods
 
        /// 
        /// Called during Close/Dispose when the content created this DrawingContext
        /// needs to be committed.
        ///  
        /// 
        ///     Collection containing the Drawing elements created with this 
        ///     DrawingContext. 
        /// 
        ///  
        ///     This will only be called once (at most) per instance.
        /// 
        protected virtual void CloseCore(DrawingCollection rootDrawingGroupChildren)
        { 
            // Default implementation is a no-op
        } 
 
        /// 
        /// Verifies that the DrawingContext is being referenced from the 
        /// appropriate UIContext, and that the object hasn't been disposed
        /// 
        protected override void VerifyApiNonstructuralChange()
        { 
            base.VerifyApiNonstructuralChange();
 
            VerifyNotDisposed(); 
        }
 
        #endregion Protected Methods

        #region Internal Properties
 
        /// 
        /// Determines whether this DrawingContext should connect inheritance contexts 
        /// to DependencyObjects which are passed to its methods. 
        /// This property is modeled after DependencyObject.CanBeInheritanceContext.
        /// Defaults to true. 
        /// NOTE: This is currently only respected by DrawingDrawingContext and sub-classes.
        /// 
        internal bool CanBeInheritanceContext
        { 
            get
            { 
                return _canBeInheritanceContext; 
            }
 
            set
            {
                _canBeInheritanceContext = value;
            } 
        }
 
        #endregion Internal Properties 

        #region Private Methods 

        /// 
        /// Throws an exception if this object is already disposed.
        ///  
        private void VerifyNotDisposed()
        { 
            if (_disposed) 
            {
                throw new ObjectDisposedException("DrawingDrawingContext"); 
            }
        }

        ///  
        /// Freezes the given freezable if the fFreeze flag is true.  Used by
        /// the various drawing methods to freeze resources if there is no 
        /// chance the user might attempt to mutate it. 
        /// (i.e., there are no animations and the dependant properties are
        /// null or themselves frozen.) 
        /// 
        private Freezable SetupNewFreezable(Freezable newFreezable, bool fFreeze)
        {
            if (fFreeze) 
            {
                newFreezable.Freeze(); 
            } 

            return newFreezable; 
        }

        /// 
        /// Contains the functionality common to GeometryDrawing operations of 
        /// instantiating the GeometryDrawing, setting it's Freezable state,
        /// and Adding it to the Drawing Graph. 
        ///  
        private void AddNewGeometryDrawing(Brush brush, Pen pen, Geometry geometry)
        { 
            Debug.Assert(geometry != null);

            // Instantiate the GeometryDrawing
            GeometryDrawing geometryDrawing = new GeometryDrawing(); 

            // 
            // We may need to opt-out of inheritance through the new Freezable. 
            // This is controlled by this.CanBeInheritanceContext.
            // 

            geometryDrawing.CanBeInheritanceContext = CanBeInheritanceContext;

            geometryDrawing.Brush = brush; 
            geometryDrawing.Pen = pen;
            geometryDrawing.Geometry = geometry; 
 
            // Setup it's Freezeable-related state
            SetupNewFreezable( 
                geometryDrawing,
                ((brush == null) || (brush.IsFrozen)) &&    // Freeze if the brush is frozen
                ((pen == null) || (pen.IsFrozen)) &&        // and the pen is frozen
                (geometry.IsFrozen)                         // and the geometry is frozen 
                );
 
            // Add it to the drawing graph 
            AddDrawing(geometryDrawing);
        } 

        /// 
        /// Creates a new DrawingGroup for a Push* call by setting the
        /// _currentDrawingGroup to a newly instantiated DrawingGroup, 
        /// and saving the previous _currentDrawingGroup value on the
        /// _previousDrawingGroupStack. 
        ///  
        private void PushNewDrawingGroup()
        { 
            // Instantiate a new drawing group
            DrawingGroup drawingGroup = new DrawingGroup();

            // 
            // We may need to opt-out of inheritance through the new Freezable.
            // This is controlled by this.CanBeInheritanceContext. 
            // 

            drawingGroup.CanBeInheritanceContext = CanBeInheritanceContext; 

            // Setup it's freezable state
            SetupNewFreezable(
                    drawingGroup, 
                    false // Don't freeze, DrawingGroup's may contain unfrozen children/properties
                    ); 
 
            // Add it to the drawing graph, like any other Drawing
            AddDrawing(drawingGroup); 

            // Lazily allocate the stack when it is needed because many uses
            // of DrawingDrawingContext will have a depth of one.
            if (null == _previousDrawingGroupStack) 
            {
                _previousDrawingGroupStack = new Stack(2); 
            } 

            // Save the previous _currentDrawingGroup value. 
            //
            // If this is the first call, the value of _currentDrawingGroup
            // will be null because AddDrawing doesn't create a _currentDrawingGroup
            // for the first drawing.  Having null on the stack is valid, and simply 
            // denotes that this new DrawingGroup is the first child in the root
            // DrawingGroup.  It is also possible for the first value on the stack 
            // to be non-null, which means that the root DrawingGroup has other 
            // children.
            _previousDrawingGroupStack.Push(_currentDrawingGroup); 

            // Set this drawing group as the current one so that subsequent drawing's
            // are added as it's children until Pop is called.
            _currentDrawingGroup = drawingGroup; 
        }
 
        ///  
        /// Adds a new Drawing to the DrawingGraph.
        /// 
        /// This method avoids creating a DrawingGroup for the common case
        /// where only a single child exists in the root DrawingGroup.
        /// 
        private void AddDrawing(Drawing newDrawing) 
        {
            Debug.Assert(newDrawing != null); 
 
            if (_rootDrawing == null)
            { 
                // When a DrawingGroup is set, it should be made the root if
                // a root drawing didnt exist.
                Debug.Assert(_currentDrawingGroup == null);
 
                // If this is the first Drawing being added, avoid creating a DrawingGroup
                // and set this drawing as the root drawing.  This optimizes the common 
                // case where only a single child exists in the root DrawingGroup. 
                _rootDrawing = newDrawing;
            } 
            else if (_currentDrawingGroup == null)
            {
                // When the second drawing is added at the root level, set a
                // DrawingGroup as the root and add both drawings to it. 

                // Instantiate the DrawingGroup 
                _currentDrawingGroup = new DrawingGroup(); 

                // 
                // We may need to opt-out of inheritance through the new Freezable.
                // This is controlled by this.CanBeInheritanceContext.
                //
 
                _currentDrawingGroup.CanBeInheritanceContext = CanBeInheritanceContext;
 
                SetupNewFreezable( 
                    _currentDrawingGroup,
                    false // Don't freeze DrawingGroups, subsequent Draw calls may modify them 
                    );

                // Add both Children
                _currentDrawingGroup.Children.Add(_rootDrawing); 
                _currentDrawingGroup.Children.Add(newDrawing);
 
                // Set the new DrawingGroup as the current 
                _rootDrawing = _currentDrawingGroup;
            } 
            else
            {
                // If there already is a current drawing group, then simply add
                // the new drawing too it. 
                _currentDrawingGroup.Children.Add(newDrawing);
            } 
        } 

        #endregion Private Methods 

        #region Fields

        // Root drawing created by this DrawingContext. 
        //
        // If there is only a single child of the root DrawingGroup, _rootDrawing 
        // will reference the single child, and the root _currentDrawingGroup 
        // value will be null.  Otherwise, _rootDrawing will reference the
        // root DrawingGroup, and be the same value as the root _currentDrawingGroup. 
        //
        // Either way, _rootDrawing always references the root drawing.
        protected Drawing _rootDrawing;
 
        // Current DrawingGroup that new children are added to
        protected DrawingGroup _currentDrawingGroup; 
 
        // Previous values of _currentDrawingGroup
        private Stack _previousDrawingGroupStack; 

        // Has Dispose() or Close() been called?
        private bool _disposed;
 
        // Determines whether this DrawingContext should connect inheritance contexts
        // to DependencyObjects which are passed to its methods. 
        private bool _canBeInheritanceContext = true; 
        #endregion Fields
    } 
}


 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK