+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;
+#ifdef __WXGTK3__
+ bmpData->m_pixbufNoMask = pixbuf;
+#else
+ bmpData->m_pixbuf = pixbuf;
+#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)
+{
+ wxCHECK_RET(image.IsOk(), "invalid image");
+
+ if (depth == 32 || (depth == -1 && image.HasAlpha()))
+ CreateFromImageAsPixbuf(image);
+ else
+ // otherwise create pixmap, if alpha is present it will be converted to mask
+ CreateFromImageAsPixmap(image, depth);
+}
+
+bool wxBitmap::CreateFromImageAsPixmap(const wxImage& image, int depth)
+{
+ const int w = image.GetWidth();
+ const int h = image.GetHeight();