PageRenderTime 47ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Data/BitmapLayer.cs

https://bitbucket.org/tuldok89/openpdn
C# | 378 lines | 284 code | 64 blank | 30 comment | 37 complexity | 49f96d276b31d9545930403e9ccb2a74 MD5 | raw file
  1. /////////////////////////////////////////////////////////////////////////////////
  2. // Paint.NET //
  3. // Copyright (C) dotPDN LLC, Rick Brewster, Tom Jackson, and contributors. //
  4. // Portions Copyright (C) Microsoft Corporation. All Rights Reserved. //
  5. // See src/Resources/Files/License.txt for full licensing and attribution //
  6. // details. //
  7. // . //
  8. /////////////////////////////////////////////////////////////////////////////////
  9. using System;
  10. using System.Drawing;
  11. using System.Runtime.Serialization;
  12. namespace PaintDotNet
  13. {
  14. [Serializable]
  15. public class BitmapLayer
  16. : Layer,
  17. IDeserializationCallback
  18. {
  19. public override Surface RenderThumbnail(int maxEdgeLength)
  20. {
  21. Size thumbSize = Utility.ComputeThumbnailSize(Size, maxEdgeLength);
  22. var thumb = new Surface(thumbSize);
  23. thumb.SuperSamplingFitSurface(_surface);
  24. var thumb2 = new Surface(thumbSize);
  25. thumb2.ClearWithCheckboardPattern();
  26. var nbop = new UserBlendOps.NormalBlendOp();
  27. nbop.Apply(thumb2, thumb);
  28. thumb.Dispose();
  29. thumb = null;
  30. return thumb2;
  31. }
  32. private bool _disposed;
  33. protected override void Dispose(bool disposing)
  34. {
  35. if (_disposed)
  36. {
  37. }
  38. else
  39. {
  40. _disposed = true;
  41. try
  42. {
  43. if (disposing)
  44. {
  45. if (_surface != null)
  46. {
  47. _surface.Dispose();
  48. _surface = null;
  49. }
  50. }
  51. }
  52. finally
  53. {
  54. base.Dispose(disposing);
  55. }
  56. }
  57. }
  58. [NonSerialized]
  59. private BinaryPixelOp _compiledBlendOp;
  60. private void CompileBlendOp()
  61. {
  62. bool isDefaultOp = (_properties.BlendOp.GetType() == UserBlendOps.GetDefaultBlendOp());
  63. _compiledBlendOp = Opacity == 255 ? _properties.BlendOp : _properties.BlendOp.CreateWithOpacity(Opacity);
  64. }
  65. protected override void OnPropertyChanged(string propertyName)
  66. {
  67. _compiledBlendOp = null;
  68. base.OnPropertyChanged (propertyName);
  69. }
  70. [Serializable]
  71. internal sealed class BitmapLayerProperties
  72. : ICloneable,
  73. ISerializable
  74. {
  75. public UserBlendOp BlendOp;
  76. internal int Opacity; // this is ONLY used when loading older version PDN files! should normally equal -1
  77. private const string BlendOpTag = "blendOp";
  78. private const string OpacityTag = "opacity";
  79. public static string BlendOpName
  80. {
  81. get
  82. {
  83. return PdnResources.GetString("BitmapLayer.Properties.BlendOp.Name");
  84. }
  85. }
  86. public BitmapLayerProperties(UserBlendOp blendOp)
  87. {
  88. BlendOp = blendOp;
  89. Opacity = -1;
  90. }
  91. public BitmapLayerProperties(BitmapLayerProperties cloneMe)
  92. {
  93. BlendOp = cloneMe.BlendOp;
  94. Opacity = -1;
  95. }
  96. public object Clone()
  97. {
  98. return new BitmapLayerProperties(this);
  99. }
  100. public BitmapLayerProperties(SerializationInfo info, StreamingContext context)
  101. {
  102. BlendOp = (UserBlendOp)info.GetValue(BlendOpTag, typeof(UserBlendOp));
  103. // search for 'opacity' and load it if it exists
  104. Opacity = -1;
  105. foreach (SerializationEntry entry in info)
  106. {
  107. if (entry.Name != OpacityTag) continue;
  108. Opacity = (byte)entry.Value;
  109. break;
  110. }
  111. }
  112. public void GetObjectData(SerializationInfo info, StreamingContext context)
  113. {
  114. info.AddValue(BlendOpTag, BlendOp);
  115. }
  116. }
  117. private BitmapLayerProperties _properties;
  118. private Surface _surface;
  119. public override object SaveProperties()
  120. {
  121. if (_disposed)
  122. {
  123. throw new ObjectDisposedException("BitmapLayer");
  124. }
  125. object baseProperties = base.SaveProperties();
  126. return new List(_properties.Clone(), new List(baseProperties, null));
  127. }
  128. public override void LoadProperties(object oldState, bool suppressEvents)
  129. {
  130. if (_disposed)
  131. {
  132. throw new ObjectDisposedException("BitmapLayer");
  133. }
  134. var list = (List)oldState;
  135. // Get the base class' state, and our state
  136. var baseState = (LayerProperties)list.Tail.Head;
  137. var blp = (BitmapLayerProperties)(((List)oldState).Head);
  138. // Opacity is only couriered for compatibility with PDN v2.0 and v1.1
  139. // files. It should not be present in v2.1+ files (well, it'll be
  140. // part of the base class' serialization)
  141. if (blp.Opacity != -1)
  142. {
  143. baseState.opacity = (byte)blp.Opacity;
  144. blp.Opacity = -1;
  145. }
  146. // Have the base class load its properties
  147. base.LoadProperties(baseState, suppressEvents);
  148. // Now load our properties, and announce them to the world
  149. bool raiseBlendOp = false;
  150. if (blp.BlendOp.GetType() != _properties.BlendOp.GetType())
  151. {
  152. if (!suppressEvents)
  153. {
  154. raiseBlendOp = true;
  155. OnPropertyChanging(BitmapLayerProperties.BlendOpName);
  156. }
  157. }
  158. _properties = (BitmapLayerProperties)blp.Clone();
  159. _compiledBlendOp = null;
  160. Invalidate();
  161. if (raiseBlendOp)
  162. {
  163. OnPropertyChanged(BitmapLayerProperties.BlendOpName);
  164. }
  165. }
  166. public void SetBlendOp(UserBlendOp blendOp)
  167. {
  168. if (_disposed)
  169. {
  170. throw new ObjectDisposedException("BitmapLayer");
  171. }
  172. if (blendOp.GetType() == _properties.BlendOp.GetType()) return;
  173. OnPropertyChanging(BitmapLayerProperties.BlendOpName);
  174. _properties.BlendOp = blendOp;
  175. _compiledBlendOp = null;
  176. Invalidate();
  177. OnPropertyChanged(BitmapLayerProperties.BlendOpName);
  178. }
  179. public override object Clone()
  180. {
  181. if (_disposed)
  182. {
  183. throw new ObjectDisposedException("BitmapLayer");
  184. }
  185. return new BitmapLayer(this);
  186. }
  187. public Surface Surface
  188. {
  189. get
  190. {
  191. if (_disposed)
  192. {
  193. throw new ObjectDisposedException("BitmapLayer");
  194. }
  195. return _surface;
  196. }
  197. }
  198. public UserBlendOp BlendOp
  199. {
  200. get
  201. {
  202. if (_disposed)
  203. {
  204. throw new ObjectDisposedException("BitmapLayer");
  205. }
  206. return _properties.BlendOp;
  207. }
  208. }
  209. public BitmapLayer(int width, int height)
  210. : this(width, height, ColorBgra.FromBgra(255, 255, 255, 0))
  211. {
  212. }
  213. public BitmapLayer(int width, int height, ColorBgra fillColor)
  214. : base(width, height)
  215. {
  216. _surface = new Surface(width, height);
  217. // clear to see-through white, 0x00ffffff
  218. Surface.Clear(fillColor);
  219. _properties = new BitmapLayerProperties(UserBlendOps.CreateDefaultBlendOp());
  220. }
  221. /// <summary>
  222. /// Creates a new BitmapLayer of the same size as the given Surface, and copies the
  223. /// pixels from the given Surface.
  224. /// </summary>
  225. /// <param name="surface">The Surface to copy pixels from.</param>
  226. public BitmapLayer(Surface surface)
  227. : this(surface, false)
  228. {
  229. }
  230. /// <summary>
  231. /// Creates a new BitmapLayer of the same size as the given Surface, and either
  232. /// copies the pixels of the given Surface or takes ownership of it.
  233. /// </summary>
  234. /// <param name="surface">The Surface.</param>
  235. /// <param name="takeOwnership">
  236. /// true to take ownership of the surface (make sure to Dispose() it yourself), or
  237. /// false to copy its pixels
  238. /// </param>
  239. public BitmapLayer(Surface surface, bool takeOwnership)
  240. : base(surface.Width, surface.Height)
  241. {
  242. _surface = takeOwnership ? surface : surface.Clone();
  243. _properties = new BitmapLayerProperties(UserBlendOps.CreateDefaultBlendOp());
  244. }
  245. protected BitmapLayer(BitmapLayer copyMe)
  246. : base(copyMe)
  247. {
  248. _surface = copyMe.Surface.Clone();
  249. _properties = (BitmapLayerProperties)copyMe._properties.Clone();
  250. }
  251. protected unsafe override void RenderImpl(RenderArgs args, Rectangle roi)
  252. {
  253. if (_disposed)
  254. {
  255. throw new ObjectDisposedException("BitmapLayer");
  256. }
  257. if (Opacity == 0)
  258. {
  259. return;
  260. }
  261. if (_compiledBlendOp == null)
  262. {
  263. CompileBlendOp();
  264. }
  265. for (int y = roi.Top; y < roi.Bottom; ++y)
  266. {
  267. ColorBgra *dstPtr = args.Surface.GetPointAddressUnchecked(roi.Left, y);
  268. ColorBgra *srcPtr = _surface.GetPointAddressUnchecked(roi.Left, y);
  269. _compiledBlendOp.Apply(dstPtr, srcPtr, roi.Width);
  270. }
  271. }
  272. protected unsafe override void RenderImpl(RenderArgs args, Rectangle[] rois, int startIndex, int length)
  273. {
  274. if (_disposed)
  275. {
  276. throw new ObjectDisposedException("BitmapLayer");
  277. }
  278. if (Opacity == 0)
  279. {
  280. return;
  281. }
  282. if (_compiledBlendOp == null)
  283. {
  284. CompileBlendOp();
  285. }
  286. for (int i = startIndex; i < startIndex + length; ++i)
  287. {
  288. Rectangle roi = rois[i];
  289. for (int y = roi.Top; y < roi.Bottom; ++y)
  290. {
  291. ColorBgra *dstPtr = args.Surface.GetPointAddressUnchecked(roi.Left, y);
  292. ColorBgra *srcPtr = _surface.GetPointAddressUnchecked(roi.Left, y);
  293. _compiledBlendOp.Apply(dstPtr, srcPtr, roi.Width);
  294. }
  295. }
  296. }
  297. public override PdnBaseForm CreateConfigDialog()
  298. {
  299. var blpd = new BitmapLayerPropertiesDialog {Layer = this};
  300. return blpd;
  301. }
  302. public void OnDeserialization(object sender)
  303. {
  304. if (_properties.Opacity != -1)
  305. {
  306. PushSuppressPropertyChanged();
  307. Opacity = (byte)_properties.Opacity;
  308. _properties.Opacity = -1;
  309. PopSuppressPropertyChanged();
  310. }
  311. _compiledBlendOp = null;
  312. }
  313. }
  314. }