Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / 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
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ColumnResizeUndoUnit.cs
- UnmanagedMemoryStream.cs
- UIntPtr.cs
- CodeAttributeDeclaration.cs
- XmlPreloadedResolver.cs
- XmlSchemaCompilationSettings.cs
- EntityDataSourceDesignerHelper.cs
- UnicastIPAddressInformationCollection.cs
- TextRangeEditTables.cs
- DataObjectMethodAttribute.cs
- SessionViewState.cs
- ArgumentValueSerializer.cs
- SortKey.cs
- DataControlExtensions.cs
- BaseCAMarshaler.cs
- ExceptionValidationRule.cs
- SqlInternalConnectionSmi.cs
- DateTimeSerializationSection.cs
- ToolStripTextBox.cs
- CompilerErrorCollection.cs
- ObjectViewEntityCollectionData.cs
- ListItemConverter.cs
- TreeNodeCollection.cs
- TypefaceMap.cs
- ConnectionStringSettingsCollection.cs
- WebControlParameterProxy.cs
- QilList.cs
- ExtendedPropertyCollection.cs
- DataMemberAttribute.cs
- HebrewCalendar.cs
- TemplateKey.cs
- GeometryCollection.cs
- BindingManagerDataErrorEventArgs.cs
- RequiredAttributeAttribute.cs
- MgmtConfigurationRecord.cs
- FragmentQueryKB.cs
- Filter.cs
- LocationUpdates.cs
- ExceptionUtility.cs
- MetafileHeaderWmf.cs
- XmlSchemaAttribute.cs
- UserControlCodeDomTreeGenerator.cs
- JavaScriptObjectDeserializer.cs
- DocumentXmlWriter.cs
- SyntaxCheck.cs
- SqlDataSourceCache.cs
- Control.cs
- ApplicationActivator.cs
- XmlMembersMapping.cs
- EndpointDiscoveryElement.cs
- JsonReader.cs
- DataSourceXmlSubItemAttribute.cs
- UseAttributeSetsAction.cs
- BitmapImage.cs
- SendActivityEventArgs.cs
- ResourceDictionaryCollection.cs
- Context.cs
- PackWebRequestFactory.cs
- TextClipboardData.cs
- VerificationException.cs
- ConfigurationManagerHelperFactory.cs
- ToolboxDataAttribute.cs
- EntityDataSourceDesignerHelper.cs
- MailMessageEventArgs.cs
- EncodingNLS.cs
- AsyncOperationManager.cs
- MethodSignatureGenerator.cs
- Brushes.cs
- PasswordBoxAutomationPeer.cs
- ButtonPopupAdapter.cs
- RequestQueue.cs
- ListenerElementsCollection.cs
- DbInsertCommandTree.cs
- GeneralTransformGroup.cs
- ProviderConnectionPoint.cs
- ConfigXmlAttribute.cs
- ActiveDocumentEvent.cs
- HostUtils.cs
- SynchronizationLockException.cs
- SiteMapDataSourceView.cs
- MarginsConverter.cs
- StrokeIntersection.cs
- InProcStateClientManager.cs
- SettingsPropertyValue.cs
- HandledEventArgs.cs
- LinkConverter.cs
- PermissionSet.cs
- ZipFileInfo.cs
- XmlTextReaderImpl.cs
- Stack.cs
- SimpleWorkerRequest.cs
- EdmTypeAttribute.cs
- WebPartVerbCollection.cs
- DataGridViewIntLinkedList.cs
- CollectionViewGroupRoot.cs
- NavigationService.cs
- CapabilitiesUse.cs
- CodeCompiler.cs
- ButtonFieldBase.cs
- TextSegment.cs