2 // System.Drawing.Imaging.Metafile.cs
5 // Christian Meyer, eMail: Christian.Meyer@cs.tum.edu
6 // Dennis Hayes (dennish@raytek.com)
7 // Sebastien Pouliot <sebastien@ximian.com>
9 // (C) 2002 Ximian, Inc. http://www.ximian.com
10 // Copyright (C) 2004,2006-2007 Novell, Inc (http://www.novell.com)
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:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
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.
33 using System.Reflection;
34 using System.ComponentModel;
35 using System.Runtime.InteropServices;
37 namespace System.Drawing.Imaging {
39 [MonoTODO ("Metafiles, both WMF and EMF formats, are only partially supported.")]
44 [Editor ("System.Drawing.Design.MetafileEditor, " + Consts.AssemblySystem_Drawing_Design, typeof (System.Drawing.Design.UITypeEditor))]
45 public sealed class Metafile : Image {
49 internal Metafile (IntPtr ptr)
54 public Metafile (Stream stream)
57 throw new ArgumentException ("stream");
60 if (GDIPlus.RunningOnUnix ()) {
61 // With libgdiplus we use a custom API for this, because there's no easy way
62 // to get the Stream down to libgdiplus. So, we wrap the stream with a set of delegates.
63 GDIPlus.GdiPlusStreamHelper sh = new GDIPlus.GdiPlusStreamHelper (stream, false);
64 status = GDIPlus.GdipCreateMetafileFromDelegate_linux (sh.GetHeaderDelegate, sh.GetBytesDelegate,
65 sh.PutBytesDelegate, sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, out nativeObject);
67 status = GDIPlus.GdipCreateMetafileFromStream (new ComIStreamWrapper (stream), out nativeObject);
69 GDIPlus.CheckStatus (status);
72 public Metafile (string filename)
75 throw new ArgumentNullException ("filename");
76 if (filename.Length == 0)
77 throw new ArgumentException ("filename");
79 Status status = GDIPlus.GdipCreateMetafileFromFile (filename, out nativeObject);
80 if (status == Status.GenericError)
81 throw new ExternalException ("Couldn't load specified file.");
82 GDIPlus.CheckStatus (status);
85 public Metafile (IntPtr henhmetafile, bool deleteEmf)
87 Status status = GDIPlus.GdipCreateMetafileFromEmf (henhmetafile, deleteEmf, out nativeObject);
88 GDIPlus.CheckStatus (status);
91 public Metafile (IntPtr referenceHdc, EmfType emfType) :
92 this (referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, emfType, null)
96 public Metafile (IntPtr referenceHdc, Rectangle frameRect) :
97 this (referenceHdc, frameRect, MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
101 public Metafile (IntPtr referenceHdc, RectangleF frameRect) :
102 this (referenceHdc, frameRect, MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
106 public Metafile (IntPtr hmetafile, WmfPlaceableFileHeader wmfHeader)
108 Status status = GDIPlus.GdipCreateMetafileFromEmf (hmetafile, false, out nativeObject);
109 GDIPlus.CheckStatus (status);
112 public Metafile (Stream stream, IntPtr referenceHdc) :
113 this (stream, referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
117 public Metafile (string fileName, IntPtr referenceHdc) :
118 this (fileName, referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual,
123 public Metafile (IntPtr referenceHdc, EmfType emfType, string description) :
124 this (referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, emfType, description)
128 public Metafile (IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit) :
129 this (referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, null)
133 public Metafile (IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit) :
134 this (referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, null)
138 public Metafile (IntPtr hmetafile, WmfPlaceableFileHeader wmfHeader, bool deleteWmf)
140 Status status = GDIPlus.GdipCreateMetafileFromEmf (hmetafile, deleteWmf, out nativeObject);
141 GDIPlus.CheckStatus (status);
144 public Metafile (Stream stream, IntPtr referenceHdc, EmfType type) :
145 this (stream, referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, type, null)
149 public Metafile (Stream stream, IntPtr referenceHdc, Rectangle frameRect) :
150 this (stream, referenceHdc, frameRect, MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
154 public Metafile (Stream stream, IntPtr referenceHdc, RectangleF frameRect) :
155 this (stream, referenceHdc, frameRect, MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
159 public Metafile (string fileName, IntPtr referenceHdc, EmfType type) :
160 this (fileName, referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, type, null)
164 public Metafile (string fileName, IntPtr referenceHdc, Rectangle frameRect) :
165 this (fileName, referenceHdc, frameRect, MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
169 public Metafile (string fileName, IntPtr referenceHdc, RectangleF frameRect) :
170 this (fileName, referenceHdc, frameRect, MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
174 public Metafile (IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit, EmfType type) :
175 this (referenceHdc, frameRect, frameUnit, type, null)
179 public Metafile (IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit, EmfType type) :
180 this (referenceHdc, frameRect, frameUnit, type, null)
184 public Metafile (Stream stream, IntPtr referenceHdc, EmfType type, string description) :
185 this (stream, referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, type, description)
189 public Metafile (Stream stream, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit) :
190 this (stream, referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, null)
194 public Metafile (Stream stream, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit) :
195 this (stream, referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, null)
199 public Metafile (string fileName, IntPtr referenceHdc, EmfType type, string description) :
200 this (fileName, referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, type, description)
204 public Metafile (string fileName, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit) :
205 this (fileName, referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, null)
209 public Metafile (string fileName, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit) :
210 this (fileName, referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, null)
214 public Metafile (IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit, EmfType type,
217 Status status = GDIPlus.GdipRecordMetafileI (referenceHdc, type, ref frameRect, frameUnit,
218 description, out nativeObject);
219 GDIPlus.CheckStatus (status);
222 public Metafile (IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit, EmfType type,
225 Status status = GDIPlus.GdipRecordMetafile (referenceHdc, type, ref frameRect, frameUnit,
226 description, out nativeObject);
227 GDIPlus.CheckStatus (status);
230 public Metafile (Stream stream, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit,
231 EmfType type) : this (stream, referenceHdc, frameRect, frameUnit, type, null)
235 public Metafile (Stream stream, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit,
236 EmfType type) : this (stream, referenceHdc, frameRect, frameUnit, type, null)
240 public Metafile (string fileName, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit,
241 EmfType type) : this (fileName, referenceHdc, frameRect, frameUnit, type, null)
245 public Metafile (string fileName, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit,
246 string description) : this (fileName, referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, description)
250 public Metafile (string fileName, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit,
251 EmfType type) : this (fileName, referenceHdc, frameRect, frameUnit, type, null)
255 public Metafile (string fileName, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit,
256 string description) : this (fileName, referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual,
261 public Metafile (Stream stream, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit,
262 EmfType type, string description)
265 throw new NullReferenceException ("stream");
267 Status status = Status.NotImplemented;
268 if (GDIPlus.RunningOnUnix ()) {
269 // With libgdiplus we use a custom API for this, because there's no easy way
270 // to get the Stream down to libgdiplus. So, we wrap the stream with a set of delegates.
271 GDIPlus.GdiPlusStreamHelper sh = new GDIPlus.GdiPlusStreamHelper (stream, false);
272 status = GDIPlus.GdipRecordMetafileFromDelegateI_linux (sh.GetHeaderDelegate, sh.GetBytesDelegate,
273 sh.PutBytesDelegate, sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, referenceHdc,
274 type, ref frameRect, frameUnit, description, out nativeObject);
276 status = GDIPlus.GdipRecordMetafileStreamI (new ComIStreamWrapper (stream), referenceHdc,
277 type, ref frameRect, frameUnit, description, out nativeObject);
279 GDIPlus.CheckStatus (status);
282 public Metafile (Stream stream, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit,
283 EmfType type, string description)
286 throw new NullReferenceException ("stream");
288 Status status = Status.NotImplemented;
289 if (GDIPlus.RunningOnUnix ()) {
290 // With libgdiplus we use a custom API for this, because there's no easy way
291 // to get the Stream down to libgdiplus. So, we wrap the stream with a set of delegates.
292 GDIPlus.GdiPlusStreamHelper sh = new GDIPlus.GdiPlusStreamHelper (stream, false);
293 status = GDIPlus.GdipRecordMetafileFromDelegate_linux (sh.GetHeaderDelegate, sh.GetBytesDelegate,
294 sh.PutBytesDelegate, sh.SeekDelegate, sh.CloseDelegate, sh.SizeDelegate, referenceHdc,
295 type, ref frameRect, frameUnit, description, out nativeObject);
297 status = GDIPlus.GdipRecordMetafileStream (new ComIStreamWrapper (stream), referenceHdc,
298 type, ref frameRect, frameUnit, description, out nativeObject);
300 GDIPlus.CheckStatus (status);
303 public Metafile (string fileName, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit,
304 EmfType type, string description)
306 Status status = GDIPlus.GdipRecordMetafileFileNameI (fileName, referenceHdc, type, ref frameRect,
307 frameUnit, description, out nativeObject);
308 GDIPlus.CheckStatus (status);
311 public Metafile (string fileName, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit,
312 EmfType type, string description)
314 Status status = GDIPlus.GdipRecordMetafileFileName (fileName, referenceHdc, type, ref frameRect, frameUnit,
315 description, out nativeObject);
316 GDIPlus.CheckStatus (status);
321 public IntPtr GetHenhmetafile ()
326 [MonoLimitation ("Metafiles aren't only partially supported by libgdiplus.")]
327 public MetafileHeader GetMetafileHeader ()
329 IntPtr header = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (MetafileHeader)));
331 Status status = GDIPlus.GdipGetMetafileHeaderFromMetafile (nativeObject, header);
332 GDIPlus.CheckStatus (status);
333 return new MetafileHeader (header);
336 Marshal.FreeHGlobal (header);
340 [MonoLimitation ("Metafiles aren't only partially supported by libgdiplus.")]
341 public static MetafileHeader GetMetafileHeader (IntPtr henhmetafile)
343 IntPtr header = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (MetafileHeader)));
345 Status status = GDIPlus.GdipGetMetafileHeaderFromEmf (henhmetafile, header);
346 GDIPlus.CheckStatus (status);
347 return new MetafileHeader (header);
350 Marshal.FreeHGlobal (header);
354 [MonoLimitation ("Metafiles aren't only partially supported by libgdiplus.")]
355 public static MetafileHeader GetMetafileHeader (Stream stream)
358 throw new NullReferenceException ("stream");
360 IntPtr header = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (MetafileHeader)));
364 if (GDIPlus.RunningOnUnix ()) {
365 // With libgdiplus we use a custom API for this, because there's no easy way
366 // to get the Stream down to libgdiplus. So, we wrap the stream with a set of delegates.
367 GDIPlus.GdiPlusStreamHelper sh = new GDIPlus.GdiPlusStreamHelper (stream, false);
368 status = GDIPlus.GdipGetMetafileHeaderFromDelegate_linux (sh.GetHeaderDelegate,
369 sh.GetBytesDelegate, sh.PutBytesDelegate, sh.SeekDelegate, sh.CloseDelegate,
370 sh.SizeDelegate, header);
372 status = GDIPlus.GdipGetMetafileHeaderFromStream (new ComIStreamWrapper (stream), header);
374 GDIPlus.CheckStatus (status);
375 return new MetafileHeader (header);
378 Marshal.FreeHGlobal (header);
382 [MonoLimitation ("Metafiles aren't only partially supported by libgdiplus.")]
383 public static MetafileHeader GetMetafileHeader (string fileName)
385 if (fileName == null)
386 throw new ArgumentNullException ("fileName");
388 IntPtr header = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (MetafileHeader)));
390 Status status = GDIPlus.GdipGetMetafileHeaderFromFile (fileName, header);
391 GDIPlus.CheckStatus (status);
392 return new MetafileHeader (header);
395 Marshal.FreeHGlobal (header);
399 [MonoLimitation ("Metafiles aren't only partially supported by libgdiplus.")]
400 public static MetafileHeader GetMetafileHeader (IntPtr henhmetafile, WmfPlaceableFileHeader wmfHeader)
402 IntPtr header = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (MetafileHeader)));
404 Status status = GDIPlus.GdipGetMetafileHeaderFromEmf (henhmetafile, header);
405 GDIPlus.CheckStatus (status);
406 return new MetafileHeader (header);
409 Marshal.FreeHGlobal (header);
413 [MonoLimitation ("Metafiles aren't only partially supported by libgdiplus.")]
414 public void PlayRecord (EmfPlusRecordType recordType, int flags, int dataSize, byte[] data)
416 Status status = GDIPlus.GdipPlayMetafileRecord (nativeObject, recordType, flags, dataSize, data);
417 GDIPlus.CheckStatus (status);