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
- BitSet.cs
- SmiRecordBuffer.cs
- BitStream.cs
- AutomationPatternInfo.cs
- KerberosSecurityTokenAuthenticator.cs
- SqlClientWrapperSmiStream.cs
- UpdatePanelControlTrigger.cs
- ColorConverter.cs
- PopOutPanel.cs
- SmiContextFactory.cs
- x509store.cs
- ObjectSecurity.cs
- _SpnDictionary.cs
- ToolstripProfessionalRenderer.cs
- HotSpot.cs
- ConnectionsZone.cs
- FontNamesConverter.cs
- WebPartVerb.cs
- SwitchLevelAttribute.cs
- ValidatorCompatibilityHelper.cs
- ValidationSummaryDesigner.cs
- UnsafeNativeMethods.cs
- PrtTicket_Editor.cs
- ToolBarButton.cs
- FontFamilyIdentifier.cs
- HashCodeCombiner.cs
- RuleProcessor.cs
- StylusPlugInCollection.cs
- GridToolTip.cs
- SerializationStore.cs
- IntPtr.cs
- TargetConverter.cs
- DataBindingExpressionBuilder.cs
- TemplateFactory.cs
- OleServicesContext.cs
- Fonts.cs
- TimeSpanValidatorAttribute.cs
- ImmComposition.cs
- CacheManager.cs
- DiscriminatorMap.cs
- ColorConvertedBitmap.cs
- FixedSOMImage.cs
- LoadItemsEventArgs.cs
- SqlDataSourceStatusEventArgs.cs
- SmtpFailedRecipientException.cs
- CellIdBoolean.cs
- WinEventQueueItem.cs
- Misc.cs
- BaseCAMarshaler.cs
- PenThreadPool.cs
- InternalMappingException.cs
- AxDesigner.cs
- GridViewPageEventArgs.cs
- SQLChars.cs
- AspNetSynchronizationContext.cs
- Tracking.cs
- WebZone.cs
- BamlReader.cs
- FontFamily.cs
- EntitySetBase.cs
- Number.cs
- LinkConverter.cs
- InternalsVisibleToAttribute.cs
- Dispatcher.cs
- TypeForwardedToAttribute.cs
- TdsRecordBufferSetter.cs
- Blend.cs
- SqlDeflator.cs
- TextEvent.cs
- DataIdProcessor.cs
- RequestQueryParser.cs
- DelegateHelpers.cs
- CrossSiteScriptingValidation.cs
- InputLanguage.cs
- SqlTransaction.cs
- MdiWindowListItemConverter.cs
- DataGridViewRowDividerDoubleClickEventArgs.cs
- WebPartEditorApplyVerb.cs
- ServiceReference.cs
- SymbolMethod.cs
- SQLString.cs
- CalendarButton.cs
- DataSourceHelper.cs
- CanonicalXml.cs
- WebBrowserDocumentCompletedEventHandler.cs
- OdbcConnectionHandle.cs
- SafeRightsManagementQueryHandle.cs
- DbXmlEnabledProviderManifest.cs
- EncoderParameter.cs
- MetabaseServerConfig.cs
- SimpleTextLine.cs
- NativeMethods.cs
- WebRequestModuleElementCollection.cs
- HtmlSelect.cs
- SqlNamer.cs
- Label.cs
- ConstructorNeedsTagAttribute.cs
- PermissionToken.cs
- EUCJPEncoding.cs
- Byte.cs