2007-12-18 Carlos Alberto Cortez <calberto.cortez@gmail.com>
[mono.git] / mcs / class / System.Drawing / System.Drawing.Imaging / Metafile.cs
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 #if ONLY_1_1
42         [ComVisible (false)]
43 #endif
44         [Editor ("System.Drawing.Design.MetafileEditor, " + Consts.AssemblySystem_Drawing_Design, typeof (System.Drawing.Design.UITypeEditor))]
45         public sealed class Metafile : Image {
46
47                 // constructors
48
49                 internal Metafile (IntPtr ptr)
50                 {
51                         nativeObject = ptr;
52                 }
53
54                 public Metafile (Stream stream) 
55                 {
56                         if (stream == null)
57                                 throw new ArgumentException ("stream");
58
59                         Status status;
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);
66                         } else {
67                                 status = GDIPlus.GdipCreateMetafileFromStream (new ComIStreamWrapper (stream), out nativeObject);
68                         }
69                         GDIPlus.CheckStatus (status);
70                 }
71
72                 public Metafile (string filename) 
73                 {
74                         if (filename == null)
75                                 throw new ArgumentNullException ("filename");
76                         if (filename.Length == 0)
77                                 throw new ArgumentException ("filename");
78
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);
83                 }
84
85                 public Metafile (IntPtr henhmetafile, bool deleteEmf) 
86                 {
87                         Status status = GDIPlus.GdipCreateMetafileFromEmf (henhmetafile, deleteEmf, out nativeObject);
88                         GDIPlus.CheckStatus (status);
89                 }
90
91                 public Metafile (IntPtr referenceHdc, EmfType emfType) :
92                         this (referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, emfType, null)
93                 {
94                 }
95
96                 public Metafile (IntPtr referenceHdc, Rectangle frameRect) :
97                         this (referenceHdc, frameRect, MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
98                 {
99                 }
100
101                 public Metafile (IntPtr referenceHdc, RectangleF frameRect) :
102                         this (referenceHdc, frameRect, MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
103                 {
104                 }
105
106                 public Metafile (IntPtr hmetafile, WmfPlaceableFileHeader wmfHeader) 
107                 {
108                         Status status = GDIPlus.GdipCreateMetafileFromEmf (hmetafile, false, out nativeObject);
109                         GDIPlus.CheckStatus (status);
110                 }
111
112                 public Metafile (Stream stream, IntPtr referenceHdc) :
113                         this (stream, referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
114                 {
115                 }
116
117                 public Metafile (string fileName, IntPtr referenceHdc) :
118                         this (fileName, referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual,
119                         null)
120                 {
121                 }
122
123                 public Metafile (IntPtr referenceHdc, EmfType emfType, string description) :
124                         this (referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, emfType, description)
125                 {
126                 }
127
128                 public Metafile (IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit) :
129                         this (referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, null)
130                 {
131                 }
132
133                 public Metafile (IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit) :
134                         this (referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, null)
135                 {
136                 }
137
138                 public Metafile (IntPtr hmetafile, WmfPlaceableFileHeader wmfHeader, bool deleteWmf) 
139                 {
140                         Status status = GDIPlus.GdipCreateMetafileFromEmf (hmetafile, deleteWmf, out nativeObject);
141                         GDIPlus.CheckStatus (status);
142                 }
143
144                 public Metafile (Stream stream, IntPtr referenceHdc, EmfType type) :
145                         this (stream, referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, type, null)
146                 {
147                 }
148
149                 public Metafile (Stream stream, IntPtr referenceHdc, Rectangle frameRect) :
150                         this (stream, referenceHdc, frameRect, MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
151                 {
152                 }
153
154                 public Metafile (Stream stream, IntPtr referenceHdc, RectangleF frameRect) :
155                         this (stream, referenceHdc, frameRect, MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
156                 {
157                 }
158
159                 public Metafile (string fileName, IntPtr referenceHdc, EmfType type) :
160                         this (fileName, referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, type, null)
161                 {
162                 }
163
164                 public Metafile (string fileName, IntPtr referenceHdc, Rectangle frameRect) :
165                         this (fileName, referenceHdc, frameRect, MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
166                 {
167                 }
168                 
169                 public Metafile (string fileName, IntPtr referenceHdc, RectangleF frameRect) :
170                         this (fileName, referenceHdc, frameRect, MetafileFrameUnit.GdiCompatible, EmfType.EmfPlusDual, null)
171                 {
172                 }
173
174                 public Metafile (IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit, EmfType type) :
175                         this (referenceHdc, frameRect, frameUnit, type, null)
176                 {
177                 }
178
179                 public Metafile (IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit, EmfType type) :
180                         this (referenceHdc, frameRect, frameUnit, type, null)
181                 {
182                 }
183
184                 public Metafile (Stream stream, IntPtr referenceHdc, EmfType type, string description) :
185                         this (stream, referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, type, description)
186                 {
187                 }
188
189                 public Metafile (Stream stream, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit) :
190                         this (stream, referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, null)
191                 {
192                 }
193
194                 public Metafile (Stream stream, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit) :
195                         this (stream, referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, null)
196                 {
197                 }
198
199                 public Metafile (string fileName, IntPtr referenceHdc, EmfType type, string description) :
200                         this (fileName, referenceHdc, new RectangleF (), MetafileFrameUnit.GdiCompatible, type, description)
201                 {
202                 }
203
204                 public Metafile (string fileName, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit) :
205                         this (fileName, referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, null)
206                 {
207                 }
208                 
209                 public Metafile (string fileName, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit) :
210                         this (fileName, referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, null)
211                 {
212                 }
213
214                 public Metafile (IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit, EmfType type,
215                         string description)
216                 {
217                         Status status = GDIPlus.GdipRecordMetafileI (referenceHdc, type, ref frameRect, frameUnit,
218                                 description, out nativeObject);
219                         GDIPlus.CheckStatus (status);
220                 }
221
222                 public Metafile (IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit, EmfType type,
223                         string description)
224                 {
225                         Status status = GDIPlus.GdipRecordMetafile (referenceHdc, type, ref frameRect, frameUnit,
226                                 description, out nativeObject);
227                         GDIPlus.CheckStatus (status);
228                 }
229
230                 public Metafile (Stream stream, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit,
231                         EmfType type) : this (stream, referenceHdc, frameRect, frameUnit, type, null)
232                 {
233                 }
234
235                 public Metafile (Stream stream, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit,
236                         EmfType type) : this (stream, referenceHdc, frameRect, frameUnit, type, null)
237                 {
238                 }
239
240                 public Metafile (string fileName, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit,
241                         EmfType type) : this (fileName, referenceHdc, frameRect, frameUnit, type, null)
242                 {
243                 }
244                 
245                 public Metafile (string fileName, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit,
246                         string description) : this (fileName, referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual, description)
247                 {
248                 }
249
250                 public Metafile (string fileName, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit,
251                         EmfType type) : this (fileName, referenceHdc, frameRect, frameUnit, type, null)
252                 {
253                 }
254                 
255                 public Metafile (string fileName, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit, 
256                         string description) : this (fileName, referenceHdc, frameRect, frameUnit, EmfType.EmfPlusDual,
257                         description) 
258                 {
259                 }
260                 
261                 public Metafile (Stream stream, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit, 
262                         EmfType type, string description) 
263                 {
264                         if (stream == null)
265                                 throw new NullReferenceException ("stream");
266
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);
275                         } else {
276                                 status = GDIPlus.GdipRecordMetafileStreamI (new ComIStreamWrapper (stream), referenceHdc, 
277                                         type, ref frameRect, frameUnit, description, out nativeObject);
278                         }
279                         GDIPlus.CheckStatus (status);
280                 }
281
282                 public Metafile (Stream stream, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit, 
283                         EmfType type, string description) 
284                 {
285                         if (stream == null)
286                                 throw new NullReferenceException ("stream");
287
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);
296                         } else {
297                                 status = GDIPlus.GdipRecordMetafileStream (new ComIStreamWrapper (stream), referenceHdc, 
298                                         type, ref frameRect, frameUnit, description, out nativeObject);
299                         }
300                         GDIPlus.CheckStatus (status);
301                 }
302
303                 public Metafile (string fileName, IntPtr referenceHdc, Rectangle frameRect, MetafileFrameUnit frameUnit, 
304                         EmfType type, string description) 
305                 {
306                         Status status = GDIPlus.GdipRecordMetafileFileNameI (fileName, referenceHdc, type, ref frameRect, 
307                                 frameUnit, description, out nativeObject);
308                         GDIPlus.CheckStatus (status);
309                 }
310                 
311                 public Metafile (string fileName, IntPtr referenceHdc, RectangleF frameRect, MetafileFrameUnit frameUnit,
312                         EmfType type, string description) 
313                 {
314                         Status status = GDIPlus.GdipRecordMetafileFileName (fileName, referenceHdc, type, ref frameRect, frameUnit, 
315                                 description, out nativeObject);
316                         GDIPlus.CheckStatus (status);
317                 }
318
319                 // methods
320
321                 public IntPtr GetHenhmetafile ()
322                 {
323                         return nativeObject;
324                 }
325
326                 [MonoLimitation ("Metafiles aren't only partially supported by libgdiplus.")]
327                 public MetafileHeader GetMetafileHeader ()
328                 {
329                         IntPtr header = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (MetafileHeader)));
330                         try {
331                                 Status status = GDIPlus.GdipGetMetafileHeaderFromMetafile (nativeObject, header);
332                                 GDIPlus.CheckStatus (status);
333                                 return new MetafileHeader (header);
334                         }
335                         finally {
336                                 Marshal.FreeHGlobal (header);
337                         }
338                 }
339
340                 [MonoLimitation ("Metafiles aren't only partially supported by libgdiplus.")]
341                 public static MetafileHeader GetMetafileHeader (IntPtr henhmetafile)
342                 {
343                         IntPtr header = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (MetafileHeader)));
344                         try {
345                                 Status status = GDIPlus.GdipGetMetafileHeaderFromEmf (henhmetafile, header);
346                                 GDIPlus.CheckStatus (status);
347                                 return new MetafileHeader (header);
348                         }
349                         finally {
350                                 Marshal.FreeHGlobal (header);
351                         }
352                 }
353
354                 [MonoLimitation ("Metafiles aren't only partially supported by libgdiplus.")]
355                 public static MetafileHeader GetMetafileHeader (Stream stream)
356                 {
357                         if (stream == null)
358                                 throw new NullReferenceException ("stream");
359
360                         IntPtr header = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (MetafileHeader)));
361                         try {
362                                 Status status;
363
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);
371                                 } else {
372                                         status = GDIPlus.GdipGetMetafileHeaderFromStream (new ComIStreamWrapper (stream), header);
373                                 }
374                                 GDIPlus.CheckStatus (status);
375                                 return new MetafileHeader (header);
376                         }
377                         finally {
378                                 Marshal.FreeHGlobal (header);
379                         }
380                 }
381
382                 [MonoLimitation ("Metafiles aren't only partially supported by libgdiplus.")]
383                 public static MetafileHeader GetMetafileHeader (string fileName)
384                 {
385                         if (fileName == null)
386                                 throw new ArgumentNullException ("fileName");
387
388                         IntPtr header = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (MetafileHeader)));
389                         try {
390                                 Status status = GDIPlus.GdipGetMetafileHeaderFromFile (fileName, header);
391                                 GDIPlus.CheckStatus (status);
392                                 return new MetafileHeader (header);
393                         }
394                         finally {
395                                 Marshal.FreeHGlobal (header);
396                         }
397                 }
398
399                 [MonoLimitation ("Metafiles aren't only partially supported by libgdiplus.")]
400                 public static MetafileHeader GetMetafileHeader (IntPtr henhmetafile, WmfPlaceableFileHeader wmfHeader)
401                 {
402                         IntPtr header = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (MetafileHeader)));
403                         try {
404                                 Status status = GDIPlus.GdipGetMetafileHeaderFromEmf (henhmetafile, header);
405                                 GDIPlus.CheckStatus (status);
406                                 return new MetafileHeader (header);
407                         }
408                         finally {
409                                 Marshal.FreeHGlobal (header);
410                         }
411                 }
412
413                 [MonoLimitation ("Metafiles aren't only partially supported by libgdiplus.")]
414                 public void PlayRecord (EmfPlusRecordType recordType, int flags, int dataSize, byte[] data)
415                 {
416                         Status status = GDIPlus.GdipPlayMetafileRecord (nativeObject, recordType, flags, dataSize, data);
417                         GDIPlus.CheckStatus (status);
418                 }
419         }
420 }