Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / Media / HitTestWithGeometryDrawingContextWalker.cs / 1305600 / HitTestWithGeometryDrawingContextWalker.cs
//---------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: HitTestWithGeometryDrawingContextWalker.cs // // Description: The implementation of HitTestWithGeometryDrawingContextWalker, // used to perform hit tests geometry 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.Media3D; using System.Windows.Media.Animation; using System.Windows.Media.Composition; using System.Windows.Media.Imaging; namespace System.Windows.Media { ////// HitTestDrawingContextWalker - a DrawingContextWalker which will perform a point or /// geometry based hit test on the contents of a render data. /// internal class HitTestWithGeometryDrawingContextWalker : HitTestDrawingContextWalker { ////// Constructor /// /// Geometry - the geometry to hit test, in local coordinates. internal HitTestWithGeometryDrawingContextWalker(PathGeometry geometry) { // The caller should pre-cull if the geometry is null. Debug.Assert(geometry != null); _geometry = geometry; _currentTransform = null; _currentClip = null; _intersectionDetail = IntersectionDetail.NotCalculated; } ////// IsHit Property - Returns true if geometry intersected the drawing instructions. /// internal override bool IsHit { get { return (_intersectionDetail != IntersectionDetail.Empty && _intersectionDetail != IntersectionDetail.NotCalculated); } } internal override IntersectionDetail IntersectionDetail { get { if (_intersectionDetail == IntersectionDetail.NotCalculated) { return IntersectionDetail.Empty; } else { return _intersectionDetail; } } } #region Private helper classes private class ModifierNode { } private class TransformModifierNode : ModifierNode { public TransformModifierNode(Transform transform) {_transform = transform;} public Transform _transform; } private class ClipModifierNode : ModifierNode { public ClipModifierNode(Geometry clip) {_clip = clip;} public Geometry _clip; } #endregion Private helper classes #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 ((geometry == null) || geometry.IsEmpty()) { return; } Geometry testedGeometry; // Transform if so prescribed if ((_currentTransform != null) && !_currentTransform.IsIdentity) { testedGeometry = geometry.GetTransformedCopy(_currentTransform); } else { testedGeometry = geometry; } // Clip, if so prescribed if (_currentClip != null) { testedGeometry = Geometry.Combine( testedGeometry, _currentClip, GeometryCombineMode.Intersect, null); // transform } if (brush != null) { AccumulateIntersectionDetail(testedGeometry.FillContainsWithDetail(_geometry)); } // If we have a pen and we haven't yet hit, try the widened geometry. if ((pen != null) && !_contains) { AccumulateIntersectionDetail(testedGeometry.StrokeContainsWithDetail(pen, _geometry)); } // 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 (glyphRun != null) { // The InkBoundingBox + the Origin produce the true InkBoundingBox. Rect rectangle = glyphRun.ComputeInkBoundingBox(); if (!rectangle.IsEmpty) { rectangle.Offset((Vector)glyphRun.BaselineOrigin); DrawGeometry(Brushes.Black, null /* pen */, new RectangleGeometry(rectangle)); } } } ////// 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) { // Intersect the new clip with the current one // 1st case:- No change, keep the old clip // 2nd case:- No matter what, the intersection will also be empty if ((clipGeometry == null) || ((_currentClip!=null) && (_currentClip.IsEmpty()))) { clipGeometry = _currentClip; } else { // Transform the clip new if so prescribed if ((_currentTransform != null) && !_currentTransform.IsIdentity) { clipGeometry = clipGeometry.GetTransformedCopy(_currentTransform); } // Intersect it with the current clip if (_currentClip != null) { clipGeometry = Geometry.Combine( _currentClip, clipGeometry, GeometryCombineMode.Intersect, null); // Transform } } // Push the previous clip on the stack PushModifierStack(new ClipModifierNode(_currentClip)); _currentClip = clipGeometry; } ////// PushOpacityMask - /// Push an opacity mask /// /// /// The opacity mask brush /// public override void PushOpacityMask(Brush brush) { // Opacity mask does not affect hit testing, but requires a place-holder on the stack PushModifierStack(null); } ////// 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) { // Opacity does not affect hit testing, but requires a place-holder on the stack PushModifierStack(null); } ////// 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) { // Combine the new transform with the current one if ((transform == null) || transform.IsIdentity) { // The new transform does not change the existing one transform = _currentTransform; } else if ((_currentTransform != null) && !_currentTransform.IsIdentity) { // Both the current transform and the new one are nontrivial, combine them Matrix combined = _currentTransform.Value * transform.Value; transform = new MatrixTransform(combined); } // Push the previous transform on the stack PushModifierStack(new TransformModifierNode(_currentTransform)); _currentTransform = transform; } ////// PushGuidelineSet - /// Push a set of guidelines which should be applied /// to all drawing operations until the /// corresponding Pop. /// /// The GuidelineSet to push. public override void PushGuidelineSet( GuidelineSet guidelines) { // GuidelineSet does not affect hit testing, but requires a place-holder on the stack PushModifierStack(null); } ////// PushGuidelineY1 - /// Explicitly push one horizontal guideline. /// /// The coordinate of leading guideline. internal override void PushGuidelineY1( Double coordinate) { // GuidelineSet does not affect hit testing, but requires a place-holder on the stack PushModifierStack(null); } ////// 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) { // GuidelineSet does not affect hit testing, but requires a place-holder on the stack PushModifierStack(null); } ////// Pop /// public override void Pop() { // We must have a modifier stack and it must not be empty. Debug.Assert(_modifierStack != null); Debug.Assert(_modifierStack.Count > 0); object currentModifier = _modifierStack.Pop(); if (currentModifier is TransformModifierNode) { _currentTransform = ((TransformModifierNode)currentModifier)._transform; // Since the drawing context starts out with no transform and no clip, // the first element pushed on the stack will always be null. Debug.Assert((_modifierStack.Count > 0) || (_currentTransform == null)); } else if (currentModifier is ClipModifierNode) { _currentClip = ((ClipModifierNode)currentModifier)._clip; // Since the drawing context starts out with no transform and no clip, // the first element pushed on the stack will always be null. Debug.Assert((_modifierStack.Count > 0) || (_currentClip == null)); } else { Debug.Assert(currentModifier == null); } } #endregion Static Drawing Context Methods #region Private Methods ////// AccumulateIntersectionDetail - accepts a new IntersectionDetail which is the result /// of "drawingCommandGeometry.FillContainsWithDetail(hitTestGeometry)" and updates /// the current _intersectionDetail, setting _contains as appropriate. /// /// /// The IntersectionDetail from hit-testing the current node. /// private void AccumulateIntersectionDetail(IntersectionDetail intersectionDetail) { // Note that: // * "FullyContains" means that the target node contains the hit test-geometry, // * "FullyInside" means that the target node is fully inside the hit-test geometry // The old result cannot be FullyContain, because that would have // triggered a StopWalk and we wouldn't be here Debug.Assert(_intersectionDetail != IntersectionDetail.FullyContains); // The new result cannot be NotCalculated, because we just // calculated! Debug.Assert(intersectionDetail != IntersectionDetail.NotCalculated); // The current _intersectionDetail is computed from its old value and the // new result according the the following table: // \ old + // New \ + NotCalc | Empty | Intersects | FullyInside There // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ is // Empty + Empty | Empty | Intersects | Intersects no // ------------+------------------------------------------------------- Contains // Intersects + Intersects | Intersects | Intersects | Intersects column // ------------+------------------------------------------------------- (see // Contains + Contains | Contains | Contains | Contains assertion // ------------+-------------------------------------------------------- above) // FullyInside + FullInside | Intersects | Intersects | FullyInside if (_intersectionDetail == IntersectionDetail.NotCalculated) // This is the first node { _intersectionDetail = intersectionDetail; // Takes care of the first column. } else if (intersectionDetail == IntersectionDetail.FullyInside // This node is fully inside the hit geometry -- && _intersectionDetail != IntersectionDetail.FullyInside) // -- but we have already encountered a previous node that was not fully inside { _intersectionDetail = IntersectionDetail.Intersects; // Taking care of the second-to-left bottom cell } else if (intersectionDetail == IntersectionDetail.Empty // This node does not touch the hit geometry -- && _intersectionDetail != IntersectionDetail.Empty) // -- but we have already encountered a previous node that was touched { _intersectionDetail = IntersectionDetail.Intersects; // Taking care of the third and fourth cells in the first row } else { // Accept the new result as is _intersectionDetail = intersectionDetail; // Taking care of the second and third row and the diagonal } if (_intersectionDetail == IntersectionDetail.FullyContains) { // The hit geometry is fully contained in the visual, so signal a StopWalk _contains = true; } } private void PushModifierStack(ModifierNode modifier) { // Push the old modifier on the stack if (_modifierStack == null) { _modifierStack = new Stack(); } _modifierStack.Push(modifier); } #endregion Private Methods #region Private Fields // The geometry with which we are hit-testing private PathGeometry _geometry; // The stack of previous values of transfrom/clip private Stack _modifierStack; // The current transform private Transform _currentTransform; // The current clip private Geometry _currentClip; // This keeps track of the details of a geometry hit test. private IntersectionDetail _intersectionDetail; #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
- ExternalException.cs
- DataList.cs
- MemberPathMap.cs
- XmlEntityReference.cs
- DependencyPropertyConverter.cs
- TrackingWorkflowEventArgs.cs
- XmlSerializerFactory.cs
- Cursors.cs
- DataGridViewRowHeightInfoNeededEventArgs.cs
- ThemeDirectoryCompiler.cs
- TypeConverters.cs
- BitmapCache.cs
- BitmapEffectInputData.cs
- PeerToPeerException.cs
- TextSegment.cs
- X509SecurityTokenProvider.cs
- CustomValidator.cs
- SingleKeyFrameCollection.cs
- TimerEventSubscription.cs
- KnownTypeDataContractResolver.cs
- SiteMapProvider.cs
- TemplatePartAttribute.cs
- IgnoreSection.cs
- DBConnection.cs
- WindowsPrincipal.cs
- ResourceContainer.cs
- HttpModuleActionCollection.cs
- BufferAllocator.cs
- CreateParams.cs
- TriState.cs
- NativeMethods.cs
- dbenumerator.cs
- AggregatePushdown.cs
- XPathPatternParser.cs
- DBConnectionString.cs
- TemplateBindingExpression.cs
- CodeEntryPointMethod.cs
- Vector3DAnimationBase.cs
- AuthorizationSection.cs
- WebReferenceOptions.cs
- SatelliteContractVersionAttribute.cs
- TraceUtility.cs
- ValidatingPropertiesEventArgs.cs
- FrameDimension.cs
- SelectionHighlightInfo.cs
- Quaternion.cs
- CellNormalizer.cs
- RegexRunner.cs
- NumericPagerField.cs
- ObjectAssociationEndMapping.cs
- FormViewModeEventArgs.cs
- LinearQuaternionKeyFrame.cs
- ParagraphVisual.cs
- PointIndependentAnimationStorage.cs
- CodeDomConfigurationHandler.cs
- XmlSigningNodeWriter.cs
- _PooledStream.cs
- PrimitiveCodeDomSerializer.cs
- UIElementParagraph.cs
- ChannelAcceptor.cs
- ToolStripItemDesigner.cs
- CoreSwitches.cs
- TypeToken.cs
- CollectionViewGroup.cs
- Italic.cs
- versioninfo.cs
- ConfigurationSectionCollection.cs
- DelayedRegex.cs
- ListViewGroup.cs
- RepeaterCommandEventArgs.cs
- SafeLibraryHandle.cs
- XPathNodeIterator.cs
- SctClaimSerializer.cs
- EventLogPermissionEntryCollection.cs
- Int64KeyFrameCollection.cs
- DataGridViewCellCancelEventArgs.cs
- Visual3D.cs
- ListSortDescription.cs
- ColorTransformHelper.cs
- AbsoluteQuery.cs
- AttachedPropertyMethodSelector.cs
- RuntimeEnvironment.cs
- DirectoryNotFoundException.cs
- WindowsSidIdentity.cs
- DataGridTablesFactory.cs
- TextLineBreak.cs
- TagMapInfo.cs
- TextServicesProperty.cs
- TemplateInstanceAttribute.cs
- DisplayNameAttribute.cs
- StringConverter.cs
- _SSPIWrapper.cs
- DelimitedListTraceListener.cs
- SchemaImporterExtensionElementCollection.cs
- Timer.cs
- XmlAttribute.cs
- SelectionHighlightInfo.cs
- StorageEntitySetMapping.cs
- shaper.cs
- SpanIndex.cs