~baltix/+junk/irrlicht-test

« back to all changes in this revision

Viewing changes to source/Irrlicht/libpng/contrib/gregbook/rpng-x.c

  • Committer: Mantas Kriaučiūnas
  • Date: 2011-07-18 13:06:25 UTC
  • Revision ID: mantas@akl.lt-20110718130625-c5pvifp61e7kj1ol
Included whole irrlicht SVN libraries to work around launchpad recipe issue with quilt, see https://answers.launchpad.net/launchpad/+question/165193

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*---------------------------------------------------------------------------
 
2
 
 
3
   rpng - simple PNG display program                               rpng-x.c
 
4
 
 
5
   This program decodes and displays PNG images, with gamma correction and
 
6
   optionally with a user-specified background color (in case the image has
 
7
   transparency).  It is very nearly the most basic PNG viewer possible.
 
8
   This version is for the X Window System (tested by author under Unix and
 
9
   by Martin Zinser under OpenVMS; may work under OS/2 with some tweaking).
 
10
 
 
11
   to do:
 
12
    - 8-bit (colormapped) X support
 
13
    - use %.1023s to simplify truncation of title-bar string?
 
14
 
 
15
  ---------------------------------------------------------------------------
 
16
 
 
17
   Changelog:
 
18
    - 1.01:  initial public release
 
19
    - 1.02:  modified to allow abbreviated options; fixed long/ulong mis-
 
20
              match; switched to png_jmpbuf() macro
 
21
    - 1.10:  added support for non-default visuals; fixed X pixel-conversion
 
22
    - 1.11:  added extra set of parentheses to png_jmpbuf() macro; fixed
 
23
              command-line parsing bug
 
24
    - 1.12:  fixed some small X memory leaks (thanks to Fran�ois Petitjean)
 
25
    - 1.13:  fixed XFreeGC() crash bug (thanks to Patrick Welche)
 
26
    - 1.14:  added support for X resources (thanks to Gerhard Niklasch)
 
27
    - 2.00:  dual-licensed (added GNU GPL)
 
28
    - 2.01:  fixed improper display of usage screen on PNG error(s)
 
29
 
 
30
  ---------------------------------------------------------------------------
 
31
 
 
32
      Copyright (c) 1998-2008 Greg Roelofs.  All rights reserved.
 
33
 
 
34
      This software is provided "as is," without warranty of any kind,
 
35
      express or implied.  In no event shall the author or contributors
 
36
      be held liable for any damages arising in any way from the use of
 
37
      this software.
 
38
 
 
39
      The contents of this file are DUAL-LICENSED.  You may modify and/or
 
40
      redistribute this software according to the terms of one of the
 
41
      following two licenses (at your option):
 
42
 
 
43
 
 
44
      LICENSE 1 ("BSD-like with advertising clause"):
 
45
 
 
46
      Permission is granted to anyone to use this software for any purpose,
 
47
      including commercial applications, and to alter it and redistribute
 
48
      it freely, subject to the following restrictions:
 
49
 
 
50
      1. Redistributions of source code must retain the above copyright
 
51
         notice, disclaimer, and this list of conditions.
 
52
      2. Redistributions in binary form must reproduce the above copyright
 
53
         notice, disclaimer, and this list of conditions in the documenta-
 
54
         tion and/or other materials provided with the distribution.
 
55
      3. All advertising materials mentioning features or use of this
 
56
         software must display the following acknowledgment:
 
57
 
 
58
            This product includes software developed by Greg Roelofs
 
59
            and contributors for the book, "PNG: The Definitive Guide,"
 
60
            published by O'Reilly and Associates.
 
61
 
 
62
 
 
63
      LICENSE 2 (GNU GPL v2 or later):
 
64
 
 
65
      This program is free software; you can redistribute it and/or modify
 
66
      it under the terms of the GNU General Public License as published by
 
67
      the Free Software Foundation; either version 2 of the License, or
 
68
      (at your option) any later version.
 
69
 
 
70
      This program is distributed in the hope that it will be useful,
 
71
      but WITHOUT ANY WARRANTY; without even the implied warranty of
 
72
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
73
      GNU General Public License for more details.
 
74
 
 
75
      You should have received a copy of the GNU General Public License
 
76
      along with this program; if not, write to the Free Software Foundation,
 
77
      Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
78
 
 
79
  ---------------------------------------------------------------------------*/
 
80
 
 
81
#define PROGNAME  "rpng-x"
 
82
#define LONGNAME  "Simple PNG Viewer for X"
 
83
#define VERSION   "2.01 of 16 March 2008"
 
84
#define RESNAME   "rpng"        /* our X resource application name */
 
85
#define RESCLASS  "Rpng"        /* our X resource class name */
 
86
 
 
87
#include <stdio.h>
 
88
#include <stdlib.h>
 
89
#include <string.h>
 
90
#include <time.h>
 
91
#include <X11/Xlib.h>
 
92
#include <X11/Xutil.h>
 
93
#include <X11/Xos.h>
 
94
#include <X11/keysym.h>
 
