X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/707440dc36592a083e26493a882efc0d95d91506..b5a49d4c5267d4eb933d45ec615ac2ed374750dc:/src/x11/bitmap.cpp diff --git a/src/x11/bitmap.cpp b/src/x11/bitmap.cpp index 138860acb5..31fd1858f0 100644 --- a/src/x11/bitmap.cpp +++ b/src/x11/bitmap.cpp @@ -18,9 +18,21 @@ #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 @@ -70,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 ); @@ -137,11 +150,13 @@ bool wxMask::Create( const wxBitmap& bitmap, XSetForeground( xdisplay, gc, BlackPixel(xdisplay,xscreen) ); - for (int j = 0; j < image.GetHeight(); j++) + 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 < image.GetWidth(); i++) + for (i = 0; i < width; i++) { if ((data[index] == red) && (data[index+1] == green) && @@ -167,6 +182,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 ) @@ -183,6 +202,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 ); @@ -210,6 +230,10 @@ bool wxMask::Create( const wxBitmap& bitmap ) XFreeGC( (Display*) m_display, gc ); return TRUE; +#else + return FALSE; +#endif + // wxUSE_NANOX } //----------------------------------------------------------------------------- @@ -291,6 +315,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 ); @@ -307,7 +338,7 @@ bool wxBitmap::Create( int width, int height, int depth ) M_BMPDATA->m_bpp = depth; } - +#endif return Ok(); } @@ -387,6 +418,113 @@ bool wxBitmap::CreateFromXpm( const char **bits ) 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") ) @@ -614,6 +752,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 ); @@ -623,7 +764,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 ); @@ -631,6 +772,8 @@ bool wxBitmap::CreateFromImage( const wxImage& image, int depth ) } return TRUE; +#endif + // wxUSE_NANOX } static void wxCalcPrecAndShift( unsigned long mask, int *shift, int *prec ) @@ -664,7 +807,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()) { @@ -760,10 +908,12 @@ wxImage wxBitmap::ConvertToImage() const // GdkColormap *cmap = gtk_widget_get_default_colormap(); + int width = GetWidth(); + int height = GetHeight(); long pos = 0; - for (int j = 0; j < GetHeight(); j++) + for (int j = 0; j < height; j++) { - for (int i = 0; i < GetWidth(); i++) + for (int i = 0; i < width; i++) { unsigned long pixel = XGetPixel( x_image, i, j ); if (bpp == 1) @@ -817,8 +967,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 ) @@ -833,6 +984,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(); @@ -847,7 +999,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") ); } @@ -1037,7 +1189,7 @@ bool wxBitmap::LoadFile( const wxString &name, int type ) wxFileInputStream stream(name); if (stream.Ok()) { - wxImage image(decoder.Read(stream)); + wxImage image(decoder.ReadFile(stream)); if (image.Ok()) return CreateFromImage(image); else @@ -1129,3 +1281,140 @@ 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 +