DrawingGroup.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Core / CSharp / System / Windows / Media / DrawingGroup.cs / 1 / DrawingGroup.cs

                            //---------------------------------------------------------------------------- 
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// Description: DrawingGroup represents a collection of Drawing objects, and 
//              can apply group-operations such as clip and opacity to it's
//              collections 
// 
// History:
// 
//  2004/11/17 : timothyc - Created it.
//
//---------------------------------------------------------------------------
 
using System;
using System.Windows.Threading; 
 
using MS.Win32;
using System.Security; 
using System.Security.Permissions;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging; 
using System.Windows.Media.Animation;
using System.Windows.Media.Composition; 
using System.Windows.Media.Effects; 
using System.Diagnostics;
using System.Collections; 
using System.Collections.Generic;
using MS.Internal;
using MS.Internal.Media;
using System.Resources; 
using MS.Utility;
using System.Runtime.InteropServices; 
using MS.Internal.PresentationCore; 
using System.ComponentModel.Design.Serialization;
using System.ComponentModel; 

using SR = MS.Internal.PresentationCore.SR;
using SRID = MS.Internal.PresentationCore.SRID;
 
namespace System.Windows.Media
{ 
    ///  
    /// DrawingGroup represents a collection of Drawing objects, and
    /// can apply group-operations such as clip and opacity to it's 
    /// collections.
    /// 
    [ContentProperty("Children")]
    public sealed partial class DrawingGroup : Drawing 
    {
        #region Constructors 
 
        /// 
        /// Default DrawingGroup constructor. 
        /// Constructs an object with all properties set to their default values.
        /// 
        public DrawingGroup()
        { 
        }
 
        #endregion Constructors 

        #region Public methods 

        /// 
        /// Opens the DrawingGroup for re-populating it's children, clearing any existing
        /// children. 
        /// 
        ///  
        /// Returns DrawingContext to populate the DrawingGroup's children. 
        /// 
        public DrawingContext Open() 
        {
            VerifyOpen();

            _openedForAppend = false; 

            return new DrawingGroupDrawingContext(this); 
        } 

        ///  
        /// Opens the DrawingGroup for populating it's children, appending to
        /// any existing children in the collection.
        /// 
        ///  
        /// Returns DrawingContext to populate the DrawingGroup's children.
        ///  
        public DrawingContext Append() 
        {
            VerifyOpen(); 

            _openedForAppend = true;

            return new DrawingGroupDrawingContext(this); 
        }
 
        #endregion Public methods 

        #region Internal methods 

        /// 
        /// Called by a DrawingContext returned from Open or Append when the content
        /// created by it needs to be committed (because DrawingContext.Close/Dispose 
        /// was called)
        ///  
        ///  
        ///     Collection containing the Drawing elements created by a DrawingContext
        ///     returned from Open or Append. 
        /// 
        internal void Close(DrawingCollection rootDrawingGroupChildren)
        {
            WritePreamble(); 

            Debug.Assert(_open); 
            Debug.Assert(rootDrawingGroupChildren != null); 

            if (!_openedForAppend) 
            {
                // Clear out the previous contents by replacing the current collection with
                // the new collection.
                // 
                // When more than one element exists in rootDrawingGroupChildren, the
                // DrawingContext had to create this new collection anyways.  To behave 
                // consistently between the one-element and many-element cases, 
                // we always set Children to a new DrawingCollection instance during Close().
                // 
                // Doing this also avoids having to protect against exceptions being thrown
                // from user-code, which could be executed if a Changed event was fired when
                // we tried to add elements to a pre-existing collection.
                // 
                // The collection created by the DrawingContext will no longer be
                // used after the DrawingContext is closed, so we can take ownership 
                // of the reference here to avoid any more unneccesary copies. 
                Children = rootDrawingGroupChildren;
            } 
            else
            {
                //
                // 
                // Append the collection to the current Children collection
                // 
                // 
                DrawingCollection children = Children;
 
                //
                // Ensure that we can Append to the Children collection
                //
 
                if (children == null)
                { 
                    throw new InvalidOperationException(SR.Get(SRID.DrawingGroup_CannotAppendToNullCollection)); 
                }
 
                if (children.IsFrozen)
                {
                    throw new InvalidOperationException(SR.Get(SRID.DrawingGroup_CannotAppendToFrozenCollection));
                } 

                // Append the new collection to our current Children. 
                // 
                // TransactionalAppend rolls-back the Append operation in the event
                // an exception is thrown from the Changed event. 
                children.TransactionalAppend(rootDrawingGroupChildren);
            }

            // This DrawingGroup is no longer open 
            _open = false;
        } 
 
