2007-12-19 Sebastien Pouliot <sebastien@ximian.com>
[mono.git] / mcs / class / System.Drawing / System.Drawing / gdipFunctions.cs
index 4b953518555014a1cadc400a3d0638ccafdb0eba..6c5f90c02dc53def0a90434b1e5a22cd37385f55 100644 (file)
@@ -7,8 +7,9 @@
 //     Sanjay Gupta (gsanjay@novell.com)
 //     Ravindra (rkumar@novell.com)
 //     Peter Dennis Bartok (pbartok@novell.com)
+//     Sebastien Pouliot  <sebastien@ximian.com>
 //
-// Copyright (C) 2004 - 2006 Novell, Inc (http://www.novell.com)
+// Copyright (C) 2004 - 2007 Novell, Inc (http://www.novell.com)
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-using System;
 using System.IO;
 using System.Runtime.InteropServices;
 using System.Text;
 using System.Drawing.Drawing2D;
 using System.Drawing.Imaging;
 using System.Drawing.Text;
+using System.Globalization;
 using System.Security;
 #if NET_2_0
 using System.Runtime.InteropServices.ComTypes;
@@ -56,7 +57,7 @@ namespace System.Drawing
                public const int LANG_NEUTRAL = 0;
                public static IntPtr Display = IntPtr.Zero;
                public static bool UseX11Drawable;
-               public static bool UseQuartzDrawable = (Environment.GetEnvironmentVariable ("MONO_MWF_USE_QUARTZ_BACKEND") != null);
+               public static bool UseQuartzDrawable = (Environment.GetEnvironmentVariable ("MONO_MWF_USE_CARBON_BACKEND") != null);
                public static bool UseCocoaDrawable = (Environment.GetEnvironmentVariable ("MONO_GDIP_USE_COCOA_BACKEND") != null);
 
                #region gdiplus.dll functions
@@ -75,22 +76,22 @@ namespace System.Drawing
                        // shutting down
                        GC.Collect ();  
                        GC.WaitForPendingFinalizers ();
-                       
+#if false                      
                        GdiPlusToken = 0;
 
-                       // This causes crashes in MS GDI+ because this call occurs before
-                       // all managed GDI objects are finalized. When they are finalized they call
-                       // into a shutdown GDI+ and we crash.
-                       //GdiplusShutdown (ref GdiPlusToken);
+                       // This causes crashes in because this call occurs before all
+                       // managed GDI+ objects are finalized. When they are finalized 
+                       // they call into a shutdown GDI+ and we crash.
+                       GdiplusShutdown (ref GdiPlusToken);
 
                        // This causes crashes in Mono libgdiplus because this call
                        // occurs before all managed GDI objects are finalized
                        // When they are finalized they use the closed display and
                        // crash
-                       //if (UseX11Drawable && Display != IntPtr.Zero) {
-                       //      XCloseDisplay (Display);
-                       //}
-
+                       if (UseX11Drawable && Display != IntPtr.Zero) {
+                               XCloseDisplay (Display);
+                       }
+#endif
                }
 
                static GDIPlus ()
@@ -104,47 +105,58 @@ namespace System.Drawing
                        GdiplusStartupOutput output = GdiplusStartupOutput.MakeGdiplusStartupOutput();
                        try {
                                GdiplusStartup (ref GdiPlusToken, ref input, ref output);
-                       } catch (TypeInitializationException tie){
+                       }
+                       catch (TypeInitializationException) {
                                Console.Error.WriteLine (
                                        "* ERROR: Can not initialize GDI+ library\n" +
                                        "\n" +
                                        "Please check http://www.mono-project.com/Problem:GDIPlusInit for details");
-                               
                        }
-                       
+
+                       // under MS 1.x this event is raised only for the default application domain
                        AppDomain.CurrentDomain.ProcessExit += new EventHandler (ProcessExit);
                }
+
+               static public bool RunningOnWindows ()
+               {
+                       return !UseX11Drawable;
+               }
+
+               static public bool RunningOnUnix ()
+               {
+                       return UseX11Drawable;
+               }
                
                // Copies a Ptr to an array of Points and releases the memory
