/src/Effects/Effect.cs
C# | 281 lines | 199 code | 37 blank | 45 comment | 6 complexity | 2d661ad66af9c2a0f88abce4b372d820 MD5 | raw file
- /////////////////////////////////////////////////////////////////////////////////
- // Paint.NET //
- // Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors. //
- // Portions Copyright (C) Microsoft Corporation. All Rights Reserved. //
- // See src/Resources/Files/License.txt for full licensing and attribution //
- // details. //
- // . //
- /////////////////////////////////////////////////////////////////////////////////
-
- using System;
- using System.Drawing;
- using System.Linq;
- using System.Windows.Forms;
-
- namespace PaintDotNet.Effects
- {
- public abstract class Effect
- {
- private const string ShortcutKeysObsoleteString =
- "Effects may not specify their own ShortcutKeys. Use one of the constructor overloads that does not take a ShortcutKeys parameter.";
-
- private readonly string _name;
- private readonly Image _image;
- private readonly string _subMenuName;
- private readonly EffectFlags _effectFlags;
-
- protected internal bool SetRenderInfoCalled { get; private set; }
-
- /// <summary>
- /// Returns the category of the effect. If there is no EffectCategoryAttribute
- /// applied to the runtime type, then the default category, EffectCategory.Effect,
- /// will be returned.
- /// </summary>
- /// <remarks>
- /// This controls which menu in the user interface the effect is placed in to.
- /// </remarks>
- public EffectCategory Category
- {
- get
- {
- object[] attributes = GetType().GetCustomAttributes(true);
-
- return attributes.OfType<EffectCategoryAttribute>().Select(attribute => (attribute).Category).FirstOrDefault();
- }
- }
-
- public EffectEnvironmentParameters EnvironmentParameters { get; set; }
-
- [Obsolete]
- public EffectDirectives EffectDirectives
- {
- get {
- return (_effectFlags & EffectFlags.SingleThreaded) == EffectFlags.SingleThreaded ? EffectDirectives.SingleThreaded : EffectDirectives.None;
- }
- }
-
- public EffectFlags EffectFlags
- {
- get
- {
- return _effectFlags;
- }
- }
-
- public bool CheckForEffectFlags(EffectFlags flags)
- {
- return (EffectFlags & flags) == flags;
- }
-
- public string SubMenuName
- {
- get
- {
- return _subMenuName;
- }
- }
-
- public string Name
- {
- get
- {
- return _name;
- }
- }
-
- public Image Image
- {
- get
- {
- return _image;
- }
- }
-
- [Obsolete("This property is obsolete. There is no replacement.")]
- public Keys ShortcutKeys
- {
- get
- {
- return Keys.None;
- }
- }
-
- [Obsolete("Use CheckForEffectFlags() instead")]
- public bool IsConfigurable
- {
- get
- {
- return (EffectFlags & EffectFlags.Configurable) == EffectFlags.Configurable;
- }
- }
-
- public void SetRenderInfo(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs)
- {
- SetRenderInfoCalled = true;
- OnSetRenderInfo(parameters, dstArgs, srcArgs);
- }
-
- protected virtual void OnSetRenderInfo(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs)
- {
- }
-
- /// <summary>
- /// Performs the effect's rendering. The source is to be treated as read-only,
- /// and only the destination pixels within the given rectangle-of-interest are
- /// to be written to. However, in order to compute the destination pixels,
- /// any pixels from the source may be utilized.
- /// </summary>
- /// <param name="parameters">The parameters to the effect. If IsConfigurable is true, then this must not be null.</param>
- /// <param name="dstArgs">Describes the destination surface.</param>
- /// <param name="srcArgs">Describes the source surface.</param>
- /// <param name="rois">The list of rectangles that describes the region of interest.</param>
- /// <param name="startIndex">The index within roi to start enumerating from.</param>
- /// <param name="length">The number of rectangles to enumerate from roi.</param>
- public abstract void Render(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois, int startIndex, int length);
-
- public void Render(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs, Rectangle[] rois)
- {
- Render(parameters, dstArgs, srcArgs, rois, 0, rois.Length);
- }
-
- public void Render(EffectConfigToken parameters, RenderArgs dstArgs, RenderArgs srcArgs, PdnRegion roi)
- {
- Rectangle[] scans = roi.GetRegionScansReadOnlyInt();
- Render(parameters, dstArgs, srcArgs, scans, 0, scans.Length);
- }
-
- public virtual EffectConfigDialog CreateConfigDialog()
- {
- if (CheckForEffectFlags(EffectFlags.Configurable))
- {
- throw new NotImplementedException("If IsConfigurable is true, then CreateConfigDialog() must be implemented");
- }
- return null;
- }
-
- /// <summary>
- /// This is a helper function. It allows you to render an effect "in place."
- /// That is, you don't need both a destination and a source Surface.
- /// </summary>
- public void RenderInPlace(RenderArgs srcAndDstArgs, PdnRegion roi)
- {
- using (var renderSurface = new Surface(srcAndDstArgs.Surface.Size))
- {
- using (var renderArgs = new RenderArgs(renderSurface))
- {
- Rectangle[] scans = roi.GetRegionScansReadOnlyInt();
- Render(null, renderArgs, srcAndDstArgs, scans);
- srcAndDstArgs.Surface.CopySurface(renderSurface, roi);
- }
- }
- }
-
- public void RenderInPlace(RenderArgs srcAndDstArgs, Rectangle roi)
- {
- using (var region = new PdnRegion(roi))
- {
- RenderInPlace(srcAndDstArgs, region);
- }
- }
-
- protected Effect(string name, Image image)
- : this(name, image, EffectFlags.None)
- {
- }
-
- protected Effect(string name, Image image, EffectFlags flags)
- : this(name, image, null, flags)
- {
- }
-
- [Obsolete]
- protected Effect(string name, Image image, bool isConfigurable)
- : this(name, image, null, isConfigurable ? EffectFlags.Configurable : EffectFlags.None)
- {
- }
-
- [Obsolete(ShortcutKeysObsoleteString, true)]
- protected Effect(string name, Image image, Keys shortcutKeys)
- : this(name, image, null)
- {
- }
-
- [Obsolete(ShortcutKeysObsoleteString, true)]
- protected Effect(string name, Image image, Keys shortcutKeys, bool isConfigurable)
- : this(name, image, null, isConfigurable)
- {
- }
-
- [Obsolete(ShortcutKeysObsoleteString, true)]
- protected Effect(string name, Image image, Keys shortcutKeys, string subMenuName)
- : this(name, image, subMenuName, EffectDirectives.None)
- {
- }
-
- protected Effect(string name, Image image, string subMenuName)
- : this(name, image, subMenuName, EffectFlags.None)
- {
- }
-
- [Obsolete(ShortcutKeysObsoleteString, true)]
- protected Effect(string name, Image image, Keys shortcutKeys, string subMenuName, bool isConfigurable)
- : this(name, image, subMenuName, EffectDirectives.None, isConfigurable)
- {
- }
-
- [Obsolete]
- protected Effect(string name, Image image, string subMenuName, EffectDirectives effectDirectives)
- : this(name, image, subMenuName, effectDirectives == EffectDirectives.SingleThreaded ? EffectFlags.SingleThreaded : EffectFlags.None)
- {
- }
-
- [Obsolete]
- protected Effect(string name, Image image, string subMenuName, bool isConfigurable)
- : this(name, image, subMenuName, isConfigurable ? EffectFlags.Configurable : EffectFlags.None)
- {
- }
-
- [Obsolete(ShortcutKeysObsoleteString, true)]
- protected Effect(string name, Image image, Keys shortcutKeys, string subMenuName, EffectDirectives effectDirectives)
- : this(name, image, subMenuName, effectDirectives, false)
- {
- }
-
- [Obsolete(ShortcutKeysObsoleteString, true)]
- protected Effect(string name, Image image, Keys shortcutKeys, string subMenuName, EffectDirectives effectDirectives, bool isConfigurable)
- : this(name, image, subMenuName, effectDirectives, isConfigurable)
- {
- }
-
- /// <summary>
- /// Base constructor for the Effect class.
- /// </summary>
- /// <param name="name">A unique name for the effect.</param>
- /// <param name="image">A 16x16 icon for the effect that will show up in the menu.</param>
- /// <param name="subMenuName">The name of a sub-menu to place the effect into. Pass null for no sub-menu.</param>
- /// <param name="effectDirectives">A set of flags indicating important information about the effect.</param>
- /// <param name="isConfigurable">A flag indicating whether the effect is configurable. If this is true, then CreateConfigDialog must be implemented.</param>
- /// <remarks>
- /// Do not include the word 'effect' in the name parameter.
- /// The shortcut key is only honored for effects with the [EffectCategory(EffectCategory.Adjustment)] attribute.
- /// The sub-menu parameter can be used to group effects. The name parameter must still be unique.
- /// </remarks>
- [Obsolete]
- protected Effect(string name, Image image, string subMenuName, EffectDirectives effectDirectives, bool isConfigurable)
- : this(name, image, subMenuName,
- (effectDirectives == EffectDirectives.SingleThreaded ? EffectFlags.SingleThreaded : EffectFlags.None) |
- (isConfigurable ? EffectFlags.Configurable : EffectFlags.None))
- {
- }
-
- protected Effect(string name, Image image, string subMenuName, EffectFlags effectFlags)
- {
- SetRenderInfoCalled = false;
- _name = name;
- _image = image;
- _subMenuName = subMenuName;
- _effectFlags = effectFlags;
- EnvironmentParameters = EffectEnvironmentParameters.DefaultParameters;
- }
- }
- }