]> git.saurik.com Git - wxWidgets.git/blob - src/osx/carbon/dataobj.cpp
using UTType constants wherever possible to avoid typos, checking for failed conversi...
[wxWidgets.git] / src / osx / carbon / dataobj.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/osx/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 #include "wx/filename.h"
30
31 #include "wx/osx/private.h"
32
33 #if wxOSX_USE_COCOA_OR_CARBON
34 #include <QuickTime/QuickTime.h>
35 #endif
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, kUTTypePlainText );
125 break;
126
127 case wxDF_UNICODETEXT:
128 m_format = (long) CFStringCreateCopy( NULL, kUTTypeUTF16PlainText );
129 break;
130
131 case wxDF_HTML:
132 m_format = (long) CFStringCreateCopy( NULL, kUTTypeHTML );
133 break;
134
135 case wxDF_BITMAP:
136 m_format = (long) CFStringCreateCopy( NULL, kUTTypeTIFF );
137 break;
138 case wxDF_METAFILE:
139 m_format = (long) CFStringCreateCopy( NULL, kUTTypePDF );
140 break;
141
142 case wxDF_FILENAME:
143 m_format = (long) CFStringCreateCopy( NULL, kUTTypeFileURL );
144 break;
145
146 default:
147 wxFAIL_MSG( wxT("invalid data format") );
148 break;
149 }
150 }
151
152 wxString wxDataFormat::GetId() const
153 {
154 return wxCFStringRef(wxCFRetain((CFStringRef)m_format)).AsString();
155 }
156
157 void wxDataFormat::SetId( NativeFormat format )
158 {
159 if ( m_format != 0 )
160 {
161 CFRelease( (CFStringRef) m_format );
162 m_format = 0;
163 }
164 m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)format);
165 if ( UTTypeConformsTo( (CFStringRef)format, kUTTypeHTML ) )
166 {
167 m_type = wxDF_HTML;
168 }
169 if ( UTTypeConformsTo( (CFStringRef)format, kUTTypeUTF16PlainText ) )
170 {
171 m_type = wxDF_UNICODETEXT;
172 }
173 else if ( UTTypeConformsTo( (CFStringRef)format,kUTTypeUTF16ExternalPlainText ) )
174 {
175 m_type = wxDF_UNICODETEXT;
176 }
177 else if ( UTTypeConformsTo( (CFStringRef)format,kUTTypeUTF8PlainText ) )
178 {
179 m_type = wxDF_UNICODETEXT;
180 }
181 else if ( UTTypeConformsTo( (CFStringRef)format, kUTTypePlainText ) )
182 {
183 m_type = wxDF_TEXT;
184 }
185 else if ( UTTypeConformsTo( (CFStringRef)format, kUTTypeImage ) )
186 {
187 m_type = wxDF_BITMAP;
188 }
189 else if ( UTTypeConformsTo( (CFStringRef)format, kUTTypePDF ) )
190 {
191 m_type = wxDF_METAFILE;
192 }
193 else if ( UTTypeConformsTo( (CFStringRef)format, kUTTypeFileURL ) ||
194 UTTypeConformsTo( (CFStringRef)format, kPasteboardTypeFileURLPromise))
195 {
196 m_type = wxDF_FILENAME;
197 }
198 else
199 {
200 m_type = wxDF_PRIVATE;
201 m_id = wxCFStringRef( (CFStringRef) CFRetain((CFStringRef) format )).AsString();
202 }
203 }
204
205 void wxDataFormat::SetId( const wxString& zId )
206 {
207 m_type = wxDF_PRIVATE;
208 m_id = zId;
209 if ( m_format != 0 )
210 {
211 CFRelease( (CFStringRef) m_format );
212 m_format = 0;
213 }
214 // since it is private, no need to conform to anything ...
215 m_format = (long) wxCFRetain( (CFStringRef) wxCFStringRef(m_id) );
216 }
217
218 bool wxDataFormat::operator==(const wxDataFormat& format) const
219 {
220 if (IsStandard() || format.IsStandard())
221 return (format.m_type == m_type);
222 else
223 return ( UTTypeConformsTo( (CFStringRef) m_format , (CFStringRef) format.m_format ) );
224 }
225
226 //-------------------------------------------------------------------------
227 // wxDataObject
228 //-------------------------------------------------------------------------
229
230 wxDataObject::wxDataObject()
231 {
232 }
233
234 bool wxDataObject::IsSupportedFormat( const wxDataFormat& rFormat, Direction vDir ) const
235 {
236 size_t nFormatCount = GetFormatCount( vDir );
237 bool found = false;
238
239 if (nFormatCount == 1)
240 {
241 found = (rFormat == GetPreferredFormat());
242 }
243 else
244 {
245 wxDataFormat *pFormats = new wxDataFormat[nFormatCount];
246 GetAllFormats( pFormats, vDir );
247
248 for (size_t n = 0; n < nFormatCount; n++)
249 {
250 if (pFormats[n] == rFormat)
251 {
252 found = true;
253 break;
254 }
255 }
256
257 delete [] pFormats;
258 }
259
260 return found;
261 }
262
263 void wxDataObject::AddToPasteboard( void * pb, int itemID )
264 {
265 PasteboardRef pasteboard = (PasteboardRef) pb;
266 // get formats from wxDataObjects
267 wxDataFormat *array = new wxDataFormat[ GetFormatCount() ];
268 GetAllFormats( array );
269
270 for (size_t i = 0; i < GetFormatCount(); i++)
271 {
272 wxDataFormat thisFormat = array[ i ];
273
274 // add four bytes at the end for data objs like text that
275 // have a datasize = strlen but still need a buffer for the
276 // string including trailing zero
277
278 size_t datasize = GetDataSize( thisFormat );
279 if ( datasize == wxCONV_FAILED && thisFormat.GetType() == wxDF_TEXT)
280 {
281 // conversion to local text failed, so we must use unicode
282 // if wxDF_UNICODETEXT is already on the 'todo' list, skip this iteration
283 // otherwise force it
284 size_t j = 0;
285 for (j = 0; j < GetFormatCount(); j++)
286 {
287 if ( array[j].GetType() == wxDF_UNICODETEXT )
288 break;
289 }
290 if ( j < GetFormatCount() )
291 continue;
292
293 thisFormat.SetType(wxDF_UNICODETEXT);
294 datasize = GetDataSize( thisFormat );
295 }
296
297 size_t sz = datasize + 4;
298 void* buf = malloc( sz );
299 if ( buf != NULL )
300 {
301 // empty the buffer because in some case GetDataHere does not fill buf
302 memset( buf, 0, sz );
303 if ( GetDataHere( thisFormat, buf ) )
304 {
305 int counter = 1 ;
306 if ( thisFormat.GetType() == wxDF_FILENAME )
307 {
308 // the data is D-normalized UTF8 strings of filenames delimited with \n
309 char *fname = strtok((char*) buf,"\n");
310 while (fname != NULL)
311 {
312 // translate the filepath into a fileurl and put that into the pasteobard
313 CFStringRef path = CFStringCreateWithBytes(NULL,(UInt8*)fname,strlen(fname),kCFStringEncodingUTF8,false);
314 CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path , kCFURLPOSIXPathStyle, false);
315 CFRelease(path);
316 CFDataRef data = CFURLCreateData(NULL,url,kCFStringEncodingUTF8,true);
317 CFRelease(url);
318 PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) counter,
319 (CFStringRef) thisFormat.GetFormatId() , data, kPasteboardFlavorNoFlags);
320 CFRelease( data );
321 counter++;
322 fname = strtok (NULL,"\n");
323 }
324
325 }
326 else
327 {
328 CFDataRef data = CFDataCreate( kCFAllocatorDefault, (UInt8*)buf, datasize );
329 if ( thisFormat.GetType() == wxDF_TEXT )
330 PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) itemID,
331 CFSTR("com.apple.traditional-mac-plain-text") , data, kPasteboardFlavorNoFlags);
332 else
333 PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) itemID,
334 (CFStringRef) thisFormat.GetFormatId() , data, kPasteboardFlavorNoFlags);
335 CFRelease( data );
336 }
337 }
338 free( buf );
339 }
340 }
341
342 delete [] array;
343 }
344
345 bool wxDataObject::IsFormatInPasteboard( void * pb, const wxDataFormat &dataFormat )
346 {
347 PasteboardRef pasteboard = (PasteboardRef) pb;
348 bool hasData = false;
349 OSStatus err = noErr;
350 ItemCount itemCount;
351
352 // we synchronize here once again, so we don't mind which flags get returned
353 PasteboardSynchronize( pasteboard );
354
355 err = PasteboardGetItemCount( pasteboard, &itemCount );
356 if ( err == noErr )
357 {
358 for( UInt32 itemIndex = 1; itemIndex <= itemCount && hasData == false ; itemIndex++ )
359 {
360 PasteboardItemID itemID;
361 CFArrayRef flavorTypeArray;
362 CFIndex flavorCount;
363
364 err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
365 if ( err != noErr )
366 continue;
367
368 err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
369 if ( err != noErr )
370 continue;
371
372 flavorCount = CFArrayGetCount( flavorTypeArray );
373
374 for( CFIndex flavorIndex = 0; flavorIndex < flavorCount && hasData == false ; flavorIndex++ )
375 {
376 CFStringRef flavorType;
377
378 flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
379 flavorIndex );
380
381 wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
382 if ( dataFormat == flavorFormat )
383 hasData = true;
384 else if ( dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
385 hasData = true;
386 }
387 CFRelease (flavorTypeArray);
388 }
389 }
390
391 return hasData;
392 }
393
394 bool wxDataObject::GetFromPasteboard( void * pb )
395 {
396 PasteboardRef pasteboard = (PasteboardRef) pb;
397 size_t formatcount = GetFormatCount() + 1;
398 wxDataFormat *array = new wxDataFormat[ formatcount ];
399 array[0] = GetPreferredFormat();
400 GetAllFormats( &array[1] );
401 ItemCount itemCount = 0;
402 wxString filenamesPassed;
403 bool transferred = false;
404
405 // we synchronize here once again, so we don't mind which flags get returned
406 PasteboardSynchronize( pasteboard );
407
408 OSStatus err = PasteboardGetItemCount( pasteboard, &itemCount );
409 if ( err == noErr )
410 {
411 for (size_t i = 0; !transferred && i < formatcount; i++)
412 {
413 // go through the data in our order of preference
414 wxDataFormat dataFormat = array[ i ];
415
416 for( UInt32 itemIndex = 1; itemIndex <= itemCount && transferred == false ; itemIndex++ )
417 {
418 PasteboardItemID itemID = 0;
419 CFArrayRef flavorTypeArray = NULL;
420 CFIndex flavorCount = 0;
421
422 err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
423 if ( err != noErr )
424 continue;
425
426 err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
427 if ( err != noErr )
428 continue;
429
430 flavorCount = CFArrayGetCount( flavorTypeArray );
431
432 for( CFIndex flavorIndex = 0; !transferred && flavorIndex < flavorCount ; flavorIndex++ )
433 {
434 CFStringRef flavorType;
435 CFDataRef flavorData;
436 CFIndex flavorDataSize;
437
438 flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
439 flavorIndex );
440
441 wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
442
443 if ( dataFormat == flavorFormat )
444 {
445 if ( UTTypeConformsTo( (CFStringRef)flavorType, kPasteboardTypeFileURLPromise) )
446 {
447 wxString tempdir = wxFileName::GetTempDir() + wxFILE_SEP_PATH + "wxtemp.XXXXXX";
448 char* result = mkdtemp((char*)tempdir.fn_str().data());
449
450 if (!result)
451 continue;
452
453 wxCFRef<CFURLRef> dest(CFURLCreateFromFileSystemRepresentation(NULL,(const UInt8*)result,strlen(result),true));
454 PasteboardSetPasteLocation(pasteboard, dest);
455 }
456 else if ( flavorFormat.GetType() != wxDF_PRIVATE )
457 {
458 // indicate the expected format for the type, benefiting from native conversions eg utf8 -> utf16
459 flavorType = (CFStringRef) wxDataFormat( flavorFormat.GetType()).GetFormatId();
460 }
461
462 err = PasteboardCopyItemFlavorData( pasteboard, itemID, flavorType , &flavorData );
463 if ( err == noErr )
464 {
465 flavorDataSize = CFDataGetLength( flavorData );
466 if (dataFormat.GetType() == wxDF_FILENAME )
467 {
468 // revert the translation and decomposition to arrive at a proper utf8 string again
469 CFURLRef url = CFURLCreateWithBytes( kCFAllocatorDefault, CFDataGetBytePtr( flavorData ), flavorDataSize, kCFStringEncodingUTF8, NULL );
470 CFStringRef cfString = CFURLCopyFileSystemPath( url, kCFURLPOSIXPathStyle );
471 CFRelease( url );
472 CFMutableStringRef cfMutableString = CFStringCreateMutableCopy(NULL, 0, cfString);
473 CFRelease( cfString );
474 CFStringNormalize(cfMutableString,kCFStringNormalizationFormC);
475 wxString path = wxCFStringRef(cfMutableString).AsString();
476 if (!path.empty())
477 filenamesPassed += path + wxT("\n");
478 }
479 else
480 {
481 // because some data implementation expect trailing a trailing NUL, we add some headroom
482 void *buf = malloc( flavorDataSize + 4 );
483 if ( buf )
484 {
485 memset( buf, 0, flavorDataSize + 4 );
486 memcpy( buf, CFDataGetBytePtr( flavorData ), flavorDataSize );
487
488 if (dataFormat.GetType() == wxDF_TEXT)
489 wxMacConvertNewlines10To13( (char*) buf );
490 SetData( flavorFormat, flavorDataSize, buf );
491 transferred = true;
492 free( buf );
493 }
494 }
495 CFRelease (flavorData);
496 }
497 }
498 else if ( dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
499 {
500 err = PasteboardCopyItemFlavorData( pasteboard, itemID, flavorType, &flavorData );
501 if ( err == noErr )
502 {
503 flavorDataSize = CFDataGetLength( flavorData );
504 void *asciibuf = malloc( flavorDataSize + 1 );
505 if ( asciibuf )
506 {
507 memset( asciibuf, 0, flavorDataSize + 1 );
508 memcpy( asciibuf, CFDataGetBytePtr( flavorData ), flavorDataSize );
509 CFRelease (flavorData);
510
511 SetData( wxDF_TEXT, flavorDataSize, asciibuf );
512 transferred = true;
513 free( asciibuf );
514 }
515 else
516 CFRelease (flavorData);
517 }
518 }
519 }
520 CFRelease( flavorTypeArray );
521 }
522 if ( !filenamesPassed.empty() )
523 {
524 wxCharBuffer buf = filenamesPassed.fn_str();
525 SetData( wxDF_FILENAME, strlen( buf ), (const char*)buf );
526 transferred = true;
527 }
528 }
529 }
530 return transferred;
531 }
532
533 bool wxDataObject::HasDataInPasteboard( void * pb )
534 {
535 PasteboardRef pasteboard = (PasteboardRef) pb;
536 size_t formatcount = GetFormatCount() + 1;
537 wxDataFormat *array = new wxDataFormat[ formatcount ];
538 array[0] = GetPreferredFormat();
539 GetAllFormats( &array[1] );
540 ItemCount itemCount = 0;
541 bool hasData = false;
542
543 // we synchronize here once again, so we don't mind which flags get returned
544 PasteboardSynchronize( pasteboard );
545
546 OSStatus err = PasteboardGetItemCount( pasteboard, &itemCount );
547 if ( err == noErr )
548 {
549 for (size_t i = 0; !hasData && i < formatcount; i++)
550 {
551 // go through the data in our order of preference
552 wxDataFormat dataFormat = array[ i ];
553
554 for( UInt32 itemIndex = 1; itemIndex <= itemCount && hasData == false ; itemIndex++ )
555 {
556 PasteboardItemID itemID = 0;
557 CFArrayRef flavorTypeArray = NULL;
558 CFIndex flavorCount = 0;
559
560 err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
561 if ( err != noErr )
562 continue;
563
564 err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
565 if ( err != noErr )
566 continue;
567
568 flavorCount = CFArrayGetCount( flavorTypeArray );
569
570 for( CFIndex flavorIndex = 0; !hasData && flavorIndex < flavorCount ; flavorIndex++ )
571 {
572 CFStringRef flavorType;
573
574 flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
575 flavorIndex );
576
577 wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
578
579 if ( dataFormat == flavorFormat ||
580 (dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT) )
581 {
582 hasData = true;
583 }
584 }
585 CFRelease( flavorTypeArray );
586 }
587 }
588 }
589 return hasData;
590 }
591
592 // ----------------------------------------------------------------------------
593 // wxTextDataObject
594 // ----------------------------------------------------------------------------
595
596 #if wxUSE_UNICODE
597 void wxTextDataObject::GetAllFormats(wxDataFormat *formats,
598 wxDataObjectBase::Direction WXUNUSED(dir)) const
599 {
600 *formats++ = wxDataFormat( wxDF_TEXT );
601 *formats = wxDataFormat( wxDF_UNICODETEXT );
602 }
603 #endif
604
605 // ----------------------------------------------------------------------------
606 // wxFileDataObject
607 // ----------------------------------------------------------------------------
608
609 void wxFileDataObject::GetFileNames( wxCharBuffer &buf ) const
610 {
611 wxString filenames;
612
613 for (size_t i = 0; i < m_filenames.GetCount(); i++)
614 {
615 filenames += m_filenames[i];
616 filenames += wxT('\n');
617 }
618
619 buf = filenames.fn_str();
620 }
621
622 bool wxFileDataObject::GetDataHere( void *pBuf ) const
623 {
624 if (pBuf == NULL)
625 return false;
626
627 wxCharBuffer buf;
628 size_t buffLength;
629
630 GetFileNames( buf );
631 buffLength = strlen( buf );
632 memcpy( pBuf, (const char*)buf, buffLength + 1 );
633
634 return true;
635 }
636
637 size_t wxFileDataObject::GetDataSize() const
638 {
639 wxCharBuffer buf;
640 size_t buffLength;
641
642 GetFileNames( buf );
643 buffLength = strlen( buf );
644 // terminating 0
645 return buffLength + 1;
646 }
647
648 bool wxFileDataObject::SetData( size_t WXUNUSED(nSize), const void *pBuf )
649 {
650 wxString filenames;
651
652 #if wxUSE_UNICODE
653 filenames = wxString( (const char*)pBuf, *wxConvFileName );
654 #else
655 filenames = wxString (wxConvLocal.cWC2WX(wxConvFileName->cMB2WC( (const char*)pBuf)));
656 #endif
657
658 m_filenames = wxStringTokenize( filenames, wxT("\n"), wxTOKEN_STRTOK );
659
660 return true;
661 }
662
663 void wxFileDataObject::AddFile( const wxString& rFilename )
664 {
665 m_filenames.Add( rFilename );
666 }
667
668 // ----------------------------------------------------------------------------
669 // wxBitmapDataObject
670 // ----------------------------------------------------------------------------
671
672 wxBitmapDataObject::wxBitmapDataObject()
673 {
674 Init();
675 }
676
677 wxBitmapDataObject::wxBitmapDataObject( const wxBitmap& rBitmap )
678 : wxBitmapDataObjectBase( rBitmap )
679 {
680 Init();
681
682 if (m_bitmap.IsOk())
683 {
684 SetBitmap( rBitmap );
685 }
686 }
687
688 wxBitmapDataObject::~wxBitmapDataObject()
689 {
690 Clear();
691 }
692
693 void wxBitmapDataObject::SetBitmap( const wxBitmap& rBitmap )
694 {
695 Clear();
696 wxBitmapDataObjectBase::SetBitmap( rBitmap );
697 if (m_bitmap.IsOk())
698 {
699 CGImageRef cgImageRef = (CGImageRef) m_bitmap.CreateCGImage();
700
701 CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0);
702 CGImageDestinationRef destination = CGImageDestinationCreateWithData( data , kUTTypeTIFF , 1 , NULL );
703 if ( destination )
704 {
705 CGImageDestinationAddImage( destination, cgImageRef, NULL );
706 CGImageDestinationFinalize( destination );
707 CFRelease( destination );
708 }
709 m_pictHandle = NewHandle(CFDataGetLength(data));
710 if ( m_pictHandle )
711 {
712 memcpy( *(Handle)m_pictHandle, (const char *)CFDataGetBytePtr(data), CFDataGetLength(data) );
713 }
714 CFRelease( data );
715
716 CGImageRelease(cgImageRef);
717 }
718 }
719
720 void wxBitmapDataObject::Init()
721 {
722 m_pictHandle = NULL;
723 m_pictCreated = false;
724 }
725
726 void wxBitmapDataObject::Clear()
727 {
728 if (m_pictHandle != NULL)
729 {
730 DisposeHandle( (Handle) m_pictHandle );
731 m_pictHandle = NULL;
732 }
733 m_pictCreated = false;
734 }
735
736 bool wxBitmapDataObject::GetDataHere( void *pBuf ) const
737 {
738 if (m_pictHandle == NULL)
739 {
740 wxFAIL_MSG( wxT("attempt to copy empty bitmap failed") );
741 return false;
742 }
743
744 if (pBuf == NULL)
745 return false;
746
747 memcpy( pBuf, *(Handle)m_pictHandle, GetHandleSize( (Handle)m_pictHandle ) );
748
749 return true;
750 }
751
752 size_t wxBitmapDataObject::GetDataSize() const
753 {
754 if (m_pictHandle != NULL)
755 return GetHandleSize( (Handle)m_pictHandle );
756 else
757 return 0;
758 }
759
760 Handle MacCreateDataReferenceHandle(Handle theDataHandle)
761 {
762 Handle dataRef = NULL;
763 OSErr err = noErr;
764
765 // Create a data reference handle for our data.
766 err = PtrToHand( &theDataHandle, &dataRef, sizeof(Handle));
767
768 return dataRef;
769 }
770
771 bool wxBitmapDataObject::SetData( size_t nSize, const void *pBuf )
772 {
773 Clear();
774
775 if ((pBuf == NULL) || (nSize == 0))
776 return false;
777
778 Handle picHandle = NewHandle( nSize );
779 memcpy( *picHandle, pBuf, nSize );
780 m_pictHandle = picHandle;
781 CGImageRef cgImageRef = 0;
782
783 CFDataRef data = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault, (const UInt8*) pBuf, nSize, kCFAllocatorNull);
784 CGImageSourceRef source = CGImageSourceCreateWithData( data, NULL );
785 if ( source )
786 {
787 cgImageRef = CGImageSourceCreateImageAtIndex(source, 0, NULL);
788 CFRelease( source );
789 }
790 CFRelease( data );
791
792 if ( cgImageRef )
793 {
794 m_bitmap.Create( CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
795 CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
796 // since our context is upside down we dont use CGContextDrawImage
797 wxMacDrawCGImage( (CGContextRef) m_bitmap.GetHBITMAP() , &r, cgImageRef ) ;
798 CGImageRelease(cgImageRef);
799 cgImageRef = NULL;
800 }
801
802 return m_bitmap.IsOk();
803 }
804
805 #endif