671242f350d172e106580348e24bab66b0d7e6a5vboxsync/*---------------------------------------------------------------------------
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync rpng - simple PNG display program rpng-x.c
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync This program decodes and displays PNG images, with gamma correction and
671242f350d172e106580348e24bab66b0d7e6a5vboxsync optionally with a user-specified background color (in case the image has
671242f350d172e106580348e24bab66b0d7e6a5vboxsync transparency). It is very nearly the most basic PNG viewer possible.
671242f350d172e106580348e24bab66b0d7e6a5vboxsync This version is for the X Window System (tested by author under Unix and
671242f350d172e106580348e24bab66b0d7e6a5vboxsync by Martin Zinser under OpenVMS; may work under OS/2 with some tweaking).
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync to do:
671242f350d172e106580348e24bab66b0d7e6a5vboxsync - 8-bit support
671242f350d172e106580348e24bab66b0d7e6a5vboxsync - use %.1023s to simplify truncation of title-bar string?
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ---------------------------------------------------------------------------
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Changelog:
671242f350d172e106580348e24bab66b0d7e6a5vboxsync - 1.01: initial public release
671242f350d172e106580348e24bab66b0d7e6a5vboxsync - 1.02: modified to allow abbreviated options; fixed long/ulong mis-
671242f350d172e106580348e24bab66b0d7e6a5vboxsync match; switched to png_jmpbuf() macro
671242f350d172e106580348e24bab66b0d7e6a5vboxsync - 1.10: added support for non-default visuals; fixed X pixel-conversion
671242f350d172e106580348e24bab66b0d7e6a5vboxsync - 1.11: added extra set of parentheses to png_jmpbuf() macro; fixed
671242f350d172e106580348e24bab66b0d7e6a5vboxsync command-line parsing bug
671242f350d172e106580348e24bab66b0d7e6a5vboxsync - 1.12: fixed small X memory leak (thanks to Francois Petitjean)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync - 1.13: fixed XFreeGC() crash bug
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ---------------------------------------------------------------------------
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Copyright (c) 1998-2001 Greg Roelofs. All rights reserved.
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync This software is provided "as is," without warranty of any kind,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync express or implied. In no event shall the author or contributors
671242f350d172e106580348e24bab66b0d7e6a5vboxsync be held liable for any damages arising in any way from the use of
671242f350d172e106580348e24bab66b0d7e6a5vboxsync this software.
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Permission is granted to anyone to use this software for any purpose,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync including commercial applications, and to alter it and redistribute
671242f350d172e106580348e24bab66b0d7e6a5vboxsync it freely, subject to the following restrictions:
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync 1. Redistributions of source code must retain the above copyright
671242f350d172e106580348e24bab66b0d7e6a5vboxsync notice, disclaimer, and this list of conditions.
671242f350d172e106580348e24bab66b0d7e6a5vboxsync 2. Redistributions in binary form must reproduce the above copyright
671242f350d172e106580348e24bab66b0d7e6a5vboxsync notice, disclaimer, and this list of conditions in the documenta-
671242f350d172e106580348e24bab66b0d7e6a5vboxsync tion and/or other materials provided with the distribution.
671242f350d172e106580348e24bab66b0d7e6a5vboxsync 3. All advertising materials mentioning features or use of this
671242f350d172e106580348e24bab66b0d7e6a5vboxsync software must display the following acknowledgment:
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync This product includes software developed by Greg Roelofs
671242f350d172e106580348e24bab66b0d7e6a5vboxsync and contributors for the book, "PNG: The Definitive Guide,"
671242f350d172e106580348e24bab66b0d7e6a5vboxsync published by O'Reilly and Associates.
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ---------------------------------------------------------------------------*/
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#define PROGNAME "rpng-x"
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#define LONGNAME "Simple PNG Viewer for X"
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#define VERSION "1.13 of 16 August 2001"
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#include <stdio.h>
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#include <stdlib.h>
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#include <string.h>
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#include <time.h>
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#include <X11/Xlib.h>
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#include <X11/Xutil.h>
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#include <X11/Xos.h>
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#include <X11/keysym.h>
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync/* #define DEBUG : this enables the Trace() macros */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#include "readpng.h" /* typedefs, common macros, readpng prototypes */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync/* could just include png.h, but this macro is the only thing we need
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * (name and typedefs changed to local versions); note that side effects
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * only happen with alpha (which could easily be avoided with
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * "ush acopy = (alpha);") */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#define alpha_composite(composite, fg, alpha, bg) { \
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ush temp = ((ush)(fg)*(ush)(alpha) + \
671242f350d172e106580348e24bab66b0d7e6a5vboxsync (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128); \
671242f350d172e106580348e24bab66b0d7e6a5vboxsync (composite) = (uch)((temp + (temp >> 8)) >> 8); \
671242f350d172e106580348e24bab66b0d7e6a5vboxsync}
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync/* local prototypes */
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic int rpng_x_create_window(void);
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic int rpng_x_display_image(void);
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic void rpng_x_cleanup(void);
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic int rpng_x_msb(ulg u32val);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic char titlebar[1024], *window_name = titlebar;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic char *appname = LONGNAME;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic char *icon_name = PROGNAME;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic char *filename;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic FILE *infile;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic char *bgstr;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic uch bg_red=0, bg_green=0, bg_blue=0;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic double display_exponent;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic ulg image_width, image_height, image_rowbytes;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic int image_channels;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic uch *image_data;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync/* X-specific variables */
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic char *displayname;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic XImage *ximage;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic Display *display;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic int depth;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic Visual *visual;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic XVisualInfo *visual_list;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic int RShift, GShift, BShift;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic ulg RMask, GMask, BMask;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic Window window;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic GC gc;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic Colormap colormap;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic int have_nondefault_visual = FALSE;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic int have_colormap = FALSE;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic int have_window = FALSE;
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic int have_gc = FALSE;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync/*
671242f350d172e106580348e24bab66b0d7e6a5vboxsynculg numcolors=0, pixels[256];
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncush reds[256], greens[256], blues[256];
671242f350d172e106580348e24bab66b0d7e6a5vboxsync */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncint main(int argc, char **argv)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync{
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#ifdef sgi
671242f350d172e106580348e24bab66b0d7e6a5vboxsync char tmpline[80];
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#endif
671242f350d172e106580348e24bab66b0d7e6a5vboxsync char *p;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync int rc, alen, flen;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync int error = 0;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync int have_bg = FALSE;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync double LUT_exponent; /* just the lookup table */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync double CRT_exponent = 2.2; /* just the monitor */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync double default_display_exponent; /* whole display system */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XEvent e;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync KeySym k;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync displayname = (char *)NULL;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync filename = (char *)NULL;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* First set the default value for our display-system exponent, i.e.,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * the product of the CRT exponent and the exponent corresponding to
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * the frame-buffer's lookup table (LUT), if any. This is not an
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * exhaustive list of LUT values (e.g., OpenStep has a lot of weird
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * ones), but it should cover 99% of the current possibilities. */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#if defined(NeXT)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync LUT_exponent = 1.0 / 2.2;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /*
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (some_next_function_that_returns_gamma(&next_gamma))
671242f350d172e106580348e24bab66b0d7e6a5vboxsync LUT_exponent = 1.0 / next_gamma;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#elif defined(sgi)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync LUT_exponent = 1.0 / 1.7;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* there doesn't seem to be any documented function to get the
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * "gamma" value, so we do it the hard way */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync infile = fopen("/etc/config/system.glGammaVal", "r");
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (infile) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync double sgi_gamma;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fgets(tmpline, 80, infile);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fclose(infile);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync sgi_gamma = atof(tmpline);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (sgi_gamma > 0.0)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync LUT_exponent = 1.0 / sgi_gamma;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#elif defined(Macintosh)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync LUT_exponent = 1.8 / 2.61;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /*
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (some_mac_function_that_returns_gamma(&mac_gamma))
671242f350d172e106580348e24bab66b0d7e6a5vboxsync LUT_exponent = mac_gamma / 2.61;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#else
671242f350d172e106580348e24bab66b0d7e6a5vboxsync LUT_exponent = 1.0; /* assume no LUT: most PCs */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#endif
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync default_display_exponent = LUT_exponent * CRT_exponent;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* If the user has set the SCREEN_GAMMA environment variable as suggested
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * (somewhat imprecisely) in the libpng documentation, use that; otherwise
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * use the default value we just calculated. Either way, the user may
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * override this via a command-line option. */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if ((p = getenv("SCREEN_GAMMA")) != NULL)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync display_exponent = atof(p);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync else
671242f350d172e106580348e24bab66b0d7e6a5vboxsync display_exponent = default_display_exponent;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* Now parse the command line for options and the PNG filename. */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync while (*++argv && !error) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (!strncmp(*argv, "-display", 2)) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (!*++argv)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ++error;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync else
671242f350d172e106580348e24bab66b0d7e6a5vboxsync displayname = *argv;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else if (!strncmp(*argv, "-gamma", 2)) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (!*++argv)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ++error;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync else {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync display_exponent = atof(*argv);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (display_exponent <= 0.0)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ++error;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else if (!strncmp(*argv, "-bgcolor", 2)) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (!*++argv)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ++error;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync else {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync bgstr = *argv;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (strlen(bgstr) != 7 || bgstr[0] != '#')
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ++error;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync else
671242f350d172e106580348e24bab66b0d7e6a5vboxsync have_bg = TRUE;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (**argv != '-') {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync filename = *argv;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (argv[1]) /* shouldn't be any more args after filename */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ++error;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ++error; /* not expecting any other options */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (!filename) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ++error;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else if (!(infile = fopen(filename, "rb"))) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr, PROGNAME ": can't open PNG file [%s]\n", filename);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ++error;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if ((rc = readpng_init(infile, &image_width, &image_height)) != 0) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync switch (rc) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync case 1:
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr, PROGNAME
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ": [%s] is not a PNG file: incorrect signature\n",
671242f350d172e106580348e24bab66b0d7e6a5vboxsync filename);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync break;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync case 2:
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr, PROGNAME
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ": [%s] has bad IHDR (libpng longjmp)\n",
671242f350d172e106580348e24bab66b0d7e6a5vboxsync filename);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync break;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync case 4:
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr, PROGNAME ": insufficient memory\n");
671242f350d172e106580348e24bab66b0d7e6a5vboxsync break;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync default:
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr, PROGNAME
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ": unknown readpng_init() error\n");
671242f350d172e106580348e24bab66b0d7e6a5vboxsync break;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ++error;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync display = XOpenDisplay(displayname);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (!display) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync readpng_cleanup(TRUE);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr, PROGNAME ": can't open X display [%s]\n",
671242f350d172e106580348e24bab66b0d7e6a5vboxsync displayname? displayname : "default");
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ++error;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (error)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fclose(infile);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* usage screen */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (error) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr, "\n%s %s: %s\n", PROGNAME, VERSION, appname);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync readpng_version_info();
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr, "\n"
671242f350d172e106580348e24bab66b0d7e6a5vboxsync "Usage: %s [-display xdpy] [-gamma exp] [-bgcolor bg] file.png\n"
671242f350d172e106580348e24bab66b0d7e6a5vboxsync " xdpy\tname of the target X display (e.g., ``hostname:0'')\n"
671242f350d172e106580348e24bab66b0d7e6a5vboxsync " exp \ttransfer-function exponent (``gamma'') of the display\n"
671242f350d172e106580348e24bab66b0d7e6a5vboxsync "\t\t system in floating-point format (e.g., ``%.1f''); equal\n"
671242f350d172e106580348e24bab66b0d7e6a5vboxsync "\t\t to the product of the lookup-table exponent (varies)\n"
671242f350d172e106580348e24bab66b0d7e6a5vboxsync "\t\t and the CRT exponent (usually 2.2); must be positive\n"
671242f350d172e106580348e24bab66b0d7e6a5vboxsync " bg \tdesired background color in 7-character hex RGB format\n"
671242f350d172e106580348e24bab66b0d7e6a5vboxsync "\t\t (e.g., ``#ff7700'' for orange: same as HTML colors);\n"
671242f350d172e106580348e24bab66b0d7e6a5vboxsync "\t\t used with transparent images\n"
671242f350d172e106580348e24bab66b0d7e6a5vboxsync "\nPress Q, Esc or mouse button 1 (within image window, after image\n"
671242f350d172e106580348e24bab66b0d7e6a5vboxsync "is displayed) to quit.\n"
671242f350d172e106580348e24bab66b0d7e6a5vboxsync "\n", PROGNAME, default_display_exponent);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync exit(1);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* set the title-bar string, but make sure buffer doesn't overflow */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync alen = strlen(appname);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync flen = strlen(filename);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (alen + flen + 3 > 1023)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync sprintf(titlebar, "%s: ...%s", appname, filename+(alen+flen+6-1023));
671242f350d172e106580348e24bab66b0d7e6a5vboxsync else
671242f350d172e106580348e24bab66b0d7e6a5vboxsync sprintf(titlebar, "%s: %s", appname, filename);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* if the user didn't specify a background color on the command line,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * check for one in the PNG file--if not, the initialized values of 0
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * (black) will be used */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (have_bg) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync unsigned r, g, b; /* this approach quiets compiler warnings */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync bg_red = (uch)r;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync bg_green = (uch)g;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync bg_blue = (uch)b;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else if (readpng_get_bgcolor(&bg_red, &bg_green, &bg_blue) > 1) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync readpng_cleanup(TRUE);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr, PROGNAME
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ": libpng error while checking for background color\n");
671242f350d172e106580348e24bab66b0d7e6a5vboxsync exit(2);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* do the basic X initialization stuff, make the window and fill it
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * with the background color */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (rpng_x_create_window())
671242f350d172e106580348e24bab66b0d7e6a5vboxsync exit(2);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* decode the image, all at once */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Trace((stderr, "calling readpng_get_image()\n"))
671242f350d172e106580348e24bab66b0d7e6a5vboxsync image_data = readpng_get_image(display_exponent, &image_channels,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync &image_rowbytes);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Trace((stderr, "done with readpng_get_image()\n"))
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* done with PNG file, so clean up to minimize memory usage (but do NOT
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * nuke image_data!) */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync readpng_cleanup(FALSE);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fclose(infile);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (!image_data) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr, PROGNAME ": unable to decode PNG image\n");
671242f350d172e106580348e24bab66b0d7e6a5vboxsync exit(3);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* display image (composite with background if requested) */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Trace((stderr, "calling rpng_x_display_image()\n"))
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (rpng_x_display_image()) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync free(image_data);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync exit(4);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Trace((stderr, "done with rpng_x_display_image()\n"))
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* wait for the user to tell us when to quit */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync printf(
671242f350d172e106580348e24bab66b0d7e6a5vboxsync "Done. Press Q, Esc or mouse button 1 (within image window) to quit.\n");
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fflush(stdout);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync do
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XNextEvent(display, &e);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync while (!(e.type == ButtonPress && e.xbutton.button == Button1) &&
671242f350d172e106580348e24bab66b0d7e6a5vboxsync !(e.type == KeyPress && /* v--- or 1 for shifted keys */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ((k = XLookupKeysym(&e.xkey, 0)) == XK_q || k == XK_Escape) ));
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* OK, we're done: clean up all image and X resources and go away */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync rpng_x_cleanup();
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync return 0;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync}
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic int rpng_x_create_window(void)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync{
671242f350d172e106580348e24bab66b0d7e6a5vboxsync uch *xdata;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync int need_colormap = FALSE;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync int screen, pad;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ulg bg_pixel = 0L;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ulg attrmask;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Window root;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XEvent e;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XGCValues gcvalues;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XSetWindowAttributes attr;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XSizeHints *size_hints;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XTextProperty windowName, *pWindowName = &windowName;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XTextProperty iconName, *pIconName = &iconName;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XVisualInfo visual_info;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XWMHints *wm_hints;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync screen = DefaultScreen(display);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync depth = DisplayPlanes(display, screen);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync root = RootWindow(display, screen);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#ifdef DEBUG
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XSynchronize(display, True);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#endif
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#if 0
671242f350d172e106580348e24bab66b0d7e6a5vboxsync/* GRR: add 8-bit support */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (/* depth != 8 && */ depth != 16 && depth != 24 && depth != 32) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync "screen depth %d not supported (only 16-, 24- or 32-bit TrueColor)\n",
671242f350d172e106580348e24bab66b0d7e6a5vboxsync depth);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync return 2;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XMatchVisualInfo(display, screen, depth,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync (depth == 8)? PseudoColor : TrueColor, &visual_info);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync visual = visual_info.visual;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#else
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (depth != 16 && depth != 24 && depth != 32) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync int visuals_matched = 0;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Trace((stderr, "default depth is %d: checking other visuals\n",
671242f350d172e106580348e24bab66b0d7e6a5vboxsync depth))
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* 24-bit first */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync visual_info.screen = screen;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync visual_info.depth = 24;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync visual_list = XGetVisualInfo(display,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync VisualScreenMask | VisualDepthMask, &visual_info, &visuals_matched);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (visuals_matched == 0) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync/* GRR: add 15-, 16- and 32-bit TrueColor visuals (also DirectColor?) */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr, "default screen depth %d not supported, and no"
671242f350d172e106580348e24bab66b0d7e6a5vboxsync " 24-bit visuals found\n", depth);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync return 2;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Trace((stderr, "XGetVisualInfo() returned %d 24-bit visuals\n",
671242f350d172e106580348e24bab66b0d7e6a5vboxsync visuals_matched))
671242f350d172e106580348e24bab66b0d7e6a5vboxsync visual = visual_list[0].visual;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync depth = visual_list[0].depth;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync/*
671242f350d172e106580348e24bab66b0d7e6a5vboxsync colormap_size = visual_list[0].colormap_size;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync visual_class = visual->class;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync visualID = XVisualIDFromVisual(visual);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync have_nondefault_visual = TRUE;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync need_colormap = TRUE;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XMatchVisualInfo(display, screen, depth, TrueColor, &visual_info);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync visual = visual_info.visual;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#endif
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync RMask = visual->red_mask;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync GMask = visual->green_mask;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync BMask = visual->blue_mask;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync/* GRR: add/check 8-bit support */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (depth == 8 || need_colormap) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync colormap = XCreateColormap(display, root, visual, AllocNone);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (!colormap) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr, "XCreateColormap() failed\n");
671242f350d172e106580348e24bab66b0d7e6a5vboxsync return 2;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync have_colormap = TRUE;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (depth == 15 || depth == 16) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync RShift = 15 - rpng_x_msb(RMask); /* these are right-shifts */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync GShift = 15 - rpng_x_msb(GMask);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync BShift = 15 - rpng_x_msb(BMask);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else if (depth > 16) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#define NO_24BIT_MASKS
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#ifdef NO_24BIT_MASKS
671242f350d172e106580348e24bab66b0d7e6a5vboxsync RShift = rpng_x_msb(RMask) - 7; /* these are left-shifts */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync GShift = rpng_x_msb(GMask) - 7;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync BShift = rpng_x_msb(BMask) - 7;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#else
671242f350d172e106580348e24bab66b0d7e6a5vboxsync RShift = 7 - rpng_x_msb(RMask); /* these are right-shifts, too */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync GShift = 7 - rpng_x_msb(GMask);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync BShift = 7 - rpng_x_msb(BMask);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#endif
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (depth >= 15 && (RShift < 0 || GShift < 0 || BShift < 0)) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr, "rpng internal logic error: negative X shift(s)!\n");
671242f350d172e106580348e24bab66b0d7e6a5vboxsync return 2;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync/*---------------------------------------------------------------------------
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Finally, create the window.
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ---------------------------------------------------------------------------*/
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync attr.backing_store = Always;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync attrmask = CWBackingStore | CWEventMask;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (have_nondefault_visual) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync attr.colormap = colormap;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync attr.background_pixel = 0;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync attr.border_pixel = 1;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync attrmask |= CWColormap | CWBackPixel | CWBorderPixel;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync window = XCreateWindow(display, root, 0, 0, image_width, image_height, 0,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync depth, InputOutput, visual, attrmask, &attr);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (window == None) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr, "XCreateWindow() failed\n");
671242f350d172e106580348e24bab66b0d7e6a5vboxsync return 2;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else
671242f350d172e106580348e24bab66b0d7e6a5vboxsync have_window = TRUE;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (depth == 8)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XSetWindowColormap(display, window, colormap);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (!XStringListToTextProperty(&window_name, 1, pWindowName))
671242f350d172e106580348e24bab66b0d7e6a5vboxsync pWindowName = NULL;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (!XStringListToTextProperty(&icon_name, 1, pIconName))
671242f350d172e106580348e24bab66b0d7e6a5vboxsync pIconName = NULL;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* OK if either hints allocation fails; XSetWMProperties() allows NULLs */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if ((size_hints = XAllocSizeHints()) != NULL) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* window will not be resizable */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync size_hints->flags = PMinSize | PMaxSize;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync size_hints->min_width = size_hints->max_width = (int)image_width;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync size_hints->min_height = size_hints->max_height = (int)image_height;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if ((wm_hints = XAllocWMHints()) != NULL) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync wm_hints->initial_state = NormalState;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync wm_hints->input = True;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* wm_hints->icon_pixmap = icon_pixmap; */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync wm_hints->flags = StateHint | InputHint /* | IconPixmapHint */ ;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XSetWMProperties(display, window, pWindowName, pIconName, NULL, 0,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync size_hints, wm_hints, NULL);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* various properties and hints no longer needed; free memory */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (pWindowName)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XFree(pWindowName->value);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (pIconName)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XFree(pIconName->value);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (size_hints)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XFree(size_hints);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (wm_hints)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XFree(wm_hints);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XMapWindow(display, window);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync gc = XCreateGC(display, window, 0, &gcvalues);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync have_gc = TRUE;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync/*---------------------------------------------------------------------------
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Fill window with the specified background color.
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ---------------------------------------------------------------------------*/
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (depth == 24 || depth == 32) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync bg_pixel = ((ulg)bg_red << RShift) |
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ((ulg)bg_green << GShift) |
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ((ulg)bg_blue << BShift);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else if (depth == 16) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync bg_pixel = ((((ulg)bg_red << 8) >> RShift) & RMask) |
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ((((ulg)bg_green << 8) >> GShift) & GMask) |
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ((((ulg)bg_blue << 8) >> BShift) & BMask);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else /* depth == 8 */ {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* GRR: add 8-bit support */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XSetForeground(display, gc, bg_pixel);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XFillRectangle(display, window, gc, 0, 0, image_width, image_height);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync/*---------------------------------------------------------------------------
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Wait for first Expose event to do any drawing, then flush.
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ---------------------------------------------------------------------------*/
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync do
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XNextEvent(display, &e);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync while (e.type != Expose || e.xexpose.count);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XFlush(display);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync/*---------------------------------------------------------------------------
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Allocate memory for the X- and display-specific version of the image.
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ---------------------------------------------------------------------------*/
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (depth == 24 || depth == 32) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync xdata = (uch *)malloc(4*image_width*image_height);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync pad = 32;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else if (depth == 16) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync xdata = (uch *)malloc(2*image_width*image_height);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync pad = 16;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else /* depth == 8 */ {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync xdata = (uch *)malloc(image_width*image_height);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync pad = 8;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (!xdata) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr, PROGNAME ": unable to allocate image memory\n");
671242f350d172e106580348e24bab66b0d7e6a5vboxsync return 4;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ximage = XCreateImage(display, visual, depth, ZPixmap, 0,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync (char *)xdata, image_width, image_height, pad, 0);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (!ximage) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync fprintf(stderr, PROGNAME ": XCreateImage() failed\n");
671242f350d172e106580348e24bab66b0d7e6a5vboxsync free(xdata);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync return 3;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* to avoid testing the byte order every pixel (or doubling the size of
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * the drawing routine with a giant if-test), we arbitrarily set the byte
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * order to MSBFirst and let Xlib worry about inverting things on little-
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * endian machines (like Linux/x86, old VAXen, etc.)--this is not the most
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * efficient approach (the giant if-test would be better), but in the
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * interest of clarity, we take the easy way out... */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ximage->byte_order = MSBFirst;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync return 0;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync} /* end function rpng_x_create_window() */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic int rpng_x_display_image(void)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync{
671242f350d172e106580348e24bab66b0d7e6a5vboxsync uch *src;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync char *dest;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync uch r, g, b, a;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ulg i, row, lastrow = 0;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ulg pixel;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync int ximage_rowbytes = ximage->bytes_per_line;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync/* int bpp = ximage->bits_per_pixel; */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Trace((stderr, "beginning display loop (image_channels == %d)\n",
671242f350d172e106580348e24bab66b0d7e6a5vboxsync image_channels))
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Trace((stderr, " (width = %ld, rowbytes = %ld, ximage_rowbytes = %d)\n",
671242f350d172e106580348e24bab66b0d7e6a5vboxsync image_width, image_rowbytes, ximage_rowbytes))
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Trace((stderr, " (bpp = %d)\n", ximage->bits_per_pixel))
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Trace((stderr, " (byte_order = %s)\n", ximage->byte_order == MSBFirst?
671242f350d172e106580348e24bab66b0d7e6a5vboxsync "MSBFirst" : (ximage->byte_order == LSBFirst? "LSBFirst" : "unknown")))
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (depth == 24 || depth == 32) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ulg red, green, blue;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync for (lastrow = row = 0; row < image_height; ++row) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync src = image_data + row*image_rowbytes;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync dest = ximage->data + row*ximage_rowbytes;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (image_channels == 3) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync for (i = image_width; i > 0; --i) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync red = *src++;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync green = *src++;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync blue = *src++;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#ifdef NO_24BIT_MASKS
671242f350d172e106580348e24bab66b0d7e6a5vboxsync pixel = (red << RShift) |
671242f350d172e106580348e24bab66b0d7e6a5vboxsync (green << GShift) |
671242f350d172e106580348e24bab66b0d7e6a5vboxsync (blue << BShift);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* recall that we set ximage->byte_order = MSBFirst above */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* GRR BUG: this assumes bpp == 32, but may be 24: */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *dest++ = (char)((pixel >> 24) & 0xff);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *dest++ = (char)((pixel >> 16) & 0xff);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *dest++ = (char)((pixel >> 8) & 0xff);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *dest++ = (char)( pixel & 0xff);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#else
671242f350d172e106580348e24bab66b0d7e6a5vboxsync red = (RShift < 0)? red << (-RShift) : red >> RShift;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync green = (GShift < 0)? green << (-GShift) : green >> GShift;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync blue = (BShift < 0)? blue << (-BShift) : blue >> BShift;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync pixel = (red & RMask) | (green & GMask) | (blue & BMask);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* recall that we set ximage->byte_order = MSBFirst above */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *dest++ = (char)((pixel >> 24) & 0xff);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *dest++ = (char)((pixel >> 16) & 0xff);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *dest++ = (char)((pixel >> 8) & 0xff);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *dest++ = (char)( pixel & 0xff);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync#endif
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else /* if (image_channels == 4) */ {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync for (i = image_width; i > 0; --i) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync r = *src++;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync g = *src++;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync b = *src++;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync a = *src++;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (a == 255) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync red = r;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync green = g;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync blue = b;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else if (a == 0) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync red = bg_red;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync green = bg_green;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync blue = bg_blue;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* this macro (from png.h) composites the foreground
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * and background values and puts the result into the
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * first argument */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync alpha_composite(red, r, a, bg_red);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync alpha_composite(green, g, a, bg_green);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync alpha_composite(blue, b, a, bg_blue);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync pixel = (red << RShift) |
671242f350d172e106580348e24bab66b0d7e6a5vboxsync (green << GShift) |
671242f350d172e106580348e24bab66b0d7e6a5vboxsync (blue << BShift);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* recall that we set ximage->byte_order = MSBFirst above */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *dest++ = (char)((pixel >> 24) & 0xff);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *dest++ = (char)((pixel >> 16) & 0xff);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *dest++ = (char)((pixel >> 8) & 0xff);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *dest++ = (char)( pixel & 0xff);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* display after every 16 lines */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (((row+1) & 0xf) == 0) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync (int)lastrow, image_width, 16);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XFlush(display);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync lastrow = row + 1;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else if (depth == 16) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ush red, green, blue;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync for (lastrow = row = 0; row < image_height; ++row) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync src = image_data + row*image_rowbytes;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync dest = ximage->data + row*ximage_rowbytes;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (image_channels == 3) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync for (i = image_width; i > 0; --i) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync red = ((ush)(*src) << 8);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ++src;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync green = ((ush)(*src) << 8);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ++src;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync blue = ((ush)(*src) << 8);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ++src;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync pixel = ((red >> RShift) & RMask) |
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ((green >> GShift) & GMask) |
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ((blue >> BShift) & BMask);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* recall that we set ximage->byte_order = MSBFirst above */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *dest++ = (char)((pixel >> 8) & 0xff);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *dest++ = (char)( pixel & 0xff);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else /* if (image_channels == 4) */ {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync for (i = image_width; i > 0; --i) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync r = *src++;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync g = *src++;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync b = *src++;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync a = *src++;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (a == 255) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync red = ((ush)r << 8);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync green = ((ush)g << 8);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync blue = ((ush)b << 8);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else if (a == 0) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync red = ((ush)bg_red << 8);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync green = ((ush)bg_green << 8);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync blue = ((ush)bg_blue << 8);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* this macro (from png.h) composites the foreground
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * and background values and puts the result back into
671242f350d172e106580348e24bab66b0d7e6a5vboxsync * the first argument (== fg byte here: safe) */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync alpha_composite(r, r, a, bg_red);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync alpha_composite(g, g, a, bg_green);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync alpha_composite(b, b, a, bg_blue);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync red = ((ush)r << 8);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync green = ((ush)g << 8);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync blue = ((ush)b << 8);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync pixel = ((red >> RShift) & RMask) |
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ((green >> GShift) & GMask) |
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ((blue >> BShift) & BMask);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* recall that we set ximage->byte_order = MSBFirst above */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *dest++ = (char)((pixel >> 8) & 0xff);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync *dest++ = (char)( pixel & 0xff);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* display after every 16 lines */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (((row+1) & 0xf) == 0) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync (int)lastrow, image_width, 16);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XFlush(display);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync lastrow = row + 1;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync } else /* depth == 8 */ {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync /* GRR: add 8-bit support */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync Trace((stderr, "calling final XPutImage()\n"))
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (lastrow < image_height) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
671242f350d172e106580348e24bab66b0d7e6a5vboxsync (int)lastrow, image_width, image_height-lastrow);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XFlush(display);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync return 0;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync}
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic void rpng_x_cleanup(void)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync{
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (image_data) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync free(image_data);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync image_data = NULL;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (ximage) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (ximage->data) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync free(ximage->data); /* we allocated it, so we free it */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ximage->data = (char *)NULL; /* instead of XDestroyImage() */
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XDestroyImage(ximage);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync ximage = NULL;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (have_gc)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XFreeGC(display, gc);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (have_window)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XDestroyWindow(display, window);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (have_colormap)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XFreeColormap(display, colormap);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (have_nondefault_visual)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync XFree(visual_list);
671242f350d172e106580348e24bab66b0d7e6a5vboxsync}
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsyncstatic int rpng_x_msb(ulg u32val)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync{
671242f350d172e106580348e24bab66b0d7e6a5vboxsync int i;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync
671242f350d172e106580348e24bab66b0d7e6a5vboxsync for (i = 31; i >= 0; --i) {
671242f350d172e106580348e24bab66b0d7e6a5vboxsync if (u32val & 0x80000000L)
671242f350d172e106580348e24bab66b0d7e6a5vboxsync break;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync u32val <<= 1;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync }
671242f350d172e106580348e24bab66b0d7e6a5vboxsync return i;
671242f350d172e106580348e24bab66b0d7e6a5vboxsync}