Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Core / CSharp / System / Windows / Media / RenderData.cs / 1305600 / 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 : [....] - 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; } ////// 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; } #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); } } } } ////// 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 { return _bitmapEffectStackDepth; } set { _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; } ////// Reset the stack depth /// internal void EndTopLevelBitmapEffect() { BitmapEffectStackDepth = 0; } ////// Returns the size of the renderdata /// public int DataSize { get { return _curOffset; } } #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(this, 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); } } 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); } } } } } 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]; } #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 int _bitmapEffectStackDepth; private FrugalStructList
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- Activation.cs
- SpecularMaterial.cs
- SharedPerformanceCounter.cs
- DataBoundControl.cs
- RoleManagerEventArgs.cs
- UdpMessageProperty.cs
- DataListDesigner.cs
- ServiceOperationUIEditor.cs
- AttachedPropertyBrowsableAttribute.cs
- MonitorWrapper.cs
- SafeCryptoHandles.cs
- EntityDataSourceState.cs
- NullableDoubleSumAggregationOperator.cs
- EventLog.cs
- ChannelTerminatedException.cs
- Win32.cs
- Freezable.cs
- AsyncResult.cs
- SecurityTokenRequirement.cs
- Enumerable.cs
- PostBackOptions.cs
- SqlAliasesReferenced.cs
- WpfPayload.cs
- ClientUrlResolverWrapper.cs
- WbmpConverter.cs
- ExpressionVisitor.cs
- Switch.cs
- HelpInfo.cs
- EntityCodeGenerator.cs
- UriTemplateQueryValue.cs
- MsmqAppDomainProtocolHandler.cs
- XmlCharCheckingReader.cs
- XMLUtil.cs
- FlowDocumentPageViewerAutomationPeer.cs
- NamedPermissionSet.cs
- ContextProperty.cs
- HttpCapabilitiesSectionHandler.cs
- ContentControl.cs
- ExecutionEngineException.cs
- DesignerHelpers.cs
- MailWebEventProvider.cs
- RunWorkerCompletedEventArgs.cs
- EventListenerClientSide.cs
- AggregateNode.cs
- EmptyElement.cs
- FontFaceLayoutInfo.cs
- SapiGrammar.cs
- Int32CAMarshaler.cs
- StylusButtonEventArgs.cs
- TimeStampChecker.cs
- FixedSOMTextRun.cs
- Module.cs
- EntitySetBaseCollection.cs
- GeneratedView.cs
- NodeFunctions.cs
- GcSettings.cs
- LocalValueEnumerator.cs
- DbUpdateCommandTree.cs
- PropertyEmitterBase.cs
- ZoneMembershipCondition.cs
- ZeroOpNode.cs
- TouchEventArgs.cs
- FrameworkElement.cs
- CaseInsensitiveOrdinalStringComparer.cs
- MetaTableHelper.cs
- CommandTreeTypeHelper.cs
- QueryCacheKey.cs
- ExpressionConverter.cs
- GeneralTransform2DTo3D.cs
- DataSet.cs
- OdbcEnvironment.cs
- DataGridViewCellCollection.cs
- InputLangChangeEvent.cs
- DoubleStorage.cs
- DateTimeStorage.cs
- TemplatedEditableDesignerRegion.cs
- TryExpression.cs
- ObjectListCommandEventArgs.cs
- HttpResponse.cs
- ScriptingJsonSerializationSection.cs
- CryptographicAttribute.cs
- UiaCoreApi.cs
- HttpListener.cs
- MaskPropertyEditor.cs
- EdmToObjectNamespaceMap.cs
- DetailsViewInsertEventArgs.cs
- ToolboxItemLoader.cs
- BorderGapMaskConverter.cs
- MdImport.cs
- RichTextBox.cs
- CallInfo.cs
- InheritanceContextChangedEventManager.cs
- ImageSource.cs
- PropertyMapper.cs
- EntityCommandCompilationException.cs
- SizeConverter.cs
- Model3DGroup.cs
- StyleSelector.cs
- Padding.cs
- IntSecurity.cs