Implement wxMask given a wxBitmap and a mask wxColour.
TODO: Masks from other sources. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@24719 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -24,38 +24,36 @@ class WXDLLEXPORT wxPixelDataBase;
|
|||||||
// ========================================================================
|
// ========================================================================
|
||||||
// wxMask
|
// wxMask
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
/* DFE: wxMask is not implemented yet */
|
|
||||||
|
|
||||||
// A mask is a mono bitmap used for drawing bitmaps
|
// A mask is a 1-bit alpha bitmap used for drawing bitmaps transparently.
|
||||||
// transparently.
|
|
||||||
class WXDLLEXPORT wxMask: public wxObject
|
class WXDLLEXPORT wxMask: public wxObject
|
||||||
{
|
{
|
||||||
DECLARE_DYNAMIC_CLASS(wxMask)
|
DECLARE_DYNAMIC_CLASS(wxMask)
|
||||||
public:
|
public:
|
||||||
wxMask();
|
wxMask();
|
||||||
|
|
||||||
// Construct a mask from a bitmap and a colour indicating
|
// Construct a mask from a bitmap and a colour indicating
|
||||||
// the transparent area
|
// the transparent area
|
||||||
wxMask(const wxBitmap& bitmap, const wxColour& colour);
|
wxMask(const wxBitmap& bitmap, const wxColour& colour);
|
||||||
|
|
||||||
// Construct a mask from a bitmap and a palette index indicating
|
// Construct a mask from a bitmap and a palette index indicating
|
||||||
// the transparent area
|
// the transparent area
|
||||||
wxMask(const wxBitmap& bitmap, int paletteIndex);
|
wxMask(const wxBitmap& bitmap, int paletteIndex);
|
||||||
|
|
||||||
// Construct a mask from a mono bitmap (copies the bitmap).
|
// Construct a mask from a mono bitmap (copies the bitmap).
|
||||||
wxMask(const wxBitmap& bitmap);
|
wxMask(const wxBitmap& bitmap);
|
||||||
|
|
||||||
~wxMask();
|
~wxMask();
|
||||||
|
|
||||||
bool Create(const wxBitmap& bitmap, const wxColour& colour);
|
bool Create(const wxBitmap& bitmap, const wxColour& colour);
|
||||||
bool Create(const wxBitmap& bitmap, int paletteIndex);
|
bool Create(const wxBitmap& bitmap, int paletteIndex);
|
||||||
bool Create(const wxBitmap& bitmap);
|
bool Create(const wxBitmap& bitmap);
|
||||||
|
|
||||||
// Implementation
|
// wxCocoa
|
||||||
// inline WXHBITMAP GetMaskBitmap() const { return m_maskBitmap; }
|
inline WX_NSBitmapImageRep GetNSBitmapImageRep()
|
||||||
// inline void SetMaskBitmap(WXHBITMAP bmp) { m_maskBitmap = bmp; }
|
{ return m_cocoaNSBitmapImageRep; }
|
||||||
protected:
|
protected:
|
||||||
// WXHBITMAP m_maskBitmap;
|
WX_NSBitmapImageRep m_cocoaNSBitmapImageRep;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ========================================================================
|
// ========================================================================
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
#include "wx/utils.h"
|
#include "wx/utils.h"
|
||||||
#include "wx/palette.h"
|
#include "wx/palette.h"
|
||||||
#include "wx/icon.h"
|
#include "wx/icon.h"
|
||||||
|
#include "wx/colour.h"
|
||||||
#endif //WX_PRECOMP
|
#endif //WX_PRECOMP
|
||||||
#include "wx/bitmap.h"
|
#include "wx/bitmap.h"
|
||||||
#include "wx/image.h"
|
#include "wx/image.h"
|
||||||
@@ -393,7 +394,7 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth)
|
|||||||
M_BITMAPDATA->m_numColors = 0;
|
M_BITMAPDATA->m_numColors = 0;
|
||||||
M_BITMAPDATA->m_quality = 0;
|
M_BITMAPDATA->m_quality = 0;
|
||||||
M_BITMAPDATA->m_cocoaNSBitmapImageRep = bitmapImage;
|
M_BITMAPDATA->m_cocoaNSBitmapImageRep = bitmapImage;
|
||||||
M_BITMAPDATA->m_bitmapMask = NULL;
|
M_BITMAPDATA->m_bitmapMask = new wxMask(*this,wxColour(image.GetMaskRed(),image.GetMaskGreen(),image.GetMaskBlue()));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,18 +437,14 @@ IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
|
|||||||
|
|
||||||
wxMask::wxMask()
|
wxMask::wxMask()
|
||||||
{
|
{
|
||||||
/* TODO
|
m_cocoaNSBitmapImageRep = nil;
|
||||||
m_maskBitmap = 0;
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct a mask from a bitmap and a colour indicating
|
// Construct a mask from a bitmap and a colour indicating
|
||||||
// the transparent area
|
// the transparent area
|
||||||
wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
|
wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
|
||||||
{
|
{
|
||||||
/* TODO
|
m_cocoaNSBitmapImageRep = nil;
|
||||||
m_maskBitmap = 0;
|
|
||||||
*/
|
|
||||||
Create(bitmap, colour);
|
Create(bitmap, colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,9 +452,7 @@ wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
|
|||||||
// the transparent area
|
// the transparent area
|
||||||
wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
|
wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
|
||||||
{
|
{
|
||||||
/* TODO
|
m_cocoaNSBitmapImageRep = nil;
|
||||||
m_maskBitmap = 0;
|
|
||||||
*/
|
|
||||||
|
|
||||||
Create(bitmap, paletteIndex);
|
Create(bitmap, paletteIndex);
|
||||||
}
|
}
|
||||||
@@ -465,16 +460,14 @@ wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
|
|||||||
// Construct a mask from a mono bitmap (copies the bitmap).
|
// Construct a mask from a mono bitmap (copies the bitmap).
|
||||||
wxMask::wxMask(const wxBitmap& bitmap)
|
wxMask::wxMask(const wxBitmap& bitmap)
|
||||||
{
|
{
|
||||||
/* TODO
|
m_cocoaNSBitmapImageRep = nil;
|
||||||
m_maskBitmap = 0;
|
|
||||||
*/
|
|
||||||
|
|
||||||
Create(bitmap);
|
Create(bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxMask::~wxMask()
|
wxMask::~wxMask()
|
||||||
{
|
{
|
||||||
// TODO: delete mask bitmap
|
[m_cocoaNSBitmapImageRep release];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a mask from a mono bitmap (copies the bitmap).
|
// Create a mask from a mono bitmap (copies the bitmap).
|
||||||
@@ -492,11 +485,103 @@ bool wxMask::Create(const wxBitmap& bitmap, int paletteIndex)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class PixelData>
|
||||||
|
static bool wxMask_CreateFromBitmapData(PixelData srcData, const wxColour& colour, unsigned char *dstData)
|
||||||
|
{
|
||||||
|
wxCHECK_MSG(dstData,false,"Couldn't access mask data");
|
||||||
|
class PixelData::Iterator p(srcData);
|
||||||
|
const int nRows = srcData.GetHeight();
|
||||||
|
const int nCols = srcData.GetWidth();
|
||||||
|
// Total number of bytes per destination column
|
||||||
|
const int dstRowLength = (nCols+7)/8;
|
||||||
|
// Number of source columns that fit into a byte in the destination
|
||||||
|
const int width_aligned = nCols/8*8;
|
||||||
|
for(int y=0; y<nRows; ++y)
|
||||||
|
{
|
||||||
|
class PixelData::Iterator rowStart(p);
|
||||||
|
unsigned char *dstRow = dstData + y*dstRowLength;
|
||||||
|
for(int x=0; x<width_aligned; x+=8)
|
||||||
|
{
|
||||||
|
unsigned char *dstByte = dstRow + x/8;
|
||||||
|
*dstByte = 0;
|
||||||
|
// Take source RGB, compare it with the wxColour
|
||||||
|
for(int j=0; j<8; ++j, ++p)
|
||||||
|
{
|
||||||
|
*dstByte +=
|
||||||
|
( p.Red()!=colour.Red()
|
||||||
|
|| p.Green()!=colour.Green()
|
||||||
|
|| p.Blue()!=colour.Blue()
|
||||||
|
) << (7-j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Handle the remaining 0-7 pixels in the row
|
||||||
|
unsigned char *dstByte = dstRow + width_aligned/8;
|
||||||
|
*dstByte = 0;
|
||||||
|
for(int j=0; j<(nCols%8); ++j, ++p)
|
||||||
|
{
|
||||||
|
*dstByte +=
|
||||||
|
( p.Red()!=colour.Red()
|
||||||
|
|| p.Green()!=colour.Green()
|
||||||
|
|| p.Blue()!=colour.Blue()
|
||||||
|
) << (7-j);
|
||||||
|
}
|
||||||
|
p = rowStart;
|
||||||
|
p.OffsetY(srcData,1);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Create a mask from a bitmap and a colour indicating
|
// Create a mask from a bitmap and a colour indicating
|
||||||
// the transparent area
|
// the transparent area
|
||||||
bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
|
bool wxMask::Create(const wxBitmap& bitmap, const wxColour& colour)
|
||||||
{
|
{
|
||||||
// TODO
|
wxAutoNSAutoreleasePool pool;
|
||||||
return FALSE;
|
if(!bitmap.Ok())
|
||||||
|
return false;
|
||||||
|
int bmpWidth = bitmap.GetWidth();
|
||||||
|
int bmpHeight = bitmap.GetHeight();
|
||||||
|
int dstRowLength = (bmpWidth+7)/8;
|
||||||
|
|
||||||
|
// Create a bitmap image rep with 1-bit per pixel data representing
|
||||||
|
// the alpha channel padded such that rows end on byte boundaries
|
||||||
|
// Since NSBitmapImageRep doesn't have any sort of NSNullColorSpace
|
||||||
|
// we must have at least one channel of non-alpha data. In order to
|
||||||
|
// make our life easy, we use planar data which results in two
|
||||||
|
// separate arrays. We don't need to touch the first because it
|
||||||
|
// should never be used. The second is the 1-bit "alpha" data.
|
||||||
|
NSBitmapImageRep *maskRep = [[[NSBitmapImageRep alloc]
|
||||||
|
initWithBitmapDataPlanes:NULL pixelsWide:bmpWidth
|
||||||
|
pixelsHigh:bmpHeight bitsPerSample:1
|
||||||
|
samplesPerPixel:2 hasAlpha:YES isPlanar:YES
|
||||||
|
colorSpaceName:NSCalibratedWhiteColorSpace
|
||||||
|
bytesPerRow:dstRowLength bitsPerPixel:1] autorelease];
|
||||||
|
wxCHECK(maskRep,false);
|
||||||
|
|
||||||
|
// We need the source NSBitmapImageRep to detemine its pixel format
|
||||||
|
NSBitmapImageRep *srcBitmapRep = ((wxBitmapRefData*)bitmap.GetRefData())->m_cocoaNSBitmapImageRep;
|
||||||
|
wxCHECK_MSG(srcBitmapRep,false,"Can't create mask for an uninitialized bitmap");
|
||||||
|
|
||||||
|
// Get a pointer to the destination data
|
||||||
|
unsigned char *dstPlanes[5] = {NULL,NULL,NULL,NULL,NULL};
|
||||||
|
[maskRep getBitmapDataPlanes:dstPlanes];
|
||||||
|
unsigned char *dstData = dstPlanes[1];
|
||||||
|
if([srcBitmapRep bitsPerPixel]==24 && [srcBitmapRep bitsPerSample]==8 && [srcBitmapRep samplesPerPixel]==3 && [srcBitmapRep hasAlpha]==NO)
|
||||||
|
{
|
||||||
|
wxPixelData<wxBitmap,wxNativePixelFormat> pixelData(const_cast<wxBitmap&>(bitmap));
|
||||||
|
wxCHECK_MSG(wxMask_CreateFromBitmapData(pixelData, colour, dstData),
|
||||||
|
false, "Unable to access raw data");
|
||||||
|
}
|
||||||
|
else if([srcBitmapRep bitsPerPixel]==32 && [srcBitmapRep bitsPerSample]==8 && [srcBitmapRep samplesPerPixel]==4 && [srcBitmapRep hasAlpha]==YES)
|
||||||
|
{
|
||||||
|
wxPixelData<wxBitmap,wxAlphaPixelFormat> pixelData(const_cast<wxBitmap&>(bitmap));
|
||||||
|
wxCHECK_MSG(wxMask_CreateFromBitmapData(pixelData, colour, dstData),
|
||||||
|
false, "Unable to access raw data");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ wxCHECK_MSG(false,false,"Unimplemented pixel format"); }
|
||||||
|
|
||||||
|
// maskRep was autoreleased in case we had to exit quickly
|
||||||
|
m_cocoaNSBitmapImageRep = [maskRep retain];
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user