        /// 
        /// Called when an object needs to Update it's realizations. 
        /// Currently, GlyphRun is the only MIL object that needs realization
        /// updates.  Because a DrawingGroup may contain a GlyphRunDrawing
        /// somewhere in it's children collection, this message is forwarded to
        /// all Children. 
        /// 
        internal override void UpdateRealizations(RealizationContext realizationContext) 
        { 
            if (RequiresRealizationUpdates)
            { 
                Transform transform = Transform;

                // Avoid calling PushTransform if the base value is set to the default and
                // no animations have been set on the property. 
                if (transform != null)
                { 
                    realizationContext.TransformStack.Push(transform, true /* combine */); 
                }
 
                DrawingCollection children = Children;


               if (children != null) 
               {
                   for (int i = 0; i < children.Count; i++) 
                   { 
                       children.Internal_GetItem(i).UpdateRealizations(realizationContext);
                   } 
                }

                if (BitmapEffect != null)
                { 
                    if (BitmapEffectDrawing.ScheduleForUpdates)
                    { 
                        BitmapEffectDrawingContent content = new BitmapEffectDrawingContent(this, realizationContext); 
                        realizationContext.ScheduleForRealizationsUpdate(content);
 
                        _bitmapEffectDrawing = null;
                        BitmapEffectDrawing.ScheduleForUpdates = false;
                    }
 
                    BitmapEffectDrawing.UpdateRealizations(realizationContext);
                } 
 
                if (transform != null)
                { 
                    realizationContext.TransformStack.Pop();
                }
            }
        } 

