X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/9db94f829695546baf4f7050d7d021b784254279..e3eea8436d864519022dd5825ac079e5ec89af95:/src/image.c diff --git a/src/image.c b/src/image.c index 91aa119876..f309a40113 100644 --- a/src/image.c +++ b/src/image.c @@ -201,7 +201,7 @@ XPutPixel (ximage, x, y, pixel) } else #endif - if (depth == 1) + if (depth == 1) { char *base_addr = GetPixBaseAddr (pixmap); short row_bytes = GetPixRowBytes (pixmap); @@ -444,8 +444,6 @@ x_create_bitmap_from_data (f, bits, width, height) id = x_allocate_bitmap_record (f); #ifdef MAC_OS dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width); - if (! dpyinfo->bitmaps[id - 1].bitmap_data) - return -1; bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width); #endif /* MAC_OS */ @@ -605,7 +603,9 @@ x_destroy_all_bitmaps (dpyinfo) /* Useful functions defined in the section `Image type independent image structures' below. */ -static unsigned long four_corners_best P_ ((XImagePtr ximg, unsigned long width, +static unsigned long four_corners_best P_ ((XImagePtr ximg, + int *corners, + unsigned long width, unsigned long height)); static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height, @@ -659,7 +659,7 @@ x_create_bitmap_mask (f, id) return -1; } - bg = four_corners_best (ximg, width, height); + bg = four_corners_best (ximg, NULL, width, height); for (y = 0; y < ximg->height; ++y) { @@ -734,7 +734,7 @@ Lisp_Object Qxbm; /* Keywords. */ extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile; -extern Lisp_Object QCdata, QCtype; +extern Lisp_Object QCdata, QCtype, Qcount; extern Lisp_Object Qcenter; Lisp_Object QCascent, QCmargin, QCrelief; Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask; @@ -1143,6 +1143,27 @@ or omitted means use the selected frame. */) return mask; } +DEFUN ("image-extension-data", Fimage_extension_data, Simage_extension_data, 1, 2, 0, + doc: /* Return extension data for image SPEC. +FRAME is the frame on which the image will be displayed. FRAME nil +or omitted means use the selected frame. */) + (spec, frame) + Lisp_Object spec, frame; +{ + Lisp_Object ext; + + ext = Qnil; + if (valid_image_p (spec)) + { + struct frame *f = check_x_frame (frame); + int id = lookup_image (f, spec); + struct image *img = IMAGE_FROM_ID (f, id); + ext = img->data.lisp_val; + } + + return ext; +} + /*********************************************************************** Image type independent image structures @@ -1173,6 +1194,7 @@ make_image (spec, hash) img->data.lisp_val = Qnil; img->ascent = DEFAULT_IMAGE_ASCENT; img->hash = hash; + img->corners[BOT_CORNER] = -1; /* Full image */ return img; } @@ -1324,30 +1346,41 @@ image_ascent (img, face, slice) On W32, XIMG is assumed to a device context with the bitmap selected. */ static RGB_PIXEL_COLOR -four_corners_best (ximg, width, height) +four_corners_best (ximg, corners, width, height) XImagePtr_or_DC ximg; + int *corners; unsigned long width, height; { - RGB_PIXEL_COLOR corners[4], best; + RGB_PIXEL_COLOR corner_pixels[4], best; int i, best_count; - /* Get the colors at the corners of ximg. */ - corners[0] = GET_PIXEL (ximg, 0, 0); - corners[1] = GET_PIXEL (ximg, width - 1, 0); - corners[2] = GET_PIXEL (ximg, width - 1, height - 1); - corners[3] = GET_PIXEL (ximg, 0, height - 1); - + if (corners && corners[BOT_CORNER] >= 0) + { + /* Get the colors at the corner_pixels of ximg. */ + corner_pixels[0] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[TOP_CORNER]); + corner_pixels[1] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[TOP_CORNER]); + corner_pixels[2] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[BOT_CORNER] - 1); + corner_pixels[3] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[BOT_CORNER] - 1); + } + else + { + /* Get the colors at the corner_pixels of ximg. */ + corner_pixels[0] = GET_PIXEL (ximg, 0, 0); + corner_pixels[1] = GET_PIXEL (ximg, width - 1, 0); + corner_pixels[2] = GET_PIXEL (ximg, width - 1, height - 1); + corner_pixels[3] = GET_PIXEL (ximg, 0, height - 1); + } /* Choose the most frequently found color as background. */ for (i = best_count = 0; i < 4; ++i) { int j, n; for (j = n = 0; j < 4; ++j) - if (corners[i] == corners[j]) + if (corner_pixels[i] == corner_pixels[j]) ++n; if (n > best_count) - best = corners[i], best_count = n; + best = corner_pixels[i], best_count = n; } return best; @@ -1406,7 +1439,7 @@ image_background (img, f, ximg) #endif /* !HAVE_NTGUI */ } - img->background = four_corners_best (ximg, img->width, img->height); + img->background = four_corners_best (ximg, img->corners, img->width, img->height); if (free_ximg) Destroy_Image (ximg, prev); @@ -1451,7 +1484,7 @@ image_background_transparent (img, f, mask) } img->background_transparent - = (four_corners_best (mask, img->width, img->height) == PIX_MASK_RETAIN); + = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN); if (free_mask) Destroy_Image (mask, prev); @@ -2595,7 +2628,7 @@ image_load_quartz2d (f, img, png_p) UNGCPRO; return 0; } - path = cfstring_create_with_string (file); + path = cfstring_create_with_utf8_cstring (SDATA (file)); url = CFURLCreateWithFileSystemPath (NULL, path, kCFURLPOSIXPathStyle, 0); CFRelease (path); @@ -4462,6 +4495,10 @@ xpm_load_image (f, img, contents, end) img->width = width; img->height = height; + /* Maybe fill in the background field while we have ximg handy. */ + if (NILP (image_spec_value (img->spec, QCbackground, NULL))) + IMAGE_BACKGROUND (img, f, ximg); + x_put_x_image (f, ximg, img->pixmap, width, height); x_destroy_x_image (ximg); if (have_mask) @@ -5356,7 +5393,7 @@ x_build_heuristic_mask (f, img, how) } if (use_img_background) - bg = four_corners_best (ximg, img->width, img->height); + bg = four_corners_best (ximg, img->corners, img->width, img->height); /* Set all bits in mask_img to 1 whose color in ximg is different from the background color bg. */ @@ -7449,6 +7486,7 @@ tiff_load (f, img) static int gif_image_p P_ ((Lisp_Object object)); static int gif_load P_ ((struct frame *f, struct image *img)); +static void gif_clear_image P_ ((struct frame *f, struct image *img)); /* The symbol `gif' identifying images of this type. */ @@ -7497,10 +7535,22 @@ static struct image_type gif_type = &Qgif, gif_image_p, gif_load, - x_clear_image, + gif_clear_image, NULL }; +/* Free X resources of GIF image IMG which is used on frame F. */ + +static void +gif_clear_image (f, img) + struct frame *f; + struct image *img; +{ + /* IMG->data.ptr_val may contain extension data. */ + img->data.lisp_val = Qnil; + x_clear_image (f, img); +} + /* Return non-zero if OBJECT is a valid GIF image specification. */ static int @@ -7621,7 +7671,7 @@ gif_load (f, img) GifFileType *gif; struct gcpro gcpro1; Lisp_Object image; - int ino, image_left, image_top, image_width, image_height; + int ino, image_height, image_width; gif_memory_source memsrc; unsigned char *raster; @@ -7698,17 +7748,19 @@ gif_load (f, img) return 0; } - image_top = gif->SavedImages[ino].ImageDesc.Top; - image_left = gif->SavedImages[ino].ImageDesc.Left; - image_width = gif->SavedImages[ino].ImageDesc.Width; + img->corners[TOP_CORNER] = gif->SavedImages[ino].ImageDesc.Top; + img->corners[LEFT_CORNER] = gif->SavedImages[ino].ImageDesc.Left; image_height = gif->SavedImages[ino].ImageDesc.Height; + img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height; + image_width = gif->SavedImages[ino].ImageDesc.Width; + img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width; width = img->width = max (gif->SWidth, max (gif->Image.Left + gif->Image.Width, - image_left + image_width)); + img->corners[RIGHT_CORNER])); height = img->height = max (gif->SHeight, max (gif->Image.Top + gif->Image.Height, - image_top + image_height)); + img->corners[BOT_CORNER])); if (!check_image_size (f, width, height)) { @@ -7751,19 +7803,19 @@ gif_load (f, img) requires more than can be done here (see the gif89 spec, disposal methods). Let's simply assume that the part not covered by a sub-image is in the frame's background color. */ - for (y = 0; y < image_top; ++y) + for (y = 0; y < img->corners[TOP_CORNER]; ++y) for (x = 0; x < width; ++x) XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); - for (y = image_top + image_height; y < height; ++y) + for (y = img->corners[BOT_CORNER]; y < height; ++y) for (x = 0; x < width; ++x) XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); - for (y = image_top; y < image_top + image_height; ++y) + for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y) { - for (x = 0; x < image_left; ++x) + for (x = 0; x < img->corners[LEFT_CORNER]; ++x) XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); - for (x = image_left + image_width; x < width; ++x) + for (x = img->corners[RIGHT_CORNER]; x < width; ++x) XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); } @@ -7793,8 +7845,8 @@ gif_load (f, img) for (x = 0; x < image_width; x++) { int i = raster[(y * image_width) + x]; - XPutPixel (ximg, x + image_left, row + image_top, - pixel_colors[i]); + XPutPixel (ximg, x + img->corners[LEFT_CORNER], + row + img->corners[TOP_CORNER], pixel_colors[i]); } row += interlace_increment[pass]; @@ -7806,10 +7858,29 @@ gif_load (f, img) for (x = 0; x < image_width; ++x) { int i = raster[y * image_width + x]; - XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]); + XPutPixel (ximg, x + img->corners[LEFT_CORNER], + y + img->corners[TOP_CORNER], pixel_colors[i]); } } + /* Save GIF image extension data for `image-extension-data'. + Format is (count IMAGES FUNCTION "BYTES" ...). */ + img->data.lisp_val = Qnil; + if (gif->SavedImages[ino].ExtensionBlockCount > 0) + { + ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks; + for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++) + /* Append (... FUNCTION "BYTES") */ + img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount), + Fcons (make_number (ext->Function), + img->data.lisp_val)); + img->data.lisp_val = Fnreverse (img->data.lisp_val); + } + if (gif->ImageCount > 1) + img->data.lisp_val = Fcons (Qcount, + Fcons (make_number (gif->ImageCount), + img->data.lisp_val)); + fn_DGifCloseFile (gif); /* Maybe fill in the background field while we have ximg handy. */ @@ -7849,7 +7920,8 @@ gif_load (f, img) RGBColor bg_color; int width, height; XImagePtr ximg; - TimeValue time; + TimeScale time_scale; + TimeValue time, duration; int ino; CGrafPtr old_port; GDHandle old_gdh; @@ -7957,6 +8029,7 @@ gif_load (f, img) image, img->spec); goto error; } + time_scale = GetMediaTimeScale (media); specified_bg = image_spec_value (img->spec, QCbackground, NULL); if (!STRINGP (specified_bg) || @@ -7982,7 +8055,7 @@ gif_load (f, img) SetGWorld (old_port, old_gdh); SetMovieActive (movie, 1); SetMovieGWorld (movie, ximg, NULL); - SampleNumToMediaTime (media, ino + 1, &time, NULL); + SampleNumToMediaTime (media, ino + 1, &time, &duration); SetMovieTimeValue (movie, time); MoviesTask (movie, 0L); DisposeTrackMedia (media); @@ -7990,6 +8063,24 @@ gif_load (f, img) DisposeMovie (movie); if (dh) DisposeHandle (dh); + + /* Save GIF image extension data for `image-extension-data'. + Format is (count IMAGES 0xf9 GRAPHIC_CONTROL_EXTENSION_BLOCK). */ + { + unsigned char gce[4]; + int centisec = ((float)duration / time_scale) * 100.0f + 0.5f; + + /* Fill the delay time field. */ + gce[1] = centisec & 0xff; + gce[2] = (centisec >> 8) & 0xff; + /* We don't know about other fields. */ + gce[0] = gce[3] = 0; + + img->data.lisp_val = list4 (Qcount, make_number (nsamples), + make_number (0xf9), + make_unibyte_string (gce, 4)); + } + /* Maybe fill in the background field while we have ximg handy. */ if (NILP (image_spec_value (img->spec, QCbackground, NULL))) IMAGE_BACKGROUND (img, f, ximg); @@ -8555,6 +8646,7 @@ non-numeric, there is no explicit limit on the size of images. */); defsubr (&Sclear_image_cache); defsubr (&Simage_size); defsubr (&Simage_mask_p); + defsubr (&Simage_extension_data); #if GLYPH_DEBUG defsubr (&Simagep);