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
- AssociatedControlConverter.cs
- OperationSelectorBehavior.cs
- SecurityUtils.cs
- GeneralTransform3DCollection.cs
- MemberListBinding.cs
- BroadcastEventHelper.cs
- DbProviderFactories.cs
- TcpSocketManager.cs
- Image.cs
- PreparingEnlistment.cs
- ExternalFile.cs
- XmlILIndex.cs
- ListItemsPage.cs
- FieldTemplateFactory.cs
- ContractMethodInfo.cs
- WindowsListViewGroupHelper.cs
- ReflectionUtil.cs
- Panel.cs
- ClonableStack.cs
- ConfigurationSettings.cs
- Suspend.cs
- StopStoryboard.cs
- updatecommandorderer.cs
- XmlValueConverter.cs
- OleDbInfoMessageEvent.cs
- Font.cs
- NamedPipeChannelListener.cs
- PageFunction.cs
- xamlnodes.cs
- MonitoringDescriptionAttribute.cs
- SymLanguageVendor.cs
- BookmarkUndoUnit.cs
- PaintEvent.cs
- ImageMapEventArgs.cs
- ThreadSafeList.cs
- DemultiplexingClientMessageFormatter.cs
- PackageDigitalSignatureManager.cs
- SevenBitStream.cs
- ColumnHeader.cs
- DataGridTable.cs
- TriggerActionCollection.cs
- VirtualizingStackPanel.cs
- SizeKeyFrameCollection.cs
- FontResourceCache.cs
- DriveInfo.cs
- Types.cs
- EntityWrapperFactory.cs
- TemplateEditingVerb.cs
- Size3DConverter.cs
- RowsCopiedEventArgs.cs
- ErrorRuntimeConfig.cs
- NameTable.cs
- VersionedStreamOwner.cs
- DiscoveryInnerClientAdhocCD1.cs
- ByteStack.cs
- MultipleViewProviderWrapper.cs
- CustomErrorCollection.cs
- PrinterResolution.cs
- CurrencyManager.cs
- XmlDictionaryReaderQuotas.cs
- Color.cs
- IsolatedStorageFile.cs
- ParameterCollection.cs
- UniqueEventHelper.cs
- ScrollData.cs
- AutoResizedEvent.cs
- MonitoringDescriptionAttribute.cs
- elementinformation.cs
- CompilationRelaxations.cs
- WebMessageFormatHelper.cs
- HttpModuleAction.cs
- OwnerDrawPropertyBag.cs
- ColorPalette.cs
- CuspData.cs
- WindowsProgressbar.cs
- DriveNotFoundException.cs
- FileIOPermission.cs
- StateChangeEvent.cs
- WebPageTraceListener.cs
- HeaderElement.cs
- HtmlShim.cs
- ArrayElementGridEntry.cs
- CultureSpecificStringDictionary.cs
- SystemIPv6InterfaceProperties.cs
- StylusPointDescription.cs
- XmlILIndex.cs
- CultureData.cs
- Symbol.cs
- MatrixCamera.cs
- MobileErrorInfo.cs
- XdrBuilder.cs
- Control.cs
- XmlAttributeProperties.cs
- DataGridViewColumnDesigner.cs
- ProcessModule.cs
- CapabilitiesState.cs
- ValidationPropertyAttribute.cs
- DoubleAnimation.cs
- ItemCheckedEvent.cs
- TripleDES.cs