aboutsummaryrefslogtreecommitdiffstats
path: root/src/image.c
diff options
context:
space:
mode:
authorTom Tromey2013-07-06 23:18:58 -0600
committerTom Tromey2013-07-06 23:18:58 -0600
commit6dacdad5fcb278e5a16b38bb81786aac9ca27be4 (patch)
treef5f331ea361ba0f99e0f9b638d183ad492a7da31 /src/image.c
parent0a6f2ff0c8ceb29703e76cddd46ea3f176dd873a (diff)
parent219afb88d9d484393418820d1c08dc93299110ec (diff)
downloademacs-6dacdad5fcb278e5a16b38bb81786aac9ca27be4.tar.gz
emacs-6dacdad5fcb278e5a16b38bb81786aac9ca27be4.zip
merge from trunk
this merges frmo trunk and fixes various build issues. this needed a few ugly tweaks. this hangs in "make check" now
Diffstat (limited to 'src/image.c')
-rw-r--r--src/image.c596
1 files changed, 405 insertions, 191 deletions
diff --git a/src/image.c b/src/image.c
index f9f6ce70040..7ecd59d27b4 100644
--- a/src/image.c
+++ b/src/image.c
@@ -18,7 +18,7 @@ You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ 18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19 19
20#include <config.h> 20#include <config.h>
21#include <stdio.h> 21#include "sysstdio.h"
22#include <unistd.h> 22#include <unistd.h>
23 23
24#ifdef HAVE_PNG 24#ifdef HAVE_PNG
@@ -106,8 +106,6 @@ typedef struct ns_bitmap_record Bitmap_Record;
106#define GET_PIXEL(ximg, x, y) XGetPixel (ximg, x, y) 106#define GET_PIXEL(ximg, x, y) XGetPixel (ximg, x, y)
107#define NO_PIXMAP 0 107#define NO_PIXMAP 0
108 108
109#define ZPixmap 0
110
111#define PIX_MASK_RETAIN 0 109#define PIX_MASK_RETAIN 0
112#define PIX_MASK_DRAW 1 110#define PIX_MASK_DRAW 1
113 111
@@ -132,6 +130,8 @@ static void free_color_table (void);
132static unsigned long *colors_in_color_table (int *n); 130static unsigned long *colors_in_color_table (int *n);
133#endif 131#endif
134 132
133static Lisp_Object QCmax_width, QCmax_height;
134
135/* Code to deal with bitmaps. Bitmaps are referenced by their bitmap 135/* Code to deal with bitmaps. Bitmaps are referenced by their bitmap
136 id, which is just an int that this section returns. Bitmaps are 136 id, which is just an int that this section returns. Bitmaps are
137 reference counted so they can be shared among frames. 137 reference counted so they can be shared among frames.
@@ -144,16 +144,6 @@ static unsigned long *colors_in_color_table (int *n);
144 data more than once will not be caught. */ 144 data more than once will not be caught. */
145 145
146#ifdef HAVE_NS 146#ifdef HAVE_NS
147XImagePtr
148XGetImage (Display *display, Pixmap pixmap, int x, int y,
149 unsigned int width, unsigned int height,
150 unsigned long plane_mask, int format)
151{
152 /* TODO: not sure what this function is supposed to do.. */
153 ns_retain_object (pixmap);
154 return pixmap;
155}
156
157/* Use with images created by ns_image_for_XPM. */ 147/* Use with images created by ns_image_for_XPM. */
158unsigned long 148unsigned long
159XGetPixel (XImagePtr ximage, int x, int y) 149XGetPixel (XImagePtr ximage, int x, int y)
@@ -433,8 +423,24 @@ static bool x_create_x_image_and_pixmap (struct frame *, int, int, int,
433 XImagePtr *, Pixmap *); 423 XImagePtr *, Pixmap *);
434static void x_destroy_x_image (XImagePtr ximg); 424static void x_destroy_x_image (XImagePtr ximg);
435 425
426#ifdef HAVE_NTGUI
427static XImagePtr_or_DC image_get_x_image_or_dc (struct frame *, struct image *,
428 bool, HGDIOBJ *);
429static void image_unget_x_image_or_dc (struct image *, bool, XImagePtr_or_DC,
430 HGDIOBJ);
431#else
432static XImagePtr image_get_x_image (struct frame *, struct image *, bool);
433static void image_unget_x_image (struct image *, bool, XImagePtr);
434#define image_get_x_image_or_dc(f, img, mask_p, dummy) \
435 image_get_x_image (f, img, mask_p)
436#define image_unget_x_image_or_dc(img, mask_p, ximg, dummy) \
437 image_unget_x_image (img, mask_p, ximg)
438#endif
439
436#ifdef HAVE_X_WINDOWS 440#ifdef HAVE_X_WINDOWS
437 441
442static void image_sync_to_pixmaps (struct frame *, struct image *);
443
438/* Useful functions defined in the section 444/* Useful functions defined in the section
439 `Image type independent image structures' below. */ 445 `Image type independent image structures' below. */
440 446
@@ -1048,6 +1054,14 @@ prepare_image_for_display (struct frame *f, struct image *img)
1048 if (img->pixmap == NO_PIXMAP && !img->load_failed_p) 1054 if (img->pixmap == NO_PIXMAP && !img->load_failed_p)
1049 img->load_failed_p = ! img->type->load (f, img); 1055 img->load_failed_p = ! img->type->load (f, img);
1050 1056
1057#ifdef HAVE_X_WINDOWS
1058 if (!img->load_failed_p)
1059 {
1060 block_input ();
1061 image_sync_to_pixmaps (f, img);
1062 unblock_input ();
1063 }
1064#endif
1051} 1065}
1052 1066
1053 1067
@@ -1143,25 +1157,16 @@ four_corners_best (XImagePtr_or_DC ximg, int *corners,
1143 1157
1144#ifdef HAVE_NTGUI 1158#ifdef HAVE_NTGUI
1145 1159
1146#define Destroy_Image(img_dc, prev) \
1147 do { SelectObject (img_dc, prev); DeleteDC (img_dc); } while (0)
1148
1149#define Free_Pixmap(display, pixmap) \ 1160#define Free_Pixmap(display, pixmap) \
1150 DeleteObject (pixmap) 1161 DeleteObject (pixmap)
1151 1162
1152#elif defined (HAVE_NS) 1163#elif defined (HAVE_NS)
1153 1164
1154#define Destroy_Image(ximg, dummy) \
1155 ns_release_object (ximg)
1156
1157#define Free_Pixmap(display, pixmap) \ 1165#define Free_Pixmap(display, pixmap) \
1158 ns_release_object (pixmap) 1166 ns_release_object (pixmap)
1159 1167
1160#else 1168#else
1161 1169
1162#define Destroy_Image(ximg, dummy) \
1163 XDestroyImage (ximg)
1164
1165#define Free_Pixmap(display, pixmap) \ 1170#define Free_Pixmap(display, pixmap) \
1166 XFreePixmap (display, pixmap) 1171 XFreePixmap (display, pixmap)
1167 1172
@@ -1185,22 +1190,12 @@ image_background (struct image *img, struct frame *f, XImagePtr_or_DC ximg)
1185#endif /* HAVE_NTGUI */ 1190#endif /* HAVE_NTGUI */
1186 1191
1187 if (free_ximg) 1192 if (free_ximg)
1188 { 1193 ximg = image_get_x_image_or_dc (f, img, 0, &prev);
1189#ifndef HAVE_NTGUI
1190 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
1191 0, 0, img->width, img->height, ~0, ZPixmap);
1192#else
1193 HDC frame_dc = get_frame_dc (f);
1194 ximg = CreateCompatibleDC (frame_dc);
1195 release_frame_dc (f, frame_dc);
1196 prev = SelectObject (ximg, img->pixmap);
1197#endif /* !HAVE_NTGUI */
1198 }
1199 1194
1200 img->background = four_corners_best (ximg, img->corners, img->width, img->height); 1195 img->background = four_corners_best (ximg, img->corners, img->width, img->height);
1201 1196
1202 if (free_ximg) 1197 if (free_ximg)
1203 Destroy_Image (ximg, prev); 1198 image_unget_x_image_or_dc (img, 0, ximg, prev);
1204 1199
1205 img->background_valid = 1; 1200 img->background_valid = 1;
1206 } 1201 }
@@ -1226,23 +1221,13 @@ image_background_transparent (struct image *img, struct frame *f, XImagePtr_or_D
1226#endif /* HAVE_NTGUI */ 1221#endif /* HAVE_NTGUI */
1227 1222
1228 if (free_mask) 1223 if (free_mask)
1229 { 1224 mask = image_get_x_image_or_dc (f, img, 1, &prev);
1230#ifndef HAVE_NTGUI
1231 mask = XGetImage (FRAME_X_DISPLAY (f), img->mask,
1232 0, 0, img->width, img->height, ~0, ZPixmap);
1233#else
1234 HDC frame_dc = get_frame_dc (f);
1235 mask = CreateCompatibleDC (frame_dc);
1236 release_frame_dc (f, frame_dc);
1237 prev = SelectObject (mask, img->mask);
1238#endif /* HAVE_NTGUI */
1239 }
1240 1225
1241 img->background_transparent 1226 img->background_transparent
1242 = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN); 1227 = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN);
1243 1228
1244 if (free_mask) 1229 if (free_mask)
1245 Destroy_Image (mask, prev); 1230 image_unget_x_image_or_dc (img, 1, mask, prev);
1246 } 1231 }
1247 else 1232 else
1248 img->background_transparent = 0; 1233 img->background_transparent = 0;
@@ -1258,30 +1243,58 @@ image_background_transparent (struct image *img, struct frame *f, XImagePtr_or_D
1258 Helper functions for X image types 1243 Helper functions for X image types
1259 ***********************************************************************/ 1244 ***********************************************************************/
1260 1245
1261/* Clear X resources of image IMG on frame F. PIXMAP_P means free the 1246/* Clear X resources of image IMG on frame F according to FLAGS.
1262 pixmap if any. MASK_P means clear the mask pixmap if any. 1247 FLAGS is bitwise-or of the following masks:
1263 COLORS_P means free colors allocated for the image, if any. */ 1248 CLEAR_IMAGE_PIXMAP free the pixmap if any.
1249 CLEAR_IMAGE_MASK means clear the mask pixmap if any.
1250 CLEAR_IMAGE_COLORS means free colors allocated for the image, if
1251 any. */
1252
1253#define CLEAR_IMAGE_PIXMAP (1 << 0)
1254#define CLEAR_IMAGE_MASK (1 << 1)
1255#define CLEAR_IMAGE_COLORS (1 << 2)
1264 1256
1265static void 1257static void
1266x_clear_image_1 (struct frame *f, struct image *img, bool pixmap_p, 1258x_clear_image_1 (struct frame *f, struct image *img, int flags)
1267 bool mask_p, bool colors_p)
1268{ 1259{
1269 if (pixmap_p && img->pixmap) 1260 if (flags & CLEAR_IMAGE_PIXMAP)
1270 { 1261 {
1271 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap); 1262 if (img->pixmap)
1272 img->pixmap = NO_PIXMAP; 1263 {
1273 /* NOTE (HAVE_NS): background color is NOT an indexed color! */ 1264 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
1274 img->background_valid = 0; 1265 img->pixmap = NO_PIXMAP;
1266 /* NOTE (HAVE_NS): background color is NOT an indexed color! */
1267 img->background_valid = 0;
1268 }
1269#ifdef HAVE_X_WINDOWS
1270 if (img->ximg)
1271 {
1272 x_destroy_x_image (img->ximg);
1273 img->ximg = NULL;
1274 img->background_valid = 0;
1275 }
1276#endif
1275 } 1277 }
1276 1278
1277 if (mask_p && img->mask) 1279 if (flags & CLEAR_IMAGE_MASK)
1278 { 1280 {
1279 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask); 1281 if (img->mask)
1280 img->mask = NO_PIXMAP; 1282 {
1281 img->background_transparent_valid = 0; 1283 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1284 img->mask = NO_PIXMAP;
1285 img->background_transparent_valid = 0;
1286 }
1287#ifdef HAVE_X_WINDOWS
1288 if (img->mask_img)
1289 {
1290 x_destroy_x_image (img->mask_img);
1291 img->mask_img = NULL;
1292 img->background_transparent_valid = 0;
1293 }
1294#endif
1282 } 1295 }
1283 1296
1284 if (colors_p && img->ncolors) 1297 if ((flags & CLEAR_IMAGE_COLORS) && img->ncolors)
1285 { 1298 {
1286 /* W32_TODO: color table support. */ 1299 /* W32_TODO: color table support. */
1287#ifdef HAVE_X_WINDOWS 1300#ifdef HAVE_X_WINDOWS
@@ -1300,7 +1313,8 @@ static void
1300x_clear_image (struct frame *f, struct image *img) 1313x_clear_image (struct frame *f, struct image *img)
1301{ 1314{
1302 block_input (); 1315 block_input ();
1303 x_clear_image_1 (f, img, 1, 1, 1); 1316 x_clear_image_1 (f, img,
1317 CLEAR_IMAGE_PIXMAP | CLEAR_IMAGE_MASK | CLEAR_IMAGE_COLORS);
1304 unblock_input (); 1318 unblock_input ();
1305} 1319}
1306 1320
@@ -1631,10 +1645,7 @@ postprocess_image (struct frame *f, struct image *img)
1631 x_build_heuristic_mask (f, img, XCDR (mask)); 1645 x_build_heuristic_mask (f, img, XCDR (mask));
1632 } 1646 }
1633 else if (NILP (mask) && found_p && img->mask) 1647 else if (NILP (mask) && found_p && img->mask)
1634 { 1648 x_clear_image_1 (f, img, CLEAR_IMAGE_MASK);
1635 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
1636 img->mask = NO_PIXMAP;
1637 }
1638 } 1649 }
1639 1650
1640 1651
@@ -2092,6 +2103,134 @@ x_put_x_image (struct frame *f, XImagePtr ximg, Pixmap pixmap, int width, int he
2092#endif 2103#endif
2093} 2104}
2094 2105
2106/* Thin wrapper for x_create_x_image_and_pixmap, so that it matches
2107 with image_put_x_image. */
2108
2109static bool
2110image_create_x_image_and_pixmap (struct frame *f, struct image *img,
2111 int width, int height, int depth,
2112 XImagePtr *ximg, bool mask_p)
2113{
2114 eassert ((!mask_p ? img->pixmap : img->mask) == NO_PIXMAP);
2115
2116 return x_create_x_image_and_pixmap (f, width, height, depth, ximg,
2117 !mask_p ? &img->pixmap : &img->mask);
2118}
2119
2120/* Put X image XIMG into image IMG on frame F, as a mask if and only
2121 if MASK_P. On X, this simply records XIMG on a member of IMG, so
2122 it can be put into the pixmap afterwards via image_sync_to_pixmaps.
2123 On the other platforms, it puts XIMG into the pixmap, then frees
2124 the X image and its buffer. */
2125
2126static void
2127image_put_x_image (struct frame *f, struct image *img, XImagePtr ximg,
2128 bool mask_p)
2129{
2130#ifdef HAVE_X_WINDOWS
2131 if (!mask_p)
2132 {
2133 eassert (img->ximg == NULL);
2134 img->ximg = ximg;
2135 }
2136 else
2137 {
2138 eassert (img->mask_img == NULL);
2139 img->mask_img = ximg;
2140 }
2141#else
2142 x_put_x_image (f, ximg, !mask_p ? img->pixmap : img->mask,
2143 img->width, img->height);
2144 x_destroy_x_image (ximg);
2145#endif
2146}
2147
2148#ifdef HAVE_X_WINDOWS
2149/* Put the X images recorded in IMG on frame F into pixmaps, then free
2150 the X images and their buffers. */
2151
2152static void
2153image_sync_to_pixmaps (struct frame *f, struct image *img)
2154{
2155 if (img->ximg)
2156 {
2157 x_put_x_image (f, img->ximg, img->pixmap, img->width, img->height);
2158 x_destroy_x_image (img->ximg);
2159 img->ximg = NULL;
2160 }
2161 if (img->mask_img)
2162 {
2163 x_put_x_image (f, img->mask_img, img->mask, img->width, img->height);
2164 x_destroy_x_image (img->mask_img);
2165 img->mask_img = NULL;
2166 }
2167}
2168#endif
2169
2170#ifdef HAVE_NTGUI
2171/* Create a memory device context for IMG on frame F. It stores the
2172 currently selected GDI object into *PREV for future restoration by
2173 image_unget_x_image_or_dc. */
2174
2175static XImagePtr_or_DC
2176image_get_x_image_or_dc (struct frame *f, struct image *img, bool mask_p,
2177 HGDIOBJ *prev)
2178{
2179 HDC frame_dc = get_frame_dc (f);
2180 XImagePtr_or_DC ximg = CreateCompatibleDC (frame_dc);
2181
2182 release_frame_dc (f, frame_dc);
2183 *prev = SelectObject (ximg, !mask_p ? img->pixmap : img->mask);
2184
2185 return ximg;
2186}
2187
2188static void
2189image_unget_x_image_or_dc (struct image *img, bool mask_p,
2190 XImagePtr_or_DC ximg, HGDIOBJ prev)
2191{
2192 SelectObject (ximg, prev);
2193 DeleteDC (ximg);
2194}
2195#else /* !HAVE_NTGUI */
2196/* Get the X image for IMG on frame F. The resulting X image data
2197 should be treated as read-only at least on X. */
2198
2199static XImagePtr
2200image_get_x_image (struct frame *f, struct image *img, bool mask_p)
2201{
2202#ifdef HAVE_X_WINDOWS
2203 XImagePtr ximg_in_img = !mask_p ? img->ximg : img->mask_img;
2204
2205 if (ximg_in_img)
2206 return ximg_in_img;
2207 else
2208 return XGetImage (FRAME_X_DISPLAY (f), !mask_p ? img->pixmap : img->mask,
2209 0, 0, img->width, img->height, ~0, ZPixmap);
2210#elif defined (HAVE_NS)
2211 XImagePtr pixmap = !mask_p ? img->pixmap : img->mask;
2212
2213 ns_retain_object (pixmap);
2214 return pixmap;
2215#endif
2216}
2217
2218static void
2219image_unget_x_image (struct image *img, bool mask_p, XImagePtr ximg)
2220{
2221#ifdef HAVE_X_WINDOWS
2222 XImagePtr ximg_in_img = !mask_p ? img->ximg : img->mask_img;
2223
2224 if (ximg_in_img)
2225 eassert (ximg == ximg_in_img);
2226 else
2227 XDestroyImage (ximg);
2228#elif defined (HAVE_NS)
2229 ns_release_object (ximg);
2230#endif
2231}
2232#endif /* !HAVE_NTGUI */
2233
2095 2234
2096/*********************************************************************** 2235/***********************************************************************
2097 File Handling 2236 File Handling
@@ -2135,7 +2274,7 @@ x_find_image_file (Lisp_Object file)
2135static unsigned char * 2274static unsigned char *
2136slurp_file (char *file, ptrdiff_t *size) 2275slurp_file (char *file, ptrdiff_t *size)
2137{ 2276{
2138 FILE *fp = fopen (file, "rb"); 2277 FILE *fp = emacs_fopen (file, "rb");
2139 unsigned char *buf = NULL; 2278 unsigned char *buf = NULL;
2140 struct stat st; 2279 struct stat st;
2141 2280
@@ -3057,7 +3196,7 @@ struct xpm_cached_color
3057 XColor color; 3196 XColor color;
3058 3197
3059 /* Color name. */ 3198 /* Color name. */
3060 char name[1]; 3199 char name[FLEXIBLE_ARRAY_MEMBER];
3061}; 3200};
3062 3201
3063/* The hash table used for the color cache, and its bucket vector 3202/* The hash table used for the color cache, and its bucket vector
@@ -3459,9 +3598,9 @@ xpm_load (struct frame *f, struct image *img)
3459 &xpm_image, &xpm_mask, 3598 &xpm_image, &xpm_mask,
3460 &attrs); 3599 &attrs);
3461#else 3600#else
3462 rc = XpmReadFileToPixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 3601 rc = XpmReadFileToImage (FRAME_X_DISPLAY (f), SSDATA (file),
3463 SSDATA (file), &img->pixmap, &img->mask, 3602 &img->ximg, &img->mask_img,
3464 &attrs); 3603 &attrs);
3465#endif /* HAVE_NTGUI */ 3604#endif /* HAVE_NTGUI */
3466 } 3605 }
3467 else 3606 else
@@ -3482,13 +3621,38 @@ xpm_load (struct frame *f, struct image *img)
3482 &xpm_image, &xpm_mask, 3621 &xpm_image, &xpm_mask,
3483 &attrs); 3622 &attrs);
3484#else 3623#else
3485 rc = XpmCreatePixmapFromBuffer (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 3624 rc = XpmCreateImageFromBuffer (FRAME_X_DISPLAY (f), SSDATA (buffer),
3486 SSDATA (buffer), 3625 &img->ximg, &img->mask_img,
3487 &img->pixmap, &img->mask, 3626 &attrs);
3488 &attrs);
3489#endif /* HAVE_NTGUI */ 3627#endif /* HAVE_NTGUI */
3490 } 3628 }
3491 3629
3630#ifdef HAVE_X_WINDOWS
3631 if (rc == XpmSuccess)
3632 {
3633 img->pixmap = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3634 img->ximg->width, img->ximg->height,
3635 img->ximg->depth);
3636 if (img->pixmap == NO_PIXMAP)
3637 {
3638 x_clear_image (f, img);
3639 rc = XpmNoMemory;
3640 }
3641 else if (img->mask_img)
3642 {
3643 img->mask = XCreatePixmap (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
3644 img->mask_img->width,
3645 img->mask_img->height,
3646 img->mask_img->depth);
3647 if (img->mask == NO_PIXMAP)
3648 {
3649 x_clear_image (f, img);
3650 rc = XpmNoMemory;
3651 }
3652 }
3653 }
3654#endif
3655
3492 if (rc == XpmSuccess) 3656 if (rc == XpmSuccess)
3493 { 3657 {
3494#if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS) 3658#if defined (COLOR_TABLE_SUPPORT) && defined (ALLOC_XPM_COLORS)
@@ -3547,6 +3711,15 @@ xpm_load (struct frame *f, struct image *img)
3547#else 3711#else
3548 XpmFreeAttributes (&attrs); 3712 XpmFreeAttributes (&attrs);
3549#endif /* HAVE_NTGUI */ 3713#endif /* HAVE_NTGUI */
3714
3715#ifdef HAVE_X_WINDOWS
3716 /* Maybe fill in the background field while we have ximg handy. */
3717 IMAGE_BACKGROUND (img, f, img->ximg);
3718 if (img->mask_img)
3719 /* Fill in the background_transparent field while we have the
3720 mask handy. */
3721 image_background_transparent (img, f, img->mask_img);
3722#endif
3550 } 3723 }
3551 else 3724 else
3552 { 3725 {
@@ -3845,11 +4018,10 @@ xpm_load_image (struct frame *f,
3845 goto failure; 4018 goto failure;
3846 } 4019 }
3847 4020
3848 if (!x_create_x_image_and_pixmap (f, width, height, 0, 4021 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)
3849 &ximg, &img->pixmap)
3850#ifndef HAVE_NS 4022#ifndef HAVE_NS
3851 || !x_create_x_image_and_pixmap (f, width, height, 1, 4023 || !image_create_x_image_and_pixmap (f, img, width, height, 1,
3852 &mask_img, &img->mask) 4024 &mask_img, 1)
3853#endif 4025#endif
3854 ) 4026 )
3855 { 4027 {
@@ -3984,8 +4156,7 @@ xpm_load_image (struct frame *f,
3984 if (NILP (image_spec_value (img->spec, QCbackground, NULL))) 4156 if (NILP (image_spec_value (img->spec, QCbackground, NULL)))
3985 IMAGE_BACKGROUND (img, f, ximg); 4157 IMAGE_BACKGROUND (img, f, ximg);
3986 4158
3987 x_put_x_image (f, ximg, img->pixmap, width, height); 4159 image_put_x_image (f, img, ximg, 0);
3988 x_destroy_x_image (ximg);
3989#ifndef HAVE_NS 4160#ifndef HAVE_NS
3990 if (have_mask) 4161 if (have_mask)
3991 { 4162 {
@@ -3993,14 +4164,12 @@ xpm_load_image (struct frame *f,
3993 mask handy. */ 4164 mask handy. */
3994 image_background_transparent (img, f, mask_img); 4165 image_background_transparent (img, f, mask_img);
3995 4166
3996 x_put_x_image (f, mask_img, img->mask, width, height); 4167 image_put_x_image (f, img, mask_img, 1);
3997 x_destroy_x_image (mask_img);
3998 } 4168 }
3999 else 4169 else
4000 { 4170 {
4001 x_destroy_x_image (mask_img); 4171 x_destroy_x_image (mask_img);
4002 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask); 4172 x_clear_image_1 (f, img, CLEAR_IMAGE_MASK);
4003 img->mask = NO_PIXMAP;
4004 } 4173 }
4005#endif 4174#endif
4006 return 1; 4175 return 1;
@@ -4390,7 +4559,6 @@ x_to_xcolors (struct frame *f, struct image *img, bool rgb_p)
4390 XColor *colors, *p; 4559 XColor *colors, *p;
4391 XImagePtr_or_DC ximg; 4560 XImagePtr_or_DC ximg;
4392#ifdef HAVE_NTGUI 4561#ifdef HAVE_NTGUI
4393 HDC hdc;
4394 HGDIOBJ prev; 4562 HGDIOBJ prev;
4395#endif /* HAVE_NTGUI */ 4563#endif /* HAVE_NTGUI */
4396 4564
@@ -4398,17 +4566,8 @@ x_to_xcolors (struct frame *f, struct image *img, bool rgb_p)
4398 memory_full (SIZE_MAX); 4566 memory_full (SIZE_MAX);
4399 colors = xmalloc (sizeof *colors * img->width * img->height); 4567 colors = xmalloc (sizeof *colors * img->width * img->height);
4400 4568
4401#ifndef HAVE_NTGUI 4569 /* Get the X image or create a memory device context for IMG. */
4402 /* Get the X image IMG->pixmap. */ 4570 ximg = image_get_x_image_or_dc (f, img, 0, &prev);
4403 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap,
4404 0, 0, img->width, img->height, ~0, ZPixmap);
4405#else
4406 /* Load the image into a memory device context. */
4407 hdc = get_frame_dc (f);
4408 ximg = CreateCompatibleDC (hdc);
4409 release_frame_dc (f, hdc);
4410 prev = SelectObject (ximg, img->pixmap);
4411#endif /* HAVE_NTGUI */
4412 4571
4413 /* Fill the `pixel' members of the XColor array. I wished there 4572 /* Fill the `pixel' members of the XColor array. I wished there
4414 were an easy and portable way to circumvent XGetPixel. */ 4573 were an easy and portable way to circumvent XGetPixel. */
@@ -4438,7 +4597,7 @@ x_to_xcolors (struct frame *f, struct image *img, bool rgb_p)
4438#endif /* HAVE_X_WINDOWS */ 4597#endif /* HAVE_X_WINDOWS */
4439 } 4598 }
4440 4599
4441 Destroy_Image (ximg, prev); 4600 image_unget_x_image_or_dc (img, 0, ximg, prev);
4442 4601
4443 return colors; 4602 return colors;
4444} 4603}
@@ -4498,13 +4657,13 @@ x_from_xcolors (struct frame *f, struct image *img, XColor *colors)
4498{ 4657{
4499 int x, y; 4658 int x, y;
4500 XImagePtr oimg = NULL; 4659 XImagePtr oimg = NULL;
4501 Pixmap pixmap;
4502 XColor *p; 4660 XColor *p;
4503 4661
4504 init_color_table (); 4662 init_color_table ();
4505 4663
4506 x_create_x_image_and_pixmap (f, img->width, img->height, 0, 4664 x_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP | CLEAR_IMAGE_COLORS);
4507 &oimg, &pixmap); 4665 image_create_x_image_and_pixmap (f, img, img->width, img->height, 0,
4666 &oimg, 0);
4508 p = colors; 4667 p = colors;
4509 for (y = 0; y < img->height; ++y) 4668 for (y = 0; y < img->height; ++y)
4510 for (x = 0; x < img->width; ++x, ++p) 4669 for (x = 0; x < img->width; ++x, ++p)
@@ -4515,11 +4674,8 @@ x_from_xcolors (struct frame *f, struct image *img, XColor *colors)
4515 } 4674 }
4516 4675
4517 xfree (colors); 4676 xfree (colors);
4518 x_clear_image_1 (f, img, 1, 0, 1);
4519 4677
4520 x_put_x_image (f, oimg, pixmap, img->width, img->height); 4678 image_put_x_image (f, img, oimg, 0);
4521 x_destroy_x_image (oimg);
4522 img->pixmap = pixmap;
4523#ifdef COLOR_TABLE_SUPPORT 4679#ifdef COLOR_TABLE_SUPPORT
4524 img->colors = colors_in_color_table (&img->ncolors); 4680 img->colors = colors_in_color_table (&img->ncolors);
4525 free_color_table (); 4681 free_color_table ();
@@ -4704,7 +4860,10 @@ x_disable_image (struct frame *f, struct image *img)
4704#define MaskForeground(f) WHITE_PIX_DEFAULT (f) 4860#define MaskForeground(f) WHITE_PIX_DEFAULT (f)
4705 4861
4706 Display *dpy = FRAME_X_DISPLAY (f); 4862 Display *dpy = FRAME_X_DISPLAY (f);
4707 GC gc = XCreateGC (dpy, img->pixmap, 0, NULL); 4863 GC gc;
4864
4865 image_sync_to_pixmaps (f, img);
4866 gc = XCreateGC (dpy, img->pixmap, 0, NULL);
4708 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f)); 4867 XSetForeground (dpy, gc, BLACK_PIX_DEFAULT (f));
4709 XDrawLine (dpy, img->pixmap, gc, 0, 0, 4868 XDrawLine (dpy, img->pixmap, gc, 0, 0,
4710 img->width - 1, img->height - 1); 4869 img->width - 1, img->height - 1);
@@ -4769,7 +4928,6 @@ x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
4769#ifndef HAVE_NTGUI 4928#ifndef HAVE_NTGUI
4770 XImagePtr mask_img; 4929 XImagePtr mask_img;
4771#else 4930#else
4772 HDC frame_dc;
4773 HGDIOBJ prev; 4931 HGDIOBJ prev;
4774 char *mask_img; 4932 char *mask_img;
4775 int row_width; 4933 int row_width;
@@ -4779,37 +4937,25 @@ x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
4779 unsigned long bg = 0; 4937 unsigned long bg = 0;
4780 4938
4781 if (img->mask) 4939 if (img->mask)
4782 { 4940 x_clear_image_1 (f, img, CLEAR_IMAGE_MASK);
4783 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4784 img->mask = NO_PIXMAP;
4785 img->background_transparent_valid = 0;
4786 }
4787 4941
4788#ifndef HAVE_NTGUI 4942#ifndef HAVE_NTGUI
4789#ifndef HAVE_NS 4943#ifndef HAVE_NS
4790 /* Create an image and pixmap serving as mask. */ 4944 /* Create an image and pixmap serving as mask. */
4791 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1, 4945 rc = image_create_x_image_and_pixmap (f, img, img->width, img->height, 1,
4792 &mask_img, &img->mask); 4946 &mask_img, 1);
4793 if (!rc) 4947 if (!rc)
4794 return; 4948 return;
4795#endif /* !HAVE_NS */ 4949#endif /* !HAVE_NS */
4796
4797 /* Get the X image of IMG->pixmap. */
4798 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0,
4799 img->width, img->height,
4800 ~0, ZPixmap);
4801#else 4950#else
4802 /* Create the bit array serving as mask. */ 4951 /* Create the bit array serving as mask. */
4803 row_width = (img->width + 7) / 8; 4952 row_width = (img->width + 7) / 8;
4804 mask_img = xzalloc (row_width * img->height); 4953 mask_img = xzalloc (row_width * img->height);
4805
4806 /* Create a memory device context for IMG->pixmap. */
4807 frame_dc = get_frame_dc (f);
4808 ximg = CreateCompatibleDC (frame_dc);
4809 release_frame_dc (f, frame_dc);
4810 prev = SelectObject (ximg, img->pixmap);
4811#endif /* HAVE_NTGUI */ 4954#endif /* HAVE_NTGUI */
4812 4955
4956 /* Get the X image or create a memory device context for IMG. */
4957 ximg = image_get_x_image_or_dc (f, img, 0, &prev);
4958
4813 /* Determine the background color of ximg. If HOW is `(R G B)' 4959 /* Determine the background color of ximg. If HOW is `(R G B)'
4814 take that as color. Otherwise, use the image's background color. */ 4960 take that as color. Otherwise, use the image's background color. */
4815 use_img_background = 1; 4961 use_img_background = 1;
@@ -4856,9 +5002,8 @@ x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
4856 /* Fill in the background_transparent field while we have the mask handy. */ 5002 /* Fill in the background_transparent field while we have the mask handy. */
4857 image_background_transparent (img, f, mask_img); 5003 image_background_transparent (img, f, mask_img);
4858 5004
4859 /* Put mask_img into img->mask. */ 5005 /* Put mask_img into the image. */
4860 x_put_x_image (f, mask_img, img->mask, img->width, img->height); 5006 image_put_x_image (f, img, mask_img, 1);
4861 x_destroy_x_image (mask_img);
4862#endif /* !HAVE_NS */ 5007#endif /* !HAVE_NS */
4863#else 5008#else
4864 for (y = 0; y < img->height; ++y) 5009 for (y = 0; y < img->height; ++y)
@@ -4880,7 +5025,7 @@ x_build_heuristic_mask (struct frame *f, struct image *img, Lisp_Object how)
4880 xfree (mask_img); 5025 xfree (mask_img);
4881#endif /* HAVE_NTGUI */ 5026#endif /* HAVE_NTGUI */
4882 5027
4883 Destroy_Image (ximg, prev); 5028 image_unget_x_image_or_dc (img, 0, ximg, prev);
4884} 5029}
4885 5030
4886 5031
@@ -5108,8 +5253,7 @@ pbm_load (struct frame *f, struct image *img)
5108 goto error; 5253 goto error;
5109 } 5254 }
5110 5255
5111 if (!x_create_x_image_and_pixmap (f, width, height, 0, 5256 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
5112 &ximg, &img->pixmap))
5113 goto error; 5257 goto error;
5114 5258
5115 /* Initialize the color hash table. */ 5259 /* Initialize the color hash table. */
@@ -5246,9 +5390,8 @@ pbm_load (struct frame *f, struct image *img)
5246 /* Casting avoids a GCC warning. */ 5390 /* Casting avoids a GCC warning. */
5247 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg); 5391 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
5248 5392
5249 /* Put the image into a pixmap. */ 5393 /* Put ximg into the image. */
5250 x_put_x_image (f, ximg, img->pixmap, width, height); 5394 image_put_x_image (f, img, ximg, 0);
5251 x_destroy_x_image (ximg);
5252 5395
5253 /* X and W32 versions did it here, MAC version above. ++kfs 5396 /* X and W32 versions did it here, MAC version above. ++kfs
5254 img->width = width; 5397 img->width = width;
@@ -5580,7 +5723,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5580 } 5723 }
5581 5724
5582 /* Open the image file. */ 5725 /* Open the image file. */
5583 fp = fopen (SSDATA (file), "rb"); 5726 fp = emacs_fopen (SSDATA (file), "rb");
5584 if (!fp) 5727 if (!fp)
5585 { 5728 {
5586 image_error ("Cannot open image file `%s'", file, Qnil); 5729 image_error ("Cannot open image file `%s'", file, Qnil);
@@ -5686,8 +5829,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5686 5829
5687 /* Create the X image and pixmap now, so that the work below can be 5830 /* Create the X image and pixmap now, so that the work below can be
5688 omitted if the image is too large for X. */ 5831 omitted if the image is too large for X. */
5689 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, 5832 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
5690 &img->pixmap))
5691 goto error; 5833 goto error;
5692 5834
5693 /* If image contains simply transparency data, we prefer to 5835 /* If image contains simply transparency data, we prefer to
@@ -5799,12 +5941,11 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5799 contains an alpha channel. */ 5941 contains an alpha channel. */
5800 if (channels == 4 5942 if (channels == 4
5801 && !transparent_p 5943 && !transparent_p
5802 && !x_create_x_image_and_pixmap (f, width, height, 1, 5944 && !image_create_x_image_and_pixmap (f, img, width, height, 1,
5803 &mask_img, &img->mask)) 5945 &mask_img, 1))
5804 { 5946 {
5805 x_destroy_x_image (ximg); 5947 x_destroy_x_image (ximg);
5806 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap); 5948 x_clear_image_1 (f, img, CLEAR_IMAGE_PIXMAP);
5807 img->pixmap = NO_PIXMAP;
5808 goto error; 5949 goto error;
5809 } 5950 }
5810 5951
@@ -5878,9 +6019,8 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5878 Casting avoids a GCC warning. */ 6019 Casting avoids a GCC warning. */
5879 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg); 6020 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
5880 6021
5881 /* Put the image into the pixmap, then free the X image and its buffer. */ 6022 /* Put ximg into the image. */
5882 x_put_x_image (f, ximg, img->pixmap, width, height); 6023 image_put_x_image (f, img, ximg, 0);
5883 x_destroy_x_image (ximg);
5884 6024
5885 /* Same for the mask. */ 6025 /* Same for the mask. */
5886 if (mask_img) 6026 if (mask_img)
@@ -5889,8 +6029,7 @@ png_load_body (struct frame *f, struct image *img, struct png_load_context *c)
5889 mask handy. Casting avoids a GCC warning. */ 6029 mask handy. Casting avoids a GCC warning. */
5890 image_background_transparent (img, f, (XImagePtr_or_DC)mask_img); 6030 image_background_transparent (img, f, (XImagePtr_or_DC)mask_img);
5891 6031
5892 x_put_x_image (f, mask_img, img->mask, img->width, img->height); 6032 image_put_x_image (f, img, mask_img, 1);
5893 x_destroy_x_image (mask_img);
5894 } 6033 }
5895 6034
5896 return 1; 6035 return 1;
@@ -6345,7 +6484,7 @@ jpeg_load_body (struct frame *f, struct image *img,
6345 return 0; 6484 return 0;
6346 } 6485 }
6347 6486
6348 fp = fopen (SSDATA (file), "rb"); 6487 fp = emacs_fopen (SSDATA (file), "rb");
6349 if (fp == NULL) 6488 if (fp == NULL)
6350 { 6489 {
6351 image_error ("Cannot open `%s'", file, Qnil); 6490 image_error ("Cannot open `%s'", file, Qnil);
@@ -6427,7 +6566,7 @@ jpeg_load_body (struct frame *f, struct image *img,
6427 } 6566 }
6428 6567
6429 /* Create X image and pixmap. */ 6568 /* Create X image and pixmap. */
6430 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) 6569 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
6431 { 6570 {
6432 mgr->failure_code = MY_JPEG_CANNOT_CREATE_X; 6571 mgr->failure_code = MY_JPEG_CANNOT_CREATE_X;
6433 sys_longjmp (mgr->setjmp_buffer, 1); 6572 sys_longjmp (mgr->setjmp_buffer, 1);
@@ -6494,9 +6633,8 @@ jpeg_load_body (struct frame *f, struct image *img,
6494 /* Casting avoids a GCC warning. */ 6633 /* Casting avoids a GCC warning. */
6495 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg); 6634 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6496 6635
6497 /* Put the image into the pixmap. */ 6636 /* Put ximg into the image. */
6498 x_put_x_image (f, ximg, img->pixmap, width, height); 6637 image_put_x_image (f, img, ximg, 0);
6499 x_destroy_x_image (ximg);
6500 return 1; 6638 return 1;
6501} 6639}
6502 6640
@@ -6893,8 +7031,8 @@ tiff_load (struct frame *f, struct image *img)
6893 7031
6894 /* Create the X image and pixmap. */ 7032 /* Create the X image and pixmap. */
6895 if (! (height <= min (PTRDIFF_MAX, SIZE_MAX) / sizeof *buf / width 7033 if (! (height <= min (PTRDIFF_MAX, SIZE_MAX) / sizeof *buf / width
6896 && x_create_x_image_and_pixmap (f, width, height, 0, 7034 && image_create_x_image_and_pixmap (f, img, width, height, 0,
6897 &ximg, &img->pixmap))) 7035 &ximg, 0)))
6898 { 7036 {
6899 fn_TIFFClose (tiff); 7037 fn_TIFFClose (tiff);
6900 return 0; 7038 return 0;
@@ -6953,9 +7091,8 @@ tiff_load (struct frame *f, struct image *img)
6953 /* Casting avoids a GCC warning on W32. */ 7091 /* Casting avoids a GCC warning on W32. */
6954 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg); 7092 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
6955 7093
6956 /* Put the image into the pixmap, then free the X image and its buffer. */ 7094 /* Put ximg into the image. */
6957 x_put_x_image (f, ximg, img->pixmap, width, height); 7095 image_put_x_image (f, img, ximg, 0);
6958 x_destroy_x_image (ximg);
6959 xfree (buf); 7096 xfree (buf);
6960 7097
6961 return 1; 7098 return 1;
@@ -7283,7 +7420,7 @@ gif_load (struct frame *f, struct image *img)
7283 } 7420 }
7284 7421
7285 /* Create the X image and pixmap. */ 7422 /* Create the X image and pixmap. */
7286 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) 7423 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
7287 { 7424 {
7288 fn_DGifCloseFile (gif); 7425 fn_DGifCloseFile (gif);
7289 return 0; 7426 return 0;
@@ -7467,9 +7604,8 @@ gif_load (struct frame *f, struct image *img)
7467 /* Casting avoids a GCC warning. */ 7604 /* Casting avoids a GCC warning. */
7468 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg); 7605 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
7469 7606
7470 /* Put the image into the pixmap, then free the X image and its buffer. */ 7607 /* Put ximg into the image. */
7471 x_put_x_image (f, ximg, img->pixmap, width, height); 7608 image_put_x_image (f, img, ximg, 0);
7472 x_destroy_x_image (ximg);
7473 7609
7474 return 1; 7610 return 1;
7475} 7611}
@@ -7489,10 +7625,100 @@ gif_load (struct frame *f, struct image *img)
7489#endif /* HAVE_GIF */ 7625#endif /* HAVE_GIF */
7490 7626
7491 7627
7628#ifdef HAVE_IMAGEMAGICK
7629
7492/*********************************************************************** 7630/***********************************************************************
7493 ImageMagick 7631 ImageMagick
7494***********************************************************************/ 7632***********************************************************************/
7495#if defined (HAVE_IMAGEMAGICK) 7633
7634/* Scale an image size by returning SIZE / DIVISOR * MULTIPLIER,
7635 safely rounded and clipped to int range. */
7636
7637static int
7638scale_image_size (int size, size_t divisor, size_t multiplier)
7639{
7640 if (divisor != 0)
7641 {
7642 double s = size;
7643 double scaled = s * multiplier / divisor + 0.5;
7644 if (scaled < INT_MAX)
7645 return scaled;
7646 }
7647 return INT_MAX;
7648}
7649
7650/* Compute the desired size of an image with native size WIDTH x HEIGHT.
7651 Use SPEC to deduce the size. Store the desired size into
7652 *D_WIDTH x *D_HEIGHT. Store -1 x -1 if the native size is OK. */
7653static void
7654compute_image_size (size_t width, size_t height,
7655 Lisp_Object spec,
7656 int *d_width, int *d_height)
7657{
7658 Lisp_Object value;
7659 int desired_width, desired_height;
7660
7661 /* If width and/or height is set in the display spec assume we want
7662 to scale to those values. If either h or w is unspecified, the
7663 unspecified should be calculated from the specified to preserve
7664 aspect ratio. */
7665 value = image_spec_value (spec, QCwidth, NULL);
7666 desired_width = NATNUMP (value) ? min (XFASTINT (value), INT_MAX) : -1;
7667 value = image_spec_value (spec, QCheight, NULL);
7668 desired_height = NATNUMP (value) ? min (XFASTINT (value), INT_MAX) : -1;
7669
7670 if (desired_width == -1)
7671 {
7672 value = image_spec_value (spec, QCmax_width, NULL);
7673 if (NATNUMP (value))
7674 {
7675 int max_width = min (XFASTINT (value), INT_MAX);
7676 if (max_width < width)
7677 {
7678 /* The image is wider than :max-width. */
7679 desired_width = max_width;
7680 if (desired_height == -1)
7681 {
7682 desired_height = scale_image_size (desired_width,
7683 width, height);
7684 value = image_spec_value (spec, QCmax_height, NULL);
7685 if (NATNUMP (value))
7686 {
7687 int max_height = min (XFASTINT (value), INT_MAX);
7688 if (max_height < desired_height)
7689 {
7690 desired_height = max_height;
7691 desired_width = scale_image_size (desired_height,
7692 height, width);
7693 }
7694 }
7695 }
7696 }
7697 }
7698 }
7699
7700 if (desired_height == -1)
7701 {
7702 value = image_spec_value (spec, QCmax_height, NULL);
7703 if (NATNUMP (value))
7704 {
7705 int max_height = min (XFASTINT (value), INT_MAX);
7706 if (max_height < height)
7707 desired_height = max_height;
7708 }
7709 }
7710
7711 if (desired_width != -1 && desired_height == -1)
7712 /* w known, calculate h. */
7713 desired_height = scale_image_size (desired_width, width, height);
7714
7715 if (desired_width == -1 && desired_height != -1)
7716 /* h known, calculate w. */
7717 desired_width = scale_image_size (desired_height, height, width);
7718
7719 *d_width = desired_width;
7720 *d_height = desired_height;
7721}
7496 7722
7497static Lisp_Object Qimagemagick; 7723static Lisp_Object Qimagemagick;
7498 7724
@@ -7516,6 +7742,8 @@ enum imagemagick_keyword_index
7516 IMAGEMAGICK_BACKGROUND, 7742 IMAGEMAGICK_BACKGROUND,
7517 IMAGEMAGICK_HEIGHT, 7743 IMAGEMAGICK_HEIGHT,
7518 IMAGEMAGICK_WIDTH, 7744 IMAGEMAGICK_WIDTH,
7745 IMAGEMAGICK_MAX_HEIGHT,
7746 IMAGEMAGICK_MAX_WIDTH,
7519 IMAGEMAGICK_ROTATION, 7747 IMAGEMAGICK_ROTATION,
7520 IMAGEMAGICK_CROP, 7748 IMAGEMAGICK_CROP,
7521 IMAGEMAGICK_LAST 7749 IMAGEMAGICK_LAST
@@ -7538,6 +7766,8 @@ static struct image_keyword imagemagick_format[IMAGEMAGICK_LAST] =
7538 {":background", IMAGE_STRING_OR_NIL_VALUE, 0}, 7766 {":background", IMAGE_STRING_OR_NIL_VALUE, 0},
7539 {":height", IMAGE_INTEGER_VALUE, 0}, 7767 {":height", IMAGE_INTEGER_VALUE, 0},
7540 {":width", IMAGE_INTEGER_VALUE, 0}, 7768 {":width", IMAGE_INTEGER_VALUE, 0},
7769 {":max-height", IMAGE_INTEGER_VALUE, 0},
7770 {":max-width", IMAGE_INTEGER_VALUE, 0},
7541 {":rotation", IMAGE_NUMBER_VALUE, 0}, 7771 {":rotation", IMAGE_NUMBER_VALUE, 0},
7542 {":crop", IMAGE_DONT_CHECK_VALUE_TYPE, 0} 7772 {":crop", IMAGE_DONT_CHECK_VALUE_TYPE, 0}
7543 }; 7773 };
@@ -7726,24 +7956,10 @@ imagemagick_load_image (struct frame *f, struct image *img,
7726 PixelSetBlue (bg_wand, (double) bgcolor.blue / 65535); 7956 PixelSetBlue (bg_wand, (double) bgcolor.blue / 65535);
7727 } 7957 }
7728 7958
7729 /* If width and/or height is set in the display spec assume we want 7959 compute_image_size (MagickGetImageWidth (image_wand),
7730 to scale to those values. If either h or w is unspecified, the 7960 MagickGetImageHeight (image_wand),
7731 unspecified should be calculated from the specified to preserve 7961 img->spec, &desired_width, &desired_height);
7732 aspect ratio. */
7733 value = image_spec_value (img->spec, QCwidth, NULL);
7734 desired_width = (INTEGERP (value) ? XFASTINT (value) : -1);
7735 value = image_spec_value (img->spec, QCheight, NULL);
7736 desired_height = (INTEGERP (value) ? XFASTINT (value) : -1);
7737
7738 height = MagickGetImageHeight (image_wand);
7739 width = MagickGetImageWidth (image_wand);
7740 7962
7741 if (desired_width != -1 && desired_height == -1)
7742 /* w known, calculate h. */
7743 desired_height = (double) desired_width / width * height;
7744 if (desired_width == -1 && desired_height != -1)
7745 /* h known, calculate w. */
7746 desired_width = (double) desired_height / height * width;
7747 if (desired_width != -1 && desired_height != -1) 7963 if (desired_width != -1 && desired_height != -1)
7748 { 7964 {
7749 status = MagickScaleImage (image_wand, desired_width, desired_height); 7965 status = MagickScaleImage (image_wand, desired_width, desired_height);
@@ -7847,8 +8063,8 @@ imagemagick_load_image (struct frame *f, struct image *img,
7847 int imagedepth = 24; /*MagickGetImageDepth(image_wand);*/ 8063 int imagedepth = 24; /*MagickGetImageDepth(image_wand);*/
7848 const char *exportdepth = imagedepth <= 8 ? "I" : "BGRP"; /*"RGBP";*/ 8064 const char *exportdepth = imagedepth <= 8 ? "I" : "BGRP"; /*"RGBP";*/
7849 /* Try to create a x pixmap to hold the imagemagick pixmap. */ 8065 /* Try to create a x pixmap to hold the imagemagick pixmap. */
7850 if (!x_create_x_image_and_pixmap (f, width, height, imagedepth, 8066 if (!image_create_x_image_and_pixmap (f, img, width, height, imagedepth,
7851 &ximg, &img->pixmap)) 8067 &ximg, 0))
7852 { 8068 {
7853#ifdef COLOR_TABLE_SUPPORT 8069#ifdef COLOR_TABLE_SUPPORT
7854 free_color_table (); 8070 free_color_table ();
@@ -7886,8 +8102,8 @@ imagemagick_load_image (struct frame *f, struct image *img,
7886 size_t image_height; 8102 size_t image_height;
7887 8103
7888 /* Try to create a x pixmap to hold the imagemagick pixmap. */ 8104 /* Try to create a x pixmap to hold the imagemagick pixmap. */
7889 if (!x_create_x_image_and_pixmap (f, width, height, 0, 8105 if (!image_create_x_image_and_pixmap (f, img, width, height, 0,
7890 &ximg, &img->pixmap)) 8106 &ximg, 0))
7891 { 8107 {
7892#ifdef COLOR_TABLE_SUPPORT 8108#ifdef COLOR_TABLE_SUPPORT
7893 free_color_table (); 8109 free_color_table ();
@@ -7941,10 +8157,8 @@ imagemagick_load_image (struct frame *f, struct image *img,
7941 img->width = width; 8157 img->width = width;
7942 img->height = height; 8158 img->height = height;
7943 8159
7944 /* Put the image into the pixmap, then free the X image and its 8160 /* Put ximg into the image. */
7945 buffer. */ 8161 image_put_x_image (f, img, ximg, 0);
7946 x_put_x_image (f, ximg, img->pixmap, width, height);
7947 x_destroy_x_image (ximg);
7948 8162
7949 /* Final cleanup. image_wand should be the only resource left. */ 8163 /* Final cleanup. image_wand should be the only resource left. */
7950 DestroyMagickWand (image_wand); 8164 DestroyMagickWand (image_wand);
@@ -8338,7 +8552,7 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. *
8338 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf) == 8); 8552 eassert (fn_gdk_pixbuf_get_bits_per_sample (pixbuf) == 8);
8339 8553
8340 /* Try to create a x pixmap to hold the svg pixmap. */ 8554 /* Try to create a x pixmap to hold the svg pixmap. */
8341 if (!x_create_x_image_and_pixmap (f, width, height, 0, &ximg, &img->pixmap)) 8555 if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0))
8342 { 8556 {
8343 fn_g_object_unref (pixbuf); 8557 fn_g_object_unref (pixbuf);
8344 return 0; 8558 return 0;
@@ -8413,10 +8627,8 @@ svg_load_image (struct frame *f, /* Pointer to emacs frame structure. *
8413 Casting avoids a GCC warning. */ 8627 Casting avoids a GCC warning. */
8414 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg); 8628 IMAGE_BACKGROUND (img, f, (XImagePtr_or_DC)ximg);
8415 8629
8416 /* Put the image into the pixmap, then free the X image and its 8630 /* Put ximg into the image. */
8417 buffer. */ 8631 image_put_x_image (f, img, ximg, 0);
8418 x_put_x_image (f, ximg, img->pixmap, width, height);
8419 x_destroy_x_image (ximg);
8420 8632
8421 return 1; 8633 return 1;
8422 8634
@@ -8895,6 +9107,8 @@ non-numeric, there is no explicit limit on the size of images. */);
8895 DEFSYM (Qheuristic, "heuristic"); 9107 DEFSYM (Qheuristic, "heuristic");
8896 9108
8897 DEFSYM (Qpostscript, "postscript"); 9109 DEFSYM (Qpostscript, "postscript");
9110 DEFSYM (QCmax_width, ":max-width");
9111 DEFSYM (QCmax_height, ":max-height");
8898#ifdef HAVE_GHOSTSCRIPT 9112#ifdef HAVE_GHOSTSCRIPT
8899 ADD_IMAGE_TYPE (Qpostscript); 9113 ADD_IMAGE_TYPE (Qpostscript);
8900 DEFSYM (QCloader, ":loader"); 9114 DEFSYM (QCloader, ":loader");