Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / Media / BoundsDrawingContextWalker.cs / 1305600 / BoundsDrawingContextWalker.cs
//---------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: BoundsDrawingContextWalker.cs // // Description: This file contains the implementation of BoundsDrawingContextWalker. // This DrawingContextWalker is used to perform bounds calculations // on renderdata. // // History: // 04/15/2004 : [....] - Created it. // //--------------------------------------------------------------------------- using MS.Internal; using System; using System.ComponentModel; using System.Collections; using System.Collections.Generic; using System.ComponentModel.Design.Serialization; using System.Diagnostics; using System.Runtime.InteropServices; 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.Security; using System.Security.Permissions; namespace System.Windows.Media { ////// BoundsDrawingContextWalker - a DrawingContextWalker which will calculate the bounds /// of the contents of a render data. /// internal class BoundsDrawingContextWalker : DrawingContextWalker { ////// PushType enum - this defines the type of Pushes in a context, so that our /// untyped Pops know what to Pop. /// private enum PushType { Transform, Clip, Opacity, OpacityMask, Guidelines, BitmapEffect } ////// Constructor for BoundsDrawingContextWalker /// public BoundsDrawingContextWalker() { _bounds = Rect.Empty; _transform = Matrix.Identity; } public Rect Bounds { get { return _bounds; } } #region Static Drawing Context 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 (Pen.ContributesToBounds(pen)) { // _bounds is always in "world" space // So, we need to transform the geometry to world to bound it Rect geometryBounds = LineGeometry.GetBoundsHelper( pen, _transform, // world transform point0, point1, Matrix.Identity, // geometry transform Geometry.StandardFlatteningTolerance, ToleranceType.Absolute ); AddTransformedBounds(ref geometryBounds); } } ////// 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 ((brush != null) || Pen.ContributesToBounds(pen)) { // _bounds is always in "world" space // So, we need to transform the geometry to world to bound it Rect geometryBounds = RectangleGeometry.GetBoundsHelper( pen, _transform, // world transform rectangle, 0.0, 0.0, Matrix.Identity, // geometry transform Geometry.StandardFlatteningTolerance, ToleranceType.Absolute ); AddTransformedBounds(ref geometryBounds); } } ////// 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 ((brush != null) || Pen.ContributesToBounds(pen)) { // _bounds is always in "world" space // So, we need to transform the geometry to world to bound it Rect geometryBounds = RectangleGeometry.GetBoundsHelper( pen, _transform, // world transform rectangle, radiusX, radiusY, Matrix.Identity, // geometry transform Geometry.StandardFlatteningTolerance, ToleranceType.Absolute ); AddTransformedBounds(ref geometryBounds); } } ////// 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 ((brush != null) || Pen.ContributesToBounds(pen)) { // _bounds is always in "world" space // So, we need to transform the geometry to world to bound it Rect geometryBounds = EllipseGeometry.GetBoundsHelper( pen, _transform, // world transform center, radiusX, radiusY, Matrix.Identity, // geometry transform Geometry.StandardFlatteningTolerance, ToleranceType.Absolute ); AddTransformedBounds(ref geometryBounds); } } ////// 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 ((geometry != null) && ((brush != null) || Pen.ContributesToBounds(pen))) { // _bounds is always in "world" space // So, we need to transform the geometry to world to bound it Rect geometryBounds = geometry.GetBoundsInternal(pen, _transform); AddTransformedBounds(ref geometryBounds); } } ////// 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 BitmapSource to draw. /// /// The Rect into which the BitmapSource will be fit. /// public override void DrawImage( ImageSource imageSource, Rect rectangle) { if (imageSource != null) { AddBounds(ref rectangle); } } ////// 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 video, Rect rectangle) { if (video != null) { AddBounds(ref rectangle); } } ////// Draw a GlyphRun. /// /// Foreground brush to draw GlyphRun with. /// The GlyphRun to draw. public override void DrawGlyphRun(Brush foregroundBrush, GlyphRun glyphRun) { if ((foregroundBrush != null) && (glyphRun != null)) { // The InkBoundingBox + the Origin produce the true InkBoundingBox. Rect rectangle = glyphRun.ComputeInkBoundingBox(); if (!rectangle.IsEmpty) { rectangle.Offset((Vector)glyphRun.BaselineOrigin); AddBounds(ref rectangle); } } } ////// PushOpacityMask - /// Push an opacity mask, which will apply to all drawing primitives until the /// corresponding Pop call. /// /// Brush for opacity mask. public override void PushOpacityMask( Brush brush) { // Push the opacity type PushTypeStack(PushType.OpacityMask); } ////// 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 we have an old clip, push the old clip onto the stack. if (_haveClip) { // Ensure the clip stack if (_clipStack == null) { _clipStack = new Stack(2); } _clipStack.Push(_clip); } // Push the clip type PushTypeStack(PushType.Clip); if (clipGeometry != null) { // Since _clip is a value type, we need to know whether we have a clip or not. // If not, we can assert that the initial value is present (Rect.Empty). // We should also now set the _haveClip flag. if (!_haveClip) { _haveClip = true; _clip = clipGeometry.GetBoundsInternal(null /* pen */, _transform); } else { // update current clip _clip.Intersect(clipGeometry.GetBoundsInternal(null /* pen */, _transform)); } } } /// /// 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) { // Push the opacity type PushTypeStack(PushType.Opacity); } ////// 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) { // Ensure the transform stack if (_transformStack == null) { _transformStack = new Stack(2); } // Push the old transform. _transformStack.Push(_transform); // Push the transform type PushTypeStack(PushType.Transform); Matrix newValue = Matrix.Identity; // Retrieve the new transform as a matrix if it exists if ((transform != null) && !transform.IsIdentity) { // If the transform is degeneraate, we can skip all instructions until the // corresponding Pop. newValue = transform.Value; } // Update the current transform _transform = newValue * _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) { // Push the guidelines type PushTypeStack(PushType.Guidelines); // Nothing else to do. Guidelines are not used, // so we only need to register Push() type in order to treat // Pop() properly. } ////// PushGuidelineY1 - /// Explicitly push one horizontal guideline. /// /// The coordinate of leading guideline. internal override void PushGuidelineY1( Double coordinate) { // Push the guidelines type PushTypeStack(PushType.Guidelines); // Nothing else to do. Guidelines are not used, // so we only need to register Push() type in order to treat // Pop() properly. } ////// 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) { // Push the guidelines type PushTypeStack(PushType.Guidelines); // Nothing else to do. Guidelines are not used, // so we only need to register Push() type in order to treat // Pop() properly. } ////// PushEffect - /// Push a BitmapEffect which will apply to all drawing operations until the /// corresponding Pop. /// /// The BitmapEffect to push. /// The BitmapEffectInput. [Obsolete(MS.Internal.Media.VisualTreeUtils.BitmapEffectObsoleteMessage)] public override void PushEffect( BitmapEffect effect, BitmapEffectInput effectInput) { // Ensure the type stack PushTypeStack(PushType.BitmapEffect); // This API has been deprecated, so any BitmapEffect is ignored. } ////// Pop /// public override void Pop() { // We must have a type stack and it must not be empty. Debug.Assert(_pushTypeStack != null); Debug.Assert(_pushTypeStack.Count > 0); // Retrieve the PushType to figure out what what this Pop is. PushType pushType = _pushTypeStack.Pop(); switch (pushType) { case PushType.Transform: // We must have a Transform stack and it must not be empty. Debug.Assert(_transformStack != null); Debug.Assert(_transformStack.Count > 0); // Restore the transform _transform = _transformStack.Pop(); break; case PushType.Clip: // Restore the clip, if there's one to restore if ((_clipStack != null) && (_clipStack.Count > 0)) { _clip = _clipStack.Pop(); } else { // If the _clipStack was empty or null, then we no longer have a clip. _haveClip = false; } break; case PushType.BitmapEffect: // break; default: // Ignore the rest break; } } #endregion Static Drawing Context Methods #region Private Methods ////// AddBounds - Unions the non-transformed bounds which are /// local to the current Drawing operation with the /// aggregate bounds of other Drawing operations encountered /// during this walk. /// /// /// In: The bounds of the geometry to union in the coordinate /// space of the current Drawing operations /// Out: The transformed and clipped bounds of the geometry /// in the coordinate space of the top-level Drawing /// operation. /// private void AddBounds(ref Rect bounds) { // _bounds is always in "world" space // So, we need to transform the Rect to world to bound it if (!_transform.IsIdentity) { MatrixUtil.TransformRect(ref bounds, ref _transform); } AddTransformedBounds(ref bounds); } ////// AddTransformedBounds - Unions bounds which have been transformed /// into the top-level Drawing operation with the aggregate bounds of /// other Drawing operations encountered during this walk. /// /// /// In: The bounds of the geometry to union in the coordinate /// space of the current Drawing operations /// Out: The transformed and clipped bounds of the geometry /// in the coordinate space of the top-level Drawing /// operation. /// private void AddTransformedBounds(ref Rect bounds) { if (DoubleUtil.RectHasNaN(bounds)) { // We set the bounds to infinity if it has NaN bounds.X = Double.NegativeInfinity; bounds.Y = Double.NegativeInfinity; bounds.Width = Double.PositiveInfinity; bounds.Height = Double.PositiveInfinity; } if (_haveClip) { bounds.Intersect(_clip); } _bounds.Union(bounds); } ////// Ensure the type stack exists, and store given push type there. /// /// the push type to store private void PushTypeStack(PushType pushType) { if (_pushTypeStack == null) { _pushTypeStack = new Stack(2); } _pushTypeStack.Push(pushType); } /// /// Ensure that the state is clear and is good for next use. /// internal void ClearState() { _clip = Rect.Empty; _bounds = Rect.Empty; _haveClip = false; _transform = new Matrix(); _pushTypeStack = null; _transformStack = null; _clipStack = null; } #endregion Private Methods // The accumulated bounds, in world space private Rect _bounds; // The current clip in world space, if _haveClip is true. Otherwise, this // variable may hold random rects (stuff left over from previously pop'ed clipped) private Rect _clip; // States whether or not we have a clip (because Rect isn't nullable). private bool _haveClip; // The current local->world Transform as a matrix. private Matrix _transform; // The Type stack for our Push/Pop calls. This tells whether a given Pop corresponds // to a Transform, Clip, etc. private Stack_pushTypeStack; // This stack contains the Matricies encountered during our walk. // The current transform is stored in _transform and not in the Stack. private Stack _transformStack; // This stack contains the clip rects encountered during our walk. // The current clip is stored in _clip and not in the Stack. private Stack _clipStack; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TextOptions.cs
- ParameterCollection.cs
- TemplateColumn.cs
- PrintPreviewDialog.cs
- ZipIOLocalFileBlock.cs
- TextBlockAutomationPeer.cs
- MenuItem.cs
- StreamHelper.cs
- AuthorizationRule.cs
- BitmapEffectDrawingContent.cs
- ApplicationFileCodeDomTreeGenerator.cs
- CapabilitiesRule.cs
- ConditionalAttribute.cs
- PhysicalFontFamily.cs
- EntityParameterCollection.cs
- AspNetRouteServiceHttpHandler.cs
- XPathSelectionIterator.cs
- TargetInvocationException.cs
- TopClause.cs
- InstanceDescriptor.cs
- MobileTemplatedControlDesigner.cs
- PriorityQueue.cs
- TreeWalker.cs
- DataGridRelationshipRow.cs
- XhtmlTextWriter.cs
- UserControl.cs
- _SslState.cs
- PropertyChangingEventArgs.cs
- ReadOnlyCollectionBase.cs
- ConstantProjectedSlot.cs
- TextTreeRootNode.cs
- AccessDataSourceView.cs
- Task.cs
- HttpWebRequest.cs
- PolicyUnit.cs
- DictionarySectionHandler.cs
- HttpRuntime.cs
- AttributeProviderAttribute.cs
- TextModifier.cs
- SmtpException.cs
- XmlNodeList.cs
- ContentDisposition.cs
- XmlnsCache.cs
- GridViewRowEventArgs.cs
- SchemaObjectWriter.cs
- ProfileGroupSettings.cs
- DataListCommandEventArgs.cs
- AnnotationResourceChangedEventArgs.cs
- COM2TypeInfoProcessor.cs
- BaseCodePageEncoding.cs
- Region.cs
- DocumentPageViewAutomationPeer.cs
- ZipIOExtraFieldPaddingElement.cs
- FilterElement.cs
- HighlightVisual.cs
- XmlIncludeAttribute.cs
- HtmlElementCollection.cs
- SamlAuthorityBinding.cs
- DebugView.cs
- DesignerActionList.cs
- TailPinnedEventArgs.cs
- AttachmentService.cs
- BufferedOutputAsyncStream.cs
- StyleXamlParser.cs
- OutputWindow.cs
- Vector3DAnimation.cs
- ObjectViewEntityCollectionData.cs
- ToolStripDropDown.cs
- PerformanceCounterManager.cs
- BitmapSource.cs
- ColumnHeaderConverter.cs
- PropertyGridView.cs
- TabControlAutomationPeer.cs
- HelpProvider.cs
- _SslSessionsCache.cs
- CodeMemberEvent.cs
- ColumnHeader.cs
- COM2ICategorizePropertiesHandler.cs
- SignerInfo.cs
- TableLayoutStyleCollection.cs
- SizeKeyFrameCollection.cs
- SqlConnectionPoolProviderInfo.cs
- PolyBezierSegmentFigureLogic.cs
- Timeline.cs
- JoinTreeNode.cs
- nulltextcontainer.cs
- MemberDomainMap.cs
- NetworkInformationPermission.cs
- SizeValueSerializer.cs
- UIElementParagraph.cs
- AsyncOperationManager.cs
- CompilerErrorCollection.cs
- RestHandlerFactory.cs
- PaperSize.cs
- PermissionSetEnumerator.cs
- MetadataCollection.cs
- RecommendedAsConfigurableAttribute.cs
- FixedPosition.cs
- MediaPlayer.cs
- PropertyChangingEventArgs.cs