        ///  
        /// PrecomputeCore 
        ///
        /// Precomputes recursively the children of the DrawingGroup. If any 
        /// child needs realization updates, it sets the RequriesRealizationUpdates
        /// to true.
        /// 
        internal override void PrecomputeCore() 
        {
            DrawingCollection children = Children; 
 
            // Reset the RequiresRealizationUpdate flag.
 
            RequiresRealizationUpdates = false;

            if (children != null)
            { 
                // Recurse into all the children.
 
                int count = children.Count; 
                for (int i = 0; i < count; i++)
                { 
                    Drawing child = children.Internal_GetItem(i);
                    child.PrecomputeCore(); // Precompute must be called for each child
                                            // so that the RequiresRealizationUpdates flag
                                            // is properly maintained. 
                    if (child.RequiresRealizationUpdates)
                    { 
                        // If a child needs realization updates, this drawing node must be 
                        // marked.
                        RequiresRealizationUpdates = true; 
                    }
                }
             }
 
             // if it has a bitmap effect, it needs a realization update
             if (BitmapEffect != null) 
             { 
                 RequiresRealizationUpdates = true;
             } 
        }


 
        /// 
        /// Render the group using the BitmapVisualManager, apply the effect 
        /// and marshal the bitmap over the UCE to draw 
        /// 
        internal void RenderBitmapEffect(DUCE.Channel channel) 
        {
            int drawingsCount = BitmapEffectDrawing.Drawings.Count;
            for (int iTransform = BitmapEffectDrawing.WorldTransforms.Count - 1;
                     iTransform >= drawingsCount; iTransform--) 
            {
                DrawingGroup group = new DrawingGroup(); 
                // we only want to render the children and opacity 
                // clip, transform, offset, etc. are applied above the effect
                group.Children = Children; 
                group.Opacity = Opacity;
                group.OpacityMask = OpacityMask;

                // render to group to a bitmap 
                BitmapEffectDrawingContextState effectState = new BitmapEffectDrawingContextState(BitmapEffect, BitmapEffectInput);
                effectState.Context.DrawDrawing(group); 
                effectState.Context.Close(); 

                Matrix transform = BitmapEffectDrawing.WorldTransforms[iTransform].Value; 
                BitmapSource effectImage = effectState.RenderBitmapEffect(ref transform, BitmapEffectDrawing.WindowClip);

                if (effectImage != null)
                { 
                    // if there was no group for that transform create one
                    // and update it, otherwise we don't need to do anything it 
                    DrawingGroup effectGroup = new DrawingGroup(); 
                    effectGroup.Children.Add(new ImageDrawing(effectImage,
                            new Rect(0, 0, effectImage.Width, effectImage.Height))); 
                    effectGroup.Transform = new MatrixTransform(transform);

                    BitmapEffectDrawing.Drawings.Insert(drawingsCount, effectGroup);
                } 
                else
                { 
                    BitmapEffectDrawing.WorldTransforms.RemoveAt(iTransform); 
                }
            } 


            // if we have realised any drawings, set the content for
            // this drawing group to the bitmap effect realizations 
            if (BitmapEffectDrawing.WorldTransforms.Count > 0)
            { 
                DUCE.ResourceHandle drawingGroupHandle = 
                ((DUCE.IResource)this).GetHandle(channel);
 
                ((DUCE.IResource)BitmapEffectDrawing).AddRefOnChannel(channel);
                DUCE.DrawingGroupNode.SetContent(
                    drawingGroupHandle,
                    ((DUCE.IResource)BitmapEffectDrawing).GetHandle(channel), 
                    channel);
 
                ((DUCE.IResource)BitmapEffectDrawing).ReleaseOnChannel(channel); 
            }
 
            BitmapEffectDrawing.ScheduleForUpdates = true;

        }
 
