changeset 49448:26edfad422c5

(XPutPixel): Handle monochrome images; used for masks. [HAVE_PNG]: Sync with xfns.c version. (png_load): Adjust colors for Windows. Use Windows bitmaps. Disable color table lookups. (DEF_IMGLIB_FN, LOAD_IMGLIB_FN): New macros. (init_png_functions): New function. (png_read_from_memory, png_load): Call png library functions through pointers determined at runtime. (QCloader, QCbounding_box, QCpt_width, QCpt_height): Declare. (init_external_image_libraries): New function. (init_xfns): Call it.
author Jason Rumney <jasonr@gnu.org>
date Sat, 25 Jan 2003 20:45:29 +0000
parents d5ef8b62f209
children b153cf78084e
files src/w32fns.c
diffstat 1 files changed, 143 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/src/w32fns.c	Sat Jan 25 19:49:44 2003 +0000
+++ b/src/w32fns.c	Sat Jan 25 20:45:29 2003 +0000
@@ -57,6 +57,7 @@
 
 void syms_of_w32fns ();
 void globals_of_w32fns ();
+static void init_external_image_libraries ();
 
 extern void free_frame_menubar ();
 extern void x_compute_fringe_widths P_ ((struct frame *, int));
@@ -9336,6 +9337,15 @@
 			    W32 support code
  ***********************************************************************/
 
+/* Macro for defining functions that will be loaded from image DLLs.  */
+#define DEF_IMGLIB_FN(func) FARPROC fn_##func
+    
+/* Macro for loading those image functions from the library.  */
+#define LOAD_IMGLIB_FN(lib,func) {					\
+    fn_##func = (void *) GetProcAddress (lib, #func);			\
+    if (!fn_##func) return 0;						\
+  } 
+
 static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
                                             XImage **, Pixmap *));
 static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
@@ -10843,7 +10853,7 @@
 	*pixel = *pixel & ~(1 << x % 8);
     }
   else
-    image_error ("XPutPixel: palette image not supported.", NULL, Qnil);
+    image_error ("XPutPixel: palette image not supported.", Qnil, Qnil);
 }
 
 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
@@ -11625,6 +11635,59 @@
   NULL
 };
 
+/* PNG library details.  */
+
+DEF_IMGLIB_FN (png_get_io_ptr);
+DEF_IMGLIB_FN (png_check_sig);
+DEF_IMGLIB_FN (png_create_read_struct);
+DEF_IMGLIB_FN (png_create_info_struct);
+DEF_IMGLIB_FN (png_destroy_read_struct);
+DEF_IMGLIB_FN (png_set_read_fn);
+DEF_IMGLIB_FN (png_init_io);  
+DEF_IMGLIB_FN (png_set_sig_bytes);
+DEF_IMGLIB_FN (png_read_info);
+DEF_IMGLIB_FN (png_get_IHDR);
+DEF_IMGLIB_FN (png_get_valid);
+DEF_IMGLIB_FN (png_set_strip_16);
+DEF_IMGLIB_FN (png_set_expand);
+DEF_IMGLIB_FN (png_set_gray_to_rgb);
+DEF_IMGLIB_FN (png_set_background);
+DEF_IMGLIB_FN (png_get_bKGD);
+DEF_IMGLIB_FN (png_read_update_info);
+DEF_IMGLIB_FN (png_get_channels);
+DEF_IMGLIB_FN (png_get_rowbytes);
+DEF_IMGLIB_FN (png_read_image);
+DEF_IMGLIB_FN (png_read_end);
+DEF_IMGLIB_FN (png_error);
+
+static int
+init_png_functions (library)
+     HMODULE library;
+{
+  LOAD_IMGLIB_FN (library, png_get_io_ptr);
+  LOAD_IMGLIB_FN (library, png_check_sig);
+  LOAD_IMGLIB_FN (library, png_create_read_struct);
+  LOAD_IMGLIB_FN (library, png_create_info_struct);
+  LOAD_IMGLIB_FN (library, png_destroy_read_struct);
+  LOAD_IMGLIB_FN (library, png_set_read_fn);
+  LOAD_IMGLIB_FN (library, png_init_io);  
+  LOAD_IMGLIB_FN (library, png_set_sig_bytes);
+  LOAD_IMGLIB_FN (library, png_read_info);
+  LOAD_IMGLIB_FN (library, png_get_IHDR);
+  LOAD_IMGLIB_FN (library, png_get_valid);
+  LOAD_IMGLIB_FN (library, png_set_strip_16);
+  LOAD_IMGLIB_FN (library, png_set_expand);
+  LOAD_IMGLIB_FN (library, png_set_gray_to_rgb);
+  LOAD_IMGLIB_FN (library, png_set_background);
+  LOAD_IMGLIB_FN (library, png_get_bKGD);
+  LOAD_IMGLIB_FN (library, png_read_update_info);
+  LOAD_IMGLIB_FN (library, png_get_channels);
+  LOAD_IMGLIB_FN (library, png_get_rowbytes);
+  LOAD_IMGLIB_FN (library, png_read_image);
+  LOAD_IMGLIB_FN (library, png_read_end);
+  LOAD_IMGLIB_FN (library, png_error);
+  return 1;
+}
 
 /* Return non-zero if OBJECT is a valid PNG image specification.  */
 
