diff options
| author | Lars Ingebrigtsen | 2022-04-11 16:52:34 +0200 |
|---|---|---|
| committer | Lars Ingebrigtsen | 2022-04-11 16:52:34 +0200 |
| commit | 0e7185cefae6033e2e0628ce91009e1fbf328206 (patch) | |
| tree | 4713536394b95a134a738653b1e114e91ad3285a /src | |
| parent | be48dfe0b3a80c0896f4d562c6a8f428ec91d19e (diff) | |
| download | emacs-0e7185cefae6033e2e0628ce91009e1fbf328206.tar.gz emacs-0e7185cefae6033e2e0628ce91009e1fbf328206.zip | |
Make gif_load work across architectures again
* src/image.c (gif_load): Invert the way animated pixmaps are
created: Work on the cached computed-so-far pixmap, and then copy
the entire thing to the ximg with PUT_PIXEL at the end. This
should work across platforms, which the previous version didn't.
Diffstat (limited to 'src')
| -rw-r--r-- | src/image.c | 62 |
1 files changed, 39 insertions, 23 deletions
diff --git a/src/image.c b/src/image.c index f28eb5eb6e1..d6c2af7f199 100644 --- a/src/image.c +++ b/src/image.c | |||
| @@ -8775,6 +8775,7 @@ gif_load (struct frame *f, struct image *img) | |||
| 8775 | Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL); | 8775 | Lisp_Object specified_bg = image_spec_value (img->spec, QCbackground, NULL); |
| 8776 | Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL); | 8776 | Lisp_Object specified_file = image_spec_value (img->spec, QCfile, NULL); |
| 8777 | Lisp_Object specified_data = image_spec_value (img->spec, QCdata, NULL); | 8777 | Lisp_Object specified_data = image_spec_value (img->spec, QCdata, NULL); |
| 8778 | unsigned long *pixmap = NULL; | ||
| 8778 | EMACS_INT idx = -1; | 8779 | EMACS_INT idx = -1; |
| 8779 | int gif_err; | 8780 | int gif_err; |
| 8780 | struct anim_cache* cache = NULL; | 8781 | struct anim_cache* cache = NULL; |
| @@ -8794,7 +8795,10 @@ gif_load (struct frame *f, struct image *img) | |||
| 8794 | /* We have an old cache entry, and it looks correct, so use | 8795 | /* We have an old cache entry, and it looks correct, so use |
| 8795 | it. */ | 8796 | it. */ |
| 8796 | if (cache->index == idx - 1) | 8797 | if (cache->index == idx - 1) |
| 8797 | gif = cache->handle; | 8798 | { |
| 8799 | gif = cache->handle; | ||
| 8800 | pixmap = cache->temp; | ||
| 8801 | } | ||
| 8798 | } | 8802 | } |
| 8799 | } | 8803 | } |
| 8800 | 8804 | ||
| @@ -8958,6 +8962,15 @@ gif_load (struct frame *f, struct image *img) | |||
| 8958 | if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) | 8962 | if (!image_create_x_image_and_pixmap (f, img, width, height, 0, &ximg, 0)) |
| 8959 | goto gif_error; | 8963 | goto gif_error; |
| 8960 | 8964 | ||
| 8965 | /* We construct the (possibly composited animated) image in this | ||
| 8966 | buffer. */ | ||
| 8967 | if (!pixmap) | ||
| 8968 | { | ||
| 8969 | pixmap = xmalloc (width * height * sizeof (unsigned long)); | ||
| 8970 | if (cache) | ||
| 8971 | cache->temp = pixmap; | ||
| 8972 | } | ||
| 8973 | |||
| 8961 | /* Clear the part of the screen image not covered by the image. | 8974 | /* Clear the part of the screen image not covered by the image. |
| 8962 | Full animated GIF support requires more here (see the gif89 spec, | 8975 | Full animated GIF support requires more here (see the gif89 spec, |
| 8963 | disposal methods). Let's simply assume that the part not covered | 8976 | disposal methods). Let's simply assume that the part not covered |
| @@ -8972,20 +8985,21 @@ gif_load (struct frame *f, struct image *img) | |||
| 8972 | frame_bg = lookup_rgb_color (f, color.red, color.green, color.blue); | 8985 | frame_bg = lookup_rgb_color (f, color.red, color.green, color.blue); |
| 8973 | } | 8986 | } |
| 8974 | #endif /* USE_CAIRO */ | 8987 | #endif /* USE_CAIRO */ |
| 8988 | |||
| 8975 | for (y = 0; y < img->corners[TOP_CORNER]; ++y) | 8989 | for (y = 0; y < img->corners[TOP_CORNER]; ++y) |
| 8976 | for (x = 0; x < width; ++x) | 8990 | for (x = 0; x < width; ++x) |
| 8977 | PUT_PIXEL (ximg, x, y, frame_bg); | 8991 | *(pixmap + x + y * width) = frame_bg; |
| 8978 | 8992 | ||
| 8979 | for (y = img->corners[BOT_CORNER]; y < height; ++y) | 8993 | for (y = img->corners[BOT_CORNER]; y < height; ++y) |
| 8980 | for (x = 0; x < width; ++x) | 8994 | for (x = 0; x < width; ++x) |
| 8981 | PUT_PIXEL (ximg, x, y, frame_bg); | 8995 | *(pixmap + x + y * width) = frame_bg; |
| 8982 | 8996 | ||
| 8983 | for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y) | 8997 | for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y) |
| 8984 | { | 8998 | { |
| 8985 | for (x = 0; x < img->corners[LEFT_CORNER]; ++x) | 8999 | for (x = 0; x < img->corners[LEFT_CORNER]; ++x) |
| 8986 | PUT_PIXEL (ximg, x, y, frame_bg); | 9000 | *(pixmap + x + y * width) = frame_bg; |
| 8987 | for (x = img->corners[RIGHT_CORNER]; x < width; ++x) | 9001 | for (x = img->corners[RIGHT_CORNER]; x < width; ++x) |
| 8988 | PUT_PIXEL (ximg, x, y, frame_bg); | 9002 | *(pixmap + x + y * width) = frame_bg; |
| 8989 | } | 9003 | } |
| 8990 | 9004 | ||
| 8991 | /* Read the GIF image into the X image. */ | 9005 | /* Read the GIF image into the X image. */ |
| @@ -9006,13 +9020,12 @@ gif_load (struct frame *f, struct image *img) | |||
| 9006 | 9020 | ||
| 9007 | int start_frame = 0; | 9021 | int start_frame = 0; |
| 9008 | 9022 | ||
| 9009 | /* We have animation data in the cache, so copy it over so that we | 9023 | /* We have animation data in the cache. */ |
| 9010 | can alter it. */ | ||
| 9011 | int cache_image_size = width * height * ximg->bits_per_pixel / 8; | ||
| 9012 | if (cache && cache->temp) | 9024 | if (cache && cache->temp) |
| 9013 | { | 9025 | { |
| 9014 | memcpy (ximg->data, cache->temp, cache_image_size); | 9026 | start_frame = cache->index + 1; |
| 9015 | start_frame = cache->index; | 9027 | if (start_frame > idx) |
| 9028 | start_frame = 0; | ||
| 9016 | cache->index = idx; | 9029 | cache->index = idx; |
| 9017 | } | 9030 | } |
| 9018 | 9031 | ||
| @@ -9106,8 +9119,8 @@ gif_load (struct frame *f, struct image *img) | |||
| 9106 | int c = raster[y * subimg_width + x]; | 9119 | int c = raster[y * subimg_width + x]; |
| 9107 | if (transparency_color_index != c || disposal != DISPOSE_DO_NOT) | 9120 | if (transparency_color_index != c || disposal != DISPOSE_DO_NOT) |
| 9108 | { | 9121 | { |
| 9109 | PUT_PIXEL (ximg, x + subimg_left, row + subimg_top, | 9122 | *(pixmap + x + subimg_left + (y + subimg_top) * width) = |
| 9110 | pixel_colors[c]); | 9123 | pixel_colors[c]; |
| 9111 | } | 9124 | } |
| 9112 | } | 9125 | } |
| 9113 | } | 9126 | } |
| @@ -9120,21 +9133,18 @@ gif_load (struct frame *f, struct image *img) | |||
| 9120 | int c = raster[y * subimg_width + x]; | 9133 | int c = raster[y * subimg_width + x]; |
| 9121 | if (transparency_color_index != c || disposal != DISPOSE_DO_NOT) | 9134 | if (transparency_color_index != c || disposal != DISPOSE_DO_NOT) |
| 9122 | { | 9135 | { |
| 9123 | PUT_PIXEL (ximg, x + subimg_left, y + subimg_top, | 9136 | *(pixmap + x + subimg_left + (y + subimg_top) * width) = |
| 9124 | pixel_colors[c]); | 9137 | pixel_colors[c]; |
| 9125 | } | 9138 | } |
| 9126 | } | 9139 | } |
| 9127 | } | 9140 | } |
| 9128 | } | 9141 | } |
| 9129 | 9142 | ||
| 9130 | if (cache) | 9143 | /* We now have the complete image (possibly composed from a series |
| 9131 | { | 9144 | of animated frames) in pixmap. Put it into ximg. */ |
| 9132 | /* Allocate an area to store what we have computed so far. */ | 9145 | for (y = 0; y < height; ++y) |
| 9133 | if (! cache->temp) | 9146 | for (x = 0; x < width; ++x) |
| 9134 | cache->temp = xmalloc (cache_image_size); | 9147 | PUT_PIXEL (ximg, x, y, *(pixmap + x + y * width)); |
| 9135 | /* Copy over the data to the cache. */ | ||
| 9136 | memcpy (cache->temp, ximg->data, cache_image_size); | ||
| 9137 | } | ||
| 9138 | 9148 | ||
| 9139 | #ifdef COLOR_TABLE_SUPPORT | 9149 | #ifdef COLOR_TABLE_SUPPORT |
| 9140 | img->colors = colors_in_color_table (&img->ncolors); | 9150 | img->colors = colors_in_color_table (&img->ncolors); |
| @@ -9178,6 +9188,8 @@ gif_load (struct frame *f, struct image *img) | |||
| 9178 | 9188 | ||
| 9179 | if (!cache) | 9189 | if (!cache) |
| 9180 | { | 9190 | { |
| 9191 | if (pixmap) | ||
| 9192 | xfree (pixmap); | ||
| 9181 | if (gif_close (gif, &gif_err) == GIF_ERROR) | 9193 | if (gif_close (gif, &gif_err) == GIF_ERROR) |
| 9182 | { | 9194 | { |
| 9183 | #if HAVE_GIFERRORSTRING | 9195 | #if HAVE_GIFERRORSTRING |
| @@ -9204,7 +9216,11 @@ gif_load (struct frame *f, struct image *img) | |||
| 9204 | 9216 | ||
| 9205 | gif_error: | 9217 | gif_error: |
| 9206 | if (!cache) | 9218 | if (!cache) |
| 9207 | gif_close (gif, NULL); | 9219 | { |
| 9220 | if (pixmap) | ||
| 9221 | xfree (pixmap); | ||
| 9222 | gif_close (gif, NULL); | ||
| 9223 | } | ||
| 9208 | return false; | 9224 | return false; |
| 9209 | } | 9225 | } |
| 9210 | 9226 | ||