95
 
 
96
/* #define DEBUG  :  this enables the Trace() macros */
 
97
 
 
98
#include "readpng.h"   /* typedefs, common macros, readpng prototypes */
 
99
 
 
100
 
 
101
/* could just include png.h, but this macro is the only thing we need
 
102
 * (name and typedefs changed to local versions); note that side effects
 
103
 * only happen with alpha (which could easily be avoided with
 
104
 * "ush acopy = (alpha);") */
 
105
 
 
106
#define alpha_composite(composite, fg, alpha, bg) {               \
 
107
    ush temp = ((ush)(fg)*(ush)(alpha) +                          \
 
108
                (ush)(bg)*(ush)(255 - (ush)(alpha)) + (ush)128);  \
 
109
    (composite) = (uch)((temp + (temp >> 8)) >> 8);               \
 
110
}
 
111
 
 
112
 
 
113
/* local prototypes */
 
114
static int  rpng_x_create_window(void);
 
115
static int  rpng_x_display_image(void);
 
116
static void rpng_x_cleanup(void);
 
117
static int  rpng_x_msb(ulg u32val);
 
118
 
 
119
 
 
120
static char titlebar[1024], *window_name = titlebar;
 
121
static char *appname = LONGNAME;
 
122
static char *icon_name = PROGNAME;
 
123
static char *res_name = RESNAME;
 
124
static char *res_class = RESCLASS;
 
125
static char *filename;
 
126
static FILE *infile;
 
127
 
 
128
static char *bgstr;
 
129
static uch bg_red=0, bg_green=0, bg_blue=0;
 
130
 
 
131
static double display_exponent;
 
132
 
 
133
static ulg image_width, image_height, image_rowbytes;
 
134
static int image_channels;
 
135
static uch *image_data;
 
136
 
 
137
/* X-specific variables */
 
138
static char *displayname;
 
139
static XImage *ximage;
 
140
static Display *display;
 
141
static int depth;
 
142
static Visual *visual;
 
143
static XVisualInfo *visual_list;
 
144
static int RShift, GShift, BShift;
 
145
static ulg RMask, GMask, BMask;
 
146
static Window window;
 
147
static GC gc;
 
148
static Colormap colormap;
 
149
 
 
150
static int have_nondefault_visual = FALSE;
 
151
static int have_colormap = FALSE;
 
152
static int have_window = FALSE;
 
153
static int have_gc = FALSE;
 
154
/*
 
155
ulg numcolors=0, pixels[256];
 
156
ush reds[256], greens[256], blues[256];
 
157
 */
 
158
 
 
159
 
 
160
 
 
161
 
 
162
int main(int argc, char **argv)
 
