diff options
| author | Tom Tromey | 2013-07-06 23:18:58 -0600 |
|---|---|---|
| committer | Tom Tromey | 2013-07-06 23:18:58 -0600 |
| commit | 6dacdad5fcb278e5a16b38bb81786aac9ca27be4 (patch) | |
| tree | f5f331ea361ba0f99e0f9b638d183ad492a7da31 /src/image.c | |
| parent | 0a6f2ff0c8ceb29703e76cddd46ea3f176dd873a (diff) | |
| parent | 219afb88d9d484393418820d1c08dc93299110ec (diff) | |
| download | emacs-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.c | 596 |
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 | |||
| 18 | along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | 18 | along 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); | |||
| 132 | static unsigned long *colors_in_color_table (int *n); | 130 | static unsigned long *colors_in_color_table (int *n); |
| 133 | #endif | 131 | #endif |
| 134 | 132 | ||
| 133 | static 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 |
| 147 | XImagePtr | ||
| 148 | XGetImage (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. */ |
| 158 | unsigned long | 148 | unsigned long |
| 159 | XGetPixel (XImagePtr ximage, int x, int y) | 149 | XGetPixel (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 *); |
| 434 | static void x_destroy_x_image (XImagePtr ximg); | 424 | static void x_destroy_x_image (XImagePtr ximg); |
| 435 | 425 | ||
| 426 | #ifdef HAVE_NTGUI | ||
| 427 | static XImagePtr_or_DC image_get_x_image_or_dc (struct frame *, struct image *, | ||
| 428 | bool, HGDIOBJ *); | ||
| 429 | static void image_unget_x_image_or_dc (struct image *, bool, XImagePtr_or_DC, | ||
| 430 | HGDIOBJ); | ||
| 431 | #else | ||
| 432 | static XImagePtr image_get_x_image (struct frame *, struct image *, bool); | ||
| 433 | static 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 | ||
| 442 | static 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 | ||
| 1265 | static void | 1257 | static void |
| 1266 | x_clear_image_1 (struct frame *f, struct image *img, bool pixmap_p, | 1258 | x_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 | |||
| 1300 | x_clear_image (struct frame *f, struct image *img) | 1313 | x_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 | |||
| 2109 | static bool | ||
| 2110 | image_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 | |||
| 2126 | static void | ||
| 2127 | image_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 | |||
| 2152 | static void | ||
| 2153 | image_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 | |||
| 2175 | static XImagePtr_or_DC | ||
| 2176 | image_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 | |||
| 2188 | static void | ||
| 2189 | image_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 | |||
| 2199 | static XImagePtr | ||
| 2200 | image_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 | |||
| 2218 | static void | ||
| 2219 | image_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) | |||
| 2135 | static unsigned char * | 2274 | static unsigned char * |
| 2136 | slurp_file (char *file, ptrdiff_t *size) | 2275 | slurp_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 | |||
| 7637 | static int | ||
| 7638 | scale_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. */ | ||
| 7653 | static void | ||
| 7654 | compute_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 | ||
| 7497 | static Lisp_Object Qimagemagick; | 7723 | static 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"); |