        /// 
        /// Calls methods on the DrawingContext that are equivalent to the 
        /// Drawing with the Drawing's current value. 
        /// 
        internal override void WalkCurrentValue(DrawingContextWalker ctx) 
        {
            int popCount = 0;

            // We avoid unneccessary ShouldStopWalking checks based on assumptions 
            // about when ShouldStopWalking is set.  Guard that assumption with an
            // assertion. 
            // 
            // ShouldStopWalking is currently only set during a hit-test walk after
            // an object has been hit.  Because a DrawingGroup can't be hit until after 
            // the first Drawing is tested, this method doesn't check ShouldStopWalking
            // until after the first child.
            //
            // We don't need to add this check to other Drawing subclasses for 
            // the same reason -- if the Drawing being tested isn't a DrawingGroup,
            // they are always the 'first child'. 
            // 
            // If this assumption is ever broken then the ShouldStopWalking
            // check should be done on the first child -- including in the 
            // WalkCurrentValue method of other Drawing subclasses.
            Debug.Assert(!ctx.ShouldStopWalking);

            // 
            // Draw the transform property
            // 
 
            // Avoid calling PushTransform if the base value is set to the default and
            // no animations have been set on the property. 
            if (!IsBaseValueDefault(DrawingGroup.TransformProperty) ||
                (null != AnimationStorage.GetStorage(this, DrawingGroup.TransformProperty)))
            {
                ctx.PushTransform(Transform); 

                popCount++; 
            } 

            // 
            // Draw the clip property
            //

            // Avoid calling PushClip if the base value is set to the default and 
            // no animations have been set on the property.
            if (!IsBaseValueDefault(DrawingGroup.ClipGeometryProperty) || 
                (null != AnimationStorage.GetStorage(this, DrawingGroup.ClipGeometryProperty))) 
            {
                ctx.PushClip(ClipGeometry); 

                popCount++;
            }
 
            //
            // Draw the opacity property 
            // 

            // Avoid calling PushOpacity if the base value is set to the default and 
            // no animations have been set on the property.
            if (!IsBaseValueDefault(DrawingGroup.OpacityProperty) ||
                (null != AnimationStorage.GetStorage(this, DrawingGroup.OpacityProperty)))
            { 
                // Push the current value of the opacity property, which
                // is what Opacity returns. 
                ctx.PushOpacity(Opacity); 

                popCount++; 
            }

            // Draw the opacity mask property
            // 
            if (OpacityMask != null)
            { 
                ctx.PushOpacityMask(OpacityMask); 
                popCount++;
            } 

            //
            // Draw the effect property
            // 

            // Push the current value of the effect property, which 
            // is what BitmapEffect returns. 
            if (BitmapEffect != null)
            { 
                ctx.PushEffect(BitmapEffect, BitmapEffectInput);

                popCount++;
            } 

            // 
            // Draw the Children collection 
            //
 
            // Get the current value of the children collection
            DrawingCollection collection = Children;

            // Call Walk on each child 
            if (collection != null)
            { 
                for (int i = 0; i < collection.Count; i++) 
                {
                    Drawing drawing = collection.Internal_GetItem(i); 
                    if (drawing != null)
                    {
                        drawing.WalkCurrentValue(ctx);
 
                        // Don't visit the remaining children if the previous
                        // child caused us to stop walking. 
                        if (ctx.ShouldStopWalking) 
                        {
                            break; 
                        }
                    }
                }
            } 

            // 
            // Call Pop() for every Push 
            //
            // Avoid placing this logic in a finally block because if an exception is 
            // thrown, the Walk is simply aborted.  There is no requirement to Walk
            // through Pop instructions when an exception is thrown.
            //
 
            for (int i = 0; i < popCount; i++)
            { 
                ctx.Pop(); 
            }
        } 


        #endregion Internal methods
 
        #region Internal Properties
        internal BitmapEffectDrawing BitmapEffectDrawing 
        { 
            get
            { 
                if (_bitmapEffectDrawing == null)
                {
                    _bitmapEffectDrawing = new BitmapEffectDrawing();
                } 

                return _bitmapEffectDrawing; 
            } 
        }
        #endregion Internal Properties 

        #region Private Methods

        ///  
        /// Called by both Open() and Append(), this method verifies the
        /// DrawingGroup isn't already open, and set's the open flag. 
        ///  
        private void VerifyOpen()
        { 
            WritePreamble();

            // Throw an exception if we are already opened
            if (_open) 
            {
                throw new InvalidOperationException(SR.Get(SRID.DrawingGroup_AlreadyOpen)); 
            } 

            _open = true; 
        }

        /// 
        /// Invalidate caches if the effect changed 
        /// 
        private void BitmapEffectPropertyChangedHook(DependencyPropertyChangedEventArgs e) 
        { 
            ResetGroupContent();
        } 

        /// 
        /// Invalidate caches if the input changed
        ///  
        private void BitmapEffectInputPropertyChangedHook(DependencyPropertyChangedEventArgs e)
        { 
            ResetGroupContent(); 
        }
 
        /// 
        /// Reset the bitmap effect content if the group is on channel and
        /// clear the realizations
        ///  
        private void ResetGroupContent()
        { 
            DUCE.Channel channel = MediaContext.From(Dispatcher).Channel; 

            DUCE.ResourceHandle drawingGroupHandle = 
                ((DUCE.IResource)this).GetHandle(channel);

            if (!drawingGroupHandle.IsNull)
            { 
                DUCE.DrawingGroupNode.SetContent(
                    drawingGroupHandle, 
                    DUCE.ResourceHandle.Null, 
                    channel);
            } 

            _bitmapEffectDrawing = null;
        }
        #endregion Private Methods 

        #region Private fields 
 
