X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/a11672a469f036436838911c268cb2f8d5da5bf8..cd72551c2b6cbf67a4a5caf0ba00ba64e41183b2:/src/x11/bitmap.cpp diff --git a/src/x11/bitmap.cpp b/src/x11/bitmap.cpp index 6d4c558c3e..07dad230d6 100644 --- a/src/x11/bitmap.cpp +++ b/src/x11/bitmap.cpp @@ -18,11 +18,28 @@ #include "wx/log.h" #include "wx/image.h" #include "wx/app.h" +#if wxUSE_NANOX +#include "wx/dcmemory.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 +#include +#else +#include "wx/xpmdecod.h" +#include "wx/wfstream.h" +#endif #endif #include @@ -65,6 +82,7 @@ wxMask::~wxMask() bool wxMask::Create( const wxBitmap& bitmap, const wxColour& colour ) { +#if !wxUSE_NANOX if (m_bitmap) { XFreePixmap( (Display*) m_display, (Pixmap) m_bitmap ); @@ -162,6 +180,10 @@ bool wxMask::Create( const wxBitmap& bitmap, XFreeGC( xdisplay, gc ); return TRUE; +#else + return FALSE; +#endif + // wxUSE_NANOX } bool wxMask::Create( const wxBitmap& bitmap, int paletteIndex ) @@ -178,6 +200,7 @@ bool wxMask::Create( const wxBitmap& bitmap, int paletteIndex ) bool wxMask::Create( const wxBitmap& bitmap ) { +#if !wxUSE_NANOX if (m_bitmap) { XFreePixmap( (Display*) m_display, (Pixmap) m_bitmap ); @@ -205,6 +228,10 @@ bool wxMask::Create( const wxBitmap& bitmap ) XFreeGC( (Display*) m_display, gc ); return TRUE; +#else + return FALSE; +#endif + // wxUSE_NANOX } //----------------------------------------------------------------------------- @@ -286,6 +313,13 @@ bool wxBitmap::Create( int width, int height, int 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 ); @@ -302,12 +336,14 @@ bool wxBitmap::Create( int width, int height, int depth ) M_BMPDATA->m_bpp = depth; } - +#endif return Ok(); } bool wxBitmap::CreateFromXpm( const char **bits ) { +#if wxUSE_XPM +#if wxHAVE_LIB_XPM UnRef(); wxCHECK_MSG( bits != NULL, FALSE, wxT("invalid bitmap data") ) @@ -358,6 +394,7 @@ bool wxBitmap::CreateFromXpm( const char **bits ) M_BMPDATA->m_mask->SetBitmap( (WXPixmap) mask ); M_BMPDATA->m_mask->SetDisplay( xdisplay ); } + return TRUE; } else { @@ -365,12 +402,127 @@ bool wxBitmap::CreateFromXpm( const char **bits ) return FALSE; } - - return TRUE; +#else + wxXPMDecoder decoder; + wxImage image(decoder.ReadData(bits)); + if (image.Ok()) + return CreateFromImage(image); + else + return FALSE; +#endif +#endif + return FALSE; } bool wxBitmap::CreateFromImage( const wxImage& image, int depth ) { +#if wxUSE_NANOX + if (!image.Ok()) + { + wxASSERT_MSG(image.Ok(), "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") ) @@ -598,6 +750,9 @@ bool wxBitmap::CreateFromImage( const wxImage& image, int depth ) 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 ); +#ifdef __WXDEBUG__ + XSync(wxGlobalDisplay(), False); +#endif XDestroyImage( data_image ); XFreeGC( xdisplay, gc ); @@ -607,7 +762,7 @@ bool wxBitmap::CreateFromImage( const wxImage& image, int depth ) if (image.HasMask()) { GC gc = XCreateGC( xdisplay, (Pixmap) GetMask()->GetBitmap(), 0, NULL ); - XPutImage( xdisplay, (Pixmap) GetMask()->GetBitmap(), gc, data_image, 0, 0, 0, 0, width, height ); + XPutImage( xdisplay, (Pixmap) GetMask()->GetBitmap(), gc, mask_image, 0, 0, 0, 0, width, height ); XDestroyImage( mask_image ); XFreeGC( xdisplay, gc ); @@ -615,6 +770,8 @@ bool wxBitmap::CreateFromImage( const wxImage& image, int depth ) } return TRUE; +#endif + // wxUSE_NANOX } static void wxCalcPrecAndShift( unsigned long mask, int *shift, int *prec ) @@ -648,7 +805,12 @@ wxImage wxBitmap::ConvertToImage() const Visual* xvisual = DefaultVisual( xdisplay, xscreen ); int bpp = DefaultDepth( xdisplay, xscreen ); - + +#if wxUSE_NANOX + wxGetImageFromDrawable((Pixmap) GetPixmap(), 0, 0, GetWidth(), GetHeight(), image); + return image; +#else + // !wxUSE_NANOX XImage *x_image = NULL; if (GetPixmap()) { @@ -801,8 +963,9 @@ wxImage wxBitmap::ConvertToImage() const XDestroyImage( x_image ); if (x_image_mask) XDestroyImage( x_image_mask ); - return image; +#endif + // wxUSE_NANOX } wxBitmap::wxBitmap( const wxBitmap& bmp ) @@ -817,6 +980,7 @@ wxBitmap::wxBitmap( const wxString &filename, int type ) wxBitmap::wxBitmap( const char bits[], int width, int height, int WXUNUSED(depth) ) { +#if !wxUSE_NANOX m_refData = new wxBitmapRefData(); M_BMPDATA->m_display = wxGlobalDisplay(); @@ -831,7 +995,7 @@ wxBitmap::wxBitmap( const char bits[], int width, int height, int WXUNUSED(depth M_BMPDATA->m_width = width; M_BMPDATA->m_height = height; M_BMPDATA->m_bpp = 1; - +#endif wxCHECK_RET( M_BMPDATA->m_bitmap, wxT("couldn't create bitmap") ); } @@ -970,6 +1134,8 @@ bool wxBitmap::LoadFile( const wxString &name, int type ) if (type == wxBITMAP_TYPE_XPM) { +#if wxUSE_XPM +#if wxHAVE_LIB_XPM m_refData = new wxBitmapRefData(); M_BMPDATA->m_display = wxGlobalDisplay(); @@ -1013,6 +1179,29 @@ bool wxBitmap::LoadFile( const wxString &name, int type ) return FALSE; } +#else +#if wxUSE_STREAMS + wxXPMDecoder decoder; + wxFileInputStream stream(name); + if (stream.Ok()) + { + wxImage image(decoder.ReadFile(stream)); + if (image.Ok()) + return CreateFromImage(image); + else + return FALSE; + } + else + return FALSE; +#else + return FALSE; +#endif + // wxUSE_STREAMS +#endif + // wxHAVE_LIB_XPM +#endif + // wxUSE_XPM + return FALSE; } else // try if wxImage can load it { @@ -1088,3 +1277,139 @@ WXDisplay *wxBitmap::GetDisplay() const 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 +