From mboxrd@z Thu Jan 1 00:00:00 1970 Path: main.gmane.org!not-for-mail From: Juanma Barranquero Newsgroups: gmane.emacs.devel Subject: [PATCH] Delayed loading of image libraries Date: Thu, 10 Jun 2004 14:38:46 +0200 Sender: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Message-ID: <20040610133420.CAC7.JMBARRANQUERO@wke.es> NNTP-Posting-Host: deer.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit X-Trace: sea.gmane.org 1086871158 3711 80.91.224.253 (10 Jun 2004 12:39:18 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Thu, 10 Jun 2004 12:39:18 +0000 (UTC) Original-X-From: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Thu Jun 10 14:39:08 2004 Return-path: Original-Received: from quimby.gnus.org ([80.91.224.244]) by deer.gmane.org with esmtp (Exim 3.35 #1 (Debian)) id 1BYOpo-0007ky-00 for ; Thu, 10 Jun 2004 14:39:08 +0200 Original-Received: from lists.gnu.org ([199.232.76.165]) by quimby.gnus.org with esmtp (Exim 3.35 #1 (Debian)) id 1BYOpo-0002yu-00 for ; Thu, 10 Jun 2004 14:39:08 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.33) id 1BYOqU-0000Ej-OG for emacs-devel@quimby.gnus.org; Thu, 10 Jun 2004 08:39:50 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.33) id 1BYOqS-0000Dm-CX for emacs-devel@gnu.org; Thu, 10 Jun 2004 08:39:48 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.33) id 1BYOqR-0000CR-22 for emacs-devel@gnu.org; Thu, 10 Jun 2004 08:39:47 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.33) id 1BYOqQ-0000CG-U4 for emacs-devel@gnu.org; Thu, 10 Jun 2004 08:39:46 -0400 Original-Received: from [62.22.181.117] (helo=idefix.laley.net) by monty-python.gnu.org with esmtp (Exim 4.34) id 1BYOpS-0006BJ-PD for emacs-devel@gnu.org; Thu, 10 Jun 2004 08:38:47 -0400 Original-Received: from [172.17.221.23] (JMBARRANQUERO [172.17.221.23]) by idefix.laley.net with SMTP (Microsoft Exchange Internet Mail Service Version 5.5.2655.55) id LSNJ7CFL; Thu, 10 Jun 2004 14:38:02 +0200 Original-To: emacs-devel@gnu.org X-Mailer: Becky! ver. 2.08.01 [en] X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.4 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+emacs-devel=quimby.gnus.org@gnu.org Xref: main.gmane.org gmane.emacs.devel:24799 X-Report-Spam: http://spam.gmane.org/gmane.emacs.devel:24799 OK, this is the (hopefully) final version of the "delayed loading" patch. It is almost identical to the last one, except for renaming a few things and adding a missing staticpro that was causing problems on bootstrapping. I've added docs to display.texi, and an entry to etc/NEWS (though I'm, as always, unsure about the right place to put the entry). The only thing lacking is ChangeLog entries. As I said a few days ago, I'd like to install this on trunk, if no one has objections. Any comments welcome, of course. Juanma --- old/etc/NEWS 2004-06-10 09:27:32.000000000 +0200 +++ new/etc/NEWS 2004-06-10 13:32:53.000000000 +0200 @@ -17,4 +17,8 @@ * Installation Changes in Emacs 21.4 +** On MS Windows, Emacs now loads the image libraries on demand. +You can configure the supported image types and their associated dynamic +libraries by setting the variable `image-library-alist'. + --- ** A Bulgarian translation of the Emacs Tutorial is available. diff -Bru2 old/lisp/image.el new/lisp/image.el --- old/lisp/image.el 2004-06-10 09:27:54.000000000 +0200 +++ new/lisp/image.el 2004-06-10 11:46:40.000000000 +0200 @@ -49,4 +49,15 @@ a non-nil value, TYPE is the image's type.") +;;;###autoload +(defvar image-library-alist nil + "Alist of image types vs external libraries needed to display them. + +Each element is a list (IMAGE-TYPE LIBRARY...), where the car is a symbol +representing a supported image type, and the rest are strings giving +alternate filenames for the corresponding external libraries to load. +They are tried in the order they appear on the list; if none of them can +be loaded, the running session of Emacs won't display the image type. +No entries are needed for pbm and xbm images; they're always supported.") +;;;###autoload (put 'image-library-alist 'risky-local-variable t) (defun image-jpeg-p (data) @@ -112,6 +123,6 @@ "Value is non-nil if image type TYPE is available. Image types are symbols like `xbm' or `jpeg'." - (and (boundp 'image-types) (not (null (memq type image-types))))) - + (and (fboundp 'init-image-library) + (init-image-library type image-library-alist))) ;;;###autoload diff -Bru2 old/lisp/term/w32-win.el new/lisp/term/w32-win.el --- old/lisp/term/w32-win.el 2004-06-10 09:28:04.000000000 +0200 +++ new/lisp/term/w32-win.el 2004-06-10 11:46:41.000000000 +0200 @@ -1262,4 +1262,12 @@ (error "Font not found"))))) +;;; Set default known names for image libraries +(setq image-library-alist + '((xpm "libXpm-nox4.dll" "libxpm.dll") + (png "libpng13d.dll" "libpng13.dll" "libpng12d.dll" "libpng12.dll" "libpng.dll") + (jpeg "jpeg62.dll" "libjpeg.dll" "jpeg-62.dll" "jpeg.dll") + (tiff "libtiff3.dll" "libtiff.dll") + (gif "libungif.dll"))) + ;;; arch-tag: 69fb1701-28c2-4890-b351-3d1fe4b4f166 ;;; w32-win.el ends here diff -Bru2 old/lispref/display.texi new/lispref/display.texi --- old/lispref/display.texi 2004-06-10 09:28:10.000000000 +0200 +++ new/lispref/display.texi 2004-06-10 13:01:02.000000000 +0200 @@ -2876,6 +2876,11 @@ Emacs can display a number of different image formats; some of them -are supported only if particular support libraries are installed on your -machine. The supported image formats include XBM, XPM (needing the +are supported only if particular support libraries are installed on +your machine. In some environments, Emacs allows loading image +libraries on demand; if so, the variable @code{image-library-alist} +can be used to modify the set of known names for these dynamic +libraries (though it is not posible to add new image formats). + + The supported image formats include XBM, XPM (needing the libraries @code{libXpm} version 3.4k and @code{libz}), GIF (needing @code{libungif} 4.1.0), Postscript, PBM, JPEG (needing the @@ -2888,9 +2893,47 @@ @defvar image-types +@vindex image-types This variable contains a list of those image type symbols that are -supported in the current configuration. +potentially supported in the current configuration. +@emph{Potentially} here means that Emacs knows about the image types, +not necessarily that they can be loaded (they could depend on +unavailable dynamic libraries, for example). + +To know which image types are really available, use +@code{image-type-available-p}. +@end defvar + +@defvar image-library-alist +@vindex image-library-alist +This in an alist of image types vs external libraries needed to +display them. + +Each element is a list @code{(@var{IMAGE-TYPE} @var{LIBRARY}...)}, +where the car is a supported image format from @code{image-types}, and +the rest are strings giving alternate filenames for the corresponding +external libraries to load. + +They are tried in the order they appear on the list; if none of them +can be loaded, the running session of Emacs won't support the image +type. No entries are needed for @code{pbm} and @code{xbm} images; +they're always supported. + +This variable is ignored if the image libraries are statically linked +into Emacs. @end defvar +@defun image-type-available-p type +@findex image-type-available-p + +This function returns non-nil if image type TYPE is available, i.e., +if images of this type can be loaded and displayed in Emacs. TYPE +should be one of the types contained in @code{image-types}. + +For image types whose support libraries are statically linked, this +function always returns @code{t}; for other image types, it returns +@code{t} if the dynamic library could be loaded, @code{nil} otherwise. +@end defun + @menu * Image Descriptors:: How to specify an image for use in @code{:display}. --- old/src/dispextern.h 2004-06-10 09:28:19.000000000 +0200 +++ new/src/dispextern.h 2004-06-10 11:46:41.000000000 +0200 @@ -2569,5 +2569,4 @@ extern int mode_line_in_non_selected_windows; extern int redisplaying_p; -extern Lisp_Object Vimage_types; extern void add_to_log P_ ((char *, Lisp_Object, Lisp_Object)); extern int help_echo_showing_p; @@ -2655,4 +2654,6 @@ #ifdef HAVE_WINDOW_SYSTEM +extern Lisp_Object Vimage_types; + extern int x_bitmap_height P_ ((struct frame *, int)); extern int x_bitmap_width P_ ((struct frame *, int)); diff -Bru2 old/src/image.c new/src/image.c --- old/src/image.c 2004-06-10 09:28:20.000000000 +0200 +++ new/src/image.c 2004-06-10 11:51:49.000000000 +0200 @@ -606,4 +606,12 @@ static struct image_type *image_types; +/* A list of symbols, one for each supported image type. */ + +Lisp_Object Vimage_types; + +/* Cache for delayed-loading image types. */ + +static Lisp_Object Vimage_type_cache; + /* The symbol `xbm' which is used as the type symbol for XBM images. */ @@ -630,5 +638,5 @@ /* Function prototypes. */ -static void define_image_type P_ ((struct image_type *type)); +static Lisp_Object define_image_type P_ ((struct image_type *type, int loaded)); static struct image_type *lookup_image_type P_ ((Lisp_Object symbol)); static void image_error P_ ((char *format, Lisp_Object, Lisp_Object)); @@ -638,19 +646,35 @@ Lisp_Object)); +#define CACHE_IMAGE_TYPE(type, status) \ + do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0) + +#define ADD_IMAGE_TYPE(type) \ + do { Vimage_types = Fcons (type, Vimage_types); } while (0) /* Define a new image type from TYPE. This adds a copy of TYPE to - image_types and adds the symbol *TYPE->type to Vimage_types. */ + image_types and caches the loading status of TYPE. */ -static void -define_image_type (type) +static Lisp_Object +define_image_type (type, loaded) struct image_type *type; + int loaded; { - /* Make a copy of TYPE to avoid a bus error in a dumped Emacs. - The initialized data segment is read-only. */ - struct image_type *p = (struct image_type *) xmalloc (sizeof *p); - bcopy (type, p, sizeof *p); - p->next = image_types; - image_types = p; - Vimage_types = Fcons (*p->type, Vimage_types); + Lisp_Object success; + + if (!loaded) + success = Qnil; + else + { + /* Make a copy of TYPE to avoid a bus error in a dumped Emacs. + The initialized data segment is read-only. */ + struct image_type *p = (struct image_type *) xmalloc (sizeof *p); + bcopy (type, p, sizeof *p); + p->next = image_types; + image_types = p; + success = Qt; + } + + CACHE_IMAGE_TYPE(*type->type, success); + return success; } @@ -1789,4 +1813,31 @@ } +/* Load a DLL implementing an image type. + The `image-library-alist' variable associates a symbol, + identifying an image type, to a list of possible filenames. + The function returns NULL if no library could be loaded for + the given image type, or if the library was previously loaded; + else the handle of the DLL. */ +static HMODULE +w32_delayed_load (Lisp_Object libraries, Lisp_Object type) +{ + HMODULE library = NULL; + + if (CONSP (libraries) && NILP (Fassq (type, Vimage_type_cache))) + { + Lisp_Object dlls = Fassq (type, libraries); + + if (CONSP (dlls)) + for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls)) + { + CHECK_STRING_CAR (dlls); + if (library = LoadLibrary (SDATA (XCAR (dlls)))) + break; + } + } + + return library; +} + #endif /* HAVE_NTGUI */ @@ -3489,11 +3540,10 @@ DEF_IMGLIB_FN (XImageFree); - static int -init_xpm_functions (void) +init_xpm_functions (Lisp_Object libraries) { HMODULE library; - if (!(library = LoadLibrary ("libXpm.dll"))) + if (!(library = w32_delayed_load (libraries, Qxpm))) return 0; @@ -5589,19 +5639,10 @@ static int -init_png_functions (void) +init_png_functions (Lisp_Object libraries) { HMODULE library; - /* Ensure zlib is loaded. Try debug version first. */ - if (!LoadLibrary ("zlibd.dll") - && !LoadLibrary ("zlib.dll")) - return 0; - /* Try loading libpng under probable names. */ - if (!(library = LoadLibrary ("libpng13d.dll")) - && !(library = LoadLibrary ("libpng13.dll")) - && !(library = LoadLibrary ("libpng12d.dll")) - && !(library = LoadLibrary ("libpng12.dll")) - && !(library = LoadLibrary ("libpng.dll"))) + if (!(library = w32_delayed_load (libraries, Qpng))) return 0; @@ -6247,11 +6288,9 @@ static int -init_jpeg_functions (void) +init_jpeg_functions (Lisp_Object libraries) { HMODULE library; - if (!(library = LoadLibrary ("libjpeg.dll")) - && !(library = LoadLibrary ("jpeg-62.dll")) - && !(library = LoadLibrary ("jpeg.dll"))) + if (!(library = w32_delayed_load (libraries, Qjpeg))) return 0; @@ -6684,9 +6723,9 @@ static int -init_tiff_functions (void) +init_tiff_functions (Lisp_Object libraries) { HMODULE library; - if (!(library = LoadLibrary ("libtiff.dll"))) + if (!(library = w32_delayed_load (libraries, Qtiff))) return 0; @@ -7104,9 +7143,9 @@ static int -init_gif_functions (void) +init_gif_functions (Lisp_Object libraries) { HMODULE library; - if (!(library = LoadLibrary ("libungif.dll"))) + if (!(library = w32_delayed_load (libraries, Qgif))) return 0; @@ -7881,7 +7920,79 @@ ***********************************************************************/ +#ifdef HAVE_NTGUI +/* Image types that rely on external libraries are loaded dynamically + if the library is available. */ +#define CHECK_LIB_AVAILABLE(image_type, init_lib_fn) \ + define_image_type (image_type, init_lib_fn (libraries)) +#else +#define CHECK_LIB_AVAILABLE(image_type, init_lib_fn) \ + define_image_type (image_type, TRUE) +#endif /* HAVE_NTGUI */ + +DEFUN ("init-image-library", Finit_image_library, Sinit_image_library, 2, 2, 0, + doc: /* Initialize image library implementing image type TYPE. +Return non-nil if TYPE is a supported image type. + +Image types pbm and xbm are prebuilt; other types are loaded here. +Libraries to load are specified in alist LIBRARIES (usually, the value +of `image-library-alist', which see. */) + (type, libraries) +{ + Lisp_Object tested; + + /* Don't try to reload the library. */ + tested = Fassq (type, Vimage_type_cache); + if (CONSP (tested)) + return XCDR (tested); + +#if defined (HAVE_XPM) || defined (MAC_OS) + if (EQ (type, Qxpm)) + return CHECK_LIB_AVAILABLE(&xpm_type, init_xpm_functions); +#endif + +#if defined (HAVE_JPEG) || defined (MAC_OS) + if (EQ (type, Qjpeg)) + return CHECK_LIB_AVAILABLE(&jpeg_type, init_jpeg_functions); +#endif + +#if defined (HAVE_TIFF) || defined (MAC_OS) + if (EQ (type, Qtiff)) + return CHECK_LIB_AVAILABLE(&tiff_type, init_tiff_functions); +#endif + +#if defined (HAVE_GIF) || defined (MAC_OS) + if (EQ (type, Qgif)) + return CHECK_LIB_AVAILABLE(&gif_type, init_gif_functions); +#endif + +#if defined (HAVE_PNG) || defined (MAC_OS) + if (EQ (type, Qpng)) + return CHECK_LIB_AVAILABLE(&png_type, init_png_functions); +#endif + +#ifdef HAVE_GHOSTSCRIPT + if (EQ (type, Qpostscript)) + return CHECK_LIB_AVAILABLE(&gs_type, init_gs_functions); +#endif + + /* If the type is not recognized, avoid testing it ever again. */ + CACHE_IMAGE_TYPE(type, Qnil); + return Qnil; +} + void syms_of_image () { + /* Must be defined now becase we're going to update it below, while + defining the supported image types. */ + DEFVAR_LISP ("image-types", &Vimage_types, + doc: /* List of potentially supported image types. +Each element of the list is a symbol for a image type, like 'jpeg or 'png. +To check whether it is really supported, use `image-type-available-p'. */); + Vimage_types = Qnil; + + Vimage_type_cache = Qnil; + staticpro (&Vimage_type_cache); + QCascent = intern (":ascent"); staticpro (&QCascent); @@ -7917,4 +8028,5 @@ staticpro (&Qpostscript); #ifdef HAVE_GHOSTSCRIPT + ADD_IMAGE_TYPE(Qpostscript); QCloader = intern (":loader"); staticpro (&QCloader); @@ -7929,11 +8041,14 @@ Qpbm = intern ("pbm"); staticpro (&Qpbm); + ADD_IMAGE_TYPE(Qpbm); Qxbm = intern ("xbm"); staticpro (&Qxbm); + ADD_IMAGE_TYPE(Qxbm); #if defined (HAVE_XPM) || defined (MAC_OS) Qxpm = intern ("xpm"); staticpro (&Qxpm); + ADD_IMAGE_TYPE(Qxpm); #endif @@ -7941,4 +8056,5 @@ Qjpeg = intern ("jpeg"); staticpro (&Qjpeg); + ADD_IMAGE_TYPE(Qjpeg); #endif @@ -7946,4 +8062,5 @@ Qtiff = intern ("tiff"); staticpro (&Qtiff); + ADD_IMAGE_TYPE(Qtiff); #endif @@ -7951,4 +8068,5 @@ Qgif = intern ("gif"); staticpro (&Qgif); + ADD_IMAGE_TYPE(Qgif); #endif @@ -7956,6 +8074,8 @@ Qpng = intern ("png"); staticpro (&Qpng); + ADD_IMAGE_TYPE(Qpng); #endif + defsubr (&Sinit_image_library); defsubr (&Sclear_image_cache); defsubr (&Simage_size); @@ -7985,50 +8105,11 @@ } - -#ifdef HAVE_NTGUI -/* Image types that rely on external libraries are loaded dynamically - if the library is available. */ -#define IF_LIB_AVAILABLE(init_lib_fn) if (init_lib_fn()) -#else -#define IF_LIB_AVAILABLE(init_func) /* Load unconditionally */ -#endif /* HAVE_NTGUI */ - void init_image () { image_types = NULL; - Vimage_types = Qnil; - define_image_type (&xbm_type); - define_image_type (&pbm_type); - -#if defined (HAVE_XPM) || defined (MAC_OS) - IF_LIB_AVAILABLE(init_xpm_functions) - define_image_type (&xpm_type); -#endif - -#if defined (HAVE_JPEG) || defined (MAC_OS) - IF_LIB_AVAILABLE(init_jpeg_functions) - define_image_type (&jpeg_type); -#endif - -#if defined (HAVE_TIFF) || defined (MAC_OS) - IF_LIB_AVAILABLE(init_tiff_functions) - define_image_type (&tiff_type); -#endif - -#if defined (HAVE_GIF) || defined (MAC_OS) - IF_LIB_AVAILABLE(init_gif_functions) - define_image_type (&gif_type); -#endif - -#if defined (HAVE_PNG) || defined (MAC_OS) - IF_LIB_AVAILABLE(init_png_functions) - define_image_type (&png_type); -#endif - -#ifdef HAVE_GHOSTSCRIPT - define_image_type (&gs_type); -#endif + define_image_type (&xbm_type, TRUE); + define_image_type (&pbm_type, TRUE); #ifdef MAC_OS diff -Bru2 old/src/xdisp.c new/src/xdisp.c --- old/src/xdisp.c 2004-06-10 09:28:26.000000000 +0200 +++ new/src/xdisp.c 2004-06-10 11:46:41.000000000 +0200 @@ -671,8 +671,4 @@ Lisp_Object Vhscroll_step; -/* A list of symbols, one for each supported image type. */ - -Lisp_Object Vimage_types; - /* The variable `resize-mini-windows'. If nil, don't resize mini-windows. If t, always resize them to fit the text they @@ -22260,9 +22256,4 @@ Vhscroll_step = make_number (0); - DEFVAR_LISP ("image-types", &Vimage_types, - doc: /* List of supported image types. -Each element of the list is a symbol for a supported image type. */); - Vimage_types = Qnil; - DEFVAR_BOOL ("message-truncate-lines", &message_truncate_lines, doc: /* If non-nil, messages are truncated instead of resizing the echo area.