+static void PixmapToPixbuf(GdkPixmap* pixmap, GdkPixbuf* pixbuf, int w, int h)
+{
+    gdk_pixbuf_get_from_drawable(pixbuf, pixmap, NULL, 0, 0, 0, 0, w, h);
+    if (gdk_drawable_get_depth(pixmap) == 1)
+    {
+        // invert to match XBM convention
+        guchar* p = gdk_pixbuf_get_pixels(pixbuf);
+        const int inc = 3 + int(gdk_pixbuf_get_has_alpha(pixbuf) != 0);
+        const int rowpad = gdk_pixbuf_get_rowstride(pixbuf) - w * inc;
+        for (int y = h; y; y--, p += rowpad)
+            for (int x = w; x; x--, p += inc)
+            {
+                // pixels are either (0,0,0) or (0xff,0xff,0xff)
+                p[0] = ~p[0];
+                p[1] = ~p[1];
+                p[2] = ~p[2];
+            }
+    }
+}
+
+static void MaskToAlpha(GdkPixmap* mask, GdkPixbuf* pixbuf, int w, int h)
+{
+    GdkPixbuf* mask_pixbuf = gdk_pixbuf_get_from_drawable(
+        NULL, mask, NULL, 0, 0, 0, 0, w, h);
+    guchar* p = gdk_pixbuf_get_pixels(pixbuf) + 3;
+    const guchar* mask_data = gdk_pixbuf_get_pixels(mask_pixbuf);
+    const int rowpad = gdk_pixbuf_get_rowstride(pixbuf) - w * 4;
+    const int mask_rowpad = gdk_pixbuf_get_rowstride(mask_pixbuf) - w * 3;
+    for (int y = h; y; y--, p += rowpad, mask_data += mask_rowpad)
+    {
+        for (int x = w; x; x--, p += 4, mask_data += 3)
+        {
+            *p = 255;
+            // no need to test all 3 components,
+            //   pixels are either (0,0,0) or (0xff,0xff,0xff)
+            if (mask_data[0] == 0)
+                *p = 0;
+        }
+    }
+    g_object_unref(mask_pixbuf);
+}
+