Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / 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
- UrlParameterReader.cs
- ISAPIApplicationHost.cs
- QilPatternVisitor.cs
- MenuBindingsEditorForm.cs
- Int16.cs
- DeobfuscatingStream.cs
- RemotingServices.cs
- Literal.cs
- TreeViewEvent.cs
- Schema.cs
- URLString.cs
- ProxyAttribute.cs
- System.Data_BID.cs
- Interlocked.cs
- MemberAssignment.cs
- Floater.cs
- BoundingRectTracker.cs
- returneventsaver.cs
- GridViewSelectEventArgs.cs
- __Error.cs
- ExternalException.cs
- SimplePropertyEntry.cs
- AdjustableArrowCap.cs
- odbcmetadatafactory.cs
- EncryptedPackage.cs
- FontStretches.cs
- WinEventHandler.cs
- AutomationElement.cs
- NativeMethods.cs
- CalendarItem.cs
- Context.cs
- EntityParameterCollection.cs
- DescriptionAttribute.cs
- Trace.cs
- ListItemCollection.cs
- CacheSection.cs
- ToolStripDropDown.cs
- ResXResourceWriter.cs
- XmlWhitespace.cs
- EntitySetBaseCollection.cs
- ConfigurationElementCollection.cs
- Material.cs
- EntityAdapter.cs
- AsyncOperation.cs
- DbProviderSpecificTypePropertyAttribute.cs
- TextTreeRootNode.cs
- InputLangChangeEvent.cs
- ResourceManagerWrapper.cs
- BamlLocalizableResourceKey.cs
- XXXInfos.cs
- PeerCredential.cs
- Buffer.cs
- SoapAttributeAttribute.cs
- TrackingRecordPreFilter.cs
- UnsafeMethods.cs
- EventLogTraceListener.cs
- NavigationProgressEventArgs.cs
- GenerateTemporaryTargetAssembly.cs
- SystemWebExtensionsSectionGroup.cs
- ContentType.cs
- ConfigurationSettings.cs
- FixedSOMSemanticBox.cs
- BitmapEffectGeneralTransform.cs
- BufferedWebEventProvider.cs
- XmlSchemaFacet.cs
- ByteBufferPool.cs
- MobileComponentEditorPage.cs
- GregorianCalendarHelper.cs
- SafePipeHandle.cs
- SplashScreenNativeMethods.cs
- FloaterParagraph.cs
- LambdaCompiler.Unary.cs
- BamlCollectionHolder.cs
- DecimalKeyFrameCollection.cs
- FontFamilyValueSerializer.cs
- TrackingSection.cs
- safelinkcollection.cs
- TimersDescriptionAttribute.cs
- XmlReaderSettings.cs
- DataGridViewRowHeightInfoPushedEventArgs.cs
- AnnotationStore.cs
- FontWeight.cs
- PublishLicense.cs
- WmpBitmapEncoder.cs
- WeakReadOnlyCollection.cs
- AutomationProperty.cs
- DateTimeFormatInfoScanner.cs
- RtfControlWordInfo.cs
- RelationshipType.cs
- CompositeFontInfo.cs
- TextParagraphProperties.cs
- TypedTableGenerator.cs
- DataGridViewRowCancelEventArgs.cs
- NavigationWindowAutomationPeer.cs
- Point3D.cs
- HeaderUtility.cs
- SafeThreadHandle.cs
- MemoryMappedViewAccessor.cs
- DocumentGrid.cs
- UnsafePeerToPeerMethods.cs