using NSImage as first-class native representation
If given an NSImage this will be used, unless raw bitmap data access is needed, lazily converting to a CGBitmapContext at that moment
This commit is contained in:
committed by
Vadim Zeitlin
parent
3e6d927eab
commit
ee8132fea9
@@ -37,12 +37,9 @@ CGDataProviderRef wxMacCGDataProviderCreateWithMemoryBuffer( const wxMemoryBuffe
|
||||
// Implementation Notes
|
||||
// --------------------
|
||||
//
|
||||
// we are always working with a 32 bit deep pixel buffer
|
||||
// under QuickDraw its alpha parts are going to be ignored in the GWorld,
|
||||
// therefore we have a separate GWorld there for blitting the mask in
|
||||
|
||||
// under Quartz then content is transformed into a CGImageRef representing the same data
|
||||
// which can be transferred to the GPU by the OS for fast rendering
|
||||
// A bitmap can be represented using an NSImage or a CGBitmapContextRef
|
||||
// If raw bitmap data needs to be accessed, then even the NSImage has to be
|
||||
// rendered into a CGBitmapContextRef
|
||||
|
||||
class WXDLLEXPORT wxBitmapRefData: public wxGDIRefData
|
||||
{
|
||||
@@ -52,31 +49,23 @@ public:
|
||||
wxBitmapRefData(int width , int height , int depth, double logicalscale = 1.0);
|
||||
wxBitmapRefData(CGContextRef context);
|
||||
wxBitmapRefData(CGImageRef image, double scale);
|
||||
wxBitmapRefData(WX_NSImage image);
|
||||
wxBitmapRefData();
|
||||
wxBitmapRefData(const wxBitmapRefData &tocopy);
|
||||
|
||||
virtual ~wxBitmapRefData();
|
||||
|
||||
virtual bool IsOk() const wxOVERRIDE { return m_ok; }
|
||||
bool IsOk() const;
|
||||
|
||||
void Free();
|
||||
|
||||
#if wxOSX_BITMAP_NATIVE_ACCESS
|
||||
int GetWidth() const
|
||||
{ return CGBitmapContextGetWidth(m_hBitmap); }
|
||||
int GetHeight() const
|
||||
{ return CGBitmapContextGetHeight(m_hBitmap); }
|
||||
int GetDepth() const
|
||||
{ return CGBitmapContextGetBitsPerPixel(m_hBitmap); }
|
||||
int GetBytesPerRow() const
|
||||
{ return CGBitmapContextGetBytesPerRow(m_hBitmap); }
|
||||
bool HasAlpha() const
|
||||
{
|
||||
CGImageAlphaInfo alpha = CGBitmapContextGetAlphaInfo(m_hBitmap);
|
||||
return !(alpha == kCGImageAlphaNone ||
|
||||
alpha == kCGImageAlphaNoneSkipFirst ||
|
||||
alpha == kCGImageAlphaNoneSkipLast);
|
||||
}
|
||||
int GetWidth() const;
|
||||
int GetHeight() const;
|
||||
int GetDepth() const;
|
||||
int GetBytesPerRow() const;
|
||||
bool HasAlpha() const;
|
||||
WX_NSImage GetNSImage() const;
|
||||
#else
|
||||
void SetWidth( int width ) { m_width = width; }
|
||||
void SetHeight( int height ) { m_height = height; }
|
||||
@@ -130,7 +119,11 @@ private :
|
||||
bool Create(int width , int height , int depth, double logicalscale);
|
||||
bool Create( CGImageRef image, double scale );
|
||||
bool Create( CGContextRef bitmapcontext);
|
||||
bool Create( WX_NSImage image);
|
||||
void Init();
|
||||
|
||||
void EnsureBitmapExists() const;
|
||||
|
||||
void FreeDerivedRepresentations();
|
||||
|
||||
#if !wxOSX_BITMAP_NATIVE_ACCESS
|
||||
@@ -140,9 +133,11 @@ private :
|
||||
int m_depth;
|
||||
bool m_hasAlpha;
|
||||
wxMemoryBuffer m_memBuf;
|
||||
bool m_ok;
|
||||
#else
|
||||
WX_NSImage m_nsImage;
|
||||
#endif
|
||||
int m_rawAccessCount;
|
||||
bool m_ok;
|
||||
mutable CGImageRef m_cgImageRef;
|
||||
bool m_isTemplate;
|
||||
|
||||
@@ -187,8 +182,9 @@ void wxBitmapRefData::Init()
|
||||
m_depth = 0 ;
|
||||
m_bytesPerRow = 0;
|
||||
m_hasAlpha = false;
|
||||
#else
|
||||
m_nsImage = NULL;
|
||||
#endif
|
||||
m_ok = false ;
|
||||
m_bitmapMask = NULL ;
|
||||
m_cgImageRef = NULL ;
|
||||
m_isTemplate = false;
|
||||
@@ -241,6 +237,32 @@ wxBitmapRefData::wxBitmapRefData(CGImageRef image, double scale)
|
||||
Init();
|
||||
Create( image, scale );
|
||||
}
|
||||
|
||||
wxBitmapRefData::wxBitmapRefData(WX_NSImage image)
|
||||
{
|
||||
Init();
|
||||
Create( image );
|
||||
}
|
||||
|
||||
void wxBitmapRefData::EnsureBitmapExists() const
|
||||
{
|
||||
if ( ! m_hBitmap && m_nsImage)
|
||||
{
|
||||
wxBitmapRefData* t = const_cast<wxBitmapRefData*>(this);
|
||||
t->m_hBitmap = wxOSXCreateBitmapContextFromNSImage(m_nsImage, &t->m_isTemplate);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool wxBitmapRefData::Create( WX_NSImage image )
|
||||
{
|
||||
m_nsImage = image;
|
||||
|
||||
wxMacCocoaRetain(image);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// code from Technical Q&A QA1509
|
||||
|
||||
bool wxBitmapRefData::Create(CGImageRef image, double scale)
|
||||
@@ -289,10 +311,7 @@ bool wxBitmapRefData::Create(CGImageRef image, double scale)
|
||||
} /* data != NULL */
|
||||
#endif
|
||||
}
|
||||
m_ok = ( m_hBitmap != NULL ) ;
|
||||
|
||||
return m_ok ;
|
||||
|
||||
return IsOk() ;
|
||||
}
|
||||
|
||||
bool wxBitmapRefData::Create(CGContextRef context)
|
||||
@@ -336,9 +355,7 @@ bool wxBitmapRefData::Create(CGContextRef context)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
m_ok = ( m_hBitmap != NULL ) ;
|
||||
|
||||
return m_ok ;
|
||||
return IsOk() ;
|
||||
}
|
||||
|
||||
bool wxBitmapRefData::Create( int w , int h , int d, double logicalscale )
|
||||
@@ -370,13 +387,94 @@ bool wxBitmapRefData::Create( int w , int h , int d, double logicalscale )
|
||||
#if !wxOSX_BITMAP_NATIVE_ACCESS
|
||||
} /* data != NULL */
|
||||
#endif
|
||||
m_ok = ( m_hBitmap != NULL ) ;
|
||||
|
||||
return m_ok ;
|
||||
return IsOk() ;
|
||||
}
|
||||
|
||||
bool wxBitmapRefData::IsOk() const
|
||||
{
|
||||
return ( m_hBitmap.get() != NULL
|
||||
#if wxOSX_BITMAP_NATIVE_ACCESS
|
||||
|| m_nsImage != NULL
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
#if wxOSX_BITMAP_NATIVE_ACCESS
|
||||
|
||||
int wxBitmapRefData::GetWidth() const
|
||||
{
|
||||
wxCHECK_MSG( IsOk() , 0 , "Invalid Bitmap");
|
||||
|
||||
if ( m_hBitmap )
|
||||
return CGBitmapContextGetWidth(m_hBitmap);
|
||||
else
|
||||
return (int) wxOSXGetImageSize(m_nsImage).width;
|
||||
}
|
||||
|
||||
int wxBitmapRefData::GetHeight() const
|
||||
{
|
||||
wxCHECK_MSG( IsOk() , 0 , "Invalid Bitmap");
|
||||
|
||||
if ( m_hBitmap )
|
||||
return CGBitmapContextGetHeight(m_hBitmap);
|
||||
else
|
||||
return (int) wxOSXGetImageSize(m_nsImage).height;
|
||||
}
|
||||
|
||||
int wxBitmapRefData::GetDepth() const
|
||||
{
|
||||
wxCHECK_MSG( IsOk() , 0 , "Invalid Bitmap");
|
||||
|
||||
if ( m_hBitmap )
|
||||
return CGBitmapContextGetBitsPerPixel(m_hBitmap);
|
||||
else
|
||||
return 32; // a bitmap converted from an nsimage would have this depth
|
||||
}
|
||||
int wxBitmapRefData::GetBytesPerRow() const
|
||||
{
|
||||
wxCHECK_MSG( IsOk() , 0 , "Invalid Bitmap");
|
||||
|
||||
if ( m_hBitmap )
|
||||
return CGBitmapContextGetBytesPerRow(m_hBitmap);
|
||||
else
|
||||
return GetBestBytesPerRow( GetWidth() * 4);
|
||||
}
|
||||
|
||||
bool wxBitmapRefData::HasAlpha() const
|
||||
{
|
||||
wxCHECK_MSG( IsOk() , 0 , "Invalid Bitmap");
|
||||
|
||||
if ( m_hBitmap )
|
||||
{
|
||||
CGImageAlphaInfo alpha = CGBitmapContextGetAlphaInfo(m_hBitmap);
|
||||
return !(alpha == kCGImageAlphaNone || alpha == kCGImageAlphaNoneSkipFirst || alpha == kCGImageAlphaNoneSkipLast);
|
||||
}
|
||||
else
|
||||
{
|
||||
return true; // a bitmap converted from an nsimage would have alpha
|
||||
}
|
||||
}
|
||||
|
||||
WX_NSImage wxBitmapRefData::GetNSImage() const
|
||||
{
|
||||
wxCHECK_MSG( IsOk() , 0 , "Invalid Bitmap");
|
||||
|
||||
if ( !m_nsImage )
|
||||
{
|
||||
wxCFRef< CGImageRef > cgimage(CreateCGImage());
|
||||
return wxOSXGetNSImageFromCGImage( cgimage, GetScaleFactor(), IsTemplate() );
|
||||
}
|
||||
|
||||
return m_nsImage;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
void wxBitmapRefData::UseAlpha( bool use )
|
||||
{
|
||||
wxCHECK_RET( IsOk() , wxT("invalid bitmap") ) ;
|
||||
|
||||
if ( HasAlpha() == use )
|
||||
return ;
|
||||
|
||||
@@ -400,6 +498,9 @@ void wxBitmapRefData::UseAlpha( bool use )
|
||||
const void *wxBitmapRefData::GetRawAccess() const
|
||||
{
|
||||
wxCHECK_MSG( IsOk(), NULL , wxT("invalid bitmap") ) ;
|
||||
|
||||
EnsureBitmapExists();
|
||||
|
||||
#if !wxOSX_BITMAP_NATIVE_ACCESS
|
||||
return m_memBuf.GetData() ;
|
||||
#else
|
||||
@@ -665,10 +766,16 @@ IconRef wxBitmapRefData::GetIconRef()
|
||||
|
||||
CGImageRef wxBitmapRefData::CreateCGImage() const
|
||||
{
|
||||
wxASSERT( m_ok ) ;
|
||||
wxASSERT( IsOk() ) ;
|
||||
wxASSERT( m_rawAccessCount >= 0 ) ;
|
||||
CGImageRef image ;
|
||||
if ( m_rawAccessCount > 0 || m_cgImageRef == NULL )
|
||||
{
|
||||
if (m_nsImage)
|
||||
{
|
||||
image = wxOSXCreateCGImageFromNSImage(m_nsImage);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GetDepth() != 1 && m_bitmapMask == NULL)
|
||||
{
|
||||
@@ -749,8 +856,7 @@ CGImageRef wxBitmapRefData::CreateCGImage() const
|
||||
}
|
||||
maskBuf.UngetWriteBuf(GetWidth() * GetHeight());
|
||||
|
||||
dataProvider =
|
||||
wxMacCGDataProviderCreateWithMemoryBuffer( maskBuf );
|
||||
dataProvider = wxMacCGDataProviderCreateWithMemoryBuffer(maskBuf);
|
||||
|
||||
image = ::CGImageMaskCreate(w, h, 8, 8, GetWidth(), dataProvider, NULL, false);
|
||||
}
|
||||
@@ -758,14 +864,14 @@ CGImageRef wxBitmapRefData::CreateCGImage() const
|
||||
{
|
||||
CGColorSpaceRef colorSpace = wxMacGetGenericRGBColorSpace();
|
||||
dataProvider = wxMacCGDataProviderCreateWithMemoryBuffer(membuf);
|
||||
image =
|
||||
::CGImageCreate(
|
||||
image = ::CGImageCreate(
|
||||
w, h, 8, 32, GetBytesPerRow(), colorSpace, alphaInfo,
|
||||
dataProvider, NULL, false, kCGRenderingIntentDefault);
|
||||
}
|
||||
CGDataProviderRelease(dataProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
image = m_cgImageRef ;
|
||||
@@ -832,6 +938,8 @@ void wxBitmapRefData::Free()
|
||||
|
||||
FreeDerivedRepresentations();
|
||||
|
||||
wxMacCocoaRelease(m_nsImage);
|
||||
|
||||
m_hBitmap.reset();
|
||||
wxDELETE(m_bitmapMask);
|
||||
}
|
||||
@@ -849,6 +957,9 @@ wxBitmapRefData::~wxBitmapRefData()
|
||||
|
||||
bool wxBitmap::CopyFromIcon(const wxIcon& icon)
|
||||
{
|
||||
#if wxOSX_BITMAP_NATIVE_ACCESS
|
||||
return Create( icon.GetNSImage() );
|
||||
#else
|
||||
int w = icon.GetWidth() ;
|
||||
int h = icon.GetHeight() ;
|
||||
|
||||
@@ -866,6 +977,7 @@ bool wxBitmap::CopyFromIcon(const wxIcon& icon)
|
||||
}
|
||||
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
wxBitmap::wxBitmap(const char bits[], int the_width, int the_height, int no_bits)
|
||||
@@ -1006,11 +1118,11 @@ wxBitmap::wxBitmap(WX_NSImage image)
|
||||
|
||||
bool wxBitmap::Create(WX_NSImage image)
|
||||
{
|
||||
bool isTemplate;
|
||||
if (!Create(wxOSXCreateBitmapContextFromNSImage(image, &isTemplate)))
|
||||
return false;
|
||||
GetBitmapData()->SetTemplate(isTemplate);
|
||||
return true;
|
||||
UnRef();
|
||||
|
||||
m_refData = new wxBitmapRefData( image );
|
||||
|
||||
return GetBitmapData()->IsOk() ;
|
||||
}
|
||||
|
||||
wxBitmap::wxBitmap(CGContextRef bitmapcontext)
|
||||
@@ -1029,8 +1141,7 @@ bool wxBitmap::Create(CGContextRef bitmapcontext)
|
||||
|
||||
WX_NSImage wxBitmap::GetNSImage() const
|
||||
{
|
||||
wxCFRef< CGImageRef > cgimage(CreateCGImage());
|
||||
return wxOSXGetNSImageFromCGImage( cgimage, GetScaleFactor(), GetBitmapData()->IsTemplate() );
|
||||
return GetBitmapData()->GetNSImage();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user