]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/dataobj.cpp
cleanup
[wxWidgets.git] / src / mac / carbon / dataobj.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/dataobj.cpp
3 // Purpose: implementation of wxDataObject class
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 10/21/99
7 // RCS-ID: $Id$
8 // Copyright: (c) 1999 Stefan Csomor
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #if wxUSE_DATAOBJ
16
17 #include "wx/dataobj.h"
18
19 #ifndef WX_PRECOMP
20 #include "wx/intl.h"
21 #include "wx/log.h"
22 #include "wx/dcmemory.h"
23 #include "wx/image.h"
24 #endif
25
26 #include "wx/mstream.h"
27 #include "wx/metafile.h"
28 #include "wx/tokenzr.h"
29
30 #include "wx/mac/uma.h"
31
32 #ifdef __DARWIN__
33 #include <QuickTime/QuickTime.h>
34 #endif
35
36
37 // ----------------------------------------------------------------------------
38 // wxDataFormat
39 // ----------------------------------------------------------------------------
40
41 wxDataFormat::wxDataFormat()
42 {
43 m_type = wxDF_INVALID;
44 m_format = 0;
45 }
46
47 wxDataFormat::wxDataFormat( wxDataFormatId vType )
48 {
49 m_format = 0;
50 m_type = wxDF_INVALID;
51 SetType( vType );
52 }
53
54 wxDataFormat::wxDataFormat( const wxChar *zId )
55 {
56 m_format = 0;
57 m_type = wxDF_INVALID;
58 SetId( zId );
59 }
60
61 wxDataFormat::wxDataFormat( const wxString& rId )
62 {
63 m_format = 0;
64 m_type = wxDF_INVALID;
65 SetId( rId );
66 }
67
68 wxDataFormat::wxDataFormat(const wxDataFormat& rFormat)
69 {
70 if ( rFormat.m_format )
71 m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)rFormat.m_format);
72 else
73 m_format = 0;
74 m_type = rFormat.m_type;
75 m_id = rFormat.m_id;
76 }
77
78 wxDataFormat::wxDataFormat( NativeFormat vFormat )
79 {
80 m_format = 0;
81 m_type = wxDF_INVALID;
82 SetId( vFormat );
83 }
84
85 wxDataFormat::~wxDataFormat()
86 {
87 if ( m_format != 0 )
88 {
89 CFRelease( (CFStringRef) m_format );
90 m_format = 0;
91 }
92 }
93
94 // in order to be correct for 10.3 we restrict to the available types there
95 // http://developer.apple.com/qa/qa2005/qa1406.html
96 // TODO : Use UTCoreTypes.h constants once we support 10.4+ only
97
98 wxDataFormat& wxDataFormat::operator=(const wxDataFormat& rFormat)
99 {
100 if ( m_format != 0 )
101 {
102 CFRelease( (CFStringRef) m_format );
103 m_format = 0;
104 }
105 if ( rFormat.m_format )
106 m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)rFormat.m_format);
107 m_type = rFormat.m_type;
108 m_id = rFormat.m_id;
109 return *this;
110 }
111
112 void wxDataFormat::SetType( wxDataFormatId dataType )
113 {
114 m_type = dataType;
115 if ( m_format != 0 )
116 {
117 CFRelease( (CFStringRef) m_format );
118 m_format = 0;
119 }
120
121 switch (m_type)
122 {
123 case wxDF_TEXT:
124 m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.plain-text") );
125 break;
126
127 case wxDF_UNICODETEXT:
128 m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.utf16-plain-text") );
129 break;
130
131 case wxDF_BITMAP:
132 #if wxMAC_USE_CORE_GRAPHICS
133 m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.tiff") );
134 #else
135 m_format = (long) CFStringCreateCopy( NULL, CFSTR("com.apple.pict") );
136 #endif
137 break;
138 case wxDF_METAFILE:
139 #if wxMAC_USE_CORE_GRAPHICS
140 m_format = (long) CFStringCreateCopy( NULL, CFSTR("com.adobe.pdf") );
141 #else
142 m_format = (long) CFStringCreateCopy( NULL, CFSTR("com.apple.pict") );
143 #endif
144 break;
145
146 case wxDF_FILENAME:
147 m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.file-url") );
148 break;
149
150 default:
151 wxFAIL_MSG( wxT("invalid data format") );
152 break;
153 }
154 }
155
156 wxString wxDataFormat::GetId() const
157 {
158 wxCHECK_MSG( !IsStandard(), wxEmptyString,
159 wxT("name of predefined format cannot be retrieved") );
160
161 return m_id;
162 }
163
164 void wxDataFormat::SetId( NativeFormat format )
165 {
166 if ( m_format != 0 )
167 {
168 CFRelease( (CFStringRef) m_format );
169 m_format = 0;
170 }
171 m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)format);
172 if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.utf16-plain-text") ) )
173 {
174 m_type = wxDF_UNICODETEXT;
175 }
176 else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.plain-text") ) )
177 {
178 m_type = wxDF_TEXT;
179 }
180 #if wxMAC_USE_CORE_GRAPHICS
181 else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.tiff") ) )
182 {
183 m_type = wxDF_BITMAP;
184 }
185 else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("com.adobe.pdf") ) )
186 {
187 m_type = wxDF_METAFILE;
188 }
189 #else
190 else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("com.apple.pict") ) )
191 {
192 m_type = wxDF_METAFILE;
193 }
194 #endif
195 else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.file-url") ) )
196 {
197 m_type = wxDF_FILENAME;
198 }
199 else
200 {
201 m_type = wxDF_PRIVATE;
202 m_id = wxMacCFStringHolder( (CFStringRef) CFRetain((CFStringRef) format )).AsString();
203 }
204 }
205
206 void wxDataFormat::SetId( const wxString& zId )
207 {
208 m_type = wxDF_PRIVATE;
209 m_id = zId;
210 if ( m_format != 0 )
211 {
212 CFRelease( (CFStringRef) m_format );
213 m_format = 0;
214 }
215 // since it is private, no need to conform to anything ...
216 m_format = (long) wxMacCFStringHolder(m_id).Detach();
217 }
218
219 bool wxDataFormat::operator==(const wxDataFormat& format) const
220 {
221 if (IsStandard() || format.IsStandard())
222 return (format.m_type == m_type);
223 else
224 return ( UTTypeConformsTo( (CFStringRef) m_format , (CFStringRef) format.m_format ) );
225 }
226
227 //-------------------------------------------------------------------------
228 // wxDataObject
229 //-------------------------------------------------------------------------
230
231 wxDataObject::wxDataObject()
232 {
233 }
234
235 bool wxDataObject::IsSupportedFormat( const wxDataFormat& rFormat, Direction vDir ) const
236 {
237 size_t nFormatCount = GetFormatCount( vDir );
238 bool found = false;
239
240 if (nFormatCount == 1)
241 {
242 found = (rFormat == GetPreferredFormat());
243 }
244 else
245 {
246 wxDataFormat *pFormats = new wxDataFormat[nFormatCount];
247 GetAllFormats( pFormats, vDir );
248
249 for (size_t n = 0; n < nFormatCount; n++)
250 {
251 if (pFormats[n] == rFormat)
252 {
253 found = true;
254 break;
255 }
256 }
257
258 delete [] pFormats;
259 }
260
261 return found;
262 }
263
264 void wxDataObject::AddToPasteboard( void * pb, int itemID )
265 {
266 PasteboardRef pasteboard = (PasteboardRef) pb;
267 // get formats from wxDataObjects
268 wxDataFormat *array = new wxDataFormat[ GetFormatCount() ];
269 GetAllFormats( array );
270
271 for (size_t i = 0; i < GetFormatCount(); i++)
272 {
273 wxDataFormat thisFormat = array[ i ];
274
275 // add four bytes at the end for data objs like text that
276 // have a datasize = strlen but still need a buffer for the
277 // string including trailing zero
278
279 size_t datasize = GetDataSize( thisFormat );
280 size_t sz = datasize + 4;
281 void* buf = malloc( sz );
282 if ( buf != NULL )
283 {
284 // empty the buffer because in some case GetDataHere does not fill buf
285 memset( buf, 0, sz );
286 if ( GetDataHere( array[ i ], buf ) )
287 {
288 int counter = 1 ;
289 if ( thisFormat.GetType() == wxDF_FILENAME )
290 {
291 // the data is D-normalized UTF8 strings of filenames delimited with \n
292 char *fname = strtok((char*) buf,"\n");
293 while (fname != NULL)
294 {
295 // translate the filepath into a fileurl and put that into the pasteobard
296 CFStringRef path = CFStringCreateWithBytes(NULL,(UInt8*)fname,strlen(fname),kCFStringEncodingUTF8,false);
297 CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path , kCFURLPOSIXPathStyle, false);
298 CFRelease(path);
299 CFDataRef data = CFURLCreateData(NULL,url,kCFStringEncodingUTF8,true);
300 CFRelease(url);
301 PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) counter,
302 (CFStringRef) thisFormat.GetFormatId() , data, kPasteboardFlavorNoFlags);
303 CFRelease( data );
304 counter++;
305 fname = strtok (NULL,"\n");
306 }
307
308 }
309 else
310 {
311 CFDataRef data = CFDataCreate( kCFAllocatorDefault, (UInt8*)buf, datasize );
312 if ( thisFormat.GetType() == wxDF_TEXT )
313 PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) itemID,
314 CFSTR("com.apple.traditional-mac-plain-text") , data, kPasteboardFlavorNoFlags);
315 else
316 PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) itemID,
317 (CFStringRef) thisFormat.GetFormatId() , data, kPasteboardFlavorNoFlags);
318 CFRelease( data );
319 }
320 }
321 free( buf );
322 }
323 }
324
325 delete [] array;
326 }
327
328 bool wxDataObject::IsFormatInPasteboard( void * pb, const wxDataFormat &dataFormat )
329 {
330 PasteboardRef pasteboard = (PasteboardRef) pb;
331 bool hasData = false;
332 OSStatus err = noErr;
333 ItemCount itemCount;
334
335 // we synchronize here once again, so we don't mind which flags get returned
336 PasteboardSynchronize( pasteboard );
337
338 err = PasteboardGetItemCount( pasteboard, &itemCount );
339 if ( err == noErr )
340 {
341 for( UInt32 itemIndex = 1; itemIndex <= itemCount && hasData == false ; itemIndex++ )
342 {
343 PasteboardItemID itemID;
344 CFArrayRef flavorTypeArray;
345 CFIndex flavorCount;
346
347 err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
348 if ( err != noErr )
349 continue;
350
351 err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
352 if ( err != noErr )
353 continue;
354
355 flavorCount = CFArrayGetCount( flavorTypeArray );
356
357 for( CFIndex flavorIndex = 0; flavorIndex < flavorCount && hasData == false ; flavorIndex++ )
358 {
359 CFStringRef flavorType;
360
361 flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
362 flavorIndex );
363
364 wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
365 if ( dataFormat == flavorFormat )
366 hasData = true;
367 else if ( dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
368 hasData = true;
369 }
370 CFRelease (flavorTypeArray);
371 }
372 }
373
374 return hasData;
375 }
376
377 bool wxDataObject::GetFromPasteboard( void * pb )
378 {
379 PasteboardRef pasteboard = (PasteboardRef) pb;
380 size_t formatcount = GetFormatCount() + 1;
381 wxDataFormat *array = new wxDataFormat[ formatcount ];
382 array[0] = GetPreferredFormat();
383 GetAllFormats( &array[1] );
384 ItemCount itemCount = 0;
385 wxString filenamesPassed;
386 bool transferred = false;
387
388 // we synchronize here once again, so we don't mind which flags get returned
389 PasteboardSynchronize( pasteboard );
390
391 OSStatus err = PasteboardGetItemCount( pasteboard, &itemCount );
392 if ( err == noErr )
393 {
394 for (size_t i = 0; !transferred && i < formatcount; i++)
395 {
396 // go through the data in our order of preference
397 wxDataFormat dataFormat = array[ i ];
398
399 for( UInt32 itemIndex = 1; itemIndex <= itemCount && transferred == false ; itemIndex++ )
400 {
401 PasteboardItemID itemID = 0;
402 CFArrayRef flavorTypeArray = NULL;
403 CFIndex flavorCount = 0;
404
405 err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
406 if ( err != noErr )
407 continue;
408
409 err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
410 if ( err != noErr )
411 continue;
412
413 flavorCount = CFArrayGetCount( flavorTypeArray );
414
415 for( CFIndex flavorIndex = 0; !transferred && flavorIndex < flavorCount ; flavorIndex++ )
416 {
417 CFStringRef flavorType;
418 CFDataRef flavorData;
419 CFIndex flavorDataSize;
420
421 flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
422 flavorIndex );
423
424 wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
425
426 if ( dataFormat == flavorFormat )
427 {
428 err = PasteboardCopyItemFlavorData( pasteboard, itemID, flavorType , &flavorData );
429 if ( err == noErr )
430 {
431 flavorDataSize = CFDataGetLength( flavorData );
432 if (dataFormat.GetType() == wxDF_FILENAME )
433 {
434 // revert the translation and decomposition to arrive at a proper utf8 string again
435 CFURLRef url = CFURLCreateWithBytes( kCFAllocatorDefault, CFDataGetBytePtr( flavorData ), flavorDataSize, kCFStringEncodingUTF8, NULL );
436 CFStringRef cfString = CFURLCopyFileSystemPath( url, kCFURLPOSIXPathStyle );
437 CFRelease( url );
438 CFMutableStringRef cfMutableString = CFStringCreateMutableCopy(NULL, 0, cfString);
439 CFRelease( cfString );
440 CFStringNormalize(cfMutableString,kCFStringNormalizationFormC);
441 wxString path = wxMacCFStringHolder(cfMutableString).AsString();
442 if (!path.empty())
443 filenamesPassed += path + wxT("\n");
444 }
445 else
446 {
447 // because some data implementation expect trailing a trailing NUL, we add some headroom
448 void *buf = malloc( flavorDataSize + 4 );
449 if ( buf )
450 {
451 memset( buf, 0, flavorDataSize + 4 );
452 memcpy( buf, CFDataGetBytePtr( flavorData ), flavorDataSize );
453
454 if (dataFormat.GetType() == wxDF_TEXT)
455 wxMacConvertNewlines10To13( (char*) buf );
456 SetData( flavorFormat, flavorDataSize, buf );
457 transferred = true;
458 free( buf );
459 }
460 }
461 CFRelease (flavorData);
462 }
463 }
464 else if ( dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
465 {
466 err = PasteboardCopyItemFlavorData( pasteboard, itemID, flavorType, &flavorData );
467 if ( err == noErr )
468 {
469 flavorDataSize = CFDataGetLength( flavorData );
470 void *asciibuf = malloc( flavorDataSize + 1 );
471 if ( asciibuf )
472 {
473 memset( asciibuf, 0, flavorDataSize + 1 );
474 memcpy( asciibuf, CFDataGetBytePtr( flavorData ), flavorDataSize );
475 CFRelease (flavorData);
476
477 SetData( wxDF_TEXT, flavorDataSize, asciibuf );
478 transferred = true;
479 free( asciibuf );
480 }
481 else
482 CFRelease (flavorData);
483 }
484 }
485 }
486 CFRelease( flavorTypeArray );
487 }
488 if (filenamesPassed.length() > 0)
489 {
490 wxCharBuffer buf = filenamesPassed.fn_str();
491 SetData( wxDF_FILENAME, strlen( buf ), (const char*)buf );
492 transferred = true;
493 }
494 }
495 }
496 return transferred;
497 }
498
499 bool wxDataObject::HasDataInPasteboard( void * pb )
500 {
501 PasteboardRef pasteboard = (PasteboardRef) pb;
502 size_t formatcount = GetFormatCount() + 1;
503 wxDataFormat *array = new wxDataFormat[ formatcount ];
504 array[0] = GetPreferredFormat();
505 GetAllFormats( &array[1] );
506 ItemCount itemCount = 0;
507 bool hasData = false;
508
509 // we synchronize here once again, so we don't mind which flags get returned
510 PasteboardSynchronize( pasteboard );
511
512 OSStatus err = PasteboardGetItemCount( pasteboard, &itemCount );
513 if ( err == noErr )
514 {
515 for (size_t i = 0; !hasData && i < formatcount; i++)
516 {
517 // go through the data in our order of preference
518 wxDataFormat dataFormat = array[ i ];
519
520 for( UInt32 itemIndex = 1; itemIndex <= itemCount && hasData == false ; itemIndex++ )
521 {
522 PasteboardItemID itemID = 0;
523 CFArrayRef flavorTypeArray = NULL;
524 CFIndex flavorCount = 0;
525
526 err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
527 if ( err != noErr )
528 continue;
529
530 err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
531 if ( err != noErr )
532 continue;
533
534 flavorCount = CFArrayGetCount( flavorTypeArray );
535
536 for( CFIndex flavorIndex = 0; !hasData && flavorIndex < flavorCount ; flavorIndex++ )
537 {
538 CFStringRef flavorType;
539
540 flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
541 flavorIndex );
542
543 wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
544
545 if ( dataFormat == flavorFormat ||
546 dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
547 {
548 hasData = true;
549 }
550 }
551 CFRelease( flavorTypeArray );
552 }
553 }
554 }
555 return hasData;
556 }
557
558 // ----------------------------------------------------------------------------
559 // wxTextDataObject
560 // ----------------------------------------------------------------------------
561
562 #if wxUSE_UNICODE
563 void wxTextDataObject::GetAllFormats(wxDataFormat *formats,
564 wxDataObjectBase::Direction WXUNUSED(dir)) const
565 {
566 *formats++ = wxDataFormat( wxDF_TEXT );
567 *formats = wxDataFormat( wxDF_UNICODETEXT );
568 }
569 #endif
570
571 // ----------------------------------------------------------------------------
572 // wxFileDataObject
573 // ----------------------------------------------------------------------------
574
575 void wxFileDataObject::GetFileNames( wxCharBuffer &buf ) const
576 {
577 wxString filenames;
578
579 for (size_t i = 0; i < m_filenames.GetCount(); i++)
580 {
581 filenames += m_filenames[i];
582 filenames += wxT('\n');
583 }
584
585 buf = filenames.fn_str();
586 }
587
588 bool wxFileDataObject::GetDataHere( void *pBuf ) const
589 {
590 if (pBuf == NULL)
591 return false;
592
593 wxCharBuffer buf;
594 size_t buffLength;
595
596 GetFileNames( buf );
597 buffLength = strlen( buf );
598 memcpy( pBuf, (const char*)buf, buffLength + 1 );
599
600 return true;
601 }
602
603 size_t wxFileDataObject::GetDataSize() const
604 {
605 wxCharBuffer buf;
606 size_t buffLength;
607
608 GetFileNames( buf );
609 buffLength = strlen( buf );
610 // terminating 0
611 return buffLength + 1;
612 }
613
614 bool wxFileDataObject::SetData( size_t WXUNUSED(nSize), const void *pBuf )
615 {
616 wxString filenames;
617
618 #if wxUSE_UNICODE
619 filenames = wxString( (const char*)pBuf, *wxConvFileName );
620 #else
621 filenames = wxString (wxConvLocal.cWC2WX(wxConvFileName->cMB2WC( (const char*)pBuf)));
622 #endif
623
624 m_filenames = wxStringTokenize( filenames, wxT("\n"), wxTOKEN_STRTOK );
625
626 return true;
627 }
628
629 void wxFileDataObject::AddFile( const wxString& rFilename )
630 {
631 m_filenames.Add( rFilename );
632 }
633
634 // ----------------------------------------------------------------------------
635 // wxBitmapDataObject
636 // ----------------------------------------------------------------------------
637
638 wxBitmapDataObject::wxBitmapDataObject()
639 {
640 Init();
641 }
642
643 wxBitmapDataObject::wxBitmapDataObject( const wxBitmap& rBitmap )
644 : wxBitmapDataObjectBase( rBitmap )
645 {
646 Init();
647
648 if (m_bitmap.Ok())
649 {
650 #if wxMAC_USE_CORE_GRAPHICS
651 SetBitmap( rBitmap );
652 #else
653 m_pictHandle = m_bitmap.GetBitmapData()->GetPictHandle();
654 m_pictCreated = false;
655 #endif
656 }
657 }
658
659 wxBitmapDataObject::~wxBitmapDataObject()
660 {
661 Clear();
662 }
663
664 void wxBitmapDataObject::SetBitmap( const wxBitmap& rBitmap )
665 {
666 Clear();
667 wxBitmapDataObjectBase::SetBitmap( rBitmap );
668 if (m_bitmap.Ok())
669 {
670 #if wxMAC_USE_CORE_GRAPHICS
671 CGImageRef cgImageRef = (CGImageRef) m_bitmap.CGImageCreate();
672 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
673 if ( UMAGetSystemVersion() >= 0x1040 )
674 {
675 CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0);
676 CGImageDestinationRef destination = CGImageDestinationCreateWithData( data , kUTTypeTIFF , 1 , NULL );
677 if ( destination )
678 {
679 CGImageDestinationAddImage( destination, cgImageRef, NULL );
680 CGImageDestinationFinalize( destination );
681 CFRelease( destination );
682 }
683 m_pictHandle = NewHandle(CFDataGetLength(data));
684 if ( m_pictHandle )
685 {
686 memcpy( *(Handle)m_pictHandle, (const char *)CFDataGetBytePtr(data), CFDataGetLength(data) );
687 }
688 CFRelease( data );
689 }
690 else
691 #endif
692 #ifndef __LP64__
693 {
694 // export as TIFF
695 GraphicsExportComponent exporter = 0;
696 OSStatus err = OpenADefaultComponent(GraphicsExporterComponentType, kQTFileTypeTIFF, &exporter);
697 if (noErr == err)
698 {
699 m_pictHandle = NewHandle(0);
700 if ( m_pictHandle )
701 {
702 err = GraphicsExportSetInputCGImage( exporter, cgImageRef);
703 err = GraphicsExportSetOutputHandle(exporter, (Handle)m_pictHandle);
704 err = GraphicsExportDoExport(exporter, NULL);
705 }
706 CloseComponent( exporter );
707 }
708 }
709 #endif
710 CGImageRelease(cgImageRef);
711 #else
712 m_pictHandle = m_bitmap.GetBitmapData()->GetPictHandle();
713 m_pictCreated = false;
714 #endif
715 }
716 }
717
718 void wxBitmapDataObject::Init()
719 {
720 m_pictHandle = NULL;
721 m_pictCreated = false;
722 }
723
724 void wxBitmapDataObject::Clear()
725 {
726 if (m_pictHandle != NULL)
727 {
728 #if wxMAC_USE_CORE_GRAPHICS
729 DisposeHandle( (Handle) m_pictHandle );
730 #else
731 if (m_pictCreated)
732 KillPicture( (PicHandle)m_pictHandle );
733 #endif
734 m_pictHandle = NULL;
735 }
736 m_pictCreated = false;
737 }
738
739 bool wxBitmapDataObject::GetDataHere( void *pBuf ) const
740 {
741 if (m_pictHandle == NULL)
742 {
743 wxFAIL_MSG( wxT("attempt to copy empty bitmap failed") );
744 return false;
745 }
746
747 if (pBuf == NULL)
748 return false;
749
750 memcpy( pBuf, *(Handle)m_pictHandle, GetHandleSize( (Handle)m_pictHandle ) );
751
752 return true;
753 }
754
755 size_t wxBitmapDataObject::GetDataSize() const
756 {
757 if (m_pictHandle != NULL)
758 return GetHandleSize( (Handle)m_pictHandle );
759 else
760 return 0;
761 }
762
763 Handle MacCreateDataReferenceHandle(Handle theDataHandle)
764 {
765 Handle dataRef = NULL;
766 OSErr err = noErr;
767
768 // Create a data reference handle for our data.
769 err = PtrToHand( &theDataHandle, &dataRef, sizeof(Handle));
770
771 return dataRef;
772 }
773
774 bool wxBitmapDataObject::SetData( size_t nSize, const void *pBuf )
775 {
776 Clear();
777
778 if ((pBuf == NULL) || (nSize == 0))
779 return false;
780
781 #if wxMAC_USE_CORE_GRAPHICS
782 Handle picHandle = NewHandle( nSize );
783 memcpy( *picHandle, pBuf, nSize );
784 m_pictHandle = picHandle;
785 CGImageRef cgImageRef = 0;
786 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
787 if ( UMAGetSystemVersion() >= 0x1040 )
788 {
789 CFDataRef data = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault, (const UInt8*) pBuf, nSize, kCFAllocatorNull);
790 CGImageSourceRef source = CGImageSourceCreateWithData( data, NULL );
791 if ( source )
792 {
793 cgImageRef = CGImageSourceCreateImageAtIndex(source, 0, NULL);
794 }
795 CFRelease( source );
796 CFRelease( data );
797 }
798 else
799 #endif
800 #ifndef __LP64__
801 {
802 // import from TIFF
803 GraphicsImportComponent importer = 0;
804 OSStatus err = OpenADefaultComponent(GraphicsImporterComponentType, kQTFileTypeTIFF, &importer);
805 if (noErr == err)
806 {
807 if ( picHandle )
808 {
809 ComponentResult result = GraphicsImportSetDataHandle(importer, picHandle);
810 if ( result == noErr )
811 {
812 Rect frame;
813 GraphicsImportGetNaturalBounds( importer, &frame );
814 GraphicsImportCreateCGImage( importer, &cgImageRef, kGraphicsImportCreateCGImageUsingCurrentSettings );
815 }
816 }
817 CloseComponent( importer );
818 }
819 }
820 #endif
821 if ( cgImageRef )
822 {
823 m_bitmap.Create( CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
824 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
825 // since our context is upside down we dont use CGContextDrawImage
826 HIViewDrawCGImage( (CGContextRef) m_bitmap.GetHBITMAP() , &r, cgImageRef ) ;
827 CGImageRelease(cgImageRef);
828 cgImageRef = NULL;
829 }
830 #else
831 PicHandle picHandle = (PicHandle)NewHandle( nSize );
832 memcpy( *picHandle, pBuf, nSize );
833 m_pictHandle = picHandle;
834 // ownership is transferred to the bitmap
835 m_pictCreated = false;
836 #ifndef __LP64__
837 Rect frame;
838 wxMacGetPictureBounds( picHandle, &frame );
839 #if wxUSE_METAFILE
840 wxMetafile mf;
841 mf.SetHMETAFILE( (WXHMETAFILE)m_pictHandle );
842 #endif
843 wxMemoryDC mdc;
844 m_bitmap.Create( frame.right - frame.left, frame.bottom - frame.top );
845 mdc.SelectObject( m_bitmap );
846 #if wxUSE_METAFILE
847 mf.Play( &mdc );
848 #endif
849 mdc.SelectObject( wxNullBitmap );
850 #endif
851 #endif
852
853 return m_bitmap.Ok();
854 }
855
856 #endif