Mercurial > hg > xemacs-beta
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 |