Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Core / CSharp / System / Windows / Media / HitTestWithPointDrawingContextWalker.cs / 1 / HitTestWithPointDrawingContextWalker.cs
//---------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: HitTestWithPointDrawingContextWalker.cs // // Description: The implementation of HitTestWithPointDrawingContextWalker, // used to perform hit tests with a point on renderdata. // // History: // 06/20/2005 : michka - Carved it out of HitTestDrawingWalker.cs // //--------------------------------------------------------------------------- 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.Composition; using System.Windows.Media.Effects; using System.Windows.Media.Imaging; namespace System.Windows.Media { ////// HitTestDrawingContextWalker - a DrawingContextWalker which performs a hit test with a point /// internal class HitTestWithPointDrawingContextWalker: HitTestDrawingContextWalker { ////// Constructor /// /// Point - the point to hit test, in local coordinates. internal HitTestWithPointDrawingContextWalker(Point point) { _point = point; } ////// IsHit Property - Returns whether the point hit the drawing instructions. /// internal override bool IsHit { get { return _contains; } } internal override IntersectionDetail IntersectionDetail { get { return _contains ? IntersectionDetail.FullyInside : IntersectionDetail.Empty; } } #region Static Drawing Context Methods ////// DrawGeometry - /// Draw a Geometry with the provided Brush and/or Pen. /// If both the Brush and Pen are null this call is a no-op. /// /// /// The Brush with which to fill the Geometry. /// This is optional, and can be null, in which case no fill is performed. /// /// /// The Pen with which to stroke the Geometry. /// This is optional, and can be null, in which case no stroke is performed. /// /// The Geometry to fill and/or stroke. public override void DrawGeometry( Brush brush, Pen pen, Geometry geometry) { if (IsCurrentLayerNoOp ||(geometry == null) || geometry.IsEmpty()) { return; } if (brush != null) { _contains |= geometry.FillContains(_point); } // If we have a pen and we haven't yet hit, try the widened geometry. if ((pen != null) && !_contains) { _contains |= geometry.StrokeContains(pen, _point); } // If we've hit, stop walking. if (_contains) { StopWalking(); } } ////// Draw a GlyphRun. /// /// Foreground brush to draw GlyphRun with. /// The GlyphRun to draw. ////// This call is illegal if this object has already been closed or disposed. /// public override void DrawGlyphRun(Brush foregroundBrush, GlyphRun glyphRun) { if (!IsCurrentLayerNoOp && (glyphRun != null)) { // The InkBoundingBox + the Origin produce the true InkBoundingBox. Rect rectangle = glyphRun.ComputeInkBoundingBox(); if (!rectangle.IsEmpty) { rectangle.Offset((Vector)glyphRun.BaselineOrigin); _contains |= rectangle.Contains(_point); // If we've hit, stop walking. if (_contains) { StopWalking(); } } } } ////// PushClip - /// Push a clip region, which will apply to all drawing primitives until the /// corresponding Pop call. /// /// The Geometry to which we will clip. public override void PushClip( Geometry clipGeometry) { if (!IsPushNoOp()) { PushPointStack(_point); // If the clip being pushed doesn't contain the hit test point, // then we don't need to consider any of the subsequent Drawing // operations in this layer. if ((clipGeometry != null) && !clipGeometry.FillContains(_point)) { IsCurrentLayerNoOp = true; } } } ////// PushOpacityMask - /// Push an opacity mask /// /// /// The opacity mask brush /// public override void PushOpacityMask(Brush brush) { if (!IsPushNoOp()) { // This Push doesn't affect the hit test, so just push the current point PushPointStack(_point); } } ////// PushOpacity - /// Push an opacity which will blend the composite of all drawing primitives added /// until the corresponding Pop call. /// /// /// The opacity with which to blend - 0 is transparent, 1 is opaque. /// public override void PushOpacity( Double opacity) { if (!IsPushNoOp()) { // This Push doesn't affect the hit test, so just push the current point PushPointStack(_point); } } ////// PushTransform - /// Push a Transform which will apply to all drawing operations until the corresponding /// Pop. /// /// The Transform to push. public override void PushTransform( Transform transform) { if (!IsPushNoOp()) { if (transform == null || transform.IsIdentity) { PushPointStack(_point); } else { Matrix matrix = transform.Value; if (matrix.HasInverse) { // Invert the transform. The inverse will be applied to the point // so that hit testing is done in the original geometry's coordinates matrix.Invert(); // Push the transformed point on the stack. This also updates _point. PushPointStack(_point * matrix); } else { // If this transform doesn't have an inverse, then we don't need to consider any // of the subsequent Drawing operations in this layer. IsCurrentLayerNoOp = true; } } } } ////// 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) { if (!IsPushNoOp()) { // This Push doesn't affect the hit test, so just push the current point PushPointStack(_point); } } ////// PushGuidelineY1 - /// Explicitly push one horizontal guideline. /// /// The coordinate of leading guideline. internal override void PushGuidelineY1( Double coordinate) { if (!IsPushNoOp()) { // This Push doesn't affect the hit test, so just push the current point PushPointStack(_point); } } ////// 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) { if (!IsPushNoOp()) { // This Push doesn't affect the hit test, so just push the current point PushPointStack(_point); } } ////// 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) { if (!IsPushNoOp()) { if (effect != null) { if (effectInput == null) { effectInput = new BitmapEffectInput(); } effect.VisualBounds = new Rect(_point, _point); effect.TransformPoint(effectInput, _point, out _point, true /* fInverse */); } PushPointStack(_point); } } ////// Pop /// public override void Pop( ) { if (!IsPopNoOp()) { PopPointStack(); } } #endregion Static Drawing Context Methods #region Private Methods ////// PushPointStack - push a point onto the stack and update _point with it. /// /// The new Point to push. private void PushPointStack(Point point) { if (_pointStack == null) { _pointStack = new Stack(2); } // Push the old point. _pointStack.Push(_point); // update current point _point = point; } /// /// PopPointStack - pop a point off of the point stack and update _point. /// private void PopPointStack() { // We must have a point stack and it must not be empty. Debug.Assert(_pointStack != null); Debug.Assert(_pointStack.Count > 0); // Retrieve the previous point from the stack. _point = _pointStack.Pop(); } ////// Called by every Push operation, this method returns whether or not /// the operation should be a no-op. If the current subgraph layer /// is being no-op'd, it also increments the no-op depth. /// private bool IsPushNoOp() { if (IsCurrentLayerNoOp) { // Increment the depth so that the no-op status isn't reset // when this layer's cooresponding Pop is called. _noOpLayerDepth++; return true; } else { return false; } } ////// Called by Pop, this method returns whether or not Pop should be /// a no-op'd. If the current subgraph layer is being no-op'd, it also /// decrements the no-op depth, then reset's the no-op status if this /// is the last Pop in the no-op layer. /// private bool IsPopNoOp() { if (IsCurrentLayerNoOp) { Debug.Assert(_noOpLayerDepth >= 1); _noOpLayerDepth--; // If this Pop cooresponds to the Push that created // the no-op layer, then reset the no-op status. if (_noOpLayerDepth == 0) { IsCurrentLayerNoOp = false; } return true; } else { return false; } } ////// Set/resets and gets whether or not the current subgraph layer is a no-op. /// Currently, all subsequent instructions are skipped (no-op'd) when a non-invertible /// transform is pushed (because we have to invert the matrix to perform /// a hit-test), or during a point hit-test when a clip is pushed that /// doesn't contain the point. /// private bool IsCurrentLayerNoOp { set { if (value == true) { // Guard that we aren't already in a no-op layer // // Instructions that can cause the layer to be no-op'd should be // no-op'd themselves, and thus can't call this method, if we // are already in a no-op layer Debug.Assert(!_currentLayerIsNoOp); Debug.Assert(_noOpLayerDepth == 0); // Set the no-op status & initial depth _currentLayerIsNoOp = true; _noOpLayerDepth++; } else { // Guard that we are in a no-op layer, and that the correct corresponding // Pop has been called. Debug.Assert(_currentLayerIsNoOp); Debug.Assert(_noOpLayerDepth == 0); // Reset the no-op status _currentLayerIsNoOp = false; } } get { return _currentLayerIsNoOp; } } #endregion Private Methods #region Private Fields // If _isPointHitTest is true, this _point is the hit test point. private Point _point; // The hit test point transformed to target geometry's original coordinates private Stack_pointStack; // When true, all instructions should be perform no logic until the // layer is exited via a Pop() private bool _currentLayerIsNoOp; // Number of Pop() calls until _currentLayerIsNoOp should be reset. private int _noOpLayerDepth; #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. //---------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: HitTestWithPointDrawingContextWalker.cs // // Description: The implementation of HitTestWithPointDrawingContextWalker, // used to perform hit tests with a point on renderdata. // // History: // 06/20/2005 : michka - Carved it out of HitTestDrawingWalker.cs // //--------------------------------------------------------------------------- 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.Composition; using System.Windows.Media.Effects; using System.Windows.Media.Imaging; namespace System.Windows.Media { /// /// HitTestDrawingContextWalker - a DrawingContextWalker which performs a hit test with a point /// internal class HitTestWithPointDrawingContextWalker: HitTestDrawingContextWalker { ////// Constructor /// /// Point - the point to hit test, in local coordinates. internal HitTestWithPointDrawingContextWalker(Point point) { _point = point; } ////// IsHit Property - Returns whether the point hit the drawing instructions. /// internal override bool IsHit { get { return _contains; } } internal override IntersectionDetail IntersectionDetail { get { return _contains ? IntersectionDetail.FullyInside : IntersectionDetail.Empty; } } #region Static Drawing Context Methods ////// DrawGeometry - /// Draw a Geometry with the provided Brush and/or Pen. /// If both the Brush and Pen are null this call is a no-op. /// /// /// The Brush with which to fill the Geometry. /// This is optional, and can be null, in which case no fill is performed. /// /// /// The Pen with which to stroke the Geometry. /// This is optional, and can be null, in which case no stroke is performed. /// /// The Geometry to fill and/or stroke. public override void DrawGeometry( Brush brush, Pen pen, Geometry geometry) { if (IsCurrentLayerNoOp ||(geometry == null) || geometry.IsEmpty()) { return; } if (brush != null) { _contains |= geometry.FillContains(_point); } // If we have a pen and we haven't yet hit, try the widened geometry. if ((pen != null) && !_contains) { _contains |= geometry.StrokeContains(pen, _point); } // If we've hit, stop walking. if (_contains) { StopWalking(); } } ////// Draw a GlyphRun. /// /// Foreground brush to draw GlyphRun with. /// The GlyphRun to draw. ////// This call is illegal if this object has already been closed or disposed. /// public override void DrawGlyphRun(Brush foregroundBrush, GlyphRun glyphRun) { if (!IsCurrentLayerNoOp && (glyphRun != null)) { // The InkBoundingBox + the Origin produce the true InkBoundingBox. Rect rectangle = glyphRun.ComputeInkBoundingBox(); if (!rectangle.IsEmpty) { rectangle.Offset((Vector)glyphRun.BaselineOrigin); _contains |= rectangle.Contains(_point); // If we've hit, stop walking. if (_contains) { StopWalking(); } } } } ////// PushClip - /// Push a clip region, which will apply to all drawing primitives until the /// corresponding Pop call. /// /// The Geometry to which we will clip. public override void PushClip( Geometry clipGeometry) { if (!IsPushNoOp()) { PushPointStack(_point); // If the clip being pushed doesn't contain the hit test point, // then we don't need to consider any of the subsequent Drawing // operations in this layer. if ((clipGeometry != null) && !clipGeometry.FillContains(_point)) { IsCurrentLayerNoOp = true; } } } ////// PushOpacityMask - /// Push an opacity mask /// /// /// The opacity mask brush /// public override void PushOpacityMask(Brush brush) { if (!IsPushNoOp()) { // This Push doesn't affect the hit test, so just push the current point PushPointStack(_point); } } ////// PushOpacity - /// Push an opacity which will blend the composite of all drawing primitives added /// until the corresponding Pop call. /// /// /// The opacity with which to blend - 0 is transparent, 1 is opaque. /// public override void PushOpacity( Double opacity) { if (!IsPushNoOp()) { // This Push doesn't affect the hit test, so just push the current point PushPointStack(_point); } } ////// PushTransform - /// Push a Transform which will apply to all drawing operations until the corresponding /// Pop. /// /// The Transform to push. public override void PushTransform( Transform transform) { if (!IsPushNoOp()) { if (transform == null || transform.IsIdentity) { PushPointStack(_point); } else { Matrix matrix = transform.Value; if (matrix.HasInverse) { // Invert the transform. The inverse will be applied to the point // so that hit testing is done in the original geometry's coordinates matrix.Invert(); // Push the transformed point on the stack. This also updates _point. PushPointStack(_point * matrix); } else { // If this transform doesn't have an inverse, then we don't need to consider any // of the subsequent Drawing operations in this layer. IsCurrentLayerNoOp = true; } } } } ////// 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) { if (!IsPushNoOp()) { // This Push doesn't affect the hit test, so just push the current point PushPointStack(_point); } } ////// PushGuidelineY1 - /// Explicitly push one horizontal guideline. /// /// The coordinate of leading guideline. internal override void PushGuidelineY1( Double coordinate) { if (!IsPushNoOp()) { // This Push doesn't affect the hit test, so just push the current point PushPointStack(_point); } } ////// 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) { if (!IsPushNoOp()) { // This Push doesn't affect the hit test, so just push the current point PushPointStack(_point); } } ////// 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) { if (!IsPushNoOp()) { if (effect != null) { if (effectInput == null) { effectInput = new BitmapEffectInput(); } effect.VisualBounds = new Rect(_point, _point); effect.TransformPoint(effectInput, _point, out _point, true /* fInverse */); } PushPointStack(_point); } } ////// Pop /// public override void Pop( ) { if (!IsPopNoOp()) { PopPointStack(); } } #endregion Static Drawing Context Methods #region Private Methods ////// PushPointStack - push a point onto the stack and update _point with it. /// /// The new Point to push. private void PushPointStack(Point point) { if (_pointStack == null) { _pointStack = new Stack(2); } // Push the old point. _pointStack.Push(_point); // update current point _point = point; } /// /// PopPointStack - pop a point off of the point stack and update _point. /// private void PopPointStack() { // We must have a point stack and it must not be empty. Debug.Assert(_pointStack != null); Debug.Assert(_pointStack.Count > 0); // Retrieve the previous point from the stack. _point = _pointStack.Pop(); } ////// Called by every Push operation, this method returns whether or not /// the operation should be a no-op. If the current subgraph layer /// is being no-op'd, it also increments the no-op depth. /// private bool IsPushNoOp() { if (IsCurrentLayerNoOp) { // Increment the depth so that the no-op status isn't reset // when this layer's cooresponding Pop is called. _noOpLayerDepth++; return true; } else { return false; } } ////// Called by Pop, this method returns whether or not Pop should be /// a no-op'd. If the current subgraph layer is being no-op'd, it also /// decrements the no-op depth, then reset's the no-op status if this /// is the last Pop in the no-op layer. /// private bool IsPopNoOp() { if (IsCurrentLayerNoOp) { Debug.Assert(_noOpLayerDepth >= 1); _noOpLayerDepth--; // If this Pop cooresponds to the Push that created // the no-op layer, then reset the no-op status. if (_noOpLayerDepth == 0) { IsCurrentLayerNoOp = false; } return true; } else { return false; } } ////// Set/resets and gets whether or not the current subgraph layer is a no-op. /// Currently, all subsequent instructions are skipped (no-op'd) when a non-invertible /// transform is pushed (because we have to invert the matrix to perform /// a hit-test), or during a point hit-test when a clip is pushed that /// doesn't contain the point. /// private bool IsCurrentLayerNoOp { set { if (value == true) { // Guard that we aren't already in a no-op layer // // Instructions that can cause the layer to be no-op'd should be // no-op'd themselves, and thus can't call this method, if we // are already in a no-op layer Debug.Assert(!_currentLayerIsNoOp); Debug.Assert(_noOpLayerDepth == 0); // Set the no-op status & initial depth _currentLayerIsNoOp = true; _noOpLayerDepth++; } else { // Guard that we are in a no-op layer, and that the correct corresponding // Pop has been called. Debug.Assert(_currentLayerIsNoOp); Debug.Assert(_noOpLayerDepth == 0); // Reset the no-op status _currentLayerIsNoOp = false; } } get { return _currentLayerIsNoOp; } } #endregion Private Methods #region Private Fields // If _isPointHitTest is true, this _point is the hit test point. private Point _point; // The hit test point transformed to target geometry's original coordinates private Stack_pointStack; // When true, all instructions should be perform no logic until the // layer is exited via a Pop() private bool _currentLayerIsNoOp; // Number of Pop() calls until _currentLayerIsNoOp should be reset. private int _noOpLayerDepth; #endregion Private Fields } } // 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
- HybridDictionary.cs
- ReferenceAssemblyAttribute.cs
- ChangeBlockUndoRecord.cs
- SamlDoNotCacheCondition.cs
- PerfCounters.cs
- SynchronizationContext.cs
- Brush.cs
- FormViewInsertEventArgs.cs
- ClientUrlResolverWrapper.cs
- CmsUtils.cs
- InternalResources.cs
- NullableBoolConverter.cs
- AsyncPostBackErrorEventArgs.cs
- DbDataAdapter.cs
- SelectedGridItemChangedEvent.cs
- CodeTypeParameterCollection.cs
- GlyphRunDrawing.cs
- ZipIOCentralDirectoryDigitalSignature.cs
- RSAOAEPKeyExchangeDeformatter.cs
- ArrangedElement.cs
- FontStyleConverter.cs
- XmlElementCollection.cs
- DefaultTypeArgumentAttribute.cs
- SpanIndex.cs
- EventMetadata.cs
- FailedToStartupUIException.cs
- CharUnicodeInfo.cs
- AutomationProperties.cs
- ServiceAuthorizationElement.cs
- KeyBinding.cs
- __FastResourceComparer.cs
- ExpandCollapsePatternIdentifiers.cs
- LocatorPart.cs
- TextShapeableCharacters.cs
- SHA1.cs
- DataSourceDesigner.cs
- SimplePropertyEntry.cs
- DefaultTextStore.cs
- DiagnosticsConfigurationHandler.cs
- ComboBoxAutomationPeer.cs
- InstallHelper.cs
- SafeRegistryHandle.cs
- ContextProperty.cs
- SecurityPolicySection.cs
- FormViewDesigner.cs
- FamilyMap.cs
- Registry.cs
- RadioButton.cs
- MediaElement.cs
- ExpandableObjectConverter.cs
- HttpServerProtocol.cs
- ControlsConfig.cs
- Utils.cs
- IfAction.cs
- RunClient.cs
- DialogWindow.cs
- WorkflowServiceAttributes.cs
- DynamicPropertyHolder.cs
- ISessionStateStore.cs
- SystemInfo.cs
- XamlTreeBuilderBamlRecordWriter.cs
- uribuilder.cs
- XPathDocument.cs
- PreviewKeyDownEventArgs.cs
- TemplateControlParser.cs
- ReachDocumentReferenceSerializerAsync.cs
- AsyncResult.cs
- MimeMultiPart.cs
- SqlBooleanMismatchVisitor.cs
- X509ScopedServiceCertificateElement.cs
- FontConverter.cs
- PropertyInformationCollection.cs
- ObjectMemberMapping.cs
- DocumentGridPage.cs
- InvalidProgramException.cs
- WindowsBrush.cs
- ToolStripHighContrastRenderer.cs
- Literal.cs
- TileModeValidation.cs
- ColorContextHelper.cs
- HideDisabledControlAdapter.cs
- DrawingGroupDrawingContext.cs
- VectorConverter.cs
- PaperSource.cs
- StructuredCompositeActivityDesigner.cs
- ValueSerializer.cs
- cookieexception.cs
- Exceptions.cs
- WebServiceReceive.cs
- HttpCookieCollection.cs
- TerminateWorkflow.cs
- OpCodes.cs
- TableLayoutStyleCollection.cs
- ToolStripRendererSwitcher.cs
- DCSafeHandle.cs
- SeparatorAutomationPeer.cs
- XmlName.cs
- X509ChainElement.cs
- RotateTransform.cs
- TableCellAutomationPeer.cs