@@ -11687,10 +11750,10 @@
      png_size_t length;
 {
   struct png_memory_storage *tbr
-    = (struct png_memory_storage *) png_get_io_ptr (png_ptr);
+    = (struct png_memory_storage *) fn_png_get_io_ptr (png_ptr);
 
   if (length > tbr->len - tbr->index)
-    png_error (png_ptr, "Read error");
+    fn_png_error (png_ptr, "Read error");
   
   bcopy (tbr->bytes + tbr->index, data, length);
   tbr->index = tbr->index + length;
@@ -11752,7 +11815,7 @@
 
       /* Check PNG signature.  */
       if (fread (sig, 1, sizeof sig, fp) != sizeof sig
-	  || !png_check_sig (sig, sizeof sig))
+	  || !fn_png_check_sig (sig, sizeof sig))
 	{
 	  image_error ("Not a PNG file: `%s'", file, Qnil);
 	  UNGCPRO;
@@ -11769,7 +11832,7 @@
 
       /* Check PNG signature.  */
       if (tbr.len < sizeof sig
-	  || !png_check_sig (tbr.bytes, sizeof sig))
+	  || !fn_png_check_sig (tbr.bytes, sizeof sig))
 	{
 	  image_error ("Not a PNG image: `%s'", img->spec, Qnil);
 	  UNGCPRO;
@@ -11781,8 +11844,8 @@
     }
 
   /* Initialize read and info structs for PNG lib.  */
-  png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
-				    my_png_error, my_png_warning);
+  png_ptr = fn_png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
+				       my_png_error, my_png_warning);
   if (!png_ptr)
     {
       if (fp) fclose (fp);
@@ -11790,19 +11853,19 @@
       return 0;
     }
 
-  info_ptr = png_create_info_struct (png_ptr);
+  info_ptr = fn_png_create_info_struct (png_ptr);
   if (!info_ptr)
     {
-      png_destroy_read_struct (&png_ptr, NULL, NULL);
+      fn_png_destroy_read_struct (&png_ptr, NULL, NULL);
       if (fp) fclose (fp);
       UNGCPRO;
       return 0;
     }
 
-  end_info = png_create_info_struct (png_ptr);
+  end_info = fn_png_create_info_struct (png_ptr);
   if (!end_info)
     {
-      png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
+      fn_png_destroy_read_struct (&png_ptr, &info_ptr, NULL);
       if (fp) fclose (fp);
       UNGCPRO;
       return 0;
@@ -11814,7 +11877,7 @@
     {
     error:
       if (png_ptr)
-        png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
+        fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
       xfree (pixels);
       xfree (rows);
       if (fp) fclose (fp);
@@ -11824,18 +11887,18 @@
 
   /* Read image info.  */
   if (!NILP (specified_data))
-    png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
-  else
-    png_init_io (png_ptr, fp);
-
-  png_set_sig_bytes (png_ptr, sizeof sig);
-  png_read_info (png_ptr, info_ptr);
-  png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
-	        &interlace_type, NULL, NULL);
+    fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
+  else
+    fn_png_init_io (png_ptr, fp);
+
+  fn_png_set_sig_bytes (png_ptr, sizeof sig);
+  fn_png_read_info (png_ptr, info_ptr);
+  fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
+		   &interlace_type, NULL, NULL);
 
   /* If image contains simply transparency data, we prefer to 
      construct a clipping mask.  */