163
{
 
164
#ifdef sgi
 
165
    char tmpline[80];
 
166
#endif
 
167
    char *p;
 
168
    int rc, alen, flen;
 
169
    int error = 0;
 
170
    int have_bg = FALSE;
 
171
    double LUT_exponent;               /* just the lookup table */
 
172
    double CRT_exponent = 2.2;         /* just the monitor */
 
173
    double default_display_exponent;   /* whole display system */
 
174
    XEvent e;
 
175
    KeySym k;
 
176
 
 
177
 
 
178
    displayname = (char *)NULL;
 
179
    filename = (char *)NULL;
 
180
 
 
181
 
 
182
    /* First set the default value for our display-system exponent, i.e.,
 
183
     * the product of the CRT exponent and the exponent corresponding to
 
184
     * the frame-buffer's lookup table (LUT), if any.  This is not an
 
185
     * exhaustive list of LUT values (e.g., OpenStep has a lot of weird
 
186
     * ones), but it should cover 99% of the current possibilities. */
 
187
 
 
188
#if defined(NeXT)
 
189
    LUT_exponent = 1.0 / 2.2;
 
190
    /*
 
191
    if (some_next_function_that_returns_gamma(&next_gamma))
 
192
        LUT_exponent = 1.0 / next_gamma;
 
193
     */
 
194
#elif defined(sgi)
 
195
    LUT_exponent = 1.0 / 1.7;
 
196
    /* there doesn't seem to be any documented function to get the
 
197
     * "gamma" value, so we do it the hard way */
 
198
    infile = fopen("/etc/config/system.glGammaVal", "r");
 
199
    if (infile) {
 
200
        double sgi_gamma;
 
201
 
 
202
        fgets(tmpline, 80, infile);
 
203
        fclose(infile);
 
204
        sgi_gamma = atof(tmpline);
 
205
        if (sgi_gamma > 0.0)
 
206
            LUT_exponent = 1.0 / sgi_gamma;
 
207
    }
 
208
#elif defined(Macintosh)
 
209
    LUT_exponent = 1.8 / 2.61;
 
210
    /*
 
211
    if (some_mac_function_that_returns_gamma(&mac_gamma))
 
212
        LUT_exponent = mac_gamma / 2.61;
 
213
     */
 
214
#else
 
215
    LUT_exponent = 1.0;   /* assume no LUT:  most PCs */
 
216
#endif
 
217
 
 
218
    /* the defaults above give 1.0, 1.3, 1.5 and 2.2, respectively: */
 
219
    default_display_exponent = LUT_exponent * CRT_exponent;
 
220
 
 
221
 
 
222
    /* If the user has set the SCREEN_GAMMA environment variable as suggested
 
223
     * (somewhat imprecisely) in the libpng documentation, use that; otherwise
 
224
     * use the default value we just calculated.  Either way, the user may
 
225
     * override this via a command-line option. */
 
226
 
 
227
    if ((p = getenv("SCREEN_GAMMA")) != NULL)
 
228
        display_exponent = atof(p);
 
229
    else
 
230
        display_exponent = default_display_exponent;
 
231
 
 
232
 
 
233
    /* Now parse the command line for options and the PNG filename. */
 
234
 
 
235
    while (*++argv && !error) {
 
236
        if (!strncmp(*argv, "-display", 2)) {
 
237
            if (!*++argv)
 
238
                ++error;
 
239
            else
 
240
                displayname = *argv;
 
241
        } else if (!strncmp(*argv, "-gamma", 2)) {
 
242
            if (!*++argv)
 
243
                ++error;
 
244
            else {
 
245
                display_exponent = atof(*argv);
 
246
                if (display_exponent <= 0.0)
 
247
                    ++error;
 
248
            }
 
249
        } else if (!strncmp(*argv, "-bgcolor", 2)) {
 
250
            if (!*++argv)
 
251
                ++error;
 
252
            else {
 
253
                bgstr = *argv;
 
254
                if (strlen(bgstr) != 7 || bgstr[0] != '#')
 
255
                    ++error; 
 
256
                else 
 
257
                    have_bg = TRUE;
 
258
            }
 
259
        } else {
 
260
            if (**argv != '-') {
 
261
                filename = *argv;
 
262
                if (argv[1])   /* shouldn't be any more args after filename */
 
263
                    ++error;
 
264
            } else
 
265
                ++error;   /* not expecting any other options */
 
266
        }
 
267
    }
 
268
 
 
269
    if (!filename)
 
270
        ++error;
 
271
 
 
272
 
 
273
    /* print usage screen if any errors up to this point */
 
274
 
 
275
    if (error) {
 
276
        fprintf(stderr, "\n%s %s:  %s\n", PROGNAME, VERSION, appname);
 
277
        readpng_version_info();
 
278
        fprintf(stderr, "\n"
 
279
          "Usage:  %s [-display xdpy] [-gamma exp] [-bgcolor bg] file.png\n"
 
280
          "    xdpy\tname of the target X display (e.g., ``hostname:0'')\n"
 
281
          "    exp \ttransfer-function exponent (``gamma'') of the display\n"
 
282
          "\t\t  system in floating-point format (e.g., ``%.1f''); equal\n"
 
283
          "\t\t  to the product of the lookup-table exponent (varies)\n"
 
284
          "\t\t  and the CRT exponent (usually 2.2); must be positive\n"
 
285
          "    bg  \tdesired background color in 7-character hex RGB format\n"
 
286
          "\t\t  (e.g., ``#ff7700'' for orange:  same as HTML colors);\n"
 
287
          "\t\t  used with transparent images\n"
 
288
          "\nPress Q, Esc or mouse button 1 (within image window, after image\n"
 
289
          "is displayed) to quit.\n"
 
290
          "\n", PROGNAME, default_display_exponent);
 
291
        exit(1);
 
292
    }
 
293
 
 
294
 
 
295
    if (!(infile = fopen(filename, "rb"))) {
 
296
        fprintf(stderr, PROGNAME ":  can't open PNG file [%s]\n", filename);
 
297
        ++error;
 
298
    } else {
 
299
        if ((rc = readpng_init(infile, &image_width, &image_height)) != 0) {
 
300
            switch (rc) {
 
301
                case 1:
 
302
                    fprintf(stderr, PROGNAME
 
303
                      ":  [%s] is not a PNG file: incorrect signature\n",
 
304
                      filename);
 
305
                    break;
 
306
                case 2:
 
307
                    fprintf(stderr, PROGNAME
 
308
                      ":  [%s] has bad IHDR (libpng longjmp)\n", filename);
 
309
                    break;
 
310
                case 4:
 
311
                    fprintf(stderr, PROGNAME ":  insufficient memory\n");
 
312
                    break;
 
313
                default:
 
314
                    fprintf(stderr, PROGNAME
 
315
                      ":  unknown readpng_init() error\n");
 
316
                    break;
 
317
            }
 
318
            ++error;
 
319
        } else {
 
320
            display = XOpenDisplay(displayname);
 
321
            if (!display) {
 
322
                readpng_cleanup(TRUE);
 
323
                fprintf(stderr, PROGNAME ":  can't open X display [%s]\n",
 
324
                  displayname? displayname : "default");
 
325
                ++error;
 
326
            }
 
327
        }
 
328
        if (error)
 
329
            fclose(infile);
 
330
    }
 
331
 
 
332
 
 
333
    if (error) {
 
334
        fprintf(stderr, PROGNAME ":  aborting.\n");
 
335
        exit(2);
 
336
    }
 
337
 
 
338
 
 
339
    /* set the title-bar string, but make sure buffer doesn't overflow */
 
340
 
 
341
    alen = strlen(appname);
 
342
    flen = strlen(filename);
 
343
    if (alen + flen + 3 > 1023)
 
344
        sprintf(titlebar, "%s:  ...%s", appname, filename+(alen+flen+6-1023));
 
345
    else
 
346
        sprintf(titlebar, "%s:  %s", appname, filename);
 
347
 
 
348
 
 
349
    /* if the user didn't specify a background color on the command line,
 
350
     * check for one in the PNG file--if not, the initialized values of 0
 
351
     * (black) will be used */
 
352
 
 
353
    if (have_bg) {
 
354
        unsigned r, g, b;   /* this approach quiets compiler warnings */
 
355
 
 
356
        sscanf(bgstr+1, "%2x%2x%2x", &r, &g, &b);
 
357
        bg_red   = (uch)r;
 
358
        bg_green = (uch)g;
 
359
        bg_blue  = (uch)b;
 
360
    } else if (readpng_get_bgcolor(&bg_red, &bg_green, &bg_blue) > 1) {
 
361
        readpng_cleanup(TRUE);
 
362
        fprintf(stderr, PROGNAME
 
363
          ":  libpng error while checking for background color\n");
 
364
        exit(2);
 
365
    }
 
366
 
 
367
 
 
368
    /* do the basic X initialization stuff, make the window and fill it
 
369
     * with the background color */
 
370
 
 
371
    if (rpng_x_create_window())
 
372
        exit(2);
 
373
 
 
374
 
 
375
    /* decode the image, all at once */
 
376
 
 
377
    Trace((stderr, "calling readpng_get_image()\n"))
 
378
    image_data = readpng_get_image(display_exponent, &image_channels,
 
379
      &image_rowbytes);
 
380
    Trace((stderr, "done with readpng_get_image()\n"))
 
381
 
 
382
 
 
383
    /* done with PNG file, so clean up to minimize memory usage (but do NOT
 
384
     * nuke image_data!) */
 
385
 
 
386
    readpng_cleanup(FALSE);
 
387
    fclose(infile);
 
388
 
 
389
    if (!image_data) {
 
390
        fprintf(stderr, PROGNAME ":  unable to decode PNG image\n");
 
391
        exit(3);
 
392
    }
 
393
 
 
394
 
 
395
    /* display image (composite with background if requested) */
 
396
 
 
397
    Trace((stderr, "calling rpng_x_display_image()\n"))
 
398
    if (rpng_x_display_image()) {
 
399
        free(image_data);
 
400
        exit(4);
 
401
    }
 
402
    Trace((stderr, "done with rpng_x_display_image()\n"))
 
403
 
 
404
 
 
405
    /* wait for the user to tell us when to quit */
 
406
 
 
407
    printf(
 
408
      "Done.  Press Q, Esc or mouse button 1 (within image window) to quit.\n");
 
409
    fflush(stdout);
 
410
 
 
411
    do
 
412
        XNextEvent(display, &e);
 
413
    while (!(e.type == ButtonPress && e.xbutton.button == Button1) &&
 
414
           !(e.type == KeyPress &&    /*  v--- or 1 for shifted keys */
 
415
             ((k = XLookupKeysym(&e.xkey, 0)) == XK_q || k == XK_Escape) ));
 
416
 
 
417
 
 
418
    /* OK, we're done:  clean up all image and X resources and go away */
 
419
 
 
420
    rpng_x_cleanup();
 
421
 
 
422
    return 0;
 
423
}
 
