1 // 2 // BaseEffect.cs 3 // 4 // Author: 5 // Jonathan Pobst <monkey@jpobst.com> 6 // 7 // Copyright (c) 2010 Jonathan Pobst 8 // 9 // Permission is hereby granted, free of charge, to any person obtaining a copy 10 // of this software and associated documentation files (the "Software"), to deal 11 // in the Software without restriction, including without limitation the rights 12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 // copies of the Software, and to permit persons to whom the Software is 14 // furnished to do so, subject to the following conditions: 15 // 16 // The above copyright notice and this permission notice shall be included in 17 // all copies or substantial portions of the Software. 18 // 19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 // THE SOFTWARE. 26 27 using System; 28 using Cairo; 29 using Mono.Unix; 30 using Mono.Addins; 31 using Pinta.Core; 32 33 [assembly: AddinRoot ("Pinta", PintaCore.ApplicationVersion)] 34 35 namespace Pinta.Core 36 { 37 /// <summary> 38 /// The base class for all effects and adjustments. 39 /// </summary> 40 [TypeExtensionPoint] 41 public abstract class BaseEffect 42 { 43 /// <summary> 44 /// Returns the name of the effect, displayed to the user in the Adjustments/Effects menu and history pad. 45 /// </summary> 46 public abstract string Name { get; } 47 48 /// <summary> 49 /// Returns the icon to use for the effect in the Adjustments/Effects menu and history pad. 50 /// </summary> 51 public virtual string Icon { get { return "Menu.Effects.Default.png"; } } 52 53 /// <summary> 54 /// Returns whether this effect can display a configuration dialog to the user. (Implemented by LaunchConfiguration ().) 55 /// </summary> 56 public virtual bool IsConfigurable { get { return false; } } 57 58 /// <summary> 59 /// Returns the keyboard shortcut for this adjustment. Only affects adjustments, not effects. Default is no shortcut. 60 /// </summary> 61 public virtual Gdk.Key AdjustmentMenuKey { get { return (Gdk.Key)0; } } 62 63 /// <summary> 64 /// Returns the modifier(s) to the keyboard shortcut. Only affects adjustments, not effects. Default is Ctrl+Shift. 65 /// </summary> 66 public virtual Gdk.ModifierType AdjustmentMenuKeyModifiers { get { return Gdk.ModifierType.ControlMask | Gdk.ModifierType.ShiftMask; } } 67 68 /// <summary> 69 /// Returns the menu category for an effect. Only affects effects, not adjustments. Default is "General". 70 /// </summary> 71 public virtual string EffectMenuCategory { get { return "General"; } } 72 73 /// <summary> 74 /// The user configurable data this effect uses. 75 /// </summary> 76 public EffectData EffectData { get; protected set; } 77 78 /// <summary> 79 /// Launches the configuration dialog for this effect/adjustment. 80 /// </summary> 81 /// <returns>Whether the user accepted or cancelled the configuration dialog. (true: accept, false: cancel)</returns> LaunchConfiguration()82 public virtual bool LaunchConfiguration () 83 { 84 if (IsConfigurable) 85 throw new NotImplementedException (string.Format ("{0} is marked as configurable, but has not implemented LaunchConfiguration", this.GetType ())); 86 87 return false; 88 } 89 90 #region Overrideable Render Methods 91 /// <summary> 92 /// Performs the actual work of rendering an effect. Do not call base.Render (). 93 /// </summary> 94 /// <param name="src">The source surface. DO NOT MODIFY.</param> 95 /// <param name="dst">The destination surface.</param> 96 /// <param name="rois">An array of rectangles of interest (roi) specifying the area(s) to modify. Only these areas should be modified.</param> Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois)97 public virtual void Render (ImageSurface src, ImageSurface dst, Gdk.Rectangle[] rois) 98 { 99 foreach (var rect in rois) 100 Render (src, dst, rect); 101 } 102 103 /// <summary> 104 /// Performs the actual work of rendering an effect. Do not call base.Render (). 105 /// </summary> 106 /// <param name="src">The source surface. DO NOT MODIFY.</param> 107 /// <param name="dst">The destination surface.</param> 108 /// <param name="roi">A rectangle of interest (roi) specifying the area to modify. Only these areas should be modified</param> Render(ImageSurface src, ImageSurface dst, Gdk.Rectangle roi)109 protected unsafe virtual void Render (ImageSurface src, ImageSurface dst, Gdk.Rectangle roi) 110 { 111 ColorBgra* src_data_ptr = (ColorBgra*)src.DataPtr; 112 int src_width = src.Width; 113 ColorBgra* dst_data_ptr = (ColorBgra*)dst.DataPtr; 114 int dst_width = dst.Width; 115 116 for (int y = roi.Y; y <= roi.GetBottom (); ++y) { 117 ColorBgra* srcPtr = src.GetPointAddressUnchecked (src_data_ptr, src_width, roi.X, y); 118 ColorBgra* dstPtr = dst.GetPointAddressUnchecked (dst_data_ptr, dst_width, roi.X, y); 119 Render (srcPtr, dstPtr, roi.Width); 120 } 121 } 122 123 /// <summary> 124 /// Performs the actual work of rendering an effect. This overload represent a single line of the image. Do not call base.Render (). 125 /// </summary> 126 /// <param name="src">The source surface. DO NOT MODIFY.</param> 127 /// <param name="dst">The destination surface.</param> 128 /// <param name="length">The number of pixels to render.</param> Render(ColorBgra* src, ColorBgra* dst, int length)129 protected unsafe virtual void Render (ColorBgra* src, ColorBgra* dst, int length) 130 { 131 while (length > 0) { 132 *dst = Render (*src); 133 ++dst; 134 ++src; 135 --length; 136 } 137 } 138 139 /// <summary> 140 /// Performs the actual work of rendering an effect. This overload represent a single pixel of the image. 141 /// </summary> 142 /// <param name="color">The color of the source surface pixel.</param> 143 /// <returns>The color to be used for the destination pixel.</returns> Render(ColorBgra color)144 protected virtual ColorBgra Render (ColorBgra color) 145 { 146 return color; 147 } 148 #endregion 149 150 // Effects that have any configuration state which is changed 151 // during live preview, and this this state is stored in 152 // non-value-type fields should override this method. 153 // Generally this state should be stored in the effect data 154 // class, not in the effect. 155 /// <summary> 156 /// Clones this effect so the live preview system has a copy that won't change while it is working. Only override this when a MemberwiseClone is not enough. 157 /// </summary> 158 /// <returns>An identical copy of this effect.</returns> Clone()159 public virtual BaseEffect Clone () 160 { 161 var effect = (BaseEffect) this.MemberwiseClone (); 162 163 if (effect.EffectData != null) 164 effect.EffectData = EffectData.Clone (); 165 166 return effect; 167 } 168 } 169 170 /// <summary> 171 /// Holds the user configurable data used by this effect. 172 /// </summary> 173 public abstract class EffectData : ObservableObject 174 { 175 // EffectData classes that have any state stored in non-value-type 176 // fields must override this method, and clone those members. 177 /// <summary> 178 /// Clones this EffectData so the live preview system has a copy that won't change while it is working. Only override this when a MemberwiseClone is not enough. 179 /// </summary> 180 /// <returns>An identical copy of this EffectData.</returns> Clone()181 public virtual EffectData Clone () 182 { 183 return (EffectData) this.MemberwiseClone (); 184 } 185 186 /// <summary> 187 /// Fires the PropertyChanged event for this ObservableObject. 188 /// </summary> 189 /// <param name="propertyName">The name of the property that changed.</param> FirePropertyChanged(string propertyName)190 public new void FirePropertyChanged (string propertyName) 191 { 192 base.FirePropertyChanged (propertyName); 193 } 194 195 /// <summary> 196 /// Returns true if the current values of this EffectData do not modify the image. Returns false if current values modify the image. 197 /// </summary> 198 public virtual bool IsDefault { get { return false; } } 199 } 200 } 201