Code:
/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / wpf / src / Core / CSharp / System / Windows / Media / Effects / BitmapEffect.cs / 1 / BitmapEffect.cs
//------------------------------------------------------------------------------
// Microsoft Avalon
// Copyright (c) Microsoft Corporation, 2005
//
// File: BitmapEffect.cs
//-----------------------------------------------------------------------------
using MS.Internal;
using System;
using System.IO;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Diagnostics;
using System.Reflection;
using System.Windows.Threading;
using System.Threading;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Media;
using System.Windows.Markup;
using System.Windows.Media.Animation;
using System.Windows.Media.Composition;
using System.Windows.Media.Imaging;
using System.Security;
using MS.Internal.PresentationCore;
using System.Security.Permissions;
using SR = MS.Internal.PresentationCore.SR;
using SRID = MS.Internal.PresentationCore.SRID;
namespace System.Windows.Media.Effects
{
internal class BitmapEffectException : Exception
{
public BitmapEffectException()
{
}
}
///
/// BitmapEffect
///
///
/// We have the Inheritance demand, because we don't want
/// third parties to be able to subclass BitmapEffect in the partial trust scenario
///
[UIPermissionAttribute(SecurityAction.InheritanceDemand, Window = UIPermissionWindow.AllWindows)]
public abstract partial class BitmapEffect
{
private SafeMILHandle _unmanagedEffectGroup;
private SafeHandle _unmanagedEffect;
private BitmapEffectRenderContext _renderContext = new BitmapEffectRenderContext();
private Rect _visualBounds = Rect.Empty;
private const double DefaultDevicePixelsPerInch = 96.0;
internal bool _connectionsSetup = false;
#region Constructors
///
/// Constructor
///
protected BitmapEffect()
{
// STA Requirement
//
// Avalon doesn't necessarily require STA, but many components do. Examples
// include Cicero, OLE, COM, etc. So we throw an exception here if the
// thread is not STA.
if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
{
throw new InvalidOperationException(SR.Get(SRID.RequiresSTA));
}
//
// NTRAID#Longhorn-1611281-2006/04/14-bedej:
// Bitmap effects require that new realizations are produced on offset changes.
// The only other realizations that are produced on a realization walk are glyphs, and
// they do not have this requirement. Thus we optimize for the case where bitmap
// effects are not used, and if they are we fall back to doing realization walks for anything
// when an offset change occurs. This could be further optimized. See the bug description
// for further details and status.
//
if (Dispatcher != null)
{
MediaContext.From(Dispatcher).BitmapEffectsUsed = true;
}
else
{
// object is frozen
MediaContext.CurrentMediaContext.BitmapEffectsUsed = true;
}
}
#endregion
#region Protected Methods
///
/// This method is called before calling GetOutput on an effect.
/// It gives a chance for the managed effect to update the properties
/// of the unmanaged object.
///
abstract protected void UpdateUnmanagedPropertyState(SafeHandle unmanagedEffect);
///
/// Returns a safe handle to an unmanaged effect clone
///
unsafe abstract protected SafeHandle CreateUnmanagedEffect();
///
/// SetValue
///
/// SafeHandle to the unmanaged effect object
/// Name of the unmanaged property to be set
/// Object value to set unmanaged property to
///
///
/// Critical - calls native code
/// TreatAsSafe - as there is a demand
///
[SecurityCritical, SecurityTreatAsSafe]
unsafe static protected void SetValue(SafeHandle effect, string propertyName, object value)
{
SecurityHelper.DemandUIWindowPermission();
if (value is Color)
{
Color clr = (Color)value;
uint packedColor = (((uint)clr.A << 24) | ((uint)clr.B << 16) | ((uint)clr.G << 8) | (uint)clr.R);
value = (object)packedColor;
}
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.SetValue(effect, propertyName, ref value));
}
///
/// Creates an IMILBitmapEffect object
///
/// IMILBitmapEffect object
///
/// Critical - calls native code
/// TreatAsSafe - as there is a demand
///
[SecurityCritical, SecurityTreatAsSafe]
unsafe static protected SafeHandle /* IMILBitmapEffect */ CreateBitmapEffectOuter()
{
SecurityHelper.DemandUIWindowPermission();
SafeMILHandle outer = null;
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.MILFactoryEffects.CreateBitmapEffectOuter(out outer));
return outer;
}
///
/// Initializes the IMILBitmapEffect object with the IMILBitmapEffectPrimitive object
///
/// The IMILBitmapEffect object
/// The IMILBitmapEffectPrimitive object
///
/// Critical - calls native code
/// TreatAsSafe - as there is a demand
///
[SecurityCritical, SecurityTreatAsSafe]
unsafe static protected void InitializeBitmapEffect(SafeHandle /*IMILBitmapEffect */ outerObject,
SafeHandle/* IMILBitmapEffectPrimitive */ innerObject)
{
SecurityHelper.DemandUIWindowPermission();
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.MILFactoryEffects.InitializeBitmapEffect(outerObject, innerObject));
}
#endregion
#region Public Methods
///
/// This returns the output at index 0
///
public BitmapSource GetOutput(BitmapEffectInput input)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
// if we don't have the input set, we should not be calling the output property
if (input.Input == null)
{
throw new ArgumentException(SR.Get(SRID.Effect_No_InputSource), "input");
}
if (input.Input == BitmapEffectInput.ContextInputSource)
{
throw new InvalidOperationException(SR.Get(SRID.Effect_No_ContextInputSource, null));
}
BitmapSource inputSource = input.Input.Clone();
if (UpdateUnmanagedGroupState() == false ||
UpdateRenderContext(input, new Rect(0, 0, inputSource.PixelWidth, inputSource.PixelHeight)) == false)
{
return inputSource;
}
SetInputSource(UnmanagedEffectGroup, 0, inputSource);
return GetOutput(UnmanagedEffectGroup, 0, RenderContext);
}
#endregion
#region Internal Methods
///
/// This returns a handle to the unmanaged group effect
///
internal SafeMILHandle UnmanagedEffectGroup
{
get
{
if (_unmanagedEffectGroup == null)
{
_unmanagedEffectGroup = Create(new Guid("AC9C1A9A-7E18-4F64-AC7E-47CF7F051E95"));
}
return _unmanagedEffectGroup;
}
set
{
_unmanagedEffectGroup = value;
}
}
///
/// This returns a handle to an unmanaged effect
///
///
private SafeHandle UnmanagedEffect
{
get
{
if (_unmanagedEffect == null)
{
_unmanagedEffect = CreateUnmanagedEffect();
}
return _unmanagedEffect;
}
}
///
/// Returns the bounds of the visual to which the effect is applied
///
internal Rect VisualBounds
{
get { return _visualBounds; }
set { _visualBounds = value; }
}
///
/// This method is called before calling GetOutput on an effect.
/// It gives a chance for the managed effect to update the properties
/// of the unmanaged object.
///
internal void Internal_UpdateUnmanagedPropertyState(SafeHandle unmanagedEffect)
{
UpdateUnmanagedPropertyState(unmanagedEffect);
}
///
/// Returns a safe handle to an unmanaged effect clone
///
unsafe internal SafeHandle Internal_CreateUnmanagedEffect()
{
return CreateUnmanagedEffect();
}
private void SetupConnections()
{
if (!_connectionsSetup)
{
// Update the unmanaged connections
int iInputs = GetNumberInputs(UnmanagedEffect);
for (int i = 0; i < iInputs; i++)
{
BitmapEffectOutputConnector input = GetInteriorInputConnector(UnmanagedEffectGroup, i);
GetInputConnector(UnmanagedEffect, i).ConnectTo(input);
}
int iOutputs = GetNumberOutputs(UnmanagedEffect);
for (int i = 0; i < iOutputs; i++)
{
BitmapEffectInputConnector output = GetInteriorOutputConnector(UnmanagedEffectGroup, i);
output.ConnectTo(GetOutputConnector(UnmanagedEffect, i));
}
Add(UnmanagedEffectGroup, UnmanagedEffect);
_connectionsSetup = true;
}
}
///
/// Updates (propagates) all the properties to the unmanaged effect
/// Wraps the effect with an group one
///
/// This method is only called if GetOutput is called directly on the
/// effect.
///
///
internal virtual bool UpdateUnmanagedGroupState()
{
UpdateUnmanagedPropertyState(UnmanagedEffect);
SetupConnections();
return GetNumberOutputs(UnmanagedEffect) > 0;
}
///
/// Number of inputs to the effect
///
/// unmanaged effect
internal static int GetNumberInputs(SafeHandle unmanagedEffect)
{
Debug.Assert(unmanagedEffect != null, "We should have been initialized first");
uint numInputs;
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetNumberInputs(unmanagedEffect,
out numInputs));
return (int)numInputs;
}
///
/// Number of outputs from the effect
///
/// unmanaged effect
internal static int GetNumberOutputs(SafeHandle unmanagedEffect)
{
Debug.Assert(unmanagedEffect != null, "We should have been initialized first");
uint numOutputs;
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetNumberOutputs(unmanagedEffect,
out numOutputs));
return (int)numOutputs;
}
///
/// Creates the effect given a guid.
///
/// kind of effect
///
/// Critical - calls critical code method FactoryMaker.FactoryMaker
/// TreatAsSafe - as there is a demand
///
[SecurityCritical, SecurityTreatAsSafe]
internal static SafeMILHandle Create(Guid guid)
{
SecurityHelper.DemandUIWindowPermission();
SafeMILHandle bitmapEffect = null;
using (FactoryMaker myFactory = new FactoryMaker())
{
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.MILFactoryEffects.CreateBitmapEffect(
myFactory.FactoryPtr,
ref guid,
out bitmapEffect));
}
return bitmapEffect;
}
///
/// This is the render contect for the effect
///
internal BitmapEffectRenderContext RenderContext
{
get { return _renderContext; }
set { _renderContext = value; }
}
///
/// Updates the render context given the input
///
///
///
private bool UpdateRenderContext(BitmapEffectInput input, Rect inputSize)
{
_renderContext.OutputPixelFormat = PixelFormats.Pbgra32;
_renderContext.RenderRect = input.AreaToApplyEffect;
double dpiX = DefaultDevicePixelsPerInch, dpiY = DefaultDevicePixelsPerInch;
if (input.Input != BitmapEffectInput.ContextInputSource && input.Input != null)
{
dpiX = input.Input.DpiX;
dpiY = input.Input.DpiY;
}
_renderContext.OutputDPI = new Point(dpiX, dpiY);
if (!input.AreaToApplyEffect.IsEmpty)
{
Rect area = input.AreaToApplyEffect;
if (input.AreaToApplyEffectUnits == BrushMappingMode.RelativeToBoundingBox)
{
checked
{
// the inputSize here is in pixels (device space)
// the area is normalized, i.e. between (0, 0, 1, 1)
area = new Rect(inputSize.X + area.X * inputSize.Width,
inputSize.Y + area.Y * inputSize.Height,
area.Width * inputSize.Width,
area.Height * inputSize.Height);
}
}
area.Intersect(inputSize);
_renderContext.RenderRect = area;
if (area.IsEmpty)
{
return false;
}
}
return true;
}
///
/// Transform rectangle
///
/// input
///
///
///
internal Rect TransformRect(BitmapEffectInput input, Rect rect, bool fInverse)
{
if (input == null)
throw new ArgumentNullException("input");
if (rect == Rect.Empty)
return rect;
if (UpdateUnmanagedGroupState() == false ||
UpdateRenderContext(input, rect) == false)
{
return new Rect(rect.X, rect.Y, rect.Width, rect.Height);
}
return TransformRect(UnmanagedEffectGroup, 0, rect, !fInverse, RenderContext);
}
///
/// Returns true if the effect has an affine transform
/// Throws if there is anything wrong with setting up the effect state
///
private bool IsAffineTransformInternal()
{
// if update failed, assume identity
if (UpdateUnmanagedGroupState() == false)
throw new BitmapEffectException();
return HasAffineTransform(UnmanagedEffectGroup, 0);
}
///
/// Returns true if the effect has an affine transform
///
internal bool IsAffineTransform
{
get
{
try
{
return IsAffineTransformInternal();
}
catch (BitmapEffectException)
{
// return true if we failed to set up the effect
// this means no effect will be applied
// so we assume identity here
return true;
}
}
}
///
/// Return true if the effect's transform has an inverse
///
internal bool IsInverseTransform
{
get
{
// if update failed, assume identity
if (UpdateUnmanagedGroupState() == false)
return true;
return HasInverseTransform(UnmanagedEffectGroup, 0);
}
}
///
/// Returns the affine matrix if the effect has an affine transform
///
///
internal Matrix GetAffineMatrix()
{
try
{
if (IsAffineTransformInternal() == false)
throw new InvalidOperationException(SR.Get(SRID.Effect_Not_Affine, null));
}
catch (BitmapEffectException)
{
// return identity if we failed to set up the effect
// this means no effect will be applied
return Matrix.Identity;
}
return GetAffineMatrix(UnmanagedEffectGroup, 0);
}
///
/// Transforms a point
///
/// Effect input
/// input point
/// output point
/// The direction in which the point is transformed
///
internal bool TransformPoint(BitmapEffectInput input, Point inPoint, out Point outPoint, bool fInverse)
{
outPoint = inPoint;
// if this called failed, it means that we will never be able to actual
// call GetOutput either. that means the effect is a noop
if (UpdateUnmanagedGroupState() == false)
return true;
// get the bounds of the image or visual.
// if the effect is applied to a visual, we need to get the size of the
// visual and then apply the region of interest to it
// if the effect is applied to an image, we need to get the size of the image
Rect rect = VisualBounds;
if (input.Input == BitmapEffectInput.ContextInputSource || input.Input == null)
{
if (rect == Rect.Empty)
{
rect = new Rect(inPoint, inPoint);
}
}
else
{
rect = new Rect(0, 0, input.Input.Width, input.Input.Height);
}
UpdateRenderContext(input, rect);
// reset bounds
VisualBounds = Rect.Empty;
bool fPointTransformed;
outPoint = TransformPoint(UnmanagedEffectGroup, 0, inPoint, !fInverse, RenderContext, out fPointTransformed);
return fPointTransformed;
}
///
/// Add the effect to the group effect
///
/// the group effect
/// the effect to add to the graph
internal static void Add(SafeHandle effectGroup, SafeHandle effect)
{
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.Add(
effectGroup,
effect));
}
///
/// Sets the input source for a given input pin
///
/// unmanaged effect
/// index
/// image
///
/// SecurityCritical: This is code that retrieves the WicSourceHandle which is critical
/// SecurityTreatAsSafe: The inputs are safe and WicSourceHandle is not given out as well as there is a demand.
///
[SecurityCritical, SecurityTreatAsSafe]
internal static void SetInputSource(SafeHandle unmanagedEffect, int index, BitmapSource bitmap)
{
SecurityHelper.DemandUIWindowPermission();
Debug.Assert(unmanagedEffect != null, "We should have been initialized first");
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.SetInputSource(unmanagedEffect, (uint)index,
bitmap.WicSourceHandle));
}
///
/// Returns the output of the effect on the given output pin
///
/// unmanaged effect
/// index
/// context
/// Bitmap source
internal static BitmapSource GetOutput(SafeHandle unmanagedEffect, int index, BitmapEffectRenderContext context)
{
Debug.Assert(unmanagedEffect != null, "We should have been initialized first");
BitmapSourceSafeMILHandle bitmapSource;
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetOutput(unmanagedEffect, (uint)index,
context.NativeContextSafeHandle, out bitmapSource));
return new UnmanagedBitmapWrapper(bitmapSource);
}
///
/// Returns the connector object for a given input pin
///
/// unmanaged effect
/// Index of the connector
/// Input connector
internal static BitmapEffectInputConnector GetInputConnector(SafeHandle unmanagedEffect, int index)
{
SafeMILHandle connector;
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetInputConnector(unmanagedEffect,
(uint)index, out connector));
return new BitmapEffectInputConnector(connector);
}
///
/// Returns the connector object for a given output pin
///
/// unmanaged effect
/// Index of the connector
/// Input connector
internal static BitmapEffectOutputConnector GetOutputConnector(SafeHandle unmanagedEffect, int index)
{
SafeMILHandle connector;
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetOutputConnector(unmanagedEffect,
(uint)index, out connector));
return new BitmapEffectOutputConnector(connector);
}
///
/// Transforms a point by running it through the effect
///
/// unmanaged effect
///
///
///
///
///
///
internal static Point TransformPoint(SafeHandle unmanagedEffect,
int iIndex,
Point point,
bool fForwardTransform,
BitmapEffectRenderContext context,
out bool fPointTransformed)
{
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.TransformPoint(unmanagedEffect,
(uint)iIndex, ref point,
fForwardTransform,
context.NativeContextSafeHandle,
out fPointTransformed));
return point;
}
///
/// Transforms a rectangle by running it through the effect
///
/// unmanaged effect
///
///
///
///
///
internal static Rect TransformRect(SafeHandle unmanagedEffect, int iIndex, Rect rect, bool fForwardTransform, BitmapEffectRenderContext context)
{
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.TransformRect(
unmanagedEffect,
(uint)iIndex, ref rect,
fForwardTransform,
context.NativeContextSafeHandle));
return rect;
}
///
/// Returns the interior output connector
///
/// unmanaged group effect
/// connector index
/// intput connector
internal static BitmapEffectInputConnector GetInteriorOutputConnector(SafeHandle effect, int index)
{
SafeMILHandle connector;
HRESULT.Check(
MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetInteriorOutputConnector(
effect,
(uint) index,
out connector));
return new BitmapEffectInputConnector(connector);
}
///
/// Returns the interior input connector
///
/// unmanaged group effect
/// connector index
/// outtput connector
internal static BitmapEffectOutputConnector GetInteriorInputConnector(SafeHandle effect, int index)
{
SafeMILHandle connector;
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetInteriorInputConnector(effect,
(uint)index, out connector));
return new BitmapEffectOutputConnector(connector);
}
///
/// Returns true if the effect has an affine transform
///
/// unmanaged effect
/// zero basex index
///
internal static bool HasAffineTransform(SafeHandle effect, int index)
{
bool hasAffineTransform;
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.HasAffineTransform(effect,
(uint)index, out hasAffineTransform));
return hasAffineTransform;
}
///
/// Returns true if the effect's transform has an inverse
///
/// unmanaged effect
/// zero bazed index
///
internal static bool HasInverseTransform(SafeHandle effect, int index)
{
bool hasInverseTransform;
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.HasInverseTransform(effect,
(uint)index, out hasInverseTransform));
return hasInverseTransform;
}
///
/// Returns an affine matrix if the effect transformation is affine
///
/// unmanaged effect
/// zero based index
///
internal static Matrix GetAffineMatrix(SafeHandle effect, int index)
{
MilMatrix3x2D matrix = CompositionResourceManager.MatrixToMilMatrix3x2D(new Matrix());
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetAffineMatrix(effect,
(uint)index, ref matrix));
return new Matrix(matrix.S_11, matrix.S_12, matrix.S_21, matrix.S_22, matrix.DX, matrix.DY);
}
///
/// True if the effect can be emulated by the Effect pipeline. Derived classes
/// can override this method to indicate that they can be emulated using the ImageEffect
/// pipeline. If a derived class returns true it needs to also implement the GetEmulatingImageEffect
/// property to provide an emulating ImageEffect.
///
internal virtual bool CanBeEmulatedUsingEffectPipeline()
{
return false;
}
///
/// Derived classes need to return an emulating image effect if they return true from CanBeEmulatedUsingImageEffectPipeline.
///
internal virtual Effect GetEmulatingEffect()
{
throw new NotImplementedException();
}
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
//------------------------------------------------------------------------------
// Microsoft Avalon
// Copyright (c) Microsoft Corporation, 2005
//
// File: BitmapEffect.cs
//-----------------------------------------------------------------------------
using MS.Internal;
using System;
using System.IO;
using System.ComponentModel;
using System.ComponentModel.Design.Serialization;
using System.Diagnostics;
using System.Reflection;
using System.Windows.Threading;
using System.Threading;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Media;
using System.Windows.Markup;
using System.Windows.Media.Animation;
using System.Windows.Media.Composition;
using System.Windows.Media.Imaging;
using System.Security;
using MS.Internal.PresentationCore;
using System.Security.Permissions;
using SR = MS.Internal.PresentationCore.SR;
using SRID = MS.Internal.PresentationCore.SRID;
namespace System.Windows.Media.Effects
{
internal class BitmapEffectException : Exception
{
public BitmapEffectException()
{
}
}
///
/// BitmapEffect
///
///
/// We have the Inheritance demand, because we don't want
/// third parties to be able to subclass BitmapEffect in the partial trust scenario
///
[UIPermissionAttribute(SecurityAction.InheritanceDemand, Window = UIPermissionWindow.AllWindows)]
public abstract partial class BitmapEffect
{
private SafeMILHandle _unmanagedEffectGroup;
private SafeHandle _unmanagedEffect;
private BitmapEffectRenderContext _renderContext = new BitmapEffectRenderContext();
private Rect _visualBounds = Rect.Empty;
private const double DefaultDevicePixelsPerInch = 96.0;
internal bool _connectionsSetup = false;
#region Constructors
///
/// Constructor
///
protected BitmapEffect()
{
// STA Requirement
//
// Avalon doesn't necessarily require STA, but many components do. Examples
// include Cicero, OLE, COM, etc. So we throw an exception here if the
// thread is not STA.
if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
{
throw new InvalidOperationException(SR.Get(SRID.RequiresSTA));
}
//
// NTRAID#Longhorn-1611281-2006/04/14-bedej:
// Bitmap effects require that new realizations are produced on offset changes.
// The only other realizations that are produced on a realization walk are glyphs, and
// they do not have this requirement. Thus we optimize for the case where bitmap
// effects are not used, and if they are we fall back to doing realization walks for anything
// when an offset change occurs. This could be further optimized. See the bug description
// for further details and status.
//
if (Dispatcher != null)
{
MediaContext.From(Dispatcher).BitmapEffectsUsed = true;
}
else
{
// object is frozen
MediaContext.CurrentMediaContext.BitmapEffectsUsed = true;
}
}
#endregion
#region Protected Methods
///
/// This method is called before calling GetOutput on an effect.
/// It gives a chance for the managed effect to update the properties
/// of the unmanaged object.
///
abstract protected void UpdateUnmanagedPropertyState(SafeHandle unmanagedEffect);
///
/// Returns a safe handle to an unmanaged effect clone
///
unsafe abstract protected SafeHandle CreateUnmanagedEffect();
///
/// SetValue
///
/// SafeHandle to the unmanaged effect object
/// Name of the unmanaged property to be set
/// Object value to set unmanaged property to
///
///
/// Critical - calls native code
/// TreatAsSafe - as there is a demand
///
[SecurityCritical, SecurityTreatAsSafe]
unsafe static protected void SetValue(SafeHandle effect, string propertyName, object value)
{
SecurityHelper.DemandUIWindowPermission();
if (value is Color)
{
Color clr = (Color)value;
uint packedColor = (((uint)clr.A << 24) | ((uint)clr.B << 16) | ((uint)clr.G << 8) | (uint)clr.R);
value = (object)packedColor;
}
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.SetValue(effect, propertyName, ref value));
}
///
/// Creates an IMILBitmapEffect object
///
/// IMILBitmapEffect object
///
/// Critical - calls native code
/// TreatAsSafe - as there is a demand
///
[SecurityCritical, SecurityTreatAsSafe]
unsafe static protected SafeHandle /* IMILBitmapEffect */ CreateBitmapEffectOuter()
{
SecurityHelper.DemandUIWindowPermission();
SafeMILHandle outer = null;
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.MILFactoryEffects.CreateBitmapEffectOuter(out outer));
return outer;
}
///
/// Initializes the IMILBitmapEffect object with the IMILBitmapEffectPrimitive object
///
/// The IMILBitmapEffect object
/// The IMILBitmapEffectPrimitive object
///
/// Critical - calls native code
/// TreatAsSafe - as there is a demand
///
[SecurityCritical, SecurityTreatAsSafe]
unsafe static protected void InitializeBitmapEffect(SafeHandle /*IMILBitmapEffect */ outerObject,
SafeHandle/* IMILBitmapEffectPrimitive */ innerObject)
{
SecurityHelper.DemandUIWindowPermission();
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.MILFactoryEffects.InitializeBitmapEffect(outerObject, innerObject));
}
#endregion
#region Public Methods
///
/// This returns the output at index 0
///
public BitmapSource GetOutput(BitmapEffectInput input)
{
if (input == null)
{
throw new ArgumentNullException("input");
}
// if we don't have the input set, we should not be calling the output property
if (input.Input == null)
{
throw new ArgumentException(SR.Get(SRID.Effect_No_InputSource), "input");
}
if (input.Input == BitmapEffectInput.ContextInputSource)
{
throw new InvalidOperationException(SR.Get(SRID.Effect_No_ContextInputSource, null));
}
BitmapSource inputSource = input.Input.Clone();
if (UpdateUnmanagedGroupState() == false ||
UpdateRenderContext(input, new Rect(0, 0, inputSource.PixelWidth, inputSource.PixelHeight)) == false)
{
return inputSource;
}
SetInputSource(UnmanagedEffectGroup, 0, inputSource);
return GetOutput(UnmanagedEffectGroup, 0, RenderContext);
}
#endregion
#region Internal Methods
///
/// This returns a handle to the unmanaged group effect
///
internal SafeMILHandle UnmanagedEffectGroup
{
get
{
if (_unmanagedEffectGroup == null)
{
_unmanagedEffectGroup = Create(new Guid("AC9C1A9A-7E18-4F64-AC7E-47CF7F051E95"));
}
return _unmanagedEffectGroup;
}
set
{
_unmanagedEffectGroup = value;
}
}
///
/// This returns a handle to an unmanaged effect
///
///
private SafeHandle UnmanagedEffect
{
get
{
if (_unmanagedEffect == null)
{
_unmanagedEffect = CreateUnmanagedEffect();
}
return _unmanagedEffect;
}
}
///
/// Returns the bounds of the visual to which the effect is applied
///
internal Rect VisualBounds
{
get { return _visualBounds; }
set { _visualBounds = value; }
}
///
/// This method is called before calling GetOutput on an effect.
/// It gives a chance for the managed effect to update the properties
/// of the unmanaged object.
///
internal void Internal_UpdateUnmanagedPropertyState(SafeHandle unmanagedEffect)
{
UpdateUnmanagedPropertyState(unmanagedEffect);
}
///
/// Returns a safe handle to an unmanaged effect clone
///
unsafe internal SafeHandle Internal_CreateUnmanagedEffect()
{
return CreateUnmanagedEffect();
}
private void SetupConnections()
{
if (!_connectionsSetup)
{
// Update the unmanaged connections
int iInputs = GetNumberInputs(UnmanagedEffect);
for (int i = 0; i < iInputs; i++)
{
BitmapEffectOutputConnector input = GetInteriorInputConnector(UnmanagedEffectGroup, i);
GetInputConnector(UnmanagedEffect, i).ConnectTo(input);
}
int iOutputs = GetNumberOutputs(UnmanagedEffect);
for (int i = 0; i < iOutputs; i++)
{
BitmapEffectInputConnector output = GetInteriorOutputConnector(UnmanagedEffectGroup, i);
output.ConnectTo(GetOutputConnector(UnmanagedEffect, i));
}
Add(UnmanagedEffectGroup, UnmanagedEffect);
_connectionsSetup = true;
}
}
///
/// Updates (propagates) all the properties to the unmanaged effect
/// Wraps the effect with an group one
///
/// This method is only called if GetOutput is called directly on the
/// effect.
///
///
internal virtual bool UpdateUnmanagedGroupState()
{
UpdateUnmanagedPropertyState(UnmanagedEffect);
SetupConnections();
return GetNumberOutputs(UnmanagedEffect) > 0;
}
///
/// Number of inputs to the effect
///
/// unmanaged effect
internal static int GetNumberInputs(SafeHandle unmanagedEffect)
{
Debug.Assert(unmanagedEffect != null, "We should have been initialized first");
uint numInputs;
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetNumberInputs(unmanagedEffect,
out numInputs));
return (int)numInputs;
}
///
/// Number of outputs from the effect
///
/// unmanaged effect
internal static int GetNumberOutputs(SafeHandle unmanagedEffect)
{
Debug.Assert(unmanagedEffect != null, "We should have been initialized first");
uint numOutputs;
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetNumberOutputs(unmanagedEffect,
out numOutputs));
return (int)numOutputs;
}
///
/// Creates the effect given a guid.
///
/// kind of effect
///
/// Critical - calls critical code method FactoryMaker.FactoryMaker
/// TreatAsSafe - as there is a demand
///
[SecurityCritical, SecurityTreatAsSafe]
internal static SafeMILHandle Create(Guid guid)
{
SecurityHelper.DemandUIWindowPermission();
SafeMILHandle bitmapEffect = null;
using (FactoryMaker myFactory = new FactoryMaker())
{
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.MILFactoryEffects.CreateBitmapEffect(
myFactory.FactoryPtr,
ref guid,
out bitmapEffect));
}
return bitmapEffect;
}
///
/// This is the render contect for the effect
///
internal BitmapEffectRenderContext RenderContext
{
get { return _renderContext; }
set { _renderContext = value; }
}
///
/// Updates the render context given the input
///
///
///
private bool UpdateRenderContext(BitmapEffectInput input, Rect inputSize)
{
_renderContext.OutputPixelFormat = PixelFormats.Pbgra32;
_renderContext.RenderRect = input.AreaToApplyEffect;
double dpiX = DefaultDevicePixelsPerInch, dpiY = DefaultDevicePixelsPerInch;
if (input.Input != BitmapEffectInput.ContextInputSource && input.Input != null)
{
dpiX = input.Input.DpiX;
dpiY = input.Input.DpiY;
}
_renderContext.OutputDPI = new Point(dpiX, dpiY);
if (!input.AreaToApplyEffect.IsEmpty)
{
Rect area = input.AreaToApplyEffect;
if (input.AreaToApplyEffectUnits == BrushMappingMode.RelativeToBoundingBox)
{
checked
{
// the inputSize here is in pixels (device space)
// the area is normalized, i.e. between (0, 0, 1, 1)
area = new Rect(inputSize.X + area.X * inputSize.Width,
inputSize.Y + area.Y * inputSize.Height,
area.Width * inputSize.Width,
area.Height * inputSize.Height);
}
}
area.Intersect(inputSize);
_renderContext.RenderRect = area;
if (area.IsEmpty)
{
return false;
}
}
return true;
}
///
/// Transform rectangle
///
/// input
///
///
///
internal Rect TransformRect(BitmapEffectInput input, Rect rect, bool fInverse)
{
if (input == null)
throw new ArgumentNullException("input");
if (rect == Rect.Empty)
return rect;
if (UpdateUnmanagedGroupState() == false ||
UpdateRenderContext(input, rect) == false)
{
return new Rect(rect.X, rect.Y, rect.Width, rect.Height);
}
return TransformRect(UnmanagedEffectGroup, 0, rect, !fInverse, RenderContext);
}
///
/// Returns true if the effect has an affine transform
/// Throws if there is anything wrong with setting up the effect state
///
private bool IsAffineTransformInternal()
{
// if update failed, assume identity
if (UpdateUnmanagedGroupState() == false)
throw new BitmapEffectException();
return HasAffineTransform(UnmanagedEffectGroup, 0);
}
///
/// Returns true if the effect has an affine transform
///
internal bool IsAffineTransform
{
get
{
try
{
return IsAffineTransformInternal();
}
catch (BitmapEffectException)
{
// return true if we failed to set up the effect
// this means no effect will be applied
// so we assume identity here
return true;
}
}
}
///
/// Return true if the effect's transform has an inverse
///
internal bool IsInverseTransform
{
get
{
// if update failed, assume identity
if (UpdateUnmanagedGroupState() == false)
return true;
return HasInverseTransform(UnmanagedEffectGroup, 0);
}
}
///
/// Returns the affine matrix if the effect has an affine transform
///
///
internal Matrix GetAffineMatrix()
{
try
{
if (IsAffineTransformInternal() == false)
throw new InvalidOperationException(SR.Get(SRID.Effect_Not_Affine, null));
}
catch (BitmapEffectException)
{
// return identity if we failed to set up the effect
// this means no effect will be applied
return Matrix.Identity;
}
return GetAffineMatrix(UnmanagedEffectGroup, 0);
}
///
/// Transforms a point
///
/// Effect input
/// input point
/// output point
/// The direction in which the point is transformed
///
internal bool TransformPoint(BitmapEffectInput input, Point inPoint, out Point outPoint, bool fInverse)
{
outPoint = inPoint;
// if this called failed, it means that we will never be able to actual
// call GetOutput either. that means the effect is a noop
if (UpdateUnmanagedGroupState() == false)
return true;
// get the bounds of the image or visual.
// if the effect is applied to a visual, we need to get the size of the
// visual and then apply the region of interest to it
// if the effect is applied to an image, we need to get the size of the image
Rect rect = VisualBounds;
if (input.Input == BitmapEffectInput.ContextInputSource || input.Input == null)
{
if (rect == Rect.Empty)
{
rect = new Rect(inPoint, inPoint);
}
}
else
{
rect = new Rect(0, 0, input.Input.Width, input.Input.Height);
}
UpdateRenderContext(input, rect);
// reset bounds
VisualBounds = Rect.Empty;
bool fPointTransformed;
outPoint = TransformPoint(UnmanagedEffectGroup, 0, inPoint, !fInverse, RenderContext, out fPointTransformed);
return fPointTransformed;
}
///
/// Add the effect to the group effect
///
/// the group effect
/// the effect to add to the graph
internal static void Add(SafeHandle effectGroup, SafeHandle effect)
{
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.Add(
effectGroup,
effect));
}
///
/// Sets the input source for a given input pin
///
/// unmanaged effect
/// index
/// image
///
/// SecurityCritical: This is code that retrieves the WicSourceHandle which is critical
/// SecurityTreatAsSafe: The inputs are safe and WicSourceHandle is not given out as well as there is a demand.
///
[SecurityCritical, SecurityTreatAsSafe]
internal static void SetInputSource(SafeHandle unmanagedEffect, int index, BitmapSource bitmap)
{
SecurityHelper.DemandUIWindowPermission();
Debug.Assert(unmanagedEffect != null, "We should have been initialized first");
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.SetInputSource(unmanagedEffect, (uint)index,
bitmap.WicSourceHandle));
}
///
/// Returns the output of the effect on the given output pin
///
/// unmanaged effect
/// index
/// context
/// Bitmap source
internal static BitmapSource GetOutput(SafeHandle unmanagedEffect, int index, BitmapEffectRenderContext context)
{
Debug.Assert(unmanagedEffect != null, "We should have been initialized first");
BitmapSourceSafeMILHandle bitmapSource;
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetOutput(unmanagedEffect, (uint)index,
context.NativeContextSafeHandle, out bitmapSource));
return new UnmanagedBitmapWrapper(bitmapSource);
}
///
/// Returns the connector object for a given input pin
///
/// unmanaged effect
/// Index of the connector
/// Input connector
internal static BitmapEffectInputConnector GetInputConnector(SafeHandle unmanagedEffect, int index)
{
SafeMILHandle connector;
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetInputConnector(unmanagedEffect,
(uint)index, out connector));
return new BitmapEffectInputConnector(connector);
}
///
/// Returns the connector object for a given output pin
///
/// unmanaged effect
/// Index of the connector
/// Input connector
internal static BitmapEffectOutputConnector GetOutputConnector(SafeHandle unmanagedEffect, int index)
{
SafeMILHandle connector;
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetOutputConnector(unmanagedEffect,
(uint)index, out connector));
return new BitmapEffectOutputConnector(connector);
}
///
/// Transforms a point by running it through the effect
///
/// unmanaged effect
///
///
///
///
///
///
internal static Point TransformPoint(SafeHandle unmanagedEffect,
int iIndex,
Point point,
bool fForwardTransform,
BitmapEffectRenderContext context,
out bool fPointTransformed)
{
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.TransformPoint(unmanagedEffect,
(uint)iIndex, ref point,
fForwardTransform,
context.NativeContextSafeHandle,
out fPointTransformed));
return point;
}
///
/// Transforms a rectangle by running it through the effect
///
/// unmanaged effect
///
///
///
///
///
internal static Rect TransformRect(SafeHandle unmanagedEffect, int iIndex, Rect rect, bool fForwardTransform, BitmapEffectRenderContext context)
{
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.TransformRect(
unmanagedEffect,
(uint)iIndex, ref rect,
fForwardTransform,
context.NativeContextSafeHandle));
return rect;
}
///
/// Returns the interior output connector
///
/// unmanaged group effect
/// connector index
/// intput connector
internal static BitmapEffectInputConnector GetInteriorOutputConnector(SafeHandle effect, int index)
{
SafeMILHandle connector;
HRESULT.Check(
MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetInteriorOutputConnector(
effect,
(uint) index,
out connector));
return new BitmapEffectInputConnector(connector);
}
///
/// Returns the interior input connector
///
/// unmanaged group effect
/// connector index
/// outtput connector
internal static BitmapEffectOutputConnector GetInteriorInputConnector(SafeHandle effect, int index)
{
SafeMILHandle connector;
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetInteriorInputConnector(effect,
(uint)index, out connector));
return new BitmapEffectOutputConnector(connector);
}
///
/// Returns true if the effect has an affine transform
///
/// unmanaged effect
/// zero basex index
///
internal static bool HasAffineTransform(SafeHandle effect, int index)
{
bool hasAffineTransform;
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.HasAffineTransform(effect,
(uint)index, out hasAffineTransform));
return hasAffineTransform;
}
///
/// Returns true if the effect's transform has an inverse
///
/// unmanaged effect
/// zero bazed index
///
internal static bool HasInverseTransform(SafeHandle effect, int index)
{
bool hasInverseTransform;
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.HasInverseTransform(effect,
(uint)index, out hasInverseTransform));
return hasInverseTransform;
}
///
/// Returns an affine matrix if the effect transformation is affine
///
/// unmanaged effect
/// zero based index
///
internal static Matrix GetAffineMatrix(SafeHandle effect, int index)
{
MilMatrix3x2D matrix = CompositionResourceManager.MatrixToMilMatrix3x2D(new Matrix());
HRESULT.Check(MS.Win32.PresentationCore.UnsafeNativeMethods.IMILBitmapEffect.GetAffineMatrix(effect,
(uint)index, ref matrix));
return new Matrix(matrix.S_11, matrix.S_12, matrix.S_21, matrix.S_22, matrix.DX, matrix.DY);
}
///
/// True if the effect can be emulated by the Effect pipeline. Derived classes
/// can override this method to indicate that they can be emulated using the ImageEffect
/// pipeline. If a derived class returns true it needs to also implement the GetEmulatingImageEffect
/// property to provide an emulating ImageEffect.
///
internal virtual bool CanBeEmulatedUsingEffectPipeline()
{
return false;
}
///
/// Derived classes need to return an emulating image effect if they return true from CanBeEmulatedUsingImageEffectPipeline.
///
internal virtual Effect GetEmulatingEffect()
{
throw new NotImplementedException();
}
#endregion
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- FormViewModeEventArgs.cs
- HttpRequest.cs
- ParsedAttributeCollection.cs
- ExpressionList.cs
- CharStorage.cs
- MachineKey.cs
- HtmlForm.cs
- X509CertificateStore.cs
- ControlPaint.cs
- RandomNumberGenerator.cs
- FormsIdentity.cs
- MachineKeyConverter.cs
- FontWeightConverter.cs
- IdleTimeoutMonitor.cs
- TypeSource.cs
- OnOperation.cs
- WindowsListViewSubItem.cs
- PackageRelationshipCollection.cs
- IItemProperties.cs
- SupportsEventValidationAttribute.cs
- XamlTemplateSerializer.cs
- ConfigsHelper.cs
- CategoryGridEntry.cs
- Effect.cs
- IntAverageAggregationOperator.cs
- ListViewUpdatedEventArgs.cs
- RemotingConfiguration.cs
- BitmapEffectvisualstate.cs
- ProtocolViolationException.cs
- RegexFCD.cs
- IfAction.cs
- Int16.cs
- GeneralTransform.cs
- SQLInt64.cs
- LoginUtil.cs
- PathFigure.cs
- UnmanagedBitmapWrapper.cs
- SqlNotificationRequest.cs
- DataGridViewCellEventArgs.cs
- StyleHelper.cs
- HiddenField.cs
- sitestring.cs
- RecordManager.cs
- ArrayList.cs
- TreeViewImageKeyConverter.cs
- FormsAuthenticationUserCollection.cs
- BCLDebug.cs
- RegexCompiler.cs
- _Semaphore.cs
- WebPartAuthorizationEventArgs.cs
- ObjectKeyFrameCollection.cs
- TableRowCollection.cs
- MailAddress.cs
- _IPv4Address.cs
- HtmlTextArea.cs
- NumberFunctions.cs
- XmlSchemaSimpleContent.cs
- SQLBinary.cs
- TabControl.cs
- Nullable.cs
- Identity.cs
- Visual3D.cs
- FunctionCommandText.cs
- FileRecordSequenceCompletedAsyncResult.cs
- TraceInternal.cs
- MatrixCamera.cs
- PartitionedDataSource.cs
- TargetConverter.cs
- CompareValidator.cs
- WebPartAuthorizationEventArgs.cs
- NullRuntimeConfig.cs
- RTLAwareMessageBox.cs
- NullToBooleanConverter.cs
- SqlMethodAttribute.cs
- EditorZoneBase.cs
- XmlAnyElementAttributes.cs
- Keyboard.cs
- EndpointIdentityConverter.cs
- TextCompositionManager.cs
- EdmProperty.cs
- RuntimeConfigurationRecord.cs
- MediaEntryAttribute.cs
- MailMessage.cs
- LambdaCompiler.Unary.cs
- UnknownWrapper.cs
- Pkcs7Recipient.cs
- ComponentCollection.cs
- NetworkInformationException.cs
- MeasurementDCInfo.cs
- ClientTargetSection.cs
- NonClientArea.cs
- PrintingPermission.cs
- SQLGuid.cs
- ComponentResourceKeyConverter.cs
- GatewayDefinition.cs
- BoundField.cs
- DecoderReplacementFallback.cs
- StandardCommands.cs
- XmlSubtreeReader.cs
- DefaultPropertyAttribute.cs