/src/Data/BitmapLayer.cs
C# | 378 lines | 284 code | 64 blank | 30 comment | 37 complexity | 49f96d276b31d9545930403e9ccb2a74 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.Runtime.Serialization;
-
- namespace PaintDotNet
- {
- [Serializable]
- public class BitmapLayer
- : Layer,
- IDeserializationCallback
- {
- public override Surface RenderThumbnail(int maxEdgeLength)
- {
- Size thumbSize = Utility.ComputeThumbnailSize(Size, maxEdgeLength);
- var thumb = new Surface(thumbSize);
-
- thumb.SuperSamplingFitSurface(_surface);
-
- var thumb2 = new Surface(thumbSize);
- thumb2.ClearWithCheckboardPattern();
- var nbop = new UserBlendOps.NormalBlendOp();
- nbop.Apply(thumb2, thumb);
-
- thumb.Dispose();
- thumb = null;
-
- return thumb2;
- }
-
- private bool _disposed;
- protected override void Dispose(bool disposing)
- {
- if (_disposed)
- {
- }
- else
- {
- _disposed = true;
-
- try
- {
- if (disposing)
- {
- if (_surface != null)
- {
- _surface.Dispose();
- _surface = null;
- }
- }
- }
-
- finally
- {
- base.Dispose(disposing);
- }
- }
- }
-
- [NonSerialized]
- private BinaryPixelOp _compiledBlendOp;
-
- private void CompileBlendOp()
- {
- bool isDefaultOp = (_properties.BlendOp.GetType() == UserBlendOps.GetDefaultBlendOp());
-
- _compiledBlendOp = Opacity == 255 ? _properties.BlendOp : _properties.BlendOp.CreateWithOpacity(Opacity);
- }
-
- protected override void OnPropertyChanged(string propertyName)
- {
- _compiledBlendOp = null;
- base.OnPropertyChanged (propertyName);
- }
-
- [Serializable]
- internal sealed class BitmapLayerProperties
- : ICloneable,
- ISerializable
- {
- public UserBlendOp BlendOp;
- internal int Opacity; // this is ONLY used when loading older version PDN files! should normally equal -1
-
- private const string BlendOpTag = "blendOp";
- private const string OpacityTag = "opacity";
-
- public static string BlendOpName
- {
- get
- {
- return PdnResources.GetString("BitmapLayer.Properties.BlendOp.Name");
- }
- }
-
- public BitmapLayerProperties(UserBlendOp blendOp)
- {
- BlendOp = blendOp;
- Opacity = -1;
- }
-
- public BitmapLayerProperties(BitmapLayerProperties cloneMe)
- {
- BlendOp = cloneMe.BlendOp;
- Opacity = -1;
- }
-
- public object Clone()
- {
- return new BitmapLayerProperties(this);
- }
-
- public BitmapLayerProperties(SerializationInfo info, StreamingContext context)
- {
- BlendOp = (UserBlendOp)info.GetValue(BlendOpTag, typeof(UserBlendOp));
-
- // search for 'opacity' and load it if it exists
- Opacity = -1;
-
- foreach (SerializationEntry entry in info)
- {
- if (entry.Name != OpacityTag) continue;
- Opacity = (byte)entry.Value;
- break;
- }
- }
-
- public void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- info.AddValue(BlendOpTag, BlendOp);
- }
- }
-
- private BitmapLayerProperties _properties;
- private Surface _surface;
-
- public override object SaveProperties()
- {
- if (_disposed)
- {
- throw new ObjectDisposedException("BitmapLayer");
- }
-
- object baseProperties = base.SaveProperties();
- return new List(_properties.Clone(), new List(baseProperties, null));
- }
-
- public override void LoadProperties(object oldState, bool suppressEvents)
- {
- if (_disposed)
- {
- throw new ObjectDisposedException("BitmapLayer");
- }
-
- var list = (List)oldState;
-
- // Get the base class' state, and our state
- var baseState = (LayerProperties)list.Tail.Head;
- var blp = (BitmapLayerProperties)(((List)oldState).Head);
-
- // Opacity is only couriered for compatibility with PDN v2.0 and v1.1
- // files. It should not be present in v2.1+ files (well, it'll be
- // part of the base class' serialization)
- if (blp.Opacity != -1)
- {
- baseState.opacity = (byte)blp.Opacity;
- blp.Opacity = -1;
- }
-
- // Have the base class load its properties
- base.LoadProperties(baseState, suppressEvents);
-
- // Now load our properties, and announce them to the world
- bool raiseBlendOp = false;
-
- if (blp.BlendOp.GetType() != _properties.BlendOp.GetType())
- {
- if (!suppressEvents)
- {
- raiseBlendOp = true;
- OnPropertyChanging(BitmapLayerProperties.BlendOpName);
- }
- }
-
- _properties = (BitmapLayerProperties)blp.Clone();
- _compiledBlendOp = null;
-
- Invalidate();
-
- if (raiseBlendOp)
- {
- OnPropertyChanged(BitmapLayerProperties.BlendOpName);
- }
- }
-
- public void SetBlendOp(UserBlendOp blendOp)
- {
- if (_disposed)
- {
- throw new ObjectDisposedException("BitmapLayer");
- }
-
- if (blendOp.GetType() == _properties.BlendOp.GetType()) return;
- OnPropertyChanging(BitmapLayerProperties.BlendOpName);
- _properties.BlendOp = blendOp;
- _compiledBlendOp = null;
- Invalidate();
- OnPropertyChanged(BitmapLayerProperties.BlendOpName);
- }
-
- public override object Clone()
- {
- if (_disposed)
- {
- throw new ObjectDisposedException("BitmapLayer");
- }
-
- return new BitmapLayer(this);
- }
-
- public Surface Surface
- {
- get
- {
- if (_disposed)
- {
- throw new ObjectDisposedException("BitmapLayer");
- }
-
- return _surface;
- }
- }
-
- public UserBlendOp BlendOp
- {
- get
- {
- if (_disposed)
- {
- throw new ObjectDisposedException("BitmapLayer");
- }
-
- return _properties.BlendOp;
- }
- }
-
- public BitmapLayer(int width, int height)
- : this(width, height, ColorBgra.FromBgra(255, 255, 255, 0))
- {
- }
-
- public BitmapLayer(int width, int height, ColorBgra fillColor)
- : base(width, height)
- {
- _surface = new Surface(width, height);
- // clear to see-through white, 0x00ffffff
- Surface.Clear(fillColor);
- _properties = new BitmapLayerProperties(UserBlendOps.CreateDefaultBlendOp());
- }
-
- /// <summary>
- /// Creates a new BitmapLayer of the same size as the given Surface, and copies the
- /// pixels from the given Surface.
- /// </summary>
- /// <param name="surface">The Surface to copy pixels from.</param>
- public BitmapLayer(Surface surface)
- : this(surface, false)
- {
- }
-
- /// <summary>
- /// Creates a new BitmapLayer of the same size as the given Surface, and either
- /// copies the pixels of the given Surface or takes ownership of it.
- /// </summary>
- /// <param name="surface">The Surface.</param>
- /// <param name="takeOwnership">
- /// true to take ownership of the surface (make sure to Dispose() it yourself), or
- /// false to copy its pixels
- /// </param>
- public BitmapLayer(Surface surface, bool takeOwnership)
- : base(surface.Width, surface.Height)
- {
- _surface = takeOwnership ? surface : surface.Clone();
-
- _properties = new BitmapLayerProperties(UserBlendOps.CreateDefaultBlendOp());
- }
-
- protected BitmapLayer(BitmapLayer copyMe)
- : base(copyMe)
- {
- _surface = copyMe.Surface.Clone();
- _properties = (BitmapLayerProperties)copyMe._properties.Clone();
- }
-
- protected unsafe override void RenderImpl(RenderArgs args, Rectangle roi)
- {
- if (_disposed)
- {
- throw new ObjectDisposedException("BitmapLayer");
- }
-
- if (Opacity == 0)
- {
- return;
- }
-
- if (_compiledBlendOp == null)
- {
- CompileBlendOp();
- }
-
- for (int y = roi.Top; y < roi.Bottom; ++y)
- {
- ColorBgra *dstPtr = args.Surface.GetPointAddressUnchecked(roi.Left, y);
- ColorBgra *srcPtr = _surface.GetPointAddressUnchecked(roi.Left, y);
-
- _compiledBlendOp.Apply(dstPtr, srcPtr, roi.Width);
- }
- }
-
- protected unsafe override void RenderImpl(RenderArgs args, Rectangle[] rois, int startIndex, int length)
- {
- if (_disposed)
- {
- throw new ObjectDisposedException("BitmapLayer");
- }
-
- if (Opacity == 0)
- {
- return;
- }
-
- if (_compiledBlendOp == null)
- {
- CompileBlendOp();
- }
-
- for (int i = startIndex; i < startIndex + length; ++i)
- {
- Rectangle roi = rois[i];
-
- for (int y = roi.Top; y < roi.Bottom; ++y)
- {
- ColorBgra *dstPtr = args.Surface.GetPointAddressUnchecked(roi.Left, y);
- ColorBgra *srcPtr = _surface.GetPointAddressUnchecked(roi.Left, y);
-
- _compiledBlendOp.Apply(dstPtr, srcPtr, roi.Width);
- }
- }
- }
-
- public override PdnBaseForm CreateConfigDialog()
- {
- var blpd = new BitmapLayerPropertiesDialog {Layer = this};
- return blpd;
- }
-
- public void OnDeserialization(object sender)
- {
- if (_properties.Opacity != -1)
- {
- PushSuppressPropertyChanged();
- Opacity = (byte)_properties.Opacity;
- _properties.Opacity = -1;
- PopSuppressPropertyChanged();
- }
-
- _compiledBlendOp = null;
- }
- }
- }