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
- DatePicker.cs
- StateMachine.cs
- SoapAttributes.cs
- ResizeGrip.cs
- InkCanvasFeedbackAdorner.cs
- SQLMembershipProvider.cs
- ValidatorCollection.cs
- CodeCatchClauseCollection.cs
- ContainsRowNumberChecker.cs
- AssemblyInfo.cs
- ToolStripLabel.cs
- SessionStateUtil.cs
- Single.cs
- Encoder.cs
- StructuralCache.cs
- FlowDocumentReaderAutomationPeer.cs
- DbReferenceCollection.cs
- Triangle.cs
- LinkedResourceCollection.cs
- RectAnimationBase.cs
- ChannelPoolSettings.cs
- SamlAdvice.cs
- TTSEvent.cs
- CollectionsUtil.cs
- FrugalList.cs
- AuthenticationManager.cs
- HostSecurityManager.cs
- ProfilePropertyNameValidator.cs
- SendingRequestEventArgs.cs
- ObfuscationAttribute.cs
- TdsParameterSetter.cs
- ProcessHostMapPath.cs
- WebPartMovingEventArgs.cs
- ReflectPropertyDescriptor.cs
- Base64Encoder.cs
- Timer.cs
- HScrollBar.cs
- MessageQueuePermissionAttribute.cs
- ValueExpressions.cs
- WindowsPen.cs
- AssemblyHash.cs
- KeyConstraint.cs
- SettingsBase.cs
- Size.cs
- TreeNodeCollection.cs
- MemberAccessException.cs
- SchemaMapping.cs
- Executor.cs
- WebConfigurationManager.cs
- ValueUtilsSmi.cs
- DataGridViewCellStyle.cs
- ValidatedControlConverter.cs
- LocalizationCodeDomSerializer.cs
- CustomError.cs
- TextContainerChangedEventArgs.cs
- SubpageParaClient.cs
- DataTable.cs
- TypeSystem.cs
- MemberAccessException.cs
- InvalidComObjectException.cs
- FixedHighlight.cs
- BorderGapMaskConverter.cs
- PropertyManager.cs
- FastPropertyAccessor.cs
- TextSimpleMarkerProperties.cs
- PageDeviceFont.cs
- ControlBuilder.cs
- XmlSchemaComplexContentRestriction.cs
- SR.Designer.cs
- FileSystemInfo.cs
- ResolveNameEventArgs.cs
- GlyphTypeface.cs
- ExpressionNormalizer.cs
- SignatureResourceHelper.cs
- JoinElimination.cs
- XmlSchemaSimpleContentExtension.cs
- ExtensionSurface.cs
- DateTimeValueSerializerContext.cs
- HelpKeywordAttribute.cs
- DataControlFieldCollection.cs
- EventLogReader.cs
- ValueCollectionParameterReader.cs
- EntityDataSourceWrapper.cs
- CachingHintValidation.cs
- SrgsGrammarCompiler.cs
- TrackingStringDictionary.cs
- CodeStatement.cs
- RuntimeHandles.cs
- ModelPerspective.cs
- AccessText.cs
- XmlDictionaryReaderQuotasElement.cs
- IDQuery.cs
- NativeCppClassAttribute.cs
- SoapConverter.cs
- CircleHotSpot.cs
- StylusSystemGestureEventArgs.cs
- WaitHandleCannotBeOpenedException.cs
- LinqExpressionNormalizer.cs
- FormClosedEvent.cs
- MdiWindowListItemConverter.cs