(XPutPixel): Handle monochrome images; used for masks.
authorJason Rumney <jasonr@gnu.org>
Sat, 25 Jan 2003 20:45:29 +0000 (20:45 +0000)
committerJason Rumney <jasonr@gnu.org>
Sat, 25 Jan 2003 20:45:29 +0000 (20:45 +0000)
[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.

src/w32fns.c

index 1e54a07..4eeb08c 100644 (file)
@@ -57,6 +57,7 @@ Boston, MA 02111-1307, USA.  */
 
 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 @@ forall_images_in_image_cache (f, fn)
                            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 @@ static void XPutPixel (ximg, x, y, color)
        *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 @@ static struct image_type png_type =
   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_read_from_memory (png_ptr, data, length)
      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 @@ png_load (f, img)
 
       /* 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 @@ png_load (f, img)
 
       /* 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 @@ png_load (f, img)
     }
 
   /* 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 @@ png_load (f, img)
       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 @@ png_load (f, img)
     {
     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 @@ png_load (f, img)
 
   /* Read image info.  */
   if (!NILP (specified_data))
-    png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
+    fn_png_set_read_fn (png_ptr, (void *) &tbr, png_read_from_memory);
   else
-    png_init_io (png_ptr, fp);
+    fn_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_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 @@ png_load (f, img)
 
   /* 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 @@ png_load (f, img)
              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 @@ png_load (f, img)
          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 @@ png_load (f, img)
     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 @@ png_load (f, img)
        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 @@ png_load (f, img)
 #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 @@ gif_load (f, img)
 
 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 @@ versions of Windows) characters.  */);
   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 @@ versions of Windows) characters.  */);
   staticpro (&QCpt_width);
   QCpt_height = intern (":pt-height");
   staticpro (&QCpt_height);
-#endif
   QCindex = intern (":index");
   staticpro (&QCindex);
   Qpbm = intern ("pbm");
@@ -15559,18 +15624,11 @@ void globals_of_w32fns ()
   track_mouse_event_fn = (TrackMouseEvent_Proc) GetProcAddress (user32_lib, "TrackMouseEvent");
 }
 
-       
-void
-init_xfns ()
+/* Initialize image types. Based on which libraries are available.  */
+static void
+init_external_image_libraries ()
 {
-  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
+  HINSTANCE png_lib;
 
 #if HAVE_XPM
   define_image_type (&xpm_type);
@@ -15589,10 +15647,41 @@ init_xfns ()
 #endif
 
 #if HAVE_PNG
-  define_image_type (&png_type);
+  /* 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
 
 void