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