-               static public void FromUnManagedMemoryToPointI(IntPtr prt, Point [] pts)
+               static public void FromUnManagedMemoryToPointI (IntPtr prt, Point [] pts)
                {                                               
-                       int nPointSize = Marshal.SizeOf(pts[0]);
+                       int nPointSize = Marshal.SizeOf (pts[0]);
                        IntPtr pos = prt;
                        for (int i=0; i<pts.Length; i++, pos = new IntPtr (pos.ToInt64 () + nPointSize))
-                               pts[i] = (Point) Marshal.PtrToStructure(pos, typeof(Point));
+                               pts[i] = (Point) Marshal.PtrToStructure (pos, typeof (Point));
                        
-                       Marshal.FreeHGlobal(prt);                       
+                       Marshal.FreeHGlobal (prt);                      
                }
                
                // Copies a Ptr to an array of Points and releases the memory
                static public void FromUnManagedMemoryToPoint (IntPtr prt, PointF [] pts)
                {                                               
-                       int nPointSize = Marshal.SizeOf(pts[0]);
+                       int nPointSize = Marshal.SizeOf (pts[0]);
                        IntPtr pos = prt;
                        for (int i=0; i<pts.Length; i++, pos = new IntPtr (pos.ToInt64 () + nPointSize))
-                               pts[i] = (PointF) Marshal.PtrToStructure(pos, typeof(Point));
+                               pts[i] = (PointF) Marshal.PtrToStructure (pos, typeof (PointF));
                        
-                       Marshal.FreeHGlobal(prt);                       
+                       Marshal.FreeHGlobal (prt);                      
                }
                
                // Copies an array of Points to unmanaged memory
-               static public IntPtr FromPointToUnManagedMemoryI(Point [] pts)
+               static public IntPtr FromPointToUnManagedMemoryI (Point [] pts)
                {
-                       int nPointSize =  Marshal.SizeOf(pts[0]);
-                       IntPtr dest = Marshal.AllocHGlobal(nPointSize* pts.Length);
+                       int nPointSize =  Marshal.SizeOf (pts[0]);
+                       IntPtr dest = Marshal.AllocHGlobal (nPointSize * pts.Length);
                        IntPtr pos = dest;
                        for (int i=0; i<pts.Length; i++, pos = new IntPtr (pos.ToInt64 () + nPointSize))
-                               Marshal.StructureToPtr(pts[i], pos, false);     
+                               Marshal.StructureToPtr (pts[i], pos, false);    
                        
                        return dest;                    
                }               
@@ -155,78 +167,79 @@ namespace System.Drawing
                        int nPointSize = Marshal.SizeOf (pts[0]);
                        IntPtr pos = prt;
                        for (int i = 0; i < pts.Length; i++, pos = new IntPtr (pos.ToInt64 () + nPointSize))
-                               pts[i] = (RectangleF) Marshal.PtrToStructure(pos, typeof(RectangleF));
+                               pts[i] = (RectangleF) Marshal.PtrToStructure (pos, typeof (RectangleF));
                        
-                       Marshal.FreeHGlobal(prt);                       
+                       Marshal.FreeHGlobal (prt);                      
                }
                
                // Copies an array of Points to unmanaged memory
-               static public IntPtr FromPointToUnManagedMemory(PointF [] pts)
+               static public IntPtr FromPointToUnManagedMemory (PointF [] pts)
                {
-                       int nPointSize =  Marshal.SizeOf(pts[0]);
-                       IntPtr dest = Marshal.AllocHGlobal(nPointSize* pts.Length);                     
+                       int nPointSize =  Marshal.SizeOf (pts[0]);
+                       IntPtr dest = Marshal.AllocHGlobal (nPointSize * pts.Length);                   
                        IntPtr pos = dest;
                        for (int i=0; i<pts.Length; i++, pos = new IntPtr (pos.ToInt64 () + nPointSize))
-                               Marshal.StructureToPtr(pts[i], pos, false);     
+                               Marshal.StructureToPtr (pts[i], pos, false);    
                        
                        return dest;                    
                }
 
                // Converts a status into exception
