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