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