1. perform deep comparison for the classes for which it makes sense in the ports where this wasn't done yet 2. remove (shallow) comparison operators for the classes for which it does not make sense (such as wxBitmap) 3. makes wxBitmap use COW on all ports 4. adds wxObject::IsRefTo() 5. centralizes and improves COW docs git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@42752 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
1580 lines
45 KiB
C++
1580 lines
45 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
// Name: src/x11/bitmap.cpp
|
|
// Purpose: wxBitmap
|
|
// Author: Julian Smart, Robert Roebling
|
|
// Modified by:
|
|
// Created: 17/09/98
|
|
// RCS-ID: $Id$
|
|
// Copyright: (c) Julian Smart, Robert Roebling
|
|
// Licence: wxWindows licence
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// for compilers that support precompilation, includes "wx.h".
|
|
#include "wx/wxprec.h"
|
|
|
|
#include "wx/bitmap.h"
|
|
|
|
#ifndef WX_PRECOMP
|
|
#include "wx/log.h"
|
|
#include "wx/app.h"
|
|
#include "wx/dcmemory.h"
|
|
#include "wx/icon.h"
|
|
#include "wx/math.h"
|
|
#include "wx/image.h"
|
|
#endif
|
|
|
|
#include "wx/x11/private.h"
|
|
|
|
/* No point in using libXPM for NanoX */
|
|
#if wxUSE_NANOX
|
|
#undef wxHAVE_LIB_XPM
|
|
#define wxHAVE_LIB_XPM 0
|
|
|
|
// Copy from the drawable to the wxImage
|
|
bool wxGetImageFromDrawable(GR_DRAW_ID drawable, int srcX, int srcY, int width, int height, wxImage& image);
|
|
#endif
|
|
|
|
#if wxUSE_XPM
|
|
#if wxHAVE_LIB_XPM
|
|
#include <X11/xpm.h>
|
|
#else
|
|
#include "wx/xpmdecod.h"
|
|
#include "wx/wfstream.h"
|
|
#endif
|
|
#endif
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// wxMask
|
|
//-----------------------------------------------------------------------------
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS(wxMask,wxObject)
|
|
|
|
wxMask::wxMask()
|
|
{
|
|
m_bitmap = NULL;
|
|
m_display = NULL;
|
|
}
|
|
|
|
wxMask::wxMask( const wxBitmap& bitmap, const wxColour& colour )
|
|
{
|
|
m_bitmap = NULL;
|
|
Create( bitmap, colour );
|
|
}
|
|
|
|
wxMask::wxMask( const wxBitmap& bitmap, int paletteIndex )
|
|
{
|
|
m_bitmap = NULL;
|
|
Create( bitmap, paletteIndex );
|
|
}
|
|
|
|
wxMask::wxMask( const wxBitmap& bitmap )
|
|
{
|
|
m_bitmap = NULL;
|
|
Create( bitmap );
|
|
}
|
|
|
|
wxMask::~wxMask()
|
|
{
|
|
if (m_bitmap)
|
|
XFreePixmap( (Display*) m_display, (Pixmap) m_bitmap );
|
|
}
|
|
|
|
bool wxMask::Create( const wxBitmap& bitmap,
|
|
const wxColour& colour )
|
|
{
|
|
#if !wxUSE_NANOX
|
|
if (m_bitmap)
|
|
{
|
|
XFreePixmap( (Display*) m_display, (Pixmap) m_bitmap );
|
|
m_bitmap = NULL;
|
|
}
|
|
|
|
m_display = bitmap.GetDisplay();
|
|
|
|
wxImage image = bitmap.ConvertToImage();
|
|
if (!image.Ok()) return false;
|
|
|
|
m_display = bitmap.GetDisplay();
|
|
|
|
Display *xdisplay = (Display*) m_display;
|
|
int xscreen = DefaultScreen( xdisplay );
|
|
Window xroot = RootWindow( xdisplay, xscreen );
|
|
|
|
m_bitmap = (WXPixmap) XCreatePixmap( xdisplay, xroot, image.GetWidth(), image.GetHeight(), 1 );
|
|
GC gc = XCreateGC( xdisplay, (Pixmap) m_bitmap, 0, NULL );
|
|
|
|
XSetForeground( xdisplay, gc, WhitePixel(xdisplay,xscreen) );
|
|
XSetFillStyle( xdisplay, gc, FillSolid );
|
|
XFillRectangle( xdisplay, (Pixmap) m_bitmap, gc, 0, 0, image.GetWidth(), image.GetHeight() );
|
|
|
|
unsigned char *data = image.GetData();
|
|
int index = 0;
|
|
|
|
unsigned char red = colour.Red();
|
|
unsigned char green = colour.Green();
|
|
unsigned char blue = colour.Blue();
|
|
|
|
int bpp = wxTheApp->GetVisualInfo(m_display)->m_visualDepth;
|
|
|
|
if (bpp == 15)
|
|
{
|
|
red &= 0xf8;
|
|
green &= 0xf8;
|
|
blue &= 0xf8;
|
|
} else
|
|
if (bpp == 16)
|
|
{
|
|
red &= 0xf8;
|
|
green &= 0xfc;
|
|
blue &= 0xf8;
|
|
} else
|
|
if (bpp == 12)
|
|
{
|
|
red &= 0xf0;
|
|
green &= 0xf0;
|
|
blue &= 0xf0;
|
|
}
|
|
|
|
XSetForeground( xdisplay, gc, BlackPixel(xdisplay,xscreen) );
|
|
|
|
int width = image.GetWidth();
|
|
int height = image.GetHeight();
|
|
for (int j = 0; j < height; j++)
|
|
{
|
|
int start_x = -1;
|
|
int i;
|
|
for (i = 0; i < width; i++)
|
|
{
|
|
if ((data[index] == red) &&
|
|
(data[index+1] == green) &&
|
|
(data[index+2] == blue))
|
|
{
|
|
if (start_x == -1)
|
|
start_x = i;
|
|
}
|
|
else
|
|
{
|
|
if (start_x != -1)
|
|
{
|
|
XDrawLine( xdisplay, (Pixmap) m_bitmap, gc, start_x, j, i-1, j );
|
|
start_x = -1;
|
|
}
|
|
}
|
|
index += 3;
|
|
}
|
|
if (start_x != -1)
|
|
XDrawLine( xdisplay, (Pixmap) m_bitmap, gc, start_x, j, i, j );
|
|
}
|
|
|
|
XFreeGC( xdisplay, gc );
|
|
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
// wxUSE_NANOX
|
|
}
|
|
|
|
bool wxMask::Create( const wxBitmap& bitmap, int paletteIndex )
|
|
{
|
|
unsigned char r,g,b;
|
|
wxPalette *pal = bitmap.GetPalette();
|
|
|
|
wxCHECK_MSG( pal, false, wxT("Cannot create mask from bitmap without palette") );
|
|
|
|
pal->GetRGB(paletteIndex, &r, &g, &b);
|
|
|
|
return Create(bitmap, wxColour(r, g, b));
|
|
}
|
|
|
|
bool wxMask::Create( const wxBitmap& bitmap )
|
|
{
|
|
#if !wxUSE_NANOX
|
|
if (m_bitmap)
|
|
{
|
|
XFreePixmap( (Display*) m_display, (Pixmap) m_bitmap );
|
|
m_bitmap = NULL;
|
|
}
|
|
|
|
if (!bitmap.Ok()) return false;
|
|
|
|
wxCHECK_MSG( bitmap.GetBitmap(), false, wxT("Cannot create mask from colour bitmap") );
|
|
|
|
m_display = bitmap.GetDisplay();
|
|
|
|
int xscreen = DefaultScreen( (Display*) m_display );
|
|
Window xroot = RootWindow( (Display*) m_display, xscreen );
|
|
|
|
m_bitmap = (WXPixmap) XCreatePixmap( (Display*) m_display, xroot, bitmap.GetWidth(), bitmap.GetHeight(), 1 );
|
|
|
|
if (!m_bitmap) return false;
|
|
|
|
GC gc = XCreateGC( (Display*) m_display, (Pixmap) m_bitmap, 0, NULL );
|
|
|
|
XCopyPlane( (Display*) m_display, (Pixmap) bitmap.GetBitmap(), (Pixmap) m_bitmap,
|
|
gc, 0, 0, bitmap.GetWidth(), bitmap.GetHeight(), 0, 0, 1 );
|
|
|
|
XFreeGC( (Display*) m_display, gc );
|
|
|
|
return true;
|
|
#else
|
|
return false;
|
|
#endif
|
|
// wxUSE_NANOX
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// wxBitmap
|
|
//-----------------------------------------------------------------------------
|
|
|
|
class wxBitmapRefData: public wxObjectRefData
|
|
{
|
|
public:
|
|
wxBitmapRefData();
|
|
virtual ~wxBitmapRefData();
|
|
|
|
WXPixmap m_pixmap;
|
|
WXPixmap m_bitmap;
|
|
WXDisplay *m_display;
|
|
wxMask *m_mask;
|
|
int m_width;
|
|
int m_height;
|
|
int m_bpp;
|
|
wxPalette *m_palette;
|
|
};
|
|
|
|
wxBitmapRefData::wxBitmapRefData()
|
|
{
|
|
m_pixmap = NULL;
|
|
m_bitmap = NULL;
|
|
m_display = NULL;
|
|
m_mask = (wxMask *) NULL;
|
|
m_width = 0;
|
|
m_height = 0;
|
|
m_bpp = 0;
|
|
m_palette = (wxPalette *) NULL;
|
|
}
|
|
|
|
wxBitmapRefData::~wxBitmapRefData()
|
|
{
|
|
if (m_pixmap) XFreePixmap( (Display*) m_display, (Pixmap) m_pixmap );
|
|
if (m_bitmap) XFreePixmap( (Display*) m_display, (Pixmap) m_bitmap );
|
|
if (m_mask) delete m_mask;
|
|
if (m_palette) delete m_palette;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// helper function
|
|
|
|
static WXPixmap wxGetSubPixmap( WXDisplay* xdisplay, WXPixmap xpixmap,
|
|
int x, int y, int width, int height,
|
|
int depth )
|
|
{
|
|
Display * const dpy = (Display *)xdisplay;
|
|
|
|
int xscreen = DefaultScreen( dpy );
|
|
Window xroot = RootWindow( dpy, xscreen );
|
|
Visual* xvisual = DefaultVisual( dpy, xscreen );
|
|
|
|
XImage* ximage = XCreateImage( dpy, xvisual, depth,
|
|
ZPixmap, 0, 0, width, height, 32, 0 );
|
|
ximage->data = (char*)malloc( ximage->bytes_per_line * ximage->height );
|
|
ximage = XGetSubImage( dpy, (Pixmap)xpixmap,
|
|
x, y, width, height,
|
|
AllPlanes, ZPixmap, ximage, 0, 0 );
|
|
|
|
GC gc = XCreateGC( dpy, (Pixmap)xpixmap, 0, NULL );
|
|
Pixmap ret = XCreatePixmap( dpy, xroot,
|
|
width, height, depth );
|
|
|
|
XPutImage( dpy, ret, gc, ximage,
|
|
0, 0, 0, 0, width, height );
|
|
XDestroyImage( ximage );
|
|
XFreeGC( dpy, gc );
|
|
|
|
return (WXPixmap)ret;
|
|
}
|
|
|
|
#define M_BMPDATA ((wxBitmapRefData *)m_refData)
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS(wxBitmap,wxGDIObject)
|
|
|
|
wxBitmap::wxBitmap()
|
|
{
|
|
}
|
|
|
|
wxBitmap::wxBitmap( int width, int height, int depth )
|
|
{
|
|
Create( width, height, depth );
|
|
}
|
|
|
|
bool wxBitmap::Create( int width, int height, int depth )
|
|
{
|
|
UnRef();
|
|
|
|
wxCHECK_MSG( (width > 0) && (height > 0), false, wxT("invalid bitmap size") );
|
|
|
|
m_refData = new wxBitmapRefData();
|
|
|
|
M_BMPDATA->m_display = wxGlobalDisplay();
|
|
|
|
wxASSERT_MSG( M_BMPDATA->m_display, wxT("No display") );
|
|
|
|
int xscreen = DefaultScreen( (Display*) M_BMPDATA->m_display );
|
|
Window xroot = RootWindow( (Display*) M_BMPDATA->m_display, xscreen );
|
|
|
|
int bpp = DefaultDepth( (Display*) M_BMPDATA->m_display, xscreen );
|
|
if (depth == -1) depth = bpp;
|
|
|
|
wxCHECK_MSG( (depth == bpp) ||
|
|
(depth == 1), false, wxT("invalid bitmap depth") );
|
|
|
|
M_BMPDATA->m_mask = (wxMask *) NULL;
|
|
M_BMPDATA->m_width = width;
|
|
M_BMPDATA->m_height = height;
|
|
|
|
#if wxUSE_NANOX
|
|
M_BMPDATA->m_pixmap = (WXPixmap) GrNewPixmap(width, height, NULL);
|
|
M_BMPDATA->m_bpp = bpp;
|
|
|
|
wxASSERT_MSG( M_BMPDATA->m_pixmap, wxT("Bitmap creation failed") );
|
|
#else
|
|
if (depth == 1)
|
|
{
|
|
M_BMPDATA->m_bitmap = (WXPixmap) XCreatePixmap( (Display*) M_BMPDATA->m_display, xroot, width, height, 1 );
|
|
|
|
wxASSERT_MSG( M_BMPDATA->m_bitmap, wxT("Bitmap creation failed") );
|
|
|
|
M_BMPDATA->m_bpp = 1;
|
|
}
|
|
else
|
|
{
|
|
M_BMPDATA->m_pixmap = (WXPixmap) XCreatePixmap( (Display*) M_BMPDATA->m_display, xroot, width, height, depth );
|
|
|
|
wxASSERT_MSG( M_BMPDATA->m_pixmap, wxT("Pixmap creation failed") );
|
|
|
|
M_BMPDATA->m_bpp = depth;
|
|
}
|
|
#endif
|
|
return Ok();
|
|
}
|
|
|
|
bool wxBitmap::Create(const void* data, wxBitmapType type,
|
|
int width, int height, int depth)
|
|
{
|
|
UnRef();
|
|
|
|
wxBitmapHandler *handler = FindHandler(type);
|
|
|
|
if ( handler == NULL ) {
|
|
wxLogWarning(wxT("no data bitmap handler for type %ld defined."),
|
|
(long)type);
|
|
|
|
return false;
|
|
}
|
|
|
|
return handler->Create(this, data, type, width, height, depth);
|
|
}
|
|
|
|
bool wxBitmap::Create(WXPixmap pixmap)
|
|
{
|
|
UnRef();
|
|
Pixmap xpixmap = (Pixmap)pixmap;
|
|
Display* xdisplay = wxGlobalDisplay();
|
|
int xscreen = DefaultScreen( xdisplay );
|
|
Window xroot = RootWindow( xdisplay, xscreen );
|
|
|
|
// make a copy of the Pixmap
|
|
Window root;
|
|
Pixmap copy;
|
|
int x, y;
|
|
unsigned width, height, border, depth;
|
|
|
|
XGetGeometry( xdisplay, (Drawable)xpixmap, &root, &x, &y,
|
|
&width, &height, &border, &depth );
|
|
copy = XCreatePixmap( xdisplay, xroot, width, height, depth );
|
|
|
|
GC gc = XCreateGC( xdisplay, copy, 0, NULL );
|
|
XCopyArea( xdisplay, xpixmap, copy, gc, 0, 0, width, height, 0, 0 );
|
|
XFreeGC( xdisplay, gc );
|
|
|
|
// fill in ref data
|
|
wxBitmapRefData* ref = new wxBitmapRefData();
|
|
|
|
if( depth == 1 )
|
|
ref->m_bitmap = (WXPixmap)copy;
|
|
else
|
|
ref->m_pixmap = (WXPixmap)copy;
|
|
|
|
ref->m_display = (WXDisplay*)xdisplay;
|
|
ref->m_width = width;
|
|
ref->m_height = height;
|
|
ref->m_bpp = depth;
|
|
|
|
m_refData = ref;
|
|
|
|
return true;
|
|
}
|
|
|
|
wxBitmap::wxBitmap(const char* const* bits)
|
|
{
|
|
Create(bits, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0);
|
|
}
|
|
|
|
bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
|
|
{
|
|
#if wxUSE_NANOX
|
|
if (!image.Ok())
|
|
{
|
|
wxASSERT_MSG(image.Ok(), wxT("Invalid wxImage passed to wxBitmap::CreateFromImage."));
|
|
return false;
|
|
}
|
|
|
|
int w = image.GetWidth();
|
|
int h = image.GetHeight();
|
|
|
|
if (!Create(w, h, depth))
|
|
return false;
|
|
|
|
// Unfortunately the mask has to be screen-depth since
|
|
// 1-bpp bitmaps don't seem to be supported
|
|
// TODO: implement transparent drawing, presumably
|
|
// by doing several blits as per the Windows
|
|
// implementation because Nano-X doesn't support
|
|
// XSetClipMask.
|
|
// TODO: could perhaps speed this function up
|
|
// by making a buffer of pixel values,
|
|
// and then calling GrArea to write that to the
|
|
// pixmap. See demos/nxroach.c.
|
|
|
|
bool hasMask = image.HasMask();
|
|
|
|
GC pixmapGC = GrNewGC();
|
|
Pixmap pixmap = (Pixmap) GetPixmap();
|
|
|
|
GC maskGC = 0;
|
|
Pixmap maskPixmap = 0;
|
|
|
|
unsigned char maskR = 0;
|
|
unsigned char maskG = 0;
|
|
unsigned char maskB = 0;
|
|
|
|
if (hasMask)
|
|
{
|
|
maskR = image.GetMaskRed();
|
|
maskG = image.GetMaskGreen();
|
|
maskB = image.GetMaskBlue();
|
|
|
|
maskGC = GrNewGC();
|
|
maskPixmap = GrNewPixmap(w, h, 0);
|
|
if (!maskPixmap)
|
|
hasMask = false;
|
|
else
|
|
{
|
|
wxMask* mask = new wxMask;
|
|
mask->SetBitmap((WXPixmap) maskPixmap);
|
|
SetMask(mask);
|
|
}
|
|
}
|
|
|
|
GR_COLOR lastPixmapColour = 0;
|
|
GR_COLOR lastMaskColour = 0;
|
|
|
|
int i, j;
|
|
for (i = 0; i < w; i++)
|
|
{
|
|
for (j = 0; j < h; j++)
|
|
{
|
|
unsigned char red = image.GetRed(i, j);
|
|
unsigned char green = image.GetGreen(i, j);
|
|
unsigned char blue = image.GetBlue(i, j);
|
|
|
|
GR_COLOR colour = GR_RGB(red, green, blue);
|
|
|
|
// Efficiency measure
|
|
if (colour != lastPixmapColour || (i == 0 && j == 0))
|
|
{
|
|
GrSetGCForeground(pixmapGC, colour);
|
|
lastPixmapColour = colour;
|
|
}
|
|
|
|
GrPoint(pixmap, pixmapGC, i, j);
|
|
|
|
if (hasMask)
|
|
{
|
|
// scan the bitmap for the transparent colour and set the corresponding
|
|
// pixels in the mask to BLACK and the rest to WHITE
|
|
if (maskR == red && maskG == green && maskB == blue)
|
|
{
|
|
colour = GR_RGB(0, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
colour = GR_RGB(255, 255, 255);
|
|
}
|
|
if (colour != lastMaskColour || (i == 0 && j == 0))
|
|
{
|
|
GrSetGCForeground(maskGC, colour);
|
|
lastMaskColour = colour;
|
|
}
|
|
GrPoint(maskPixmap, maskGC, i, j);
|
|
}
|
|
}
|
|
}
|
|
|
|
GrDestroyGC(pixmapGC);
|
|
if (hasMask)
|
|
GrDestroyGC(maskGC);
|
|
|
|
return true;
|
|
#else
|
|
// !wxUSE_NANOX
|
|
|
|
UnRef();
|
|
|
|
wxCHECK_MSG( image.Ok(), false, wxT("invalid image") );
|
|
wxCHECK_MSG( depth == -1, false, wxT("invalid bitmap depth") );
|
|
|
|
m_refData = new wxBitmapRefData();
|
|
|
|
M_BMPDATA->m_display = wxGlobalDisplay();
|
|
|
|
Display *xdisplay = (Display*) M_BMPDATA->m_display;
|
|
|
|
int xscreen = DefaultScreen( xdisplay );
|
|
Window xroot = RootWindow( xdisplay, xscreen );
|
|
Visual* xvisual = DefaultVisual( xdisplay, xscreen );
|
|
|
|
int bpp = wxTheApp->GetVisualInfo(M_BMPDATA->m_display)->m_visualDepth;
|
|
|
|
int width = image.GetWidth();
|
|
int height = image.GetHeight();
|
|
M_BMPDATA->m_width = width;
|
|
M_BMPDATA->m_height = height;
|
|
|
|
if (depth != 1) depth = bpp;
|
|
M_BMPDATA->m_bpp = depth;
|
|
|
|
if (depth == 1)
|
|
{
|
|
wxFAIL_MSG( wxT("mono images later") );
|
|
}
|
|
else
|
|
{
|
|
// Create image
|
|
|
|
XImage *data_image = XCreateImage( xdisplay, xvisual, bpp, ZPixmap, 0, 0, width, height, 32, 0 );
|
|
data_image->data = (char*) malloc( data_image->bytes_per_line * data_image->height );
|
|
|
|
if (data_image->data == NULL)
|
|
{
|
|
wxLogError( wxT("Out of memory.") ); // TODO clean
|
|
return false;
|
|
}
|
|
|
|
M_BMPDATA->m_pixmap = (WXPixmap) XCreatePixmap( xdisplay, xroot, width, height, depth );
|
|
|
|
// Create mask
|
|
|
|
XImage *mask_image = (XImage*) NULL;
|
|
if (image.HasMask())
|
|
{
|
|
mask_image = XCreateImage( xdisplay, xvisual, 1, ZPixmap, 0, 0, width, height, 32, 0 );
|
|
mask_image->data = (char*) malloc( mask_image->bytes_per_line * mask_image->height );
|
|
|
|
if (mask_image->data == NULL)
|
|
{
|
|
wxLogError( wxT("Out of memory.") ); // TODO clean
|
|
return false;
|
|
}
|
|
|
|
wxMask *mask = new wxMask();
|
|
mask->SetDisplay( xdisplay );
|
|
mask->SetBitmap( (WXPixmap) XCreatePixmap( xdisplay, xroot, width, height, 1 ) );
|
|
|
|
SetMask( mask );
|
|
}
|
|
|
|
if (bpp < 8) bpp = 8;
|
|
|
|
// Render
|
|
|
|
enum byte_order { RGB, RBG, BRG, BGR, GRB, GBR };
|
|
byte_order b_o = RGB;
|
|
|
|
wxXVisualInfo* vi = wxTheApp->GetVisualInfo(M_BMPDATA->m_display);
|
|
unsigned long greenMask = vi->m_visualGreenMask,
|
|
redMask = vi->m_visualRedMask,
|
|
blueMask = vi->m_visualBlueMask;
|
|
|
|
if (bpp > 8)
|
|
{
|
|
if ((redMask > greenMask) && (greenMask > blueMask)) b_o = RGB;
|
|
else if ((redMask > blueMask) && (blueMask > greenMask)) b_o = RBG;
|
|
else if ((blueMask > redMask) && (redMask > greenMask)) b_o = BRG;
|
|
else if ((blueMask > greenMask) && (greenMask > redMask))b_o = BGR;
|
|
else if ((greenMask > redMask) && (redMask > blueMask)) b_o = GRB;
|
|
else if ((greenMask > blueMask) && (blueMask > redMask)) b_o = GBR;
|
|
}
|
|
|
|
int r_mask = image.GetMaskRed();
|
|
int g_mask = image.GetMaskGreen();
|
|
int b_mask = image.GetMaskBlue();
|
|
|
|
unsigned char* data = image.GetData();
|
|
wxASSERT_MSG( data, wxT("No image data") );
|
|
|
|
unsigned char *colorCube =
|
|
wxTheApp->GetVisualInfo(M_BMPDATA->m_display)->m_colorCube;
|
|
|
|
bool hasMask = image.HasMask();
|
|
|
|
int index = 0;
|
|
for (int y = 0; y < height; y++)
|
|
{
|
|
for (int x = 0; x < width; x++)
|
|
{
|
|
int r = data[index];
|
|
index++;
|
|
int g = data[index];
|
|
index++;
|
|
int b = data[index];
|
|
index++;
|
|
|
|
if (hasMask)
|
|
{
|
|
if ((r == r_mask) && (b == b_mask) && (g == g_mask))
|
|
XPutPixel( mask_image, x, y, 0 );
|
|
else
|
|
XPutPixel( mask_image, x, y, 1 );
|
|
}
|
|
|
|
switch (bpp)
|
|
{
|
|
case 8:
|
|
{
|
|
int pixel = 0;
|
|
pixel = colorCube[ ((r & 0xf8) << 7) + ((g & 0xf8) << 2) + ((b & 0xf8) >> 3) ];
|
|
XPutPixel( data_image, x, y, pixel );
|
|
break;
|
|
}
|
|
case 12: // SGI only
|
|
{
|
|
int pixel = 0;
|
|
switch (b_o)
|
|
{
|
|
case RGB: pixel = ((r & 0xf0) << 4) | (g & 0xf0) | ((b & 0xf0) >> 4); break;
|
|
case RBG: pixel = ((r & 0xf0) << 4) | (b & 0xf0) | ((g & 0xf0) >> 4); break;
|
|
case GRB: pixel = ((g & 0xf0) << 4) | (r & 0xf0) | ((b & 0xf0) >> 4); break;
|
|
case GBR: pixel = ((g & 0xf0) << 4) | (b & 0xf0) | ((r & 0xf0) >> 4); break;
|
|
case BRG: pixel = ((b & 0xf0) << 4) | (r & 0xf0) | ((g & 0xf0) >> 4); break;
|
|
case BGR: pixel = ((b & 0xf0) << 4) | (g & 0xf0) | ((r & 0xf0) >> 4); break;
|
|
}
|
|
XPutPixel( data_image, x, y, pixel );
|
|
break;
|
|
}
|
|
case 15:
|
|
{
|
|
int pixel = 0;
|
|
switch (b_o)
|
|
{
|
|
case RGB: pixel = ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | ((b & 0xf8) >> 3); break;
|
|
case RBG: pixel = ((r & 0xf8) << 7) | ((b & 0xf8) << 2) | ((g & 0xf8) >> 3); break;
|
|
case GRB: pixel = ((g & 0xf8) << 7) | ((r & 0xf8) << 2) | ((b & 0xf8) >> 3); break;
|
|
case GBR: pixel = ((g & 0xf8) << 7) | ((b & 0xf8) << 2) | ((r & 0xf8) >> 3); break;
|
|
case BRG: pixel = ((b & 0xf8) << 7) | ((r & 0xf8) << 2) | ((g & 0xf8) >> 3); break;
|
|
case BGR: pixel = ((b & 0xf8) << 7) | ((g & 0xf8) << 2) | ((r & 0xf8) >> 3); break;
|
|
}
|
|
XPutPixel( data_image, x, y, pixel );
|
|
break;
|
|
}
|
|
case 16:
|
|
{
|
|
// I actually don't know if for 16-bit displays, it is alway the green
|
|
// component or the second component which has 6 bits.
|
|
int pixel = 0;
|
|
switch (b_o)
|
|
{
|
|
case RGB: pixel = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | ((b & 0xf8) >> 3); break;
|
|
case RBG: pixel = ((r & 0xf8) << 8) | ((b & 0xfc) << 3) | ((g & 0xf8) >> 3); break;
|
|
case GRB: pixel = ((g & 0xf8) << 8) | ((r & 0xfc) << 3) | ((b & 0xf8) >> 3); break;
|
|
case GBR: pixel = ((g & 0xf8) << 8) | ((b & 0xfc) << 3) | ((r & 0xf8) >> 3); break;
|
|
case BRG: pixel = ((b & 0xf8) << 8) | ((r & 0xfc) << 3) | ((g & 0xf8) >> 3); break;
|
|
case BGR: pixel = ((b & 0xf8) << 8) | ((g & 0xfc) << 3) | ((r & 0xf8) >> 3); break;
|
|
}
|
|
XPutPixel( data_image, x, y, pixel );
|
|
break;
|
|
}
|
|
case 32:
|
|
case 24:
|
|
{
|
|
int pixel = 0;
|
|
switch (b_o)
|
|
{
|
|
case RGB: pixel = (r << 16) | (g << 8) | b; break;
|
|
case RBG: pixel = (r << 16) | (b << 8) | g; break;
|
|
case BRG: pixel = (b << 16) | (r << 8) | g; break;
|
|
case BGR: pixel = (b << 16) | (g << 8) | r; break;
|
|
case GRB: pixel = (g << 16) | (r << 8) | b; break;
|
|
case GBR: pixel = (g << 16) | (b << 8) | r; break;
|
|
}
|
|
XPutPixel( data_image, x, y, pixel );
|
|
}
|
|
default: break;
|
|
}
|
|
} // for
|
|
} // for
|
|
|
|
// Blit picture
|
|
|
|
GC gc = XCreateGC( xdisplay, (Pixmap) M_BMPDATA->m_pixmap, 0, NULL );
|
|
XPutImage( xdisplay, (Pixmap) M_BMPDATA->m_pixmap, gc, data_image, 0, 0, 0, 0, width, height );
|
|
XDestroyImage( data_image );
|
|
XFreeGC( xdisplay, gc );
|
|
|
|
// Blit mask
|
|
|
|
if (image.HasMask())
|
|
{
|
|
GC gc = XCreateGC( xdisplay, (Pixmap) GetMask()->GetBitmap(), 0, NULL );
|
|
XPutImage( xdisplay, (Pixmap) GetMask()->GetBitmap(), gc, mask_image, 0, 0, 0, 0, width, height );
|
|
|
|
XDestroyImage( mask_image );
|
|
XFreeGC( xdisplay, gc );
|
|
}
|
|
}
|
|
|
|
return true;
|
|
#endif
|
|
// wxUSE_NANOX
|
|
}
|
|
|
|
wxImage wxBitmap::ConvertToImage() const
|
|
{
|
|
wxImage image;
|
|
|
|
wxCHECK_MSG( Ok(), wxNullImage, wxT("invalid bitmap") );
|
|
|
|
Display *xdisplay = (Display*) M_BMPDATA->m_display;
|
|
wxASSERT_MSG( xdisplay, wxT("No display") );
|
|
|
|
#if wxUSE_NANOX
|
|
//int bpp = DefaultDepth(xdisplay, xscreen);
|
|
wxGetImageFromDrawable((Pixmap) GetPixmap(), 0, 0, GetWidth(), GetHeight(), image);
|
|
return image;
|
|
#else
|
|
// !wxUSE_NANOX
|
|
int bpp = wxTheApp->GetVisualInfo(M_BMPDATA->m_display)->m_visualDepth;
|
|
XImage *x_image = NULL;
|
|
if (GetPixmap())
|
|
{
|
|
x_image = XGetImage( xdisplay, (Pixmap) GetPixmap(),
|
|
0, 0,
|
|
GetWidth(), GetHeight(),
|
|
AllPlanes, ZPixmap );
|
|
} else
|
|
if (GetBitmap())
|
|
{
|
|
x_image = XGetImage( xdisplay, (Pixmap) GetBitmap(),
|
|
0, 0,
|
|
GetWidth(), GetHeight(),
|
|
AllPlanes, ZPixmap );
|
|
} else
|
|
{
|
|
wxFAIL_MSG( wxT("Ill-formed bitmap") );
|
|
}
|
|
|
|
wxCHECK_MSG( x_image, wxNullImage, wxT("couldn't create image") );
|
|
|
|
image.Create( GetWidth(), GetHeight() );
|
|
char unsigned *data = image.GetData();
|
|
|
|
if (!data)
|
|
{
|
|
XDestroyImage( x_image );
|
|
wxFAIL_MSG( wxT("couldn't create image") );
|
|
return wxNullImage;
|
|
}
|
|
|
|
XImage *x_image_mask = NULL;
|
|
if (GetMask())
|
|
{
|
|
x_image_mask = XGetImage( xdisplay, (Pixmap) GetMask()->GetBitmap(),
|
|
0, 0,
|
|
GetWidth(), GetHeight(),
|
|
AllPlanes, ZPixmap );
|
|
|
|
image.SetMaskColour( 16, 16, 16 ); // anything unlikely and dividable
|
|
}
|
|
|
|
int red_shift_right = 0;
|
|
int green_shift_right = 0;
|
|
int blue_shift_right = 0;
|
|
int red_shift_left = 0;
|
|
int green_shift_left = 0;
|
|
int blue_shift_left = 0;
|
|
bool use_shift = false;
|
|
|
|
if (GetPixmap())
|
|
{
|
|
wxXVisualInfo* vi = wxTheApp->GetVisualInfo(M_BMPDATA->m_display);
|
|
|
|
red_shift_right = vi->m_visualRedShift;
|
|
red_shift_left = 8 - vi->m_visualRedPrec;
|
|
green_shift_right = vi->m_visualGreenShift;
|
|
green_shift_left = 8 - vi->m_visualGreenPrec;
|
|
blue_shift_right = vi->m_visualBlueShift;
|
|
blue_shift_left = 8 - vi->m_visualBluePrec;
|
|
|
|
use_shift = (vi->m_visualType == GrayScale) ||
|
|
(vi->m_visualType != PseudoColor);
|
|
}
|
|
|
|
if (GetBitmap())
|
|
{
|
|
bpp = 1;
|
|
}
|
|
|
|
XColor *colors = (XColor*)wxTheApp->
|
|
GetVisualInfo(M_BMPDATA->m_display)->m_visualColormap;
|
|
|
|
int width = GetWidth();
|
|
int height = GetHeight();
|
|
long pos = 0;
|
|
for (int j = 0; j < height; j++)
|
|
{
|
|
for (int i = 0; i < width; i++)
|
|
{
|
|
unsigned long pixel = XGetPixel( x_image, i, j );
|
|
if (bpp == 1)
|
|
{
|
|
if (pixel == 0)
|
|
{
|
|
data[pos] = 0;
|
|
data[pos+1] = 0;
|
|
data[pos+2] = 0;
|
|
}
|
|
else
|
|
{
|
|
data[pos] = 255;
|
|
data[pos+1] = 255;
|
|
data[pos+2] = 255;
|
|
}
|
|
}
|
|
else if (use_shift)
|
|
{
|
|
data[pos] = (unsigned char)((pixel >> red_shift_right) << red_shift_left);
|
|
data[pos+1] = (unsigned char)((pixel >> green_shift_right) << green_shift_left);
|
|
data[pos+2] = (unsigned char)((pixel >> blue_shift_right) << blue_shift_left);
|
|
}
|
|
else if (colors)
|
|
{
|
|
data[pos] = (unsigned char)(colors[pixel].red >> 8);
|
|
data[pos+1] = (unsigned char)(colors[pixel].green >> 8);
|
|
data[pos+2] = (unsigned char)(colors[pixel].blue >> 8);
|
|
}
|
|
else
|
|
{
|
|
wxFAIL_MSG( wxT("Image conversion failed. Unknown visual type.") );
|
|
}
|
|
|
|
if (x_image_mask)
|
|
{
|
|
int mask_pixel = XGetPixel( x_image_mask, i, j );
|
|
if (mask_pixel == 0)
|
|
{
|
|
data[pos] = 16;
|
|
data[pos+1] = 16;
|
|
data[pos+2] = 16;
|
|
}
|
|
}
|
|
|
|
pos += 3;
|
|
}
|
|
}
|
|
|
|
XDestroyImage( x_image );
|
|
if (x_image_mask) XDestroyImage( x_image_mask );
|
|
return image;
|
|
#endif
|
|
// wxUSE_NANOX
|
|
}
|
|
|
|
wxBitmap::wxBitmap( const wxString &filename, wxBitmapType type )
|
|
{
|
|
LoadFile( filename, type );
|
|
}
|
|
|
|
wxBitmap::wxBitmap( const char bits[], int width, int height, int depth )
|
|
{
|
|
m_refData = new wxBitmapRefData;
|
|
|
|
(void) Create(bits, wxBITMAP_TYPE_XBM_DATA, width, height, depth);
|
|
}
|
|
|
|
wxBitmap::~wxBitmap()
|
|
{
|
|
}
|
|
|
|
bool wxBitmap::IsOk() const
|
|
{
|
|
return (m_refData != NULL);
|
|
}
|
|
|
|
int wxBitmap::GetHeight() const
|
|
{
|
|
wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
|
|
|
|
return M_BMPDATA->m_height;
|
|
}
|
|
|
|
int wxBitmap::GetWidth() const
|
|
{
|
|
wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
|
|
|
|
return M_BMPDATA->m_width;
|
|
}
|
|
|
|
int wxBitmap::GetDepth() const
|
|
{
|
|
wxCHECK_MSG( Ok(), -1, wxT("invalid bitmap") );
|
|
|
|
return M_BMPDATA->m_bpp;
|
|
}
|
|
|
|
wxMask *wxBitmap::GetMask() const
|
|
{
|
|
wxCHECK_MSG( Ok(), (wxMask *) NULL, wxT("invalid bitmap") );
|
|
|
|
return M_BMPDATA->m_mask;
|
|
}
|
|
|
|
void wxBitmap::SetMask( wxMask *mask )
|
|
{
|
|
wxCHECK_RET( Ok(), wxT("invalid bitmap") );
|
|
|
|
AllocExclusive();
|
|
if (M_BMPDATA->m_mask) delete M_BMPDATA->m_mask;
|
|
|
|
M_BMPDATA->m_mask = mask;
|
|
}
|
|
|
|
bool wxBitmap::CopyFromIcon(const wxIcon& icon)
|
|
{
|
|
*this = icon;
|
|
return true;
|
|
}
|
|
|
|
wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const
|
|
{
|
|
wxCHECK_MSG( Ok() &&
|
|
(rect.x >= 0) && (rect.y >= 0) &&
|
|
(rect.x+rect.width <= M_BMPDATA->m_width ) &&
|
|
(rect.y+rect.height <= M_BMPDATA->m_height),
|
|
wxNullBitmap, wxT("invalid bitmap or bitmap region") );
|
|
|
|
wxBitmap ret( rect.width, rect.height, M_BMPDATA->m_bpp );
|
|
wxASSERT_MSG( ret.Ok(), wxT("GetSubBitmap error") );
|
|
|
|
if( GetMask() )
|
|
{
|
|
wxMask* mask = new wxMask();
|
|
mask->SetDisplay( GetMask()->GetDisplay() );
|
|
mask->SetBitmap( wxGetSubPixmap( GetMask()->GetDisplay(),
|
|
GetMask()->GetBitmap(),
|
|
rect.x, rect.y,
|
|
rect.width, rect.height,
|
|
1 ) );
|
|
|
|
ret.SetMask( mask );
|
|
}
|
|
|
|
if( GetPixmap() )
|
|
{
|
|
ret.SetPixmap( wxGetSubPixmap( GetDisplay(),
|
|
GetPixmap(),
|
|
rect.x, rect.y,
|
|
rect.width, rect.height,
|
|
M_BMPDATA->m_bpp ) );
|
|
}
|
|
|
|
if( GetBitmap() )
|
|
{
|
|
ret.SetBitmap( wxGetSubPixmap( GetDisplay(),
|
|
GetBitmap(),
|
|
rect.x, rect.y,
|
|
rect.width, rect.height,
|
|
1 ) );
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
bool wxBitmap::SaveFile( const wxString &name, wxBitmapType type,
|
|
const wxPalette *palette ) const
|
|
{
|
|
wxCHECK_MSG( Ok(), false, wxT("invalid bitmap") );
|
|
|
|
wxBitmapHandler *handler = FindHandler(type);
|
|
|
|
// Try to save the bitmap via wxImage handlers:
|
|
if (handler == NULL)
|
|
{
|
|
wxImage image(this->ConvertToImage());
|
|
if (image.Ok()) return image.SaveFile( name, type );
|
|
|
|
return false;
|
|
}
|
|
|
|
return handler->SaveFile(this, name, type, palette);
|
|
}
|
|
|
|
bool wxBitmap::LoadFile( const wxString &name, wxBitmapType type )
|
|
{
|
|
UnRef();
|
|
|
|
if (!wxFileExists(name)) return false;
|
|
|
|
wxBitmapHandler *handler = FindHandler(type);
|
|
|
|
if (handler == NULL)
|
|
{
|
|
wxImage image;
|
|
if (!image.LoadFile( name, type ))
|
|
return false;
|
|
|
|
if (image.Ok())
|
|
{
|
|
*this = wxBitmap(image);
|
|
return true;
|
|
}
|
|
else return false;
|
|
}
|
|
|
|
return handler->LoadFile(this, name, type, -1, -1);
|
|
}
|
|
|
|
void wxBitmap::SetPalette(const wxPalette& palette)
|
|
{
|
|
wxCHECK_RET(Ok(), wxT("invalid bitmap"));
|
|
wxCHECK_RET(GetDepth() > 1 && GetDepth() <= 8,
|
|
wxT("cannot set palette for bitmap of this depth"));
|
|
|
|
AllocExclusive();
|
|
delete M_BMPDATA->m_palette;
|
|
M_BMPDATA->m_palette = NULL;
|
|
|
|
if (!palette.Ok()) return;
|
|
|
|
M_BMPDATA->m_palette = new wxPalette(palette);
|
|
}
|
|
|
|
wxPalette *wxBitmap::GetPalette() const
|
|
{
|
|
if (!Ok()) return (wxPalette *) NULL;
|
|
|
|
return M_BMPDATA->m_palette;
|
|
}
|
|
|
|
void wxBitmap::SetHeight( int height )
|
|
{
|
|
AllocExclusive();
|
|
|
|
M_BMPDATA->m_height = height;
|
|
}
|
|
|
|
void wxBitmap::SetWidth( int width )
|
|
{
|
|
AllocExclusive();
|
|
|
|
M_BMPDATA->m_width = width;
|
|
}
|
|
|
|
void wxBitmap::SetDepth( int depth )
|
|
{
|
|
AllocExclusive();
|
|
|
|
M_BMPDATA->m_bpp = depth;
|
|
}
|
|
|
|
void wxBitmap::SetPixmap( WXPixmap pixmap )
|
|
{
|
|
if (!m_refData) m_refData = new wxBitmapRefData();
|
|
|
|
M_BMPDATA->m_pixmap = pixmap;
|
|
}
|
|
|
|
void wxBitmap::SetBitmap( WXPixmap bitmap )
|
|
{
|
|
if (!m_refData) m_refData = new wxBitmapRefData();
|
|
|
|
M_BMPDATA->m_bitmap = bitmap;
|
|
}
|
|
|
|
WXPixmap wxBitmap::GetPixmap() const
|
|
{
|
|
wxCHECK_MSG( Ok(), (WXPixmap) NULL, wxT("invalid bitmap") );
|
|
|
|
return M_BMPDATA->m_pixmap;
|
|
}
|
|
|
|
WXPixmap wxBitmap::GetBitmap() const
|
|
{
|
|
wxCHECK_MSG( Ok(), (WXPixmap) NULL, wxT("invalid bitmap") );
|
|
|
|
return M_BMPDATA->m_bitmap;
|
|
}
|
|
|
|
WXPixmap wxBitmap::GetDrawable() const
|
|
{
|
|
wxCHECK_MSG( Ok(), (WXPixmap) NULL, wxT("invalid bitmap") );
|
|
|
|
return M_BMPDATA->m_bpp == 1 ? M_BMPDATA->m_bitmap : M_BMPDATA->m_pixmap;
|
|
}
|
|
|
|
WXDisplay *wxBitmap::GetDisplay() const
|
|
{
|
|
wxCHECK_MSG( Ok(), (WXDisplay*) NULL, wxT("invalid bitmap") );
|
|
|
|
return M_BMPDATA->m_display;
|
|
}
|
|
|
|
#if wxUSE_NANOX
|
|
// Copy from the drawable to the wxImage
|
|
bool wxGetImageFromDrawable(GR_DRAW_ID drawable, int srcX, int srcY, int width, int height, wxImage& image)
|
|
{
|
|
GR_SCREEN_INFO sinfo;
|
|
int x, y;
|
|
GR_PIXELVAL *pixels;
|
|
GR_PALETTE* palette = NULL;
|
|
unsigned char rgb[3], *pp;
|
|
|
|
GrGetScreenInfo(&sinfo);
|
|
|
|
if (sinfo.pixtype == MWPF_PALETTE) {
|
|
if(!(palette = (GR_PALETTE*) malloc(sizeof(GR_PALETTE)))) {
|
|
return false;
|
|
}
|
|
GrGetSystemPalette(palette);
|
|
}
|
|
|
|
if(!(pixels = (GR_PIXELVAL*) malloc(sizeof(GR_PIXELVAL) * width * height)))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
image.Create(width, height);
|
|
|
|
GrReadArea(drawable, srcX, srcY, width, height,
|
|
pixels);
|
|
|
|
|
|
for(x = 0; x < sinfo.cols; x++) {
|
|
|
|
pp = (unsigned char *)pixels +
|
|
((x + (y * sinfo.cols)) *
|
|
sizeof(GR_PIXELVAL));
|
|
|
|
switch(sinfo.pixtype) {
|
|
/* FIXME: These may need modifying on big endian. */
|
|
case MWPF_TRUECOLOR0888:
|
|
case MWPF_TRUECOLOR888:
|
|
rgb[0] = pp[2];
|
|
rgb[1] = pp[1];
|
|
rgb[2] = pp[0];
|
|
break;
|
|
case MWPF_PALETTE:
|
|
rgb[0] = palette->palette[pp[0]].r;
|
|
rgb[1] = palette->palette[pp[0]].g;
|
|
rgb[2] = palette->palette[pp[0]].b;
|
|
break;
|
|
case MWPF_TRUECOLOR565:
|
|
rgb[0] = pp[1] & 0xf8;
|
|
rgb[1] = ((pp[1] & 0x07) << 5) |
|
|
((pp[0] & 0xe0) >> 3);
|
|
rgb[2] = (pp[0] & 0x1f) << 3;
|
|
break;
|
|
case MWPF_TRUECOLOR555:
|
|
rgb[0] = (pp[1] & 0x7c) << 1;
|
|
rgb[1] = ((pp[1] & 0x03) << 6) |
|
|
((pp[0] & 0xe0) >> 2);
|
|
rgb[2] = (pp[0] & 0x1f) << 3;
|
|
break;
|
|
case MWPF_TRUECOLOR332:
|
|
rgb[0] = pp[0] & 0xe0;
|
|
rgb[1] = (pp[0] & 0x1c) << 3;
|
|
rgb[2] = (pp[0] & 0x03) << 6;
|
|
break;
|
|
default:
|
|
fprintf(stderr, "Unsupported pixel "
|
|
"format\n");
|
|
return 1;
|
|
}
|
|
|
|
image.SetRGB(x, y, rgb[0], rgb[1], rgb[2]);
|
|
|
|
}
|
|
|
|
free(pixels);
|
|
if(palette) free(palette);
|
|
|
|
return true;
|
|
}
|
|
|
|
#if 0
|
|
int GrGetPixelColor(GR_SCREEN_INFO* sinfo, GR_PALETTE* palette, GR_PIXELVAL pixel,
|
|
unsigned char* red, unsigned char* green, unsigned char* blue)
|
|
{
|
|
unsigned char rgb[3], *pp;
|
|
|
|
pp = (unsigned char*) & pixel ;
|
|
|
|
switch (sinfo.pixtype)
|
|
{
|
|
/* FIXME: These may need modifying on big endian. */
|
|
case MWPF_TRUECOLOR0888:
|
|
case MWPF_TRUECOLOR888:
|
|
rgb[0] = pp[2];
|
|
rgb[1] = pp[1];
|
|
rgb[2] = pp[0];
|
|
break;
|
|
case MWPF_PALETTE:
|
|
rgb[0] = palette->palette[pp[0]].r;
|
|
rgb[1] = palette->palette[pp[0]].g;
|
|
rgb[2] = palette->palette[pp[0]].b;
|
|
break;
|
|
case MWPF_TRUECOLOR565:
|
|
rgb[0] = pp[1] & 0xf8;
|
|
rgb[1] = ((pp[1] & 0x07) << 5) |
|
|
((pp[0] & 0xe0) >> 3);
|
|
rgb[2] = (pp[0] & 0x1f) << 3;
|
|
break;
|
|
case MWPF_TRUECOLOR555:
|
|
rgb[0] = (pp[1] & 0x7c) << 1;
|
|
rgb[1] = ((pp[1] & 0x03) << 6) |
|
|
((pp[0] & 0xe0) >> 2);
|
|
rgb[2] = (pp[0] & 0x1f) << 3;
|
|
break;
|
|
case MWPF_TRUECOLOR332:
|
|
rgb[0] = pp[0] & 0xe0;
|
|
rgb[1] = (pp[0] & 0x1c) << 3;
|
|
rgb[2] = (pp[0] & 0x03) << 6;
|
|
break;
|
|
default:
|
|
fprintf(stderr, "Unsupported pixel format\n");
|
|
return 0;
|
|
}
|
|
|
|
|
|
*(red) = rgb[0];
|
|
*(green) = rgb[1];
|
|
*(blue) = rgb[2];
|
|
return 1;
|
|
}
|
|
#endif
|
|
|
|
#endif
|
|
// wxUSE_NANOX
|
|
|
|
// ============================================================================
|
|
// Bitmap handlers
|
|
// ============================================================================
|
|
|
|
IMPLEMENT_ABSTRACT_CLASS(wxBitmapHandler, wxBitmapHandlerBase)
|
|
|
|
#define M_BMPHANDLERDATA ((wxBitmapRefData *)bitmap->GetRefData())
|
|
|
|
#if wxUSE_XPM
|
|
|
|
#if wxHAVE_LIB_XPM || wxUSE_STREAMS
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxXPMFileHandler
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class wxXPMFileHandler : public wxBitmapHandler
|
|
{
|
|
DECLARE_DYNAMIC_CLASS(wxXPMFileHandler)
|
|
public:
|
|
wxXPMFileHandler()
|
|
{
|
|
SetName( wxT("XPM file") );
|
|
SetExtension( wxT("xpm") );
|
|
SetType( wxBITMAP_TYPE_XPM );
|
|
};
|
|
|
|
virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
|
|
int desiredWidth, int desiredHeight);
|
|
|
|
virtual bool SaveFile(const wxBitmap *bitmap, const wxString& name,
|
|
int type, const wxPalette *palette = NULL);
|
|
|
|
virtual bool Create(wxBitmap *WXUNUSED(bitmap), const void* WXUNUSED(data), long WXUNUSED(flags),
|
|
int WXUNUSED(width), int WXUNUSED(height), int WXUNUSED(depth) = 1)
|
|
{ return false; }
|
|
};
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler, wxBitmapHandler)
|
|
|
|
bool wxXPMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name,
|
|
long WXUNUSED(flags), int WXUNUSED(desiredWidth),
|
|
int WXUNUSED(desiredHeight))
|
|
{
|
|
#if wxHAVE_LIB_XPM
|
|
if (!bitmap->GetRefData())
|
|
bitmap->SetRefData( new wxBitmapRefData() );
|
|
|
|
M_BMPHANDLERDATA->m_display = wxGlobalDisplay();
|
|
|
|
Display *xdisplay = (Display*) M_BMPHANDLERDATA->m_display;
|
|
|
|
int xscreen = DefaultScreen( xdisplay );
|
|
Window xroot = RootWindow( xdisplay, xscreen );
|
|
|
|
int bpp = DefaultDepth( xdisplay, xscreen );
|
|
|
|
XpmAttributes xpmAttr;
|
|
xpmAttr.valuemask = XpmReturnInfos; // nothing yet, but get infos back
|
|
|
|
Pixmap pixmap;
|
|
Pixmap mask = 0;
|
|
|
|
int ErrorStatus = XpmReadFileToPixmap( xdisplay, xroot,
|
|
(char*) name.c_str(),
|
|
&pixmap, &mask, &xpmAttr);
|
|
|
|
if (ErrorStatus == XpmSuccess)
|
|
{
|
|
M_BMPHANDLERDATA->m_width = xpmAttr.width;
|
|
M_BMPHANDLERDATA->m_height = xpmAttr.height;
|
|
|
|
M_BMPHANDLERDATA->m_bpp = bpp; // mono as well?
|
|
|
|
XpmFreeAttributes(&xpmAttr);
|
|
|
|
M_BMPHANDLERDATA->m_bitmap = (WXPixmap) pixmap;
|
|
|
|
if (mask)
|
|
{
|
|
M_BMPHANDLERDATA->m_mask = new wxMask;
|
|
M_BMPHANDLERDATA->m_mask->SetBitmap( (WXPixmap) mask );
|
|
M_BMPHANDLERDATA->m_mask->SetDisplay( xdisplay );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
UnRef();
|
|
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
#elif wxUSE_STREAMS
|
|
wxXPMDecoder decoder;
|
|
wxFileInputStream stream(name);
|
|
if (stream.Ok())
|
|
{
|
|
wxImage image(decoder.ReadFile(stream));
|
|
return image.Ok() && bitmap->CreateFromImage(image);
|
|
}
|
|
|
|
return false;
|
|
#else // !wxHAVE_LIB_XPM && !wxUSE_STREAMS
|
|
return false;
|
|
#endif // wxHAVE_LIB_XPM / wxUSE_STREAMS
|
|
}
|
|
|
|
bool wxXPMFileHandler::SaveFile(const wxBitmap *bitmap, const wxString& name,
|
|
int type,
|
|
const wxPalette *WXUNUSED(palette))
|
|
{
|
|
wxImage image(bitmap->ConvertToImage());
|
|
if (image.Ok()) return image.SaveFile( name, (wxBitmapType)type );
|
|
|
|
return false;
|
|
}
|
|
|
|
#endif // wxHAVE_LIB_XPM || wxUSE_STREAMS
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxXPMDataHandler
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class wxXPMDataHandler : public wxBitmapHandler
|
|
{
|
|
DECLARE_DYNAMIC_CLASS(wxXPMDataHandler)
|
|
public:
|
|
wxXPMDataHandler()
|
|
{
|
|
SetName( wxT("XPM data") );
|
|
SetExtension( wxT("xpm") );
|
|
SetType( wxBITMAP_TYPE_XPM_DATA );
|
|
};
|
|
|
|
virtual bool LoadFile(wxBitmap *WXUNUSED(bitmap),
|
|
const wxString& WXUNUSED(name),
|
|
long WXUNUSED(flags),
|
|
int WXUNUSED(desiredWidth),
|
|
int WXUNUSED(desiredHeight))
|
|
{ return false; }
|
|
|
|
virtual bool SaveFile(const wxBitmap *WXUNUSED(bitmap),
|
|
const wxString& WXUNUSED(name),
|
|
int WXUNUSED(type),
|
|
const wxPalette *WXUNUSED(palette) = NULL)
|
|
{ return false; }
|
|
|
|
virtual bool Create(wxBitmap *bitmap, const void* data, long flags,
|
|
int width, int height, int depth = 1);
|
|
};
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler)
|
|
|
|
bool wxXPMDataHandler::Create(wxBitmap *bitmap, const void* bits,
|
|
long WXUNUSED(flags),
|
|
int WXUNUSED(width), int WXUNUSED(height), int WXUNUSED(depth))
|
|
{
|
|
#if wxHAVE_LIB_XPM
|
|
wxCHECK_MSG( bits != NULL, false, wxT("invalid bitmap data") );
|
|
|
|
if (!bitmap->GetRefData())
|
|
bitmap->SetRefData( new wxBitmapRefData() );
|
|
|
|
M_BMPHANDLERDATA->m_display = wxGlobalDisplay();
|
|
|
|
Display *xdisplay = (Display*) M_BMPHANDLERDATA->m_display;
|
|
|
|
int xscreen = DefaultScreen( xdisplay );
|
|
Window xroot = RootWindow( xdisplay, xscreen );
|
|
|
|
int bpp = DefaultDepth( xdisplay, xscreen );
|
|
|
|
XpmAttributes xpmAttr;
|
|
xpmAttr.valuemask = XpmReturnInfos; // nothing yet, but get infos back
|
|
|
|
Pixmap pixmap = 0;
|
|
Pixmap mask = 0;
|
|
|
|
int ErrorStatus = XpmCreatePixmapFromData( xdisplay, xroot, (char**) bits,
|
|
&pixmap, &mask, &xpmAttr );
|
|
|
|
if (ErrorStatus == XpmSuccess)
|
|
{
|
|
M_BMPHANDLERDATA->m_width = xpmAttr.width;
|
|
M_BMPHANDLERDATA->m_height = xpmAttr.height;
|
|
|
|
M_BMPHANDLERDATA->m_bpp = bpp; // mono as well?
|
|
|
|
#if __WXDEBUG__
|
|
unsigned int depthRet;
|
|
int xRet, yRet;
|
|
unsigned int widthRet, heightRet, borderWidthRet;
|
|
XGetGeometry( xdisplay, pixmap, &xroot, &xRet, &yRet,
|
|
&widthRet, &heightRet, &borderWidthRet, &depthRet);
|
|
|
|
wxASSERT_MSG( bpp == (int)depthRet, wxT("colour depth mismatch") );
|
|
#endif
|
|
|
|
XpmFreeAttributes(&xpmAttr);
|
|
|
|
M_BMPHANDLERDATA->m_pixmap = (WXPixmap) pixmap;
|
|
|
|
if (mask)
|
|
{
|
|
M_BMPHANDLERDATA->m_mask = new wxMask;
|
|
M_BMPHANDLERDATA->m_mask->SetBitmap( (WXPixmap) mask );
|
|
M_BMPHANDLERDATA->m_mask->SetDisplay( xdisplay );
|
|
}
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
bitmap->UnRef();
|
|
|
|
return false;
|
|
}
|
|
#else // !wxHAVE_LIB_XPM
|
|
wxXPMDecoder decoder;
|
|
wxImage image(decoder.ReadData((const char **)bits));
|
|
return image.Ok() && bitmap->CreateFromImage(image);
|
|
#endif // wxHAVE_LIB_XPM/!wxHAVE_LIB_XPM
|
|
}
|
|
|
|
#endif // wxUSE_XPM
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// wxXBMDataHandler
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class WXDLLEXPORT wxXBMDataHandler: public wxBitmapHandler
|
|
{
|
|
DECLARE_DYNAMIC_CLASS(wxXBMDataHandler)
|
|
public:
|
|
inline wxXBMDataHandler()
|
|
{
|
|
SetName( wxT("XBM data") );
|
|
SetExtension( wxT("xbm") );
|
|
SetType( wxBITMAP_TYPE_XBM_DATA );
|
|
};
|
|
|
|
virtual bool LoadFile(wxBitmap *WXUNUSED(bitmap),
|
|
const wxString& WXUNUSED(name),
|
|
long WXUNUSED(flags),
|
|
int WXUNUSED(desiredWidth),
|
|
int WXUNUSED(desiredHeight))
|
|
{ return false; }
|
|
|
|
virtual bool SaveFile(const wxBitmap *WXUNUSED(bitmap),
|
|
const wxString& WXUNUSED(name),
|
|
int WXUNUSED(type),
|
|
const wxPalette *WXUNUSED(palette) = NULL)
|
|
{ return false; }
|
|
|
|
virtual bool Create(wxBitmap *bitmap, const void* data, long flags,
|
|
int width, int height, int depth = 1);
|
|
};
|
|
|
|
IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler, wxBitmapHandler)
|
|
|
|
bool wxXBMDataHandler::Create( wxBitmap *bitmap, const void* bits,
|
|
long WXUNUSED(flags),
|
|
int width, int height, int WXUNUSED(depth))
|
|
{
|
|
#if !wxUSE_NANOX
|
|
if (!bitmap->GetRefData())
|
|
bitmap->SetRefData( new wxBitmapRefData() );
|
|
|
|
M_BMPHANDLERDATA->m_display = wxGlobalDisplay();
|
|
|
|
Display *xdisplay = (Display*) M_BMPHANDLERDATA->m_display;
|
|
|
|
int xscreen = DefaultScreen( xdisplay );
|
|
Window xroot = RootWindow( xdisplay, xscreen );
|
|
|
|
M_BMPHANDLERDATA->m_mask = (wxMask *) NULL;
|
|
M_BMPHANDLERDATA->m_bitmap =
|
|
(WXPixmap) XCreateBitmapFromData( xdisplay, xroot,
|
|
(char *) bits, width, height );
|
|
M_BMPHANDLERDATA->m_width = width;
|
|
M_BMPHANDLERDATA->m_height = height;
|
|
M_BMPHANDLERDATA->m_bpp = 1;
|
|
|
|
return true;
|
|
#else
|
|
wxCHECK_MSG( M_BMPHANDLERDATA->m_bitmap, false,
|
|
wxT("couldn't create bitmap") );
|
|
#endif
|
|
}
|
|
|
|
void wxBitmap::InitStandardHandlers()
|
|
{
|
|
AddHandler(new wxXBMDataHandler);
|
|
#if wxUSE_XPM
|
|
#if wxHAVE_LIB_XPM || wxUSE_STREAMS
|
|
AddHandler(new wxXPMFileHandler);
|
|
#endif
|
|
AddHandler(new wxXPMDataHandler);
|
|
#endif
|
|
}
|