mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-06 03:40:56 -08:00
(four_corners_best): New arg CORNERS specifies what pixels
to look at in case image has margin. (x_create_bitmap_mask): Pass NULL for CORNERS to four_corners_best. (image_background, image_background_transparent) (x_build_heuristic_mask): Pass img->corners to four_corners_best. (gif_load): Set img->corners according to image's margin spec. Use img->corners values directly where applicable. Save image extension data in img->data.lisp_val. (gif_clear_image): New function to free img->data.lisp_val. (gif_type): Use it instead of generic x_clear_image. (Fimage_extension_data): New defun. (syms_of_image): Defsubr it.
This commit is contained in:
parent
7b48cc1354
commit
6ac3c7bb02
1 changed files with 101 additions and 31 deletions
132
src/image.c
132
src/image.c
|
|
@ -603,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,
|
||||
|
|
@ -657,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)
|
||||
{
|
||||
|
|
@ -732,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;
|
||||
|
|
@ -1141,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
|
||||
|
|
@ -1171,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;
|
||||
}
|
||||
|
||||
|
|
@ -1322,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;
|
||||
|
|
@ -1404,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);
|
||||
|
|
@ -1449,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);
|
||||
|
|
@ -5358,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. */
|
||||
|
|
@ -7451,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. */
|
||||
|
||||
|
|
@ -7499,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
|
||||
|
|
@ -7623,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;
|
||||
|
||||
|
|
@ -7700,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))
|
||||
{
|
||||
|
|
@ -7753,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));
|
||||
}
|
||||
|
||||
|
|
@ -7795,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];
|
||||
|
|
@ -7808,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. */
|
||||
|
|
@ -8557,6 +8626,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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue