+
+wxBitmap::wxBitmap(const char bits[], int width, int height, int depth)
+{
+ wxASSERT(depth == 1);
+ if (width > 0 && height > 0 && depth == 1)
+ {
+ m_refData = new wxBitmapRefData(width, height, 1);
+#ifdef __WXGTK3__
+ GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, false, 8, width, height);
+ M_BMPDATA->m_pixbufNoMask = pixbuf;
+ const char* src = bits;
+ guchar* dst = gdk_pixbuf_get_pixels(pixbuf);
+ const int stride_src = (width + 7) / 8;
+ const int rowinc_dst = gdk_pixbuf_get_rowstride(pixbuf) - 3 * width;
+ for (int j = 0; j < width; j++, src += stride_src, dst += rowinc_dst)
+ {
+ for (int i = 0; i < height; i++)
+ {
+ guchar c = 0xff;
+ if (src[i >> 3] & (1 << (i & 7)))
+ c = 0;
+ *dst++ = c;
+ *dst++ = c;
+ *dst++ = c;
+ }
+ }
+#else
+ M_BMPDATA->m_pixmap = gdk_bitmap_create_from_data(
+ wxGetRootWindow()->window, bits, width, height);
+#endif
+ }
+}
+
+wxBitmap::wxBitmap(const char* const* bits)
+{
+ wxCHECK2_MSG(bits != NULL, return, wxT("invalid bitmap data"));
+
+#if wxUSE_IMAGE
+ *this = wxBitmap(wxImage(bits));
+#elif defined __WXGTK3__
+ GdkPixbuf* pixbuf = gdk_pixbuf_new_from_xpm_data(const_cast<const char**>(bits));
+ if (pixbuf)
+ {
+ m_refData = new wxBitmapRefData(
+ gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf),
+ gdk_pixbuf_get_n_channels(pixbuf) * 8);
+ M_BMPDATA->m_pixbufNoMask = pixbuf;
+ wxASSERT(M_BMPDATA->m_bpp == 32 || !gdk_pixbuf_get_has_alpha(M_BMPDATA->m_pixbufNoMask));
+ }
+#else
+ GdkBitmap* mask = NULL;
+ GdkPixmap* pixmap = gdk_pixmap_create_from_xpm_d(wxGetRootWindow()->window, &mask, NULL, const_cast<char**>(bits));
+ if (pixmap)
+ {
+ int width, height;
+ gdk_drawable_get_size(pixmap, &width, &height);
+ m_refData = new wxBitmapRefData(width, height, -1);
+ M_BMPDATA->m_pixmap = pixmap;
+ if (mask)
+ {
+ M_BMPDATA->m_mask = new wxMask(mask);
+ }
+ }
+#endif
+}
+
+wxBitmap::wxBitmap(GdkPixbuf* pixbuf, int depth)
+{
+ if (pixbuf)
+ {
+ if (depth != 1)
+ depth = gdk_pixbuf_get_n_channels(pixbuf) * 8;
+ wxBitmapRefData* bmpData = new wxBitmapRefData(
+ gdk_pixbuf_get_width(pixbuf), gdk_pixbuf_get_height(pixbuf),
+ depth);
+ m_refData = bmpData;
+#ifdef __WXGTK3__
+ bmpData->m_pixbufNoMask = pixbuf;
+#else
+ bmpData->m_pixbuf = pixbuf;
+#endif
+ }
+}
+
+#ifndef __WXGTK3__
+wxBitmap::wxBitmap(GdkPixmap* pixmap)
+{
+ if (pixmap)
+ {
+ int w, h;
+ gdk_drawable_get_size(pixmap, &w, &h);
+ wxBitmapRefData* bmpData =
+ new wxBitmapRefData(w, h, gdk_drawable_get_depth(pixmap));
+ m_refData = bmpData;
+ bmpData->m_pixmap = pixmap;
+ }
+}
+#endif
+
+wxBitmap::~wxBitmap()
+{
+}
+
+bool wxBitmap::Create( int width, int height, int depth )
+{
+ UnRef();
+ wxCHECK_MSG(width >= 0 && height >= 0, false, "invalid bitmap size");
+ m_refData = new wxBitmapRefData(width, height, depth);
+ return true;
+}
+
+#ifdef __WXGTK3__
+static void CopyImageData(
+ guchar* dst, int dstChannels, int dstStride,
+ const guchar* src, int srcChannels, int srcStride,
+ int w, int h)
+{
+ if (dstChannels == srcChannels)
+ {
+ if (dstStride == srcStride)
+ memcpy(dst, src, size_t(dstStride) * h);
+ else
+ {
+ const int stride = dstStride < srcStride ? dstStride : srcStride;
+ for (int j = 0; j < h; j++, src += srcStride, dst += dstStride)
+ memcpy(dst, src, stride);
+ }
+ }
+ else
+ {
+ for (int j = 0; j < h; j++, src += srcStride, dst += dstStride)
+ {
+ guchar* d = dst;
+ const guchar* s = src;
+ if (dstChannels == 4)
+ {
+ for (int i = 0; i < w; i++, d += 4, s += 3)
+ {
+ d[0] = s[0];
+ d[1] = s[1];
+ d[2] = s[2];
+ d[3] = 0xff;
+ }
+ }
+ else
+ {
+ for (int i = 0; i < w; i++, d += 3, s += 4)
+ {
+ d[0] = s[0];
+ d[1] = s[1];
+ d[2] = s[2];
+ }
+ }
+ }
+ }
+}
+#endif
+
+#if wxUSE_IMAGE
+#ifdef __WXGTK3__
+wxBitmap::wxBitmap(const wxImage& image, int depth)
+{
+ wxCHECK_RET(image.IsOk(), "invalid image");
+
+ const int w = image.GetWidth();
+ const int h = image.GetHeight();
+ const guchar* alpha = image.GetAlpha();
+ if (depth < 0)
+ depth = alpha ? 32 : 24;
+ else if (depth != 1 && depth != 32)
+ depth = 24;
+ wxBitmapRefData* bmpData = new wxBitmapRefData(w, h, depth);
+ m_refData = bmpData;
+ GdkPixbuf* pixbuf_dst = gdk_pixbuf_new(GDK_COLORSPACE_RGB, depth == 32, 8, w, h);
+ bmpData->m_pixbufNoMask = pixbuf_dst;
+ wxASSERT(bmpData->m_bpp == 32 || !gdk_pixbuf_get_has_alpha(bmpData->m_pixbufNoMask));
+ const guchar* src = image.GetData();
+
+ guchar* dst = gdk_pixbuf_get_pixels(pixbuf_dst);
+ const int dstStride = gdk_pixbuf_get_rowstride(pixbuf_dst);
+ CopyImageData(dst, gdk_pixbuf_get_n_channels(pixbuf_dst), dstStride, src, 3, 3 * w, w, h);
+
+ if (depth == 32 && alpha)
+ {
+ for (int j = 0; j < h; j++, dst += dstStride)
+ for (int i = 0; i < w; i++)
+ dst[i * 4 + 3] = *alpha++;
+ }
+ if (image.HasMask())
+ {
+ const guchar r = image.GetMaskRed();
+ const guchar g = image.GetMaskGreen();
+ const guchar b = image.GetMaskBlue();
+ cairo_surface_t* surface = cairo_image_surface_create(CAIRO_FORMAT_A8, w, h);
+ const int stride = cairo_image_surface_get_stride(surface);
+ dst = cairo_image_surface_get_data(surface);
+ memset(dst, 0xff, stride * h);
+ for (int j = 0; j < h; j++, dst += stride)
+ for (int i = 0; i < w; i++, src += 3)
+ if (src[0] == r && src[1] == g && src[2] == b)
+ dst[i] = 0;
+ cairo_surface_mark_dirty(surface);
+ bmpData->m_mask = new wxMask(surface);
+ }
+}
+#else
+wxBitmap::wxBitmap(const wxImage& image, int depth)