X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/8362e67ca7c330fd5ac67ab395d56bcc0c786494..4a699e3a59b19c21b6faae714b56cac5a75df2e2:/src/gtk/bitmap.cpp?ds=sidebyside diff --git a/src/gtk/bitmap.cpp b/src/gtk/bitmap.cpp index 0a519cf24e..9a730d8534 100644 --- a/src/gtk/bitmap.cpp +++ b/src/gtk/bitmap.cpp @@ -21,6 +21,7 @@ #include "wx/rawbmp.h" #include "wx/gtk/private/object.h" +#include "wx/gtk/private.h" #include @@ -79,6 +80,23 @@ wxMask::wxMask() m_bitmap = NULL; } +wxMask::wxMask(const wxMask& mask) +{ + if ( !mask.m_bitmap ) + { + m_bitmap = NULL; + return; + } + + // create a copy of an existing mask + gint w, h; + gdk_drawable_get_size(mask.m_bitmap, &w, &h); + m_bitmap = gdk_pixmap_new(mask.m_bitmap, w, h, 1); + + wxGtkObject gc(gdk_gc_new(m_bitmap)); + gdk_draw_drawable(m_bitmap, gc, mask.m_bitmap, 0, 0, 0, 0, -1, -1); +} + wxMask::wxMask( const wxBitmap& bitmap, const wxColour& colour ) { m_bitmap = NULL; @@ -99,6 +117,11 @@ wxMask::wxMask( const wxBitmap& bitmap ) InitFromMonoBitmap(bitmap); } +wxMask::wxMask(GdkPixmap* bitmap) +{ + m_bitmap = bitmap; +} + wxMask::~wxMask() { if (m_bitmap) @@ -190,7 +213,7 @@ bool wxMask::InitFromMonoBitmap(const wxBitmap& bitmap) return true; } -GdkBitmap *wxMask::GetBitmap() const +GdkPixmap* wxMask::GetBitmap() const { return m_bitmap; } @@ -214,6 +237,13 @@ public: int m_height; int m_bpp; bool m_alphaRequested; + +private: + // We don't provide a copy ctor as copying m_pixmap and m_pixbuf properly + // is expensive and we don't want to do it implicitly (and possibly + // accidentally). wxBitmap::CloneGDIRefData() which does need to do it does + // it explicitly itself. + wxDECLARE_NO_COPY_CLASS(wxBitmapRefData); }; wxBitmapRefData::wxBitmapRefData(int width, int height, int depth) @@ -276,8 +306,19 @@ wxBitmap::wxBitmap(const char* const* bits) if (M_BMPDATA->m_pixmap != NULL && mask != NULL) { - M_BMPDATA->m_mask = new wxMask; - M_BMPDATA->m_mask->m_bitmap = mask; + M_BMPDATA->m_mask = new wxMask(mask); + } +} + +wxBitmap::wxBitmap(GdkPixbuf* pixbuf) +{ + if (pixbuf) + { + wxBitmapRefData* bmpData = new wxBitmapRefData( + gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), + gdk_pixbuf_get_n_channels(pixbuf) * 8); + m_refData = bmpData; + bmpData->m_pixbuf = pixbuf; } } @@ -300,13 +341,11 @@ bool wxBitmap::CreateFromImage(const wxImage& image, int depth) UnRef(); wxCHECK_MSG( image.IsOk(), false, wxT("invalid image") ); - wxCHECK_MSG( depth == -1 || depth == 1, false, wxT("invalid bitmap depth") ); if (image.GetWidth() <= 0 || image.GetHeight() <= 0) return false; - // create pixbuf if image has alpha and requested depth is compatible - if (image.HasAlpha() && (depth == -1 || depth == 32)) + if (depth == 32 || (depth == -1 && image.HasAlpha())) return CreateFromImageAsPixbuf(image); // otherwise create pixmap, if alpha is present it will be converted to mask @@ -388,9 +427,7 @@ bool wxBitmap::CreateFromImageAsPixmap(const wxImage& image, int depth) 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); + SetMask(new wxMask(gdk_bitmap_create_from_data(M_BMPDATA->m_pixmap, (char*)out, w, h))); delete[] out; } return IsOk(); @@ -398,8 +435,6 @@ bool wxBitmap::CreateFromImageAsPixmap(const wxImage& image, int depth) bool wxBitmap::CreateFromImageAsPixbuf(const wxImage& image) { - wxASSERT(image.HasAlpha()); - int width = image.GetWidth(); int height = image.GetHeight(); @@ -417,12 +452,13 @@ bool wxBitmap::CreateFromImageAsPixbuf(const wxImage& image) for (int y = 0; y < height; y++, out += rowpad) { - for (int x = 0; x < width; x++, alpha++, out += 4, in += 3) + for (int x = 0; x < width; x++, out += 4, in += 3) { out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; - out[3] = *alpha; + if (alpha) + out[3] = *alpha++; } } @@ -589,10 +625,8 @@ wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const rect.y + h <= bmpData->m_height, ret, wxT("invalid bitmap region")); - wxBitmapRefData* newRef = new wxBitmapRefData(*bmpData); + wxBitmapRefData * const newRef = new wxBitmapRefData(w, h, bmpData->m_bpp); ret.m_refData = newRef; - newRef->m_width = w; - newRef->m_height = h; if (bmpData->m_pixbuf) { @@ -609,15 +643,16 @@ wxBitmap wxBitmap::GetSubBitmap( const wxRect& rect) const newRef->m_pixmap, gc, bmpData->m_pixmap, rect.x, rect.y, 0, 0, w, h); g_object_unref(gc); } - newRef->m_mask = NULL; - if (bmpData->m_mask && bmpData->m_mask->m_bitmap) + GdkPixmap* mask = NULL; + if (bmpData->m_mask) + mask = bmpData->m_mask->GetBitmap(); + if (mask) { - GdkPixmap* sub_mask = gdk_pixmap_new(bmpData->m_mask->m_bitmap, w, h, 1); - newRef->m_mask = new wxMask; - newRef->m_mask->m_bitmap = sub_mask; + GdkPixmap* sub_mask = gdk_pixmap_new(mask, w, h, 1); + newRef->m_mask = new wxMask(sub_mask); GdkGC* gc = gdk_gc_new(sub_mask); gdk_draw_drawable( - sub_mask, gc, bmpData->m_mask->m_bitmap, rect.x, rect.y, 0, 0, w, h); + sub_mask, gc, mask, rect.x, rect.y, 0, 0, w, h); g_object_unref(gc); } @@ -643,7 +678,7 @@ bool wxBitmap::SaveFile( const wxString &name, wxBitmapType type, const wxPalett default: break; } return type_name && - gdk_pixbuf_save(GetPixbuf(), name.fn_str(), type_name, NULL, NULL); + gdk_pixbuf_save(GetPixbuf(), wxGTK_CONV_FN(name), type_name, NULL, NULL); } bool wxBitmap::LoadFile( const wxString &name, wxBitmapType type ) @@ -655,10 +690,9 @@ bool wxBitmap::LoadFile( const wxString &name, wxBitmapType type ) else #endif { - UnRef(); - GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file(name.fn_str(), NULL); - if (pixbuf) - SetPixbuf(pixbuf); + wxUnusedVar(type); // The type is detected automatically by GDK. + + *this = wxBitmap(gdk_pixbuf_new_from_file(wxGTK_CONV_FN(name), NULL)); } return IsOk(); @@ -719,16 +753,20 @@ GdkPixmap *wxBitmap::GetPixmap() const if (bmpData->m_pixbuf) { + GdkPixmap* pixmap = NULL; GdkPixmap** mask_pixmap = NULL; if (gdk_pixbuf_get_has_alpha(bmpData->m_pixbuf)) { // make new mask from alpha - delete bmpData->m_mask; - bmpData->m_mask = new wxMask; - mask_pixmap = &bmpData->m_mask->m_bitmap; + mask_pixmap = &pixmap; } gdk_pixbuf_render_pixmap_and_mask( bmpData->m_pixbuf, &bmpData->m_pixmap, mask_pixmap, 128); + if (pixmap) + { + delete bmpData->m_mask; + bmpData->m_mask = new wxMask(pixmap); + } } else { @@ -757,7 +795,7 @@ GdkPixbuf *wxBitmap::GetPixbuf() const const int h = bmpData->m_height; GdkPixmap* mask = NULL; if (bmpData->m_mask) - mask = bmpData->m_mask->m_bitmap; + mask = bmpData->m_mask->GetBitmap(); const bool useAlpha = bmpData->m_alphaRequested || mask; bmpData->m_pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, useAlpha, 8, w, h); if (bmpData->m_pixmap) @@ -774,22 +812,6 @@ bool wxBitmap::HasPixbuf() const return M_BMPDATA->m_pixbuf != NULL; } -void wxBitmap::SetPixbuf(GdkPixbuf* pixbuf) -{ - UnRef(); - - if (!pixbuf) - return; - - int depth = -1; - if (gdk_pixbuf_get_has_alpha(pixbuf)) - depth = 32; - m_refData = new wxBitmapRefData( - gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf), depth); - - M_BMPDATA->m_pixbuf = pixbuf; -} - void wxBitmap::PurgeOtherRepresentations(wxBitmap::Representation keep) { if (keep == Pixmap && HasPixbuf()) @@ -842,7 +864,9 @@ wxGDIRefData* wxBitmap::CreateGDIRefData() const wxGDIRefData* wxBitmap::CloneGDIRefData(const wxGDIRefData* data) const { const wxBitmapRefData* oldRef = static_cast(data); - wxBitmapRefData* newRef = new wxBitmapRefData(*oldRef); + wxBitmapRefData * const newRef = new wxBitmapRefData(oldRef->m_width, + oldRef->m_height, + oldRef->m_bpp); if (oldRef->m_pixmap != NULL) { newRef->m_pixmap = gdk_pixmap_new( @@ -859,12 +883,7 @@ wxGDIRefData* wxBitmap::CloneGDIRefData(const wxGDIRefData* data) const } if (oldRef->m_mask != NULL) { - newRef->m_mask = new wxMask; - newRef->m_mask->m_bitmap = gdk_pixmap_new( - oldRef->m_mask->m_bitmap, oldRef->m_width, oldRef->m_height, 1); - wxGtkObject gc(gdk_gc_new(newRef->m_mask->m_bitmap)); - gdk_draw_drawable(newRef->m_mask->m_bitmap, - gc, oldRef->m_mask->m_bitmap, 0, 0, 0, 0, -1, -1); + newRef->m_mask = new wxMask(*oldRef->m_mask); } return newRef;