424
 
 
425
 
 
426
 
 
427
 
 
428
 
 
429
static int rpng_x_create_window(void)
 
430
{
 
431
    uch *xdata;
 
432
    int need_colormap = FALSE;
 
433
    int screen, pad;
 
434
    ulg bg_pixel = 0L;
 
435
    ulg attrmask;
 
436
    Window root;
 
437
    XEvent e;
 
438
    XGCValues gcvalues;
 
439
    XSetWindowAttributes attr;
 
440
    XTextProperty windowName, *pWindowName = &windowName;
 
441
    XTextProperty iconName, *pIconName = &iconName;
 
442
    XVisualInfo visual_info;
 
443
    XSizeHints *size_hints;
 
444
    XWMHints *wm_hints;
 
445
    XClassHint *class_hints;
 
446
 
 
447
 
 
448
    screen = DefaultScreen(display);
 
449
    depth = DisplayPlanes(display, screen);
 
450
    root = RootWindow(display, screen);
 
451
 
 
452
#ifdef DEBUG
 
453
    XSynchronize(display, True);
 
454
#endif
 
455
 
 
456
#if 0
 
457
/* GRR:  add 8-bit support */
 
458
    if (/* depth != 8 && */ depth != 16 && depth != 24 && depth != 32) {
 
459
        fprintf(stderr,
 
460
          "screen depth %d not supported (only 16-, 24- or 32-bit TrueColor)\n",
 
461
          depth);
 
462
        return 2;
 
463
    }
 
464
 
 
465
    XMatchVisualInfo(display, screen, depth,
 
466
      (depth == 8)? PseudoColor : TrueColor, &visual_info);
 
467
    visual = visual_info.visual;
 
468
#else
 
469
    if (depth != 16 && depth != 24 && depth != 32) {
 
470
        int visuals_matched = 0;
 
471
 
 
472
        Trace((stderr, "default depth is %d:  checking other visuals\n",
 
473
          depth))
 
474
 
 
475
        /* 24-bit first */
 
476
        visual_info.screen = screen;
 
477
        visual_info.depth = 24;
 
478
        visual_list = XGetVisualInfo(display,
 
479
          VisualScreenMask | VisualDepthMask, &visual_info, &visuals_matched);
 
480
        if (visuals_matched == 0) {
 
481
/* GRR:  add 15-, 16- and 32-bit TrueColor visuals (also DirectColor?) */
 
482
            fprintf(stderr, "default screen depth %d not supported, and no"
 
483
              " 24-bit visuals found\n", depth);
 
484
            return 2;
 
485
        }
 
486
        Trace((stderr, "XGetVisualInfo() returned %d 24-bit visuals\n",
 
487
          visuals_matched))
 
488
        visual = visual_list[0].visual;
 
489
        depth = visual_list[0].depth;
 
490
/*
 
491
        colormap_size = visual_list[0].colormap_size;
 
492
        visual_class = visual->class;
 
493
        visualID = XVisualIDFromVisual(visual);
 
494
 */
 
495
        have_nondefault_visual = TRUE;
 
496
        need_colormap = TRUE;
 
497
    } else {
 
498
        XMatchVisualInfo(display, screen, depth, TrueColor, &visual_info);
 
499
        visual = visual_info.visual;
 
500
    }
 
501
#endif
 
502
 
 
503
    RMask = visual->red_mask;
 
504
    GMask = visual->green_mask;
 
505
    BMask = visual->blue_mask;
 
506
 
 
507
/* GRR:  add/check 8-bit support */
 
508
    if (depth == 8 || need_colormap) {
 
509
        colormap = XCreateColormap(display, root, visual, AllocNone);
 
510
        if (!colormap) {
 
511
            fprintf(stderr, "XCreateColormap() failed\n");
 
512
            return 2;
 
513
        }
 
514
        have_colormap = TRUE;
 
515
    }
 
516
    if (depth == 15 || depth == 16) {
 
517
        RShift = 15 - rpng_x_msb(RMask);    /* these are right-shifts */
 
518
        GShift = 15 - rpng_x_msb(GMask);
 
519
        BShift = 15 - rpng_x_msb(BMask);
 
520
    } else if (depth > 16) {
 
521
#define NO_24BIT_MASKS
 
522
#ifdef NO_24BIT_MASKS
 
523
        RShift = rpng_x_msb(RMask) - 7;     /* these are left-shifts */
 
524
        GShift = rpng_x_msb(GMask) - 7;
 
525
        BShift = rpng_x_msb(BMask) - 7;
 
526
#else
 
527
        RShift = 7 - rpng_x_msb(RMask);     /* these are right-shifts, too */
 
528
        GShift = 7 - rpng_x_msb(GMask);
 
529
        BShift = 7 - rpng_x_msb(BMask);
 
530
#endif
 
531
    }
 
532
    if (depth >= 15 && (RShift < 0 || GShift < 0 || BShift < 0)) {
 
533
        fprintf(stderr, "rpng internal logic error:  negative X shift(s)!\n");
 
534
        return 2;
 
535
    }
 
536
 
 
537
/*---------------------------------------------------------------------------
 
538
    Finally, create the window.
 
539
  ---------------------------------------------------------------------------*/
 
540
 
 
541
    attr.backing_store = Always;
 
542
    attr.event_mask = ExposureMask | KeyPressMask | ButtonPressMask;
 
543
    attrmask = CWBackingStore | CWEventMask;
 
544
    if (have_nondefault_visual) {
 
545
        attr.colormap = colormap;
 
546
        attr.background_pixel = 0;
 
547
        attr.border_pixel = 1;
 
548
        attrmask |= CWColormap | CWBackPixel | CWBorderPixel;
 
549
    }
 
550
 
 
551
    window = XCreateWindow(display, root, 0, 0, image_width, image_height, 0,
 
552
      depth, InputOutput, visual, attrmask, &attr);
 
553
 
 
554
    if (window == None) {
 
555
        fprintf(stderr, "XCreateWindow() failed\n");
 
556
        return 2;
 
557
    } else
 
558
        have_window = TRUE;
 
559
 
 
560
    if (depth == 8)
 
561
        XSetWindowColormap(display, window, colormap);
 
562
 
 
563
    if (!XStringListToTextProperty(&window_name, 1, pWindowName))
 
564
        pWindowName = NULL;
 
565
    if (!XStringListToTextProperty(&icon_name, 1, pIconName))
 
566
        pIconName = NULL;
 
567
 
 
568
    /* OK if any hints allocation fails; XSetWMProperties() allows NULLs */
 
569
 
 
570
    if ((size_hints = XAllocSizeHints()) != NULL) {
 
571
        /* window will not be resizable */
 
572
        size_hints->flags = PMinSize | PMaxSize;
 
573
        size_hints->min_width = size_hints->max_width = (int)image_width;
 
574
        size_hints->min_height = size_hints->max_height = (int)image_height;
 
575
    }
 
576
 
 
577
    if ((wm_hints = XAllocWMHints()) != NULL) {
 
578
        wm_hints->initial_state = NormalState;
 
579
        wm_hints->input = True;
 
580
     /* wm_hints->icon_pixmap = icon_pixmap; */
 
581
        wm_hints->flags = StateHint | InputHint  /* | IconPixmapHint */ ;
 
582
    }
 
583
 
 
584
    if ((class_hints = XAllocClassHint()) != NULL) {
 
585
        class_hints->res_name = res_name;
 
586
        class_hints->res_class = res_class;
 
587
    }
 
588
 
 
589
    XSetWMProperties(display, window, pWindowName, pIconName, NULL, 0,
 
590
      size_hints, wm_hints, class_hints);
 
591
 
 
592
    /* various properties and hints no longer needed; free memory */
 
593
    if (pWindowName)
 
594
       XFree(pWindowName->value);
 
595
    if (pIconName)
 
596
       XFree(pIconName->value);
 
597
    if (size_hints)
 
598
        XFree(size_hints);
 
599
    if (wm_hints)
 
600
       XFree(wm_hints);
 
601
    if (class_hints)
 
602
       XFree(class_hints);
 
603
 
 
604
    XMapWindow(display, window);
 
605
 
 
606
    gc = XCreateGC(display, window, 0, &gcvalues);
 
607
    have_gc = TRUE;
 
608
 
 
609
/*---------------------------------------------------------------------------
 
610
    Fill window with the specified background color.
 
611
  ---------------------------------------------------------------------------*/
 
612
 
 
613
    if (depth == 24 || depth == 32) {
 
614
        bg_pixel = ((ulg)bg_red   << RShift) |
 
615
                   ((ulg)bg_green << GShift) |
 
616
                   ((ulg)bg_blue  << BShift);
 
617
    } else if (depth == 16) {
 
618
        bg_pixel = ((((ulg)bg_red   << 8) >> RShift) & RMask) |
 
619
                   ((((ulg)bg_green << 8) >> GShift) & GMask) |
 
620
                   ((((ulg)bg_blue  << 8) >> BShift) & BMask);
 
621
    } else /* depth == 8 */ {
 
622
 
 
623
        /* GRR:  add 8-bit support */
 
624
 
 
625
    }
 
626
 
 
627
    XSetForeground(display, gc, bg_pixel);
 
628
    XFillRectangle(display, window, gc, 0, 0, image_width, image_height);
 
629
 
 
630
/*---------------------------------------------------------------------------
 
631
    Wait for first Expose event to do any drawing, then flush.
 
632
  ---------------------------------------------------------------------------*/
 
633
 
 
634
    do
 
635
        XNextEvent(display, &e);
 
636
    while (e.type != Expose || e.xexpose.count);
 
637
 
 
638
    XFlush(display);
 
639
 
 
640
/*---------------------------------------------------------------------------
 
641
    Allocate memory for the X- and display-specific version of the image.
 
642
  ---------------------------------------------------------------------------*/
 
643
 
 
644
    if (depth == 24 || depth == 32) {
 
645
        xdata = (uch *)malloc(4*image_width*image_height);
 
646
        pad = 32;
 
647
    } else if (depth == 16) {
 
648
        xdata = (uch *)malloc(2*image_width*image_height);
 
649
        pad = 16;
 
650
    } else /* depth == 8 */ {
 
651
        xdata = (uch *)malloc(image_width*image_height);
 
652
        pad = 8;
 
653
    }
 
654
 
 
655
    if (!xdata) {
 
656
        fprintf(stderr, PROGNAME ":  unable to allocate image memory\n");
 
657
        return 4;
 
658
    }
 
659
 
 
660
    ximage = XCreateImage(display, visual, depth, ZPixmap, 0,
 
661
      (char *)xdata, image_width, image_height, pad, 0);
 
662
 
 
663
    if (!ximage) {
 
664
        fprintf(stderr, PROGNAME ":  XCreateImage() failed\n");
 
665
        free(xdata);
 
666
        return 3;
 
667
    }
 
668
 
 
669
    /* to avoid testing the byte order every pixel (or doubling the size of
 
670
     * the drawing routine with a giant if-test), we arbitrarily set the byte
 
671
     * order to MSBFirst and let Xlib worry about inverting things on little-
 
672
     * endian machines (like Linux/x86, old VAXen, etc.)--this is not the most
 
673
     * efficient approach (the giant if-test would be better), but in the
 
674
     * interest of clarity, we take the easy way out... */
 
675
 
 
676
    ximage->byte_order = MSBFirst;
 
677
 
 
678
    return 0;
 
679
 
 
680
} /* end function rpng_x_create_window() */
 
