// // Copyright (C) 2008 Aaron Bockover, abockover@novell.com // Copyright (C) 2008 Jordi Mas i Hernandez, jmas@softcatala.org // // 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. // using System; using System.Runtime.InteropServices; using Cairo; namespace Mistelix.Widgets { public class DataImageSurface : ImageSurface, IDisposable { delegate void cairo_destroy_func_t (IntPtr userdata); static int user_data_key = 0; static cairo_destroy_func_t destroy_func; protected IntPtr data; static protected bool is_le = BitConverter.IsLittleEndian; static void DestroyPixelData (IntPtr data) { Marshal.FreeHGlobal (data); } static DataImageSurface () { destroy_func = new cairo_destroy_func_t (DestroyPixelData); } static public IntPtr Allocate (byte [] pixels) { IntPtr ptr = Marshal.AllocHGlobal (pixels.Length); Marshal.Copy (pixels, 0, ptr, pixels.Length); return ptr; } public DataImageSurface (IntPtr data, Cairo.Format format, int width, int height, int stride) : base (data, format, width, height, width * 4) { this.data = data; SetDestroyFunc (); } public byte[] Get24bitsPixBuf () { return FromCairo32ToPixBuf (Data, Width, Height, 3); } // Converts a pixel data array from Cairo 32-bits to GDK 24/32 bits static public byte[] FromCairo32ToPixBuf (byte[] cairo_pixels, int width, int height, int channels) { int pos_cairo = 0; int pos_gdk = 0; byte [] pixels; pixels = new byte [height * width * channels]; for (int h = 0; h < height; h++) { for (int i = 0; i < width; i++) { if (is_le) { pixels[pos_gdk + 2] = cairo_pixels[pos_cairo + 0]; pixels[pos_gdk + 1] = cairo_pixels[pos_cairo + 1]; pixels[pos_gdk + 0] = cairo_pixels[pos_cairo + 2]; if (channels == 4) pixels[pos_gdk + 3] = cairo_pixels[pos_cairo + 3]; } else { pixels[pos_gdk + 0] = cairo_pixels[pos_cairo + 1]; pixels[pos_gdk + 1] = cairo_pixels[pos_cairo + 2]; pixels[pos_gdk + 2] = cairo_pixels[pos_cairo + 3]; if (channels == 4) pixels[pos_gdk + 3] = cairo_pixels[pos_cairo + 0]; } pos_gdk += channels; pos_cairo += 4; } } return pixels; } [DllImport ("libcairo.so.2")] static extern Cairo.Status cairo_surface_set_user_data (IntPtr surface, ref int key, IntPtr userdata, cairo_destroy_func_t destroy); void SetDestroyFunc () { try { Cairo.Status status = cairo_surface_set_user_data (Handle, ref user_data_key, data, destroy_func); if (status != Cairo.Status.Success) { throw new ApplicationException (String.Format ( "cairo_surface_set_user_data returned {0}", status)); } } catch (Exception e) { Console.Error.WriteLine (e); } } } }