X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/afbfbfdf2b6a467474ace5b51232548f09a45dc8..9c7669d7a4ecf5fee714dccc0718165b871beca1:/src/gtk/bitmap.cpp diff --git a/src/gtk/bitmap.cpp b/src/gtk/bitmap.cpp index de5863dd79..fcc84f7786 100644 --- a/src/gtk/bitmap.cpp +++ b/src/gtk/bitmap.cpp @@ -18,22 +18,13 @@ #include "wx/icon.h" #include "wx/math.h" #include "wx/image.h" + #include "wx/colour.h" #endif #include "wx/rawbmp.h" #include -extern void gdk_wx_draw_bitmap (GdkDrawable *drawable, - GdkGC *gc, - GdkDrawable *src, - gint xsrc, - gint ysrc, - gint xdest, - gint ydest, - gint width, - gint height); - //----------------------------------------------------------------------------- // data //----------------------------------------------------------------------------- @@ -86,80 +77,60 @@ bool wxMask::Create( const wxBitmap& bitmap, m_bitmap = (GdkBitmap*) NULL; } - wxImage image = bitmap.ConvertToImage(); - if (!image.Ok()) return false; - - m_bitmap = gdk_pixmap_new( wxGetRootWindow()->window, image.GetWidth(), image.GetHeight(), 1 ); - GdkGC *gc = gdk_gc_new( m_bitmap ); - - GdkColor color; - color.pixel = 1; - gdk_gc_set_foreground( gc, &color ); - gdk_draw_rectangle( m_bitmap, gc, TRUE, 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(); + const int w = bitmap.GetWidth(); + const int h = bitmap.GetHeight(); - GdkVisual *visual = wxTheApp->GetGdkVisual(); + // create mask as XBM format bitmap - int bpp = visual->depth; - if ((bpp == 16) && (visual->red_mask != 0xf800)) - bpp = 15; - if (bpp == 15) + // one bit per pixel, each row starts on a byte boundary + const size_t out_size = size_t((w + 7) / 8) * unsigned(h); + wxByte* out = new wxByte[out_size]; + // set bits are unmasked + memset(out, 0xff, out_size); + unsigned bit_index = 0; + if (bitmap.HasPixbuf()) { - red = red & 0xf8; - green = green & 0xf8; - blue = blue & 0xf8; - } - else if (bpp == 16) - { - red = red & 0xf8; - green = green & 0xfc; - blue = blue & 0xf8; - } - else if (bpp == 12) - { - red = red & 0xf0; - green = green & 0xf0; - blue = blue & 0xf0; + const wxByte r_mask = colour.Red(); + const wxByte g_mask = colour.Green(); + const wxByte b_mask = colour.Blue(); + GdkPixbuf* pixbuf = bitmap.GetPixbuf(); + const wxByte* in = gdk_pixbuf_get_pixels(pixbuf); + const int inc = 3 + int(gdk_pixbuf_get_has_alpha(pixbuf) != 0); + const int rowpadding = gdk_pixbuf_get_rowstride(pixbuf) - inc * w; + for (int y = 0; y < h; y++, in += rowpadding) + { + for (int x = 0; x < w; x++, in += inc, bit_index++) + if (in[0] == r_mask && in[1] == g_mask && in[2] == b_mask) + out[bit_index >> 3] ^= 1 << (bit_index & 7); + // move index to next byte boundary + bit_index = (bit_index + 7) & ~7u; + } } - - color.pixel = 0; - gdk_gc_set_foreground( gc, &color ); - - for (int j = 0; j < image.GetHeight(); j++) + else { - int start_x = -1; - int i; - for (i = 0; i < image.GetWidth(); i++) + GdkImage* image = gdk_drawable_get_image(bitmap.GetPixmap(), 0, 0, w, h); + GdkColormap* colormap = gdk_image_get_colormap(image); + guint32 mask_pixel; + if (colormap == NULL) + // mono bitmap, white is pixel value 0 + mask_pixel = guint32(colour.Red() != 255 || colour.Green() != 255 || colour.Blue() != 255); + else { - if ((data[index] == red) && - (data[index+1] == green) && - (data[index+2] == blue)) - { - if (start_x == -1) - start_x = i; - } - else - { - if (start_x != -1) - { - gdk_draw_line( m_bitmap, gc, start_x, j, i-1, j ); - start_x = -1; - } - } - index += 3; + wxColor c(colour); + c.CalcPixel(colormap); + mask_pixel = c.GetPixel(); + } + for (int y = 0; y < h; y++) + { + for (int x = 0; x < w; x++, bit_index++) + if (gdk_image_get_pixel(image, x, y) == mask_pixel) + out[bit_index >> 3] ^= 1 << (bit_index & 7); + bit_index = (bit_index + 7) & ~7u; } - if (start_x != -1) - gdk_draw_line( m_bitmap, gc, start_x, j, i, j ); + g_object_unref(image); } - - g_object_unref (gc); - + m_bitmap = gdk_bitmap_create_from_data(wxGetRootWindow()->window, (char*)out, w, h); + delete[] out; return true; } @@ -194,9 +165,8 @@ bool wxMask::Create( const wxBitmap& bitmap ) if (!m_bitmap) return false; GdkGC *gc = gdk_gc_new( m_bitmap ); - - gdk_wx_draw_bitmap( m_bitmap, gc, bitmap.GetPixmap(), 0, 0, 0, 0, bitmap.GetWidth(), bitmap.GetHeight() ); - + gdk_gc_set_function(gc, GDK_COPY_INVERT); + gdk_draw_drawable(m_bitmap, gc, bitmap.GetPixmap(), 0, 0, 0, 0, bitmap.GetWidth(), bitmap.GetHeight()); g_object_unref (gc); return true; @@ -215,7 +185,7 @@ class wxBitmapRefData: public wxObjectRefData { public: wxBitmapRefData(); - ~wxBitmapRefData(); + virtual ~wxBitmapRefData(); GdkPixmap *m_pixmap; GdkPixbuf *m_pixbuf; @@ -333,7 +303,7 @@ wxBitmap wxBitmap::Rescale( int clipx, int clipy, int clipwidth, int clipheight, { bmp.SetDepth(GetDepth()); bmp.SetPixbuf(gdk_pixbuf_new(GDK_COLORSPACE_RGB, - gdk_pixbuf_get_has_alpha(GetPixbuf()), + true, //gdk_pixbuf_get_has_alpha(GetPixbuf()), 8, width, height)); gdk_pixbuf_scale(GetPixbuf(), bmp.GetPixbuf(), 0, 0, width, height, @@ -508,171 +478,89 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth) return false; if (depth == 1) - return CreateFromImageAsBitmap(image); + return CreateFromImageAsPixmap(image, depth); if (image.HasAlpha()) return CreateFromImageAsPixbuf(image); - return CreateFromImageAsPixmap(image); + return CreateFromImageAsPixmap(image, depth); } -// conversion to mono bitmap: -bool wxBitmap::CreateFromImageAsBitmap(const wxImage& img) +bool wxBitmap::CreateFromImageAsPixmap(const wxImage& image, int depth) { - // convert alpha channel to mask, if it is present: - wxImage image(img); - image.ConvertAlphaToMask(); - - int width = image.GetWidth(); - int height = image.GetHeight(); - - SetPixmap( gdk_pixmap_new( wxGetRootWindow()->window, width, height, 1 ) ); - - // Create picture image - - GdkGC* data_gc = gdk_gc_new(M_BMPDATA->m_pixmap); - GdkColor color; - color.pixel = 1; - gdk_gc_set_foreground(data_gc, &color); - gdk_draw_rectangle(M_BMPDATA->m_pixmap, data_gc, true, 0, 0, width, height); - GdkImage* data_image = gdk_drawable_get_image(M_BMPDATA->m_pixmap, 0, 0, width, height); - - // Create mask image - - GdkImage *mask_image = (GdkImage*) NULL; - GdkGC* mask_gc = NULL; - - if (image.HasMask()) + const int w = image.GetWidth(); + const int h = image.GetHeight(); + if (depth == 1) { - wxMask* mask = new wxMask; - mask->m_bitmap = gdk_pixmap_new( wxGetRootWindow()->window, width, height, 1 ); - mask_gc = gdk_gc_new(mask->m_bitmap); - gdk_gc_set_foreground(mask_gc, &color); - gdk_draw_rectangle(mask->m_bitmap, mask_gc, true, 0, 0, width, height); - mask_image = gdk_drawable_get_image(mask->m_bitmap, 0, 0, width, height); - - SetMask( mask ); + // create XBM format bitmap + + // one bit per pixel, each row starts on a byte boundary + const size_t out_size = size_t((w + 7) / 8) * unsigned(h); + wxByte* out = new wxByte[out_size]; + // set bits are black + memset(out, 0xff, out_size); + const wxByte* in = image.GetData(); + unsigned bit_index = 0; + for (int y = 0; y < h; y++) + { + for (int x = 0; x < w; x++, in += 3, bit_index++) + if (in[0] == 255 && in[1] == 255 && in[2] == 255) + out[bit_index >> 3] ^= 1 << (bit_index & 7); + // move index to next byte boundary + bit_index = (bit_index + 7) & ~7u; + } + SetPixmap(gdk_bitmap_create_from_data(wxGetRootWindow()->window, (char*)out, w, h)); + delete[] out; + } + else + { + SetPixmap(gdk_pixmap_new(wxGetRootWindow()->window, w, h, depth)); + GdkGC* gc = gdk_gc_new(M_BMPDATA->m_pixmap); + gdk_draw_rgb_image( + M_BMPDATA->m_pixmap, gc, + 0, 0, w, h, + GDK_RGB_DITHER_NONE, image.GetData(), w * 3); + g_object_unref(gc); } - int r_mask = image.GetMaskRed(); - int g_mask = image.GetMaskGreen(); - int b_mask = image.GetMaskBlue(); - - unsigned char* data = image.GetData(); - - int index = 0; - for (int y = 0; y < height; y++) + const wxByte* alpha = image.GetAlpha(); + if (alpha != NULL || image.HasMask()) { - for (int x = 0; x < width; x++) + // create mask as XBM format bitmap + + const size_t out_size = size_t((w + 7) / 8) * unsigned(h); + wxByte* out = new wxByte[out_size]; + memset(out, 0xff, out_size); + unsigned bit_index = 0; + if (alpha != NULL) { - int r = data[index]; - index++; - int g = data[index]; - index++; - int b = data[index]; - index++; - - if (mask_image != NULL) + for (int y = 0; y < h; y++) { - if ((r == r_mask) && (b == b_mask) && (g == g_mask)) - gdk_image_put_pixel( mask_image, x, y, 0 ); + for (int x = 0; x < w; x++, bit_index++) + if (*alpha++ < wxIMAGE_ALPHA_THRESHOLD) + out[bit_index >> 3] ^= 1 << (bit_index & 7); + bit_index = (bit_index + 7) & ~7u; } - - if ((r == 255) && (b == 255) && (g == 255)) - gdk_image_put_pixel( data_image, x, y, 0 ); - - } // for - } // for - - // Blit picture - - gdk_draw_image( GetPixmap(), data_gc, data_image, 0, 0, 0, 0, width, height ); - - g_object_unref (data_image); - g_object_unref (data_gc); - - // Blit mask - - if (mask_image != NULL) - { - gdk_draw_image( GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height ); - - g_object_unref (mask_image); - g_object_unref (mask_gc); - } - - return true; -} - -// conversion to colour bitmap: -bool wxBitmap::CreateFromImageAsPixmap(const wxImage& image) -{ - // alpha is handled by CreateFromImageAsPixbuf - wxASSERT(!image.HasAlpha()); - - int width = image.GetWidth(); - int height = image.GetHeight(); - - SetPixmap( gdk_pixmap_new( wxGetRootWindow()->window, width, height, -1 ) ); - - GdkGC *gc = gdk_gc_new( GetPixmap() ); - - gdk_draw_rgb_image( GetPixmap(), - gc, - 0, 0, - width, height, - GDK_RGB_DITHER_NONE, - image.GetData(), - width*3 ); - - g_object_unref (gc); - - // Create mask image - - if (!image.HasMask()) - return true; - - wxMask* mask = new wxMask; - mask->m_bitmap = gdk_pixmap_new( wxGetRootWindow()->window, width, height, 1 ); - GdkGC* mask_gc = gdk_gc_new(mask->m_bitmap); - GdkColor color; - color.pixel = 1; - gdk_gc_set_foreground(mask_gc, &color); - gdk_draw_rectangle(mask->m_bitmap, mask_gc, true, 0, 0, width, height); - GdkImage* mask_image = gdk_drawable_get_image(mask->m_bitmap, 0, 0, width, height); - - SetMask( mask ); - - int r_mask = image.GetMaskRed(); - int g_mask = image.GetMaskGreen(); - int b_mask = image.GetMaskBlue(); - - unsigned char* data = image.GetData(); - - int index = 0; - for (int y = 0; y < height; y++) - { - for (int x = 0; x < width; x++) + } + else { - int r = data[index]; - index++; - int g = data[index]; - index++; - int b = data[index]; - index++; - - if ((r == r_mask) && (b == b_mask) && (g == g_mask)) - gdk_image_put_pixel( mask_image, x, y, 0 ); - } // for - } // for - - // Blit mask - - gdk_draw_image( GetMask()->GetBitmap(), mask_gc, mask_image, 0, 0, 0, 0, width, height ); - - g_object_unref (mask_image); - g_object_unref (mask_gc); - + const wxByte r_mask = image.GetMaskRed(); + const wxByte g_mask = image.GetMaskGreen(); + const wxByte b_mask = image.GetMaskBlue(); + const wxByte* in = image.GetData(); + for (int y = 0; y < h; y++) + { + for (int x = 0; x < w; x++, in += 3, bit_index++) + if (in[0] == r_mask && in[1] == g_mask && in[2] == b_mask) + out[bit_index >> 3] ^= 1 << (bit_index & 7); + bit_index = (bit_index + 7) & ~7u; + } + } + wxMask* mask = new wxMask; + mask->m_bitmap = gdk_bitmap_create_from_data(M_BMPDATA->m_pixmap, (char*)out, w, h); + SetMask(mask); + delete[] out; + } return true; } @@ -682,7 +570,7 @@ bool wxBitmap::CreateFromImageAsPixbuf(const wxImage& image) int height = image.GetHeight(); GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, - image.HasAlpha(), + true, //image.HasAlpha(), 8 /* bits per sample */, width, height); if (!pixbuf) @@ -693,7 +581,7 @@ bool wxBitmap::CreateFromImageAsPixbuf(const wxImage& image) wxASSERT( gdk_pixbuf_get_width(pixbuf) == width ); wxASSERT( gdk_pixbuf_get_height(pixbuf) == height ); - SetDepth(wxTheApp->GetGdkVisual()->depth); + SetDepth(32); SetPixbuf(pixbuf); // Copy the data: @@ -759,7 +647,7 @@ wxImage wxBitmap::ConvertToImage() const GdkPixmap* pixmap_invert = NULL; if (GetDepth() == 1) { - // mono bitmaps are inverted + // mono bitmaps are inverted, i.e. 0 is white pixmap_invert = gdk_pixmap_new(pixmap, w, h, 1); GdkGC* gc = gdk_gc_new(pixmap_invert); gdk_gc_set_function(gc, GDK_COPY_INVERT); @@ -905,7 +793,7 @@ wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const if (HasPixbuf()) { GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, - gdk_pixbuf_get_has_alpha(GetPixbuf()), + true, //gdk_pixbuf_get_has_alpha(GetPixbuf()), 8, rect.width, rect.height); ret.SetPixbuf(pixbuf); ret.SetDepth(M_BMPDATA->m_bpp); @@ -916,23 +804,9 @@ wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const else { ret = wxBitmap(rect.width, rect.height, M_BMPDATA->m_bpp); - if (M_BMPDATA->m_bpp != 1) - { - GdkGC *gc = gdk_gc_new( ret.GetPixmap() ); - gdk_draw_drawable( ret.GetPixmap(), gc, GetPixmap(), rect.x, rect.y, 0, 0, rect.width, rect.height ); - g_object_unref (gc); - } - else - { - GdkGC *gc = gdk_gc_new( ret.GetPixmap() ); - GdkColor col; - col.pixel = 0xFFFFFF; - gdk_gc_set_foreground( gc, &col ); - col.pixel = 0; - gdk_gc_set_background( gc, &col ); - gdk_wx_draw_bitmap( ret.GetPixmap(), gc, GetPixmap(), rect.x, rect.y, 0, 0, rect.width, rect.height ); - g_object_unref (gc); - } + GdkGC *gc = gdk_gc_new( ret.GetPixmap() ); + gdk_draw_drawable( ret.GetPixmap(), gc, GetPixmap(), rect.x, rect.y, 0, 0, rect.width, rect.height ); + g_object_unref (gc); } if (GetMask()) @@ -941,12 +815,7 @@ wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const mask->m_bitmap = gdk_pixmap_new( wxGetRootWindow()->window, rect.width, rect.height, 1 ); GdkGC *gc = gdk_gc_new( mask->m_bitmap ); - GdkColor col; - col.pixel = 0xFFFFFF; - gdk_gc_set_foreground( gc, &col ); - col.pixel = 0; - gdk_gc_set_background( gc, &col ); - gdk_wx_draw_bitmap( mask->m_bitmap, gc, M_BMPDATA->m_mask->m_bitmap, rect.x, rect.y, 0, 0, rect.width, rect.height ); + gdk_draw_drawable(mask->m_bitmap, gc, M_BMPDATA->m_mask->m_bitmap, rect.x, rect.y, 0, 0, rect.width, rect.height); g_object_unref (gc); ret.SetMask( mask ); @@ -1074,8 +943,10 @@ GdkPixbuf *wxBitmap::GetPixbuf() const int width = GetWidth(); int height = GetHeight(); + // always create the alpha channel so raw bitmap access will work + // correctly GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, - GetMask() != NULL, + true, // GetMask() != NULL, 8, width, height); M_BMPDATA->m_pixbuf = gdk_pixbuf_get_from_drawable(pixbuf, M_BMPDATA->m_pixmap, NULL, @@ -1156,11 +1027,14 @@ void *wxBitmap::GetRawData(wxPixelDataBase& data, int bpp) if (!pixbuf) return NULL; + if (!gdk_pixbuf_get_has_alpha( pixbuf )) + return NULL; + #if 0 if (gdk_pixbuf_get_has_alpha( pixbuf )) - wxPrintf( wxT("Has alpha\n") ); + wxPrintf( wxT("Has alpha, %d channels\n"), gdk_pixbuf_get_n_channels(pixbuf) ); else - wxPrintf( wxT("No alpha.\n") ); + wxPrintf( wxT("No alpha, %d channels.\n"), gdk_pixbuf_get_n_channels(pixbuf) ); #endif data.m_height = gdk_pixbuf_get_height( pixbuf );