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