Mercurial > hg > xemacs-beta
annotate src/glyphs-eimage.c @ 5127:a9c41067dd88 ben-lisp-object
more cleanups, terminology clarification, lots of doc work
-------------------- ChangeLog entries follow: --------------------
man/ChangeLog addition:
2010-03-05 Ben Wing <ben@xemacs.org>
* internals/internals.texi (Introduction to Allocation):
* internals/internals.texi (Integers and Characters):
* internals/internals.texi (Allocation from Frob Blocks):
* internals/internals.texi (lrecords):
* internals/internals.texi (Low-level allocation):
Rewrite section on allocation of Lisp objects to reflect the new
reality. Remove references to nonexistent XSETINT and XSETCHAR.
modules/ChangeLog addition:
2010-03-05 Ben Wing <ben@xemacs.org>
* postgresql/postgresql.c (allocate_pgconn):
* postgresql/postgresql.c (allocate_pgresult):
* postgresql/postgresql.h (struct Lisp_PGconn):
* postgresql/postgresql.h (struct Lisp_PGresult):
* ldap/eldap.c (allocate_ldap):
* ldap/eldap.h (struct Lisp_LDAP):
Same changes as in src/ dir. See large log there in ChangeLog,
but basically:
ALLOC_LISP_OBJECT -> ALLOC_NORMAL_LISP_OBJECT
LISP_OBJECT_HEADER -> NORMAL_LISP_OBJECT_HEADER
../hlo/src/ChangeLog addition:
2010-03-05 Ben Wing <ben@xemacs.org>
* alloc.c:
* alloc.c (old_alloc_sized_lcrecord):
* alloc.c (very_old_free_lcrecord):
* alloc.c (copy_lisp_object):
* alloc.c (zero_sized_lisp_object):
* alloc.c (zero_nonsized_lisp_object):
* alloc.c (lisp_object_storage_size):
* alloc.c (free_normal_lisp_object):
* alloc.c (FREE_FIXED_TYPE_WHEN_NOT_IN_GC):
* alloc.c (ALLOC_FROB_BLOCK_LISP_OBJECT):
* alloc.c (Fcons):
* alloc.c (noseeum_cons):
* alloc.c (make_float):
* alloc.c (make_bignum):
* alloc.c (make_bignum_bg):
* alloc.c (make_ratio):
* alloc.c (make_ratio_bg):
* alloc.c (make_ratio_rt):
* alloc.c (make_bigfloat):
* alloc.c (make_bigfloat_bf):
* alloc.c (size_vector):
* alloc.c (make_compiled_function):
* alloc.c (Fmake_symbol):
* alloc.c (allocate_extent):
* alloc.c (allocate_event):
* alloc.c (make_key_data):
* alloc.c (make_button_data):
* alloc.c (make_motion_data):
* alloc.c (make_process_data):
* alloc.c (make_timeout_data):
* alloc.c (make_magic_data):
* alloc.c (make_magic_eval_data):
* alloc.c (make_eval_data):
* alloc.c (make_misc_user_data):
* alloc.c (Fmake_marker):
* alloc.c (noseeum_make_marker):
* alloc.c (size_string_direct_data):
* alloc.c (make_uninit_string):
* alloc.c (make_string_nocopy):
* alloc.c (mark_lcrecord_list):
* alloc.c (alloc_managed_lcrecord):
* alloc.c (free_managed_lcrecord):
* alloc.c (sweep_lcrecords_1):
* alloc.c (malloced_storage_size):
* buffer.c (allocate_buffer):
* buffer.c (compute_buffer_usage):
* buffer.c (DEFVAR_BUFFER_LOCAL_1):
* buffer.c (nuke_all_buffer_slots):
* buffer.c (common_init_complex_vars_of_buffer):
* buffer.h (struct buffer_text):
* buffer.h (struct buffer):
* bytecode.c:
* bytecode.c (make_compiled_function_args):
* bytecode.c (size_compiled_function_args):
* bytecode.h (struct compiled_function_args):
* casetab.c (allocate_case_table):
* casetab.h (struct Lisp_Case_Table):
* charset.h (struct Lisp_Charset):
* chartab.c (fill_char_table):
* chartab.c (Fmake_char_table):
* chartab.c (make_char_table_entry):
* chartab.c (copy_char_table_entry):
* chartab.c (Fcopy_char_table):
* chartab.c (put_char_table):
* chartab.h (struct Lisp_Char_Table_Entry):
* chartab.h (struct Lisp_Char_Table):
* console-gtk-impl.h (struct gtk_device):
* console-gtk-impl.h (struct gtk_frame):
* console-impl.h (struct console):
* console-msw-impl.h (struct Lisp_Devmode):
* console-msw-impl.h (struct mswindows_device):
* console-msw-impl.h (struct msprinter_device):
* console-msw-impl.h (struct mswindows_frame):
* console-msw-impl.h (struct mswindows_dialog_id):
* console-stream-impl.h (struct stream_console):
* console-stream.c (stream_init_console):
* console-tty-impl.h (struct tty_console):
* console-tty-impl.h (struct tty_device):
* console-tty.c (allocate_tty_console_struct):
* console-x-impl.h (struct x_device):
* console-x-impl.h (struct x_frame):
* console.c (allocate_console):
* console.c (nuke_all_console_slots):
* console.c (DEFVAR_CONSOLE_LOCAL_1):
* console.c (common_init_complex_vars_of_console):
* data.c (make_weak_list):
* data.c (make_weak_box):
* data.c (make_ephemeron):
* database.c:
* database.c (struct Lisp_Database):
* database.c (allocate_database):
* database.c (finalize_database):
* device-gtk.c (allocate_gtk_device_struct):
* device-impl.h (struct device):
* device-msw.c:
* device-msw.c (mswindows_init_device):
* device-msw.c (msprinter_init_device):
* device-msw.c (finalize_devmode):
* device-msw.c (allocate_devmode):
* device-tty.c (allocate_tty_device_struct):
* device-x.c (allocate_x_device_struct):
* device.c:
* device.c (nuke_all_device_slots):
* device.c (allocate_device):
* dialog-msw.c (handle_question_dialog_box):
* elhash.c:
* elhash.c (struct Lisp_Hash_Table):
* elhash.c (finalize_hash_table):
* elhash.c (make_general_lisp_hash_table):
* elhash.c (Fcopy_hash_table):
* elhash.h (htentry):
* emacs.c (main_1):
* eval.c:
* eval.c (size_multiple_value):
* event-stream.c (finalize_command_builder):
* event-stream.c (allocate_command_builder):
* event-stream.c (free_command_builder):
* event-stream.c (event_stream_generate_wakeup):
* event-stream.c (event_stream_resignal_wakeup):
* event-stream.c (event_stream_disable_wakeup):
* event-stream.c (event_stream_wakeup_pending_p):
* events.h (struct Lisp_Timeout):
* events.h (struct command_builder):
* extents-impl.h:
* extents-impl.h (struct extent_auxiliary):
* extents-impl.h (struct extent_info):
* extents-impl.h (set_extent_no_chase_aux_field):
* extents-impl.h (set_extent_no_chase_normal_field):
* extents.c:
* extents.c (gap_array_marker):
* extents.c (gap_array):
* extents.c (extent_list_marker):
* extents.c (extent_list):
* extents.c (stack_of_extents):
* extents.c (gap_array_make_marker):
* extents.c (extent_list_make_marker):
* extents.c (allocate_extent_list):
* extents.c (SLOT):
* extents.c (mark_extent_auxiliary):
* extents.c (allocate_extent_auxiliary):
* extents.c (attach_extent_auxiliary):
* extents.c (size_gap_array):
* extents.c (finalize_extent_info):
* extents.c (allocate_extent_info):
* extents.c (uninit_buffer_extents):
* extents.c (allocate_soe):
* extents.c (copy_extent):
* extents.c (vars_of_extents):
* extents.h:
* faces.c (allocate_face):
* faces.h (struct Lisp_Face):
* faces.h (struct face_cachel):
* file-coding.c:
* file-coding.c (finalize_coding_system):
* file-coding.c (sizeof_coding_system):
* file-coding.c (Fcopy_coding_system):
* file-coding.h (struct Lisp_Coding_System):
* file-coding.h (MARKED_SLOT):
* fns.c (size_bit_vector):
* font-mgr.c:
* font-mgr.c (finalize_fc_pattern):
* font-mgr.c (print_fc_pattern):
* font-mgr.c (Ffc_pattern_p):
* font-mgr.c (Ffc_pattern_create):
* font-mgr.c (Ffc_name_parse):
* font-mgr.c (Ffc_name_unparse):
* font-mgr.c (Ffc_pattern_duplicate):
* font-mgr.c (Ffc_pattern_add):
* font-mgr.c (Ffc_pattern_del):
* font-mgr.c (Ffc_pattern_get):
* font-mgr.c (fc_config_create_using):
* font-mgr.c (fc_strlist_to_lisp_using):
* font-mgr.c (fontset_to_list):
* font-mgr.c (Ffc_config_p):
* font-mgr.c (Ffc_config_up_to_date):
* font-mgr.c (Ffc_config_build_fonts):
* font-mgr.c (Ffc_config_get_cache):
* font-mgr.c (Ffc_config_get_fonts):
* font-mgr.c (Ffc_config_set_current):
* font-mgr.c (Ffc_config_get_blanks):
* font-mgr.c (Ffc_config_get_rescan_interval):
* font-mgr.c (Ffc_config_set_rescan_interval):
* font-mgr.c (Ffc_config_app_font_add_file):
* font-mgr.c (Ffc_config_app_font_add_dir):
* font-mgr.c (Ffc_config_app_font_clear):
* font-mgr.c (size):
* font-mgr.c (Ffc_config_substitute):
* font-mgr.c (Ffc_font_render_prepare):
* font-mgr.c (Ffc_font_match):
* font-mgr.c (Ffc_font_sort):
* font-mgr.c (finalize_fc_config):
* font-mgr.c (print_fc_config):
* font-mgr.h:
* font-mgr.h (struct fc_pattern):
* font-mgr.h (XFC_PATTERN):
* font-mgr.h (struct fc_config):
* font-mgr.h (XFC_CONFIG):
* frame-gtk.c (allocate_gtk_frame_struct):
* frame-impl.h (struct frame):
* frame-msw.c (mswindows_init_frame_1):
* frame-x.c (allocate_x_frame_struct):
* frame.c (nuke_all_frame_slots):
* frame.c (allocate_frame_core):
* gc.c:
* gc.c (GC_CHECK_NOT_FREE):
* glyphs.c (finalize_image_instance):
* glyphs.c (allocate_image_instance):
* glyphs.c (Fcolorize_image_instance):
* glyphs.c (allocate_glyph):
* glyphs.c (unmap_subwindow_instance_cache_mapper):
* glyphs.c (register_ignored_expose):
* glyphs.h (struct Lisp_Image_Instance):
* glyphs.h (struct Lisp_Glyph):
* glyphs.h (struct glyph_cachel):
* glyphs.h (struct expose_ignore):
* gui.c (allocate_gui_item):
* gui.h (struct Lisp_Gui_Item):
* keymap.c (struct Lisp_Keymap):
* keymap.c (make_keymap):
* lisp.h:
* lisp.h (struct Lisp_String_Direct_Data):
* lisp.h (struct Lisp_String_Indirect_Data):
* lisp.h (struct Lisp_Vector):
* lisp.h (struct Lisp_Bit_Vector):
* lisp.h (DECLARE_INLINE_LISP_BIT_VECTOR):
* lisp.h (struct weak_box):
* lisp.h (struct ephemeron):
* lisp.h (struct weak_list):
* lrecord.h:
* lrecord.h (struct lrecord_implementation):
* lrecord.h (MC_ALLOC_CALL_FINALIZER):
* lrecord.h (struct lcrecord_list):
* lstream.c (finalize_lstream):
* lstream.c (sizeof_lstream):
* lstream.c (Lstream_new):
* lstream.c (Lstream_delete):
* lstream.h (struct lstream):
* marker.c:
* marker.c (finalize_marker):
* marker.c (compute_buffer_marker_usage):
* mule-charset.c:
* mule-charset.c (make_charset):
* mule-charset.c (compute_charset_usage):
* objects-impl.h (struct Lisp_Color_Instance):
* objects-impl.h (struct Lisp_Font_Instance):
* objects-tty-impl.h (struct tty_color_instance_data):
* objects-tty-impl.h (struct tty_font_instance_data):
* objects-tty.c (tty_initialize_color_instance):
* objects-tty.c (tty_initialize_font_instance):
* objects.c (finalize_color_instance):
* objects.c (Fmake_color_instance):
* objects.c (finalize_font_instance):
* objects.c (Fmake_font_instance):
* objects.c (reinit_vars_of_objects):
* opaque.c:
* opaque.c (sizeof_opaque):
* opaque.c (make_opaque_ptr):
* opaque.c (free_opaque_ptr):
* opaque.h:
* opaque.h (Lisp_Opaque):
* opaque.h (Lisp_Opaque_Ptr):
* print.c (printing_unreadable_lcrecord):
* print.c (external_object_printer):
* print.c (debug_p4):
* process.c (finalize_process):
* process.c (make_process_internal):
* procimpl.h (struct Lisp_Process):
* rangetab.c (Fmake_range_table):
* rangetab.c (Fcopy_range_table):
* rangetab.h (struct Lisp_Range_Table):
* scrollbar.c:
* scrollbar.c (create_scrollbar_instance):
* scrollbar.c (compute_scrollbar_instance_usage):
* scrollbar.h (struct scrollbar_instance):
* specifier.c (finalize_specifier):
* specifier.c (sizeof_specifier):
* specifier.c (set_specifier_caching):
* specifier.h (struct Lisp_Specifier):
* specifier.h (struct specifier_caching):
* symeval.h:
* symeval.h (SYMBOL_VALUE_MAGIC_P):
* symeval.h (DEFVAR_SYMVAL_FWD):
* symsinit.h:
* syntax.c (init_buffer_syntax_cache):
* syntax.h (struct syntax_cache):
* toolbar.c:
* toolbar.c (allocate_toolbar_button):
* toolbar.c (update_toolbar_button):
* toolbar.h (struct toolbar_button):
* tooltalk.c (struct Lisp_Tooltalk_Message):
* tooltalk.c (make_tooltalk_message):
* tooltalk.c (struct Lisp_Tooltalk_Pattern):
* tooltalk.c (make_tooltalk_pattern):
* ui-gtk.c:
* ui-gtk.c (allocate_ffi_data):
* ui-gtk.c (emacs_gtk_object_finalizer):
* ui-gtk.c (allocate_emacs_gtk_object_data):
* ui-gtk.c (allocate_emacs_gtk_boxed_data):
* ui-gtk.h:
* window-impl.h (struct window):
* window-impl.h (struct window_mirror):
* window.c (finalize_window):
* window.c (allocate_window):
* window.c (new_window_mirror):
* window.c (mark_window_as_deleted):
* window.c (make_dummy_parent):
* window.c (compute_window_mirror_usage):
* window.c (compute_window_usage):
Overall point of this change and previous ones in this repository:
(1) Introduce new, clearer terminology: everything other than int
or char is a "record" object, which comes in two types: "normal
objects" and "frob-block objects". Fix up all places that
referred to frob-block objects as "simple", "basic", etc.
(2) Provide an advertised interface for doing operations on Lisp
objects, including creating new types, that is clean and
consistent in its naming, uses the above-referenced terms and
avoids referencing "lrecords", "old lcrecords", etc., which should
hide under the surface.
(3) Make the size_in_bytes and finalizer methods take a
Lisp_Object rather than a void * for consistency with other methods.
(4) Separate finalizer method into finalizer and disksaver, so
that normal finalize methods don't have to worry about disksaving.
Other specifics:
(1) Renaming:
LISP_OBJECT_HEADER -> NORMAL_LISP_OBJECT_HEADER
ALLOC_LISP_OBJECT -> ALLOC_NORMAL_LISP_OBJECT
implementation->basic_p -> implementation->frob_block_p
ALLOCATE_FIXED_TYPE_AND_SET_IMPL -> ALLOC_FROB_BLOCK_LISP_OBJECT
*FCCONFIG*, wrap_fcconfig -> *FC_CONFIG*, wrap_fc_config
*FCPATTERN*, wrap_fcpattern -> *FC_PATTERN*, wrap_fc_pattern
(the last two changes make the naming of these macros consistent
with the naming of all other macros, since the objects are named
fc-config and fc-pattern with a hyphen)
(2) Lots of documentation fixes in lrecord.h.
(3) Eliminate macros for copying, freeing, zeroing objects, getting
their storage size. Instead, new functions:
zero_sized_lisp_object()
zero_nonsized_lisp_object()
lisp_object_storage_size()
free_normal_lisp_object()
(copy_lisp_object() already exists)
LISP_OBJECT_FROB_BLOCK_P() (actually a macro)
Eliminated:
free_lrecord()
zero_lrecord()
copy_lrecord()
copy_sized_lrecord()
old_copy_lcrecord()
old_copy_sized_lcrecord()
old_zero_lcrecord()
old_zero_sized_lcrecord()
LISP_OBJECT_STORAGE_SIZE()
COPY_SIZED_LISP_OBJECT()
COPY_SIZED_LCRECORD()
COPY_LISP_OBJECT()
ZERO_LISP_OBJECT()
FREE_LISP_OBJECT()
(4) Catch the remaining places where lrecord stuff was used directly
and use the advertised interface, e.g. alloc_sized_lrecord() ->
ALLOC_SIZED_LISP_OBJECT().
(5) Make certain statically-declared pseudo-objects
(buffer_local_flags, console_local_flags) have their lheader
initialized correctly, so things like copy_lisp_object() can work
on them. Make extent_auxiliary_defaults a proper heap object
Vextent_auxiliary_defaults, and make extent auxiliaries dumpable
so that this object can be dumped. allocate_extent_auxiliary()
now just creates the object, and attach_extent_auxiliary()
creates an extent auxiliary and attaches to an extent, like the
old allocate_extent_auxiliary().
(6) Create EXTENT_AUXILIARY_SLOTS macro, similar to the foo-slots.h
files but in a macro instead of a file. The purpose is to avoid
duplication when iterating over all the slots in an extent auxiliary.
Use it.
(7) In lstream.c, don't zero out object after allocation because
allocation routines take care of this.
(8) In marker.c, fix a mistake in computing marker overhead.
(9) In print.c, clean up printing_unreadable_lcrecord(),
external_object_printer() to avoid lots of ifdef NEW_GC's.
(10) Separate toolbar-button allocation into a separate
allocate_toolbar_button() function for use in the example code
in lrecord.h.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Fri, 05 Mar 2010 04:08:17 -0600 |
parents | 7e57c0575a15 |
children | 6c6d78781d59 8b2f75cecb89 |
rev | line source |
---|---|
428 | 1 /* EImage-specific Lisp objects. |
2 Copyright (C) 1993, 1994, 1998 Free Software Foundation, Inc. | |
3 Copyright (C) 1995 Board of Trustees, University of Illinois. | |
4 Copyright (C) 1995 Tinker Systems | |
2959 | 5 Copyright (C) 1995, 1996, 2001, 2002, 2004, 2005 Ben Wing |
428 | 6 Copyright (C) 1995 Sun Microsystems |
7 | |
8 This file is part of XEmacs. | |
9 | |
10 XEmacs is free software; you can redistribute it and/or modify it | |
11 under the terms of the GNU General Public License as published by the | |
12 Free Software Foundation; either version 2, or (at your option) any | |
13 later version. | |
14 | |
15 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
17 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
18 for more details. | |
19 | |
20 You should have received a copy of the GNU General Public License | |
21 along with XEmacs; see the file COPYING. If not, write to | |
22 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
23 Boston, MA 02111-1307, USA. */ | |
24 | |
25 /* Synched up with: Not in FSF. */ | |
26 | |
2959 | 27 /* Originally part of glyphs.c. |
28 | |
428 | 29 GIF/JPEG support added by Ben Wing for 19.14 |
30 PNG support added by Bill Perry for 19.14 | |
31 Improved GIF/JPEG support added by Bill Perry 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 | |
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 | |
36 TIFF code by Jareth Hein for 21.0 | |
4708
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
37 GIF support changed to external giflib by Jerry James for 21.5 |
428 | 38 TODO: |
39 Convert images.el to C and stick it in here? | |
3094 | 40 This file is really repetitious; can we refactor? |
428 | 41 */ |
42 | |
43 #include <config.h> | |
44 #include "lisp.h" | |
45 #include "lstream.h" | |
46 #include "console.h" | |
872 | 47 #include "device-impl.h" |
428 | 48 #include "faces.h" |
49 #include "glyphs.h" | |
872 | 50 #include "objects-impl.h" |
428 | 51 |
52 #include "buffer.h" | |
53 #include "frame.h" | |
54 #include "opaque.h" | |
442 | 55 #include "window.h" |
428 | 56 |
57 #include "sysfile.h" | |
58 | |
59 #ifdef HAVE_PNG | |
1743 | 60 |
61 BEGIN_C_DECLS | |
62 | |
647 | 63 #define message message_ /* Yuck */ |
428 | 64 #include <png.h> |
647 | 65 #undef message |
1743 | 66 |
67 END_C_DECLS | |
68 | |
428 | 69 #else |
70 #include <setjmp.h> | |
71 #endif | |
72 #include "file-coding.h" | |
73 | |
74 #ifdef HAVE_TIFF | |
75 DEFINE_IMAGE_INSTANTIATOR_FORMAT (tiff); | |
76 Lisp_Object Qtiff; | |
77 #endif | |
78 | |
79 #ifdef HAVE_JPEG | |
80 DEFINE_IMAGE_INSTANTIATOR_FORMAT (jpeg); | |
81 Lisp_Object Qjpeg; | |
82 #endif | |
83 | |
84 #ifdef HAVE_GIF | |
85 DEFINE_IMAGE_INSTANTIATOR_FORMAT (gif); | |
86 Lisp_Object Qgif; | |
87 #endif | |
88 | |
89 #ifdef HAVE_PNG | |
90 DEFINE_IMAGE_INSTANTIATOR_FORMAT (png); | |
91 Lisp_Object Qpng; | |
92 #endif | |
93 | |
94 | |
95 #ifdef HAVE_JPEG | |
96 | |
97 /********************************************************************** | |
98 * JPEG * | |
99 **********************************************************************/ | |
100 | |
1743 | 101 BEGIN_C_DECLS |
102 | |
4854 | 103 #ifdef WIN32_ANY |
104 /* #### Yuck! More horrifitude. tiffio.h, below, and sysfile.h above, | |
105 include <windows.h>, which defines INT32 and INT16, the former | |
106 differently and incompatibly from jmorecfg.h, included by jpeglib.h. We | |
107 can disable the stuff in jmorecfg.h by defining XMD_H (clever, huh?); | |
108 then we define these typedefs the way that <windows.h> wants them (which | |
109 is more correct, anyway; jmorecfg.h defines INT32 as `long'). */ | |
2500 | 110 #define XMD_H |
111 typedef signed int INT32; | |
112 typedef signed short INT16; | |
4326
a5ff7e67ac1b
Don't let libtiff override the size of a boolean, Win32. From Ron Isaacson.
Aidan Kehoe <kehoea@parhasard.net>
parents:
3839
diff
changeset
|
113 |
a5ff7e67ac1b
Don't let libtiff override the size of a boolean, Win32. From Ron Isaacson.
Aidan Kehoe <kehoea@parhasard.net>
parents:
3839
diff
changeset
|
114 /* And another one... jmorecfg.h defines the 'boolean' type as int, |
a5ff7e67ac1b
Don't let libtiff override the size of a boolean, Win32. From Ron Isaacson.
Aidan Kehoe <kehoea@parhasard.net>
parents:
3839
diff
changeset
|
115 which conflicts with the standard Windows 'boolean' definition as |
a5ff7e67ac1b
Don't let libtiff override the size of a boolean, Win32. From Ron Isaacson.
Aidan Kehoe <kehoea@parhasard.net>
parents:
3839
diff
changeset
|
116 unsigned char. Ref: http://www.asmail.be/msg0054688232.html */ |
a5ff7e67ac1b
Don't let libtiff override the size of a boolean, Win32. From Ron Isaacson.
Aidan Kehoe <kehoea@parhasard.net>
parents:
3839
diff
changeset
|
117 #ifndef __RPCNDR_H__ /* don't conflict if rpcndr.h already read */ |
a5ff7e67ac1b
Don't let libtiff override the size of a boolean, Win32. From Ron Isaacson.
Aidan Kehoe <kehoea@parhasard.net>
parents:
3839
diff
changeset
|
118 typedef unsigned char boolean; |
a5ff7e67ac1b
Don't let libtiff override the size of a boolean, Win32. From Ron Isaacson.
Aidan Kehoe <kehoea@parhasard.net>
parents:
3839
diff
changeset
|
119 #endif |
a5ff7e67ac1b
Don't let libtiff override the size of a boolean, Win32. From Ron Isaacson.
Aidan Kehoe <kehoea@parhasard.net>
parents:
3839
diff
changeset
|
120 #define HAVE_BOOLEAN /* prevent jmorecfg.h from redefining it */ |
2500 | 121 #endif |
122 | |
5009
2eec7322eb7f
Miscellaneous small fixes to Windows VS6 build
Vin Shelton <acs@xemacs.org>
parents:
4982
diff
changeset
|
123 /* Yet more breakage... jmorecfg.h unconditionally defines FAR either as |
2eec7322eb7f
Miscellaneous small fixes to Windows VS6 build
Vin Shelton <acs@xemacs.org>
parents:
4982
diff
changeset
|
124 "far" or as blank. Windef.h unconditionally defines FAR as "far". |
2eec7322eb7f
Miscellaneous small fixes to Windows VS6 build
Vin Shelton <acs@xemacs.org>
parents:
4982
diff
changeset
|
125 We'll avoid the compile warning by redefing FAR the way windows defines it, |
2eec7322eb7f
Miscellaneous small fixes to Windows VS6 build
Vin Shelton <acs@xemacs.org>
parents:
4982
diff
changeset
|
126 after loading the JPEG headers. */ |
2eec7322eb7f
Miscellaneous small fixes to Windows VS6 build
Vin Shelton <acs@xemacs.org>
parents:
4982
diff
changeset
|
127 #undef FAR |
428 | 128 #include <jpeglib.h> |
129 #include <jerror.h> | |
5009
2eec7322eb7f
Miscellaneous small fixes to Windows VS6 build
Vin Shelton <acs@xemacs.org>
parents:
4982
diff
changeset
|
130 #undef FAR |
2eec7322eb7f
Miscellaneous small fixes to Windows VS6 build
Vin Shelton <acs@xemacs.org>
parents:
4982
diff
changeset
|
131 #define FAR far |
1743 | 132 |
133 END_C_DECLS | |
428 | 134 |
135 /*#define USE_TEMP_FILES_FOR_JPEG_IMAGES 1*/ | |
136 static void | |
137 jpeg_validate (Lisp_Object instantiator) | |
138 { | |
139 file_or_data_must_be_present (instantiator); | |
140 } | |
141 | |
142 static Lisp_Object | |
442 | 143 jpeg_normalize (Lisp_Object inst, Lisp_Object console_type, |
2286 | 144 Lisp_Object UNUSED (dest_mask)) |
428 | 145 { |
146 return simple_image_type_normalize (inst, console_type, Qjpeg); | |
147 } | |
148 | |
149 static int | |
150 jpeg_possible_dest_types (void) | |
151 { | |
152 return IMAGE_COLOR_PIXMAP_MASK; | |
153 } | |
154 | |
155 /* To survive the otherwise baffling complexity of making sure | |
156 everything gets cleaned up in the presence of an error, we | |
157 use an unwind_protect(). */ | |
158 | |
159 struct jpeg_unwind_data | |
160 { | |
161 /* Stream that we need to close */ | |
162 FILE *instream; | |
163 /* Object that holds state info for JPEG decoding */ | |
164 struct jpeg_decompress_struct *cinfo_ptr; | |
165 /* EImage data */ | |
2367 | 166 Binbyte *eimage; |
428 | 167 }; |
168 | |
169 static Lisp_Object | |
170 jpeg_instantiate_unwind (Lisp_Object unwind_obj) | |
171 { | |
172 struct jpeg_unwind_data *data = | |
173 (struct jpeg_unwind_data *) get_opaque_ptr (unwind_obj); | |
174 | |
175 free_opaque_ptr (unwind_obj); | |
176 if (data->cinfo_ptr) | |
177 jpeg_destroy_decompress (data->cinfo_ptr); | |
178 | |
179 if (data->instream) | |
771 | 180 retry_fclose (data->instream); |
428 | 181 |
1726 | 182 if (data->eimage) |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
183 xfree (data->eimage); |
428 | 184 |
185 return Qnil; | |
186 } | |
187 | |
188 /* | |
189 * ERROR HANDLING: | |
190 * | |
191 * The JPEG library's standard error handler (jerror.c) is divided into | |
192 * several "methods" which you can override individually. This lets you | |
193 * adjust the behavior without duplicating a lot of code, which you might | |
194 * have to update with each future release. | |
195 * | |
196 * Our example here shows how to override the "error_exit" method so that | |
197 * control is returned to the library's caller when a fatal error occurs, | |
198 * rather than calling exit() as the standard error_exit method does. | |
199 * | |
200 * We use C's setjmp/longjmp facility to return control. This means that the | |
201 * routine which calls the JPEG library must first execute a setjmp() call to | |
202 * establish the return point. We want the replacement error_exit to do a | |
203 * longjmp(). But we need to make the setjmp buffer accessible to the | |
204 * error_exit routine. To do this, we make a private extension of the | |
205 * standard JPEG error handler object. (If we were using C++, we'd say we | |
206 * were making a subclass of the regular error handler.) | |
207 * | |
208 * Here's the extended error handler struct: | |
209 */ | |
210 | |
211 struct my_jpeg_error_mgr | |
212 { | |
213 struct jpeg_error_mgr pub; /* "public" fields */ | |
214 jmp_buf setjmp_buffer; /* for return to caller */ | |
215 }; | |
216 | |
217 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61) | |
218 METHODDEF(void) | |
219 #else | |
220 METHODDEF void | |
221 #endif | |
2286 | 222 our_init_source (j_decompress_ptr UNUSED (cinfo)) |
428 | 223 { |
224 } | |
225 | |
226 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61) | |
227 METHODDEF(boolean) | |
228 #else | |
229 METHODDEF boolean | |
230 #endif | |
231 our_fill_input_buffer (j_decompress_ptr cinfo) | |
232 { | |
233 /* Insert a fake EOI marker */ | |
234 struct jpeg_source_mgr *src = cinfo->src; | |
235 static JOCTET buffer[2]; | |
236 | |
237 buffer[0] = (JOCTET) 0xFF; | |
238 buffer[1] = (JOCTET) JPEG_EOI; | |
239 | |
240 src->next_input_byte = buffer; | |
241 src->bytes_in_buffer = 2; | |
242 return TRUE; | |
243 } | |
244 | |
245 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61) | |
246 METHODDEF(void) | |
247 #else | |
248 METHODDEF void | |
249 #endif | |
250 our_skip_input_data (j_decompress_ptr cinfo, long num_bytes) | |
251 { | |
252 struct jpeg_source_mgr *src = NULL; | |
253 | |
254 src = (struct jpeg_source_mgr *) cinfo->src; | |
255 | |
256 if (!src) | |
647 | 257 return; |
258 else if (num_bytes > (long) src->bytes_in_buffer) | |
428 | 259 { |
647 | 260 ERREXIT (cinfo, JERR_INPUT_EOF); |
261 /*NOTREACHED*/ | |
262 } | |
428 | 263 |
264 src->bytes_in_buffer -= num_bytes; | |
265 src->next_input_byte += num_bytes; | |
266 } | |
267 | |
268 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61) | |
269 METHODDEF(void) | |
270 #else | |
271 METHODDEF void | |
272 #endif | |
2286 | 273 our_term_source (j_decompress_ptr UNUSED (cinfo)) |
428 | 274 { |
275 } | |
276 | |
277 typedef struct | |
278 { | |
279 struct jpeg_source_mgr pub; | |
280 } our_jpeg_source_mgr; | |
281 | |
282 static void | |
665 | 283 jpeg_memory_src (j_decompress_ptr cinfo, JOCTET *data, Bytecount len) |
428 | 284 { |
285 struct jpeg_source_mgr *src; | |
286 | |
287 if (cinfo->src == NULL) | |
288 { /* first time for this JPEG object? */ | |
289 cinfo->src = (struct jpeg_source_mgr *) | |
290 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, | |
291 sizeof(our_jpeg_source_mgr)); | |
292 src = (struct jpeg_source_mgr *) cinfo->src; | |
293 src->next_input_byte = data; | |
294 } | |
295 src = (struct jpeg_source_mgr *) cinfo->src; | |
296 src->init_source = our_init_source; | |
297 src->fill_input_buffer = our_fill_input_buffer; | |
298 src->skip_input_data = our_skip_input_data; | |
299 src->resync_to_restart = jpeg_resync_to_restart; /* use default method */ | |
300 src->term_source = our_term_source; | |
301 src->bytes_in_buffer = len; | |
302 src->next_input_byte = data; | |
303 } | |
304 | |
305 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61) | |
306 METHODDEF(void) | |
307 #else | |
308 METHODDEF void | |
309 #endif | |
310 my_jpeg_error_exit (j_common_ptr cinfo) | |
311 { | |
312 /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */ | |
313 struct my_jpeg_error_mgr *myerr = (struct my_jpeg_error_mgr *) cinfo->err; | |
314 | |
315 /* Return control to the setjmp point */ | |
316 longjmp (myerr->setjmp_buffer, 1); | |
317 } | |
318 | |
319 #if defined(JPEG_LIB_VERSION) && (JPEG_LIB_VERSION >= 61) | |
320 METHODDEF(void) | |
321 #else | |
322 METHODDEF void | |
323 #endif | |
324 my_jpeg_output_message (j_common_ptr cinfo) | |
325 { | |
771 | 326 Extbyte buffer[JMSG_LENGTH_MAX]; |
867 | 327 Ibyte *intbuf; |
428 | 328 |
329 /* Create the message */ | |
330 (*cinfo->err->format_message) (cinfo, buffer); | |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
331 intbuf = EXTERNAL_TO_ITEXT (buffer, Qjpeg_error_message_encoding); |
771 | 332 warn_when_safe (Qjpeg, Qinfo, "%s", intbuf); |
428 | 333 } |
334 | |
335 /* The code in this routine is based on example.c from the JPEG library | |
336 source code and from gif_instantiate() */ | |
337 static void | |
338 jpeg_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
2959 | 339 Lisp_Object pointer_fg, Lisp_Object pointer_bg, |
428 | 340 int dest_mask, Lisp_Object domain) |
341 { | |
440 | 342 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
428 | 343 /* It is OK for the unwind data to be local to this function, |
344 because the unwind-protect is always executed when this | |
345 stack frame is still valid. */ | |
346 struct jpeg_unwind_data unwind; | |
347 int speccount = specpdl_depth (); | |
348 | |
349 /* This struct contains the JPEG decompression parameters and pointers to | |
350 * working space (which is allocated as needed by the JPEG library). | |
351 */ | |
352 struct jpeg_decompress_struct cinfo; | |
353 /* We use our private extension JPEG error handler. | |
354 * Note that this struct must live as long as the main JPEG parameter | |
355 * struct, to avoid dangling-pointer problems. | |
356 */ | |
357 struct my_jpeg_error_mgr jerr; | |
358 | |
359 /* Step -1: First record our unwind-protect, which will clean up after | |
360 any exit, normal or not */ | |
361 | |
362 xzero (unwind); | |
363 record_unwind_protect (jpeg_instantiate_unwind, make_opaque_ptr (&unwind)); | |
364 | |
365 /* Step 1: allocate and initialize JPEG decompression object */ | |
366 | |
367 /* We set up the normal JPEG error routines, then override error_exit. */ | |
368 cinfo.err = jpeg_std_error (&jerr.pub); | |
369 jerr.pub.error_exit = my_jpeg_error_exit; | |
370 jerr.pub.output_message = my_jpeg_output_message; | |
371 | |
372 /* Establish the setjmp return context for my_error_exit to use. */ | |
373 if (setjmp (jerr.setjmp_buffer)) | |
374 { | |
375 /* If we get here, the JPEG code has signaled an error. | |
376 * We need to clean up the JPEG object, close the input file, and return. | |
377 */ | |
378 | |
379 { | |
380 Lisp_Object errstring; | |
771 | 381 Extbyte buffer[JMSG_LENGTH_MAX]; |
428 | 382 |
383 /* Create the message */ | |
384 (*cinfo.err->format_message) ((j_common_ptr) &cinfo, buffer); | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
4952
diff
changeset
|
385 errstring = build_extstring (buffer, Qjpeg_error_message_encoding); |
428 | 386 |
387 signal_image_error_2 ("JPEG decoding error", | |
388 errstring, instantiator); | |
389 } | |
390 } | |
391 | |
392 /* Now we can initialize the JPEG decompression object. */ | |
393 jpeg_create_decompress (&cinfo); | |
394 unwind.cinfo_ptr = &cinfo; | |
395 | |
396 /* Step 2: specify data source (eg, a file) */ | |
397 | |
398 { | |
399 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
2367 | 400 const Binbyte *bytes; |
665 | 401 Bytecount len; |
428 | 402 |
403 /* #### This is a definite problem under Mule due to the amount of | |
404 stack data it might allocate. Need to be able to convert and | |
405 write out to a file. */ | |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
406 LISP_STRING_TO_SIZED_EXTERNAL (data, bytes, len, Qbinary); |
428 | 407 jpeg_memory_src (&cinfo, (JOCTET *) bytes, len); |
408 } | |
409 | |
410 /* Step 3: read file parameters with jpeg_read_header() */ | |
411 | |
412 jpeg_read_header (&cinfo, TRUE); | |
413 /* We can ignore the return value from jpeg_read_header since | |
414 * (a) suspension is not possible with the stdio data source, and | |
415 * (b) we passed TRUE to reject a tables-only JPEG file as an error. | |
416 * See libjpeg.doc for more info. | |
417 */ | |
418 | |
419 { | |
4646
6c6bfdb80a0c
Prevent integer overflow and subsequent crashes when attempting to load large
Jerry James <james@xemacs.org>
parents:
4326
diff
changeset
|
420 UINT_64_BIT pixels_sq; |
428 | 421 int jpeg_gray = 0; /* if we're dealing with a grayscale */ |
422 /* Step 4: set parameters for decompression. */ | |
423 | |
424 /* Now that we're using EImages, send all data as 24bit color. | |
425 The backend routine will take care of any necessary reductions. | |
426 We do have to handle the grayscale case ourselves, however. */ | |
427 if (cinfo.jpeg_color_space == JCS_GRAYSCALE) | |
428 { | |
429 cinfo.out_color_space = JCS_GRAYSCALE; | |
430 jpeg_gray = 1; | |
431 } | |
432 else | |
433 { | |
434 /* we're relying on the jpeg driver to do any other conversions, | |
435 or signal an error if the conversion isn't supported. */ | |
436 cinfo.out_color_space = JCS_RGB; | |
437 } | |
438 | |
439 /* Step 5: Start decompressor */ | |
440 jpeg_start_decompress (&cinfo); | |
441 | |
442 /* Step 6: Read in the data and put into EImage format (8bit RGB triples)*/ | |
4646
6c6bfdb80a0c
Prevent integer overflow and subsequent crashes when attempting to load large
Jerry James <james@xemacs.org>
parents:
4326
diff
changeset
|
443 pixels_sq = |
6c6bfdb80a0c
Prevent integer overflow and subsequent crashes when attempting to load large
Jerry James <james@xemacs.org>
parents:
4326
diff
changeset
|
444 (UINT_64_BIT) cinfo.output_width * (UINT_64_BIT) cinfo.output_height; |
6c6bfdb80a0c
Prevent integer overflow and subsequent crashes when attempting to load large
Jerry James <james@xemacs.org>
parents:
4326
diff
changeset
|
445 if (pixels_sq > ((size_t) -1) / 3) |
6c6bfdb80a0c
Prevent integer overflow and subsequent crashes when attempting to load large
Jerry James <james@xemacs.org>
parents:
4326
diff
changeset
|
446 signal_image_error ("JPEG image too large to instantiate", instantiator); |
2367 | 447 unwind.eimage = |
448 xnew_binbytes (cinfo.output_width * cinfo.output_height * 3); | |
428 | 449 if (!unwind.eimage) |
450 signal_image_error("Unable to allocate enough memory for image", instantiator); | |
451 | |
452 { | |
453 JSAMPARRAY row_buffer; /* Output row buffer */ | |
454 JSAMPLE *jp; | |
455 int row_stride; /* physical row width in output buffer */ | |
2367 | 456 Binbyte *op = unwind.eimage; |
428 | 457 |
458 /* We may need to do some setup of our own at this point before reading | |
459 * the data. After jpeg_start_decompress() we have the correct scaled | |
460 * output image dimensions available | |
461 * We need to make an output work buffer of the right size. | |
462 */ | |
463 /* JSAMPLEs per row in output buffer. */ | |
464 row_stride = cinfo.output_width * cinfo.output_components; | |
465 /* Make a one-row-high sample array that will go away when done | |
466 with image */ | |
467 row_buffer = ((*cinfo.mem->alloc_sarray) | |
468 ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1)); | |
469 | |
470 /* Here we use the library's state variable cinfo.output_scanline as the | |
471 * loop counter, so that we don't have to keep track ourselves. | |
472 */ | |
473 while (cinfo.output_scanline < cinfo.output_height) | |
474 { | |
475 int i; | |
476 | |
477 /* jpeg_read_scanlines expects an array of pointers to scanlines. | |
478 * Here the array is only one element long, but you could ask for | |
479 * more than one scanline at a time if that's more convenient. | |
480 */ | |
481 (void) jpeg_read_scanlines (&cinfo, row_buffer, 1); | |
482 jp = row_buffer[0]; | |
647 | 483 for (i = 0; i < (int) cinfo.output_width; i++) |
428 | 484 { |
485 int clr; | |
486 if (jpeg_gray) | |
487 { | |
2367 | 488 Binbyte val; |
428 | 489 #if (BITS_IN_JSAMPLE == 8) |
2367 | 490 val = (Binbyte) *jp++; |
428 | 491 #else /* other option is 12 */ |
2367 | 492 val = (Binbyte) (*jp++ >> 4); |
428 | 493 #endif |
494 for (clr = 0; clr < 3; clr++) /* copy the same value into RGB */ | |
495 *op++ = val; | |
496 } | |
497 else | |
498 { | |
499 for (clr = 0; clr < 3; clr++) | |
500 #if (BITS_IN_JSAMPLE == 8) | |
2367 | 501 *op++ = (Binbyte)*jp++; |
428 | 502 #else /* other option is 12 */ |
2367 | 503 *op++ = (Binbyte)(*jp++ >> 4); |
428 | 504 #endif |
505 } | |
506 } | |
507 } | |
508 } | |
509 } | |
510 | |
511 /* Step 6.5: Create the pixmap and set up the image instance */ | |
512 /* now instantiate */ | |
442 | 513 MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), |
428 | 514 init_image_instance_from_eimage, |
515 (ii, cinfo.output_width, cinfo.output_height, 1, | |
516 unwind.eimage, dest_mask, | |
2959 | 517 instantiator, pointer_fg, pointer_bg, domain)); |
428 | 518 |
519 /* Step 7: Finish decompression */ | |
520 | |
521 jpeg_finish_decompress (&cinfo); | |
522 /* We can ignore the return value since suspension is not possible | |
523 * with the stdio data source. | |
524 */ | |
525 | |
526 /* And we're done! */ | |
527 /* This will clean up everything else. */ | |
771 | 528 unbind_to (speccount); |
428 | 529 } |
530 | |
531 #endif /* HAVE_JPEG */ | |
532 | |
533 #ifdef HAVE_GIF | |
534 /********************************************************************** | |
535 * GIF * | |
536 **********************************************************************/ | |
537 | |
4708
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
538 #include <gif_lib.h> |
428 | 539 |
540 static void | |
541 gif_validate (Lisp_Object instantiator) | |
542 { | |
543 file_or_data_must_be_present (instantiator); | |
544 } | |
545 | |
546 static Lisp_Object | |
442 | 547 gif_normalize (Lisp_Object inst, Lisp_Object console_type, |
2286 | 548 Lisp_Object UNUSED (dest_mask)) |
428 | 549 { |
550 return simple_image_type_normalize (inst, console_type, Qgif); | |
551 } | |
552 | |
553 static int | |
554 gif_possible_dest_types (void) | |
555 { | |
556 return IMAGE_COLOR_PIXMAP_MASK; | |
557 } | |
558 | |
559 /* To survive the otherwise baffling complexity of making sure | |
560 everything gets cleaned up in the presence of an error, we | |
561 use an unwind_protect(). */ | |
562 | |
563 struct gif_unwind_data | |
564 { | |
2367 | 565 Binbyte *eimage; |
428 | 566 /* Object that holds the decoded data from a GIF file */ |
567 GifFileType *giffile; | |
568 }; | |
569 | |
570 static Lisp_Object | |
571 gif_instantiate_unwind (Lisp_Object unwind_obj) | |
572 { | |
573 struct gif_unwind_data *data = | |
574 (struct gif_unwind_data *) get_opaque_ptr (unwind_obj); | |
575 | |
576 free_opaque_ptr (unwind_obj); | |
577 if (data->giffile) | |
578 { | |
579 DGifCloseFile (data->giffile); | |
4708
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
580 FreeSavedImages(data->giffile); |
428 | 581 } |
647 | 582 if (data->eimage) |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
583 xfree (data->eimage); |
428 | 584 |
585 return Qnil; | |
586 } | |
587 | |
588 typedef struct gif_memory_storage | |
589 { | |
2367 | 590 Binbyte *bytes; /* The data */ |
665 | 591 Bytecount len; /* How big is it? */ |
592 Bytecount index; /* Where are we? */ | |
428 | 593 } gif_memory_storage; |
594 | |
4708
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
595 static int |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
596 gif_read_from_memory (GifFileType *gif, GifByteType *buf, int size) |
428 | 597 { |
4708
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
598 gif_memory_storage *mem = (gif_memory_storage *) gif->UserData; |
428 | 599 |
600 if (size > (mem->len - mem->index)) | |
647 | 601 return -1; |
602 memcpy (buf, mem->bytes + mem->index, size); | |
428 | 603 mem->index = mem->index + size; |
604 return size; | |
605 } | |
606 | |
4708
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
607 static const char * |
5016
2ade80e8c640
enable more warnings and fix them
Ben Wing <ben@xemacs.org>
parents:
4982
diff
changeset
|
608 gif_decode_error_string (void) |
428 | 609 { |
4708
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
610 switch (GifLastError ()) |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
611 { |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
612 case D_GIF_ERR_OPEN_FAILED: |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
613 return "GIF error: unable to open"; |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
614 case D_GIF_ERR_READ_FAILED: |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
615 return "GIF error: read failed"; |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
616 case D_GIF_ERR_NOT_GIF_FILE: |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
617 return "GIF error: not a GIF file"; |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
618 case D_GIF_ERR_NO_SCRN_DSCR: |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
619 return "GIF error: no Screen Descriptor detected"; |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
620 case D_GIF_ERR_NO_IMAG_DSCR: |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
621 return "GIF error: no Image Descriptor detected"; |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
622 case D_GIF_ERR_NO_COLOR_MAP: |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
623 return "GIF error: no global or local color map"; |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
624 case D_GIF_ERR_WRONG_RECORD: |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
625 return "GIF error: wrong record type"; |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
626 case D_GIF_ERR_DATA_TOO_BIG: |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
627 return "GIF error: image is larger than indicated by header"; |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
628 case D_GIF_ERR_NOT_ENOUGH_MEM: |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
629 return "GIF error: out of memory"; |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
630 case D_GIF_ERR_CLOSE_FAILED: |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
631 return "GIF error: failed to close file"; |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
632 case D_GIF_ERR_NOT_READABLE: |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
633 return "GIF error: file is not readable"; |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
634 case D_GIF_ERR_IMAGE_DEFECT: |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
635 return "GIF error: image is defective"; |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
636 case D_GIF_ERR_EOF_TOO_SOON: |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
637 return "GIF error: image EOF detected before image complete"; |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
638 default: |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
639 return "GIF error: unknown error"; |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
640 } |
428 | 641 } |
642 | |
643 static void | |
644 gif_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
2959 | 645 Lisp_Object pointer_fg, Lisp_Object pointer_bg, |
428 | 646 int dest_mask, Lisp_Object domain) |
647 { | |
440 | 648 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
428 | 649 /* It is OK for the unwind data to be local to this function, |
650 because the unwind-protect is always executed when this | |
651 stack frame is still valid. */ | |
652 struct gif_unwind_data unwind; | |
653 int speccount = specpdl_depth (); | |
654 gif_memory_storage mem_struct; | |
2367 | 655 Binbyte *bytes; |
665 | 656 Bytecount len; |
428 | 657 int height = 0; |
658 int width = 0; | |
659 | |
660 xzero (unwind); | |
661 record_unwind_protect (gif_instantiate_unwind, make_opaque_ptr (&unwind)); | |
662 | |
663 /* 1. Now decode the data. */ | |
664 | |
665 { | |
666 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
667 | |
668 assert (!NILP (data)); | |
669 | |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
670 LISP_STRING_TO_SIZED_EXTERNAL (data, bytes, len, Qbinary); |
428 | 671 mem_struct.bytes = bytes; |
672 mem_struct.len = len; | |
673 mem_struct.index = 0; | |
4708
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
674 unwind.giffile = DGifOpen (&mem_struct, gif_read_from_memory); |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
675 if (unwind.giffile == NULL) |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
676 signal_image_error (gif_decode_error_string (), instantiator); |
428 | 677 |
678 /* Then slurp the image into memory, decoding along the way. | |
679 The result is the image in a simple one-byte-per-pixel | |
4708
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
680 format. */ |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
681 if (DGifSlurp (unwind.giffile) == GIF_ERROR) |
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
682 signal_image_error (gif_decode_error_string (), instantiator); |
428 | 683 } |
684 | |
685 /* 3. Now create the EImage(s) */ | |
686 { | |
687 ColorMapObject *cmo = unwind.giffile->SColorMap; | |
688 int i, j, row, pass, interlace, slice; | |
4646
6c6bfdb80a0c
Prevent integer overflow and subsequent crashes when attempting to load large
Jerry James <james@xemacs.org>
parents:
4326
diff
changeset
|
689 UINT_64_BIT pixels_sq; |
2367 | 690 Binbyte *eip; |
428 | 691 /* interlaced gifs have rows in this order: |
692 0, 8, 16, ..., 4, 12, 20, ..., 2, 6, 10, ..., 1, 3, 5, ... */ | |
693 static int InterlacedOffset[] = { 0, 4, 2, 1 }; | |
694 static int InterlacedJumps[] = { 8, 8, 4, 2 }; | |
695 | |
696 height = unwind.giffile->SHeight; | |
697 width = unwind.giffile->SWidth; | |
4646
6c6bfdb80a0c
Prevent integer overflow and subsequent crashes when attempting to load large
Jerry James <james@xemacs.org>
parents:
4326
diff
changeset
|
698 pixels_sq = (UINT_64_BIT) width * (UINT_64_BIT) height; |
6c6bfdb80a0c
Prevent integer overflow and subsequent crashes when attempting to load large
Jerry James <james@xemacs.org>
parents:
4326
diff
changeset
|
699 if (pixels_sq > ((size_t) -1) / (3 * unwind.giffile->ImageCount)) |
6c6bfdb80a0c
Prevent integer overflow and subsequent crashes when attempting to load large
Jerry James <james@xemacs.org>
parents:
4326
diff
changeset
|
700 signal_image_error ("GIF image too large to instantiate", instantiator); |
2367 | 701 unwind.eimage = |
702 xnew_binbytes (width * height * 3 * unwind.giffile->ImageCount); | |
428 | 703 if (!unwind.eimage) |
704 signal_image_error("Unable to allocate enough memory for image", instantiator); | |
705 | |
706 /* write the data in EImage format (8bit RGB triples) */ | |
707 | |
708 for (slice = 0; slice < unwind.giffile->ImageCount; slice++) | |
709 { | |
638 | 710 /* We check here that the current image covers the full "screen" size. */ |
428 | 711 if (unwind.giffile->SavedImages[slice].ImageDesc.Height != height |
712 || unwind.giffile->SavedImages[slice].ImageDesc.Width != width | |
713 || unwind.giffile->SavedImages[slice].ImageDesc.Left != 0 | |
714 || unwind.giffile->SavedImages[slice].ImageDesc.Top != 0) | |
715 signal_image_error ("Image in GIF file is not full size", | |
716 instantiator); | |
717 | |
718 interlace = unwind.giffile->SavedImages[slice].ImageDesc.Interlace; | |
719 pass = 0; | |
720 row = interlace ? InterlacedOffset[pass] : 0; | |
721 eip = unwind.eimage + (width * height * 3 * slice); | |
722 for (i = 0; i < height; i++) | |
723 { | |
724 if (interlace) | |
725 if (row >= height) { | |
726 row = InterlacedOffset[++pass]; | |
727 while (row >= height) | |
728 row = InterlacedOffset[++pass]; | |
729 } | |
730 eip = unwind.eimage + (width * height * 3 * slice) + (row * width * 3); | |
731 for (j = 0; j < width; j++) | |
732 { | |
2367 | 733 Binbyte pixel = |
428 | 734 unwind.giffile->SavedImages[slice].RasterBits[(i * width) + j]; |
735 *eip++ = cmo->Colors[pixel].Red; | |
736 *eip++ = cmo->Colors[pixel].Green; | |
737 *eip++ = cmo->Colors[pixel].Blue; | |
738 } | |
739 row += interlace ? InterlacedJumps[pass] : 1; | |
740 } | |
741 } | |
742 | |
743 /* now instantiate */ | |
442 | 744 MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), |
428 | 745 init_image_instance_from_eimage, |
2959 | 746 (ii, width, height, unwind.giffile->ImageCount, |
747 unwind.eimage, dest_mask, instantiator, pointer_fg, | |
748 pointer_bg, domain)); | |
428 | 749 } |
750 | |
751 /* We read the gif successfully. If we have more than one slice then | |
752 animate the gif. */ | |
753 if (unwind.giffile->ImageCount > 1) | |
754 { | |
755 /* See if there is a timeout value. In theory there could be one | |
4708
1cecc3e9f0a0
Use giflib or libungif to provide GIF support, instead of using internal
Jerry James <james@xemacs.org>
parents:
4698
diff
changeset
|
756 for every image - but that makes the implementation way too |
428 | 757 complicated for now so we just take the first. */ |
758 unsigned short timeout = 0; | |
759 Lisp_Object tid; | |
760 | |
761 if (unwind.giffile->SavedImages[0].Function == GRAPHICS_EXT_FUNC_CODE | |
762 && | |
763 unwind.giffile->SavedImages[0].ExtensionBlockCount) | |
764 { | |
765 timeout = (unsigned short) | |
438 | 766 ((unwind.giffile->SavedImages[0].ExtensionBlocks[0].Bytes[2] << 8) + |
428 | 767 unwind.giffile-> SavedImages[0].ExtensionBlocks[0].Bytes[1]) * 10; |
768 } | |
769 | |
770 /* Too short a timeout will crucify us performance-wise. */ | |
771 tid = add_glyph_animated_timeout (timeout > 10 ? timeout : 10, image_instance); | |
772 | |
773 if (!NILP (tid)) | |
774 IMAGE_INSTANCE_PIXMAP_TIMEOUT (ii) = XINT (tid); | |
775 } | |
438 | 776 |
771 | 777 unbind_to (speccount); |
428 | 778 } |
779 | |
780 #endif /* HAVE_GIF */ | |
781 | |
782 | |
783 #ifdef HAVE_PNG | |
784 | |
785 /********************************************************************** | |
786 * PNG * | |
787 **********************************************************************/ | |
788 static void | |
789 png_validate (Lisp_Object instantiator) | |
790 { | |
791 file_or_data_must_be_present (instantiator); | |
792 } | |
793 | |
794 static Lisp_Object | |
442 | 795 png_normalize (Lisp_Object inst, Lisp_Object console_type, |
2286 | 796 Lisp_Object UNUSED (dest_mask)) |
428 | 797 { |
798 return simple_image_type_normalize (inst, console_type, Qpng); | |
799 } | |
800 | |
801 static int | |
802 png_possible_dest_types (void) | |
803 { | |
804 return IMAGE_COLOR_PIXMAP_MASK; | |
805 } | |
806 | |
807 struct png_memory_storage | |
808 { | |
2367 | 809 const Binbyte *bytes; /* The data */ |
665 | 810 Bytecount len; /* How big is it? */ |
811 Bytecount index; /* Where are we? */ | |
428 | 812 }; |
813 | |
814 static void | |
647 | 815 png_read_from_memory (png_structp png_ptr, png_bytep data, |
816 png_size_t length) | |
428 | 817 { |
818 struct png_memory_storage *tbr = | |
819 (struct png_memory_storage *) png_get_io_ptr (png_ptr); | |
820 | |
665 | 821 if ((Bytecount) length > (tbr->len - tbr->index)) |
428 | 822 png_error (png_ptr, (png_const_charp) "Read Error"); |
647 | 823 memcpy (data, tbr->bytes + tbr->index,length); |
428 | 824 tbr->index = tbr->index + length; |
825 } | |
826 | |
827 struct png_error_struct | |
828 { | |
442 | 829 const char *err_str; |
428 | 830 jmp_buf setjmp_buffer; /* for return to caller */ |
831 }; | |
832 | |
833 /* jh 98/03/12 - #### AARRRGH! libpng includes jmp_buf inside its own | |
834 structure, and there are cases where the size can be different from | |
835 between inside the library, and inside the code! To do an end run | |
836 around this, use our own error functions, and don't rely on things | |
837 passed in the png_ptr to them. This is an ugly hack and must | |
838 go away when the lisp engine is threaded! */ | |
839 static struct png_error_struct png_err_stct; | |
840 | |
841 static void | |
2286 | 842 png_error_func (png_structp UNUSED (png_ptr), png_const_charp msg) |
428 | 843 { |
844 png_err_stct.err_str = msg; | |
845 longjmp (png_err_stct.setjmp_buffer, 1); | |
846 } | |
847 | |
848 static void | |
2286 | 849 png_warning_func (png_structp UNUSED (png_ptr), png_const_charp msg) |
428 | 850 { |
3734 | 851 DECLARE_EISTRING (eimsg); |
852 | |
853 eicpy_ext(eimsg, msg, Qbinary); | |
854 warn_when_safe (Qpng, Qinfo, "%s", eidata(eimsg)); | |
428 | 855 } |
856 | |
857 struct png_unwind_data | |
858 { | |
859 FILE *instream; | |
2367 | 860 Binbyte *eimage; |
428 | 861 png_structp png_ptr; |
862 png_infop info_ptr; | |
863 }; | |
864 | |
865 static Lisp_Object | |
866 png_instantiate_unwind (Lisp_Object unwind_obj) | |
867 { | |
868 struct png_unwind_data *data = | |
869 (struct png_unwind_data *) get_opaque_ptr (unwind_obj); | |
870 | |
871 free_opaque_ptr (unwind_obj); | |
872 if (data->png_ptr) | |
3839 | 873 { |
874 /* ensure we can't get here again */ | |
875 png_structp tmp = data->png_ptr; | |
876 data->png_ptr = NULL; | |
877 png_destroy_read_struct (&tmp, &(data->info_ptr), (png_infopp)NULL); | |
878 } | |
879 | |
428 | 880 if (data->instream) |
771 | 881 retry_fclose (data->instream); |
428 | 882 |
1726 | 883 if (data->eimage) |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
884 xfree (data->eimage); |
428 | 885 |
886 return Qnil; | |
887 } | |
888 | |
889 static void | |
890 png_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
2959 | 891 Lisp_Object pointer_fg, Lisp_Object pointer_bg, |
428 | 892 int dest_mask, Lisp_Object domain) |
893 { | |
440 | 894 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
428 | 895 struct png_unwind_data unwind; |
896 int speccount = specpdl_depth (); | |
897 int height, width; | |
898 struct png_memory_storage tbr; /* Data to be read */ | |
899 | |
900 /* PNG variables */ | |
901 png_structp png_ptr; | |
902 png_infop info_ptr; | |
903 | |
3839 | 904 xzero (unwind); |
905 record_unwind_protect (png_instantiate_unwind, make_opaque_ptr (&unwind)); | |
906 | |
907 if (setjmp (png_err_stct.setjmp_buffer)) | |
908 { | |
909 /* Something blew up: | |
910 just display the error (cleanup happens in the unwind) */ | |
911 signal_image_error_2 ("Error decoding PNG", | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
4952
diff
changeset
|
912 build_extstring (png_err_stct.err_str, |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4854
diff
changeset
|
913 Qerror_message_encoding), |
3839 | 914 instantiator); |
915 } | |
916 | |
428 | 917 /* Initialize all PNG structures */ |
3839 | 918 png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, |
919 (void *) &png_err_stct, | |
428 | 920 png_error_func, png_warning_func); |
921 if (!png_ptr) | |
922 signal_image_error ("Error obtaining memory for png_read", instantiator); | |
3839 | 923 unwind.png_ptr = png_ptr; |
924 | |
428 | 925 info_ptr = png_create_info_struct (png_ptr); |
926 if (!info_ptr) | |
927 { | |
3839 | 928 unwind.png_ptr = NULL; /* avoid re-calling png_destroy_read_struct |
929 when unwinding */ | |
428 | 930 png_destroy_read_struct (&png_ptr, (png_infopp)NULL, (png_infopp)NULL); |
931 signal_image_error ("Error obtaining memory for png_read", instantiator); | |
932 } | |
933 unwind.info_ptr = info_ptr; | |
934 | |
935 /* This code is a mixture of stuff from Ben's GIF/JPEG stuff from | |
936 this file, example.c from the libpng 0.81 distribution, and the | |
937 pngtopnm sources. -WMP- | |
938 */ | |
939 /* It has been further modified to handle the API changes for 0.96, | |
940 and is no longer usable for previous versions. jh | |
941 */ | |
942 | |
943 /* Initialize the IO layer and read in header information */ | |
944 { | |
945 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
2367 | 946 const Binbyte *bytes; |
665 | 947 Bytecount len; |
428 | 948 |
949 assert (!NILP (data)); | |
950 | |
951 /* #### This is a definite problem under Mule due to the amount of | |
952 stack data it might allocate. Need to think about using Lstreams */ | |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
953 LISP_STRING_TO_SIZED_EXTERNAL (data, bytes, len, Qbinary); |
428 | 954 tbr.bytes = bytes; |
955 tbr.len = len; | |
956 tbr.index = 0; | |
957 png_set_read_fn (png_ptr,(void *) &tbr, png_read_from_memory); | |
958 } | |
959 | |
960 png_read_info (png_ptr, info_ptr); | |
961 | |
962 { | |
4698
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
963 int y, padding; |
2367 | 964 Binbyte **row_pointers; |
4646
6c6bfdb80a0c
Prevent integer overflow and subsequent crashes when attempting to load large
Jerry James <james@xemacs.org>
parents:
4326
diff
changeset
|
965 UINT_64_BIT pixels_sq; |
428 | 966 height = info_ptr->height; |
967 width = info_ptr->width; | |
4646
6c6bfdb80a0c
Prevent integer overflow and subsequent crashes when attempting to load large
Jerry James <james@xemacs.org>
parents:
4326
diff
changeset
|
968 pixels_sq = (UINT_64_BIT) width * (UINT_64_BIT) height; |
6c6bfdb80a0c
Prevent integer overflow and subsequent crashes when attempting to load large
Jerry James <james@xemacs.org>
parents:
4326
diff
changeset
|
969 if (pixels_sq > ((size_t) -1) / 3) |
6c6bfdb80a0c
Prevent integer overflow and subsequent crashes when attempting to load large
Jerry James <james@xemacs.org>
parents:
4326
diff
changeset
|
970 signal_image_error ("PNG image too large to instantiate", instantiator); |
428 | 971 |
4698
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
972 /* Wow, allocate all the memory. Truly, exciting. |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
973 Well, yes, there's excitement to be had. It turns out that libpng |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
974 strips in place, so the last row overruns the buffer if depth is 16 |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
975 or there's an alpha channel. This is a crash on Linux. So we need |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
976 to add padding. |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
977 The worst case is reducing 8 bytes (16-bit RGBA) to 3 (8-bit RGB). */ |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
978 |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
979 padding = 5 * width; |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
980 unwind.eimage = xnew_array_and_zero (Binbyte, |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
981 (size_t) (pixels_sq * 3 + padding)); |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
982 |
428 | 983 /* libpng expects that the image buffer passed in contains a |
984 picture to draw on top of if the png has any transparencies. | |
985 This could be a good place to pass that in... */ | |
986 | |
987 row_pointers = xnew_array (png_byte *, height); | |
988 for (y = 0; y < height; y++) | |
989 row_pointers[y] = unwind.eimage + (width * 3 * y); | |
990 | |
991 { | |
992 /* if the png specifies a background chunk, go ahead and | |
993 use it, else use what we can get from the default face. */ | |
994 png_color_16 my_background, *image_background; | |
995 Lisp_Object bkgd = Qnil; | |
996 | |
997 my_background.red = 0x7fff; | |
998 my_background.green = 0x7fff; | |
999 my_background.blue = 0x7fff; | |
1000 bkgd = FACE_BACKGROUND (Vdefault_face, domain); | |
1001 if (!COLOR_INSTANCEP (bkgd)) | |
1002 { | |
1003 warn_when_safe (Qpng, Qinfo, "Couldn't get background color!"); | |
1004 } | |
1005 else | |
1006 { | |
4698
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1007 Lisp_Color_Instance *c = XCOLOR_INSTANCE (bkgd); |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1008 Lisp_Object rgb = MAYBE_LISP_DEVMETH (XDEVICE (c->device), |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1009 color_instance_rgb_components, |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1010 (c)); |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1011 #define GETCOLOR(col) my_background.col = (unsigned short) XINT (XCAR (rgb)) |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1012 GETCOLOR(red); rgb = XCDR (rgb); |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1013 GETCOLOR(green); rgb = XCDR (rgb); |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1014 GETCOLOR(blue); |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1015 #undef GETCOLOR |
428 | 1016 } |
1017 | |
1018 if (png_get_bKGD (png_ptr, info_ptr, &image_background)) | |
1019 png_set_background (png_ptr, image_background, | |
1020 PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); | |
1021 else | |
1022 png_set_background (png_ptr, &my_background, | |
1023 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); | |
1024 } | |
1025 | |
1026 /* Now that we're using EImage, ask for 8bit RGB triples for any type | |
1027 of image*/ | |
4698
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1028 /* convert palette images to RGB */ |
428 | 1029 if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) |
4698
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1030 png_set_palette_to_rgb (png_ptr); |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1031 /* convert grayscale images to RGB */ |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1032 else if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY || |
428 | 1033 info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) |
1034 png_set_gray_to_rgb (png_ptr); | |
4698
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1035 /* pad images with depth < 8 bits */ |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1036 else if (info_ptr->bit_depth < 8) |
428 | 1037 { |
1038 if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY) | |
1039 png_set_expand (png_ptr); | |
1040 else | |
1041 png_set_packing (png_ptr); | |
1042 } | |
4698
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1043 /* strip 16-bit depth files down to 8 bits */ |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1044 if (info_ptr->bit_depth == 16) |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1045 png_set_strip_16 (png_ptr); |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1046 /* strip alpha channel |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1047 #### shouldn't we handle this? |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1048 first call png_read_update_info in case above transformations |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1049 have generated an alpha channel */ |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1050 png_read_update_info(png_ptr, info_ptr); |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1051 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1052 png_set_strip_alpha (png_ptr); |
428 | 1053 |
1054 png_read_image (png_ptr, row_pointers); | |
1055 png_read_end (png_ptr, info_ptr); | |
1056 | |
4698
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1057 /* #### There should be some way to pass this type of data down |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1058 * into the glyph code, where you can get to it from lisp |
a9493cab536f
Fix crash due to mishandling transparency.
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4682
diff
changeset
|
1059 * anyway. - WMP */ |
428 | 1060 { |
1061 int i; | |
3734 | 1062 DECLARE_EISTRING (key); |
1063 DECLARE_EISTRING (text); | |
428 | 1064 |
1065 for (i = 0 ; i < info_ptr->num_text ; i++) | |
1066 { | |
1067 /* How paranoid do I have to be about no trailing NULLs, and | |
1068 using (int)info_ptr->text[i].text_length, and strncpy and a temp | |
1069 string somewhere? */ | |
3734 | 1070 eireset(key); |
1071 eireset(text); | |
1072 eicpy_ext(key, info_ptr->text[i].key, Qbinary); | |
1073 eicpy_ext(text, info_ptr->text[i].text, Qbinary); | |
428 | 1074 |
1075 warn_when_safe (Qpng, Qinfo, "%s - %s", | |
3734 | 1076 eidata(key), eidata(text)); |
428 | 1077 } |
1078 } | |
1079 | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
1080 xfree (row_pointers); |
428 | 1081 } |
1082 | |
1083 /* now instantiate */ | |
442 | 1084 MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), |
428 | 1085 init_image_instance_from_eimage, |
1086 (ii, width, height, 1, unwind.eimage, dest_mask, | |
2959 | 1087 instantiator, pointer_fg, pointer_bg, domain)); |
428 | 1088 |
1089 /* This will clean up everything else. */ | |
771 | 1090 unbind_to (speccount); |
428 | 1091 } |
1092 | |
1093 #endif /* HAVE_PNG */ | |
1094 | |
1095 | |
1096 #ifdef HAVE_TIFF | |
1097 #include "tiffio.h" | |
1098 | |
1099 /********************************************************************** | |
1100 * TIFF * | |
1101 **********************************************************************/ | |
1102 static void | |
1103 tiff_validate (Lisp_Object instantiator) | |
1104 { | |
1105 file_or_data_must_be_present (instantiator); | |
1106 } | |
1107 | |
1108 static Lisp_Object | |
442 | 1109 tiff_normalize (Lisp_Object inst, Lisp_Object console_type, |
2286 | 1110 Lisp_Object UNUSED (dest_mask)) |
428 | 1111 { |
1112 return simple_image_type_normalize (inst, console_type, Qtiff); | |
1113 } | |
1114 | |
1115 static int | |
1116 tiff_possible_dest_types (void) | |
1117 { | |
1118 return IMAGE_COLOR_PIXMAP_MASK; | |
1119 } | |
1120 | |
1121 struct tiff_unwind_data | |
1122 { | |
2367 | 1123 Binbyte *eimage; |
428 | 1124 /* Object that holds the decoded data from a TIFF file */ |
1125 TIFF *tiff; | |
1126 }; | |
1127 | |
1128 static Lisp_Object | |
1129 tiff_instantiate_unwind (Lisp_Object unwind_obj) | |
1130 { | |
1131 struct tiff_unwind_data *data = | |
1132 (struct tiff_unwind_data *) get_opaque_ptr (unwind_obj); | |
1133 | |
1134 free_opaque_ptr (unwind_obj); | |
1135 if (data->tiff) | |
1136 { | |
1137 TIFFClose(data->tiff); | |
1138 } | |
1139 if (data->eimage) | |
4976
16112448d484
Rename xfree(FOO, TYPE) -> xfree(FOO)
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
1140 xfree (data->eimage); |
428 | 1141 |
1142 return Qnil; | |
1143 } | |
1144 | |
1145 typedef struct tiff_memory_storage | |
1146 { | |
2367 | 1147 Binbyte *bytes; /* The data */ |
665 | 1148 Bytecount len; /* How big is it? */ |
1149 Bytecount index; /* Where are we? */ | |
428 | 1150 } tiff_memory_storage; |
1151 | |
1152 static size_t | |
647 | 1153 tiff_memory_read (thandle_t data, tdata_t buf, tsize_t size) |
428 | 1154 { |
647 | 1155 tiff_memory_storage *mem = (tiff_memory_storage *) data; |
428 | 1156 |
665 | 1157 if ((Bytecount) size > (mem->len - mem->index)) |
428 | 1158 return (size_t) -1; |
647 | 1159 memcpy (buf, mem->bytes + mem->index, size); |
428 | 1160 mem->index = mem->index + size; |
1161 return size; | |
1162 } | |
1163 | |
647 | 1164 static size_t |
2286 | 1165 tiff_memory_write (thandle_t UNUSED (data), tdata_t UNUSED (buf), |
1166 tsize_t UNUSED (size)) | |
428 | 1167 { |
2500 | 1168 ABORT(); |
2270 | 1169 return 0; |
428 | 1170 } |
1171 | |
647 | 1172 static toff_t |
1173 tiff_memory_seek (thandle_t data, toff_t off, int whence) | |
428 | 1174 { |
647 | 1175 tiff_memory_storage *mem = (tiff_memory_storage *) data; |
428 | 1176 int newidx; |
647 | 1177 switch(whence) |
1178 { | |
1179 case SEEK_SET: | |
1180 newidx = off; | |
1181 break; | |
1182 case SEEK_END: | |
1183 newidx = mem->len + off; | |
1184 break; | |
1185 case SEEK_CUR: | |
1186 newidx = mem->index + off; | |
1187 break; | |
1188 default: | |
1189 fprintf (stderr, "Eh? invalid seek mode in tiff_memory_seek\n"); | |
1190 return (toff_t) -1; | |
1191 } | |
428 | 1192 |
1193 if ((newidx > mem->len) || (newidx < 0)) | |
593 | 1194 return (toff_t) -1; |
428 | 1195 |
1196 mem->index = newidx; | |
1197 return newidx; | |
1198 } | |
1199 | |
1200 static int | |
2286 | 1201 tiff_memory_close (thandle_t UNUSED (data)) |
428 | 1202 { |
1203 return 0; | |
1204 } | |
1205 | |
1206 static int | |
2286 | 1207 tiff_map_noop (thandle_t UNUSED (data), tdata_t* UNUSED (pbase), |
1208 toff_t* UNUSED (psize)) | |
428 | 1209 { |
1210 return 0; | |
1211 } | |
1212 | |
1213 static void | |
2286 | 1214 tiff_unmap_noop (thandle_t UNUSED (data), tdata_t UNUSED (pbase), |
1215 toff_t UNUSED (psize)) | |
428 | 1216 { |
1217 return; | |
1218 } | |
1219 | |
1220 static toff_t | |
647 | 1221 tiff_memory_size (thandle_t data) |
428 | 1222 { |
1223 tiff_memory_storage *mem = (tiff_memory_storage*)data; | |
1224 return mem->len; | |
1225 } | |
1226 | |
1227 struct tiff_error_struct | |
1228 { | |
438 | 1229 #ifdef HAVE_VSNPRINTF |
428 | 1230 char err_str[256]; |
1231 #else | |
1232 char err_str[1024]; /* return the error string */ | |
1233 #endif | |
1234 jmp_buf setjmp_buffer; /* for return to caller */ | |
1235 }; | |
1236 | |
1237 /* jh 98/03/12 - ###This struct for passing data to the error functions | |
1238 is an ugly hack caused by the fact that libtiff (as of v3.4) doesn't | |
1239 have any place to store error func data. This should be rectified | |
1240 before XEmacs gets threads! */ | |
1241 static struct tiff_error_struct tiff_err_data; | |
1242 | |
1243 static void | |
2286 | 1244 tiff_error_func (const char *UNUSED (module), const char *fmt, ...) |
428 | 1245 { |
1246 va_list vargs; | |
1247 | |
1248 va_start (vargs, fmt); | |
438 | 1249 #ifdef HAVE_VSNPRINTF |
428 | 1250 vsnprintf (tiff_err_data.err_str, 255, fmt, vargs); |
1251 #else | |
1252 /* pray this doesn't overflow... */ | |
1253 vsprintf (tiff_err_data.err_str, fmt, vargs); | |
1254 #endif | |
1255 va_end (vargs); | |
1256 /* return to setjmp point */ | |
1257 longjmp (tiff_err_data.setjmp_buffer, 1); | |
1258 } | |
1259 | |
1260 static void | |
647 | 1261 tiff_warning_func (const char *module, const char *fmt, ...) |
428 | 1262 { |
1263 va_list vargs; | |
438 | 1264 #ifdef HAVE_VSNPRINTF |
428 | 1265 char warn_str[256]; |
1266 #else | |
1267 char warn_str[1024]; | |
1268 #endif | |
3734 | 1269 DECLARE_EISTRING (eimodule); |
1270 DECLARE_EISTRING (eiwarnstr); | |
428 | 1271 |
1272 va_start (vargs, fmt); | |
438 | 1273 #ifdef HAVE_VSNPRINTF |
428 | 1274 vsnprintf (warn_str, 255, fmt, vargs); |
1275 #else | |
1276 vsprintf (warn_str, fmt, vargs); | |
1277 #endif | |
1278 va_end (vargs); | |
3734 | 1279 |
1280 eicpy_ext(eimodule, module, Qbinary); | |
1281 eicpy_ext(eiwarnstr, warn_str, Qbinary); | |
1282 | |
428 | 1283 warn_when_safe (Qtiff, Qinfo, "%s - %s", |
3734 | 1284 eidata(eimodule), |
1285 eidata(eiwarnstr)); | |
428 | 1286 } |
1287 | |
1288 static void | |
1289 tiff_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, | |
2959 | 1290 Lisp_Object pointer_fg, Lisp_Object pointer_bg, |
428 | 1291 int dest_mask, Lisp_Object domain) |
1292 { | |
440 | 1293 Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); |
428 | 1294 tiff_memory_storage mem_struct; |
1295 /* It is OK for the unwind data to be local to this function, | |
1296 because the unwind-protect is always executed when this | |
1297 stack frame is still valid. */ | |
1298 struct tiff_unwind_data unwind; | |
1299 int speccount = specpdl_depth (); | |
1300 uint32 width, height; | |
1301 | |
1302 xzero (unwind); | |
1303 record_unwind_protect (tiff_instantiate_unwind, make_opaque_ptr (&unwind)); | |
1304 | |
1305 /* set up error facilities */ | |
1306 if (setjmp (tiff_err_data.setjmp_buffer)) | |
1307 { | |
1308 /* An error was signaled. No clean up is needed, as unwind handles that | |
1309 for us. Just pass the error along. */ | |
1310 signal_image_error_2 ("TIFF decoding error", | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
4952
diff
changeset
|
1311 build_extstring (tiff_err_data.err_str, |
4952
19a72041c5ed
Mule-izing, various fixes related to char * arguments
Ben Wing <ben@xemacs.org>
parents:
4854
diff
changeset
|
1312 Qerror_message_encoding), |
428 | 1313 instantiator); |
1314 } | |
1315 TIFFSetErrorHandler ((TIFFErrorHandler)tiff_error_func); | |
1316 TIFFSetWarningHandler ((TIFFErrorHandler)tiff_warning_func); | |
1317 { | |
1318 Lisp_Object data = find_keyword_in_vector (instantiator, Q_data); | |
2367 | 1319 Binbyte *bytes; |
665 | 1320 Bytecount len; |
428 | 1321 |
1322 uint32 *raster; | |
2367 | 1323 Binbyte *ep; |
4646
6c6bfdb80a0c
Prevent integer overflow and subsequent crashes when attempting to load large
Jerry James <james@xemacs.org>
parents:
4326
diff
changeset
|
1324 UINT_64_BIT pixels_sq; |
428 | 1325 |
1326 assert (!NILP (data)); | |
1327 | |
1328 /* #### This is a definite problem under Mule due to the amount of | |
1329 stack data it might allocate. Think about Lstreams... */ | |
4981
4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
Ben Wing <ben@xemacs.org>
parents:
4953
diff
changeset
|
1330 LISP_STRING_TO_SIZED_EXTERNAL (data, bytes, len, Qbinary); |
428 | 1331 mem_struct.bytes = bytes; |
1332 mem_struct.len = len; | |
1333 mem_struct.index = 0; | |
1334 | |
442 | 1335 unwind.tiff = TIFFClientOpen ("memfile", "r", (thandle_t) &mem_struct, |
428 | 1336 (TIFFReadWriteProc)tiff_memory_read, |
1337 (TIFFReadWriteProc)tiff_memory_write, | |
1338 tiff_memory_seek, tiff_memory_close, tiff_memory_size, | |
1339 tiff_map_noop, tiff_unmap_noop); | |
1340 if (!unwind.tiff) | |
440 | 1341 signal_image_error ("Insufficient memory to instantiate TIFF image", instantiator); |
428 | 1342 |
1343 TIFFGetField (unwind.tiff, TIFFTAG_IMAGEWIDTH, &width); | |
1344 TIFFGetField (unwind.tiff, TIFFTAG_IMAGELENGTH, &height); | |
4646
6c6bfdb80a0c
Prevent integer overflow and subsequent crashes when attempting to load large
Jerry James <james@xemacs.org>
parents:
4326
diff
changeset
|
1345 pixels_sq = (UINT_64_BIT) width * (UINT_64_BIT) height; |
6c6bfdb80a0c
Prevent integer overflow and subsequent crashes when attempting to load large
Jerry James <james@xemacs.org>
parents:
4326
diff
changeset
|
1346 if (pixels_sq >= 1 << 29) |
6c6bfdb80a0c
Prevent integer overflow and subsequent crashes when attempting to load large
Jerry James <james@xemacs.org>
parents:
4326
diff
changeset
|
1347 signal_image_error ("TIFF image too large to instantiate", instantiator); |
4682
648f4a0dac3e
Fix build problems on WIN32 platforms caused by the large image crash fix.
Jerry James <james@xemacs.org>
parents:
4646
diff
changeset
|
1348 unwind.eimage = xnew_binbytes ((size_t) pixels_sq * 3); |
428 | 1349 |
440 | 1350 /* #### This is little more than proof-of-concept/function testing. |
428 | 1351 It needs to be reimplemented via scanline reads for both memory |
1352 compactness. */ | |
4646
6c6bfdb80a0c
Prevent integer overflow and subsequent crashes when attempting to load large
Jerry James <james@xemacs.org>
parents:
4326
diff
changeset
|
1353 raster = (uint32*) _TIFFmalloc ((tsize_t) (pixels_sq * sizeof (uint32))); |
428 | 1354 if (raster != NULL) |
1355 { | |
647 | 1356 int i, j; |
428 | 1357 uint32 *rp; |
1358 ep = unwind.eimage; | |
1359 rp = raster; | |
1360 if (TIFFReadRGBAImage (unwind.tiff, width, height, raster, 0)) | |
1361 { | |
1362 for (i = height - 1; i >= 0; i--) | |
1363 { | |
1364 /* This is to get around weirdness in the libtiff library where properly | |
1365 made TIFFs will come out upside down. libtiff bug or jhod-brainlock? */ | |
1366 rp = raster + (i * width); | |
647 | 1367 for (j = 0; j < (int) width; j++) |
428 | 1368 { |
2367 | 1369 *ep++ = (Binbyte)TIFFGetR(*rp); |
1370 *ep++ = (Binbyte)TIFFGetG(*rp); | |
1371 *ep++ = (Binbyte)TIFFGetB(*rp); | |
428 | 1372 rp++; |
1373 } | |
1374 } | |
1375 } | |
1376 _TIFFfree (raster); | |
1377 } else | |
1378 signal_image_error ("Unable to allocate memory for TIFFReadRGBA", instantiator); | |
1379 | |
1380 } | |
1381 | |
1382 /* now instantiate */ | |
442 | 1383 MAYBE_DEVMETH (DOMAIN_XDEVICE (ii->domain), |
428 | 1384 init_image_instance_from_eimage, |
1385 (ii, width, height, 1, unwind.eimage, dest_mask, | |
2959 | 1386 instantiator, pointer_fg, pointer_bg, domain)); |
428 | 1387 |
771 | 1388 unbind_to (speccount); |
428 | 1389 } |
1390 | |
1391 #endif /* HAVE_TIFF */ | |
1392 | |
1393 | |
1394 /************************************************************************/ | |
1395 /* initialization */ | |
1396 /************************************************************************/ | |
1397 | |
1398 void | |
1399 syms_of_glyphs_eimage (void) | |
1400 { | |
1401 } | |
1402 | |
1403 void | |
1404 image_instantiator_format_create_glyphs_eimage (void) | |
1405 { | |
1406 /* image-instantiator types */ | |
1407 #ifdef HAVE_JPEG | |
1408 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (jpeg, "jpeg"); | |
1409 | |
1410 IIFORMAT_HAS_METHOD (jpeg, validate); | |
1411 IIFORMAT_HAS_METHOD (jpeg, normalize); | |
1412 IIFORMAT_HAS_METHOD (jpeg, possible_dest_types); | |
1413 IIFORMAT_HAS_METHOD (jpeg, instantiate); | |
1414 | |
1415 IIFORMAT_VALID_KEYWORD (jpeg, Q_data, check_valid_string); | |
1416 IIFORMAT_VALID_KEYWORD (jpeg, Q_file, check_valid_string); | |
1417 #endif | |
1418 | |
1419 #ifdef HAVE_GIF | |
1420 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (gif, "gif"); | |
1421 | |
1422 IIFORMAT_HAS_METHOD (gif, validate); | |
1423 IIFORMAT_HAS_METHOD (gif, normalize); | |
1424 IIFORMAT_HAS_METHOD (gif, possible_dest_types); | |
1425 IIFORMAT_HAS_METHOD (gif, instantiate); | |
1426 | |
1427 IIFORMAT_VALID_KEYWORD (gif, Q_data, check_valid_string); | |
1428 IIFORMAT_VALID_KEYWORD (gif, Q_file, check_valid_string); | |
1429 #endif | |
1430 | |
1431 #ifdef HAVE_PNG | |
1432 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (png, "png"); | |
1433 | |
1434 IIFORMAT_HAS_METHOD (png, validate); | |
1435 IIFORMAT_HAS_METHOD (png, normalize); | |
1436 IIFORMAT_HAS_METHOD (png, possible_dest_types); | |
1437 IIFORMAT_HAS_METHOD (png, instantiate); | |
1438 | |
1439 IIFORMAT_VALID_KEYWORD (png, Q_data, check_valid_string); | |
1440 IIFORMAT_VALID_KEYWORD (png, Q_file, check_valid_string); | |
1441 #endif | |
1442 | |
1443 #ifdef HAVE_TIFF | |
1444 INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tiff, "tiff"); | |
1445 | |
1446 IIFORMAT_HAS_METHOD (tiff, validate); | |
1447 IIFORMAT_HAS_METHOD (tiff, normalize); | |
1448 IIFORMAT_HAS_METHOD (tiff, possible_dest_types); | |
1449 IIFORMAT_HAS_METHOD (tiff, instantiate); | |
1450 | |
1451 IIFORMAT_VALID_KEYWORD (tiff, Q_data, check_valid_string); | |
1452 IIFORMAT_VALID_KEYWORD (tiff, Q_file, check_valid_string); | |
1453 #endif | |
1454 | |
1455 } | |
1456 | |
1457 void | |
1458 vars_of_glyphs_eimage (void) | |
1459 { | |
1460 #ifdef HAVE_JPEG | |
1461 Fprovide (Qjpeg); | |
1462 #endif | |
1463 | |
1464 #ifdef HAVE_GIF | |
1465 Fprovide (Qgif); | |
1466 #endif | |
1467 | |
1468 #ifdef HAVE_PNG | |
1469 Fprovide (Qpng); | |
1470 #endif | |
1471 | |
1472 #ifdef HAVE_TIFF | |
1473 Fprovide (Qtiff); | |
1474 #endif | |
1475 | |
1476 } |