Mercurial > emacs
comparison src/image.c @ 90386:2ecafc6d5db7
Revision: emacs@sv.gnu.org/emacs--unicode--0--patch-58
Merge from emacs--devo--0
Patches applied:
* emacs--devo--0 (patch 239-258)
- Update from CVS
- (Ffield_beginning, find_field): Undo change of 2006-04-23.
- Rcirc patch from Ryan Yeske
- Merge from gnus--rel--5.10
- Clean up lisp/gnus/ChangeLog a bit
* gnus--rel--5.10 (patch 91-98)
- Merge from emacs--devo--0
- Update from CVS
author | Miles Bader <miles@gnu.org> |
---|---|
date | Tue, 02 May 2006 05:51:52 +0000 |
parents | 72dea2ff0142 60bff6b0c656 |
children | 146cd8369025 |
comparison
equal
deleted
inserted
replaced
90385:72dea2ff0142 | 90386:2ecafc6d5db7 |
---|---|
601 #ifdef HAVE_X_WINDOWS | 601 #ifdef HAVE_X_WINDOWS |
602 | 602 |
603 /* Useful functions defined in the section | 603 /* Useful functions defined in the section |
604 `Image type independent image structures' below. */ | 604 `Image type independent image structures' below. */ |
605 | 605 |
606 static unsigned long four_corners_best P_ ((XImagePtr ximg, unsigned long width, | 606 static unsigned long four_corners_best P_ ((XImagePtr ximg, |
607 int *corners, | |
608 unsigned long width, | |
607 unsigned long height)); | 609 unsigned long height)); |
608 | 610 |
609 static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height, | 611 static int x_create_x_image_and_pixmap P_ ((struct frame *f, int width, int height, |
610 int depth, XImagePtr *ximg, | 612 int depth, XImagePtr *ximg, |
611 Pixmap *pixmap)); | 613 Pixmap *pixmap)); |
655 { | 657 { |
656 XDestroyImage (ximg); | 658 XDestroyImage (ximg); |
657 return -1; | 659 return -1; |
658 } | 660 } |
659 | 661 |
660 bg = four_corners_best (ximg, width, height); | 662 bg = four_corners_best (ximg, NULL, width, height); |
661 | 663 |
662 for (y = 0; y < ximg->height; ++y) | 664 for (y = 0; y < ximg->height; ++y) |
663 { | 665 { |
664 for (x = 0; x < ximg->width; ++x) | 666 for (x = 0; x < ximg->width; ++x) |
665 { | 667 { |
730 Lisp_Object Qxbm; | 732 Lisp_Object Qxbm; |
731 | 733 |
732 /* Keywords. */ | 734 /* Keywords. */ |
733 | 735 |
734 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile; | 736 extern Lisp_Object QCwidth, QCheight, QCforeground, QCbackground, QCfile; |
735 extern Lisp_Object QCdata, QCtype; | 737 extern Lisp_Object QCdata, QCtype, Qcount; |
736 extern Lisp_Object Qcenter; | 738 extern Lisp_Object Qcenter; |
737 Lisp_Object QCascent, QCmargin, QCrelief; | 739 Lisp_Object QCascent, QCmargin, QCrelief; |
738 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask; | 740 Lisp_Object QCconversion, QCcolor_symbols, QCheuristic_mask; |
739 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask; | 741 Lisp_Object QCindex, QCmatrix, QCcolor_adjustment, QCmask; |
740 | 742 |
1139 error ("Invalid image specification"); | 1141 error ("Invalid image specification"); |
1140 | 1142 |
1141 return mask; | 1143 return mask; |
1142 } | 1144 } |
1143 | 1145 |
1146 DEFUN ("image-extension-data", Fimage_extension_data, Simage_extension_data, 1, 2, 0, | |
1147 doc: /* Return extension data for image SPEC. | |
1148 FRAME is the frame on which the image will be displayed. FRAME nil | |
1149 or omitted means use the selected frame. */) | |
1150 (spec, frame) | |
1151 Lisp_Object spec, frame; | |
1152 { | |
1153 Lisp_Object ext; | |
1154 | |
1155 ext = Qnil; | |
1156 if (valid_image_p (spec)) | |
1157 { | |
1158 struct frame *f = check_x_frame (frame); | |
1159 int id = lookup_image (f, spec); | |
1160 struct image *img = IMAGE_FROM_ID (f, id); | |
1161 ext = img->data.lisp_val; | |
1162 } | |
1163 | |
1164 return ext; | |
1165 } | |
1166 | |
1144 | 1167 |
1145 /*********************************************************************** | 1168 /*********************************************************************** |
1146 Image type independent image structures | 1169 Image type independent image structures |
1147 ***********************************************************************/ | 1170 ***********************************************************************/ |
1148 | 1171 |
1169 xassert (img->type != NULL); | 1192 xassert (img->type != NULL); |
1170 img->spec = spec; | 1193 img->spec = spec; |
1171 img->data.lisp_val = Qnil; | 1194 img->data.lisp_val = Qnil; |
1172 img->ascent = DEFAULT_IMAGE_ASCENT; | 1195 img->ascent = DEFAULT_IMAGE_ASCENT; |
1173 img->hash = hash; | 1196 img->hash = hash; |
1197 img->corners[BOT_CORNER] = -1; /* Full image */ | |
1174 return img; | 1198 return img; |
1175 } | 1199 } |
1176 | 1200 |
1177 | 1201 |
1178 /* Free image IMG which was used on frame F, including its resources. */ | 1202 /* Free image IMG which was used on frame F, including its resources. */ |
1320 | 1344 |
1321 /* Find the "best" corner color of a bitmap. | 1345 /* Find the "best" corner color of a bitmap. |
1322 On W32, XIMG is assumed to a device context with the bitmap selected. */ | 1346 On W32, XIMG is assumed to a device context with the bitmap selected. */ |
1323 | 1347 |
1324 static RGB_PIXEL_COLOR | 1348 static RGB_PIXEL_COLOR |
1325 four_corners_best (ximg, width, height) | 1349 four_corners_best (ximg, corners, width, height) |
1326 XImagePtr_or_DC ximg; | 1350 XImagePtr_or_DC ximg; |
1351 int *corners; | |
1327 unsigned long width, height; | 1352 unsigned long width, height; |
1328 { | 1353 { |
1329 RGB_PIXEL_COLOR corners[4], best; | 1354 RGB_PIXEL_COLOR corner_pixels[4], best; |
1330 int i, best_count; | 1355 int i, best_count; |
1331 | 1356 |
1332 /* Get the colors at the corners of ximg. */ | 1357 if (corners && corners[BOT_CORNER] >= 0) |
1333 corners[0] = GET_PIXEL (ximg, 0, 0); | 1358 { |
1334 corners[1] = GET_PIXEL (ximg, width - 1, 0); | 1359 /* Get the colors at the corner_pixels of ximg. */ |
1335 corners[2] = GET_PIXEL (ximg, width - 1, height - 1); | 1360 corner_pixels[0] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[TOP_CORNER]); |
1336 corners[3] = GET_PIXEL (ximg, 0, height - 1); | 1361 corner_pixels[1] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[TOP_CORNER]); |
1337 | 1362 corner_pixels[2] = GET_PIXEL (ximg, corners[RIGHT_CORNER] - 1, corners[BOT_CORNER] - 1); |
1363 corner_pixels[3] = GET_PIXEL (ximg, corners[LEFT_CORNER], corners[BOT_CORNER] - 1); | |
1364 } | |
1365 else | |
1366 { | |
1367 /* Get the colors at the corner_pixels of ximg. */ | |
1368 corner_pixels[0] = GET_PIXEL (ximg, 0, 0); | |
1369 corner_pixels[1] = GET_PIXEL (ximg, width - 1, 0); | |
1370 corner_pixels[2] = GET_PIXEL (ximg, width - 1, height - 1); | |
1371 corner_pixels[3] = GET_PIXEL (ximg, 0, height - 1); | |
1372 } | |
1338 /* Choose the most frequently found color as background. */ | 1373 /* Choose the most frequently found color as background. */ |
1339 for (i = best_count = 0; i < 4; ++i) | 1374 for (i = best_count = 0; i < 4; ++i) |
1340 { | 1375 { |
1341 int j, n; | 1376 int j, n; |
1342 | 1377 |
1343 for (j = n = 0; j < 4; ++j) | 1378 for (j = n = 0; j < 4; ++j) |
1344 if (corners[i] == corners[j]) | 1379 if (corner_pixels[i] == corner_pixels[j]) |
1345 ++n; | 1380 ++n; |
1346 | 1381 |
1347 if (n > best_count) | 1382 if (n > best_count) |
1348 best = corners[i], best_count = n; | 1383 best = corner_pixels[i], best_count = n; |
1349 } | 1384 } |
1350 | 1385 |
1351 return best; | 1386 return best; |
1352 } | 1387 } |
1353 | 1388 |
1402 release_frame_dc (f, frame_dc); | 1437 release_frame_dc (f, frame_dc); |
1403 prev = SelectObject (ximg, img->pixmap); | 1438 prev = SelectObject (ximg, img->pixmap); |
1404 #endif /* !HAVE_NTGUI */ | 1439 #endif /* !HAVE_NTGUI */ |
1405 } | 1440 } |
1406 | 1441 |
1407 img->background = four_corners_best (ximg, img->width, img->height); | 1442 img->background = four_corners_best (ximg, img->corners, img->width, img->height); |
1408 | 1443 |
1409 if (free_ximg) | 1444 if (free_ximg) |
1410 Destroy_Image (ximg, prev); | 1445 Destroy_Image (ximg, prev); |
1411 | 1446 |
1412 img->background_valid = 1; | 1447 img->background_valid = 1; |
1447 prev = SelectObject (mask, img->mask); | 1482 prev = SelectObject (mask, img->mask); |
1448 #endif /* HAVE_NTGUI */ | 1483 #endif /* HAVE_NTGUI */ |
1449 } | 1484 } |
1450 | 1485 |
1451 img->background_transparent | 1486 img->background_transparent |
1452 = (four_corners_best (mask, img->width, img->height) == PIX_MASK_RETAIN); | 1487 = (four_corners_best (mask, img->corners, img->width, img->height) == PIX_MASK_RETAIN); |
1453 | 1488 |
1454 if (free_mask) | 1489 if (free_mask) |
1455 Destroy_Image (mask, prev); | 1490 Destroy_Image (mask, prev); |
1456 } | 1491 } |
1457 else | 1492 else |
4458 } | 4493 } |
4459 | 4494 |
4460 img->width = width; | 4495 img->width = width; |
4461 img->height = height; | 4496 img->height = height; |
4462 | 4497 |
4498 /* Maybe fill in the background field while we have ximg handy. */ | |
4499 if (NILP (image_spec_value (img->spec, QCbackground, NULL))) | |
4500 IMAGE_BACKGROUND (img, f, ximg); | |
4501 | |
4463 x_put_x_image (f, ximg, img->pixmap, width, height); | 4502 x_put_x_image (f, ximg, img->pixmap, width, height); |
4464 x_destroy_x_image (ximg); | 4503 x_destroy_x_image (ximg); |
4465 if (have_mask) | 4504 if (have_mask) |
4466 { | 4505 { |
4467 /* Fill in the background_transparent field while we have the | 4506 /* Fill in the background_transparent field while we have the |
5352 use_img_background = 0; | 5391 use_img_background = 0; |
5353 } | 5392 } |
5354 } | 5393 } |
5355 | 5394 |
5356 if (use_img_background) | 5395 if (use_img_background) |
5357 bg = four_corners_best (ximg, img->width, img->height); | 5396 bg = four_corners_best (ximg, img->corners, img->width, img->height); |
5358 | 5397 |
5359 /* Set all bits in mask_img to 1 whose color in ximg is different | 5398 /* Set all bits in mask_img to 1 whose color in ximg is different |
5360 from the background color bg. */ | 5399 from the background color bg. */ |
5361 #ifndef HAVE_NTGUI | 5400 #ifndef HAVE_NTGUI |
5362 for (y = 0; y < img->height; ++y) | 5401 for (y = 0; y < img->height; ++y) |
7445 | 7484 |
7446 #if defined (HAVE_GIF) || defined (MAC_OS) | 7485 #if defined (HAVE_GIF) || defined (MAC_OS) |
7447 | 7486 |
7448 static int gif_image_p P_ ((Lisp_Object object)); | 7487 static int gif_image_p P_ ((Lisp_Object object)); |
7449 static int gif_load P_ ((struct frame *f, struct image *img)); | 7488 static int gif_load P_ ((struct frame *f, struct image *img)); |
7489 static void gif_clear_image P_ ((struct frame *f, struct image *img)); | |
7450 | 7490 |
7451 /* The symbol `gif' identifying images of this type. */ | 7491 /* The symbol `gif' identifying images of this type. */ |
7452 | 7492 |
7453 Lisp_Object Qgif; | 7493 Lisp_Object Qgif; |
7454 | 7494 |
7493 static struct image_type gif_type = | 7533 static struct image_type gif_type = |
7494 { | 7534 { |
7495 &Qgif, | 7535 &Qgif, |
7496 gif_image_p, | 7536 gif_image_p, |
7497 gif_load, | 7537 gif_load, |
7498 x_clear_image, | 7538 gif_clear_image, |
7499 NULL | 7539 NULL |
7500 }; | 7540 }; |
7541 | |
7542 /* Free X resources of GIF image IMG which is used on frame F. */ | |
7543 | |
7544 static void | |
7545 gif_clear_image (f, img) | |
7546 struct frame *f; | |
7547 struct image *img; | |
7548 { | |
7549 /* IMG->data.ptr_val may contain extension data. */ | |
7550 img->data.lisp_val = Qnil; | |
7551 x_clear_image (f, img); | |
7552 } | |
7501 | 7553 |
7502 /* Return non-zero if OBJECT is a valid GIF image specification. */ | 7554 /* Return non-zero if OBJECT is a valid GIF image specification. */ |
7503 | 7555 |
7504 static int | 7556 static int |
7505 gif_image_p (object) | 7557 gif_image_p (object) |
7617 ColorMapObject *gif_color_map; | 7669 ColorMapObject *gif_color_map; |
7618 unsigned long pixel_colors[256]; | 7670 unsigned long pixel_colors[256]; |
7619 GifFileType *gif; | 7671 GifFileType *gif; |
7620 struct gcpro gcpro1; | 7672 struct gcpro gcpro1; |
7621 Lisp_Object image; | 7673 Lisp_Object image; |
7622 int ino, image_left, image_top, image_width, image_height; | 7674 int ino, image_height, image_width; |
7623 gif_memory_source memsrc; | 7675 gif_memory_source memsrc; |
7624 unsigned char *raster; | 7676 unsigned char *raster; |
7625 | 7677 |
7626 specified_file = image_spec_value (img->spec, QCfile, NULL); | 7678 specified_file = image_spec_value (img->spec, QCfile, NULL); |
7627 specified_data = image_spec_value (img->spec, QCdata, NULL); | 7679 specified_data = image_spec_value (img->spec, QCdata, NULL); |
7694 fn_DGifCloseFile (gif); | 7746 fn_DGifCloseFile (gif); |
7695 UNGCPRO; | 7747 UNGCPRO; |
7696 return 0; | 7748 return 0; |
7697 } | 7749 } |
7698 | 7750 |
7699 image_top = gif->SavedImages[ino].ImageDesc.Top; | 7751 img->corners[TOP_CORNER] = gif->SavedImages[ino].ImageDesc.Top; |
7700 image_left = gif->SavedImages[ino].ImageDesc.Left; | 7752 img->corners[LEFT_CORNER] = gif->SavedImages[ino].ImageDesc.Left; |
7753 image_height = gif->SavedImages[ino].ImageDesc.Height; | |
7754 img->corners[BOT_CORNER] = img->corners[TOP_CORNER] + image_height; | |
7701 image_width = gif->SavedImages[ino].ImageDesc.Width; | 7755 image_width = gif->SavedImages[ino].ImageDesc.Width; |
7702 image_height = gif->SavedImages[ino].ImageDesc.Height; | 7756 img->corners[RIGHT_CORNER] = img->corners[LEFT_CORNER] + image_width; |
7703 | 7757 |
7704 width = img->width = max (gif->SWidth, | 7758 width = img->width = max (gif->SWidth, |
7705 max (gif->Image.Left + gif->Image.Width, | 7759 max (gif->Image.Left + gif->Image.Width, |
7706 image_left + image_width)); | 7760 img->corners[RIGHT_CORNER])); |
7707 height = img->height = max (gif->SHeight, | 7761 height = img->height = max (gif->SHeight, |
7708 max (gif->Image.Top + gif->Image.Height, | 7762 max (gif->Image.Top + gif->Image.Height, |
7709 image_top + image_height)); | 7763 img->corners[BOT_CORNER])); |
7710 | 7764 |
7711 if (!check_image_size (f, width, height)) | 7765 if (!check_image_size (f, width, height)) |
7712 { | 7766 { |
7713 image_error ("Invalid image size", Qnil, Qnil); | 7767 image_error ("Invalid image size", Qnil, Qnil); |
7714 fn_DGifCloseFile (gif); | 7768 fn_DGifCloseFile (gif); |
7747 /* Clear the part of the screen image that are not covered by | 7801 /* Clear the part of the screen image that are not covered by |
7748 the image from the GIF file. Full animated GIF support | 7802 the image from the GIF file. Full animated GIF support |
7749 requires more than can be done here (see the gif89 spec, | 7803 requires more than can be done here (see the gif89 spec, |
7750 disposal methods). Let's simply assume that the part | 7804 disposal methods). Let's simply assume that the part |
7751 not covered by a sub-image is in the frame's background color. */ | 7805 not covered by a sub-image is in the frame's background color. */ |
7752 for (y = 0; y < image_top; ++y) | 7806 for (y = 0; y < img->corners[TOP_CORNER]; ++y) |
7753 for (x = 0; x < width; ++x) | 7807 for (x = 0; x < width; ++x) |
7754 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); | 7808 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); |
7755 | 7809 |
7756 for (y = image_top + image_height; y < height; ++y) | 7810 for (y = img->corners[BOT_CORNER]; y < height; ++y) |
7757 for (x = 0; x < width; ++x) | 7811 for (x = 0; x < width; ++x) |
7758 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); | 7812 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); |
7759 | 7813 |
7760 for (y = image_top; y < image_top + image_height; ++y) | 7814 for (y = img->corners[TOP_CORNER]; y < img->corners[BOT_CORNER]; ++y) |
7761 { | 7815 { |
7762 for (x = 0; x < image_left; ++x) | 7816 for (x = 0; x < img->corners[LEFT_CORNER]; ++x) |
7763 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); | 7817 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); |
7764 for (x = image_left + image_width; x < width; ++x) | 7818 for (x = img->corners[RIGHT_CORNER]; x < width; ++x) |
7765 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); | 7819 XPutPixel (ximg, x, y, FRAME_BACKGROUND_PIXEL (f)); |
7766 } | 7820 } |
7767 | 7821 |
7768 /* Read the GIF image into the X image. We use a local variable | 7822 /* Read the GIF image into the X image. We use a local variable |
7769 `raster' here because RasterBits below is a char *, and invites | 7823 `raster' here because RasterBits below is a char *, and invites |
7789 } | 7843 } |
7790 | 7844 |
7791 for (x = 0; x < image_width; x++) | 7845 for (x = 0; x < image_width; x++) |
7792 { | 7846 { |
7793 int i = raster[(y * image_width) + x]; | 7847 int i = raster[(y * image_width) + x]; |
7794 XPutPixel (ximg, x + image_left, row + image_top, | 7848 XPutPixel (ximg, x + img->corners[LEFT_CORNER], |
7795 pixel_colors[i]); | 7849 row + img->corners[TOP_CORNER], pixel_colors[i]); |
7796 } | 7850 } |
7797 | 7851 |
7798 row += interlace_increment[pass]; | 7852 row += interlace_increment[pass]; |
7799 } | 7853 } |
7800 } | 7854 } |
7802 { | 7856 { |
7803 for (y = 0; y < image_height; ++y) | 7857 for (y = 0; y < image_height; ++y) |
7804 for (x = 0; x < image_width; ++x) | 7858 for (x = 0; x < image_width; ++x) |
7805 { | 7859 { |
7806 int i = raster[y * image_width + x]; | 7860 int i = raster[y * image_width + x]; |
7807 XPutPixel (ximg, x + image_left, y + image_top, pixel_colors[i]); | 7861 XPutPixel (ximg, x + img->corners[LEFT_CORNER], |
7862 y + img->corners[TOP_CORNER], pixel_colors[i]); | |
7808 } | 7863 } |
7809 } | 7864 } |
7865 | |
7866 /* Save GIF image extension data for `image-extension-data'. | |
7867 Format is (count IMAGES FUNCTION "BYTES" ...). */ | |
7868 img->data.lisp_val = Qnil; | |
7869 if (gif->SavedImages[ino].ExtensionBlockCount > 0) | |
7870 { | |
7871 ExtensionBlock *ext = gif->SavedImages[ino].ExtensionBlocks; | |
7872 for (i = 0; i < gif->SavedImages[ino].ExtensionBlockCount; i++, ext++) | |
7873 /* Append (... FUNCTION "BYTES") */ | |
7874 img->data.lisp_val = Fcons (make_unibyte_string (ext->Bytes, ext->ByteCount), | |
7875 Fcons (make_number (ext->Function), | |
7876 img->data.lisp_val)); | |
7877 img->data.lisp_val = Fnreverse (img->data.lisp_val); | |
7878 } | |
7879 if (gif->ImageCount > 1) | |
7880 img->data.lisp_val = Fcons (Qcount, | |
7881 Fcons (make_number (gif->ImageCount), | |
7882 img->data.lisp_val)); | |
7810 | 7883 |
7811 fn_DGifCloseFile (gif); | 7884 fn_DGifCloseFile (gif); |
7812 | 7885 |
7813 /* Maybe fill in the background field while we have ximg handy. */ | 7886 /* Maybe fill in the background field while we have ximg handy. */ |
7814 if (NILP (image_spec_value (img->spec, QCbackground, NULL))) | 7887 if (NILP (image_spec_value (img->spec, QCbackground, NULL))) |
8551 | 8624 |
8552 defsubr (&Sinit_image_library); | 8625 defsubr (&Sinit_image_library); |
8553 defsubr (&Sclear_image_cache); | 8626 defsubr (&Sclear_image_cache); |
8554 defsubr (&Simage_size); | 8627 defsubr (&Simage_size); |
8555 defsubr (&Simage_mask_p); | 8628 defsubr (&Simage_mask_p); |
8629 defsubr (&Simage_extension_data); | |
8556 | 8630 |
8557 #if GLYPH_DEBUG | 8631 #if GLYPH_DEBUG |
8558 defsubr (&Simagep); | 8632 defsubr (&Simagep); |
8559 defsubr (&Slookup_image); | 8633 defsubr (&Slookup_image); |
8560 #endif | 8634 #endif |