        private bool _openedForAppend;
        private bool _open; 
        private BitmapEffectDrawing _bitmapEffectDrawing;
        #endregion Private fields
    }
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------------- 
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// Description: DrawingGroup represents a collection of Drawing objects, and 
//              can apply group-operations such as clip and opacity to it's
//              collections 
// 
// History:
// 
//  2004/11/17 : timothyc - Created it.
//
//---------------------------------------------------------------------------
 
using System;
using System.Windows.Threading; 
 
using MS.Win32;
using System.Security; 
using System.Security.Permissions;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging; 
using System.Windows.Media.Animation;
using System.Windows.Media.Composition; 
using System.Windows.Media.Effects; 
using System.Diagnostics;
using System.Collections; 
using System.Collections.Generic;
using MS.Internal;
using MS.Internal.Media;
using System.Resources; 
using MS.Utility;
using System.Runtime.InteropServices; 
using MS.Internal.PresentationCore; 
using System.ComponentModel.Design.Serialization;
using System.ComponentModel; 

using SR = MS.Internal.PresentationCore.SR;
using SRID = MS.Internal.PresentationCore.SRID;
 
namespace System.Windows.Media
{ 
    ///  
    /// DrawingGroup represents a collection of Drawing objects, and
    /// can apply group-operations such as clip and opacity to it's 
    /// collections.
    /// 
    [ContentProperty("Children")]
    public sealed partial class DrawingGroup : Drawing 
    {
        #region Constructors 
 
        /// 
        /// Default DrawingGroup constructor. 
        /// Constructs an object with all properties set to their default values.
        /// 
        public DrawingGroup()
        { 
        }
 
        #endregion Constructors 

        #region Public methods 

        /// 
        /// Opens the DrawingGroup for re-populating it's children, clearing any existing
        /// children. 
        /// 
        ///  
        /// Returns DrawingContext to populate the DrawingGroup's children. 
        /// 
        public DrawingContext Open() 
        {
            VerifyOpen();

            _openedForAppend = false; 

            return new DrawingGroupDrawingContext(this); 
        } 

        ///  
        /// Opens the DrawingGroup for populating it's children, appending to
        /// any existing children in the collection.
        /// 
        ///  
        /// Returns DrawingContext to populate the DrawingGroup's children.
        ///  
        public DrawingContext Append() 
        {
            VerifyOpen(); 

            _openedForAppend = true;

            return new DrawingGroupDrawingContext(this); 
        }
 
        #endregion Public methods 

        #region Internal methods 

        /// 
        /// Called by a DrawingContext returned from Open or Append when the content
        /// created by it needs to be committed (because DrawingContext.Close/Dispose 
        /// was called)
        ///  
        ///  
        ///     Collection containing the Drawing elements created by a DrawingContext
        ///     returned from Open or Append. 
        /// 
        internal void Close(DrawingCollection rootDrawingGroupChildren)
        {
            WritePreamble(); 

            Debug.Assert(_open); 
            Debug.Assert(rootDrawingGroupChildren != null); 

            if (!_openedForAppend) 
            {
                // Clear out the previous contents by replacing the current collection with
                // the new collection.
                // 
                // When more than one element exists in rootDrawingGroupChildren, the
                // DrawingContext had to create this new collection anyways.  To behave 
                // consistently between the one-element and many-element cases, 
                // we always set Children to a new DrawingCollection instance during Close().
                // 
                // Doing this also avoids having to protect against exceptions being thrown
                // from user-code, which could be executed if a Changed event was fired when
                // we tried to add elements to a pre-existing collection.
                // 
                // The collection created by the DrawingContext will no longer be
                // used after the DrawingContext is closed, so we can take ownership 
                // of the reference here to avoid any more unneccesary copies. 
                Children = rootDrawingGroupChildren;
            } 
            else
            {
                //
                // 
                // Append the collection to the current Children collection
                // 
                // 
                DrawingCollection children = Children;
 
                //
                // Ensure that we can Append to the Children collection
                //
 
                if (children == null)
                { 
                    throw new InvalidOperationException(SR.Get(SRID.DrawingGroup_CannotAppendToNullCollection)); 
                }
 
                if (children.IsFrozen)
                {
                    throw new InvalidOperationException(SR.Get(SRID.DrawingGroup_CannotAppendToFrozenCollection));
                } 

                // Append the new collection to our current Children. 
                // 
                // TransactionalAppend rolls-back the Append operation in the event
                // an exception is thrown from the Changed event. 
                children.TransactionalAppend(rootDrawingGroupChildren);
            }

            // This DrawingGroup is no longer open 
            _open = false;
        } 
 
        /// 
        /// Called when an object needs to Update it's realizations. 
        /// Currently, GlyphRun is the only MIL object that needs realization
        /// updates.  Because a DrawingGroup may contain a GlyphRunDrawing
        /// somewhere in it's children collection, this message is forwarded to
        /// all Children. 
        /// 
        internal override void UpdateRealizations(RealizationContext realizationContext) 
        { 
            if (RequiresRealizationUpdates)
            { 
                Transform transform = Transform;

                // Avoid calling PushTransform if the base value is set to the default and
                // no animations have been set on the property. 
                if (transform != null)
                { 
                    realizationContext.TransformStack.Push(transform, true /* combine */); 
                }
 
                DrawingCollection children = Children;


               if (children != null) 
               {
                   for (int i = 0; i < children.Count; i++) 
                   { 
                       children.Internal_GetItem(i).UpdateRealizations(realizationContext);
                   } 
                }

                if (BitmapEffect != null)
                { 
                    if (BitmapEffectDrawing.ScheduleForUpdates)
                    { 
                        BitmapEffectDrawingContent content = new BitmapEffectDrawingContent(this, realizationContext); 
                        realizationContext.ScheduleForRealizationsUpdate(content);
 
                        _bitmapEffectDrawing = null;
                        BitmapEffectDrawing.ScheduleForUpdates = false;
                    }
 
                    BitmapEffectDrawing.UpdateRealizations(realizationContext);
                } 
 
                if (transform != null)
                { 
                    realizationContext.TransformStack.Pop();
                }
            }
        } 