-  if (png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
+  if (fn_png_get_valid (png_ptr, info_ptr, PNG_INFO_tRNS))
     transparent_p = 1;
   else
     transparent_p = 0;
@@ -11846,16 +11909,16 @@
 
   /* Strip more than 8 bits per channel.  */
   if (bit_depth == 16)
-    png_set_strip_16 (png_ptr);
+    fn_png_set_strip_16 (png_ptr);
 
   /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
      if available.  */
-  png_set_expand (png_ptr);
+  fn_png_set_expand (png_ptr);
 
   /* Convert grayscale images to RGB.  */
   if (color_type == PNG_COLOR_TYPE_GRAY 
       || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
-    png_set_gray_to_rgb (png_ptr);
+    fn_png_set_gray_to_rgb (png_ptr);
 
   screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
 
@@ -11897,15 +11960,15 @@
 	      user_bg.green = 256 * GetGValue (color);
 	      user_bg.blue = 256 * GetBValue (color);
 
-	      png_set_background (png_ptr, &user_bg,
-				  PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+	      fn_png_set_background (png_ptr, &user_bg,
+				     PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
 	    }
 	}
-      else if (png_get_bKGD (png_ptr, info_ptr, &image_bg))
+      else if (fn_png_get_bKGD (png_ptr, info_ptr, &image_bg))
 	/* Image contains a background color with which to 
 	   combine the image.  */
-	png_set_background (png_ptr, image_bg,
-			    PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
+	fn_png_set_background (png_ptr, image_bg,
+			       PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
       else
 	{
 	  /* Image does not contain a background color with which
@@ -11926,24 +11989,24 @@
 	  frame_background.green = 256 * GetGValue (color);
 	  frame_background.blue = 256 * GetBValue (color);
 
-	  png_set_background (png_ptr, &frame_background,
-			      PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
+	  fn_png_set_background (png_ptr, &frame_background,
+				 PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
 	}
     }
 
   /* Update info structure.  */
-  png_read_update_info (png_ptr, info_ptr);
+  fn_png_read_update_info (png_ptr, info_ptr);
 
   /* Get number of channels.  Valid values are 1 for grayscale images
      and images with a palette, 2 for grayscale images with transparency
      information (alpha channel), 3 for RGB images, and 4 for RGB
      images with alpha channel, i.e. RGBA.  If conversions above were
      sufficient we should only have 3 or 4 channels here.  */
-  channels = png_get_channels (png_ptr, info_ptr);
+  channels = fn_png_get_channels (png_ptr, info_ptr);
   xassert (channels == 3 || channels == 4);
 
   /* Number of bytes needed for one row of the image.  */
-  row_bytes = png_get_rowbytes (png_ptr, info_ptr);
+  row_bytes = fn_png_get_rowbytes (png_ptr, info_ptr);
 
   /* Allocate memory for the image.  */
   pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
@@ -11952,8 +12015,8 @@
     rows[i] = pixels + i * row_bytes;
 
   /* Read the entire image.  */
-  png_read_image (png_ptr, rows);
-  png_read_end (png_ptr, info_ptr);
+  fn_png_read_image (png_ptr, rows);
+  fn_png_read_end (png_ptr, info_ptr);
   if (fp)
     {
       fclose (fp);
@@ -12028,7 +12091,7 @@
        overrode it.  */
     {
       png_color_16 *bg;
-      if (png_get_bKGD (png_ptr, info_ptr, &bg))
+      if (fn_png_get_bKGD (png_ptr, info_ptr, &bg))
 	{
 #if 0 /* TODO: Color tables.  */
 	  img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
@@ -12047,7 +12110,7 @@
 #endif
 
   /* Clean up.  */
-  png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
+  fn_png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
   xfree (rows);
   xfree (pixels);
 
@@ -13122,6 +13185,10 @@
 
 Lisp_Object Qpostscript;
 
+/* Keyword symbols.  */
+
+Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
+
 #ifdef HAVE_GHOSTSCRIPT
 static int gs_image_p P_ ((Lisp_Object object));
 static int gs_load P_ ((struct frame *f, struct image *img));
@@ -15476,7 +15543,6 @@
   staticpro (&QCrelief);
   Qpostscript = intern ("postscript");
   staticpro (&Qpostscript);
-#if 0 /* TODO: These need entries at top of file.  */
   QCloader = intern (":loader");
   staticpro (&QCloader);
   QCbounding_box = intern (":bounding-box");
@@ -15485,7 +15551,6 @@
   staticpro (&QCpt_width);
   QCpt_height = intern (":pt-height");
   staticpro (&QCpt_height);
-#endif
   QCindex = intern (":index");
   staticpro (&QCindex);
   Qpbm = intern ("pbm");
@@ -15559,18 +15624,11 @@
   track_mouse_event_fn = (TrackMouseEvent_Proc) GetProcAddress (user32_lib, "TrackMouseEvent");
 }
 
-	
-void
-init_xfns ()
-{
-  image_types = NULL;
-  Vimage_types = Qnil;
-
-  define_image_type (&pbm_type);
-  define_image_type (&xbm_type);
-#if 0 /* TODO : Image support for W32 */
-  define_image_type (&gs_type);
-#endif
+/* Initialize image types. Based on which libraries are available.  */
+static void
+init_external_image_libraries ()
+{
+  HINSTANCE png_lib;
 
 #if HAVE_XPM
   define_image_type (&xpm_type);
@@ -15589,8 +15647,39 @@
 #endif
 
 #if HAVE_PNG
-  define_image_type (&png_type);
-#endif
+  /* Ensure zlib is loaded.  Try debug version first.  */
+  if (!LoadLibrary ("zlibd.dll"))
+    LoadLibrary ("zlib.dll");
+
+  /* Try loading libpng under probable names.  */
+  if ((png_lib = LoadLibrary ("libpng13d.dll"))
+      || (png_lib = LoadLibrary ("libpng13.dll"))
+      || (png_lib = LoadLibrary ("libpng12d.dll"))
+      || (png_lib = LoadLibrary ("libpng12.dll"))
+      || (png_lib = LoadLibrary ("libpng.dll")))
+    {
+      if (init_png_functions (png_lib))
+	define_image_type (&png_type);
+    }
+#endif
+}
+
+void
+init_xfns ()
+{
+  image_types = NULL;
+  Vimage_types = Qnil;
+
+  define_image_type (&pbm_type);
+  define_image_type (&xbm_type);
+
+#if 0 /* TODO : Ghostscript support for W32 */
+  define_image_type (&gs_type);
+#endif
+
+  /* Image types that rely on external libraries are loaded dynamically
+     if the library is available.  */
+  init_external_image_libraries ();
 }
 
 #undef abort