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