        ///  
        /// PrecomputeCore 
        ///
        /// Precomputes recursively the children of the DrawingGroup. If any 
        /// child needs realization updates, it sets the RequriesRealizationUpdates
        /// to true.
        /// 
        internal override void PrecomputeCore() 
        {
            DrawingCollection children = Children; 
 
            // Reset the RequiresRealizationUpdate flag.
 
            RequiresRealizationUpdates = false;

            if (children != null)
            { 
                // Recurse into all the children.
 
                int count = children.Count; 
                for (int i = 0; i < count; i++)
                { 
                    Drawing child = children.Internal_GetItem(i);
                    child.PrecomputeCore(); // Precompute must be called for each child
                                            // so that the RequiresRealizationUpdates flag
                                            // is properly maintained. 
                    if (child.RequiresRealizationUpdates)
                    { 
                        // If a child needs realization updates, this drawing node must be 
                        // marked.
                        RequiresRealizationUpdates = true; 
                    }
                }
             }
 
             // if it has a bitmap effect, it needs a realization update
             if (BitmapEffect != null) 
             { 
                 RequiresRealizationUpdates = true;
             } 
        }


 
        /// 
        /// Render the group using the BitmapVisualManager, apply the effect 
        /// and marshal the bitmap over the UCE to draw 
        /// 
        internal void RenderBitmapEffect(DUCE.Channel channel) 
        {
            int drawingsCount = BitmapEffectDrawing.Drawings.Count;
            for (int iTransform = BitmapEffectDrawing.WorldTransforms.Count - 1;
                     iTransform >= drawingsCount; iTransform--) 
            {
                DrawingGroup group = new DrawingGroup(); 
                // we only want to render the children and opacity 
                // clip, transform, offset, etc. are applied above the effect
                group.Children = Children; 
                group.Opacity = Opacity;
                group.OpacityMask = OpacityMask;

                // render to group to a bitmap 
                BitmapEffectDrawingContextState effectState = new BitmapEffectDrawingContextState(BitmapEffect, BitmapEffectInput);
                effectState.Context.DrawDrawing(group); 
                effectState.Context.Close(); 

                Matrix transform = BitmapEffectDrawing.WorldTransforms[iTransform].Value; 
                BitmapSource effectImage = effectState.RenderBitmapEffect(ref transform, BitmapEffectDrawing.WindowClip);

                if (effectImage != null)
                { 
                    // if there was no group for that transform create one
                    // and update it, otherwise we don't need to do anything it 
                    DrawingGroup effectGroup = new DrawingGroup(); 
                    effectGroup.Children.Add(new ImageDrawing(effectImage,
                            new Rect(0, 0, effectImage.Width, effectImage.Height))); 
                    effectGroup.Transform = new MatrixTransform(transform);

                    BitmapEffectDrawing.Drawings.Insert(drawingsCount, effectGroup);
                } 
                else
                { 
                    BitmapEffectDrawing.WorldTransforms.RemoveAt(iTransform); 
                }
            } 


            // if we have realised any drawings, set the content for
            // this drawing group to the bitmap effect realizations 
            if (BitmapEffectDrawing.WorldTransforms.Count > 0)
            { 
                DUCE.ResourceHandle drawingGroupHandle = 
                ((DUCE.IResource)this).GetHandle(channel);
 
                ((DUCE.IResource)BitmapEffectDrawing).AddRefOnChannel(channel);
                DUCE.DrawingGroupNode.SetContent(
                    drawingGroupHandle,
                    ((DUCE.IResource)BitmapEffectDrawing).GetHandle(channel), 
                    channel);
 
                ((DUCE.IResource)BitmapEffectDrawing).ReleaseOnChannel(channel); 
            }
 
            BitmapEffectDrawing.ScheduleForUpdates = true;

        }
 
        /// 
        /// Calls methods on the DrawingContext that are equivalent to the 
        /// Drawing with the Drawing's current value. 
        /// 
        internal override void WalkCurrentValue(DrawingContextWalker ctx) 
        {
            int popCount = 0;

            // We avoid unneccessary ShouldStopWalking checks based on assumptions 
            // about when ShouldStopWalking is set.  Guard that assumption with an
            // assertion. 
            // 
            // ShouldStopWalking is currently only set during a hit-test walk after
            // an object has been hit.  Because a DrawingGroup can't be hit until after 
            // the first Drawing is tested, this method doesn't check ShouldStopWalking
            // until after the first child.
            //
            // We don't need to add this check to other Drawing subclasses for 
            // the same reason -- if the Drawing being tested isn't a DrawingGroup,
            // they are always the 'first child'. 
            // 
            // If this assumption is ever broken then the ShouldStopWalking
            // check should be done on the first child -- including in the 
            // WalkCurrentValue method of other Drawing subclasses.
            Debug.Assert(!ctx.ShouldStopWalking);

            // 
            // Draw the transform property
            // 
 
            // Avoid calling PushTransform if the base value is set to the default and
            // no animations have been set on the property. 
            if (!IsBaseValueDefault(DrawingGroup.TransformProperty) ||
                (null != AnimationStorage.GetStorage(this, DrawingGroup.TransformProperty)))
            {
                ctx.PushTransform(Transform); 

                popCount++; 
            } 

            // 
            // Draw the clip property
            //

            // Avoid calling PushClip if the base value is set to the default and 
            // no animations have been set on the property.
            if (!IsBaseValueDefault(DrawingGroup.ClipGeometryProperty) || 
                (null != AnimationStorage.GetStorage(this, DrawingGroup.ClipGeometryProperty))) 
            {
                ctx.PushClip(ClipGeometry); 

                popCount++;
            }
 
            //
            // Draw the opacity property 
            // 

            // Avoid calling PushOpacity if the base value is set to the default and 
            // no animations have been set on the property.
            if (!IsBaseValueDefault(DrawingGroup.OpacityProperty) ||
                (null != AnimationStorage.GetStorage(this, DrawingGroup.OpacityProperty)))
            { 
                // Push the current value of the opacity property, which
                // is what Opacity returns. 
                ctx.PushOpacity(Opacity); 

                popCount++; 
            }

            // Draw the opacity mask property
            // 
            if (OpacityMask != null)
            { 
                ctx.PushOpacityMask(OpacityMask); 
                popCount++;
            } 

            //
            // Draw the effect property
            // 

            // Push the current value of the effect property, which 
            // is what BitmapEffect returns. 
            if (BitmapEffect != null)
            { 
                ctx.PushEffect(BitmapEffect, BitmapEffectInput);

                popCount++;
            } 

            // 
            // Draw the Children collection 
            //
 
            // Get the current value of the children collection
            DrawingCollection collection = Children;

            // Call Walk on each child 
            if (collection != null)
            { 
                for (int i = 0; i < collection.Count; i++) 
                {
                    Drawing drawing = collection.Internal_GetItem(i); 
                    if (drawing != null)
                    {
                        drawing.WalkCurrentValue(ctx);
 
                        // Don't visit the remaining children if the previous
                        // child caused us to stop walking. 
                        if (ctx.ShouldStopWalking) 
                        {
                            break; 
                        }
                    }
                }
            } 

            // 
            // Call Pop() for every Push 
            //
            // Avoid placing this logic in a finally block because if an exception is 
            // thrown, the Walk is simply aborted.  There is no requirement to Walk
            // through Pop instructions when an exception is thrown.
            //
 
            for (int i = 0; i < popCount; i++)
            { 
                ctx.Pop(); 
            }
        } 