+               // TODO: Add more status code mappings here
                static internal void CheckStatus (Status status)
                {
+                       string msg;
                        switch (status) {
-
-                               case Status.Ok:
-                                       return;
-
-                               // TODO: Add more status code mappings here
-
-                               case Status.GenericError:
-                                       throw new Exception ("Generic Error.");
-
-                               case Status.InvalidParameter:
-                                       throw new ArgumentException ("Invalid Parameter. A null reference or invalid value was found.");
-
-                               case Status.OutOfMemory:
-                                       throw new OutOfMemoryException ("Out of memory.");
-
-                               case Status.ObjectBusy:
-                                       throw new MemberAccessException ("Object busy.");
-
-                               case Status.InsufficientBuffer:
-                                       throw new IO.InternalBufferOverflowException ("Insufficient buffer.");
-
-                               case Status.PropertyNotSupported:
-                                       throw new NotSupportedException ("Property not supported.");
-
-                               case Status.FileNotFound:
-                                       throw new IO.FileNotFoundException ("File not found.");
-
-                               case Status.AccessDenied:
-                                       throw new UnauthorizedAccessException ("Access denied.");
-
-                               case Status.UnknownImageFormat:
-                                       throw new NotSupportedException ("Either image format is unknown or you don't have the required libraries for this format.");
-
-                               case Status.NotImplemented:
-                                       throw new NotImplementedException ("Feature not implemented.");
-
-                               case Status.WrongState:
-                                       throw new ArgumentException ("Properties not set properly.");
-
-                               case Status.FontFamilyNotFound:
-                                       throw new ArgumentException ("FontFamily wasn't found.");
-
-                               case Status.ValueOverflow:
-                                       throw new OverflowException ("Argument out of range.");
-
-                               default:
-                                       throw new Exception ("Unknown Error.");
+                       case Status.Ok:
+                               return;
+                       case Status.GenericError:
+                               msg = Locale.GetText ("Generic Error [GDI+ status: {0}]", status);
+                               throw new Exception (msg);
+                       case Status.InvalidParameter:
+                               msg = Locale.GetText ("A null reference or invalid value was found [GDI+ status: {0}]", status);
+                               throw new ArgumentException (msg);
+                       case Status.OutOfMemory:
+                               msg = Locale.GetText ("Not enough memory to complete operation [GDI+ status: {0}]", status);
+                               throw new OutOfMemoryException (msg);
+                       case Status.ObjectBusy:
+                               msg = Locale.GetText ("Object is busy and cannot state allow this operation [GDI+ status: {0}]", status);
+                               throw new MemberAccessException (msg);
+                       case Status.InsufficientBuffer:
+                               msg = Locale.GetText ("Insufficient buffer provided to complete operation [GDI+ status: {0}]", status);
+                               throw new InternalBufferOverflowException (msg);
+                       case Status.PropertyNotSupported:
+                               msg = Locale.GetText ("Property not supported [GDI+ status: {0}]", status);
+                               throw new NotSupportedException (msg);
+                       case Status.FileNotFound:
+                               msg = Locale.GetText ("Requested file was not found [GDI+ status: {0}]", status);
+                               throw new FileNotFoundException (msg);
+                       case Status.AccessDenied:
+                               msg = Locale.GetText ("Access to resource was denied [GDI+ status: {0}]", status);
+                               throw new UnauthorizedAccessException (msg);
+                       case Status.UnknownImageFormat:
+                               msg = Locale.GetText ("Either the image format is unknown or you don't have the required libraries to decode this format [GDI+ status: {0}]", status);
+                               throw new NotSupportedException (msg);
+                       case Status.NotImplemented:
+                               msg = Locale.GetText ("The requested feature is not implemented [GDI+ status: {0}]", status);
+                               throw new NotImplementedException (msg);
+                       case Status.WrongState:
+                               msg = Locale.GetText ("Object is not in a state that can allow this operation [GDI+ status: {0}]", status);
+                               throw new ArgumentException (msg);
+                       case Status.FontFamilyNotFound:
+                               msg = Locale.GetText ("The requested FontFamily could not be found [GDI+ status: {0}]", status);
+                               throw new ArgumentException (msg);
+                       case Status.ValueOverflow:
+                               msg = Locale.GetText ("Argument is out of range [GDI+ status: {0}]", status);
+                               throw new OverflowException (msg);
+                       case Status.Win32Error:
+                               msg = Locale.GetText ("The operation is invalid [GDI+ status: {0}]", status);
+                               throw new InvalidOperationException (msg);
+                       default:
+                               msg = Locale.GetText ("Unknown Error [GDI+ status: {0}]", status);
+                               throw new Exception (msg);
                        }
                }
                