681
 
 
682
 
 
683
 
 
684
 
 
685
 
 
686
static int rpng_x_display_image(void)
 
687
{
 
688
    uch *src;
 
689
    char *dest;
 
690
    uch r, g, b, a;
 
691
    ulg i, row, lastrow = 0;
 
692
    ulg pixel;
 
693
    int ximage_rowbytes = ximage->bytes_per_line;
 
694
/*  int bpp = ximage->bits_per_pixel;  */
 
695
 
 
696
 
 
697
    Trace((stderr, "beginning display loop (image_channels == %d)\n",
 
698
      image_channels))
 
699
    Trace((stderr, "   (width = %ld, rowbytes = %ld, ximage_rowbytes = %d)\n",
 
700
      image_width, image_rowbytes, ximage_rowbytes))
 
701
    Trace((stderr, "   (bpp = %d)\n", ximage->bits_per_pixel))
 
702
    Trace((stderr, "   (byte_order = %s)\n", ximage->byte_order == MSBFirst?
 
703
      "MSBFirst" : (ximage->byte_order == LSBFirst? "LSBFirst" : "unknown")))
 
704
 
 
705
    if (depth == 24 || depth == 32) {
 
706
        ulg red, green, blue;
 
707
 
 
708
        for (lastrow = row = 0;  row < image_height;  ++row) {
 
709
            src = image_data + row*image_rowbytes;
 
710
            dest = ximage->data + row*ximage_rowbytes;
 
711
            if (image_channels == 3) {
 
712
                for (i = image_width;  i > 0;  --i) {
 
713
                    red   = *src++;
 
714
                    green = *src++;
 
715
                    blue  = *src++;
 
716
#ifdef NO_24BIT_MASKS
 
717
                    pixel = (red   << RShift) |
 
718
                            (green << GShift) |
 
719
                            (blue  << BShift);
 
720
                    /* recall that we set ximage->byte_order = MSBFirst above */
 
721
                    /* GRR BUG:  this assumes bpp == 32, but may be 24: */
 
722
                    *dest++ = (char)((pixel >> 24) & 0xff);
 
723
                    *dest++ = (char)((pixel >> 16) & 0xff);
 
724
                    *dest++ = (char)((pixel >>  8) & 0xff);
 
725
                    *dest++ = (char)( pixel        & 0xff);
 
726
#else
 
727
                    red   = (RShift < 0)? red   << (-RShift) : red   >> RShift;
 
728
                    green = (GShift < 0)? green << (-GShift) : green >> GShift;
 
729
                    blue  = (BShift < 0)? blue  << (-BShift) : blue  >> BShift;
 
730
                    pixel = (red & RMask) | (green & GMask) | (blue & BMask);
 
731
                    /* recall that we set ximage->byte_order = MSBFirst above */
 
732
                    *dest++ = (char)((pixel >> 24) & 0xff);
 
733
                    *dest++ = (char)((pixel >> 16) & 0xff);
 
734
                    *dest++ = (char)((pixel >>  8) & 0xff);
 
735
                    *dest++ = (char)( pixel        & 0xff);
 
736
#endif
 
737
                }
 
738
            } else /* if (image_channels == 4) */ {
 
739
                for (i = image_width;  i > 0;  --i) {
 
740
                    r = *src++;
 
741
                    g = *src++;
 
742
                    b = *src++;
 
743
                    a = *src++;
 
744
                    if (a == 255) {
 
745
                        red   = r;
 
746
                        green = g;
 
747
                        blue  = b;
 
748
                    } else if (a == 0) {
 
749
                        red   = bg_red;
 
750
                        green = bg_green;
 
751
                        blue  = bg_blue;
 
752
                    } else {
 
753
                        /* this macro (from png.h) composites the foreground
 
754
                         * and background values and puts the result into the
 
755
                         * first argument */
 
756
                        alpha_composite(red,   r, a, bg_red);
 
757
                        alpha_composite(green, g, a, bg_green);
 
758
                        alpha_composite(blue,  b, a, bg_blue);
 
759
                    }
 
760
                    pixel = (red   << RShift) |
 
761
                            (green << GShift) |
 
762
                            (blue  << BShift);
 
763
                    /* recall that we set ximage->byte_order = MSBFirst above */
 
764
                    *dest++ = (char)((pixel >> 24) & 0xff);
 
765
                    *dest++ = (char)((pixel >> 16) & 0xff);
 
766
                    *dest++ = (char)((pixel >>  8) & 0xff);
 
767
                    *dest++ = (char)( pixel        & 0xff);
 
768
                }
 
769
            }
 
770
            /* display after every 16 lines */
 
771
            if (((row+1) & 0xf) == 0) {
 
772
                XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
 
773
                  (int)lastrow, image_width, 16);
 
774
                XFlush(display);
 
775
                lastrow = row + 1;
 
776
            }
 
777
        }
 
778
 
 
779
    } else if (depth == 16) {
 
780
        ush red, green, blue;
 
781
 
 
782
        for (lastrow = row = 0;  row < image_height;  ++row) {
 
783
            src = image_data + row*image_rowbytes;
 
784
            dest = ximage->data + row*ximage_rowbytes;
 
785
            if (image_channels == 3) {
 
786
                for (i = image_width;  i > 0;  --i) {
 
787
                    red   = ((ush)(*src) << 8);
 
788
                    ++src;
 
789
                    green = ((ush)(*src) << 8);
 
790
                    ++src;
 
791
                    blue  = ((ush)(*src) << 8);
 
792
                    ++src;
 
793
                    pixel = ((red   >> RShift) & RMask) |
 
794
                            ((green >> GShift) & GMask) |
 
795
                            ((blue  >> BShift) & BMask);
 
796
                    /* recall that we set ximage->byte_order = MSBFirst above */
 
797
                    *dest++ = (char)((pixel >>  8) & 0xff);
 
798
                    *dest++ = (char)( pixel        & 0xff);
 
799
                }
 
800
            } else /* if (image_channels == 4) */ {
 
801
                for (i = image_width;  i > 0;  --i) {
 
802
                    r = *src++;
 
803
                    g = *src++;
 
804
                    b = *src++;
 
805
                    a = *src++;
 
806
                    if (a == 255) {
 
807
                        red   = ((ush)r << 8);
 
808
                        green = ((ush)g << 8);
 
809
                        blue  = ((ush)b << 8);
 
810
                    } else if (a == 0) {
 
811
                        red   = ((ush)bg_red   << 8);
 
812
                        green = ((ush)bg_green << 8);
 
813
                        blue  = ((ush)bg_blue  << 8);
 
814
                    } else {
 
815
                        /* this macro (from png.h) composites the foreground
 
816
                         * and background values and puts the result back into
 
817
                         * the first argument (== fg byte here:  safe) */
 
818
                        alpha_composite(r, r, a, bg_red);
 
819
                        alpha_composite(g, g, a, bg_green);
 
820
                        alpha_composite(b, b, a, bg_blue);
 
821
                        red   = ((ush)r << 8);
 
822
                        green = ((ush)g << 8);
 
823
                        blue  = ((ush)b << 8);
 
824
                    }
 
825
                    pixel = ((red   >> RShift) & RMask) |
 
826
                            ((green >> GShift) & GMask) |
 
827
                            ((blue  >> BShift) & BMask);
 
828
                    /* recall that we set ximage->byte_order = MSBFirst above */
 
829
                    *dest++ = (char)((pixel >>  8) & 0xff);
 
830
                    *dest++ = (char)( pixel        & 0xff);
 
831
                }
 
832
            }
 
833
            /* display after every 16 lines */
 
834
            if (((row+1) & 0xf) == 0) {
 
835
                XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
 
836
                  (int)lastrow, image_width, 16);
 
837
                XFlush(display);
 
838
                lastrow = row + 1;
 
839
            }
 
840
        }
 
