git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@54129 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
754 lines
24 KiB
C++
754 lines
24 KiB
C++
///////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/mac/carbon/dataobj.cpp
|
|
// Purpose: implementation of wxDataObject class
|
|
// Author: Stefan Csomor
|
|
// Modified by:
|
|
// Created: 10/21/99
|
|
// RCS-ID: $Id$
|
|
// Copyright: (c) 1999 Stefan Csomor
|
|
// Licence: wxWindows licence
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// For compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#if wxUSE_DATAOBJ
|
|
|
|
#include "wx/dataobj.h"
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/intl.h"
|
|
#include "wx/log.h"
|
|
#include "wx/dcmemory.h"
|
|
#include "wx/image.h"
|
|
#endif
|
|
|
|
#include "wx/mstream.h"
|
|
#include "wx/metafile.h"
|
|
#include "wx/tokenzr.h"
|
|
|
|
#include "wx/osx/uma.h"
|
|
|
|
#ifdef __DARWIN__
|
|
#include <QuickTime/QuickTime.h>
|
|
#endif
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxDataFormat
|
|
// ----------------------------------------------------------------------------
|
|
|
|
wxDataFormat::wxDataFormat()
|
|
{
|
|
m_type = wxDF_INVALID;
|
|
m_format = 0;
|
|
}
|
|
|
|
wxDataFormat::wxDataFormat( wxDataFormatId vType )
|
|
{
|
|
m_format = 0;
|
|
m_type = wxDF_INVALID;
|
|
SetType( vType );
|
|
}
|
|
|
|
wxDataFormat::wxDataFormat( const wxChar *zId )
|
|
{
|
|
m_format = 0;
|
|
m_type = wxDF_INVALID;
|
|
SetId( zId );
|
|
}
|
|
|
|
wxDataFormat::wxDataFormat( const wxString& rId )
|
|
{
|
|
m_format = 0;
|
|
m_type = wxDF_INVALID;
|
|
SetId( rId );
|
|
}
|
|
|
|
wxDataFormat::wxDataFormat(const wxDataFormat& rFormat)
|
|
{
|
|
if ( rFormat.m_format )
|
|
m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)rFormat.m_format);
|
|
else
|
|
m_format = 0;
|
|
m_type = rFormat.m_type;
|
|
m_id = rFormat.m_id;
|
|
}
|
|
|
|
wxDataFormat::wxDataFormat( NativeFormat vFormat )
|
|
{
|
|
m_format = 0;
|
|
m_type = wxDF_INVALID;
|
|
SetId( vFormat );
|
|
}
|
|
|
|
wxDataFormat::~wxDataFormat()
|
|
{
|
|
if ( m_format != 0 )
|
|
{
|
|
CFRelease( (CFStringRef) m_format );
|
|
m_format = 0;
|
|
}
|
|
}
|
|
|
|
// in order to be correct for 10.3 we restrict to the available types there
|
|
// http://developer.apple.com/qa/qa2005/qa1406.html
|
|
// TODO : Use UTCoreTypes.h constants once we support 10.4+ only
|
|
|
|
wxDataFormat& wxDataFormat::operator=(const wxDataFormat& rFormat)
|
|
{
|
|
if ( m_format != 0 )
|
|
{
|
|
CFRelease( (CFStringRef) m_format );
|
|
m_format = 0;
|
|
}
|
|
if ( rFormat.m_format )
|
|
m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)rFormat.m_format);
|
|
m_type = rFormat.m_type;
|
|
m_id = rFormat.m_id;
|
|
return *this;
|
|
}
|
|
|
|
void wxDataFormat::SetType( wxDataFormatId dataType )
|
|
{
|
|
m_type = dataType;
|
|
if ( m_format != 0 )
|
|
{
|
|
CFRelease( (CFStringRef) m_format );
|
|
m_format = 0;
|
|
}
|
|
|
|
switch (m_type)
|
|
{
|
|
case wxDF_TEXT:
|
|
m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.plain-text") );
|
|
break;
|
|
|
|
case wxDF_UNICODETEXT:
|
|
m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.utf16-plain-text") );
|
|
break;
|
|
|
|
case wxDF_BITMAP:
|
|
m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.tiff") );
|
|
break;
|
|
case wxDF_METAFILE:
|
|
m_format = (long) CFStringCreateCopy( NULL, CFSTR("com.adobe.pdf") );
|
|
break;
|
|
|
|
case wxDF_FILENAME:
|
|
m_format = (long) CFStringCreateCopy( NULL, CFSTR("public.file-url") );
|
|
break;
|
|
|
|
default:
|
|
wxFAIL_MSG( wxT("invalid data format") );
|
|
break;
|
|
}
|
|
}
|
|
|
|
wxString wxDataFormat::GetId() const
|
|
{
|
|
return wxCFStringRef(wxCFRetain((CFStringRef)m_format)).AsString();
|
|
}
|
|
|
|
void wxDataFormat::SetId( NativeFormat format )
|
|
{
|
|
if ( m_format != 0 )
|
|
{
|
|
CFRelease( (CFStringRef) m_format );
|
|
m_format = 0;
|
|
}
|
|
m_format = (NativeFormat) CFStringCreateCopy(NULL, (CFStringRef)format);
|
|
if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.utf16-plain-text") ) )
|
|
{
|
|
m_type = wxDF_UNICODETEXT;
|
|
}
|
|
else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.plain-text") ) )
|
|
{
|
|
m_type = wxDF_TEXT;
|
|
}
|
|
else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.tiff") ) )
|
|
{
|
|
m_type = wxDF_BITMAP;
|
|
}
|
|
else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("com.adobe.pdf") ) )
|
|
{
|
|
m_type = wxDF_METAFILE;
|
|
}
|
|
else if ( UTTypeConformsTo( (CFStringRef)format, CFSTR("public.file-url") ) )
|
|
{
|
|
m_type = wxDF_FILENAME;
|
|
}
|
|
else
|
|
{
|
|
m_type = wxDF_PRIVATE;
|
|
m_id = wxCFStringRef( (CFStringRef) CFRetain((CFStringRef) format )).AsString();
|
|
}
|
|
}
|
|
|
|
void wxDataFormat::SetId( const wxString& zId )
|
|
{
|
|
m_type = wxDF_PRIVATE;
|
|
m_id = zId;
|
|
if ( m_format != 0 )
|
|
{
|
|
CFRelease( (CFStringRef) m_format );
|
|
m_format = 0;
|
|
}
|
|
// since it is private, no need to conform to anything ...
|
|
m_format = (long) wxCFRetain( (CFStringRef) wxCFStringRef(m_id) );
|
|
}
|
|
|
|
bool wxDataFormat::operator==(const wxDataFormat& format) const
|
|
{
|
|
if (IsStandard() || format.IsStandard())
|
|
return (format.m_type == m_type);
|
|
else
|
|
return ( UTTypeConformsTo( (CFStringRef) m_format , (CFStringRef) format.m_format ) );
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
// wxDataObject
|
|
//-------------------------------------------------------------------------
|
|
|
|
wxDataObject::wxDataObject()
|
|
{
|
|
}
|
|
|
|
bool wxDataObject::IsSupportedFormat( const wxDataFormat& rFormat, Direction vDir ) const
|
|
{
|
|
size_t nFormatCount = GetFormatCount( vDir );
|
|
bool found = false;
|
|
|
|
if (nFormatCount == 1)
|
|
{
|
|
found = (rFormat == GetPreferredFormat());
|
|
}
|
|
else
|
|
{
|
|
wxDataFormat *pFormats = new wxDataFormat[nFormatCount];
|
|
GetAllFormats( pFormats, vDir );
|
|
|
|
for (size_t n = 0; n < nFormatCount; n++)
|
|
{
|
|
if (pFormats[n] == rFormat)
|
|
{
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
delete [] pFormats;
|
|
}
|
|
|
|
return found;
|
|
}
|
|
|
|
void wxDataObject::AddToPasteboard( void * pb, int itemID )
|
|
{
|
|
PasteboardRef pasteboard = (PasteboardRef) pb;
|
|
// get formats from wxDataObjects
|
|
wxDataFormat *array = new wxDataFormat[ GetFormatCount() ];
|
|
GetAllFormats( array );
|
|
|
|
for (size_t i = 0; i < GetFormatCount(); i++)
|
|
{
|
|
wxDataFormat thisFormat = array[ i ];
|
|
|
|
// add four bytes at the end for data objs like text that
|
|
// have a datasize = strlen but still need a buffer for the
|
|
// string including trailing zero
|
|
|
|
size_t datasize = GetDataSize( thisFormat );
|
|
size_t sz = datasize + 4;
|
|
void* buf = malloc( sz );
|
|
if ( buf != NULL )
|
|
{
|
|
// empty the buffer because in some case GetDataHere does not fill buf
|
|
memset( buf, 0, sz );
|
|
if ( GetDataHere( array[ i ], buf ) )
|
|
{
|
|
int counter = 1 ;
|
|
if ( thisFormat.GetType() == wxDF_FILENAME )
|
|
{
|
|
// the data is D-normalized UTF8 strings of filenames delimited with \n
|
|
char *fname = strtok((char*) buf,"\n");
|
|
while (fname != NULL)
|
|
{
|
|
// translate the filepath into a fileurl and put that into the pasteobard
|
|
CFStringRef path = CFStringCreateWithBytes(NULL,(UInt8*)fname,strlen(fname),kCFStringEncodingUTF8,false);
|
|
CFURLRef url = CFURLCreateWithFileSystemPath(NULL, path , kCFURLPOSIXPathStyle, false);
|
|
CFRelease(path);
|
|
CFDataRef data = CFURLCreateData(NULL,url,kCFStringEncodingUTF8,true);
|
|
CFRelease(url);
|
|
PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) counter,
|
|
(CFStringRef) thisFormat.GetFormatId() , data, kPasteboardFlavorNoFlags);
|
|
CFRelease( data );
|
|
counter++;
|
|
fname = strtok (NULL,"\n");
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
CFDataRef data = CFDataCreate( kCFAllocatorDefault, (UInt8*)buf, datasize );
|
|
if ( thisFormat.GetType() == wxDF_TEXT )
|
|
PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) itemID,
|
|
CFSTR("com.apple.traditional-mac-plain-text") , data, kPasteboardFlavorNoFlags);
|
|
else
|
|
PasteboardPutItemFlavor( pasteboard, (PasteboardItemID) itemID,
|
|
(CFStringRef) thisFormat.GetFormatId() , data, kPasteboardFlavorNoFlags);
|
|
CFRelease( data );
|
|
}
|
|
}
|
|
free( buf );
|
|
}
|
|
}
|
|
|
|
delete [] array;
|
|
}
|
|
|
|
bool wxDataObject::IsFormatInPasteboard( void * pb, const wxDataFormat &dataFormat )
|
|
{
|
|
PasteboardRef pasteboard = (PasteboardRef) pb;
|
|
bool hasData = false;
|
|
OSStatus err = noErr;
|
|
ItemCount itemCount;
|
|
|
|
// we synchronize here once again, so we don't mind which flags get returned
|
|
PasteboardSynchronize( pasteboard );
|
|
|
|
err = PasteboardGetItemCount( pasteboard, &itemCount );
|
|
if ( err == noErr )
|
|
{
|
|
for( UInt32 itemIndex = 1; itemIndex <= itemCount && hasData == false ; itemIndex++ )
|
|
{
|
|
PasteboardItemID itemID;
|
|
CFArrayRef flavorTypeArray;
|
|
CFIndex flavorCount;
|
|
|
|
err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
|
|
if ( err != noErr )
|
|
continue;
|
|
|
|
err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
|
|
if ( err != noErr )
|
|
continue;
|
|
|
|
flavorCount = CFArrayGetCount( flavorTypeArray );
|
|
|
|
for( CFIndex flavorIndex = 0; flavorIndex < flavorCount && hasData == false ; flavorIndex++ )
|
|
{
|
|
CFStringRef flavorType;
|
|
|
|
flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
|
|
flavorIndex );
|
|
|
|
wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
|
|
if ( dataFormat == flavorFormat )
|
|
hasData = true;
|
|
else if ( dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
|
|
hasData = true;
|
|
}
|
|
CFRelease (flavorTypeArray);
|
|
}
|
|
}
|
|
|
|
return hasData;
|
|
}
|
|
|
|
bool wxDataObject::GetFromPasteboard( void * pb )
|
|
{
|
|
PasteboardRef pasteboard = (PasteboardRef) pb;
|
|
size_t formatcount = GetFormatCount() + 1;
|
|
wxDataFormat *array = new wxDataFormat[ formatcount ];
|
|
array[0] = GetPreferredFormat();
|
|
GetAllFormats( &array[1] );
|
|
ItemCount itemCount = 0;
|
|
wxString filenamesPassed;
|
|
bool transferred = false;
|
|
|
|
// we synchronize here once again, so we don't mind which flags get returned
|
|
PasteboardSynchronize( pasteboard );
|
|
|
|
OSStatus err = PasteboardGetItemCount( pasteboard, &itemCount );
|
|
if ( err == noErr )
|
|
{
|
|
for (size_t i = 0; !transferred && i < formatcount; i++)
|
|
{
|
|
// go through the data in our order of preference
|
|
wxDataFormat dataFormat = array[ i ];
|
|
|
|
for( UInt32 itemIndex = 1; itemIndex <= itemCount && transferred == false ; itemIndex++ )
|
|
{
|
|
PasteboardItemID itemID = 0;
|
|
CFArrayRef flavorTypeArray = NULL;
|
|
CFIndex flavorCount = 0;
|
|
|
|
err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
|
|
if ( err != noErr )
|
|
continue;
|
|
|
|
err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
|
|
if ( err != noErr )
|
|
continue;
|
|
|
|
flavorCount = CFArrayGetCount( flavorTypeArray );
|
|
|
|
for( CFIndex flavorIndex = 0; !transferred && flavorIndex < flavorCount ; flavorIndex++ )
|
|
{
|
|
CFStringRef flavorType;
|
|
CFDataRef flavorData;
|
|
CFIndex flavorDataSize;
|
|
|
|
flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
|
|
flavorIndex );
|
|
|
|
wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
|
|
|
|
if ( dataFormat == flavorFormat )
|
|
{
|
|
err = PasteboardCopyItemFlavorData( pasteboard, itemID, flavorType , &flavorData );
|
|
if ( err == noErr )
|
|
{
|
|
flavorDataSize = CFDataGetLength( flavorData );
|
|
if (dataFormat.GetType() == wxDF_FILENAME )
|
|
{
|
|
// revert the translation and decomposition to arrive at a proper utf8 string again
|
|
CFURLRef url = CFURLCreateWithBytes( kCFAllocatorDefault, CFDataGetBytePtr( flavorData ), flavorDataSize, kCFStringEncodingUTF8, NULL );
|
|
CFStringRef cfString = CFURLCopyFileSystemPath( url, kCFURLPOSIXPathStyle );
|
|
CFRelease( url );
|
|
CFMutableStringRef cfMutableString = CFStringCreateMutableCopy(NULL, 0, cfString);
|
|
CFRelease( cfString );
|
|
CFStringNormalize(cfMutableString,kCFStringNormalizationFormC);
|
|
wxString path = wxCFStringRef(cfMutableString).AsString();
|
|
if (!path.empty())
|
|
filenamesPassed += path + wxT("\n");
|
|
}
|
|
else
|
|
{
|
|
// because some data implementation expect trailing a trailing NUL, we add some headroom
|
|
void *buf = malloc( flavorDataSize + 4 );
|
|
if ( buf )
|
|
{
|
|
memset( buf, 0, flavorDataSize + 4 );
|
|
memcpy( buf, CFDataGetBytePtr( flavorData ), flavorDataSize );
|
|
|
|
if (dataFormat.GetType() == wxDF_TEXT)
|
|
wxMacConvertNewlines10To13( (char*) buf );
|
|
SetData( flavorFormat, flavorDataSize, buf );
|
|
transferred = true;
|
|
free( buf );
|
|
}
|
|
}
|
|
CFRelease (flavorData);
|
|
}
|
|
}
|
|
else if ( dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
|
|
{
|
|
err = PasteboardCopyItemFlavorData( pasteboard, itemID, flavorType, &flavorData );
|
|
if ( err == noErr )
|
|
{
|
|
flavorDataSize = CFDataGetLength( flavorData );
|
|
void *asciibuf = malloc( flavorDataSize + 1 );
|
|
if ( asciibuf )
|
|
{
|
|
memset( asciibuf, 0, flavorDataSize + 1 );
|
|
memcpy( asciibuf, CFDataGetBytePtr( flavorData ), flavorDataSize );
|
|
CFRelease (flavorData);
|
|
|
|
SetData( wxDF_TEXT, flavorDataSize, asciibuf );
|
|
transferred = true;
|
|
free( asciibuf );
|
|
}
|
|
else
|
|
CFRelease (flavorData);
|
|
}
|
|
}
|
|
}
|
|
CFRelease( flavorTypeArray );
|
|
}
|
|
if (filenamesPassed.length() > 0)
|
|
{
|
|
wxCharBuffer buf = filenamesPassed.fn_str();
|
|
SetData( wxDF_FILENAME, strlen( buf ), (const char*)buf );
|
|
transferred = true;
|
|
}
|
|
}
|
|
}
|
|
return transferred;
|
|
}
|
|
|
|
bool wxDataObject::HasDataInPasteboard( void * pb )
|
|
{
|
|
PasteboardRef pasteboard = (PasteboardRef) pb;
|
|
size_t formatcount = GetFormatCount() + 1;
|
|
wxDataFormat *array = new wxDataFormat[ formatcount ];
|
|
array[0] = GetPreferredFormat();
|
|
GetAllFormats( &array[1] );
|
|
ItemCount itemCount = 0;
|
|
bool hasData = false;
|
|
|
|
// we synchronize here once again, so we don't mind which flags get returned
|
|
PasteboardSynchronize( pasteboard );
|
|
|
|
OSStatus err = PasteboardGetItemCount( pasteboard, &itemCount );
|
|
if ( err == noErr )
|
|
{
|
|
for (size_t i = 0; !hasData && i < formatcount; i++)
|
|
{
|
|
// go through the data in our order of preference
|
|
wxDataFormat dataFormat = array[ i ];
|
|
|
|
for( UInt32 itemIndex = 1; itemIndex <= itemCount && hasData == false ; itemIndex++ )
|
|
{
|
|
PasteboardItemID itemID = 0;
|
|
CFArrayRef flavorTypeArray = NULL;
|
|
CFIndex flavorCount = 0;
|
|
|
|
err = PasteboardGetItemIdentifier( pasteboard, itemIndex, &itemID );
|
|
if ( err != noErr )
|
|
continue;
|
|
|
|
err = PasteboardCopyItemFlavors( pasteboard, itemID, &flavorTypeArray );
|
|
if ( err != noErr )
|
|
continue;
|
|
|
|
flavorCount = CFArrayGetCount( flavorTypeArray );
|
|
|
|
for( CFIndex flavorIndex = 0; !hasData && flavorIndex < flavorCount ; flavorIndex++ )
|
|
{
|
|
CFStringRef flavorType;
|
|
|
|
flavorType = (CFStringRef)CFArrayGetValueAtIndex( flavorTypeArray,
|
|
flavorIndex );
|
|
|
|
wxDataFormat flavorFormat( (wxDataFormat::NativeFormat) flavorType );
|
|
|
|
if ( dataFormat == flavorFormat ||
|
|
dataFormat.GetType() == wxDF_UNICODETEXT && flavorFormat.GetType() == wxDF_TEXT )
|
|
{
|
|
hasData = true;
|
|
}
|
|
}
|
|
CFRelease( flavorTypeArray );
|
|
}
|
|
}
|
|
}
|
|
return hasData;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxTextDataObject
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#if wxUSE_UNICODE
|
|
void wxTextDataObject::GetAllFormats(wxDataFormat *formats,
|
|
wxDataObjectBase::Direction WXUNUSED(dir)) const
|
|
{
|
|
*formats++ = wxDataFormat( wxDF_TEXT );
|
|
*formats = wxDataFormat( wxDF_UNICODETEXT );
|
|
}
|
|
#endif
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxFileDataObject
|
|
// ----------------------------------------------------------------------------
|
|
|
|
void wxFileDataObject::GetFileNames( wxCharBuffer &buf ) const
|
|
{
|
|
wxString filenames;
|
|
|
|
for (size_t i = 0; i < m_filenames.GetCount(); i++)
|
|
{
|
|
filenames += m_filenames[i];
|
|
filenames += wxT('\n');
|
|
}
|
|
|
|
buf = filenames.fn_str();
|
|
}
|
|
|
|
bool wxFileDataObject::GetDataHere( void *pBuf ) const
|
|
{
|
|
if (pBuf == NULL)
|
|
return false;
|
|
|
|
wxCharBuffer buf;
|
|
size_t buffLength;
|
|
|
|
GetFileNames( buf );
|
|
buffLength = strlen( buf );
|
|
memcpy( pBuf, (const char*)buf, buffLength + 1 );
|
|
|
|
return true;
|
|
}
|
|
|
|
size_t wxFileDataObject::GetDataSize() const
|
|
{
|
|
wxCharBuffer buf;
|
|
size_t buffLength;
|
|
|
|
GetFileNames( buf );
|
|
buffLength = strlen( buf );
|
|
// terminating 0
|
|
return buffLength + 1;
|
|
}
|
|
|
|
bool wxFileDataObject::SetData( size_t WXUNUSED(nSize), const void *pBuf )
|
|
{
|
|
wxString filenames;
|
|
|
|
#if wxUSE_UNICODE
|
|
filenames = wxString( (const char*)pBuf, *wxConvFileName );
|
|
#else
|
|
filenames = wxString (wxConvLocal.cWC2WX(wxConvFileName->cMB2WC( (const char*)pBuf)));
|
|
#endif
|
|
|
|
m_filenames = wxStringTokenize( filenames, wxT("\n"), wxTOKEN_STRTOK );
|
|
|
|
return true;
|
|
}
|
|
|
|
void wxFileDataObject::AddFile( const wxString& rFilename )
|
|
{
|
|
m_filenames.Add( rFilename );
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxBitmapDataObject
|
|
// ----------------------------------------------------------------------------
|
|
|
|
wxBitmapDataObject::wxBitmapDataObject()
|
|
{
|
|
Init();
|
|
}
|
|
|
|
wxBitmapDataObject::wxBitmapDataObject( const wxBitmap& rBitmap )
|
|
: wxBitmapDataObjectBase( rBitmap )
|
|
{
|
|
Init();
|
|
|
|
if (m_bitmap.Ok())
|
|
{
|
|
SetBitmap( rBitmap );
|
|
}
|
|
}
|
|
|
|
wxBitmapDataObject::~wxBitmapDataObject()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void wxBitmapDataObject::SetBitmap( const wxBitmap& rBitmap )
|
|
{
|
|
Clear();
|
|
wxBitmapDataObjectBase::SetBitmap( rBitmap );
|
|
if (m_bitmap.Ok())
|
|
{
|
|
CGImageRef cgImageRef = (CGImageRef) m_bitmap.CreateCGImage();
|
|
|
|
CFMutableDataRef data = CFDataCreateMutable(kCFAllocatorDefault, 0);
|
|
CGImageDestinationRef destination = CGImageDestinationCreateWithData( data , kUTTypeTIFF , 1 , NULL );
|
|
if ( destination )
|
|
{
|
|
CGImageDestinationAddImage( destination, cgImageRef, NULL );
|
|
CGImageDestinationFinalize( destination );
|
|
CFRelease( destination );
|
|
}
|
|
m_pictHandle = NewHandle(CFDataGetLength(data));
|
|
if ( m_pictHandle )
|
|
{
|
|
memcpy( *(Handle)m_pictHandle, (const char *)CFDataGetBytePtr(data), CFDataGetLength(data) );
|
|
}
|
|
CFRelease( data );
|
|
|
|
CGImageRelease(cgImageRef);
|
|
}
|
|
}
|
|
|
|
void wxBitmapDataObject::Init()
|
|
{
|
|
m_pictHandle = NULL;
|
|
m_pictCreated = false;
|
|
}
|
|
|
|
void wxBitmapDataObject::Clear()
|
|
{
|
|
if (m_pictHandle != NULL)
|
|
{
|
|
DisposeHandle( (Handle) m_pictHandle );
|
|
m_pictHandle = NULL;
|
|
}
|
|
m_pictCreated = false;
|
|
}
|
|
|
|
bool wxBitmapDataObject::GetDataHere( void *pBuf ) const
|
|
{
|
|
if (m_pictHandle == NULL)
|
|
{
|
|
wxFAIL_MSG( wxT("attempt to copy empty bitmap failed") );
|
|
return false;
|
|
}
|
|
|
|
if (pBuf == NULL)
|
|
return false;
|
|
|
|
memcpy( pBuf, *(Handle)m_pictHandle, GetHandleSize( (Handle)m_pictHandle ) );
|
|
|
|
return true;
|
|
}
|
|
|
|
size_t wxBitmapDataObject::GetDataSize() const
|
|
{
|
|
if (m_pictHandle != NULL)
|
|
return GetHandleSize( (Handle)m_pictHandle );
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
Handle MacCreateDataReferenceHandle(Handle theDataHandle)
|
|
{
|
|
Handle dataRef = NULL;
|
|
OSErr err = noErr;
|
|
|
|
// Create a data reference handle for our data.
|
|
err = PtrToHand( &theDataHandle, &dataRef, sizeof(Handle));
|
|
|
|
return dataRef;
|
|
}
|
|
|
|
bool wxBitmapDataObject::SetData( size_t nSize, const void *pBuf )
|
|
{
|
|
Clear();
|
|
|
|
if ((pBuf == NULL) || (nSize == 0))
|
|
return false;
|
|
|
|
Handle picHandle = NewHandle( nSize );
|
|
memcpy( *picHandle, pBuf, nSize );
|
|
m_pictHandle = picHandle;
|
|
CGImageRef cgImageRef = 0;
|
|
|
|
CFDataRef data = CFDataCreateWithBytesNoCopy( kCFAllocatorDefault, (const UInt8*) pBuf, nSize, kCFAllocatorNull);
|
|
CGImageSourceRef source = CGImageSourceCreateWithData( data, NULL );
|
|
if ( source )
|
|
{
|
|
cgImageRef = CGImageSourceCreateImageAtIndex(source, 0, NULL);
|
|
}
|
|
CFRelease( source );
|
|
CFRelease( data );
|
|
|
|
if ( cgImageRef )
|
|
{
|
|
m_bitmap.Create( CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
|
|
CGRect r = CGRectMake( 0 , 0 , CGImageGetWidth(cgImageRef) , CGImageGetHeight(cgImageRef) );
|
|
// since our context is upside down we dont use CGContextDrawImage
|
|
wxMacDrawCGImage( (CGContextRef) m_bitmap.GetHBITMAP() , &r, cgImageRef ) ;
|
|
CGImageRelease(cgImageRef);
|
|
cgImageRef = NULL;
|
|
}
|
|
|
|
return m_bitmap.Ok();
|
|
}
|
|
|
|
#endif
|