Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / Orcas / SP / wpf / src / Core / CSharp / System / Windows / Media / Effects / BitmapEffect.cs / 2 / 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
- ImportCatalogPart.cs
- Ipv6Element.cs
- MenuBase.cs
- WpfWebRequestHelper.cs
- ExecutedRoutedEventArgs.cs
- DbConnectionOptions.cs
- ReadOnlyHierarchicalDataSourceView.cs
- BatchWriter.cs
- UpnEndpointIdentity.cs
- Rect3DConverter.cs
- CompositeFontFamily.cs
- Compiler.cs
- XmlLanguage.cs
- ProcessHostConfigUtils.cs
- ObjectListComponentEditor.cs
- LineSegment.cs
- DataList.cs
- SerialPort.cs
- DelegatingChannelListener.cs
- TcpTransportElement.cs
- UrlUtility.cs
- Currency.cs
- TemplateControlBuildProvider.cs
- GeometryGroup.cs
- DataGridBoundColumn.cs
- DateTimeOffset.cs
- ModelItemCollection.cs
- TTSEngineTypes.cs
- SqlDataSourceStatusEventArgs.cs
- DiagnosticTraceSource.cs
- WebPartMenuStyle.cs
- XmlBoundElement.cs
- XmlMemberMapping.cs
- ToolStripItemTextRenderEventArgs.cs
- InertiaRotationBehavior.cs
- XamlFigureLengthSerializer.cs
- StyleConverter.cs
- TrackingMemoryStream.cs
- CounterSampleCalculator.cs
- UInt64Converter.cs
- Stream.cs
- EventLog.cs
- ByteArrayHelperWithString.cs
- WebServiceHost.cs
- SymbolType.cs
- SHA1.cs
- ApplicationDirectory.cs
- NamespaceEmitter.cs
- CodeAttachEventStatement.cs
- DataKeyArray.cs
- RepeatBehavior.cs
- IRCollection.cs
- QueryExtender.cs
- MouseEvent.cs
- WindowsPrincipal.cs
- TreeNodeCollection.cs
- XmlText.cs
- Set.cs
- SqlConnectionPoolProviderInfo.cs
- ExtentJoinTreeNode.cs
- RangeValuePattern.cs
- PipelineComponent.cs
- DocumentXmlWriter.cs
- ProviderUtil.cs
- EditorZone.cs
- SrgsSemanticInterpretationTag.cs
- TypeAccessException.cs
- ThreadAttributes.cs
- CustomWebEventKey.cs
- OutKeywords.cs
- MiniAssembly.cs
- Style.cs
- NativeMethods.cs
- EarlyBoundInfo.cs
- FormsIdentity.cs
- FontWeights.cs
- ContextMarshalException.cs
- followingsibling.cs
- NavigationCommands.cs
- DummyDataSource.cs
- FormsAuthenticationModule.cs
- FilteredAttributeCollection.cs
- SchemaImporterExtension.cs
- SafeMILHandle.cs
- ChildrenQuery.cs
- ComponentEvent.cs
- Debugger.cs
- RequestSecurityTokenForRemoteTokenFactory.cs
- BlurBitmapEffect.cs
- FilterQuery.cs
- KnownColorTable.cs
- SEHException.cs
- TextAnchor.cs
- IdnElement.cs
- CompilerGeneratedAttribute.cs
- GridViewPageEventArgs.cs
- ArraySegment.cs
- RawContentTypeMapper.cs
- GroupDescription.cs
- AsyncParams.cs