841
 
 
842
    } else /* depth == 8 */ {
 
843
 
 
844
        /* GRR:  add 8-bit support */
 
845
 
 
846
    }
 
847
 
 
848
    Trace((stderr, "calling final XPutImage()\n"))
 
849
    if (lastrow < image_height) {
 
850
        XPutImage(display, window, gc, ximage, 0, (int)lastrow, 0,
 
851
          (int)lastrow, image_width, image_height-lastrow);
 
852
        XFlush(display);
 
853
    }
 
854
 
 
855
    return 0;
 
856
}
 
857
 
 
858
 
 
859
 
 
860
 
 
861
static void rpng_x_cleanup(void)
 
862
{
 
863
    if (image_data) {
 
864
        free(image_data);
 
865
        image_data = NULL;
 
866
    }
 
867
 
 
868
    if (ximage) {
 
869
        if (ximage->data) {
 
870
            free(ximage->data);           /* we allocated it, so we free it */
 
871
            ximage->data = (char *)NULL;  /*  instead of XDestroyImage() */
 
872
        }
 
873
        XDestroyImage(ximage);
 
874
        ximage = NULL;
 
875
    }
 
876
 
 
877
    if (have_gc)
 
878
        XFreeGC(display, gc);
 
879
 
 
880
    if (have_window)
 
881
        XDestroyWindow(display, window);
 
882
 
 
883
    if (have_colormap)
 
884
        XFreeColormap(display, colormap);
 
885
 
 
886
    if (have_nondefault_visual)
 
887
        XFree(visual_list);
 
888
}
 
889
 
 
890
 
 
891
 
 
892
 
 
893
 
 
894
static int rpng_x_msb(ulg u32val)
 
895
{
 
896
    int i;
 
897
 
 
898
    for (i = 31;  i >= 0;  --i) {
 
899
        if (u32val & 0x80000000L)
 
900
            break;
 
901
        u32val <<= 1;
 
902
    }
 
903
    return i;
 
904
}