        #endregion Internal methods
 
        #region Internal Properties
        internal BitmapEffectDrawing BitmapEffectDrawing 
        { 
            get
            { 
                if (_bitmapEffectDrawing == null)
                {
                    _bitmapEffectDrawing = new BitmapEffectDrawing();
                } 

                return _bitmapEffectDrawing; 
            } 
        }
        #endregion Internal Properties 

        #region Private Methods

        ///  
        /// Called by both Open() and Append(), this method verifies the
        /// DrawingGroup isn't already open, and set's the open flag. 
        ///  
        private void VerifyOpen()
        { 
            WritePreamble();

            // Throw an exception if we are already opened
            if (_open) 
            {
                throw new InvalidOperationException(SR.Get(SRID.DrawingGroup_AlreadyOpen)); 
            } 

            _open = true; 
        }

        /// 
        /// Invalidate caches if the effect changed 
        /// 
        private void BitmapEffectPropertyChangedHook(DependencyPropertyChangedEventArgs e) 
        { 
            ResetGroupContent();
        } 

        /// 
        /// Invalidate caches if the input changed
        ///  
        private void BitmapEffectInputPropertyChangedHook(DependencyPropertyChangedEventArgs e)
        { 
            ResetGroupContent(); 
        }
 
        /// 
        /// Reset the bitmap effect content if the group is on channel and
        /// clear the realizations
        ///  
        private void ResetGroupContent()
        { 
            DUCE.Channel channel = MediaContext.From(Dispatcher).Channel; 

            DUCE.ResourceHandle drawingGroupHandle = 
                ((DUCE.IResource)this).GetHandle(channel);

            if (!drawingGroupHandle.IsNull)
            { 
                DUCE.DrawingGroupNode.SetContent(
                    drawingGroupHandle, 
                    DUCE.ResourceHandle.Null, 
                    channel);
            } 

            _bitmapEffectDrawing = null;
        }
        #endregion Private Methods 

        #region Private fields 
 
        private bool _openedForAppend;
        private bool _open; 
        private BitmapEffectDrawing _bitmapEffectDrawing;
        #endregion Private fields
    }
} 


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

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