Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Core / CSharp / System / Windows / Media / RealizationDrawingContextWalker.cs / 1 / RealizationDrawingContextWalker.cs
//------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: RealizationDrawingContextWalker.cs // // Description: // This file contains the implementation of RealizationDrawingContextWalker. // This DrawingContextWalker is used to perform realization updates on // render data. // //----------------------------------------------------------------------------- namespace System.Windows.Media { 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; ////// RealizationDrawingContextWalker - a DrawingContextWalker which will /// update realizations of the contents of the render data. /// internal class RealizationDrawingContextWalker : DrawingContextWalker { //--------------------------------------------------------------------- // // Internal Constructors // //--------------------------------------------------------------------- #region Internal Constructors ////// Constructor for BoundsDrawingContextWalker /// /// The render context. internal RealizationDrawingContextWalker(RealizationContext ctx) { Debug.Assert(ctx != null); _ctx = ctx; _operationTypeStack = new Stack(2); _opacityMaskBoundsStack = new Stack (2); _opacityMaskBrushStack = new Stack (2); _opacityMaskMatrixStack = new MatrixStack(); _opacityMaskRect = Rect.Empty; _opacityMaskAccumulate = 0; } #endregion Internal Constructors //---------------------------------------------------------------------- // // Public Methods // //--------------------------------------------------------------------- #region Public Methods /// /// 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) { // Ignore the clip value. _operationTypeStack.Push(OperationType.Clip); } ////// Push an opacity mask /// /// /// The opacity mask /// public override void PushOpacityMask(Brush brush) { _operationTypeStack.Push(OperationType.OpacityMask); _opacityMaskBoundsStack.Push(_opacityMaskRect); _opacityMaskRect = Rect.Empty; _opacityMaskAccumulate++; _opacityMaskBrushStack.Push(brush); _opacityMaskMatrixStack.Push(Transform.Identity, /* combine */ false); } private void PopOpacityMask() { Debug.Assert(_opacityMaskBoundsStack.Count > 0); Debug.Assert(_opacityMaskBrushStack.Count > 0); Brush brush = _opacityMaskBrushStack.Pop(); if (brush != null) { brush.UpdateRealizations(_opacityMaskRect, _ctx); } _opacityMaskRect = Rect.Union(_opacityMaskRect, _opacityMaskBoundsStack.Pop()); _opacityMaskAccumulate--; } private void TransformAndUnionOpacityMaskBounds(Rect bounds) { Rect r = Rect.Transform(bounds, _opacityMaskMatrixStack.Peek()); _opacityMaskRect.Union(r); return; } ////// 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) { // Ignore the opacity value. _operationTypeStack.Push(OperationType.Opacity); } ////// Push a Transform which will apply to all drawing operations /// until the corresponding Pop. /// /// The Transform to push. public override void PushTransform(Transform transform) { // Retrieve the new transform as a matrix if it exists. if (transform != null && !transform.IsIdentity) { // Push the operation type. _operationTypeStack.Push(OperationType.Transform); // Push the valid transform on the stack. _ctx.TransformStack.Push(transform, /* combine */ true); _opacityMaskMatrixStack.Push(transform, /* combine */ true); } else { // Do not store identity (or null) transforms on the transform stack. _operationTypeStack.Push(OperationType.InvalidOrIrrelevantTransform); } } ////// 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) { _operationTypeStack.Push(OperationType.BitmapEffect); pushedEffects++; } ////// 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) { // Ignore the guidelines value. _operationTypeStack.Push(OperationType.Guidelines); } ////// PushGuidelineY1 - /// Explicitly push one horizontal guideline. /// /// The coordinate of leading guideline. internal override void PushGuidelineY1( Double coordinate) { // Ignore the guidelines values. _operationTypeStack.Push(OperationType.Guidelines); } ////// 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) { // Ignore the guidelines values. _operationTypeStack.Push(OperationType.Guidelines); } ////// Pops a transform/clip/opacity change from the stack. /// public override void Pop() { // We must have a type stack and it must not be empty. Debug.Assert(_operationTypeStack != null); Debug.Assert(_operationTypeStack.Count > 0); // Retrieve the OperationType to figure out what what this Pop is. OperationType operationType = _operationTypeStack.Pop(); switch (operationType) { case OperationType.Transform: // Restore the previous transform _ctx.TransformStack.Pop(); _opacityMaskMatrixStack.Pop(); break; case OperationType.BitmapEffect: pushedEffects--; break; case OperationType.OpacityMask: PopOpacityMask(); break; default: // Do nothing for the 'not stored' operation types Debug.Assert(operationType == OperationType.Clip || operationType == OperationType.Opacity || operationType == OperationType.Guidelines || operationType == OperationType.InvalidOrIrrelevantTransform || operationType == OperationType.BitmapEffect); break; } } ////// 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) { // skip realization updates if there is an effect on the stack // we will do this at a later time if (pushedEffects > 0) { return; } if (pen != null) { RealizationBrushHelper helper = new RealizationBrushHelper(pen, null); bool requiresRealizationUpdates = helper.NeedsRealizationUpdates; if ( requiresRealizationUpdates || _opacityMaskAccumulate > 0) { Rect fillBounds = Rect.Empty; // This is the union of the geometry and the stroke. Rect strokeBounds = LineGeometry.GetBoundsHelper( pen, Matrix.Identity, // world transform point0, point1, Matrix.Identity, // geometry transform Geometry.StandardFlatteningTolerance, ToleranceType.Absolute ); if (_opacityMaskAccumulate > 0) { TransformAndUnionOpacityMaskBounds(strokeBounds); } if (requiresRealizationUpdates) { helper.UpdateRealizations(strokeBounds, fillBounds, _ctx); } } } } ////// 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) { // skip realization updates if there is an effect on the stack // we will do this at a later time if (pushedEffects > 0) { return; } if (pen != null || brush != null) { RealizationBrushHelper helper = new RealizationBrushHelper(pen, brush); bool requiresRealizationUpdates = helper.NeedsRealizationUpdates; if (requiresRealizationUpdates || _opacityMaskAccumulate > 0) { Rect fillBounds = Rect.Empty; Rect strokeBounds = Rect.Empty; if (brush != null) { fillBounds = RectangleGeometry.GetBoundsHelper( null, Matrix.Identity, // world transform rectangle, 0, 0, Matrix.Identity, // geometry transform Geometry.StandardFlatteningTolerance, ToleranceType.Absolute ); } if (pen != null) { // This is the union of the geometry and the stroke. strokeBounds = RectangleGeometry.GetBoundsHelper( pen, Matrix.Identity, // world transform rectangle, 0, 0, Matrix.Identity, // geometry transform Geometry.StandardFlatteningTolerance, ToleranceType.Absolute ); } if (_opacityMaskAccumulate > 0) { TransformAndUnionOpacityMaskBounds(pen != null ? strokeBounds : fillBounds); } if (requiresRealizationUpdates) { helper.UpdateRealizations(strokeBounds, fillBounds, _ctx); } } } } ////// 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) { // skip realization updates if there is an effect on the stack // we will do this at a later time if (pushedEffects > 0) { return; } if (!rectangle.IsEmpty && (pen != null || brush != null)) { RealizationBrushHelper helper = new RealizationBrushHelper(pen, brush); bool requiresRealizationUpdates = helper.NeedsRealizationUpdates; if (requiresRealizationUpdates || _opacityMaskAccumulate > 0) { Rect fillBounds = Rect.Empty; Rect strokeBounds = Rect.Empty; if (brush != null) { fillBounds = RectangleGeometry.GetBoundsHelper( null, Matrix.Identity, // world transform rectangle, radiusX, radiusY, Matrix.Identity, // geometry transform Geometry.StandardFlatteningTolerance, ToleranceType.Absolute ); } if (pen != null) { // This is the union of the geometry and the stroke. strokeBounds = RectangleGeometry.GetBoundsHelper( pen, Matrix.Identity, // world transform rectangle, radiusX, radiusY, Matrix.Identity, // geometry transform Geometry.StandardFlatteningTolerance, ToleranceType.Absolute ); } if (_opacityMaskAccumulate > 0) { TransformAndUnionOpacityMaskBounds(pen != null ? strokeBounds : fillBounds); } if (requiresRealizationUpdates) { helper.UpdateRealizations(strokeBounds, fillBounds, _ctx); } } } } ////// 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) { // skip realization updates if there is an effect on the stack // we will do this at a later time if (pushedEffects > 0) { return; } if (pen != null || brush != null) { RealizationBrushHelper helper = new RealizationBrushHelper(pen, brush); bool requiresRealizationUpdates = helper.NeedsRealizationUpdates; Rect fillBounds = Rect.Empty; Rect strokeBounds = Rect.Empty; if (requiresRealizationUpdates || _opacityMaskAccumulate > 0) { if (brush != null) { fillBounds = EllipseGeometry.GetBoundsHelper( null, Matrix.Identity, // world transform center, radiusX, radiusY, Matrix.Identity, // geometry transform Geometry.StandardFlatteningTolerance, ToleranceType.Absolute ); } if (pen != null) { // This is the union of the geometry and the stroke. strokeBounds = EllipseGeometry.GetBoundsHelper( pen, Matrix.Identity, // world transform center, radiusX, radiusY, Matrix.Identity, // geometry transform Geometry.StandardFlatteningTolerance, ToleranceType.Absolute ); } if (_opacityMaskAccumulate > 0) { TransformAndUnionOpacityMaskBounds(pen != null ? strokeBounds : fillBounds); } if (requiresRealizationUpdates) { helper.UpdateRealizations(strokeBounds, fillBounds, _ctx); } } } } ////// 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) { // skip realization updates if there is an effect on the stack // we will do this at a later time if (pushedEffects > 0) { return; } if (geometry != null && (pen != null || brush != null)) { RealizationBrushHelper helper = new RealizationBrushHelper(pen, brush); bool requiresRealizationUpdates = helper.NeedsRealizationUpdates; if (requiresRealizationUpdates || _opacityMaskAccumulate > 0) { Rect fillBounds = Rect.Empty; Rect strokeBounds = Rect.Empty; if (brush != null) { fillBounds = geometry.GetBoundsInternal(null, Matrix.Identity); } if (pen != null) { // This is the union of the geometry and the stroke. strokeBounds = geometry.GetBoundsInternal(pen, Matrix.Identity); } if (_opacityMaskAccumulate > 0) { TransformAndUnionOpacityMaskBounds(pen != null ? strokeBounds : fillBounds); } if (requiresRealizationUpdates) { helper.UpdateRealizations(strokeBounds, fillBounds, _ctx); } } } } ////// 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) { // skip realization updates if there is an effect on the stack // we will do this at a later time if (pushedEffects > 0) { return; } DrawingImage di = imageSource as DrawingImage; if (di != null && di.Drawing != null) { Drawing drawing = di.Drawing; if (drawing.RequiresRealizationUpdates || _opacityMaskAccumulate > 0) { Rect drawingBounds = drawing.Bounds; if (_opacityMaskAccumulate > 0) { TransformAndUnionOpacityMaskBounds(drawingBounds); } if (drawing.RequiresRealizationUpdates && !DoubleUtil.AreClose(drawingBounds.Width, 0) && !DoubleUtil.AreClose(drawingBounds.Height, 0)) { Matrix scale = Matrix.CreateScaling( rectangle.Width / drawingBounds.Width, rectangle.Height / drawingBounds.Height); _ctx.TransformStack.Push(ref scale, true); // Update realizations inside the drawing graph. drawing.UpdateRealizations(_ctx); _ctx.TransformStack.Pop(); } } } } ////// 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) { // Do nothing. } ////// Draw a GlyphRun. /// /// Foreground brush to draw GlyphRun with. /// The GlyphRun to draw. public override void DrawGlyphRun(Brush foregroundBrush, GlyphRun glyphRun) { // skip realization updates if there is an effect on the stack // we will do this at a later time if (pushedEffects > 0) { return; } if (glyphRun != null && foregroundBrush != null) { RealizationBrushHelper helper = new RealizationBrushHelper(null, foregroundBrush); if (helper.NeedsRealizationUpdates || _opacityMaskAccumulate > 0) { Rect strokeBounds = Rect.Empty; Rect fillBounds = glyphRun.ComputeInkBoundingBox(); if (!fillBounds.IsEmpty) { Point baselineOrigin = glyphRun.BaselineOrigin; fillBounds.X += baselineOrigin.X; fillBounds.Y += baselineOrigin.Y; if (_opacityMaskAccumulate > 0) { TransformAndUnionOpacityMaskBounds(fillBounds); } if (helper.NeedsRealizationUpdates) { helper.UpdateRealizations(strokeBounds, fillBounds, _ctx); } } } } } ////// DrawDrawing is being overriden here to invoke the spezialized realization walk /// on Drawings. /// public override void DrawDrawing(Drawing drawing) { // skip realization updates if there is an effect on the stack // we will do this at a later time if (pushedEffects > 0) { return; } if (drawing != null) { drawing.UpdateRealizations(_ctx); } } #endregion Public Methods internal RealizationContext Context { get { return _ctx; } } //---------------------------------------------------------------------- // // Private Fields // //---------------------------------------------------------------------- #region Private Fields // The current realization context. private readonly RealizationContext _ctx; // The Type stack for our Push/Pop calls. This tells whether a given // Pop corresponds to a Transform, Clip, etc. private readonly Stack_operationTypeStack; private Stack _opacityMaskBoundsStack; private int _opacityMaskAccumulate; private Rect _opacityMaskRect; private Stack _opacityMaskBrushStack; private MatrixStack _opacityMaskMatrixStack; int pushedEffects; #endregion Private Fields //--------------------------------------------------------------------- // // Private Types // //---------------------------------------------------------------------- #region Private Types /// /// OperationType enum - this defines the type of Pushes in a context, /// so that our untyped Pops know what to Pop. /// private enum OperationType { Transform, InvalidOrIrrelevantTransform, Clip, Opacity, OpacityMask, Guidelines, BitmapEffect } #endregion Private Types } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: RealizationDrawingContextWalker.cs // // Description: // This file contains the implementation of RealizationDrawingContextWalker. // This DrawingContextWalker is used to perform realization updates on // render data. // //----------------------------------------------------------------------------- namespace System.Windows.Media { 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; ////// RealizationDrawingContextWalker - a DrawingContextWalker which will /// update realizations of the contents of the render data. /// internal class RealizationDrawingContextWalker : DrawingContextWalker { //--------------------------------------------------------------------- // // Internal Constructors // //--------------------------------------------------------------------- #region Internal Constructors ////// Constructor for BoundsDrawingContextWalker /// /// The render context. internal RealizationDrawingContextWalker(RealizationContext ctx) { Debug.Assert(ctx != null); _ctx = ctx; _operationTypeStack = new Stack(2); _opacityMaskBoundsStack = new Stack (2); _opacityMaskBrushStack = new Stack (2); _opacityMaskMatrixStack = new MatrixStack(); _opacityMaskRect = Rect.Empty; _opacityMaskAccumulate = 0; } #endregion Internal Constructors //---------------------------------------------------------------------- // // Public Methods // //--------------------------------------------------------------------- #region Public Methods /// /// 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) { // Ignore the clip value. _operationTypeStack.Push(OperationType.Clip); } ////// Push an opacity mask /// /// /// The opacity mask /// public override void PushOpacityMask(Brush brush) { _operationTypeStack.Push(OperationType.OpacityMask); _opacityMaskBoundsStack.Push(_opacityMaskRect); _opacityMaskRect = Rect.Empty; _opacityMaskAccumulate++; _opacityMaskBrushStack.Push(brush); _opacityMaskMatrixStack.Push(Transform.Identity, /* combine */ false); } private void PopOpacityMask() { Debug.Assert(_opacityMaskBoundsStack.Count > 0); Debug.Assert(_opacityMaskBrushStack.Count > 0); Brush brush = _opacityMaskBrushStack.Pop(); if (brush != null) { brush.UpdateRealizations(_opacityMaskRect, _ctx); } _opacityMaskRect = Rect.Union(_opacityMaskRect, _opacityMaskBoundsStack.Pop()); _opacityMaskAccumulate--; } private void TransformAndUnionOpacityMaskBounds(Rect bounds) { Rect r = Rect.Transform(bounds, _opacityMaskMatrixStack.Peek()); _opacityMaskRect.Union(r); return; } ////// 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) { // Ignore the opacity value. _operationTypeStack.Push(OperationType.Opacity); } ////// Push a Transform which will apply to all drawing operations /// until the corresponding Pop. /// /// The Transform to push. public override void PushTransform(Transform transform) { // Retrieve the new transform as a matrix if it exists. if (transform != null && !transform.IsIdentity) { // Push the operation type. _operationTypeStack.Push(OperationType.Transform); // Push the valid transform on the stack. _ctx.TransformStack.Push(transform, /* combine */ true); _opacityMaskMatrixStack.Push(transform, /* combine */ true); } else { // Do not store identity (or null) transforms on the transform stack. _operationTypeStack.Push(OperationType.InvalidOrIrrelevantTransform); } } ////// 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) { _operationTypeStack.Push(OperationType.BitmapEffect); pushedEffects++; } ////// 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) { // Ignore the guidelines value. _operationTypeStack.Push(OperationType.Guidelines); } ////// PushGuidelineY1 - /// Explicitly push one horizontal guideline. /// /// The coordinate of leading guideline. internal override void PushGuidelineY1( Double coordinate) { // Ignore the guidelines values. _operationTypeStack.Push(OperationType.Guidelines); } ////// 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) { // Ignore the guidelines values. _operationTypeStack.Push(OperationType.Guidelines); } ////// Pops a transform/clip/opacity change from the stack. /// public override void Pop() { // We must have a type stack and it must not be empty. Debug.Assert(_operationTypeStack != null); Debug.Assert(_operationTypeStack.Count > 0); // Retrieve the OperationType to figure out what what this Pop is. OperationType operationType = _operationTypeStack.Pop(); switch (operationType) { case OperationType.Transform: // Restore the previous transform _ctx.TransformStack.Pop(); _opacityMaskMatrixStack.Pop(); break; case OperationType.BitmapEffect: pushedEffects--; break; case OperationType.OpacityMask: PopOpacityMask(); break; default: // Do nothing for the 'not stored' operation types Debug.Assert(operationType == OperationType.Clip || operationType == OperationType.Opacity || operationType == OperationType.Guidelines || operationType == OperationType.InvalidOrIrrelevantTransform || operationType == OperationType.BitmapEffect); break; } } ////// 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) { // skip realization updates if there is an effect on the stack // we will do this at a later time if (pushedEffects > 0) { return; } if (pen != null) { RealizationBrushHelper helper = new RealizationBrushHelper(pen, null); bool requiresRealizationUpdates = helper.NeedsRealizationUpdates; if ( requiresRealizationUpdates || _opacityMaskAccumulate > 0) { Rect fillBounds = Rect.Empty; // This is the union of the geometry and the stroke. Rect strokeBounds = LineGeometry.GetBoundsHelper( pen, Matrix.Identity, // world transform point0, point1, Matrix.Identity, // geometry transform Geometry.StandardFlatteningTolerance, ToleranceType.Absolute ); if (_opacityMaskAccumulate > 0) { TransformAndUnionOpacityMaskBounds(strokeBounds); } if (requiresRealizationUpdates) { helper.UpdateRealizations(strokeBounds, fillBounds, _ctx); } } } } ////// 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) { // skip realization updates if there is an effect on the stack // we will do this at a later time if (pushedEffects > 0) { return; } if (pen != null || brush != null) { RealizationBrushHelper helper = new RealizationBrushHelper(pen, brush); bool requiresRealizationUpdates = helper.NeedsRealizationUpdates; if (requiresRealizationUpdates || _opacityMaskAccumulate > 0) { Rect fillBounds = Rect.Empty; Rect strokeBounds = Rect.Empty; if (brush != null) { fillBounds = RectangleGeometry.GetBoundsHelper( null, Matrix.Identity, // world transform rectangle, 0, 0, Matrix.Identity, // geometry transform Geometry.StandardFlatteningTolerance, ToleranceType.Absolute ); } if (pen != null) { // This is the union of the geometry and the stroke. strokeBounds = RectangleGeometry.GetBoundsHelper( pen, Matrix.Identity, // world transform rectangle, 0, 0, Matrix.Identity, // geometry transform Geometry.StandardFlatteningTolerance, ToleranceType.Absolute ); } if (_opacityMaskAccumulate > 0) { TransformAndUnionOpacityMaskBounds(pen != null ? strokeBounds : fillBounds); } if (requiresRealizationUpdates) { helper.UpdateRealizations(strokeBounds, fillBounds, _ctx); } } } } ////// 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) { // skip realization updates if there is an effect on the stack // we will do this at a later time if (pushedEffects > 0) { return; } if (!rectangle.IsEmpty && (pen != null || brush != null)) { RealizationBrushHelper helper = new RealizationBrushHelper(pen, brush); bool requiresRealizationUpdates = helper.NeedsRealizationUpdates; if (requiresRealizationUpdates || _opacityMaskAccumulate > 0) { Rect fillBounds = Rect.Empty; Rect strokeBounds = Rect.Empty; if (brush != null) { fillBounds = RectangleGeometry.GetBoundsHelper( null, Matrix.Identity, // world transform rectangle, radiusX, radiusY, Matrix.Identity, // geometry transform Geometry.StandardFlatteningTolerance, ToleranceType.Absolute ); } if (pen != null) { // This is the union of the geometry and the stroke. strokeBounds = RectangleGeometry.GetBoundsHelper( pen, Matrix.Identity, // world transform rectangle, radiusX, radiusY, Matrix.Identity, // geometry transform Geometry.StandardFlatteningTolerance, ToleranceType.Absolute ); } if (_opacityMaskAccumulate > 0) { TransformAndUnionOpacityMaskBounds(pen != null ? strokeBounds : fillBounds); } if (requiresRealizationUpdates) { helper.UpdateRealizations(strokeBounds, fillBounds, _ctx); } } } } ////// 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) { // skip realization updates if there is an effect on the stack // we will do this at a later time if (pushedEffects > 0) { return; } if (pen != null || brush != null) { RealizationBrushHelper helper = new RealizationBrushHelper(pen, brush); bool requiresRealizationUpdates = helper.NeedsRealizationUpdates; Rect fillBounds = Rect.Empty; Rect strokeBounds = Rect.Empty; if (requiresRealizationUpdates || _opacityMaskAccumulate > 0) { if (brush != null) { fillBounds = EllipseGeometry.GetBoundsHelper( null, Matrix.Identity, // world transform center, radiusX, radiusY, Matrix.Identity, // geometry transform Geometry.StandardFlatteningTolerance, ToleranceType.Absolute ); } if (pen != null) { // This is the union of the geometry and the stroke. strokeBounds = EllipseGeometry.GetBoundsHelper( pen, Matrix.Identity, // world transform center, radiusX, radiusY, Matrix.Identity, // geometry transform Geometry.StandardFlatteningTolerance, ToleranceType.Absolute ); } if (_opacityMaskAccumulate > 0) { TransformAndUnionOpacityMaskBounds(pen != null ? strokeBounds : fillBounds); } if (requiresRealizationUpdates) { helper.UpdateRealizations(strokeBounds, fillBounds, _ctx); } } } } ////// 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) { // skip realization updates if there is an effect on the stack // we will do this at a later time if (pushedEffects > 0) { return; } if (geometry != null && (pen != null || brush != null)) { RealizationBrushHelper helper = new RealizationBrushHelper(pen, brush); bool requiresRealizationUpdates = helper.NeedsRealizationUpdates; if (requiresRealizationUpdates || _opacityMaskAccumulate > 0) { Rect fillBounds = Rect.Empty; Rect strokeBounds = Rect.Empty; if (brush != null) { fillBounds = geometry.GetBoundsInternal(null, Matrix.Identity); } if (pen != null) { // This is the union of the geometry and the stroke. strokeBounds = geometry.GetBoundsInternal(pen, Matrix.Identity); } if (_opacityMaskAccumulate > 0) { TransformAndUnionOpacityMaskBounds(pen != null ? strokeBounds : fillBounds); } if (requiresRealizationUpdates) { helper.UpdateRealizations(strokeBounds, fillBounds, _ctx); } } } } ////// 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) { // skip realization updates if there is an effect on the stack // we will do this at a later time if (pushedEffects > 0) { return; } DrawingImage di = imageSource as DrawingImage; if (di != null && di.Drawing != null) { Drawing drawing = di.Drawing; if (drawing.RequiresRealizationUpdates || _opacityMaskAccumulate > 0) { Rect drawingBounds = drawing.Bounds; if (_opacityMaskAccumulate > 0) { TransformAndUnionOpacityMaskBounds(drawingBounds); } if (drawing.RequiresRealizationUpdates && !DoubleUtil.AreClose(drawingBounds.Width, 0) && !DoubleUtil.AreClose(drawingBounds.Height, 0)) { Matrix scale = Matrix.CreateScaling( rectangle.Width / drawingBounds.Width, rectangle.Height / drawingBounds.Height); _ctx.TransformStack.Push(ref scale, true); // Update realizations inside the drawing graph. drawing.UpdateRealizations(_ctx); _ctx.TransformStack.Pop(); } } } } ////// 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) { // Do nothing. } ////// Draw a GlyphRun. /// /// Foreground brush to draw GlyphRun with. /// The GlyphRun to draw. public override void DrawGlyphRun(Brush foregroundBrush, GlyphRun glyphRun) { // skip realization updates if there is an effect on the stack // we will do this at a later time if (pushedEffects > 0) { return; } if (glyphRun != null && foregroundBrush != null) { RealizationBrushHelper helper = new RealizationBrushHelper(null, foregroundBrush); if (helper.NeedsRealizationUpdates || _opacityMaskAccumulate > 0) { Rect strokeBounds = Rect.Empty; Rect fillBounds = glyphRun.ComputeInkBoundingBox(); if (!fillBounds.IsEmpty) { Point baselineOrigin = glyphRun.BaselineOrigin; fillBounds.X += baselineOrigin.X; fillBounds.Y += baselineOrigin.Y; if (_opacityMaskAccumulate > 0) { TransformAndUnionOpacityMaskBounds(fillBounds); } if (helper.NeedsRealizationUpdates) { helper.UpdateRealizations(strokeBounds, fillBounds, _ctx); } } } } } ////// DrawDrawing is being overriden here to invoke the spezialized realization walk /// on Drawings. /// public override void DrawDrawing(Drawing drawing) { // skip realization updates if there is an effect on the stack // we will do this at a later time if (pushedEffects > 0) { return; } if (drawing != null) { drawing.UpdateRealizations(_ctx); } } #endregion Public Methods internal RealizationContext Context { get { return _ctx; } } //---------------------------------------------------------------------- // // Private Fields // //---------------------------------------------------------------------- #region Private Fields // The current realization context. private readonly RealizationContext _ctx; // The Type stack for our Push/Pop calls. This tells whether a given // Pop corresponds to a Transform, Clip, etc. private readonly Stack_operationTypeStack; private Stack _opacityMaskBoundsStack; private int _opacityMaskAccumulate; private Rect _opacityMaskRect; private Stack _opacityMaskBrushStack; private MatrixStack _opacityMaskMatrixStack; int pushedEffects; #endregion Private Fields //--------------------------------------------------------------------- // // Private Types // //---------------------------------------------------------------------- #region Private Types /// /// OperationType enum - this defines the type of Pushes in a context, /// so that our untyped Pops know what to Pop. /// private enum OperationType { Transform, InvalidOrIrrelevantTransform, Clip, Opacity, OpacityMask, Guidelines, BitmapEffect } #endregion Private Types } } // 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
- autovalidator.cs
- BaseTemplateCodeDomTreeGenerator.cs
- DockPattern.cs
- GenericsInstances.cs
- PrinterUnitConvert.cs
- File.cs
- RelationshipManager.cs
- HiddenFieldPageStatePersister.cs
- CustomValidator.cs
- IPAddressCollection.cs
- XamlSerializer.cs
- ValueSerializerAttribute.cs
- IfAction.cs
- XPathQilFactory.cs
- DeadLetterQueue.cs
- ObjectQuery_EntitySqlExtensions.cs
- QueryableDataSourceEditData.cs
- AppDomainFactory.cs
- CacheOutputQuery.cs
- ToolStrip.cs
- UriParserTemplates.cs
- LinkDescriptor.cs
- Preprocessor.cs
- Win32SafeHandles.cs
- COAUTHIDENTITY.cs
- RightsManagementPermission.cs
- altserialization.cs
- FontSource.cs
- IPGlobalProperties.cs
- AssemblyInfo.cs
- MailDefinitionBodyFileNameEditor.cs
- PrintDialog.cs
- RestClientProxyHandler.cs
- CodeTryCatchFinallyStatement.cs
- SubMenuStyle.cs
- RegexTree.cs
- DataGridViewRowsRemovedEventArgs.cs
- ScrollItemProviderWrapper.cs
- CharKeyFrameCollection.cs
- WebPartCollection.cs
- HashCryptoHandle.cs
- Component.cs
- InheritanceAttribute.cs
- TemplateBamlRecordReader.cs
- QilTernary.cs
- DBDataPermissionAttribute.cs
- StaticExtensionConverter.cs
- PropertyIdentifier.cs
- DispatcherSynchronizationContext.cs
- CollectionViewGroupInternal.cs
- Literal.cs
- CacheDependency.cs
- PropertyCondition.cs
- HttpRequest.cs
- BitmapEffectDrawing.cs
- DocumentReference.cs
- ProgressChangedEventArgs.cs
- TrustLevel.cs
- UriSection.cs
- InvalidCastException.cs
- MappingException.cs
- AudioException.cs
- JournalNavigationScope.cs
- DefaultEvaluationContext.cs
- ExpandedWrapper.cs
- ProviderBase.cs
- HtmlFormWrapper.cs
- FlowNode.cs
- CalendarTable.cs
- AccessibleObject.cs
- HttpFileCollection.cs
- ErrorProvider.cs
- AttributeCollection.cs
- MailMessageEventArgs.cs
- KeyToListMap.cs
- TransportBindingElement.cs
- OleAutBinder.cs
- HierarchicalDataTemplate.cs
- TextParagraph.cs
- CalendarDataBindingHandler.cs
- BamlTreeNode.cs
- XmlNodeChangedEventArgs.cs
- MenuAutomationPeer.cs
- Tile.cs
- TransportElement.cs
- formatter.cs
- _AutoWebProxyScriptHelper.cs
- MinimizableAttributeTypeConverter.cs
- PageFunction.cs
- PropertyChangedEventArgs.cs
- LabelLiteral.cs
- EditorZone.cs
- ETagAttribute.cs
- SmtpNtlmAuthenticationModule.cs
- SchemaNotation.cs
- CurrencyManager.cs
- DialogWindow.cs
- CharacterString.cs
- DebugHandleTracker.cs
- RowCache.cs