diff options
Diffstat (limited to 'mcs/class/Managed.Windows.Forms/System.Windows.Forms/ImageListStreamer.cs')
-rw-r--r-- | mcs/class/Managed.Windows.Forms/System.Windows.Forms/ImageListStreamer.cs | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ImageListStreamer.cs b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ImageListStreamer.cs new file mode 100644 index 00000000000..6f5fae74117 --- /dev/null +++ b/mcs/class/Managed.Windows.Forms/System.Windows.Forms/ImageListStreamer.cs @@ -0,0 +1,226 @@ +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// +// Copyright (c) 2002-2005 Novell, Inc. +// +// Authors: +// Jackson Harper (jackson@ximian.com) +// +// Based on work done by: +// Dennis Hayes (dennish@Raytek.com) +// Aleksey Ryabchuk (ryabchuk@yahoo.com) + +using System.IO; +using System.Drawing; +using System.Collections; +using System.Drawing.Imaging; +using System.Runtime.Serialization; +using System.Runtime.InteropServices; + + +namespace System.Windows.Forms { + + [Serializable] + public sealed class ImageListStreamer : ISerializable { + + private static byte [] signature = new byte [] {77 , 83 , 70 , 116}; + + private readonly ImageList.ImageCollection imageCollection; + private Image [] images; + private Size image_size; + private Color back_color; + + internal ImageListStreamer (ImageList.ImageCollection imageCollection) { + this.imageCollection = imageCollection; + } + + private ImageListStreamer (SerializationInfo info, StreamingContext context) { + + byte [] data = (byte [])info.GetValue ("Data", typeof (byte [])); + if (data == null || data.Length <= signature.Length) + return; + // check the signature ( 'MSFt' ) + if (data [0] != signature [0] || data [1] != signature [1] || + data [2] != signature [2] || data [3] != signature [3]) + return; + + // calulate size of array needed for decomressed data + int i = 0; + int real_byte_count = 0; + for (i = signature.Length; i < data.Length; i += 2) + real_byte_count += data [i]; + + if (real_byte_count == 0) + return; + + int j = 0; + byte [] decompressed = new byte [real_byte_count]; + + for (i = signature.Length; i < data.Length; i += 2) { + for (int k = 0; k < data [i]; k++) + decompressed [j++] = data [i + 1]; + } + + MemoryStream stream = new MemoryStream (decompressed); + BinaryReader reader = new BinaryReader (stream); + + try { + // read image list header + reader.ReadUInt16 (); // usMagic + reader.ReadUInt16 (); // usVersion + ushort cCurImage = reader.ReadUInt16 (); + reader.ReadUInt16 (); // cMaxImage + reader.ReadUInt16 (); // cGrow + ushort cx = reader.ReadUInt16 (); + ushort cy = reader.ReadUInt16 (); + uint bkcolor = reader.ReadUInt32 (); + reader.ReadUInt16 (); // flags + + short [] ovls = new short [4]; + for (i = 0; i < ovls.Length; i++) { + ovls[i] = reader.ReadInt16 (); + } + + image_size = new Size (cx, cy); + back_color = Color.FromArgb ((int) bkcolor); + + MemoryStream start = new MemoryStream (decompressed, + (int) stream.Position, + (int) stream.Length - (int) stream.Position, + false); + + Image image = Image.FromStream (start); + + // Holy calamity. This is what happens on MS + // if the background colour is 0xFFFFFFFF (CLR_NONE) + // the mask is set to the color at pixel 0, 0 + Bitmap bmp = image as Bitmap; + if (bkcolor == 0xFFFFFFFF && bmp != null) + back_color = bmp.GetPixel (0, 0); + + int step = image.Width / cx; + images = new Image [cCurImage]; + + Rectangle dest_rect = new Rectangle (0, 0, cx, cy); + for (int r = 0 ; r < cCurImage ; r++) { + Rectangle area = new Rectangle ( + (r % step) * cx, + (r / step) * cy, + cx, cy); + Bitmap b = new Bitmap (cx, cy); + using (Graphics g = Graphics.FromImage (b)) { + g.DrawImage (image, dest_rect, area, + GraphicsUnit.Pixel); + } + b.MakeTransparent (back_color); + images [r] = b; + } + + } catch (Exception e) { + + } + } + + [MonoTODO ("RLE is broken")] + public void GetObjectData (SerializationInfo info, StreamingContext context) + { + MemoryStream stream = new MemoryStream (); + BinaryWriter writer = new BinaryWriter (stream); + + writer.Write (signature); + writer.Write (GetStreamData ()); + + info.AddValue ("Data", stream.ToArray (), typeof (byte [])); + } + + [MonoTODO ("Images should be written to the stream")] + private byte [] GetStreamData () + { + MemoryStream stream = new MemoryStream (); + BinaryWriter writer = new BinaryWriter (stream); + Image [] images = (imageCollection != null) ? imageCollection.ToArray () : this.images; + + int cols = 4; + int rows = images.Length / cols; + if (images.Length % cols > 0) + ++rows; + + Bitmap main = new Bitmap (cols * ImageSize.Width, rows * ImageSize.Height); + using (Graphics g = Graphics.FromImage (main)) { + g.FillRectangle (ThemeEngine.Current.ResPool.GetSolidBrush (BackColor), 0, 0, cols * ImageSize.Width, rows * ImageSize.Height); + for (int i = 0; i < images.Length; i++) { + g.DrawImage (images [i], (i % cols) * ImageSize.Width, + (i / cols) * ImageSize.Height); + } + } + + writer.Write ((ushort) (('L' << 8) | 'I')); // magic + writer.Write ((ushort) 0x101); // version + writer.Write ((ushort) images.Length); + writer.Write ((ushort) images.Length); + writer.Write ((ushort) (rows * cols)); + writer.Write ((ushort) 0x4); // grow....not sure this should be hard coded + writer.Write ((ushort) image_size.Width); + writer.Write ((ushort) image_size.Height); + writer.Write (BackColor.ToArgb ()); + writer.Write ((ushort) 0x1009); // flags + + for (int i = 0; i < 4; i++) + writer.Write ((short) -1); // ovls + + return RLEncodeData (stream.ToArray ()); + } + + // TODO: This is broken + private byte [] RLEncodeData (byte [] data) + { + MemoryStream stream = new MemoryStream (); + BinaryWriter writer = new BinaryWriter (stream); + + for (int i = 0; i < data.Length; i += 2) { + int seq = 0; + byte item = data [i]; + while (data [i++] == item && i < data.Length) + seq++; + writer.Write ((byte) seq); + writer.Write (item); + } + + return stream.ToArray (); + + } + + internal Image [] Images { + get { return images; } + } + + internal Size ImageSize { + get { return image_size; } + } + + internal ColorDepth ColorDepth { + get { return ColorDepth.Depth32Bit; } + } + + internal Color BackColor { + get { return back_color; } + } + } +} + |