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 / RenderData.cs / 1 / RenderData.cs
//---------------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: RenderData.cs // // Description: This file contains the implementation of RenderData. // A RenderData is the backing store for a Drawing or the contents // of a Visual. It contains a data stream which is a byte array // containing renderdata instructions and an array of dependent resource. // // History: // 03/30/2004 : adsmith - Created it. // //--------------------------------------------------------------------------- using MS.Internal; using MS.Utility; 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.Imaging; using System.Windows.Media.Effects; using System.Security; using System.Security.Permissions; namespace System.Windows.Media { ////// RenderData /// A RenderData is the backing store for a Drawing or the contents /// of a Visual. It contains a data stream which is a byte array /// containing renderdata instructions and an array of dependent resource. /// /// NOTE: RenderData is a not a fully functional Freezable /// internal partial class RenderData : Freezable, DUCE.IResource, IDrawingContent { ////// Default constructor. /// internal RenderData() { // RenderData is a transient object that does not want to participate // as the InheritanceContext of any of its dependents. (It can be // the Freezable context.) CanBeInheritanceContext = false; } ////// RenderData flags definition. /// [System.Flags] internal enum Flags : uint { HasStaticContentRequiringRealizations = 0x1, HasDynamicContentRequiringRealizations = 0x2, ContentIntroducesGraphness = 0x4, } ////// CheckFlagsAnd returns true if all flags in the bitmask flags are set. /// ///If there aren't any bits set on the specified flags the method /// returns true private bool CheckFlagsAnd(Flags flags) { return (_flags & flags) == flags; } ////// CheckFlagsOr returns true if any of the flags in the bitmask flags is set. /// ///If there aren't any bits set on the specified flags the method /// returns true private bool CheckFlagsOr(Flags flags) { return (flags == 0) || ((_flags & flags) > 0); } ////// SetFlags is used to set or unset a flag. /// private void SetFlags(bool value, Flags f) { _flags = value ? (_flags | f) : (_flags & (~f)); } ////// RecordHeader - This struct is the header for each record entry /// internal struct RecordHeader { public int Size; public MILCMD Id; } private enum PushType { BitmapEffect, Other } ////// WriteDataRecord - writes a data record in the form of "size - id - data" /// The Length of the data packed is "size" - (2 * sizeof(int)). /// Note that the cbRecordSize param is *only* the size of the record itself. The Size /// written to the stream will be larger (by sizeof(RecordHeader)) because it includes the size /// itself and the id. /// /// MILCMD - the record id /// /// byte* pointing to at least cbRecordSize bytes which will be copied to the stream. /// /// int - the size, in bytes, of pbRecord. Must be >= 0. ////// Critical: This code has unsafe code and dereferences a pointer /// [SecurityCritical] public unsafe void WriteDataRecord(MILCMD id, byte* pbRecord, int cbRecordSize) { Debug.Assert(cbRecordSize >= 0); // The records must always be padded to be QWORD aligned. Debug.Assert((_curOffset % 8) == 0); Debug.Assert((cbRecordSize % 8) == 0); Debug.Assert((sizeof(RecordHeader) % 8) == 0); int totalSize, newOffset; checked { totalSize = cbRecordSize + sizeof(RecordHeader); newOffset = _curOffset + totalSize; } // Do we need to increase the buffer size? // Yes, if there's no buffer or if the buffer is too small. if ((_buffer == null) || (newOffset > _buffer.Length)) { EnsureBuffer(newOffset); } // At this point, _buffer must be non-null and // _buffer.Length must be >= newOffset Debug.Assert((_buffer != null) && (_buffer.Length >= newOffset)); // Also, because pinning a 0-length buffer fails, we assert this too. Debug.Assert(_buffer.Length > 0); RecordHeader header; header.Size = totalSize; header.Id = id; Marshal.Copy((IntPtr)(&header), this._buffer, _curOffset, sizeof(RecordHeader)); Marshal.Copy((IntPtr)pbRecord, this._buffer, _curOffset + sizeof(RecordHeader), cbRecordSize); _curOffset += totalSize; // don't update if we don't have any effects or // we already have pushed at least one effect on the stack if (_effectDataResource != null && BitmapEffectStackDepth == 0) { _effectDataResource.UpdateDataSize(id, totalSize); } } #region IDrawingContent ////// Returns the bounding box occupied by the content /// ////// Bounding box occupied by the content /// public Rect GetContentBounds(BoundsDrawingContextWalker ctx) { Debug.Assert(ctx != null); DrawingContextWalk(ctx); return ctx.Bounds; } ////// Forward the current value of the content to the DrawingContextWalker /// methods. /// /// DrawingContextWalker to forward content to. public void WalkContent(DrawingContextWalker walker) { DrawingContextWalk(walker); } ////// Determines whether or not a point exists within the content /// /// Point to hit-test for. ////// 'true' if the point exists within the content, 'false' otherwise /// public bool HitTestPoint(Point point) { HitTestDrawingContextWalker ctx = new HitTestWithPointDrawingContextWalker(point); DrawingContextWalk(ctx); return ctx.IsHit; } ////// Hit-tests a geometry against this content /// /// PathGeometry to hit-test for. ////// IntersectionDetail describing the result of the hit-test /// public IntersectionDetail HitTestGeometry(PathGeometry geometry) { HitTestDrawingContextWalker ctx = new HitTestWithGeometryDrawingContextWalker(geometry); DrawingContextWalk(ctx); return ctx.IntersectionDetail; } protected override Freezable CreateInstanceCore() { return new RenderData(); } // We don't need to call ReadPreamble() because this is an internal class. // Plus, the extra VerifyAccess() calls might be an issue. // // We don't need to call WritePreamble() because this cannot be frozen // (FreezeCore always returns false) // // We don't need to call WritePostscript() because we only care if children // below us change. // // About the calls to Invariant.Assert(false)... we're only implementing // Freezable to hook up parent pointers from the children Freezables // to the RenderData. RenderData should never be cloned or frozen and // the class is internal so we'll just put in some Asserts to make sure // we don't do it in the future. protected override void CloneCore(Freezable source) { Invariant.Assert(false); } protected override void CloneCurrentValueCore(Freezable source) { Invariant.Assert(false); } protected override bool FreezeCore(bool isChecking) { return false; } protected override void GetAsFrozenCore(Freezable source) { Invariant.Assert(false); } protected override void GetCurrentValueAsFrozenCore(Freezable source) { Invariant.Assert(false); } ////// Propagates an event handler to Freezables and AnimationClockResources /// referenced by the content. /// /// Event handler to propagate /// 'true' to add the handler, 'false' to remove it public void PropagateChangedHandler(EventHandler handler, bool adding) { Debug.Assert(!this.IsFrozen); if (adding) { this.Changed += handler; } else { this.Changed -= handler; } for (int i = 0, count = _dependentResources.Count; i < count; i++) { Freezable freezableResource = _dependentResources[i] as Freezable; if (freezableResource != null) { // Ideally, we would call OFPC(null, freezable) in AddDependentResource // but RenderData never removes resources so nothing would ever remove // the context pointer. Fortunately, content calls PropagateChangedHandler // when it cares and when it stops caring about its resources. Thus, we'll // do all context hookup here. if (adding) { OnFreezablePropertyChanged(null, freezableResource); } else { OnFreezablePropertyChanged(freezableResource, null); } } else { // If it's not a Freezable it may be an AnimationClockResource, which we // also need to handle. AnimationClockResource clockResource = _dependentResources[i] as AnimationClockResource; if (clockResource != null) { // if it is a clock, it better not be a Freezable too or we'll // end up firing the handler twice Debug.Assert(_dependentResources[i] as Freezable == null); clockResource.PropagateChangedHandlersCore(handler, adding); } } } } ////// Walks the dictionary of resources and precomputes them. /// void IDrawingContent.PrecomputeContent() { MediaContext mc = MediaContext.From(Dispatcher); bool graphness = false; for (int i = 0, count = _dependentResources.Count; i < count; i++) { Animatable a = _dependentResources[i] as Animatable; if (a != null) { a.Precompute(); if (a.RequiresRealizationUpdates) { HasDynamicContentRequiringRealizations |= true; graphness |= a.CanIntroduceGraphness(); } } } SetFlags(graphness, Flags.ContentIntroducesGraphness); } ////// True iff the render data requires realization updates. /// bool IDrawingContent.ContentRequiresRealizationUpdates { get { return HasStaticContentRequiringRealizations || HasDynamicContentRequiringRealizations; } } ////// True if this content can introduce graphness. /// ////// There are two ways to introduce graphness in renderdata. /// the ContentIntroducesGraphness flag means that somewhere /// in the _dependentResources array is a resource that requires /// realization updates and can introduce graphness to the scene, /// such as a VisualBrush or DrawingBrush. /// bool IDrawingContent.ContentIntroducesGraphness { get { return CheckFlagsOr(Flags.ContentIntroducesGraphness); } } ////// Performs a realization update for the current render data. /// /// The render context. public void UpdateRealizations(RealizationContext realizationContext) { DrawingContextWalk(realizationContext.DrawingContextWalker); if (_effectDataResource != null) { if (_effectDataResource.BitmapEffectDrawing.ScheduleForUpdates) { BitmapEffectRenderDataContent content = new BitmapEffectRenderDataContent(this, realizationContext); realizationContext.ScheduleForRealizationsUpdate(content); _effectDataResource.BitmapEffectDrawing.ScheduleForUpdates = false; } _effectDataResource.BitmapEffectDrawing.UpdateRealizations(realizationContext); } } ////// HasStaticContentRequiringRealizations /// internal bool HasStaticContentRequiringRealizations { get { return CheckFlagsAnd(Flags.HasStaticContentRequiringRealizations); } set { SetFlags(value, Flags.HasStaticContentRequiringRealizations); } } ////// HasDynamicContentRequiringRealizations /// internal bool HasDynamicContentRequiringRealizations { get { return CheckFlagsAnd(Flags.HasDynamicContentRequiringRealizations); } set { SetFlags(value, Flags.HasDynamicContentRequiringRealizations); } } ////// Returns the stack depth for the last top level effect that was pushed /// If no effects are currently on the stack, returns 0 /// internal int BitmapEffectStackDepth { get { if (_effectDataResource == null) { return 0; } return _effectDataResource.BitmapEffectStackDepth; } set { //if this is the first time create it if (_effectDataResource == null) { _effectDataResource = new BitmapEffectRenderDataResource(); // set the DataSize to be the current offset // we want to add all commands up until the first PushEffect _effectDataResource.DataSize = _curOffset; } _effectDataResource.BitmapEffectStackDepth = value; } } ////// keep track where on the stack, the effect was pushed /// we do this only for top level effects /// /// internal void BeginTopLevelBitmapEffect(int stackDepth) { BitmapEffectStackDepth = stackDepth; // we have a new top level effect _effectDataResource.TopLevelEffects++; HasStaticContentRequiringRealizations = true; } ////// Reset the stack depth /// internal void EndTopLevelBitmapEffect() { BitmapEffectStackDepth = 0; } ////// Returns the size of the renderdata /// public int DataSize { get { if (_effectDataResource == null) { return _curOffset; } else { return _effectDataResource.DataSize; } } } #endregion IDrawingContent #region DUCE DUCE.ResourceHandle DUCE.IResource.AddRefOnChannel(DUCE.Channel channel) { using (CompositionEngineLock.Acquire()) { // AddRef'ing or Releasing the renderdata itself doesn't propgate through the dependents, // unless our ref goes from or to 0. This is why we have this if statement guarding // the inner loop. if (_duceResource.CreateOrAddRefOnChannel(channel, DUCE.ResourceType.TYPE_RENDERDATA)) { // First we AddRefOnChannel each of the dependent resources, // then we update our own. for (int i = 0; i < _dependentResources.Count; i++) { DUCE.IResource resource = _dependentResources[i] as DUCE.IResource; if (resource != null) { resource.AddRefOnChannel(channel); } } if (_effectDataResource != null) { _effectDataResource.CreateBitmapEffectResources(channel); } UpdateResource(channel); } return _duceResource.GetHandle(channel); } } void DUCE.IResource.ReleaseOnChannel(DUCE.Channel channel) { using (CompositionEngineLock.Acquire()) { Debug.Assert(_duceResource.IsOnChannel(channel)); // AddRef'ing or Releasing the renderdata itself doesn't propgate through the dependents, // unless our ref goes from or to 0. This is why we have this if statement guarding // the inner loop. if (_duceResource.ReleaseOnChannel(channel)) { for (int i = 0; i < _dependentResources.Count; i++) { DUCE.IResource resource = _dependentResources[i] as DUCE.IResource; if (resource != null) { resource.ReleaseOnChannel(channel); } } if (_effectDataResource != null) { _effectDataResource.ReleaseBitmapEffectResources(channel); } } } } DUCE.ResourceHandle DUCE.IResource.GetHandle(DUCE.Channel channel) { DUCE.ResourceHandle handle; // Reconsider the need for this lock when removing the MultiChannelResource. using (CompositionEngineLock.Acquire()) { // This method is a short cut and must only be called while the ref count // of this resource on this channel is non-zero. Thus we assert that this // resource is already on this channel. Debug.Assert(_duceResource.IsOnChannel(channel)); handle = _duceResource.GetHandle(channel); } return handle; } int DUCE.IResource.GetChannelCount() { return _duceResource.GetChannelCount(); } DUCE.Channel DUCE.IResource.GetChannel(int index) { return _duceResource.GetChannel(index); } ////// This is only implemented by Visual and Visual3D. /// void DUCE.IResource.RemoveChildFromParent(DUCE.IResource parent, DUCE.Channel channel) { throw new NotImplementedException(); } ////// This is only implemented by Visual and Visual3D. /// DUCE.ResourceHandle DUCE.IResource.Get3DHandle(DUCE.Channel channel) { throw new NotImplementedException(); } #endregion DUCE public uint AddDependentResource(Object o) { // Append the resource to the internal array. if (o == null) { return 0; } else { return (uint)(_dependentResources.Add(o) + 1); } } #region Internal Resource Methods private void UpdateResource(DUCE.Channel channel) { Debug.Assert(_duceResource.IsOnChannel(channel)); MarshalToDUCE(channel); } #endregion Internal Resource Methods #region Private Methods ////// EnsureBuffer - this method ensures that the capacity is at least equal to cbRequiredSize. /// /// int - the new minimum size required. Must be >= 0. private void EnsureBuffer(int cbRequiredSize) { Debug.Assert(cbRequiredSize >= 0); // If we don't have a buffer, this is easy: we simply allocate a new one of the appropriate size. if (_buffer == null) { _buffer = new byte[cbRequiredSize]; } else { // For efficiency, we shouldn't have been called if there's already enough room Debug.Assert(_buffer.Length < cbRequiredSize); // The new size will be 1.5 x the previous size, or the min size required (whichever is larger) // We perform the 1.5x math by taking 2x of the length and subtracting 0.5x the length because // the 2x and 0.5x can be figured via shifts. This is ~2x faster than performing the floating // point math. int newSize = Math.Max((_buffer.Length << 1) - (_buffer.Length >> 1), cbRequiredSize); // This is a double-check against the math above - if newSize isn't at least cbRequiredSize, // this growth function is broken. Debug.Assert(newSize >= cbRequiredSize); byte[] _newBuffer = new byte[newSize]; _buffer.CopyTo(_newBuffer, 0); _buffer = _newBuffer; } } ////// DependentLookup - given an index into the dependent resource array, /// we return null if the index is 0, else we return the dependent at index - 1. /// /// uint - 1-based index into the dependent array, 0 means "no lookup". private object DependentLookup(uint index) { Debug.Assert(index <= (uint)Int32.MaxValue); if (index == 0) { return null; } Debug.Assert(_dependentResources.Count >= index); return _dependentResources[(int)index - 1]; } ////// Update the DrawingGroup resource for each bitmap effect /// internal void ExecuteBitmapEffectRealizationUpdates(DUCE.Channel channel) { Debug.Assert(_effectDataResource != null); _effectDataResource.UpdateBitmapEffectResources(this, channel); } #endregion Private Methods #region Private Fields // The buffer into which the renderdata is written private byte[] _buffer; // The offset of the beginning of the next record // We ensure that the types in our instruction structs are correctly aligned wrt. their // size for read/write access, assuming that the instruction struct sits at an 8-byte // boundary. Thus _curOffset must always be at an 8-byte boundary to begin writing // an instruction. private int _curOffset; private FrugalStructList
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- TextEditorContextMenu.cs
- XmlCharCheckingWriter.cs
- LineServicesRun.cs
- GroupStyle.cs
- Comparer.cs
- PolicyStatement.cs
- OleDbWrapper.cs
- Emitter.cs
- UIPropertyMetadata.cs
- CryptoStream.cs
- PermissionToken.cs
- SqlBulkCopyColumnMapping.cs
- WebResponse.cs
- ProfessionalColorTable.cs
- BaseCodePageEncoding.cs
- OracleConnectionStringBuilder.cs
- FastEncoder.cs
- HttpRuntimeSection.cs
- webeventbuffer.cs
- RawUIStateInputReport.cs
- InvalidPrinterException.cs
- AssemblyAttributesGoHere.cs
- StaticSiteMapProvider.cs
- WebServiceHost.cs
- FormsIdentity.cs
- RenderData.cs
- QueryContinueDragEvent.cs
- JsonCollectionDataContract.cs
- SessionEndingCancelEventArgs.cs
- WindowsIdentity.cs
- Italic.cs
- ToolTipService.cs
- HtmlInputText.cs
- SafeProcessHandle.cs
- RuntimeIdentifierPropertyAttribute.cs
- Exceptions.cs
- UTF8Encoding.cs
- DrawingContextWalker.cs
- DrawingCollection.cs
- DataViewManager.cs
- ControlEvent.cs
- ContentDefinition.cs
- LinqDataSourceDisposeEventArgs.cs
- ModelTreeEnumerator.cs
- CodeTypeConstructor.cs
- arc.cs
- WebPartVerbsEventArgs.cs
- Events.cs
- PerformanceCounterPermission.cs
- HotSpotCollection.cs
- OAVariantLib.cs
- RenderTargetBitmap.cs
- PipelineModuleStepContainer.cs
- BooleanKeyFrameCollection.cs
- TiffBitmapEncoder.cs
- RenderOptions.cs
- EntityDataSourceSelectedEventArgs.cs
- GlyphElement.cs
- ReplacementText.cs
- CustomErrorCollection.cs
- VoiceChangeEventArgs.cs
- BamlCollectionHolder.cs
- MissingMemberException.cs
- PropertyBuilder.cs
- WindowManager.cs
- Size3D.cs
- _SpnDictionary.cs
- TypeTypeConverter.cs
- TypeConverter.cs
- SafeHandles.cs
- RuntimeIdentifierPropertyAttribute.cs
- Hex.cs
- EntityCommandExecutionException.cs
- XmlMapping.cs
- SamlAction.cs
- UIElementParagraph.cs
- GridViewRowPresenterBase.cs
- DefaultSerializationProviderAttribute.cs
- ValidatedControlConverter.cs
- webeventbuffer.cs
- ExpanderAutomationPeer.cs
- UnauthorizedWebPart.cs
- Journal.cs
- WebDescriptionAttribute.cs
- XmlObjectSerializerContext.cs
- Int64KeyFrameCollection.cs
- KeyTimeConverter.cs
- CanonicalFontFamilyReference.cs
- ActivitySurrogateSelector.cs
- MediaSystem.cs
- ShaderRenderModeValidation.cs
- PictureBox.cs
- ToolStripItemImageRenderEventArgs.cs
- WSSecurityXXX2005.cs
- ValueUtilsSmi.cs
- DynamicUpdateCommand.cs
- EventProviderWriter.cs
- GenericTextProperties.cs
- ControlPropertyNameConverter.cs
- HtmlFormWrapper.cs