-               
                // Memory functions
                [DllImport("gdiplus.dll")]
                static internal extern IntPtr GdipAlloc (int size);
@@ -914,9 +927,9 @@ namespace System.Drawing
                internal static extern Status GdipCreateFromHWND (IntPtr hwnd, out IntPtr graphics);
 
                [DllImport("gdiplus.dll", CharSet=CharSet.Unicode)]
-               internal static extern Status GdipMeasureString(IntPtr graphics, string str, int length, IntPtr font,
-                ref RectangleF layoutRect, IntPtr stringFormat, out RectangleF boundingBox, out int codepointsFitted,
-                               out int linesFilled);                                           
+               internal unsafe static extern Status GdipMeasureString(IntPtr graphics, string str, int length,
+                       IntPtr font, ref RectangleF layoutRect, IntPtr stringFormat, out RectangleF boundingBox,
+                       int *codepointsFitted, int *linesFilled);
                                
                [DllImport("gdiplus.dll", CharSet=CharSet.Unicode)]
                internal static extern Status GdipMeasureCharacterRanges (IntPtr graphics, string str, int length, IntPtr font,
@@ -980,6 +993,9 @@ namespace System.Drawing
                [DllImport("gdiplus.dll")]
                internal static extern Status GdipGetImageFlags(IntPtr image, out int flag);
 
+               [DllImport ("gdiplus.dll")]
+               internal static extern Status GdipGetImageType (IntPtr image, out ImageType type);
+
                [DllImport("gdiplus.dll")]
                internal static extern Status GdipImageGetFrameDimensionsCount ( IntPtr image, out uint count );
                                                                                                   
@@ -987,7 +1003,7 @@ namespace System.Drawing
                internal static extern Status GdipImageGetFrameDimensionsList ( IntPtr image, [Out] Guid [] dimensionIDs, uint count );
  
                [DllImport("gdiplus.dll")]
-               internal static extern Status GdipGetImageHeight (IntPtr image, out int height);
+               internal static extern Status GdipGetImageHeight (IntPtr image, out uint height);
                                                                                                   
                [DllImport("gdiplus.dll")]
                internal static extern Status GdipGetImageHorizontalResolution ( IntPtr image, out float resolution );
@@ -1038,7 +1054,7 @@ namespace System.Drawing
                internal static extern Status GdipGetEncoderParameterList ( IntPtr image, ref Guid encoder, uint size, IntPtr buffer );
                
                [DllImport("gdiplus.dll")]
-               internal static extern Status GdipImageGetFrameCount (IntPtr image, ref Guid guidDimension, out int count );
+               internal static extern Status GdipImageGetFrameCount (IntPtr image, ref Guid guidDimension, out uint count );
                
                [DllImport("gdiplus.dll")]
                internal static extern Status GdipImageSelectActiveFrame (IntPtr image, ref Guid guidDimension, int frameIndex);
@@ -1053,7 +1069,7 @@ namespace System.Drawing
                internal static extern Status GdipRemovePropertyItem (IntPtr image, int propertyId);
                
                [DllImport("gdiplus.dll")]
-               internal static extern Status GdipSetPropertyItem (IntPtr image, IntPtr propertyItem);
+               internal unsafe static extern Status GdipSetPropertyItem (IntPtr image, GdipPropertyItem *propertyItem);
                
                [DllImport("gdiplus.dll")]
                internal static extern Status GdipGetImageThumbnail ( IntPtr image, uint width, uint height, out IntPtr thumbImage, IntPtr callback, IntPtr callBackData );
@@ -1417,8 +1433,6 @@ namespace System.Drawing
 
                // These are our private functions, they exists in our own libgdiplus library, this way we
                // avoid relying on wine in System.Drawing
-               [DllImport("gdiplus.dll")]
-               internal static extern Status GdipGetHfont (IntPtr font, out IntPtr Hfont);     
                [DllImport("gdiplus.dll", CharSet=CharSet.Ansi)]                   
                internal static extern Status GdipCreateFontFromHfont(IntPtr hdc, out IntPtr font, ref LOGFONT lf);
 
@@ -1428,12 +1442,17 @@ namespace System.Drawing
                [DllImport("user32.dll", EntryPoint="GetDC", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
                internal static extern IntPtr GetDC(IntPtr hwnd);       
                [DllImport("user32.dll", EntryPoint="ReleaseDC", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
-               internal static extern int ReleaseDC(IntPtr hdc);
+               internal static extern int ReleaseDC (IntPtr hWnd, IntPtr hDC);
                [DllImport("gdi32.dll", EntryPoint="SelectObject", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
                internal static extern IntPtr SelectObject(IntPtr hdc, IntPtr obj);     
                [DllImport("user32.dll", SetLastError=true)]
                internal static extern bool GetIconInfo (IntPtr hIcon, out IconInfo iconinfo);
+               [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, SetLastError=true)]
+               internal static extern IntPtr CreateIconIndirect ([In] ref IconInfo piconinfo);
+               [DllImport("user32.dll", CallingConvention = CallingConvention.StdCall, SetLastError=true)]
+               internal static extern bool DestroyIcon (IntPtr hIcon);
+               [DllImport("gdi32.dll")]
+               internal static extern bool DeleteObject (IntPtr hObject);
                [DllImport("user32.dll")]
                internal static extern IntPtr GetDesktopWindow ();
 
@@ -1441,6 +1460,9 @@ namespace System.Drawing
                public static extern int BitBlt(IntPtr hdcDest, int nXDest, int nYDest, 
                        int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop);
 
+               [DllImport ("user32.dll", EntryPoint = "GetSysColor", CallingConvention = CallingConvention.StdCall)]
+               public static extern uint Win32GetSysColor (GetSysColorIndex index);
+
 
                // Some special X11 stuff
                [DllImport("libX11", EntryPoint="XOpenDisplay")]
@@ -1543,6 +1565,9 @@ namespace System.Drawing
                
                [DllImport ("gdiplus.dll")]
                internal static extern Status GdipGetFontHeightGivenDPI (IntPtr font, float dpi, out float height);
+
+               [DllImport ("gdiplus.dll")]
+               internal static extern Status GdipCloneFontFamily (IntPtr fontFamily, out IntPtr clone);
                
                
                // String Format
@@ -1587,6 +1612,55 @@ namespace System.Drawing
                 [DllImport ("gdiplus.dll")]
                 internal static extern Status GdipGetStringFormatTabStops(IntPtr format, int count, out float firstTabOffset, [In, Out] float [] tabStops);
                                
+               // metafile
+               [DllImport ("gdiplus.dll", CharSet = CharSet.Auto)]
+               internal static extern Status GdipCreateMetafileFromFile ([MarshalAs (UnmanagedType.LPWStr)] string filename, out IntPtr metafile);
+               [DllImport ("gdiplus.dll")]
+               internal static extern Status GdipCreateMetafileFromEmf (IntPtr hEmf, bool deleteEmf, out IntPtr metafile);
+               [DllImport ("gdiplus.dll")]
+               internal static extern Status GdipCreateMetafileFromWmf (IntPtr hWmf, bool deleteWmf, WmfPlaceableFileHeader wmfPlaceableFileHeader, out IntPtr metafile);
+               [DllImport ("gdiplus.dll", CharSet = CharSet.Auto)]
+               internal static extern Status GdipGetMetafileHeaderFromFile ([MarshalAs (UnmanagedType.LPWStr)] string filename, IntPtr header);
+               [DllImport ("gdiplus.dll")]
+               internal static extern Status GdipGetMetafileHeaderFromMetafile (IntPtr metafile, IntPtr header);
+               [DllImport ("gdiplus.dll")]
+               internal static extern Status GdipGetMetafileHeaderFromEmf (IntPtr hEmf, IntPtr header);
+               [DllImport ("gdiplus.dll")]
+               internal static extern Status GdipGetMetafileHeaderFromWmf (IntPtr hWmf, IntPtr wmfPlaceableFileHeader, IntPtr header);
+               [DllImport ("gdiplus.dll")]
+               internal static extern Status GdipGetHemfFromMetafile (IntPtr metafile, out IntPtr hEmf);
+               [DllImport ("gdiplus.dll")]
+               internal static extern Status GdipGetMetafileDownLevelRasterizationLimit (IntPtr metafile, ref uint metafileRasterizationLimitDpi);
+               [DllImport ("gdiplus.dll")]
+               internal static extern Status GdipSetMetafileDownLevelRasterizationLimit (IntPtr metafile, uint metafileRasterizationLimitDpi);
+               [DllImport ("gdiplus.dll")]
+               internal static extern Status GdipPlayMetafileRecord (IntPtr metafile, EmfPlusRecordType recordType, int flags, int dataSize, byte[] data);
+
+               [DllImport ("gdiplus.dll")]
+               internal static extern Status GdipRecordMetafile (IntPtr hdc, EmfType type, ref RectangleF frameRect, 
+                       MetafileFrameUnit frameUnit, [MarshalAs (UnmanagedType.LPWStr)] string description, out IntPtr metafile);
+               [DllImport ("gdiplus.dll")]
+               internal static extern Status GdipRecordMetafileI (IntPtr hdc, EmfType type, ref Rectangle frameRect, 
+                       MetafileFrameUnit frameUnit, [MarshalAs (UnmanagedType.LPWStr)] string description, out IntPtr metafile);
+               [DllImport ("gdiplus.dll")]
+               internal static extern Status GdipRecordMetafileFileName ([MarshalAs (UnmanagedType.LPWStr)] string filename, IntPtr hdc, EmfType type,
+                       ref RectangleF frameRect, MetafileFrameUnit frameUnit, [MarshalAs (UnmanagedType.LPWStr)] string description, out IntPtr metafile);
+               [DllImport ("gdiplus.dll")]
+               internal static extern Status GdipRecordMetafileFileNameI ([MarshalAs (UnmanagedType.LPWStr)] string filename, IntPtr hdc, EmfType type,
+                       ref Rectangle frameRect, MetafileFrameUnit frameUnit, [MarshalAs (UnmanagedType.LPWStr)] string description, out IntPtr metafile);
+#if !TEST
+               [DllImport("gdiplus.dll", ExactSpelling=true, CharSet=CharSet.Unicode)]
+               internal static extern Status GdipCreateMetafileFromStream([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(ComIStreamMarshaler))] IStream stream, out IntPtr metafile);
+               [DllImport("gdiplus.dll", ExactSpelling=true, CharSet=CharSet.Unicode)]
+               internal static extern Status GdipGetMetafileHeaderFromStream([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(ComIStreamMarshaler))] IStream stream, IntPtr header);
+
+               [DllImport ("gdiplus.dll")]
+               internal static extern Status GdipRecordMetafileStream ([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(ComIStreamMarshaler))] IStream stream, IntPtr hdc, 
+                       EmfType type, ref RectangleF frameRect, MetafileFrameUnit frameUnit, [MarshalAs (UnmanagedType.LPWStr)] string description, out IntPtr metafile);
+               [DllImport ("gdiplus.dll")]
+               internal static extern Status GdipRecordMetafileStreamI ([MarshalAs(UnmanagedType.CustomMarshaler, MarshalTypeRef=typeof(ComIStreamMarshaler))] IStream stream, IntPtr hdc, 
+                       EmfType type, ref Rectangle frameRect, MetafileFrameUnit frameUnit, [MarshalAs (UnmanagedType.LPWStr)] string description, out IntPtr metafile);
+#endif
                //ImageCodecInfo functions
                [DllImport("gdiplus.dll")]
                static internal extern Status GdipGetImageDecodersSize (out int decoderNums, out int arraySize);
@@ -1620,11 +1694,15 @@ namespace System.Drawing
                        private byte[]  start_buf;
                        private int     start_buf_pos;
                        private int     start_buf_len;
+                       private byte[]  managedBuf;
+                       private const int default_bufsize = 4096;
                        
-                       public GdiPlusStreamHelper (Stream s) 
+                       public GdiPlusStreamHelper (Stream s, bool seekToOrigin
                        { 
+                               managedBuf = new byte [default_bufsize];
+                               
                                stream = s;
-                               if (stream != null && stream.CanSeek) {
+                               if (stream != null && stream.CanSeek && seekToOrigin) {
                                        stream.Seek (0, SeekOrigin.Begin);
                                }
                        }
@@ -1668,7 +1746,8 @@ namespace System.Drawing
                                        return -1;
                                }
 
-                               byte[] managedBuf = new byte[bufsz];
+                               if (bufsz > managedBuf.Length)
+                                       managedBuf = new byte[bufsz];
                                int bytesRead = 0;
                                long streamPosition = 0;
 
@@ -1776,7 +1855,8 @@ namespace System.Drawing
 
                        public int StreamPutBytesImpl (IntPtr buf, int bufsz) 
                        {
-                               byte[] managedBuf = new byte[bufsz];
+                               if (bufsz > managedBuf.Length)
+                                       managedBuf = new byte[bufsz];
                                Marshal.Copy (buf, managedBuf, 0, bufsz);
                                stream.Write (managedBuf, 0, bufsz);
                                return bufsz;
@@ -1845,14 +1925,38 @@ namespace System.Drawing
                [DllImport("gdiplus.dll")]
                internal static extern Status GdipCreateFromXDrawable_linux (IntPtr drawable, IntPtr display, out IntPtr graphics);
                
-               // Stream functions for non-Win32 (libgdiplus specific(
+               // Stream functions for non-Win32 (libgdiplus specific)
+               [DllImport("gdiplus.dll")]
+               static internal extern Status GdipLoadImageFromDelegate_linux (StreamGetHeaderDelegate getHeader, 
+                       StreamGetBytesDelegate getBytes, StreamPutBytesDelegate putBytes, StreamSeekDelegate doSeek, 
+                       StreamCloseDelegate close, StreamSizeDelegate size, out IntPtr image);
+
                [DllImport("gdiplus.dll")]
-               static internal extern Status GdipLoadImageFromDelegate_linux ( StreamGetHeaderDelegate getHeader, StreamGetBytesDelegate getBytes, StreamPutBytesDelegate putBytes, 
-                                                       StreamSeekDelegate doSeek, StreamCloseDelegate close, StreamSizeDelegate size, out IntPtr image);
+               static internal extern Status GdipSaveImageToDelegate_linux (IntPtr image, StreamGetBytesDelegate getBytes, 
+                       StreamPutBytesDelegate putBytes, StreamSeekDelegate doSeek, StreamCloseDelegate close, 
+                       StreamSizeDelegate size, ref Guid encoderClsID, IntPtr encoderParameters);              
+
                [DllImport("gdiplus.dll")]
-               static internal extern Status GdipSaveImageToDelegate_linux ( IntPtr image, StreamGetBytesDelegate getBytes, StreamPutBytesDelegate putBytes, 
-                       StreamSeekDelegate doSeek, StreamCloseDelegate close, StreamSizeDelegate size, ref Guid encoderClsID, IntPtr encoderParameters );               
-               
+               static internal extern Status GdipCreateMetafileFromDelegate_linux (StreamGetHeaderDelegate getHeader, 
+                       StreamGetBytesDelegate getBytes, StreamPutBytesDelegate putBytes, StreamSeekDelegate doSeek, 
+                       StreamCloseDelegate close, StreamSizeDelegate size, out IntPtr metafile);
+
+               [DllImport("gdiplus.dll")]
+               static internal extern Status GdipGetMetafileHeaderFromDelegate_linux (StreamGetHeaderDelegate getHeader, 
+                       StreamGetBytesDelegate getBytes, StreamPutBytesDelegate putBytes, StreamSeekDelegate doSeek, 
+                       StreamCloseDelegate close, StreamSizeDelegate size, IntPtr header);
+
+               [DllImport("gdiplus.dll")]
+               static internal extern Status GdipRecordMetafileFromDelegate_linux (StreamGetHeaderDelegate getHeader, 
+                       StreamGetBytesDelegate getBytes, StreamPutBytesDelegate putBytes, StreamSeekDelegate doSeek, 
+                       StreamCloseDelegate close, StreamSizeDelegate size, IntPtr hdc, EmfType type, ref RectangleF frameRect, 
+                       MetafileFrameUnit frameUnit, [MarshalAs (UnmanagedType.LPWStr)] string description, out IntPtr metafile);
+
+               [DllImport("gdiplus.dll")]
+               static internal extern Status GdipRecordMetafileFromDelegateI_linux (StreamGetHeaderDelegate getHeader, 
+                       StreamGetBytesDelegate getBytes, StreamPutBytesDelegate putBytes, StreamSeekDelegate doSeek, 
+                       StreamCloseDelegate close, StreamSizeDelegate size, IntPtr hdc, EmfType type, ref Rectangle frameRect, 
+                       MetafileFrameUnit frameUnit, [MarshalAs (UnmanagedType.LPWStr)] string description, out IntPtr metafile);
 #endregion
        }
 }