"Fossies" - the Fresh Open Source Software Archive

Member "mono-6.12.0.122/mcs/class/System.Drawing/System.Drawing.Imaging/Metafile.cs" (22 Feb 2021, 19489 Bytes) of package /linux/misc/mono-sources/mono/mono-6.12.0.122.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C# source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 //
    2 // System.Drawing.Imaging.Metafile.cs
    3 //
    4 // Authors:
    5 //  Christian Meyer, eMail: Christian.Meyer@cs.tum.edu
    6 //  Dennis Hayes (dennish@raytek.com)
    7 //  Sebastien Pouliot  <sebastien@ximian.com>
    8 //
    9 // (C) 2002 Ximian, Inc.  http://www.ximian.com
   10 // Copyright (C) 2004,2006-2007 Novell, Inc (http://www.novell.com)
   11 //
   12 // Permission is hereby granted, free of charge, to any person obtaining
   13 // a copy of this software and associated documentation files (the
   14 // "Software"), to deal in the Software without restriction, including
   15 // without limitation the rights to use, copy, modify, merge, publish,
   16 // distribute, sublicense, and/or sell copies of the Software, and to
   17 // permit persons to whom the Software is furnished to do so, subject to
   18 // the following conditions:
   19 // 
   20 // The above copyright notice and this permission notice shall be
   21 // included in all copies or substantial portions of the Software.
   22 // 
   23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
   24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
   25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
   26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
   27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
   28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
   29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   30 //
   31 
   32 using System.IO;
   33 using System.Reflection;
   34 using System.ComponentModel;
   35 using System.Runtime.InteropServices;
   36 
   37 namespace System.Drawing.Imaging {
   38 
   39     [MonoTODO ("Metafiles, both WMF and EMF formats, are only partially supported.")]
   40     [Serializable]
   41     [Editor ("System.Drawing.Design.MetafileEditor, " + Consts.AssemblySystem_Drawing_Design, typeof (System.Drawing.Design.UITypeEditor))]
   42     public sealed class Metafile : Image {
   43 
   44         // Non-null if a graphics instance was created using
   45         // Graphics.FromImage(this) The metadata holder is responsible for
   46         // freeing the nativeImage if the Metadata instance is disposed before
   47         // the Graphics instance.
   48         private MetafileHolder _metafileHolder;
   49 
   50         // A class responsible for disposing of the native Metafile instance
   51         // if it needs to outlive the managed Metafile instance.
   52         //
   53         // The following are both legal with win32 GDI+:
   54         //     Metafile mf = ...; // get a metafile instance
   55         //     Graphics g = Graphics.FromImage(mf); // get a graphics instance
   56         //     g.Dispose();  mf.Dispose(); // dispose of the graphics instance first
   57         //   OR
   58         //     mf.Dispose(); g.Dispose();  // dispose of the metafile instance first
   59         //
   60         // ligbgdiplus has a bug where disposing of the metafile instance first will
   61         // trigger a use of freed memory when the graphics instance is disposed, which
   62         // could lead to crashes when the native memory is reused.
   63         //
   64         // The metafile holder is designed to take ownership of the native metafile image
   65         // when the managed Metafile instance is disposed while a Graphics instance is still
   66         // not disposed (ie the second code pattern above) and to keep the native image alive until the graphics
   67         // instance is disposed.
   68         //
   69         // Note that the following throws, so we only ever need to keep track of one Graphics
   70         // instance at a time:
   71         //  Metafile mf = ...;  // get a metafile instance
   72         //  Graphics g = Graphics.FromImage(mf);
   73         //  Graphics g2 = Graphics.FromImage(mf);  // throws OutOfMemoryException on GDI+ on Win32
   74         internal sealed class MetafileHolder : IDisposable
   75         {
   76             private bool _disposed;
   77             private IntPtr _nativeImage;
   78 
   79 
   80             internal bool Disposed { get => _disposed; }
   81             internal MetafileHolder()
   82             {
   83                 _disposed = false;
   84                 _nativeImage = IntPtr.Zero;
   85             }
   86 
   87             ~MetafileHolder() => Dispose(false);
   88 
   89             public void Dispose()
   90             {
   91                 Dispose(true);
   92                 GC.SuppressFinalize(this);
   93             }
   94 
   95             internal void Dispose(bool disposing)
   96             {
   97                 if (!_disposed)
   98                 {
   99                     IntPtr nativeImage = _nativeImage;
  100                     _nativeImage = IntPtr.Zero;
  101                     _disposed = true;
  102                     if (nativeImage != IntPtr.Zero)
  103                     {
  104                         Status status = GDIPlus.GdipDisposeImage(nativeImage);
  105                         GDIPlus.CheckStatus(status);
  106                     }
  107                 }
  108             }
  109 
  110             internal void MetafileDisposed(IntPtr nativeImage)
  111             {
  112                 _nativeImage = nativeImage;
  113             }
  114 
  115             internal void GraphicsDisposed()
  116             {
  117                 Dispose();
  118             }
  119         }
  120 
  121         internal MetafileHolder AddMetafileHolder()
  122         {
  123             // If _metafileHolder is not null and hasn't been disposed yet, there's already a graphics instance associated with
  124             // this metafile, the native code will return an error status.
  125             if (_metafileHolder != null && !_metafileHolder.Disposed)
  126                 return null;
  127             _metafileHolder = new MetafileHolder();
  128             return _metafileHolder;
  129         }
  130 
  131         // constructors
  132 
  133         internal Metafile (IntPtr ptr)
  134         {
  135             nativeObject = ptr;
  136         }
  137 
  138         // Usually called when cloning images that need to have
  139         // not only the handle saved, but also the underlying stream
  140         // (when using MS GDI+ and IStream we must ensure the stream stays alive for all the life of the Image)
  141         internal Metafile (IntPtr ptr, Stream stream)
  142         {
  143             // under Win32 stream is owned by SD/GDI+ code
  144             if (GDIPlus.RunningOnWindows ())
  145                 this.stream = stream;
  146             nativeObject = ptr;
  147         }
  148 
  149         public Metafile (Stream stream) 
  150         {
  151             if (stream == null)
  152                 throw new ArgumentException ("stream");
  153 
  154             Status status;
  155             if (GDIPlus.RunningOnUnix ()) {
  156                 // With libgdiplus we use a custom API for this, because there's no easy way
  157                 // to get the Stream down to libgdiplus. So, we wrap the stream with a set of delegates.
  158                 GDIPlus.GdiPlusStreamHelper sh = new GDIPlus.GdiPlusStreamHelper (stream, false);
  159                 status = GDIPlus.GdipCreateMetafileFromDelegate_linux (sh.GetHeaderDelegate, sh.GetBytesDelegate, 
  160                     sh.PutBytesDelegate, sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, out nativeObject);
  161             } else {
  162                 status = GDIPlus.GdipCreateMetafileFromStream (new ComIStreamWrapper (stream), out nativeObject);
  163             }
  164             GDIPlus.CheckStatus (status);
  165         }
  166 
  167         public Metafile (string filename) 
  168         {
  169             if (filename == null)
  170                 throw new ArgumentNullException ("filename");
  171             if (filename.Length == 0)
  172                 throw new ArgumentException ("filename");
  173 
  174             Status status = GDIPlus.GdipCreateMetafileFromFile (filename, out nativeObject);
  175             if (status == Status.GenericError)
  176                 throw new ExternalException ("Couldn't load specified file.");
  177             GDIPlus.CheckStatus (status);
  178         }
  179 
  180         public Metafile (IntPtr henhmetafile, bool deleteEmf) 
  181         {
  182             Status status = GDIPlus.GdipCreateMetafileFromEmf (henhmetafile, deleteEmf, out nativeObject);
  183             GDIPlus.CheckStatus (status);
  184         }
  185 
  186         public Metafile (IntPtr referenceHdc, EmfType emfType) :
  187             this (referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, emfType, null)
  188         {
  189         }
  190 
  191         public Metafile (IntPtr referenceHdc, Rectangle frameRect) :
  192             this (referenceHdc, frameRect, MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
  193         {
  194         }
  195 
  196         public Metafile (IntPtr referenceHdc, RectangleF frameRect) :
  197             this (referenceHdc, frameRect, MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
  198         {
  199         }
  200 
  201         public Metafile (IntPtr hmetafile, WmfPlaceableFileHeader wmfHeader) 
  202         {
  203             Status status = GDIPlus.GdipCreateMetafileFromEmf (hmetafile, false, out nativeObject);
  204             GDIPlus.CheckStatus (status);
  205         }
  206 
  207         public Metafile (Stream stream, IntPtr referenceHdc) :
  208             this (stream, referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
  209         {
  210         }
  211 
  212         public Metafile (string fileName, IntPtr referenceHdc) :
  213             this (fileName, referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual,
  214             null)
  215         {
  216         }
  217 
  218         public Metafile (IntPtr referenceHdc, EmfType emfType, string description) :
  219             this (referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, emfType, description)
  220         {
  221         }
  222 
  223         public Metafile (IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit) :
  224             this (referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, null)
  225         {
  226         }
  227 
  228         public Metafile (IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit) :
  229             this (referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, null)
  230         {
  231         }
  232 
  233         public Metafile (IntPtr hmetafile, WmfPlaceableFileHeader wmfHeader, bool deleteWmf) 
  234         {
  235             Status status = GDIPlus.GdipCreateMetafileFromEmf (hmetafile, deleteWmf, out nativeObject);
  236             GDIPlus.CheckStatus (status);
  237         }
  238 
  239         public Metafile (Stream stream, IntPtr referenceHdc, EmfType type) :
  240             this (stream, referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, type, null)
  241         {
  242         }
  243 
  244         public Metafile (Stream stream, IntPtr referenceHdc, Rectangle frameRect) :
  245             this (stream, referenceHdc, frameRect, MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
  246         {
  247         }
  248 
  249         public Metafile (Stream stream, IntPtr referenceHdc, RectangleF frameRect) :
  250             this (stream, referenceHdc, frameRect, MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
  251         {
  252         }
  253 
  254         public Metafile (string fileName, IntPtr referenceHdc, EmfType type) :
  255             this (fileName, referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, type, null)
  256         {
  257         }
  258 
  259         public Metafile (string fileName, IntPtr referenceHdc, Rectangle frameRect) :
  260             this (fileName, referenceHdc, frameRect, MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
  261         {
  262         }
  263         
  264         public Metafile (string fileName, IntPtr referenceHdc, RectangleF frameRect) :
  265             this (fileName, referenceHdc, frameRect, MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
  266         {
  267         }
  268 
  269         public Metafile (IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit, EmfType type) :
  270             this (referenceHdc, frameRect, frameUnit, type, null)
  271         {
  272         }
  273 
  274         public Metafile (IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit, EmfType type) :
  275             this (referenceHdc, frameRect, frameUnit, type, null)
  276         {
  277         }
  278 
  279         public Metafile (Stream stream, IntPtr referenceHdc, EmfType type, string description) :
  280             this (stream, referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, type, description)
  281         {
  282         }
  283 
  284         public Metafile (Stream stream, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit) :
  285             this (stream, referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, null)
  286         {
  287         }
  288 
  289         public Metafile (Stream stream, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit) :
  290             this (stream, referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, null)
  291         {
  292         }
  293 
  294         public Metafile (string fileName, IntPtr referenceHdc, EmfType type, string description) :
  295             this (fileName, referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, type, description)
  296         {
  297         }
  298 
  299         public Metafile (string fileName, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit) :
  300             this (fileName, referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, null)
  301         {
  302         }
  303         
  304         public Metafile (string fileName, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit) :
  305             this (fileName, referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, null)
  306         {
  307         }
  308 
  309         public Metafile (IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit, EmfType type,
  310             string desc)
  311         {
  312             Status status = GDIPlus.GdipRecordMetafileI (referenceHdc, type, ref frameRect, frameUnit,
  313                 desc, out nativeObject);
  314             GDIPlus.CheckStatus (status);
  315         }
  316 
  317         public Metafile (IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit, EmfType type,
  318             string description)
  319         {
  320             Status status = GDIPlus.GdipRecordMetafile (referenceHdc, type, ref frameRect, frameUnit,
  321                 description, out nativeObject);
  322             GDIPlus.CheckStatus (status);
  323         }
  324 
  325         public Metafile (Stream stream, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit,
  326             EmfType type) : this (stream, referenceHdc, frameRect, frameUnit, type, null)
  327         {
  328         }
  329 
  330         public Metafile (Stream stream, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit,
  331             EmfType type) : this (stream, referenceHdc, frameRect, frameUnit, type, null)
  332         {
  333         }
  334 
  335         public Metafile (string fileName, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit,
  336             EmfType type) : this (fileName, referenceHdc, frameRect, frameUnit, type, null)
  337         {
  338         }
  339         
  340         public Metafile (string fileName, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit,
  341             string description) : this (fileName, referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, description)
  342         {
  343         }
  344 
  345         public Metafile (string fileName, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit,
  346             EmfType type) : this (fileName, referenceHdc, frameRect, frameUnit, type, null)
  347         {
  348         }
  349         
  350         public Metafile (string fileName, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit, 
  351             string desc) : this (fileName, referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual,
  352             desc) 
  353         {
  354         }
  355         
  356         public Metafile (Stream stream, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit, 
  357             EmfType type, string description) 
  358         {
  359             if (stream == null)
  360                 throw new NullReferenceException ("stream");
  361 
  362             Status status = Status.NotImplemented;
  363             if (GDIPlus.RunningOnUnix ()) {
  364                 // With libgdiplus we use a custom API for this, because there's no easy way
  365                 // to get the Stream down to libgdiplus. So, we wrap the stream with a set of delegates.
  366                 GDIPlus.GdiPlusStreamHelper sh = new GDIPlus.GdiPlusStreamHelper (stream, false);
  367                 status = GDIPlus.GdipRecordMetafileFromDelegateI_linux (sh.GetHeaderDelegate, sh.GetBytesDelegate, 
  368                     sh.PutBytesDelegate, sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, referenceHdc, 
  369                     type, ref frameRect, frameUnit, description, out nativeObject);
  370             } else {
  371                 status = GDIPlus.GdipRecordMetafileStreamI (new ComIStreamWrapper (stream), referenceHdc, 
  372                     type, ref frameRect, frameUnit, description, out nativeObject);
  373             }
  374             GDIPlus.CheckStatus (status);
  375         }
  376 
  377         public Metafile (Stream stream, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit, 
  378             EmfType type, string description) 
  379         {
  380             if (stream == null)
  381                 throw new NullReferenceException ("stream");
  382 
  383             Status status = Status.NotImplemented;
  384             if (GDIPlus.RunningOnUnix ()) {
  385                 // With libgdiplus we use a custom API for this, because there's no easy way
  386                 // to get the Stream down to libgdiplus. So, we wrap the stream with a set of delegates.
  387                 GDIPlus.GdiPlusStreamHelper sh = new GDIPlus.GdiPlusStreamHelper (stream, false);
  388                 status = GDIPlus.GdipRecordMetafileFromDelegate_linux (sh.GetHeaderDelegate, sh.GetBytesDelegate, 
  389                     sh.PutBytesDelegate, sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, referenceHdc, 
  390                     type, ref frameRect, frameUnit, description, out nativeObject);
  391             } else {
  392                 status = GDIPlus.GdipRecordMetafileStream (new ComIStreamWrapper (stream), referenceHdc, 
  393                     type, ref frameRect, frameUnit, description, out nativeObject);
  394             }
  395             GDIPlus.CheckStatus (status);
  396         }
  397 
  398         public Metafile (string fileName, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit, 
  399             EmfType type, string description) 
  400         {
  401             Status status = GDIPlus.GdipRecordMetafileFileNameI (fileName, referenceHdc, type, ref frameRect, 
  402                 frameUnit, description, out nativeObject);
  403             GDIPlus.CheckStatus (status);
  404         }
  405         
  406         public Metafile (string fileName, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit,
  407             EmfType type, string description) 
  408         {
  409             Status status = GDIPlus.GdipRecordMetafileFileName (fileName, referenceHdc, type, ref frameRect, frameUnit, 
  410                 description, out nativeObject);
  411             GDIPlus.CheckStatus (status);
  412         }
  413 
  414         protected override void Dispose(bool disposing)
  415         {
  416             if (_metafileHolder != null && !_metafileHolder.Disposed)
  417             {
  418                 // There's a graphics instance created from this Metafile,
  419                 // transfer responsibility for disposing the nativeImage to the
  420                 // MetafileHolder
  421                 _metafileHolder.MetafileDisposed(nativeObject);
  422                 _metafileHolder = null;
  423                 nativeObject = IntPtr.Zero;
  424             }
  425 
  426             base.Dispose(disposing);
  427         }
  428 
  429         // methods
  430 
  431         public IntPtr GetHenhmetafile ()
  432         {
  433             return nativeObject;
  434         }
  435 
  436         [MonoLimitation ("Metafiles aren't only partially supported by libgdiplus.")]
  437         public MetafileHeader GetMetafileHeader ()
  438         {
  439             IntPtr header = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (MetafileHeader)));
  440             try {
  441                 Status status = GDIPlus.GdipGetMetafileHeaderFromMetafile (nativeObject, header);
  442                 GDIPlus.CheckStatus (status);
  443                 return new MetafileHeader (header);
  444             }
  445             finally {
  446                 Marshal.FreeHGlobal (header);
  447             }
  448         }
  449 
  450         [MonoLimitation ("Metafiles aren't only partially supported by libgdiplus.")]
  451         public static MetafileHeader GetMetafileHeader (IntPtr henhmetafile)
  452         {
  453             IntPtr header = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (MetafileHeader)));
  454             try {
  455                 Status status = GDIPlus.GdipGetMetafileHeaderFromEmf (henhmetafile, header);
  456                 GDIPlus.CheckStatus (status);
  457                 return new MetafileHeader (header);
  458             }
  459             finally {
  460                 Marshal.FreeHGlobal (header);
  461             }
  462         }
  463 
  464         [MonoLimitation ("Metafiles aren't only partially supported by libgdiplus.")]
  465         public static MetafileHeader GetMetafileHeader (Stream stream)
  466         {
  467             if (stream == null)
  468                 throw new NullReferenceException ("stream");
  469 
  470             IntPtr header = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (MetafileHeader)));
  471             try {
  472                 Status status;
  473 
  474                 if (GDIPlus.RunningOnUnix ()) {
  475                     // With libgdiplus we use a custom API for this, because there's no easy way
  476                     // to get the Stream down to libgdiplus. So, we wrap the stream with a set of delegates.
  477                     GDIPlus.GdiPlusStreamHelper sh = new GDIPlus.GdiPlusStreamHelper (stream, false);
  478                     status = GDIPlus.GdipGetMetafileHeaderFromDelegate_linux (sh.GetHeaderDelegate, 
  479                         sh.GetBytesDelegate, sh.PutBytesDelegate, sh.SeekDelegate, sh.CloseDelegate, 
  480                         sh.SizeDelegate, header);
  481                 } else {
  482                     status = GDIPlus.GdipGetMetafileHeaderFromStream (new ComIStreamWrapper (stream), header);
  483                 }
  484                 GDIPlus.CheckStatus (status);
  485                 return new MetafileHeader (header);
  486             }
  487             finally {
  488                 Marshal.FreeHGlobal (header);
  489             }
  490         }
  491 
  492         [MonoLimitation ("Metafiles aren't only partially supported by libgdiplus.")]
  493         public static MetafileHeader GetMetafileHeader (string fileName)
  494         {
  495             if (fileName == null)
  496                 throw new ArgumentNullException ("fileName");
  497 
  498             IntPtr header = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (MetafileHeader)));
  499             try {
  500                 Status status = GDIPlus.GdipGetMetafileHeaderFromFile (fileName, header);
  501                 GDIPlus.CheckStatus (status);
  502                 return new MetafileHeader (header);
  503             }
  504             finally {
  505                 Marshal.FreeHGlobal (header);
  506             }
  507         }
  508 
  509         [MonoLimitation ("Metafiles aren't only partially supported by libgdiplus.")]
  510         public static MetafileHeader GetMetafileHeader (IntPtr hmetafile, WmfPlaceableFileHeader wmfHeader)
  511         {
  512             IntPtr header = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (MetafileHeader)));
  513             try {
  514                 Status status = GDIPlus.GdipGetMetafileHeaderFromEmf (hmetafile, header);
  515                 GDIPlus.CheckStatus (status);
  516                 return new MetafileHeader (header);
  517             }
  518             finally {
  519                 Marshal.FreeHGlobal (header);
  520             }
  521         }
  522 
  523         [MonoLimitation ("Metafiles aren't only partially supported by libgdiplus.")]
  524         public void PlayRecord (EmfPlusRecordType recordType, int flags, int dataSize, byte[] data)
  525         {
  526             Status status = GDIPlus.GdipPlayMetafileRecord (nativeObject, recordType, flags, dataSize, data);
  527             GDIPlus.CheckStatus (status);
  528         }
  529     }
  530 }