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
- TrackingAnnotationCollection.cs
- ECDiffieHellman.cs
- JsonGlobals.cs
- ThemeableAttribute.cs
- ASCIIEncoding.cs
- FileNotFoundException.cs
- InputLanguageManager.cs
- MaterialCollection.cs
- DesignerSerializerAttribute.cs
- PerformanceCounterLib.cs
- HTMLTagNameToTypeMapper.cs
- TagNameToTypeMapper.cs
- MsmqUri.cs
- HttpValueCollection.cs
- DataGridViewDataConnection.cs
- EntityObject.cs
- ListSourceHelper.cs
- SmtpSpecifiedPickupDirectoryElement.cs
- TokenBasedSet.cs
- ArithmeticException.cs
- ObjectFullSpanRewriter.cs
- WindowsToolbarAsMenu.cs
- DataExchangeServiceBinder.cs
- PropertyManager.cs
- LinqDataSourceContextEventArgs.cs
- FontInfo.cs
- StreamGeometryContext.cs
- ButtonAutomationPeer.cs
- FunctionMappingTranslator.cs
- Point3DAnimationUsingKeyFrames.cs
- SubordinateTransaction.cs
- SplashScreen.cs
- GenericTextProperties.cs
- GeneralTransform3DTo2DTo3D.cs
- NeutralResourcesLanguageAttribute.cs
- AnimatedTypeHelpers.cs
- TrackingServices.cs
- UserControlCodeDomTreeGenerator.cs
- Quad.cs
- ListViewCancelEventArgs.cs
- XmlValidatingReader.cs
- SchemaImporter.cs
- DecoratedNameAttribute.cs
- CompiledRegexRunner.cs
- XmlEntityReference.cs
- EncryptedKey.cs
- RSAPKCS1SignatureDeformatter.cs
- TimeSpanParse.cs
- CharConverter.cs
- BitStack.cs
- ReaderContextStackData.cs
- MasterPage.cs
- serverconfig.cs
- ModifiableIteratorCollection.cs
- QueryNode.cs
- BamlLocalizableResourceKey.cs
- MiniMapControl.xaml.cs
- RequestCacheManager.cs
- SecurityIdentifierElementCollection.cs
- ExpressionPrinter.cs
- TransactionFlowOption.cs
- CodeAttachEventStatement.cs
- TagPrefixAttribute.cs
- ComponentSerializationService.cs
- LayoutEvent.cs
- ComponentEvent.cs
- RadioButtonPopupAdapter.cs
- PopupControlService.cs
- QilParameter.cs
- ActiveDocumentEvent.cs
- TransactionsSectionGroup.cs
- PolicyFactory.cs
- SpecialNameAttribute.cs
- ConfigurationStrings.cs
- Win32Exception.cs
- Rotation3DAnimationUsingKeyFrames.cs
- SQLString.cs
- MergePropertyDescriptor.cs
- SiteMapDataSource.cs
- ConfigurationSectionGroup.cs
- PropertyGridView.cs
- COM2ColorConverter.cs
- RemoteWebConfigurationHostServer.cs
- StylusPointPropertyInfo.cs
- SourceFileBuildProvider.cs
- WpfKnownTypeInvoker.cs
- BmpBitmapDecoder.cs
- Tag.cs
- StatusInfoItem.cs
- DataRelationPropertyDescriptor.cs
- ISAPIWorkerRequest.cs
- Missing.cs
- ToolStripMenuItem.cs
- InstanceContextManager.cs
- GeneralTransformGroup.cs
- StorageMappingItemLoader.cs
- TextDecorations.cs
- CacheVirtualItemsEvent.cs
- TypeContext.cs
- BuilderInfo.cs