comparison src/glyphs-eimage.c @ 4708:1cecc3e9f0a0

Use giflib or libungif to provide GIF support, instead of using internal routines. Delete internal GIF support code with no stated license. Fix up a number of references in the documentation to GIF support. See discussion on xemacs-beta: <87iqg4vg9t.fsf@uwakimon.sk.tsukuba.ac.jp>.
author Jerry James <james@xemacs.org>
date Mon, 05 Oct 2009 10:11:59 -0600
parents a9493cab536f
children b3ea9c582280
comparison
equal deleted inserted replaced
4707:5bb0735f56e0 4708:1cecc3e9f0a0
32 Cleanup/simplification of error handling by Ben Wing for 19.14 32 Cleanup/simplification of error handling by Ben Wing for 19.14
33 GIF support changed to external Gifreader lib by Jareth Hein for 21.0 33 GIF support changed to external Gifreader lib by Jareth Hein for 21.0
34 Many changes for color work and optimizations by Jareth Hein for 21.0 34 Many changes for color work and optimizations by Jareth Hein for 21.0
35 Switch of GIF/JPEG/PNG to new EImage intermediate code by Jareth Hein for 21.0 35 Switch of GIF/JPEG/PNG to new EImage intermediate code by Jareth Hein for 21.0
36 TIFF code by Jareth Hein for 21.0 36 TIFF code by Jareth Hein for 21.0
37 GIF support changed to external giflib by Jerry James for 21.5
37 TODO: 38 TODO:
38 Convert images.el to C and stick it in here? 39 Convert images.el to C and stick it in here?
39 This file is really repetitious; can we refactor? 40 This file is really repetitious; can we refactor?
40 */ 41 */
41 42
525 #ifdef HAVE_GIF 526 #ifdef HAVE_GIF
526 /********************************************************************** 527 /**********************************************************************
527 * GIF * 528 * GIF *
528 **********************************************************************/ 529 **********************************************************************/
529 530
530 #include "gifrlib.h" 531 #include <gif_lib.h>
531 532
532 static void 533 static void
533 gif_validate (Lisp_Object instantiator) 534 gif_validate (Lisp_Object instantiator)
534 { 535 {
535 file_or_data_must_be_present (instantiator); 536 file_or_data_must_be_present (instantiator);
567 568
568 free_opaque_ptr (unwind_obj); 569 free_opaque_ptr (unwind_obj);
569 if (data->giffile) 570 if (data->giffile)
570 { 571 {
571 DGifCloseFile (data->giffile); 572 DGifCloseFile (data->giffile);
572 GifFree(data->giffile); 573 FreeSavedImages(data->giffile);
573 } 574 }
574 if (data->eimage) 575 if (data->eimage)
575 xfree (data->eimage, Binbyte *); 576 xfree (data->eimage, Binbyte *);
576 577
577 return Qnil; 578 return Qnil;
582 Binbyte *bytes; /* The data */ 583 Binbyte *bytes; /* The data */
583 Bytecount len; /* How big is it? */ 584 Bytecount len; /* How big is it? */
584 Bytecount index; /* Where are we? */ 585 Bytecount index; /* Where are we? */
585 } gif_memory_storage; 586 } gif_memory_storage;
586 587
587 static Bytecount 588 static int
588 gif_read_from_memory (GifByteType *buf, Bytecount size, VoidPtr data) 589 gif_read_from_memory (GifFileType *gif, GifByteType *buf, int size)
589 { 590 {
590 gif_memory_storage *mem = (gif_memory_storage *) data; 591 gif_memory_storage *mem = (gif_memory_storage *) gif->UserData;
591 592
592 if (size > (mem->len - mem->index)) 593 if (size > (mem->len - mem->index))
593 return -1; 594 return -1;
594 memcpy (buf, mem->bytes + mem->index, size); 595 memcpy (buf, mem->bytes + mem->index, size);
595 mem->index = mem->index + size; 596 mem->index = mem->index + size;
596 return size; 597 return size;
597 } 598 }
598 599
599 static int 600 static const char *
600 gif_memory_close (VoidPtr UNUSED (data)) 601 gif_decode_error_string ()
601 { 602 {
602 return 0; 603 switch (GifLastError ())
603 } 604 {
604 605 case D_GIF_ERR_OPEN_FAILED:
605 struct gif_error_struct 606 return "GIF error: unable to open";
606 { 607 case D_GIF_ERR_READ_FAILED:
607 const Extbyte *err_str; /* return the error string */ 608 return "GIF error: read failed";
608 jmp_buf setjmp_buffer; /* for return to caller */ 609 case D_GIF_ERR_NOT_GIF_FILE:
609 }; 610 return "GIF error: not a GIF file";
610 611 case D_GIF_ERR_NO_SCRN_DSCR:
611 static void 612 return "GIF error: no Screen Descriptor detected";
612 gif_error_func (const Extbyte *err_str, VoidPtr error_ptr) 613 case D_GIF_ERR_NO_IMAG_DSCR:
613 { 614 return "GIF error: no Image Descriptor detected";
614 struct gif_error_struct *error_data = (struct gif_error_struct *) error_ptr; 615 case D_GIF_ERR_NO_COLOR_MAP:
615 616 return "GIF error: no global or local color map";
616 /* return to setjmp point */ 617 case D_GIF_ERR_WRONG_RECORD:
617 error_data->err_str = err_str; 618 return "GIF error: wrong record type";
618 longjmp (error_data->setjmp_buffer, 1); 619 case D_GIF_ERR_DATA_TOO_BIG:
620 return "GIF error: image is larger than indicated by header";
621 case D_GIF_ERR_NOT_ENOUGH_MEM:
622 return "GIF error: out of memory";
623 case D_GIF_ERR_CLOSE_FAILED:
624 return "GIF error: failed to close file";
625 case D_GIF_ERR_NOT_READABLE:
626 return "GIF error: file is not readable";
627 case D_GIF_ERR_IMAGE_DEFECT:
628 return "GIF error: image is defective";
629 case D_GIF_ERR_EOF_TOO_SOON:
630 return "GIF error: image EOF detected before image complete";
631 default:
632 return "GIF error: unknown error";
633 }
619 } 634 }
620 635
621 static void 636 static void
622 gif_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, 637 gif_instantiate (Lisp_Object image_instance, Lisp_Object instantiator,
623 Lisp_Object pointer_fg, Lisp_Object pointer_bg, 638 Lisp_Object pointer_fg, Lisp_Object pointer_bg,
628 because the unwind-protect is always executed when this 643 because the unwind-protect is always executed when this
629 stack frame is still valid. */ 644 stack frame is still valid. */
630 struct gif_unwind_data unwind; 645 struct gif_unwind_data unwind;
631 int speccount = specpdl_depth (); 646 int speccount = specpdl_depth ();
632 gif_memory_storage mem_struct; 647 gif_memory_storage mem_struct;
633 struct gif_error_struct gif_err;
634 Binbyte *bytes; 648 Binbyte *bytes;
635 Bytecount len; 649 Bytecount len;
636 int height = 0; 650 int height = 0;
637 int width = 0; 651 int width = 0;
638 652
644 { 658 {
645 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); 659 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data);
646 660
647 assert (!NILP (data)); 661 assert (!NILP (data));
648 662
649 if (!(unwind.giffile = GifSetup()))
650 signal_image_error ("Insufficient memory to instantiate GIF image", instantiator);
651
652 /* set up error facilities */
653 if (setjmp(gif_err.setjmp_buffer))
654 {
655 /* An error was signaled. No clean up is needed, as unwind handles that
656 for us. Just pass the error along. */
657 Ibyte *interr;
658 Lisp_Object errstring;
659 EXTERNAL_TO_C_STRING (gif_err.err_str, interr, Qnative);
660 errstring = build_msg_intstring (interr);
661 signal_image_error_2 ("GIF decoding error", errstring, instantiator);
662 }
663 GifSetErrorFunc(unwind.giffile, (Gif_error_func)gif_error_func, (VoidPtr)&gif_err);
664
665 TO_EXTERNAL_FORMAT (LISP_STRING, data, ALLOCA, (bytes, len), Qbinary); 663 TO_EXTERNAL_FORMAT (LISP_STRING, data, ALLOCA, (bytes, len), Qbinary);
666 mem_struct.bytes = bytes; 664 mem_struct.bytes = bytes;
667 mem_struct.len = len; 665 mem_struct.len = len;
668 mem_struct.index = 0; 666 mem_struct.index = 0;
669 GifSetReadFunc(unwind.giffile, gif_read_from_memory, (VoidPtr)&mem_struct); 667 unwind.giffile = DGifOpen (&mem_struct, gif_read_from_memory);
670 GifSetCloseFunc(unwind.giffile, gif_memory_close, (VoidPtr)&mem_struct); 668 if (unwind.giffile == NULL)
671 DGifInitRead(unwind.giffile); 669 signal_image_error (gif_decode_error_string (), instantiator);
672 670
673 /* Then slurp the image into memory, decoding along the way. 671 /* Then slurp the image into memory, decoding along the way.
674 The result is the image in a simple one-byte-per-pixel 672 The result is the image in a simple one-byte-per-pixel
675 format (#### the GIF routines only support 8-bit GIFs, 673 format. */
676 it appears). */ 674 if (DGifSlurp (unwind.giffile) == GIF_ERROR)
677 DGifSlurp (unwind.giffile); 675 signal_image_error (gif_decode_error_string (), instantiator);
678 } 676 }
679 677
680 /* 3. Now create the EImage(s) */ 678 /* 3. Now create the EImage(s) */
681 { 679 {
682 ColorMapObject *cmo = unwind.giffile->SColorMap; 680 ColorMapObject *cmo = unwind.giffile->SColorMap;
746 /* We read the gif successfully. If we have more than one slice then 744 /* We read the gif successfully. If we have more than one slice then
747 animate the gif. */ 745 animate the gif. */
748 if (unwind.giffile->ImageCount > 1) 746 if (unwind.giffile->ImageCount > 1)
749 { 747 {
750 /* See if there is a timeout value. In theory there could be one 748 /* See if there is a timeout value. In theory there could be one
751 for every image - but that makes the implementation way to 749 for every image - but that makes the implementation way too
752 complicated for now so we just take the first. */ 750 complicated for now so we just take the first. */
753 unsigned short timeout = 0; 751 unsigned short timeout = 0;
754 Lisp_Object tid; 752 Lisp_Object tid;
755 753
756 if (unwind.giffile->SavedImages[0].Function == GRAPHICS_EXT_FUNC_CODE 754 if (unwind.giffile->SavedImages[0].Function == GRAPHICS_EXT_FUNC_CODE