+/* Thin wrapper for x_create_x_image_and_pixmap, so that it matches
+ with image_put_x_image. */
+
+static bool
+image_create_x_image_and_pixmap (struct frame *f, struct image *img,
+ int width, int height, int depth,
+ XImagePtr *ximg, bool mask_p)
+{
+ eassert ((!mask_p ? img->pixmap : img->mask) == NO_PIXMAP);
+
+ return x_create_x_image_and_pixmap (f, width, height, depth, ximg,
+ !mask_p ? &img->pixmap : &img->mask);
+}
+
+/* Put X image XIMG into image IMG on frame F, as a mask if and only
+ if MASK_P. On X, this simply records XIMG on a member of IMG, so
+ it can be put into the pixmap afterwards via image_sync_to_pixmaps.
+ On the other platforms, it puts XIMG into the pixmap, then frees
+ the X image and its buffer. */
+
+static void
+image_put_x_image (struct frame *f, struct image *img, XImagePtr ximg,
+ bool mask_p)
+{
+#ifdef HAVE_X_WINDOWS
+ if (!mask_p)
+ {
+ eassert (img->ximg == NULL);
+ img->ximg = ximg;
+ }
+ else
+ {
+ eassert (img->mask_img == NULL);
+ img->mask_img = ximg;
+ }
+#else
+ x_put_x_image (f, ximg, !mask_p ? img->pixmap : img->mask,
+ img->width, img->height);
+ x_destroy_x_image (ximg);
+#endif
+}
+
+#ifdef HAVE_X_WINDOWS
+/* Put the X images recorded in IMG on frame F into pixmaps, then free
+ the X images and their buffers. */
+
+static void
+image_sync_to_pixmaps (struct frame *f, struct image *img)
+{
+ if (img->ximg)
+ {
+ x_put_x_image (f, img->ximg, img->pixmap, img->width, img->height);
+ x_destroy_x_image (img->ximg);
+ img->ximg = NULL;
+ }
+ if (img->mask_img)
+ {
+ x_put_x_image (f, img->mask_img, img->mask, img->width, img->height);
+ x_destroy_x_image (img->mask_img);
+ img->mask_img = NULL;
+ }
+}
+#endif
+
+#ifdef HAVE_NTGUI
+/* Create a memory device context for IMG on frame F. It stores the
+ currently selected GDI object into *PREV for future restoration by
+ image_unget_x_image_or_dc. */
+
+static XImagePtr_or_DC
+image_get_x_image_or_dc (struct frame *f, struct image *img, bool mask_p,
+ HGDIOBJ *prev)
+{
+ HDC frame_dc = get_frame_dc (f);
+ XImagePtr_or_DC ximg = CreateCompatibleDC (frame_dc);
+
+ release_frame_dc (f, frame_dc);
+ *prev = SelectObject (ximg, !mask_p ? img->pixmap : img->mask);
+
+ return ximg;
+}
+
+static void
+image_unget_x_image_or_dc (struct image *img, bool mask_p,
+ XImagePtr_or_DC ximg, HGDIOBJ prev)
+{
+ SelectObject (ximg, prev);
+ DeleteDC (ximg);
+}
+#else /* !HAVE_NTGUI */
+/* Get the X image for IMG on frame F. The resulting X image data
+ should be treated as read-only at least on X. */
+
+static XImagePtr
+image_get_x_image (struct frame *f, struct image *img, bool mask_p)
+{
+#ifdef HAVE_X_WINDOWS
+ XImagePtr ximg_in_img = !mask_p ? img->ximg : img->mask_img;
+
+ if (ximg_in_img)
+ return ximg_in_img;
+ else
+ return XGetImage (FRAME_X_DISPLAY (f), !mask_p ? img->pixmap : img->mask,
+ 0, 0, img->width, img->height, ~0, ZPixmap);
+#elif defined (HAVE_NS)
+ XImagePtr pixmap = !mask_p ? img->pixmap : img->mask;
+
+ ns_retain_object (pixmap);
+ return pixmap;
+#endif
+}
+
+static void
+image_unget_x_image (struct image *img, bool mask_p, XImagePtr ximg)
+{
+#ifdef HAVE_X_WINDOWS
+ XImagePtr ximg_in_img = !mask_p ? img->ximg : img->mask_img;
+
+ if (ximg_in_img)
+ eassert (ximg == ximg_in_img);
+ else
+ XDestroyImage (ximg);
+#elif defined (HAVE_NS)
+ ns_release_object (ximg);
+#endif
+}
+#endif /* !HAVE_NTGUI */
+