Blame contrib/gregbook/rpng2-x.c

Packit 0ba690
/*---------------------------------------------------------------------------
Packit 0ba690
Packit 0ba690
   rpng2 - progressive-model PNG display program                  rpng2-x.c
Packit 0ba690
Packit 0ba690
   This program decodes and displays PNG files progressively, as if it were
Packit 0ba690
   a web browser (though the front end is only set up to read from files).
Packit 0ba690
   It supports gamma correction, user-specified background colors, and user-
Packit 0ba690
   specified background patterns (for transparent images).  This version is
Packit 0ba690
   for the X Window System (tested by the author under Unix and by Martin
Packit 0ba690
   Zinser under OpenVMS; may work under OS/2 with a little tweaking).
Packit 0ba690
Packit 0ba690
   Thanks to Adam Costello and Pieter S. van der Meulen for the "diamond"
Packit 0ba690
   and "radial waves" patterns, respectively.
Packit 0ba690
Packit 0ba690
   to do (someday, maybe):
Packit 0ba690
    - fix expose/redraw code:  don't draw entire row if only part exposed
Packit 0ba690
    - 8-bit (colormapped) X support
Packit 0ba690
    - finish resizable checkerboard-gradient (sizes 4-128?)
Packit 0ba690
    - use %.1023s to simplify truncation of title-bar string?
Packit 0ba690
Packit 0ba690
  ---------------------------------------------------------------------------
Packit 0ba690
Packit 0ba690
   Changelog:
Packit 0ba690
    - 1.01:  initial public release
Packit 0ba690
    - 1.02:  modified to allow abbreviated options; fixed char/uchar mismatch
Packit 0ba690
    - 1.10:  added support for non-default visuals; fixed X pixel-conversion
Packit 0ba690
    - 1.11:  added -usleep option for demos; fixed command-line parsing bug
Packit 0ba690
    - 1.12:  added -pause option for demos and testing
Packit 0ba690
    - 1.20:  added runtime MMX-enabling/disabling and new -mmx* options
Packit 0ba690
    - 1.21:  fixed some small X memory leaks (thanks to François Petitjean)
Packit 0ba690
    - 1.22:  fixed XFreeGC() crash bug (thanks to Patrick Welche)
Packit 0ba690
    - 1.23:  added -bgpat 0 mode (std white/gray checkerboard, 8x8 squares)
Packit 0ba690
    - 1.30:  added -loop option for -bgpat (ifdef FEATURE_LOOP); fixed bpp =
Packit 0ba690
              24; added support for X resources (thanks to Gerhard Niklasch)
Packit 0ba690
    - 1.31:  added code to skip unused chunks (thanks to Glenn Randers-Pehrson)
Packit 0ba690
    - 1.32:  added AMD64/EM64T support (__x86_64__); added basic expose/redraw
Packit 0ba690
              handling
Packit 0ba690
    - 2.00:  dual-licensed (added GNU GPL)
Packit 0ba690
    - 2.01:  fixed 64-bit typo in readpng2.c; fixed -pause usage description
Packit 0ba690
    - 2.02:  fixed improper display of usage screen on PNG error(s); fixed
Packit 0ba690
              unexpected-EOF and file-read-error cases; fixed Trace() cut-and-
Packit 0ba690
              paste bugs
Packit 0ba690
Packit 0ba690
  ---------------------------------------------------------------------------
Packit 0ba690
Packit 0ba690
      Copyright (c) 1998-2008 Greg Roelofs.  All rights reserved.
Packit 0ba690
Packit 0ba690
      This software is provided "as is," without warranty of any kind,
Packit 0ba690
      express or implied.  In no event shall the author or contributors
Packit 0ba690
      be held liable for any damages arising in any way from the use of
Packit 0ba690
      this software.
Packit 0ba690
Packit 0ba690
      The contents of this file are DUAL-LICENSED.  You may modify and/or
Packit 0ba690
      redistribute this software according to the terms of one of the
Packit 0ba690
      following two licenses (at your option):
Packit 0ba690
Packit 0ba690
Packit 0ba690
      LICENSE 1 ("BSD-like with advertising clause"):
Packit 0ba690
Packit 0ba690
      Permission is granted to anyone to use this software for any purpose,
Packit 0ba690
      including commercial applications, and to alter it and redistribute
Packit 0ba690
      it freely, subject to the following restrictions:
Packit 0ba690
Packit 0ba690
      1. Redistributions of source code must retain the above copyright
Packit 0ba690
         notice, disclaimer, and this list of conditions.
Packit 0ba690
      2. Redistributions in binary form must reproduce the above copyright
Packit 0ba690
         notice, disclaimer, and this list of conditions in the documenta-
Packit 0ba690
         tion and/or other materials provided with the distribution.
Packit 0ba690
      3. All advertising materials mentioning features or use of this
Packit 0ba690
         software must display the following acknowledgment:
Packit 0ba690
Packit 0ba690
            This product includes software developed by Greg Roelofs
Packit 0ba690
            and contributors for the book, "PNG: The Definitive Guide,"
Packit 0ba690
            published by O'Reilly and Associates.
Packit 0ba690
Packit 0ba690
Packit 0ba690
      LICENSE 2 (GNU GPL v2 or later):
Packit 0ba690
Packit 0ba690
      This program is free software; you can redistribute it and/or modify
Packit 0ba690
      it under the terms of the GNU General Public License as published by
Packit 0ba690
      the Free Software Foundation; either version 2 of the License, or
Packit 0ba690
      (at your option) any later version.
Packit 0ba690
Packit 0ba690
      This program is distributed in the hope that it will be useful,
Packit 0ba690
      but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 0ba690
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 0ba690
      GNU General Public License for more details.
Packit 0ba690
Packit 0ba690
      You should have received a copy of the GNU General Public License
Packit 0ba690
      along with this program; if not, write to the Free Software Foundation,
Packit 0ba690
      Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
Packit 0ba690
Packit 0ba690
  ---------------------------------------------------------------------------*/
Packit 0ba690
Packit 0ba690
#define PROGNAME  "rpng2-x"
Packit 0ba690
#define LONGNAME  "Progressive PNG Viewer for X"
Packit 0ba690
#define VERSION   "2.02 of 16 March 2008"
Packit 0ba690
#define RESNAME   "rpng2"	/* our X resource application name */
Packit 0ba690
#define RESCLASS  "Rpng"	/* our X resource class name */
Packit 0ba690
Packit 0ba690
#include <stdio.h>
Packit 0ba690
#include <stdlib.h>
Packit 0ba690
#include <ctype.h>
Packit 0ba690
#include <string.h>
Packit 0ba690
#include <setjmp.h>       /* for jmpbuf declaration in readpng2.h */
Packit 0ba690
#include <time.h>
Packit 0ba690
#include <math.h>         /* only for PvdM background code */
Packit 0ba690
#include <X11/Xlib.h>
Packit 0ba690
#include <X11/Xutil.h>
Packit 0ba690
#include <X11/Xos.h>
Packit 0ba690
#include <X11/keysym.h>   /* defines XK_* macros */
Packit 0ba690
Packit 0ba690
#ifdef VMS
Packit 0ba690
#  include <unistd.h>
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
/* all for PvdM background code: */
Packit 0ba690
#ifndef PI
Packit 0ba690
#  define PI             3.141592653589793238
Packit 0ba690
#endif
Packit 0ba690
#define PI_2             (PI*0.5)
Packit 0ba690
#define INV_PI_360       (360.0 / PI)
Packit 0ba690
#define MAX(a,b)         (a>b?a:b)
Packit 0ba690
#define MIN(a,b)         (a
Packit 0ba690
#define CLIP(a,min,max)  MAX(min,MIN((a),max))
Packit 0ba690
#define ABS(a)           ((a)<0?-(a):(a))
Packit 0ba690
#define CLIP8P(c)        MAX(0,(MIN((c),255)))   /* 8-bit pos. integer (uch) */
Packit 0ba690
#define ROUNDF(f)        ((int)(f + 0.5))
Packit 0ba690
Packit 0ba690
#define QUIT(e,k) ((e.type == ButtonPress && e.xbutton.button == Button1) ||  \
Packit 0ba690
                  (e.type == KeyPress &&   /*  v--- or 1 for shifted keys */  \
Packit 0ba690
                  ((k = XLookupKeysym(&e.xkey, 0)) == XK_q || k == XK_Escape)))
Packit 0ba690
Packit 0ba690
#define NO_24BIT_MASKS	/* undef case not fully written--only for redisplay() */
Packit 0ba690
Packit 0ba690
#define rgb1_max   bg_freq
Packit 0ba690
#define rgb1_min   bg_gray
Packit 0ba690
#define rgb2_max   bg_bsat
Packit 0ba690
#define rgb2_min   bg_brot
Packit 0ba690
Packit 0ba690
/* #define DEBUG */     /* this enables the Trace() macros */
Packit 0ba690
Packit 0ba690
#include "readpng2.h"   /* typedefs, common macros, readpng2 prototypes */
Packit 0ba690
Packit 0ba690
Packit 0ba690
/* could just include png.h, but this macro is the only thing we need
Packit 0ba690
 * (name and typedefs changed to local versions); note that side effects
Packit 0ba690
 * only happen with alpha (which could easily be avoided with
Packit 0ba690
 * "ush acopy = (alpha);") */
Packit 0ba690
Packit 0ba690
#define alpha_composite(composite, fg, alpha, bg) {               \
Packit 0ba690
    ush temp = ((ush)(fg)*(ush)(alpha) +                          \
Packit 0ba690
                (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128);  \
Packit 0ba690
    (composite) = (uch)((temp + (temp >> 8)) >> 8);               \
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
Packit 0ba690
#define INBUFSIZE 4096   /* with pseudo-timing on (1 sec delay/block), this
Packit 0ba690
                          *  block size corresponds roughly to a download
Packit 0ba690
                          *  speed 10% faster than theoretical 33.6K maximum
Packit 0ba690
                          *  (assuming 8 data bits, 1 stop bit and no other
Packit 0ba690
                          *  overhead) */
Packit 0ba690
Packit 0ba690
/* local prototypes */
Packit 0ba690
static void rpng2_x_init (void);
Packit 0ba690
static int  rpng2_x_create_window (void);
Packit 0ba690
static int  rpng2_x_load_bg_image (void);
Packit 0ba690
static void rpng2_x_display_row (ulg row);
Packit 0ba690
static void rpng2_x_finish_display (void);
Packit 0ba690
static void rpng2_x_redisplay_image (ulg startcol, ulg startrow,
Packit 0ba690
                                     ulg width, ulg height);
Packit 0ba690
#ifdef FEATURE_LOOP
Packit 0ba690
static void rpng2_x_reload_bg_image (void);
Packit 0ba690
static int  is_number (char *p);
Packit 0ba690
#endif
Packit 0ba690
static void rpng2_x_cleanup (void);
Packit 0ba690
static int  rpng2_x_msb (ulg u32val);
Packit 0ba690
Packit 0ba690
Packit 0ba690
static char titlebar[1024], *window_name = titlebar;
Packit 0ba690
static char *appname = LONGNAME;
Packit 0ba690
static char *icon_name = PROGNAME;
Packit 0ba690
static char *res_name = RESNAME;
Packit 0ba690
static char *res_class = RESCLASS;
Packit 0ba690
static char *filename;
Packit 0ba690
static FILE *infile;
Packit 0ba690
Packit 0ba690
static mainprog_info rpng2_info;
Packit 0ba690
Packit 0ba690
static uch inbuf[INBUFSIZE];
Packit 0ba690
static int incount;
Packit 0ba690
Packit 0ba690
static int pat = 6;        /* must be less than num_bgpat */
Packit 0ba690
static int bg_image = 0;
Packit 0ba690
static int bgscale, bgscale_default = 16;
Packit 0ba690
static ulg bg_rowbytes;
Packit 0ba690
static uch *bg_data;
Packit 0ba690
Packit 0ba690
int pause_after_pass = FALSE;
Packit 0ba690
int demo_timing = FALSE;
Packit 0ba690
ulg usleep_duration = 0L;
Packit 0ba690
Packit 0ba690
static struct rgb_color {
Packit 0ba690
    uch r, g, b;
Packit 0ba690
} rgb[] = {
Packit 0ba690
    {  0,   0,   0},    /*  0:  black */
Packit 0ba690
    {255, 255, 255},    /*  1:  white */
Packit 0ba690
    {173, 132,  57},    /*  2:  tan */
Packit 0ba690
    { 64, 132,   0},    /*  3:  medium green */
Packit 0ba690
    {189, 117,   1},    /*  4:  gold */
Packit 0ba690
    {253, 249,   1},    /*  5:  yellow */
Packit 0ba690
    {  0,   0, 255},    /*  6:  blue */
Packit 0ba690
    {  0,   0, 120},    /*  7:  medium blue */
Packit 0ba690
    {255,   0, 255},    /*  8:  magenta */
Packit 0ba690
    { 64,   0,  64},    /*  9:  dark magenta */
Packit 0ba690
    {255,   0,   0},    /* 10:  red */
Packit 0ba690
    { 64,   0,   0},    /* 11:  dark red */
Packit 0ba690
    {255, 127,   0},    /* 12:  orange */
Packit 0ba690
    {192,  96,   0},    /* 13:  darker orange */
Packit 0ba690
    { 24,  60,   0},    /* 14:  dark green-yellow */
Packit 0ba690
    { 85, 125, 200},    /* 15:  ice blue */
Packit 0ba690
    {192, 192, 192}     /* 16:  Netscape/Mosaic gray */
Packit 0ba690
};
Packit 0ba690
/* not used for now, but should be for error-checking:
Packit 0ba690
static int num_rgb = sizeof(rgb) / sizeof(struct rgb_color);
Packit 0ba690
 */
Packit 0ba690
Packit 0ba690
/*
Packit 0ba690
    This whole struct is a fairly cheesy way to keep the number of
Packit 0ba690
    command-line options to a minimum.  The radial-waves background
Packit 0ba690
    type is a particularly poor fit to the integer elements of the
Packit 0ba690
    struct...but a few macros and a little fixed-point math will do
Packit 0ba690
    wonders for ya.
Packit 0ba690
Packit 0ba690
    type bits:
Packit 0ba690
       F E D C B A 9 8 7 6 5 4 3 2 1 0
Packit 0ba690
                             | | | | |
Packit 0ba690
                             | | +-+-+-- 0 = sharp-edged checkerboard
Packit 0ba690
                             | |         1 = soft diamonds
Packit 0ba690
                             | |         2 = radial waves
Packit 0ba690
                             | |       3-7 = undefined
Packit 0ba690
                             | +-- gradient #2 inverted?
Packit 0ba690
                             +-- alternating columns inverted?
Packit 0ba690
 */
Packit 0ba690
static struct background_pattern {
Packit 0ba690
    ush type;
Packit 0ba690
    int rgb1_max, rgb1_min;     /* or bg_freq, bg_gray */
Packit 0ba690
    int rgb2_max, rgb2_min;     /* or bg_bsat, bg_brot (both scaled by 10)*/
Packit 0ba690
} bg[] = {
Packit 0ba690
    {0,     1,1, 16,16},        /* checkered:  white vs. light gray (basic) */
Packit 0ba690
    {0+8,   2,0,  1,15},        /* checkered:  tan/black vs. white/ice blue */
Packit 0ba690
    {0+24,  2,0,  1,0},         /* checkered:  tan/black vs. white/black */
Packit 0ba690
    {0+8,   4,5,  0,2},         /* checkered:  gold/yellow vs. black/tan */
Packit 0ba690
    {0+8,   4,5,  0,6},         /* checkered:  gold/yellow vs. black/blue */
Packit 0ba690
    {0,     7,0,  8,9},         /* checkered:  deep blue/black vs. magenta */
Packit 0ba690
    {0+8,  13,0,  5,14},        /* checkered:  orange/black vs. yellow */
Packit 0ba690
    {0+8,  12,0, 10,11},        /* checkered:  orange/black vs. red */
Packit 0ba690
    {1,     7,0,  8,0},         /* diamonds:  deep blue/black vs. magenta */
Packit 0ba690
    {1,    12,0, 11,0},         /* diamonds:  orange vs. dark red */
Packit 0ba690
    {1,    10,0,  7,0},         /* diamonds:  red vs. medium blue */
Packit 0ba690
    {1,     4,0,  5,0},         /* diamonds:  gold vs. yellow */
Packit 0ba690
    {1,     3,0,  0,0},         /* diamonds:  medium green vs. black */
Packit 0ba690
    {2,    16, 100,  20,   0},  /* radial:  ~hard radial color-beams */
Packit 0ba690
    {2,    18, 100,  10,   2},  /* radial:  soft, curved radial color-beams */
Packit 0ba690
    {2,    16, 256, 100, 250},  /* radial:  very tight spiral */
Packit 0ba690
    {2, 10000, 256,  11,   0}   /* radial:  dipole-moire' (almost fractal) */
Packit 0ba690
};
Packit 0ba690
static int num_bgpat = sizeof(bg) / sizeof(struct background_pattern);
Packit 0ba690
Packit 0ba690
Packit 0ba690
/* X-specific variables */
Packit 0ba690
static char *displayname;
Packit 0ba690
static XImage *ximage;
Packit 0ba690
static Display *display;
Packit 0ba690
static int depth;
Packit 0ba690
static Visual *visual;
Packit 0ba690
static XVisualInfo *visual_list;
Packit 0ba690
static int RShift, GShift, BShift;
Packit 0ba690
static ulg RMask, GMask, BMask;
Packit 0ba690
static Window window;
Packit 0ba690
static GC gc;
Packit 0ba690
static Colormap colormap;
Packit 0ba690
Packit 0ba690
static int have_nondefault_visual = FALSE;
Packit 0ba690
static int have_colormap = FALSE;
Packit 0ba690
static int have_window = FALSE;
Packit 0ba690
static int have_gc = FALSE;
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
int main(int argc, char **argv)
Packit 0ba690
{
Packit 0ba690
#ifdef sgi
Packit 0ba690
    char tmpline[80];
Packit 0ba690
#endif
Packit 0ba690
    char *p, *bgstr = NULL;
Packit 0ba690
    int rc, alen, flen;
Packit 0ba690
    int error = 0;
Packit 0ba690
    int timing = FALSE;
Packit 0ba690
    int have_bg = FALSE;
Packit 0ba690
#ifdef FEATURE_LOOP
Packit 0ba690
    int loop = FALSE;
Packit 0ba690
    long loop_interval = -1;		/* seconds (100,000 max) */
Packit 0ba690
#endif
Packit 0ba690
    double LUT_exponent;                /* just the lookup table */
Packit 0ba690
    double CRT_exponent = 2.2;          /* just the monitor */
Packit 0ba690
    double default_display_exponent;    /* whole display system */
Packit 0ba690
    XEvent e;
Packit 0ba690
    KeySym k;
Packit 0ba690
Packit 0ba690
Packit 0ba690
    /* First initialize a few things, just to be sure--memset takes care of
Packit 0ba690
     * default background color (black), booleans (FALSE), pointers (NULL),
Packit 0ba690
     * etc. */
Packit 0ba690
Packit 0ba690
    displayname = (char *)NULL;
Packit 0ba690
    filename = (char *)NULL;
Packit 0ba690
    memset(&rpng2_info, 0, sizeof(mainprog_info));
Packit 0ba690
Packit 0ba690
Packit 0ba690
    /* Set the default value for our display-system exponent, i.e., the
Packit 0ba690
     * product of the CRT exponent and the exponent corresponding to
Packit 0ba690
     * the frame-buffer's lookup table (LUT), if any.  This is not an
Packit 0ba690
     * exhaustive list of LUT values (e.g., OpenStep has a lot of weird
Packit 0ba690
     * ones), but it should cover 99% of the current possibilities. */
Packit 0ba690
Packit 0ba690
#if defined(NeXT)
Packit 0ba690
    /* third-party utilities can modify the default LUT exponent */
Packit 0ba690
    LUT_exponent = 1.0 / 2.2;
Packit 0ba690
    /*
Packit 0ba690
    if (some_next_function_that_returns_gamma(&next_gamma))
Packit 0ba690
        LUT_exponent = 1.0 / next_gamma;
Packit 0ba690
     */
Packit 0ba690
#elif defined(sgi)
Packit 0ba690
    LUT_exponent = 1.0 / 1.7;
Packit 0ba690
    /* there doesn't seem to be any documented function to
Packit 0ba690
     * get the "gamma" value, so we do it the hard way */
Packit 0ba690
    infile = fopen("/etc/config/system.glGammaVal", "r");
Packit 0ba690
    if (infile) {
Packit 0ba690
        double sgi_gamma;
Packit 0ba690
Packit 0ba690
        fgets(tmpline, 80, infile);
Packit 0ba690
        fclose(infile);
Packit 0ba690
        sgi_gamma = atof(tmpline);
Packit 0ba690
        if (sgi_gamma > 0.0)
Packit 0ba690
            LUT_exponent = 1.0 / sgi_gamma;
Packit 0ba690
    }
Packit 0ba690
#elif defined(Macintosh)
Packit 0ba690
    LUT_exponent = 1.8 / 2.61;
Packit 0ba690
    /*
Packit 0ba690
    if (some_mac_function_that_returns_gamma(&mac_gamma))
Packit 0ba690
        LUT_exponent = mac_gamma / 2.61;
Packit 0ba690
     */
Packit 0ba690
#else
Packit 0ba690
    LUT_exponent = 1.0;   /* assume no LUT:  most PCs */
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
    /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
Packit 0ba690
    default_display_exponent = LUT_exponent * CRT_exponent;
Packit 0ba690
Packit 0ba690
Packit 0ba690
    /* If the user has set the SCREEN_GAMMA environment variable as suggested
Packit 0ba690
     * (somewhat imprecisely) in the libpng documentation, use that; otherwise
Packit 0ba690
     * use the default value we just calculated.  Either way, the user may
Packit 0ba690
     * override this via a command-line option. */
Packit 0ba690
Packit 0ba690
    if ((p = getenv("SCREEN_GAMMA")) != NULL)
Packit 0ba690
        rpng2_info.display_exponent = atof(p);
Packit 0ba690
    else
Packit 0ba690
        rpng2_info.display_exponent = default_display_exponent;
Packit 0ba690
Packit 0ba690
Packit 0ba690
    /* Now parse the command line for options and the PNG filename. */
Packit 0ba690
Packit 0ba690
    while (*++argv && !error) {
Packit 0ba690
        if (!strncmp(*argv, "-display", 2)) {
Packit 0ba690
            if (!*++argv)
Packit 0ba690
                ++error;
Packit 0ba690
            else
Packit 0ba690
                displayname = *argv;
Packit 0ba690
        } else if (!strncmp(*argv, "-gamma", 2)) {
Packit 0ba690
            if (!*++argv)
Packit 0ba690
                ++error;
Packit 0ba690
            else {
Packit 0ba690
                rpng2_info.display_exponent = atof(*argv);
Packit 0ba690
                if (rpng2_info.display_exponent <= 0.0)
Packit 0ba690
                    ++error;
Packit 0ba690
            }
Packit 0ba690
        } else if (!strncmp(*argv, "-bgcolor", 4)) {
Packit 0ba690
            if (!*++argv)
Packit 0ba690
                ++error;
Packit 0ba690
            else {
Packit 0ba690
                bgstr = *argv;
Packit 0ba690
                if (strlen(bgstr) != 7 || bgstr[0] != '#')
Packit 0ba690
                    ++error;
Packit 0ba690
                else {
Packit 0ba690
                    have_bg = TRUE;
Packit 0ba690
                    bg_image = FALSE;
Packit 0ba690
                }
Packit 0ba690
            }
Packit 0ba690
        } else if (!strncmp(*argv, "-bgpat", 4)) {
Packit 0ba690
            if (!*++argv)
Packit 0ba690
                ++error;
Packit 0ba690
            else {
Packit 0ba690
                pat = atoi(*argv);
Packit 0ba690
                if (pat >= 0 && pat < num_bgpat) {
Packit 0ba690
                    bg_image = TRUE;
Packit 0ba690
                    have_bg = FALSE;
Packit 0ba690
                } else
Packit 0ba690
                    ++error;
Packit 0ba690
            }
Packit 0ba690
        } else if (!strncmp(*argv, "-usleep", 2)) {
Packit 0ba690
            if (!*++argv)
Packit 0ba690
                ++error;
Packit 0ba690
            else {
Packit 0ba690
                usleep_duration = (ulg)atol(*argv);
Packit 0ba690
                demo_timing = TRUE;
Packit 0ba690
            }
Packit 0ba690
        } else if (!strncmp(*argv, "-pause", 2)) {
Packit 0ba690
            pause_after_pass = TRUE;
Packit 0ba690
        } else if (!strncmp(*argv, "-timing", 2)) {
Packit 0ba690
            timing = TRUE;
Packit 0ba690
#ifdef FEATURE_LOOP
Packit 0ba690
        } else if (!strncmp(*argv, "-loop", 2)) {
Packit 0ba690
            loop = TRUE;
Packit 0ba690
            if (!argv[1] || !is_number(argv[1]))
Packit 0ba690
                loop_interval = 2;
Packit 0ba690
            else {
Packit 0ba690
                ++argv;
Packit 0ba690
                loop_interval = atol(*argv);
Packit 0ba690
                if (loop_interval < 0)
Packit 0ba690
                    loop_interval = 2;
Packit 0ba690
                else if (loop_interval > 100000)   /* bit more than one day */
Packit 0ba690
                    loop_interval = 100000;
Packit 0ba690
            }
Packit 0ba690
#endif
Packit 0ba690
#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__))
Packit 0ba690
        } else if (!strncmp(*argv, "-nommxfilters", 7)) {
Packit 0ba690
            rpng2_info.nommxfilters = TRUE;
Packit 0ba690
        } else if (!strncmp(*argv, "-nommxcombine", 7)) {
Packit 0ba690
            rpng2_info.nommxcombine = TRUE;
Packit 0ba690
        } else if (!strncmp(*argv, "-nommxinterlace", 7)) {
Packit 0ba690
            rpng2_info.nommxinterlace = TRUE;
Packit 0ba690
        } else if (!strcmp(*argv, "-nommx")) {
Packit 0ba690
            rpng2_info.nommxfilters = TRUE;
Packit 0ba690
            rpng2_info.nommxcombine = TRUE;
Packit 0ba690
            rpng2_info.nommxinterlace = TRUE;
Packit 0ba690
#endif
Packit 0ba690
        } else {
Packit 0ba690
            if (**argv != '-') {
Packit 0ba690
                filename = *argv;
Packit 0ba690
                if (argv[1])   /* shouldn't be any more args after filename */
Packit 0ba690
                    ++error;
Packit 0ba690
            } else
Packit 0ba690
                ++error;   /* not expecting any other options */
Packit 0ba690
        }
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    if (!filename)
Packit 0ba690
        ++error;
Packit 0ba690
Packit 0ba690
Packit 0ba690
    /* print usage screen if any errors up to this point */
Packit 0ba690
Packit 0ba690
    if (error) {
Packit 0ba690
        fprintf(stderr, "\n%s %s:  %s\n\n", PROGNAME, VERSION, appname);
Packit 0ba690
        readpng2_version_info();
Packit 0ba690
        fprintf(stderr, "\n"
Packit 0ba690
          "Usage:  %s [-display xdpy] [-gamma exp] [-bgcolor bg | -bgpat pat]\n"
Packit 0ba690
#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__))
Packit 0ba690
          "        %*s [[-nommxfilters] [-nommxcombine] [-nommxinterlace] | -nommx]\n"
Packit 0ba690
#endif
Packit 0ba690
#ifdef FEATURE_LOOP
Packit 0ba690
          "        %*s [-usleep dur | -timing] [-pause] [-loop [sec]] file.png\n\n"
Packit 0ba690
#else
Packit 0ba690
          "        %*s [-usleep dur | -timing] [-pause] file.png\n\n"
Packit 0ba690
#endif
Packit 0ba690
          "    xdpy\tname of the target X display (e.g., ``hostname:0'')\n"
Packit 0ba690
          "    exp \ttransfer-function exponent (``gamma'') of the display\n"
Packit 0ba690
          "\t\t  system in floating-point format (e.g., ``%.1f''); equal\n"
Packit 0ba690
          "\t\t  to the product of the lookup-table exponent (varies)\n"
Packit 0ba690
          "\t\t  and the CRT exponent (usually 2.2); must be positive\n"
Packit 0ba690
          "    bg  \tdesired background color in 7-character hex RGB format\n"
Packit 0ba690
          "\t\t  (e.g., ``#ff7700'' for orange:  same as HTML colors);\n"
Packit 0ba690
          "\t\t  used with transparent images; overrides -bgpat\n"
Packit 0ba690
          "    pat \tdesired background pattern number (0-%d); used with\n"
Packit 0ba690
          "\t\t  transparent images; overrides -bgcolor\n"
Packit 0ba690
#ifdef FEATURE_LOOP
Packit 0ba690
          "    -loop\tloops through background images after initial display\n"
Packit 0ba690
          "\t\t  is complete (depends on -bgpat)\n"
Packit 0ba690
          "    sec \tseconds to display each background image (default = 2)\n"
Packit 0ba690
#endif
Packit 0ba690
#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__))
Packit 0ba690
          "    -nommx*\tdisable optimized MMX routines for decoding row filters,\n"
Packit 0ba690
          "\t\t  combining rows, and expanding interlacing, respectively\n"
Packit 0ba690
#endif
Packit 0ba690
          "    dur \tduration in microseconds to wait after displaying each\n"
Packit 0ba690
          "\t\t  row (for demo purposes)\n"
Packit 0ba690
          "    -timing\tenables delay for every block read, to simulate modem\n"
Packit 0ba690
          "\t\t  download of image (~36 Kbps)\n"
Packit 0ba690
          "    -pause\tpauses after displaying each pass until mouse clicked\n"
Packit 0ba690
          "\nPress Q, Esc or mouse button 1 (within image window, after image\n"
Packit 0ba690
          "is displayed) to quit.\n"
Packit 0ba690
          "\n", PROGNAME,
Packit 0ba690
#if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__))
Packit 0ba690
          (int)strlen(PROGNAME), " ",
Packit 0ba690
#endif
Packit 0ba690
          (int)strlen(PROGNAME), " ", default_display_exponent, num_bgpat-1);
Packit 0ba690
        exit(1);
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
Packit 0ba690
    if (!(infile = fopen(filename, "rb"))) {
Packit 0ba690
        fprintf(stderr, PROGNAME ":  can't open PNG file [%s]\n", filename);
Packit 0ba690
        ++error;
Packit 0ba690
    } else {
Packit 0ba690
        incount = fread(inbuf, 1, INBUFSIZE, infile);
Packit 0ba690
        if (incount < 8 || !readpng2_check_sig(inbuf, 8)) {
Packit 0ba690
            fprintf(stderr, PROGNAME
Packit 0ba690
              ":  [%s] is not a PNG file: incorrect signature\n",
Packit 0ba690
              filename);
Packit 0ba690
            ++error;
Packit 0ba690
        } else if ((rc = readpng2_init(&rpng2_info)) != 0) {
Packit 0ba690
            switch (rc) {
Packit 0ba690
                case 2:
Packit 0ba690
                    fprintf(stderr, PROGNAME
Packit 0ba690
                      ":  [%s] has bad IHDR (libpng longjmp)\n", filename);
Packit 0ba690
                    break;
Packit 0ba690
                case 4:
Packit 0ba690
                    fprintf(stderr, PROGNAME ":  insufficient memory\n");
Packit 0ba690
                    break;
Packit 0ba690
                default:
Packit 0ba690
                    fprintf(stderr, PROGNAME
Packit 0ba690
                      ":  unknown readpng2_init() error\n");
Packit 0ba690
                    break;
Packit 0ba690
            }
Packit 0ba690
            ++error;
Packit 0ba690
        } else {
Packit 0ba690
            Trace((stderr, "about to call XOpenDisplay()\n"))
Packit 0ba690
            display = XOpenDisplay(displayname);
Packit 0ba690
            if (!display) {
Packit 0ba690
                readpng2_cleanup(&rpng2_info);
Packit 0ba690
                fprintf(stderr, PROGNAME ":  can't open X display [%s]\n",
Packit 0ba690
                  displayname? displayname : "default");
Packit 0ba690
                ++error;
Packit 0ba690
            }
Packit 0ba690
        }
Packit 0ba690
        if (error)
Packit 0ba690
            fclose(infile);
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
Packit 0ba690
    if (error) {
Packit 0ba690
        fprintf(stderr, PROGNAME ":  aborting.\n");
Packit 0ba690
        exit(2);
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
Packit 0ba690
    /* set the title-bar string, but make sure buffer doesn't overflow */
Packit 0ba690
Packit 0ba690
    alen = strlen(appname);
Packit 0ba690
    flen = strlen(filename);
Packit 0ba690
    if (alen + flen + 3 > 1023)
Packit 0ba690
        sprintf(titlebar, "%s:  ...%s", appname, filename+(alen+flen+6-1023));
Packit 0ba690
    else
Packit 0ba690
        sprintf(titlebar, "%s:  %s", appname, filename);
Packit 0ba690
Packit 0ba690
Packit 0ba690
    /* set some final rpng2_info variables before entering main data loop */
Packit 0ba690
Packit 0ba690
    if (have_bg) {
Packit 0ba690
        unsigned r, g, b;   /* this approach quiets compiler warnings */
Packit 0ba690
Packit 0ba690
        sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b);
Packit 0ba690
        rpng2_info.bg_red   = (uch)r;
Packit 0ba690
        rpng2_info.bg_green = (uch)g;
Packit 0ba690
        rpng2_info.bg_blue  = (uch)b;
Packit 0ba690
    } else
Packit 0ba690
        rpng2_info.need_bgcolor = TRUE;
Packit 0ba690
Packit 0ba690
    rpng2_info.state = kPreInit;
Packit 0ba690
    rpng2_info.mainprog_init = rpng2_x_init;
Packit 0ba690
    rpng2_info.mainprog_display_row = rpng2_x_display_row;
Packit 0ba690
    rpng2_info.mainprog_finish_display = rpng2_x_finish_display;
Packit 0ba690
Packit 0ba690
Packit 0ba690
    /* OK, this is the fun part:  call readpng2_decode_data() at the start of
Packit 0ba690
     * the loop to deal with our first buffer of data (read in above to verify
Packit 0ba690
     * that the file is a PNG image), then loop through the file and continue
Packit 0ba690
     * calling the same routine to handle each chunk of data.  It in turn
Packit 0ba690
     * passes the data to libpng, which will invoke one or more of our call-
Packit 0ba690
     * backs as decoded data become available.  We optionally call sleep() for
Packit 0ba690
     * one second per iteration to simulate downloading the image via an analog
Packit 0ba690
     * modem. */
Packit 0ba690
Packit 0ba690
    for (;;) {
Packit 0ba690
        Trace((stderr, "about to call readpng2_decode_data()\n"))
Packit 0ba690
        if (readpng2_decode_data(&rpng2_info, inbuf, incount))
Packit 0ba690
            ++error;
Packit 0ba690
        Trace((stderr, "done with readpng2_decode_data()\n"))
Packit 0ba690
Packit 0ba690
        if (error || incount != INBUFSIZE || rpng2_info.state == kDone) {
Packit 0ba690
            if (rpng2_info.state == kDone) {
Packit 0ba690
                Trace((stderr, "done decoding PNG image\n"))
Packit 0ba690
            } else if (ferror(infile)) {
Packit 0ba690
                fprintf(stderr, PROGNAME
Packit 0ba690
                  ":  error while reading PNG image file\n");
Packit 0ba690
                exit(3);
Packit 0ba690
            } else if (feof(infile)) {
Packit 0ba690
                fprintf(stderr, PROGNAME ":  end of file reached "
Packit 0ba690
                  "(unexpectedly) while reading PNG image file\n");
Packit 0ba690
                exit(3);
Packit 0ba690
            } else /* if (error) */ {
Packit 0ba690
                // will print error message below
Packit 0ba690
            }
Packit 0ba690
            break;
Packit 0ba690
        }
Packit 0ba690
Packit 0ba690
        if (timing)
Packit 0ba690
            sleep(1);
Packit 0ba690
Packit 0ba690
        incount = fread(inbuf, 1, INBUFSIZE, infile);
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
Packit 0ba690
    /* clean up PNG stuff and report any decoding errors */
Packit 0ba690
Packit 0ba690
    fclose(infile);
Packit 0ba690
    Trace((stderr, "about to call readpng2_cleanup()\n"))
Packit 0ba690
    readpng2_cleanup(&rpng2_info);
Packit 0ba690
Packit 0ba690
    if (error) {
Packit 0ba690
        fprintf(stderr, PROGNAME ":  libpng error while decoding PNG image\n");
Packit 0ba690
        exit(3);
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
Packit 0ba690
#ifdef FEATURE_LOOP
Packit 0ba690
Packit 0ba690
    if (loop && bg_image) {
Packit 0ba690
        Trace((stderr, "entering -loop loop (FEATURE_LOOP)\n"))
Packit 0ba690
        for (;;) {
Packit 0ba690
            int i, use_sleep;
Packit 0ba690
            struct timeval now, then;
Packit 0ba690
Packit 0ba690
            /* get current time and add loop_interval to get target time */
Packit 0ba690
            if (gettimeofday(&then, NULL) == 0) {
Packit 0ba690
                then.tv_sec += loop_interval;
Packit 0ba690
                use_sleep = FALSE;
Packit 0ba690
            } else
Packit 0ba690
                use_sleep = TRUE;
Packit 0ba690
Packit 0ba690
            /* do quick check for a quit event but don't wait for it */
Packit 0ba690
            /* GRR BUG:  should also check for Expose events and redraw... */
Packit 0ba690
            if (XCheckMaskEvent(display, KeyPressMask | ButtonPressMask, &e))
Packit 0ba690
                if (QUIT(e,k))
Packit 0ba690
                    break;
Packit 0ba690
Packit 0ba690
            /* generate next background image */
Packit 0ba690
            if (++pat >= num_bgpat)
Packit 0ba690
                pat = 0;
Packit 0ba690
            rpng2_x_reload_bg_image();
Packit 0ba690
Packit 0ba690
            /* wait for timeout, using whatever means are available */
Packit 0ba690
            if (use_sleep || gettimeofday(&now, NULL) != 0) {
Packit 0ba690
                for (i = loop_interval;  i > 0;  --i) {
Packit 0ba690
                    sleep(1);
Packit 0ba690
                    /* GRR BUG:  also need to check for Expose (and redraw!) */
Packit 0ba690
                    if (XCheckMaskEvent(display, KeyPressMask | ButtonPressMask,
Packit 0ba690
                        &e) && QUIT(e,k))
Packit 0ba690
                        break;
Packit 0ba690
                }
Packit 0ba690
            } else {
Packit 0ba690
                /* Y2038 BUG! */
Packit 0ba690
                if (now.tv_sec < then.tv_sec ||
Packit 0ba690
                    (now.tv_sec == then.tv_sec && now.tv_usec < then.tv_usec))
Packit 0ba690
                {
Packit 0ba690
                    int quit = FALSE;
Packit 0ba690
                    long seconds_to_go = then.tv_sec - now.tv_sec;
Packit 0ba690
                    long usleep_usec;
Packit 0ba690
Packit 0ba690
                    /* basically chew up most of remaining loop-interval with
Packit 0ba690
                     *  calls to sleep(1) interleaved with checks for quit
Packit 0ba690
                     *  events, but also recalc time-to-go periodically; when
Packit 0ba690
                     *  done, clean up any remaining time with usleep() call
Packit 0ba690
                     *  (could also use SIGALRM, but signals are a pain...) */
Packit 0ba690
                    while (seconds_to_go-- > 1) {
Packit 0ba690
                        int seconds_done = 0;
Packit 0ba690
Packit 0ba690
                        for (i = seconds_to_go;  i > 0 && !quit;  --i) {
Packit 0ba690
                            sleep(1);
Packit 0ba690
                            /* GRR BUG:  need to check for Expose and redraw */
Packit 0ba690
                            if (XCheckMaskEvent(display, KeyPressMask |
Packit 0ba690
                                ButtonPressMask, &e) && QUIT(e,k))
Packit 0ba690
                                quit = TRUE;
Packit 0ba690
                            if (++seconds_done > 1000)
Packit 0ba690
                                break;   /* time to redo seconds_to_go meas. */
Packit 0ba690
                        }
Packit 0ba690
                        if (quit)
Packit 0ba690
                            break;
Packit 0ba690
Packit 0ba690
                        /* OK, more than 1000 seconds since last check:
Packit 0ba690
                         *  correct the time-to-go measurement for drift */
Packit 0ba690
                        if (gettimeofday(&now, NULL) == 0) {
Packit 0ba690
                            if (now.tv_sec >= then.tv_sec)
Packit 0ba690
                                break;
Packit 0ba690
                            seconds_to_go = then.tv_sec - now.tv_sec;
Packit 0ba690
                        } else
Packit 0ba690
                            ++seconds_to_go;  /* restore what we subtracted */
Packit 0ba690
                    }
Packit 0ba690
                    if (quit)
Packit 0ba690
                        break;   /* breaks outer do-loop, skips redisplay */
Packit 0ba690
Packit 0ba690
                    /* since difference between "now" and "then" is already
Packit 0ba690
                     *  eaten up to within a couple of seconds, don't need to
Packit 0ba690
                     *  worry about overflow--but might have overshot (neg.) */
Packit 0ba690
                    if (gettimeofday(&now, NULL) == 0) {
Packit 0ba690
                        usleep_usec = 1000000L*(then.tv_sec - now.tv_sec) +
Packit 0ba690
                          then.tv_usec - now.tv_usec;
Packit 0ba690
                        if (usleep_usec > 0)
Packit 0ba690
                            usleep((ulg)usleep_usec);
Packit 0ba690
                    }
Packit 0ba690
                }
Packit 0ba690
            }
Packit 0ba690
Packit 0ba690
            /* composite image against new background and display (note that
Packit 0ba690
             *  we do not take into account the time spent doing this...) */
Packit 0ba690
            rpng2_x_redisplay_image (0, 0, rpng2_info.width, rpng2_info.height);
Packit 0ba690
        }
Packit 0ba690
Packit 0ba690
    } else /* FALL THROUGH and do the normal thing */
Packit 0ba690
Packit 0ba690
#endif /* FEATURE_LOOP */
Packit 0ba690
Packit 0ba690
    /* wait for the user to tell us when to quit */
Packit 0ba690
Packit 0ba690
    if (rpng2_info.state >= kWindowInit) {
Packit 0ba690
        Trace((stderr, "entering final wait-for-quit-event loop\n"))
Packit 0ba690
        do {
Packit 0ba690
            XNextEvent(display, &e);
Packit 0ba690
            if (e.type == Expose) {
Packit 0ba690
                XExposeEvent *ex = (XExposeEvent *)&e;
Packit 0ba690
                rpng2_x_redisplay_image (ex->x, ex->y, ex->width, ex->height);
Packit 0ba690
            }
Packit 0ba690
        } while (!QUIT(e,k));
Packit 0ba690
    } else {
Packit 0ba690
        fprintf(stderr, PROGNAME ":  init callback never called:  probable "
Packit 0ba690
          "libpng error while decoding PNG metadata\n");
Packit 0ba690
        exit(4);
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
Packit 0ba690
    /* we're done:  clean up all image and X resources and go away */
Packit 0ba690
Packit 0ba690
    Trace((stderr, "about to call rpng2_x_cleanup()\n"))
Packit 0ba690
    rpng2_x_cleanup();
Packit 0ba690
Packit 0ba690
    return 0;
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
/* this function is called by readpng2_info_callback() in readpng2.c, which
Packit 0ba690
 * in turn is called by libpng after all of the pre-IDAT chunks have been
Packit 0ba690
 * read and processed--i.e., we now have enough info to finish initializing */
Packit 0ba690
Packit 0ba690
static void rpng2_x_init(void)
Packit 0ba690
{
Packit 0ba690
    ulg i;
Packit 0ba690
    ulg rowbytes = rpng2_info.rowbytes;
Packit 0ba690
Packit 0ba690
    Trace((stderr, "beginning rpng2_x_init()\n"))
Packit 0ba690
    Trace((stderr, "  rowbytes = %d\n", rpng2_info.rowbytes))
Packit 0ba690
    Trace((stderr, "  width  = %ld\n", rpng2_info.width))
Packit 0ba690
    Trace((stderr, "  height = %ld\n", rpng2_info.height))
Packit 0ba690
Packit 0ba690
    rpng2_info.image_data = (uch *)malloc(rowbytes * rpng2_info.height);
Packit 0ba690
    if (!rpng2_info.image_data) {
Packit 0ba690
        readpng2_cleanup(&rpng2_info);
Packit 0ba690
        return;
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    rpng2_info.row_pointers = (uch **)malloc(rpng2_info.height * sizeof(uch *));
Packit 0ba690
    if (!rpng2_info.row_pointers) {
Packit 0ba690
        free(rpng2_info.image_data);
Packit 0ba690
        rpng2_info.image_data = NULL;
Packit 0ba690
        readpng2_cleanup(&rpng2_info);
Packit 0ba690
        return;
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    for (i = 0;  i < rpng2_info.height;  ++i)
Packit 0ba690
        rpng2_info.row_pointers[i] = rpng2_info.image_data + i*rowbytes;
Packit 0ba690
Packit 0ba690
Packit 0ba690
    /* do the basic X initialization stuff, make the window, and fill it with
Packit 0ba690
     * the user-specified, file-specified or default background color or
Packit 0ba690
     * pattern */
Packit 0ba690
Packit 0ba690
    if (rpng2_x_create_window()) {
Packit 0ba690
Packit 0ba690
        /* GRR TEMPORARY HACK:  this is fundamentally no different from cases
Packit 0ba690
         * above; libpng should longjmp() back to us when png_ptr goes away.
Packit 0ba690
         * If we/it segfault instead, seems like a libpng bug... */
Packit 0ba690
Packit 0ba690
        /* we're here via libpng callback, so if window fails, clean and bail */
Packit 0ba690
        readpng2_cleanup(&rpng2_info);
Packit 0ba690
        rpng2_x_cleanup();
Packit 0ba690
        exit(2);
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    rpng2_info.state = kWindowInit;
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
static int rpng2_x_create_window(void)
Packit 0ba690
{
Packit 0ba690
    ulg bg_red   = rpng2_info.bg_red;
Packit 0ba690
    ulg bg_green = rpng2_info.bg_green;
Packit 0ba690
    ulg bg_blue  = rpng2_info.bg_blue;
Packit 0ba690
    ulg bg_pixel = 0L;
Packit 0ba690
    ulg attrmask;
Packit 0ba690
    int need_colormap = FALSE;
Packit 0ba690
    int screen, pad;
Packit 0ba690
    uch *xdata;
Packit 0ba690
    Window root;
Packit 0ba690
    XEvent e;
Packit 0ba690
    XGCValues gcvalues;
Packit 0ba690
    XSetWindowAttributes attr;
Packit 0ba690
    XTextProperty windowName, *pWindowName = &windowName;
Packit 0ba690
    XTextProperty iconName, *pIconName = &iconName;
Packit 0ba690
    XVisualInfo visual_info;
Packit 0ba690
    XSizeHints *size_hints;
Packit 0ba690
    XWMHints *wm_hints;
Packit 0ba690
    XClassHint *class_hints;
Packit 0ba690
Packit 0ba690
Packit 0ba690
    Trace((stderr, "beginning rpng2_x_create_window()\n"))
Packit 0ba690
Packit 0ba690
    screen = DefaultScreen(display);
Packit 0ba690
    depth = DisplayPlanes(display, screen);
Packit 0ba690
    root = RootWindow(display, screen);
Packit 0ba690
Packit 0ba690
#ifdef DEBUG
Packit 0ba690
    XSynchronize(display, True);
Packit 0ba690
#endif
Packit 0ba690
Packit 0ba690
    if (depth != 16 && depth != 24 && depth != 32) {
Packit 0ba690
        int visuals_matched = 0;
Packit 0ba690
Packit 0ba690
        Trace((stderr, "default depth is %d:  checking other visuals\n",
Packit 0ba690
          depth))
Packit 0ba690
Packit 0ba690
        /* 24-bit first */
Packit 0ba690
        visual_info.screen = screen;
Packit 0ba690
        visual_info.depth = 24;
Packit 0ba690
        visual_list = XGetVisualInfo(display,
Packit 0ba690
          VisualScreenMask | VisualDepthMask, &visual_info, &visuals_matched);
Packit 0ba690
        if (visuals_matched == 0) {
Packit 0ba690
/* GRR:  add 15-, 16- and 32-bit TrueColor visuals (also DirectColor?) */
Packit 0ba690
            fprintf(stderr, "default screen depth %d not supported, and no"
Packit 0ba690
              " 24-bit visuals found\n", depth);
Packit 0ba690
            return 2;
Packit 0ba690
        }
Packit 0ba690
        Trace((stderr, "XGetVisualInfo() returned %d 24-bit visuals\n",
Packit 0ba690
          visuals_matched))
Packit 0ba690
        visual = visual_list[0].visual;
Packit 0ba690
        depth = visual_list[0].depth;
Packit 0ba690
/*
Packit 0ba690
        colormap_size = visual_list[0].colormap_size;
Packit 0ba690
        visual_class = visual->class;
Packit 0ba690
        visualID = XVisualIDFromVisual(visual);
Packit 0ba690
 */
Packit 0ba690
        have_nondefault_visual = TRUE;
Packit 0ba690
        need_colormap = TRUE;
Packit 0ba690
    } else {
Packit 0ba690
        XMatchVisualInfo(display, screen, depth, TrueColor, &visual_info);
Packit 0ba690
        visual = visual_info.visual;
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    RMask = visual->red_mask;
Packit 0ba690
    GMask = visual->green_mask;
Packit 0ba690
    BMask = visual->blue_mask;
Packit 0ba690
Packit 0ba690
/* GRR:  add/check 8-bit support */
Packit 0ba690
    if (depth == 8 || need_colormap) {
Packit 0ba690
        colormap = XCreateColormap(display, root, visual, AllocNone);
Packit 0ba690
        if (!colormap) {
Packit 0ba690
            fprintf(stderr, "XCreateColormap() failed\n");
Packit 0ba690
            return 2;
Packit 0ba690
        }
Packit 0ba690
        have_colormap = TRUE;
Packit 0ba690
        if (depth == 8)
Packit 0ba690
            bg_image = FALSE;   /* gradient just wastes palette entries */
Packit 0ba690
    }
Packit 0ba690
    if (depth == 15 || depth == 16) {
Packit 0ba690
        RShift = 15 - rpng2_x_msb(RMask);    /* these are right-shifts */
Packit 0ba690
        GShift = 15 - rpng2_x_msb(GMask);
Packit 0ba690
        BShift = 15 - rpng2_x_msb(BMask);
Packit 0ba690
    } else if (depth > 16) {
Packit 0ba690
        RShift = rpng2_x_msb(RMask) - 7;     /* these are left-shifts */
Packit 0ba690
        GShift = rpng2_x_msb(GMask) - 7;
Packit 0ba690
        BShift = rpng2_x_msb(BMask) - 7;
Packit 0ba690
    }
Packit 0ba690
    if (depth >= 15 && (RShift < 0 || GShift < 0 || BShift < 0)) {
Packit 0ba690
        fprintf(stderr, "rpng2 internal logic error:  negative X shift(s)!\n");
Packit 0ba690
        return 2;
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
/*---------------------------------------------------------------------------
Packit 0ba690
    Finally, create the window.
Packit 0ba690
  ---------------------------------------------------------------------------*/
Packit 0ba690
Packit 0ba690
    attr.backing_store = Always;
Packit 0ba690
    attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask;
Packit 0ba690
    attrmask = CWBackingStore | CWEventMask;
Packit 0ba690
    if (have_nondefault_visual) {
Packit 0ba690
        attr.colormap = colormap;
Packit 0ba690
        attr.background_pixel = 0;
Packit 0ba690
        attr.border_pixel = 1;
Packit 0ba690
        attrmask |= CWColormap | CWBackPixel | CWBorderPixel;
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    window = XCreateWindow(display, root, 0, 0, rpng2_info.width,
Packit 0ba690
      rpng2_info.height, 0, depth, InputOutput, visual, attrmask, &attr);
Packit 0ba690
Packit 0ba690
    if (window == None) {
Packit 0ba690
        fprintf(stderr, "XCreateWindow() failed\n");
Packit 0ba690
        return 2;
Packit 0ba690
    } else
Packit 0ba690
        have_window = TRUE;
Packit 0ba690
Packit 0ba690
    if (depth == 8)
Packit 0ba690
        XSetWindowColormap(display, window, colormap);
Packit 0ba690
Packit 0ba690
    if (!XStringListToTextProperty(&window_name, 1, pWindowName))
Packit 0ba690
        pWindowName = NULL;
Packit 0ba690
    if (!XStringListToTextProperty(&icon_name, 1, pIconName))
Packit 0ba690
        pIconName = NULL;
Packit 0ba690
Packit 0ba690
    /* OK if either hints allocation fails; XSetWMProperties() allows NULLs */
Packit 0ba690
Packit 0ba690
    if ((size_hints = XAllocSizeHints()) != NULL) {
Packit 0ba690
        /* window will not be resizable */
Packit 0ba690
        size_hints->flags = PMinSize | PMaxSize;
Packit 0ba690
        size_hints->min_width = size_hints->max_width = (int)rpng2_info.width;
Packit 0ba690
        size_hints->min_height = size_hints->max_height =
Packit 0ba690
          (int)rpng2_info.height;
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    if ((wm_hints = XAllocWMHints()) != NULL) {
Packit 0ba690
        wm_hints->initial_state = NormalState;
Packit 0ba690
        wm_hints->input = True;
Packit 0ba690
     /* wm_hints->icon_pixmap = icon_pixmap; */
Packit 0ba690
        wm_hints->flags = StateHint | InputHint  /* | IconPixmapHint */ ;
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    if ((class_hints = XAllocClassHint()) != NULL) {
Packit 0ba690
        class_hints->res_name = res_name;
Packit 0ba690
        class_hints->res_class = res_class;
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    XSetWMProperties(display, window, pWindowName, pIconName, NULL, 0,
Packit 0ba690
      size_hints, wm_hints, class_hints);
Packit 0ba690
Packit 0ba690
    /* various properties and hints no longer needed; free memory */
Packit 0ba690
    if (pWindowName)
Packit 0ba690
       XFree(pWindowName->value);
Packit 0ba690
    if (pIconName)
Packit 0ba690
       XFree(pIconName->value);
Packit 0ba690
    if (size_hints)
Packit 0ba690
        XFree(size_hints);
Packit 0ba690
    if (wm_hints)
Packit 0ba690
       XFree(wm_hints);
Packit 0ba690
    if (class_hints)
Packit 0ba690
       XFree(class_hints);
Packit 0ba690
Packit 0ba690
    XMapWindow(display, window);
Packit 0ba690
Packit 0ba690
    gc = XCreateGC(display, window, 0, &gcvalues);
Packit 0ba690
    have_gc = TRUE;
Packit 0ba690
Packit 0ba690
/*---------------------------------------------------------------------------
Packit 0ba690
    Allocate memory for the X- and display-specific version of the image.
Packit 0ba690
  ---------------------------------------------------------------------------*/
Packit 0ba690
Packit 0ba690
    if (depth == 24 || depth == 32) {
Packit 0ba690
        xdata = (uch *)malloc(4*rpng2_info.width*rpng2_info.height);
Packit 0ba690
        pad = 32;
Packit 0ba690
    } else if (depth == 16) {
Packit 0ba690
        xdata = (uch *)malloc(2*rpng2_info.width*rpng2_info.height);
Packit 0ba690
        pad = 16;
Packit 0ba690
    } else /* depth == 8 */ {
Packit 0ba690
        xdata = (uch *)malloc(rpng2_info.width*rpng2_info.height);
Packit 0ba690
        pad = 8;
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    if (!xdata) {
Packit 0ba690
        fprintf(stderr, PROGNAME ":  unable to allocate image memory\n");
Packit 0ba690
        return 4;
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    ximage = XCreateImage(display, visual, depth, ZPixmap, 0,
Packit 0ba690
      (char *)xdata, rpng2_info.width, rpng2_info.height, pad, 0);
Packit 0ba690
Packit 0ba690
    if (!ximage) {
Packit 0ba690
        fprintf(stderr, PROGNAME ":  XCreateImage() failed\n");
Packit 0ba690
        free(xdata);
Packit 0ba690
        return 3;
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    /* to avoid testing the byte order every pixel (or doubling the size of
Packit 0ba690
     * the drawing routine with a giant if-test), we arbitrarily set the byte
Packit 0ba690
     * order to MSBFirst and let Xlib worry about inverting things on little-
Packit 0ba690
     * endian machines (e.g., Linux/x86, old VAXen, etc.)--this is not the
Packit 0ba690
     * most efficient approach (the giant if-test would be better), but in
Packit 0ba690
     * the interest of clarity, we'll take the easy way out... */
Packit 0ba690
Packit 0ba690
    ximage->byte_order = MSBFirst;
Packit 0ba690
Packit 0ba690
/*---------------------------------------------------------------------------
Packit 0ba690
    Fill window with the specified background color (default is black) or
Packit 0ba690
    faked "background image" (but latter is disabled if 8-bit; gradients
Packit 0ba690
    just waste palette entries).
Packit 0ba690
  ---------------------------------------------------------------------------*/
Packit 0ba690
Packit 0ba690
    if (bg_image)
Packit 0ba690
        rpng2_x_load_bg_image();    /* resets bg_image if fails */
Packit 0ba690
Packit 0ba690
    if (!bg_image) {
Packit 0ba690
        if (depth == 24 || depth == 32) {
Packit 0ba690
            bg_pixel = (bg_red   << RShift) |
Packit 0ba690
                       (bg_green << GShift) |
Packit 0ba690
                       (bg_blue  << BShift);
Packit 0ba690
        } else if (depth == 16) {
Packit 0ba690
            bg_pixel = (((bg_red   << 8) >> RShift) & RMask) |
Packit 0ba690
                       (((bg_green << 8) >> GShift) & GMask) |
Packit 0ba690
                       (((bg_blue  << 8) >> BShift) & BMask);
Packit 0ba690
        } else /* depth == 8 */ {
Packit 0ba690
Packit 0ba690
            /* GRR:  add 8-bit support */
Packit 0ba690
Packit 0ba690
        }
Packit 0ba690
        XSetForeground(display, gc, bg_pixel);
Packit 0ba690
        XFillRectangle(display, window, gc, 0, 0, rpng2_info.width,
Packit 0ba690
          rpng2_info.height);
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
/*---------------------------------------------------------------------------
Packit 0ba690
    Wait for first Expose event to do any drawing, then flush and return.
Packit 0ba690
  ---------------------------------------------------------------------------*/
Packit 0ba690
Packit 0ba690
    do
Packit 0ba690
        XNextEvent(display, &e);
Packit 0ba690
    while (e.type != Expose || e.xexpose.count);
Packit 0ba690
Packit 0ba690
    XFlush(display);
Packit 0ba690
Packit 0ba690
    return 0;
Packit 0ba690
Packit 0ba690
} /* end function rpng2_x_create_window() */
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
static int rpng2_x_load_bg_image(void)
Packit 0ba690
{
Packit 0ba690
    uch *src;
Packit 0ba690
    char *dest;
Packit 0ba690
    uch r1, r2, g1, g2, b1, b2;
Packit 0ba690
    uch r1_inv, r2_inv, g1_inv, g2_inv, b1_inv, b2_inv;
Packit 0ba690
    int k, hmax, max;
Packit 0ba690
    int xidx, yidx, yidx_max;
Packit 0ba690
    int even_odd_vert, even_odd_horiz, even_odd;
Packit 0ba690
    int invert_gradient2 = (bg[pat].type & 0x08);
Packit 0ba690
    int invert_column;
Packit 0ba690
    int ximage_rowbytes = ximage->bytes_per_line;
Packit 0ba690
    ulg i, row;
Packit 0ba690
    ulg pixel;
Packit 0ba690
Packit 0ba690
/*---------------------------------------------------------------------------
Packit 0ba690
    Allocate buffer for fake background image to be used with transparent
Packit 0ba690
    images; if this fails, revert to plain background color.
Packit 0ba690
  ---------------------------------------------------------------------------*/
Packit 0ba690
Packit 0ba690
    bg_rowbytes = 3 * rpng2_info.width;
Packit 0ba690
    bg_data = (uch *)malloc(bg_rowbytes * rpng2_info.height);
Packit 0ba690
    if (!bg_data) {
Packit 0ba690
        fprintf(stderr, PROGNAME
Packit 0ba690
          ":  unable to allocate memory for background image\n");
Packit 0ba690
        bg_image = 0;
Packit 0ba690
        return 1;
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    bgscale = (pat == 0)? 8 : bgscale_default;
Packit 0ba690
    yidx_max = bgscale - 1;
Packit 0ba690
Packit 0ba690
/*---------------------------------------------------------------------------
Packit 0ba690
    Vertical gradients (ramps) in NxN squares, alternating direction and
Packit 0ba690
    colors (N == bgscale).
Packit 0ba690
  ---------------------------------------------------------------------------*/
Packit 0ba690
Packit 0ba690
    if ((bg[pat].type & 0x07) == 0) {
Packit 0ba690
        uch r1_min  = rgb[bg[pat].rgb1_min].r;
Packit 0ba690
        uch g1_min  = rgb[bg[pat].rgb1_min].g;
Packit 0ba690
        uch b1_min  = rgb[bg[pat].rgb1_min].b;
Packit 0ba690
        uch r2_min  = rgb[bg[pat].rgb2_min].r;
Packit 0ba690
        uch g2_min  = rgb[bg[pat].rgb2_min].g;
Packit 0ba690
        uch b2_min  = rgb[bg[pat].rgb2_min].b;
Packit 0ba690
        int r1_diff = rgb[bg[pat].rgb1_max].r - r1_min;
Packit 0ba690
        int g1_diff = rgb[bg[pat].rgb1_max].g - g1_min;
Packit 0ba690
        int b1_diff = rgb[bg[pat].rgb1_max].b - b1_min;
Packit 0ba690
        int r2_diff = rgb[bg[pat].rgb2_max].r - r2_min;
Packit 0ba690
        int g2_diff = rgb[bg[pat].rgb2_max].g - g2_min;
Packit 0ba690
        int b2_diff = rgb[bg[pat].rgb2_max].b - b2_min;
Packit 0ba690
Packit 0ba690
        for (row = 0;  row < rpng2_info.height;  ++row) {
Packit 0ba690
            yidx = (int)(row % bgscale);
Packit 0ba690
            even_odd_vert = (int)((row / bgscale) & 1);
Packit 0ba690
Packit 0ba690
            r1 = r1_min + (r1_diff * yidx) / yidx_max;
Packit 0ba690
            g1 = g1_min + (g1_diff * yidx) / yidx_max;
Packit 0ba690
            b1 = b1_min + (b1_diff * yidx) / yidx_max;
Packit 0ba690
            r1_inv = r1_min + (r1_diff * (yidx_max-yidx)) / yidx_max;
Packit 0ba690
            g1_inv = g1_min + (g1_diff * (yidx_max-yidx)) / yidx_max;
Packit 0ba690
            b1_inv = b1_min + (b1_diff * (yidx_max-yidx)) / yidx_max;
Packit 0ba690
Packit 0ba690
            r2 = r2_min + (r2_diff * yidx) / yidx_max;
Packit 0ba690
            g2 = g2_min + (g2_diff * yidx) / yidx_max;
Packit 0ba690
            b2 = b2_min + (b2_diff * yidx) / yidx_max;
Packit 0ba690
            r2_inv = r2_min + (r2_diff * (yidx_max-yidx)) / yidx_max;
Packit 0ba690
            g2_inv = g2_min + (g2_diff * (yidx_max-yidx)) / yidx_max;
Packit 0ba690
            b2_inv = b2_min + (b2_diff * (yidx_max-yidx)) / yidx_max;
Packit 0ba690
Packit 0ba690
            dest = (char *)bg_data + row*bg_rowbytes;
Packit 0ba690
            for (i = 0;  i < rpng2_info.width;  ++i) {
Packit 0ba690
                even_odd_horiz = (int)((i / bgscale) & 1);
Packit 0ba690
                even_odd = even_odd_vert ^ even_odd_horiz;
Packit 0ba690
                invert_column =
Packit 0ba690
                  (even_odd_horiz && (bg[pat].type & 0x10));
Packit 0ba690
                if (even_odd == 0) {        /* gradient #1 */
Packit 0ba690
                    if (invert_column) {
Packit 0ba690
                        *dest++ = r1_inv;
Packit 0ba690
                        *dest++ = g1_inv;
Packit 0ba690
                        *dest++ = b1_inv;
Packit 0ba690
                    } else {
Packit 0ba690
                        *dest++ = r1;
Packit 0ba690
                        *dest++ = g1;
Packit 0ba690
                        *dest++ = b1;
Packit 0ba690
                    }
Packit 0ba690
                } else {                    /* gradient #2 */
Packit 0ba690
                    if ((invert_column && invert_gradient2) ||
Packit 0ba690
                        (!invert_column && !invert_gradient2))
Packit 0ba690
                    {
Packit 0ba690
                        *dest++ = r2;       /* not inverted or */
Packit 0ba690
                        *dest++ = g2;       /*  doubly inverted */
Packit 0ba690
                        *dest++ = b2;
Packit 0ba690
                    } else {
Packit 0ba690
                        *dest++ = r2_inv;
Packit 0ba690
                        *dest++ = g2_inv;   /* singly inverted */
Packit 0ba690
                        *dest++ = b2_inv;
Packit 0ba690
                    }
Packit 0ba690
                }
Packit 0ba690
            }
Packit 0ba690
        }
Packit 0ba690
Packit 0ba690
/*---------------------------------------------------------------------------
Packit 0ba690
    Soft gradient-diamonds with scale = bgscale.  Code contributed by Adam
Packit 0ba690
    M. Costello.
Packit 0ba690
  ---------------------------------------------------------------------------*/
Packit 0ba690
Packit 0ba690
    } else if ((bg[pat].type & 0x07) == 1) {
Packit 0ba690
Packit 0ba690
        hmax = (bgscale-1)/2;   /* half the max weight of a color */
Packit 0ba690
        max = 2*hmax;           /* the max weight of a color */
Packit 0ba690
Packit 0ba690
        r1 = rgb[bg[pat].rgb1_max].r;
Packit 0ba690
        g1 = rgb[bg[pat].rgb1_max].g;
Packit 0ba690
        b1 = rgb[bg[pat].rgb1_max].b;
Packit 0ba690
        r2 = rgb[bg[pat].rgb2_max].r;
Packit 0ba690
        g2 = rgb[bg[pat].rgb2_max].g;
Packit 0ba690
        b2 = rgb[bg[pat].rgb2_max].b;
Packit 0ba690
Packit 0ba690
        for (row = 0;  row < rpng2_info.height;  ++row) {
Packit 0ba690
            yidx = (int)(row % bgscale);
Packit 0ba690
            if (yidx > hmax)
Packit 0ba690
                yidx = bgscale-1 - yidx;
Packit 0ba690
            dest = (char *)bg_data + row*bg_rowbytes;
Packit 0ba690
            for (i = 0;  i < rpng2_info.width;  ++i) {
Packit 0ba690
                xidx = (int)(i % bgscale);
Packit 0ba690
                if (xidx > hmax)
Packit 0ba690
                    xidx = bgscale-1 - xidx;
Packit 0ba690
                k = xidx + yidx;
Packit 0ba690
                *dest++ = (k*r1 + (max-k)*r2) / max;
Packit 0ba690
                *dest++ = (k*g1 + (max-k)*g2) / max;
Packit 0ba690
                *dest++ = (k*b1 + (max-k)*b2) / max;
Packit 0ba690
            }
Packit 0ba690
        }
Packit 0ba690
Packit 0ba690
/*---------------------------------------------------------------------------
Packit 0ba690
    Radial "starburst" with azimuthal sinusoids; [eventually number of sinu-
Packit 0ba690
    soids will equal bgscale?].  This one is slow but very cool.  Code con-
Packit 0ba690
    tributed by Pieter S. van der Meulen (originally in Smalltalk).
Packit 0ba690
  ---------------------------------------------------------------------------*/
Packit 0ba690
Packit 0ba690
    } else if ((bg[pat].type & 0x07) == 2) {
Packit 0ba690
        uch ch;
Packit 0ba690
        int ii, x, y, hw, hh, grayspot;
Packit 0ba690
        double freq, rotate, saturate, gray, intensity;
Packit 0ba690
        double angle=0.0, aoffset=0.0, maxDist, dist;
Packit 0ba690
        double red=0.0, green=0.0, blue=0.0, hue, s, v, f, p, q, t;
Packit 0ba690
Packit 0ba690
        fprintf(stderr, "%s:  computing radial background...",
Packit 0ba690
          PROGNAME);
Packit 0ba690
        fflush(stderr);
Packit 0ba690
Packit 0ba690
        hh = (int)(rpng2_info.height / 2);
Packit 0ba690
        hw = (int)(rpng2_info.width / 2);
Packit 0ba690
Packit 0ba690
        /* variables for radial waves:
Packit 0ba690
         *   aoffset:  number of degrees to rotate hue [CURRENTLY NOT USED]
Packit 0ba690
         *   freq:  number of color beams originating from the center
Packit 0ba690
         *   grayspot:  size of the graying center area (anti-alias)
Packit 0ba690
         *   rotate:  rotation of the beams as a function of radius
Packit 0ba690
         *   saturate:  saturation of beams' shape azimuthally
Packit 0ba690
         */
Packit 0ba690
        angle = CLIP(angle, 0.0, 360.0);
Packit 0ba690
        grayspot = CLIP(bg[pat].bg_gray, 1, (hh + hw));
Packit 0ba690
        freq = MAX((double)bg[pat].bg_freq, 0.0);
Packit 0ba690
        saturate = (double)bg[pat].bg_bsat * 0.1;
Packit 0ba690
        rotate = (double)bg[pat].bg_brot * 0.1;
Packit 0ba690
        gray = 0.0;
Packit 0ba690
        intensity = 0.0;
Packit 0ba690
        maxDist = (double)((hw*hw) + (hh*hh));
Packit 0ba690
Packit 0ba690
        for (row = 0;  row < rpng2_info.height;  ++row) {
Packit 0ba690
            y = (int)(row - hh);
Packit 0ba690
            dest = (char *)bg_data + row*bg_rowbytes;
Packit 0ba690
            for (i = 0;  i < rpng2_info.width;  ++i) {
Packit 0ba690
                x = (int)(i - hw);
Packit 0ba690
                angle = (x == 0)? PI_2 : atan((double)y / (double)x);
Packit 0ba690
                gray = (double)MAX(ABS(y), ABS(x)) / grayspot;
Packit 0ba690
                gray = MIN(1.0, gray);
Packit 0ba690
                dist = (double)((x*x) + (y*y)) / maxDist;
Packit 0ba690
                intensity = cos((angle+(rotate*dist*PI)) * freq) *
Packit 0ba690
                  gray * saturate;
Packit 0ba690
                intensity = (MAX(MIN(intensity,1.0),-1.0) + 1.0) * 0.5;
Packit 0ba690
                hue = (angle + PI) * INV_PI_360 + aoffset;
Packit 0ba690
                s = gray * ((double)(ABS(x)+ABS(y)) / (double)(hw + hh));
Packit 0ba690
                s = MIN(MAX(s,0.0), 1.0);
Packit 0ba690
                v = MIN(MAX(intensity,0.0), 1.0);
Packit 0ba690
Packit 0ba690
                if (s == 0.0) {
Packit 0ba690
                    ch = (uch)(v * 255.0);
Packit 0ba690
                    *dest++ = ch;
Packit 0ba690
                    *dest++ = ch;
Packit 0ba690
                    *dest++ = ch;
Packit 0ba690
                } else {
Packit 0ba690
                    if ((hue < 0.0) || (hue >= 360.0))
Packit 0ba690
                        hue -= (((int)(hue / 360.0)) * 360.0);
Packit 0ba690
                    hue /= 60.0;
Packit 0ba690
                    ii = (int)hue;
Packit 0ba690
                    f = hue - (double)ii;
Packit 0ba690
                    p = (1.0 - s) * v;
Packit 0ba690
                    q = (1.0 - (s * f)) * v;
Packit 0ba690
                    t = (1.0 - (s * (1.0 - f))) * v;
Packit 0ba690
                    if      (ii == 0) { red = v; green = t; blue = p; }
Packit 0ba690
                    else if (ii == 1) { red = q; green = v; blue = p; }
Packit 0ba690
                    else if (ii == 2) { red = p; green = v; blue = t; }
Packit 0ba690
                    else if (ii == 3) { red = p; green = q; blue = v; }
Packit 0ba690
                    else if (ii == 4) { red = t; green = p; blue = v; }
Packit 0ba690
                    else if (ii == 5) { red = v; green = p; blue = q; }
Packit 0ba690
                    *dest++ = (uch)(red * 255.0);
Packit 0ba690
                    *dest++ = (uch)(green * 255.0);
Packit 0ba690
                    *dest++ = (uch)(blue * 255.0);
Packit 0ba690
                }
Packit 0ba690
            }
Packit 0ba690
        }
Packit 0ba690
        fprintf(stderr, "done.\n");
Packit 0ba690
        fflush(stderr);
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
/*---------------------------------------------------------------------------
Packit 0ba690
    Blast background image to display buffer before beginning PNG decode.
Packit 0ba690
  ---------------------------------------------------------------------------*/
Packit 0ba690
Packit 0ba690
    if (depth == 24 || depth == 32) {
Packit 0ba690
        ulg red, green, blue;
Packit 0ba690
        int bpp = ximage->bits_per_pixel;
Packit 0ba690
Packit 0ba690
        for (row = 0;  row < rpng2_info.height;  ++row) {
Packit 0ba690
            src = bg_data + row*bg_rowbytes;
Packit 0ba690
            dest = ximage->data + row*ximage_rowbytes;
Packit 0ba690
            if (bpp == 32) {	/* slightly optimized version */
Packit 0ba690
                for (i = rpng2_info.width;  i > 0;  --i) {
Packit 0ba690
                    red   = *src++;
Packit 0ba690
                    green = *src++;
Packit 0ba690
                    blue  = *src++;
Packit 0ba690
                    pixel = (red   << RShift) |
Packit 0ba690
                            (green << GShift) |
Packit 0ba690
                            (blue  << BShift);
Packit 0ba690
                    /* recall that we set ximage->byte_order = MSBFirst above */
Packit 0ba690
                    *dest++ = (char)((pixel >> 24) & 0xff);
Packit 0ba690
                    *dest++ = (char)((pixel >> 16) & 0xff);
Packit 0ba690
                    *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                    *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
                }
Packit 0ba690
            } else {
Packit 0ba690
                for (i = rpng2_info.width;  i > 0;  --i) {
Packit 0ba690
                    red   = *src++;
Packit 0ba690
                    green = *src++;
Packit 0ba690
                    blue  = *src++;
Packit 0ba690
                    pixel = (red   << RShift) |
Packit 0ba690
                            (green << GShift) |
Packit 0ba690
                            (blue  << BShift);
Packit 0ba690
                    /* recall that we set ximage->byte_order = MSBFirst above */
Packit 0ba690
                    /* GRR BUG?  this assumes bpp == 24 & bits are packed low */
Packit 0ba690
                    /*           (probably need to use RShift, RMask, etc.) */
Packit 0ba690
                    *dest++ = (char)((pixel >> 16) & 0xff);
Packit 0ba690
                    *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                    *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
                }
Packit 0ba690
            }
Packit 0ba690
        }
Packit 0ba690
Packit 0ba690
    } else if (depth == 16) {
Packit 0ba690
        ush red, green, blue;
Packit 0ba690
Packit 0ba690
        for (row = 0;  row < rpng2_info.height;  ++row) {
Packit 0ba690
            src = bg_data + row*bg_rowbytes;
Packit 0ba690
            dest = ximage->data + row*ximage_rowbytes;
Packit 0ba690
            for (i = rpng2_info.width;  i > 0;  --i) {
Packit 0ba690
                red   = ((ush)(*src) << 8);  ++src;
Packit 0ba690
                green = ((ush)(*src) << 8);  ++src;
Packit 0ba690
                blue  = ((ush)(*src) << 8);  ++src;
Packit 0ba690
                pixel = ((red   >> RShift) & RMask) |
Packit 0ba690
                        ((green >> GShift) & GMask) |
Packit 0ba690
                        ((blue  >> BShift) & BMask);
Packit 0ba690
                /* recall that we set ximage->byte_order = MSBFirst above */
Packit 0ba690
                *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
            }
Packit 0ba690
        }
Packit 0ba690
Packit 0ba690
    } else /* depth == 8 */ {
Packit 0ba690
Packit 0ba690
        /* GRR:  add 8-bit support */
Packit 0ba690
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    XPutImage(display, window, gc, ximage, 0, 0, 0, 0, rpng2_info.width,
Packit 0ba690
      rpng2_info.height);
Packit 0ba690
Packit 0ba690
    return 0;
Packit 0ba690
Packit 0ba690
} /* end function rpng2_x_load_bg_image() */
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
static void rpng2_x_display_row(ulg row)
Packit 0ba690
{
Packit 0ba690
    uch bg_red   = rpng2_info.bg_red;
Packit 0ba690
    uch bg_green = rpng2_info.bg_green;
Packit 0ba690
    uch bg_blue  = rpng2_info.bg_blue;
Packit 0ba690
    uch *src, *src2=NULL;
Packit 0ba690
    char *dest;
Packit 0ba690
    uch r, g, b, a;
Packit 0ba690
    int ximage_rowbytes = ximage->bytes_per_line;
Packit 0ba690
    ulg i, pixel;
Packit 0ba690
    static int rows=0, prevpass=(-1);
Packit 0ba690
    static ulg firstrow;
Packit 0ba690
Packit 0ba690
/*---------------------------------------------------------------------------
Packit 0ba690
    rows and firstrow simply track how many rows (and which ones) have not
Packit 0ba690
    yet been displayed; alternatively, we could call XPutImage() for every
Packit 0ba690
    row and not bother with the records-keeping.
Packit 0ba690
  ---------------------------------------------------------------------------*/
Packit 0ba690
Packit 0ba690
    Trace((stderr, "beginning rpng2_x_display_row()\n"))
Packit 0ba690
Packit 0ba690
    if (rpng2_info.pass != prevpass) {
Packit 0ba690
        if (pause_after_pass && rpng2_info.pass > 0) {
Packit 0ba690
            XEvent e;
Packit 0ba690
            KeySym k;
Packit 0ba690
Packit 0ba690
            fprintf(stderr,
Packit 0ba690
              "%s:  end of pass %d of 7; click in image window to continue\n",
Packit 0ba690
              PROGNAME, prevpass + 1);
Packit 0ba690
            do
Packit 0ba690
                XNextEvent(display, &e);
Packit 0ba690
            while (!QUIT(e,k));
Packit 0ba690
        }
Packit 0ba690
        fprintf(stderr, "%s:  pass %d of 7\r", PROGNAME, rpng2_info.pass + 1);
Packit 0ba690
        fflush(stderr);
Packit 0ba690
        prevpass = rpng2_info.pass;
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    if (rows == 0)
Packit 0ba690
        firstrow = row;   /* first row that is not yet displayed */
Packit 0ba690
Packit 0ba690
    ++rows;   /* count of rows received but not yet displayed */
Packit 0ba690
Packit 0ba690
/*---------------------------------------------------------------------------
Packit 0ba690
    Aside from the use of the rpng2_info struct, the lack of an outer loop
Packit 0ba690
    (over rows) and moving the XPutImage() call outside the "if (depth)"
Packit 0ba690
    tests, this routine is identical to rpng_x_display_image() in the non-
Packit 0ba690
    progressive version of the program.
Packit 0ba690
  ---------------------------------------------------------------------------*/
Packit 0ba690
Packit 0ba690
    if (depth == 24 || depth == 32) {
Packit 0ba690
        ulg red, green, blue;
Packit 0ba690
        int bpp = ximage->bits_per_pixel;
Packit 0ba690
Packit 0ba690
        src = rpng2_info.image_data + row*rpng2_info.rowbytes;
Packit 0ba690
        if (bg_image)
Packit 0ba690
            src2 = bg_data + row*bg_rowbytes;
Packit 0ba690
        dest = ximage->data + row*ximage_rowbytes;
Packit 0ba690
        if (rpng2_info.channels == 3) {
Packit 0ba690
            for (i = rpng2_info.width;  i > 0;  --i) {
Packit 0ba690
                red   = *src++;
Packit 0ba690
                green = *src++;
Packit 0ba690
                blue  = *src++;
Packit 0ba690
                pixel = (red   << RShift) |
Packit 0ba690
                        (green << GShift) |
Packit 0ba690
                        (blue  << BShift);
Packit 0ba690
                /* recall that we set ximage->byte_order = MSBFirst above */
Packit 0ba690
                if (bpp == 32) {
Packit 0ba690
                    *dest++ = (char)((pixel >> 24) & 0xff);
Packit 0ba690
                    *dest++ = (char)((pixel >> 16) & 0xff);
Packit 0ba690
                    *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                    *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
                } else {
Packit 0ba690
                    /* GRR BUG?  this assumes bpp == 24 & bits are packed low */
Packit 0ba690
                    /*           (probably need to use RShift, RMask, etc.) */
Packit 0ba690
                    *dest++ = (char)((pixel >> 16) & 0xff);
Packit 0ba690
                    *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                    *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
                }
Packit 0ba690
            }
Packit 0ba690
        } else /* if (rpng2_info.channels == 4) */ {
Packit 0ba690
            for (i = rpng2_info.width;  i > 0;  --i) {
Packit 0ba690
                r = *src++;
Packit 0ba690
                g = *src++;
Packit 0ba690
                b = *src++;
Packit 0ba690
                a = *src++;
Packit 0ba690
                if (bg_image) {
Packit 0ba690
                    bg_red   = *src2++;
Packit 0ba690
                    bg_green = *src2++;
Packit 0ba690
                    bg_blue  = *src2++;
Packit 0ba690
                }
Packit 0ba690
                if (a == 255) {
Packit 0ba690
                    red   = r;
Packit 0ba690
                    green = g;
Packit 0ba690
                    blue  = b;
Packit 0ba690
                } else if (a == 0) {
Packit 0ba690
                    red   = bg_red;
Packit 0ba690
                    green = bg_green;
Packit 0ba690
                    blue  = bg_blue;
Packit 0ba690
                } else {
Packit 0ba690
                    /* this macro (from png.h) composites the foreground
Packit 0ba690
                     * and background values and puts the result into the
Packit 0ba690
                     * first argument */
Packit 0ba690
                    alpha_composite(red,   r, a, bg_red);
Packit 0ba690
                    alpha_composite(green, g, a, bg_green);
Packit 0ba690
                    alpha_composite(blue,  b, a, bg_blue);
Packit 0ba690
                }
Packit 0ba690
                pixel = (red   << RShift) |
Packit 0ba690
                        (green << GShift) |
Packit 0ba690
                        (blue  << BShift);
Packit 0ba690
                /* recall that we set ximage->byte_order = MSBFirst above */
Packit 0ba690
                if (bpp == 32) {
Packit 0ba690
                    *dest++ = (char)((pixel >> 24) & 0xff);
Packit 0ba690
                    *dest++ = (char)((pixel >> 16) & 0xff);
Packit 0ba690
                    *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                    *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
                } else {
Packit 0ba690
                    /* GRR BUG?  this assumes bpp == 24 & bits are packed low */
Packit 0ba690
                    /*           (probably need to use RShift, RMask, etc.) */
Packit 0ba690
                    *dest++ = (char)((pixel >> 16) & 0xff);
Packit 0ba690
                    *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                    *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
                }
Packit 0ba690
            }
Packit 0ba690
        }
Packit 0ba690
Packit 0ba690
    } else if (depth == 16) {
Packit 0ba690
        ush red, green, blue;
Packit 0ba690
Packit 0ba690
        src = rpng2_info.row_pointers[row];
Packit 0ba690
        if (bg_image)
Packit 0ba690
            src2 = bg_data + row*bg_rowbytes;
Packit 0ba690
        dest = ximage->data + row*ximage_rowbytes;
Packit 0ba690
        if (rpng2_info.channels == 3) {
Packit 0ba690
            for (i = rpng2_info.width;  i > 0;  --i) {
Packit 0ba690
                red   = ((ush)(*src) << 8);
Packit 0ba690
                ++src;
Packit 0ba690
                green = ((ush)(*src) << 8);
Packit 0ba690
                ++src;
Packit 0ba690
                blue  = ((ush)(*src) << 8);
Packit 0ba690
                ++src;
Packit 0ba690
                pixel = ((red   >> RShift) & RMask) |
Packit 0ba690
                        ((green >> GShift) & GMask) |
Packit 0ba690
                        ((blue  >> BShift) & BMask);
Packit 0ba690
                /* recall that we set ximage->byte_order = MSBFirst above */
Packit 0ba690
                *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
            }
Packit 0ba690
        } else /* if (rpng2_info.channels == 4) */ {
Packit 0ba690
            for (i = rpng2_info.width;  i > 0;  --i) {
Packit 0ba690
                r = *src++;
Packit 0ba690
                g = *src++;
Packit 0ba690
                b = *src++;
Packit 0ba690
                a = *src++;
Packit 0ba690
                if (bg_image) {
Packit 0ba690
                    bg_red   = *src2++;
Packit 0ba690
                    bg_green = *src2++;
Packit 0ba690
                    bg_blue  = *src2++;
Packit 0ba690
                }
Packit 0ba690
                if (a == 255) {
Packit 0ba690
                    red   = ((ush)r << 8);
Packit 0ba690
                    green = ((ush)g << 8);
Packit 0ba690
                    blue  = ((ush)b << 8);
Packit 0ba690
                } else if (a == 0) {
Packit 0ba690
                    red   = ((ush)bg_red   << 8);
Packit 0ba690
                    green = ((ush)bg_green << 8);
Packit 0ba690
                    blue  = ((ush)bg_blue  << 8);
Packit 0ba690
                } else {
Packit 0ba690
                    /* this macro (from png.h) composites the foreground
Packit 0ba690
                     * and background values and puts the result back into
Packit 0ba690
                     * the first argument (== fg byte here:  safe) */
Packit 0ba690
                    alpha_composite(r, r, a, bg_red);
Packit 0ba690
                    alpha_composite(g, g, a, bg_green);
Packit 0ba690
                    alpha_composite(b, b, a, bg_blue);
Packit 0ba690
                    red   = ((ush)r << 8);
Packit 0ba690
                    green = ((ush)g << 8);
Packit 0ba690
                    blue  = ((ush)b << 8);
Packit 0ba690
                }
Packit 0ba690
                pixel = ((red   >> RShift) & RMask) |
Packit 0ba690
                        ((green >> GShift) & GMask) |
Packit 0ba690
                        ((blue  >> BShift) & BMask);
Packit 0ba690
                /* recall that we set ximage->byte_order = MSBFirst above */
Packit 0ba690
                *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
            }
Packit 0ba690
        }
Packit 0ba690
Packit 0ba690
    } else /* depth == 8 */ {
Packit 0ba690
Packit 0ba690
        /* GRR:  add 8-bit support */
Packit 0ba690
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
Packit 0ba690
/*---------------------------------------------------------------------------
Packit 0ba690
    Display after every 16 rows or when on one of last two rows.  (Region
Packit 0ba690
    may include previously displayed lines due to interlacing--i.e., not
Packit 0ba690
    contiguous.  Also, second-to-last row is final one in interlaced images
Packit 0ba690
    with odd number of rows.)  For demos, flush (and delay) after every 16th
Packit 0ba690
    row so "sparse" passes don't go twice as fast.
Packit 0ba690
  ---------------------------------------------------------------------------*/
Packit 0ba690
Packit 0ba690
    if (demo_timing && (row - firstrow >= 16 || row >= rpng2_info.height-2)) {
Packit 0ba690
        XPutImage(display, window, gc, ximage, 0, (int)firstrow, 0,
Packit 0ba690
          (int)firstrow, rpng2_info.width, row - firstrow + 1);
Packit 0ba690
        XFlush(display);
Packit 0ba690
        rows = 0;
Packit 0ba690
        usleep(usleep_duration);
Packit 0ba690
    } else
Packit 0ba690
    if (!demo_timing && ((rows & 0xf) == 0 || row >= rpng2_info.height-2)) {
Packit 0ba690
        XPutImage(display, window, gc, ximage, 0, (int)firstrow, 0,
Packit 0ba690
          (int)firstrow, rpng2_info.width, row - firstrow + 1);
Packit 0ba690
        XFlush(display);
Packit 0ba690
        rows = 0;
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
static void rpng2_x_finish_display(void)
Packit 0ba690
{
Packit 0ba690
    Trace((stderr, "beginning rpng2_x_finish_display()\n"))
Packit 0ba690
Packit 0ba690
    /* last row has already been displayed by rpng2_x_display_row(), so we
Packit 0ba690
     * have nothing to do here except set a flag and let the user know that
Packit 0ba690
     * the image is done */
Packit 0ba690
Packit 0ba690
    rpng2_info.state = kDone;
Packit 0ba690
    printf(
Packit 0ba690
      "Done.  Press Q, Esc or mouse button 1 (within image window) to quit.\n");
Packit 0ba690
    fflush(stdout);
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
static void rpng2_x_redisplay_image(ulg startcol, ulg startrow,
Packit 0ba690
                                    ulg width, ulg height)
Packit 0ba690
{
Packit 0ba690
    uch bg_red   = rpng2_info.bg_red;
Packit 0ba690
    uch bg_green = rpng2_info.bg_green;
Packit 0ba690
    uch bg_blue  = rpng2_info.bg_blue;
Packit 0ba690
    uch *src, *src2=NULL;
Packit 0ba690
    char *dest;
Packit 0ba690
    uch r, g, b, a;
Packit 0ba690
    ulg i, row, lastrow = 0;
Packit 0ba690
    ulg pixel;
Packit 0ba690
    int ximage_rowbytes = ximage->bytes_per_line;
Packit 0ba690
Packit 0ba690
Packit 0ba690
    Trace((stderr, "beginning display loop (image_channels == %d)\n",
Packit 0ba690
      rpng2_info.channels))
Packit 0ba690
    Trace((stderr, "   (width = %ld, rowbytes = %d, ximage_rowbytes = %d)\n",
Packit 0ba690
      rpng2_info.width, rpng2_info.rowbytes, ximage_rowbytes))
Packit 0ba690
    Trace((stderr, "   (bpp = %d)\n", ximage->bits_per_pixel))
Packit 0ba690
    Trace((stderr, "   (byte_order = %s)\n", ximage->byte_order == MSBFirst?
Packit 0ba690
      "MSBFirst" : (ximage->byte_order == LSBFirst? "LSBFirst" : "unknown")))
Packit 0ba690
Packit 0ba690
/*---------------------------------------------------------------------------
Packit 0ba690
    Aside from the use of the rpng2_info struct and of src2 (for background
Packit 0ba690
    image), this routine is identical to rpng_x_display_image() in the non-
Packit 0ba690
    progressive version of the program--for the simple reason that redisplay
Packit 0ba690
    of the image against a new background happens after the image is fully
Packit 0ba690
    decoded and therefore is, by definition, non-progressive.
Packit 0ba690
  ---------------------------------------------------------------------------*/
Packit 0ba690
Packit 0ba690
    if (depth == 24 || depth == 32) {
Packit 0ba690
        ulg red, green, blue;
Packit 0ba690
        int bpp = ximage->bits_per_pixel;
Packit 0ba690
Packit 0ba690
        for (lastrow = row = startrow;  row < startrow+height;  ++row) {
Packit 0ba690
            src = rpng2_info.image_data + row*rpng2_info.rowbytes;
Packit 0ba690
            if (bg_image)
Packit 0ba690
                src2 = bg_data + row*bg_rowbytes;
Packit 0ba690
            dest = ximage->data + row*ximage_rowbytes;
Packit 0ba690
            if (rpng2_info.channels == 3) {
Packit 0ba690
                for (i = rpng2_info.width;  i > 0;  --i) {
Packit 0ba690
                    red   = *src++;
Packit 0ba690
                    green = *src++;
Packit 0ba690
                    blue  = *src++;
Packit 0ba690
#ifdef NO_24BIT_MASKS
Packit 0ba690
                    pixel = (red   << RShift) |
Packit 0ba690
                            (green << GShift) |
Packit 0ba690
                            (blue  << BShift);
Packit 0ba690
                    /* recall that we set ximage->byte_order = MSBFirst above */
Packit 0ba690
                    if (bpp == 32) {
Packit 0ba690
                        *dest++ = (char)((pixel >> 24) & 0xff);
Packit 0ba690
                        *dest++ = (char)((pixel >> 16) & 0xff);
Packit 0ba690
                        *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                        *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
                    } else {
Packit 0ba690
                        /* this assumes bpp == 24 & bits are packed low */
Packit 0ba690
                        /* (probably need to use RShift, RMask, etc.) */
Packit 0ba690
                        *dest++ = (char)((pixel >> 16) & 0xff);
Packit 0ba690
                        *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                        *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
                    }
Packit 0ba690
#else
Packit 0ba690
                    red   = (RShift < 0)? red   << (-RShift) : red   >> RShift;
Packit 0ba690
                    green = (GShift < 0)? green << (-GShift) : green >> GShift;
Packit 0ba690
                    blue  = (BShift < 0)? blue  << (-BShift) : blue  >> BShift;
Packit 0ba690
                    pixel = (red & RMask) | (green & GMask) | (blue & BMask);
Packit 0ba690
                    /* recall that we set ximage->byte_order = MSBFirst above */
Packit 0ba690
                    if (bpp == 32) {
Packit 0ba690
                        *dest++ = (char)((pixel >> 24) & 0xff);
Packit 0ba690
                        *dest++ = (char)((pixel >> 16) & 0xff);
Packit 0ba690
                        *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                        *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
                    } else {
Packit 0ba690
                        /* GRR BUG */
Packit 0ba690
                        /* this assumes bpp == 24 & bits are packed low */
Packit 0ba690
                        /* (probably need to use RShift/RMask/etc. here, too) */
Packit 0ba690
                        *dest++ = (char)((pixel >> 16) & 0xff);
Packit 0ba690
                        *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                        *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
                    }
Packit 0ba690
#endif
Packit 0ba690
                }
Packit 0ba690
Packit 0ba690
            } else /* if (rpng2_info.channels == 4) */ {
Packit 0ba690
                for (i = rpng2_info.width;  i > 0;  --i) {
Packit 0ba690
                    r = *src++;
Packit 0ba690
                    g = *src++;
Packit 0ba690
                    b = *src++;
Packit 0ba690
                    a = *src++;
Packit 0ba690
                    if (bg_image) {
Packit 0ba690
                        bg_red   = *src2++;
Packit 0ba690
                        bg_green = *src2++;
Packit 0ba690
                        bg_blue  = *src2++;
Packit 0ba690
                    }
Packit 0ba690
                    if (a == 255) {
Packit 0ba690
                        red   = r;
Packit 0ba690
                        green = g;
Packit 0ba690
                        blue  = b;
Packit 0ba690
                    } else if (a == 0) {
Packit 0ba690
                        red   = bg_red;
Packit 0ba690
                        green = bg_green;
Packit 0ba690
                        blue  = bg_blue;
Packit 0ba690
                    } else {
Packit 0ba690
                        /* this macro (from png.h) composites the foreground
Packit 0ba690
                         * and background values and puts the result into the
Packit 0ba690
                         * first argument */
Packit 0ba690
                        alpha_composite(red,   r, a, bg_red);
Packit 0ba690
                        alpha_composite(green, g, a, bg_green);
Packit 0ba690
                        alpha_composite(blue,  b, a, bg_blue);
Packit 0ba690
                    }
Packit 0ba690
#ifdef NO_24BIT_MASKS
Packit 0ba690
                    pixel = (red   << RShift) |
Packit 0ba690
                            (green << GShift) |
Packit 0ba690
                            (blue  << BShift);
Packit 0ba690
                    /* recall that we set ximage->byte_order = MSBFirst above */
Packit 0ba690
                    if (bpp == 32) {
Packit 0ba690
                        *dest++ = (char)((pixel >> 24) & 0xff);
Packit 0ba690
                        *dest++ = (char)((pixel >> 16) & 0xff);
Packit 0ba690
                        *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                        *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
                    } else {
Packit 0ba690
                        /* this assumes bpp == 24 & bits are packed low */
Packit 0ba690
                        /* (probably need to use RShift, RMask, etc.) */
Packit 0ba690
                        *dest++ = (char)((pixel >> 16) & 0xff);
Packit 0ba690
                        *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                        *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
                    }
Packit 0ba690
#else
Packit 0ba690
                    red   = (RShift < 0)? red   << (-RShift) : red   >> RShift;
Packit 0ba690
                    green = (GShift < 0)? green << (-GShift) : green >> GShift;
Packit 0ba690
                    blue  = (BShift < 0)? blue  << (-BShift) : blue  >> BShift;
Packit 0ba690
                    pixel = (red & RMask) | (green & GMask) | (blue & BMask);
Packit 0ba690
                    /* recall that we set ximage->byte_order = MSBFirst above */
Packit 0ba690
                    if (bpp == 32) {
Packit 0ba690
                        *dest++ = (char)((pixel >> 24) & 0xff);
Packit 0ba690
                        *dest++ = (char)((pixel >> 16) & 0xff);
Packit 0ba690
                        *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                        *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
                    } else {
Packit 0ba690
                        /* GRR BUG */
Packit 0ba690
                        /* this assumes bpp == 24 & bits are packed low */
Packit 0ba690
                        /* (probably need to use RShift/RMask/etc. here, too) */
Packit 0ba690
                        *dest++ = (char)((pixel >> 16) & 0xff);
Packit 0ba690
                        *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                        *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
                    }
Packit 0ba690
#endif
Packit 0ba690
                }
Packit 0ba690
            }
Packit 0ba690
            /* display after every 16 lines */
Packit 0ba690
            if (((row+1) & 0xf) == 0) {
Packit 0ba690
                XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
Packit 0ba690
                  (int)lastrow, rpng2_info.width, 16);
Packit 0ba690
                XFlush(display);
Packit 0ba690
                lastrow = row + 1;
Packit 0ba690
            }
Packit 0ba690
        }
Packit 0ba690
Packit 0ba690
    } else if (depth == 16) {
Packit 0ba690
        ush red, green, blue;
Packit 0ba690
Packit 0ba690
        for (lastrow = row = startrow;  row < startrow+height;  ++row) {
Packit 0ba690
            src = rpng2_info.row_pointers[row];
Packit 0ba690
            if (bg_image)
Packit 0ba690
                src2 = bg_data + row*bg_rowbytes;
Packit 0ba690
            dest = ximage->data + row*ximage_rowbytes;
Packit 0ba690
            if (rpng2_info.channels == 3) {
Packit 0ba690
                for (i = rpng2_info.width;  i > 0;  --i) {
Packit 0ba690
                    red   = ((ush)(*src) << 8);
Packit 0ba690
                    ++src;
Packit 0ba690
                    green = ((ush)(*src) << 8);
Packit 0ba690
                    ++src;
Packit 0ba690
                    blue  = ((ush)(*src) << 8);
Packit 0ba690
                    ++src;
Packit 0ba690
                    pixel = ((red   >> RShift) & RMask) |
Packit 0ba690
                            ((green >> GShift) & GMask) |
Packit 0ba690
                            ((blue  >> BShift) & BMask);
Packit 0ba690
                    /* recall that we set ximage->byte_order = MSBFirst above */
Packit 0ba690
                    *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                    *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
                }
Packit 0ba690
            } else /* if (rpng2_info.channels == 4) */ {
Packit 0ba690
                for (i = rpng2_info.width;  i > 0;  --i) {
Packit 0ba690
                    r = *src++;
Packit 0ba690
                    g = *src++;
Packit 0ba690
                    b = *src++;
Packit 0ba690
                    a = *src++;
Packit 0ba690
                    if (bg_image) {
Packit 0ba690
                        bg_red   = *src2++;
Packit 0ba690
                        bg_green = *src2++;
Packit 0ba690
                        bg_blue  = *src2++;
Packit 0ba690
                    }
Packit 0ba690
                    if (a == 255) {
Packit 0ba690
                        red   = ((ush)r << 8);
Packit 0ba690
                        green = ((ush)g << 8);
Packit 0ba690
                        blue  = ((ush)b << 8);
Packit 0ba690
                    } else if (a == 0) {
Packit 0ba690
                        red   = ((ush)bg_red   << 8);
Packit 0ba690
                        green = ((ush)bg_green << 8);
Packit 0ba690
                        blue  = ((ush)bg_blue  << 8);
Packit 0ba690
                    } else {
Packit 0ba690
                        /* this macro (from png.h) composites the foreground
Packit 0ba690
                         * and background values and puts the result back into
Packit 0ba690
                         * the first argument (== fg byte here:  safe) */
Packit 0ba690
                        alpha_composite(r, r, a, bg_red);
Packit 0ba690
                        alpha_composite(g, g, a, bg_green);
Packit 0ba690
                        alpha_composite(b, b, a, bg_blue);
Packit 0ba690
                        red   = ((ush)r << 8);
Packit 0ba690
                        green = ((ush)g << 8);
Packit 0ba690
                        blue  = ((ush)b << 8);
Packit 0ba690
                    }
Packit 0ba690
                    pixel = ((red   >> RShift) & RMask) |
Packit 0ba690
                            ((green >> GShift) & GMask) |
Packit 0ba690
                            ((blue  >> BShift) & BMask);
Packit 0ba690
                    /* recall that we set ximage->byte_order = MSBFirst above */
Packit 0ba690
                    *dest++ = (char)((pixel >>  8) & 0xff);
Packit 0ba690
                    *dest++ = (char)( pixel        & 0xff);
Packit 0ba690
                }
Packit 0ba690
            }
Packit 0ba690
            /* display after every 16 lines */
Packit 0ba690
            if (((row+1) & 0xf) == 0) {
Packit 0ba690
                XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
Packit 0ba690
                  (int)lastrow, rpng2_info.width, 16);
Packit 0ba690
                XFlush(display);
Packit 0ba690
                lastrow = row + 1;
Packit 0ba690
            }
Packit 0ba690
        }
Packit 0ba690
Packit 0ba690
    } else /* depth == 8 */ {
Packit 0ba690
Packit 0ba690
        /* GRR:  add 8-bit support */
Packit 0ba690
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    Trace((stderr, "calling final XPutImage()\n"))
Packit 0ba690
    if (lastrow < startrow+height) {
Packit 0ba690
        XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
Packit 0ba690
          (int)lastrow, rpng2_info.width, rpng2_info.height-lastrow);
Packit 0ba690
        XFlush(display);
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
} /* end function rpng2_x_redisplay_image() */
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
#ifdef FEATURE_LOOP
Packit 0ba690
Packit 0ba690
static void rpng2_x_reload_bg_image(void)
Packit 0ba690
{
Packit 0ba690
    char *dest;
Packit 0ba690
    uch r1, r2, g1, g2, b1, b2;
Packit 0ba690
    uch r1_inv, r2_inv, g1_inv, g2_inv, b1_inv, b2_inv;
Packit 0ba690
    int k, hmax, max;
Packit 0ba690
    int xidx, yidx, yidx_max;
Packit 0ba690
    int even_odd_vert, even_odd_horiz, even_odd;
Packit 0ba690
    int invert_gradient2 = (bg[pat].type & 0x08);
Packit 0ba690
    int invert_column;
Packit 0ba690
    ulg i, row;
Packit 0ba690
Packit 0ba690
Packit 0ba690
    bgscale = (pat == 0)? 8 : bgscale_default;
Packit 0ba690
    yidx_max = bgscale - 1;
Packit 0ba690
Packit 0ba690
/*---------------------------------------------------------------------------
Packit 0ba690
    Vertical gradients (ramps) in NxN squares, alternating direction and
Packit 0ba690
    colors (N == bgscale).
Packit 0ba690
  ---------------------------------------------------------------------------*/
Packit 0ba690
Packit 0ba690
    if ((bg[pat].type & 0x07) == 0) {
Packit 0ba690
        uch r1_min  = rgb[bg[pat].rgb1_min].r;
Packit 0ba690
        uch g1_min  = rgb[bg[pat].rgb1_min].g;
Packit 0ba690
        uch b1_min  = rgb[bg[pat].rgb1_min].b;
Packit 0ba690
        uch r2_min  = rgb[bg[pat].rgb2_min].r;
Packit 0ba690
        uch g2_min  = rgb[bg[pat].rgb2_min].g;
Packit 0ba690
        uch b2_min  = rgb[bg[pat].rgb2_min].b;
Packit 0ba690
        int r1_diff = rgb[bg[pat].rgb1_max].r - r1_min;
Packit 0ba690
        int g1_diff = rgb[bg[pat].rgb1_max].g - g1_min;
Packit 0ba690
        int b1_diff = rgb[bg[pat].rgb1_max].b - b1_min;
Packit 0ba690
        int r2_diff = rgb[bg[pat].rgb2_max].r - r2_min;
Packit 0ba690
        int g2_diff = rgb[bg[pat].rgb2_max].g - g2_min;
Packit 0ba690
        int b2_diff = rgb[bg[pat].rgb2_max].b - b2_min;
Packit 0ba690
Packit 0ba690
        for (row = 0;  row < rpng2_info.height;  ++row) {
Packit 0ba690
            yidx = (int)(row % bgscale);
Packit 0ba690
            even_odd_vert = (int)((row / bgscale) & 1);
Packit 0ba690
Packit 0ba690
            r1 = r1_min + (r1_diff * yidx) / yidx_max;
Packit 0ba690
            g1 = g1_min + (g1_diff * yidx) / yidx_max;
Packit 0ba690
            b1 = b1_min + (b1_diff * yidx) / yidx_max;
Packit 0ba690
            r1_inv = r1_min + (r1_diff * (yidx_max-yidx)) / yidx_max;
Packit 0ba690
            g1_inv = g1_min + (g1_diff * (yidx_max-yidx)) / yidx_max;
Packit 0ba690
            b1_inv = b1_min + (b1_diff * (yidx_max-yidx)) / yidx_max;
Packit 0ba690
Packit 0ba690
            r2 = r2_min + (r2_diff * yidx) / yidx_max;
Packit 0ba690
            g2 = g2_min + (g2_diff * yidx) / yidx_max;
Packit 0ba690
            b2 = b2_min + (b2_diff * yidx) / yidx_max;
Packit 0ba690
            r2_inv = r2_min + (r2_diff * (yidx_max-yidx)) / yidx_max;
Packit 0ba690
            g2_inv = g2_min + (g2_diff * (yidx_max-yidx)) / yidx_max;
Packit 0ba690
            b2_inv = b2_min + (b2_diff * (yidx_max-yidx)) / yidx_max;
Packit 0ba690
Packit 0ba690
            dest = (char *)bg_data + row*bg_rowbytes;
Packit 0ba690
            for (i = 0;  i < rpng2_info.width;  ++i) {
Packit 0ba690
                even_odd_horiz = (int)((i / bgscale) & 1);
Packit 0ba690
                even_odd = even_odd_vert ^ even_odd_horiz;
Packit 0ba690
                invert_column =
Packit 0ba690
                  (even_odd_horiz && (bg[pat].type & 0x10));
Packit 0ba690
                if (even_odd == 0) {        /* gradient #1 */
Packit 0ba690
                    if (invert_column) {
Packit 0ba690
                        *dest++ = r1_inv;
Packit 0ba690
                        *dest++ = g1_inv;
Packit 0ba690
                        *dest++ = b1_inv;
Packit 0ba690
                    } else {
Packit 0ba690
                        *dest++ = r1;
Packit 0ba690
                        *dest++ = g1;
Packit 0ba690
                        *dest++ = b1;
Packit 0ba690
                    }
Packit 0ba690
                } else {                    /* gradient #2 */
Packit 0ba690
                    if ((invert_column && invert_gradient2) ||
Packit 0ba690
                        (!invert_column && !invert_gradient2))
Packit 0ba690
                    {
Packit 0ba690
                        *dest++ = r2;       /* not inverted or */
Packit 0ba690
                        *dest++ = g2;       /*  doubly inverted */
Packit 0ba690
                        *dest++ = b2;
Packit 0ba690
                    } else {
Packit 0ba690
                        *dest++ = r2_inv;
Packit 0ba690
                        *dest++ = g2_inv;   /* singly inverted */
Packit 0ba690
                        *dest++ = b2_inv;
Packit 0ba690
                    }
Packit 0ba690
                }
Packit 0ba690
            }
Packit 0ba690
        }
Packit 0ba690
Packit 0ba690
/*---------------------------------------------------------------------------
Packit 0ba690
    Soft gradient-diamonds with scale = bgscale.  Code contributed by Adam
Packit 0ba690
    M. Costello.
Packit 0ba690
  ---------------------------------------------------------------------------*/
Packit 0ba690
Packit 0ba690
    } else if ((bg[pat].type & 0x07) == 1) {
Packit 0ba690
Packit 0ba690
        hmax = (bgscale-1)/2;   /* half the max weight of a color */
Packit 0ba690
        max = 2*hmax;           /* the max weight of a color */
Packit 0ba690
Packit 0ba690
        r1 = rgb[bg[pat].rgb1_max].r;
Packit 0ba690
        g1 = rgb[bg[pat].rgb1_max].g;
Packit 0ba690
        b1 = rgb[bg[pat].rgb1_max].b;
Packit 0ba690
        r2 = rgb[bg[pat].rgb2_max].r;
Packit 0ba690
        g2 = rgb[bg[pat].rgb2_max].g;
Packit 0ba690
        b2 = rgb[bg[pat].rgb2_max].b;
Packit 0ba690
Packit 0ba690
        for (row = 0;  row < rpng2_info.height;  ++row) {
Packit 0ba690
            yidx = (int)(row % bgscale);
Packit 0ba690
            if (yidx > hmax)
Packit 0ba690
                yidx = bgscale-1 - yidx;
Packit 0ba690
            dest = (char *)bg_data + row*bg_rowbytes;
Packit 0ba690
            for (i = 0;  i < rpng2_info.width;  ++i) {
Packit 0ba690
                xidx = (int)(i % bgscale);
Packit 0ba690
                if (xidx > hmax)
Packit 0ba690
                    xidx = bgscale-1 - xidx;
Packit 0ba690
                k = xidx + yidx;
Packit 0ba690
                *dest++ = (k*r1 + (max-k)*r2) / max;
Packit 0ba690
                *dest++ = (k*g1 + (max-k)*g2) / max;
Packit 0ba690
                *dest++ = (k*b1 + (max-k)*b2) / max;
Packit 0ba690
            }
Packit 0ba690
        }
Packit 0ba690
Packit 0ba690
/*---------------------------------------------------------------------------
Packit 0ba690
    Radial "starburst" with azimuthal sinusoids; [eventually number of sinu-
Packit 0ba690
    soids will equal bgscale?].  This one is slow but very cool.  Code con-
Packit 0ba690
    tributed by Pieter S. van der Meulen (originally in Smalltalk).
Packit 0ba690
  ---------------------------------------------------------------------------*/
Packit 0ba690
Packit 0ba690
    } else if ((bg[pat].type & 0x07) == 2) {
Packit 0ba690
        uch ch;
Packit 0ba690
        int ii, x, y, hw, hh, grayspot;
Packit 0ba690
        double freq, rotate, saturate, gray, intensity;
Packit 0ba690
        double angle=0.0, aoffset=0.0, maxDist, dist;
Packit 0ba690
        double red=0.0, green=0.0, blue=0.0, hue, s, v, f, p, q, t;
Packit 0ba690
Packit 0ba690
        hh = (int)(rpng2_info.height / 2);
Packit 0ba690
        hw = (int)(rpng2_info.width / 2);
Packit 0ba690
Packit 0ba690
        /* variables for radial waves:
Packit 0ba690
         *   aoffset:  number of degrees to rotate hue [CURRENTLY NOT USED]
Packit 0ba690
         *   freq:  number of color beams originating from the center
Packit 0ba690
         *   grayspot:  size of the graying center area (anti-alias)
Packit 0ba690
         *   rotate:  rotation of the beams as a function of radius
Packit 0ba690
         *   saturate:  saturation of beams' shape azimuthally
Packit 0ba690
         */
Packit 0ba690
        angle = CLIP(angle, 0.0, 360.0);
Packit 0ba690
        grayspot = CLIP(bg[pat].bg_gray, 1, (hh + hw));
Packit 0ba690
        freq = MAX((double)bg[pat].bg_freq, 0.0);
Packit 0ba690
        saturate = (double)bg[pat].bg_bsat * 0.1;
Packit 0ba690
        rotate = (double)bg[pat].bg_brot * 0.1;
Packit 0ba690
        gray = 0.0;
Packit 0ba690
        intensity = 0.0;
Packit 0ba690
        maxDist = (double)((hw*hw) + (hh*hh));
Packit 0ba690
Packit 0ba690
        for (row = 0;  row < rpng2_info.height;  ++row) {
Packit 0ba690
            y = (int)(row - hh);
Packit 0ba690
            dest = (char *)bg_data + row*bg_rowbytes;
Packit 0ba690
            for (i = 0;  i < rpng2_info.width;  ++i) {
Packit 0ba690
                x = (int)(i - hw);
Packit 0ba690
                angle = (x == 0)? PI_2 : atan((double)y / (double)x);
Packit 0ba690
                gray = (double)MAX(ABS(y), ABS(x)) / grayspot;
Packit 0ba690
                gray = MIN(1.0, gray);
Packit 0ba690
                dist = (double)((x*x) + (y*y)) / maxDist;
Packit 0ba690
                intensity = cos((angle+(rotate*dist*PI)) * freq) *
Packit 0ba690
                  gray * saturate;
Packit 0ba690
                intensity = (MAX(MIN(intensity,1.0),-1.0) + 1.0) * 0.5;
Packit 0ba690
                hue = (angle + PI) * INV_PI_360 + aoffset;
Packit 0ba690
                s = gray * ((double)(ABS(x)+ABS(y)) / (double)(hw + hh));
Packit 0ba690
                s = MIN(MAX(s,0.0), 1.0);
Packit 0ba690
                v = MIN(MAX(intensity,0.0), 1.0);
Packit 0ba690
Packit 0ba690
                if (s == 0.0) {
Packit 0ba690
                    ch = (uch)(v * 255.0);
Packit 0ba690
                    *dest++ = ch;
Packit 0ba690
                    *dest++ = ch;
Packit 0ba690
                    *dest++ = ch;
Packit 0ba690
                } else {
Packit 0ba690
                    if ((hue < 0.0) || (hue >= 360.0))
Packit 0ba690
                        hue -= (((int)(hue / 360.0)) * 360.0);
Packit 0ba690
                    hue /= 60.0;
Packit 0ba690
                    ii = (int)hue;
Packit 0ba690
                    f = hue - (double)ii;
Packit 0ba690
                    p = (1.0 - s) * v;
Packit 0ba690
                    q = (1.0 - (s * f)) * v;
Packit 0ba690
                    t = (1.0 - (s * (1.0 - f))) * v;
Packit 0ba690
                    if      (ii == 0) { red = v; green = t; blue = p; }
Packit 0ba690
                    else if (ii == 1) { red = q; green = v; blue = p; }
Packit 0ba690
                    else if (ii == 2) { red = p; green = v; blue = t; }
Packit 0ba690
                    else if (ii == 3) { red = p; green = q; blue = v; }
Packit 0ba690
                    else if (ii == 4) { red = t; green = p; blue = v; }
Packit 0ba690
                    else if (ii == 5) { red = v; green = p; blue = q; }
Packit 0ba690
                    *dest++ = (uch)(red * 255.0);
Packit 0ba690
                    *dest++ = (uch)(green * 255.0);
Packit 0ba690
                    *dest++ = (uch)(blue * 255.0);
Packit 0ba690
                }
Packit 0ba690
            }
Packit 0ba690
        }
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
} /* end function rpng2_x_reload_bg_image() */
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
static int is_number(char *p)
Packit 0ba690
{
Packit 0ba690
    while (*p) {
Packit 0ba690
        if (!isdigit(*p))
Packit 0ba690
            return FALSE;
Packit 0ba690
        ++p;
Packit 0ba690
    }
Packit 0ba690
    return TRUE;
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
#endif /* FEATURE_LOOP */
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
static void rpng2_x_cleanup(void)
Packit 0ba690
{
Packit 0ba690
    if (bg_image && bg_data) {
Packit 0ba690
        free(bg_data);
Packit 0ba690
        bg_data = NULL;
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    if (rpng2_info.image_data) {
Packit 0ba690
        free(rpng2_info.image_data);
Packit 0ba690
        rpng2_info.image_data = NULL;
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    if (rpng2_info.row_pointers) {
Packit 0ba690
        free(rpng2_info.row_pointers);
Packit 0ba690
        rpng2_info.row_pointers = NULL;
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    if (ximage) {
Packit 0ba690
        if (ximage->data) {
Packit 0ba690
            free(ximage->data);           /* we allocated it, so we free it */
Packit 0ba690
            ximage->data = (char *)NULL;  /*  instead of XDestroyImage() */
Packit 0ba690
        }
Packit 0ba690
        XDestroyImage(ximage);
Packit 0ba690
        ximage = NULL;
Packit 0ba690
    }
Packit 0ba690
Packit 0ba690
    if (have_gc)
Packit 0ba690
        XFreeGC(display, gc);
Packit 0ba690
Packit 0ba690
    if (have_window)
Packit 0ba690
        XDestroyWindow(display, window);
Packit 0ba690
Packit 0ba690
    if (have_colormap)
Packit 0ba690
        XFreeColormap(display, colormap);
Packit 0ba690
Packit 0ba690
    if (have_nondefault_visual)
Packit 0ba690
        XFree(visual_list);
Packit 0ba690
}
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
Packit 0ba690
static int rpng2_x_msb(ulg u32val)
Packit 0ba690
{
Packit 0ba690
    int i;
Packit 0ba690
Packit 0ba690
    for (i = 31;  i >= 0;  --i) {
Packit 0ba690
        if (u32val & 0x80000000L)
Packit 0ba690
            break;
Packit 0ba690
        u32val <<= 1;
Packit 0ba690
    }
Packit 0ba690
    return i;
Packit 0ba690
}