Commit 839b1909 authored by Jason Rumney's avatar Jason Rumney

(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.
parent 84e47416
...@@ -57,6 +57,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -57,6 +57,7 @@ Boston, MA 02111-1307, USA. */
void syms_of_w32fns (); void syms_of_w32fns ();
void globals_of_w32fns (); void globals_of_w32fns ();
static void init_external_image_libraries ();
extern void free_frame_menubar (); extern void free_frame_menubar ();
extern void x_compute_fringe_widths P_ ((struct frame *, int)); extern void x_compute_fringe_widths P_ ((struct frame *, int));
...@@ -9336,6 +9337,15 @@ forall_images_in_image_cache (f, fn) ...@@ -9336,6 +9337,15 @@ forall_images_in_image_cache (f, fn)
W32 support code 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, static int x_create_x_image_and_pixmap P_ ((struct frame *, int, int, int,
XImage **, Pixmap *)); XImage **, Pixmap *));
static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int)); static void x_put_x_image P_ ((struct frame *, XImage *, Pixmap, int, int));
...@@ -10843,7 +10853,7 @@ static void XPutPixel (ximg, x, y, color) ...@@ -10843,7 +10853,7 @@ static void XPutPixel (ximg, x, y, color)
*pixel = *pixel & ~(1 << x % 8); *pixel = *pixel & ~(1 << x % 8);
} }
else 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 /* Create IMG->pixmap from an array COLORS of XColor structures, whose
...@@ -11625,6 +11635,59 @@ static struct image_type png_type = ...@@ -11625,6 +11635,59 @@ static struct image_type png_type =
NULL 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. */ /* Return non-zero if OBJECT is a valid PNG image specification. */
...@@ -11687,10 +11750,10 @@ png_read_from_memory (png_ptr, data, length) ...@@ -11687,10 +11750,10 @@ png_read_from_memory (png_ptr, data, length)
png_size_t length; png_size_t length;
{ {
struct png_memory_storage *tbr 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) 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); bcopy (tbr->bytes + tbr->index, data, length);
tbr->index = tbr->index + length; tbr->index = tbr->index + length;
...@@ -11752,7 +11815,7 @@ png_load (f, img) ...@@ -11752,7 +11815,7 @@ png_load (f, img)
/* Check PNG signature. */ /* Check PNG signature. */
if (fread (sig, 1, sizeof sig, fp) != sizeof sig 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); image_error ("Not a PNG file: `%s'", file, Qnil);
UNGCPRO; UNGCPRO;
...@@ -11769,7 +11832,7 @@ png_load (f, img) ...@@ -11769,7 +11832,7 @@ png_load (f, img)
/* Check PNG signature. */ /* Check PNG signature. */
if (tbr.len < sizeof sig 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); image_error ("Not a PNG image: `%s'", img->spec, Qnil);
UNGCPRO; UNGCPRO;
...@@ -11781,8 +11844,8 @@ png_load (f, img) ...@@ -11781,8 +11844,8 @@ png_load (f, img)
} }
/* Initialize read and info structs for PNG lib. */ /* Initialize read and info structs for PNG lib. */
png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, png_ptr = fn_png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL,
my_png_error, my_png_warning); my_png_error, my_png_warning);
if (!png_ptr) if (!png_ptr)
{ {
if (fp) fclose (fp); if (fp) fclose (fp);
...@@ -11790,19 +11853,19 @@ png_load (f, img) ...@@ -11790,19 +11853,19 @@ png_load (f, img)
return 0; return 0;
} }
info_ptr = png_create_info_struct (png_ptr); info_ptr = fn_png_create_info_struct (png_ptr);
if (!info_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); if (fp) fclose (fp);
UNGCPRO; UNGCPRO;
return 0; return 0;
} }
end_info = png_create_info_struct (png_ptr); end_info = fn_png_create_info_struct (png_ptr);
if (!end_info) 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); if (fp) fclose (fp);
UNGCPRO; UNGCPRO;
return 0; return 0;
...@@ -11814,7 +11877,7 @@ png_load (f, img) ...@@ -11814,7 +11877,7 @@ png_load (f, img)
{ {
error: error:
if (png_ptr) 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 (pixels);
xfree (rows); xfree (rows);
if (fp) fclose (fp); if (fp) fclose (fp);
...@@ -11824,18 +11887,18 @@ png_load (f, img) ...@@ -11824,18 +11887,18 @@ png_load (f, img)
/* Read image info. */ /* Read image info. */
if (!NILP (specified_data)) 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 else
png_init_io (png_ptr, fp); fn_png_init_io (png_ptr, fp);
png_set_sig_bytes (png_ptr, sizeof sig); fn_png_set_sig_bytes (png_ptr, sizeof sig);
png_read_info (png_ptr, info_ptr); fn_png_read_info (png_ptr, info_ptr);
png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, fn_png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
&interlace_type, NULL, NULL); &interlace_type, NULL, NULL);
/* If image contains simply transparency data, we prefer to /* If image contains simply transparency data, we prefer to
construct a clipping mask. */ 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; transparent_p = 1;
else else
transparent_p = 0; transparent_p = 0;
...@@ -11846,16 +11909,16 @@ png_load (f, img) ...@@ -11846,16 +11909,16 @@ png_load (f, img)
/* Strip more than 8 bits per channel. */ /* Strip more than 8 bits per channel. */
if (bit_depth == 16) 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 /* Expand data to 24 bit RGB, or 8 bit grayscale, with alpha channel
if available. */ if available. */
png_set_expand (png_ptr); fn_png_set_expand (png_ptr);
/* Convert grayscale images to RGB. */ /* Convert grayscale images to RGB. */
if (color_type == PNG_COLOR_TYPE_GRAY if (color_type == PNG_COLOR_TYPE_GRAY
|| color_type == PNG_COLOR_TYPE_GRAY_ALPHA) || 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); screen_gamma = (f->gamma ? 1 / f->gamma / 0.45455 : 2.2);
...@@ -11897,15 +11960,15 @@ png_load (f, img) ...@@ -11897,15 +11960,15 @@ png_load (f, img)
user_bg.green = 256 * GetGValue (color); user_bg.green = 256 * GetGValue (color);
user_bg.blue = 256 * GetBValue (color); user_bg.blue = 256 * GetBValue (color);
png_set_background (png_ptr, &user_bg, fn_png_set_background (png_ptr, &user_bg,
PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); 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 /* Image contains a background color with which to
combine the image. */ combine the image. */
png_set_background (png_ptr, image_bg, fn_png_set_background (png_ptr, image_bg,
PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); PNG_BACKGROUND_GAMMA_FILE, 1, 1.0);
else else
{ {
/* Image does not contain a background color with which /* Image does not contain a background color with which
...@@ -11926,24 +11989,24 @@ png_load (f, img) ...@@ -11926,24 +11989,24 @@ png_load (f, img)
frame_background.green = 256 * GetGValue (color); frame_background.green = 256 * GetGValue (color);
frame_background.blue = 256 * GetBValue (color); frame_background.blue = 256 * GetBValue (color);
png_set_background (png_ptr, &frame_background, fn_png_set_background (png_ptr, &frame_background,
PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0); PNG_BACKGROUND_GAMMA_SCREEN, 0, 1.0);
} }
} }
/* Update info structure. */ /* 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 /* Get number of channels. Valid values are 1 for grayscale images
and images with a palette, 2 for grayscale images with transparency and images with a palette, 2 for grayscale images with transparency
information (alpha channel), 3 for RGB images, and 4 for RGB information (alpha channel), 3 for RGB images, and 4 for RGB
images with alpha channel, i.e. RGBA. If conversions above were images with alpha channel, i.e. RGBA. If conversions above were
sufficient we should only have 3 or 4 channels here. */ 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); xassert (channels == 3 || channels == 4);
/* Number of bytes needed for one row of the image. */ /* 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. */ /* Allocate memory for the image. */
pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels); pixels = (png_byte *) xmalloc (row_bytes * height * sizeof *pixels);
...@@ -11952,8 +12015,8 @@ png_load (f, img) ...@@ -11952,8 +12015,8 @@ png_load (f, img)
rows[i] = pixels + i * row_bytes; rows[i] = pixels + i * row_bytes;
/* Read the entire image. */ /* Read the entire image. */
png_read_image (png_ptr, rows); fn_png_read_image (png_ptr, rows);
png_read_end (png_ptr, info_ptr); fn_png_read_end (png_ptr, info_ptr);
if (fp) if (fp)
{ {
fclose (fp); fclose (fp);
...@@ -12028,7 +12091,7 @@ png_load (f, img) ...@@ -12028,7 +12091,7 @@ png_load (f, img)
overrode it. */ overrode it. */
{ {
png_color_16 *bg; 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. */ #if 0 /* TODO: Color tables. */
img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue); img->background = lookup_rgb_color (f, bg->red, bg->green, bg->blue);
...@@ -12047,7 +12110,7 @@ png_load (f, img) ...@@ -12047,7 +12110,7 @@ png_load (f, img)
#endif #endif
/* Clean up. */ /* 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 (rows);
xfree (pixels); xfree (pixels);
...@@ -13122,6 +13185,10 @@ gif_load (f, img) ...@@ -13122,6 +13185,10 @@ gif_load (f, img)
Lisp_Object Qpostscript; Lisp_Object Qpostscript;
/* Keyword symbols. */
Lisp_Object QCloader, QCbounding_box, QCpt_width, QCpt_height;
#ifdef HAVE_GHOSTSCRIPT #ifdef HAVE_GHOSTSCRIPT
static int gs_image_p P_ ((Lisp_Object object)); static int gs_image_p P_ ((Lisp_Object object));
static int gs_load P_ ((struct frame *f, struct image *img)); static int gs_load P_ ((struct frame *f, struct image *img));
...@@ -15476,7 +15543,6 @@ versions of Windows) characters. */); ...@@ -15476,7 +15543,6 @@ versions of Windows) characters. */);
staticpro (&QCrelief); staticpro (&QCrelief);
Qpostscript = intern ("postscript"); Qpostscript = intern ("postscript");
staticpro (&Qpostscript); staticpro (&Qpostscript);
#if 0 /* TODO: These need entries at top of file. */
QCloader = intern (":loader"); QCloader = intern (":loader");
staticpro (&QCloader); staticpro (&QCloader);
QCbounding_box = intern (":bounding-box"); QCbounding_box = intern (":bounding-box");
...@@ -15485,7 +15551,6 @@ versions of Windows) characters. */); ...@@ -15485,7 +15551,6 @@ versions of Windows) characters. */);
staticpro (&QCpt_width); staticpro (&QCpt_width);
QCpt_height = intern (":pt-height"); QCpt_height = intern (":pt-height");
staticpro (&QCpt_height); staticpro (&QCpt_height);
#endif
QCindex = intern (":index"); QCindex = intern (":index");
staticpro (&QCindex); staticpro (&QCindex);
Qpbm = intern ("pbm"); Qpbm = intern ("pbm");
...@@ -15559,18 +15624,11 @@ void globals_of_w32fns () ...@@ -15559,18 +15624,11 @@ void globals_of_w32fns ()
track_mouse_event_fn = (TrackMouseEvent_Proc) GetProcAddress (user32_lib, "TrackMouseEvent"); track_mouse_event_fn = (TrackMouseEvent_Proc) GetProcAddress (user32_lib, "TrackMouseEvent");
} }
/* Initialize image types. Based on which libraries are available. */
void static void
init_xfns () init_external_image_libraries ()
{ {
image_types = NULL; HINSTANCE png_lib;
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
#if HAVE_XPM #if HAVE_XPM
define_image_type (&xpm_type); define_image_type (&xpm_type);
...@@ -15589,10 +15647,41 @@ init_xfns () ...@@ -15589,10 +15647,41 @@ init_xfns ()
#endif #endif
#if HAVE_PNG #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 #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 #undef abort
void void
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment