xref: /petsc/src/sys/classes/draw/impls/x/xinit.c (revision e0877f539457ad1ce8178bc0750eac5ffa490a67)
1 
2 /*
3    This file contains routines to open an X window display and window
4    This consists of a number of routines that set the various
5    fields in the Window structure, which is passed to
6    all of these routines.
7 
8    Note that if you use the default visual and colormap, then you
9    can use these routines with any X toolkit that will give you the
10    Window id of the window that it is managing.  Use that instead of the
11    call to PetscDrawXiCreateWindow .  Similarly for the Display.
12 */
13 
14 #include <../src/sys/classes/draw/impls/x/ximpl.h>
15 
16 extern PetscErrorCode PetscDrawXi_wait_map(PetscDraw_X*);
17 extern PetscErrorCode PetscDrawXiFontFixed(PetscDraw_X*,int,int,PetscDrawXiFont**);
18 extern PetscErrorCode PetscDrawXiInitCmap(PetscDraw_X*);
19 extern PetscErrorCode PetscDrawSetColormap_X(PetscDraw_X*,Colormap);
20 
21 /*
22   PetscDrawXiOpenDisplay - Open and setup a display
23 */
24 #undef __FUNCT__
25 #define __FUNCT__ "PetscDrawXiOpenDisplay"
26 PetscErrorCode PetscDrawXiOpenDisplay(PetscDraw_X *XiWin,const char display[])
27 {
28   PetscFunctionBegin;
29   XiWin->disp = XOpenDisplay(display);
30   if (!XiWin->disp) {
31     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to open display on %s\n\
32     Make sure your COMPUTE NODES are authorized to connect \n\
33     to this X server and either your DISPLAY variable\n\
34     is set or you use the -display name option\n",display);
35   }
36   XiWin->screen     = DefaultScreen(XiWin->disp);
37   XiWin->vis        = DefaultVisual(XiWin->disp,XiWin->screen);
38   XiWin->depth      = DefaultDepth(XiWin->disp,XiWin->screen);
39   XiWin->cmap       = DefaultColormap(XiWin->disp,XiWin->screen);
40   XiWin->background = WhitePixel(XiWin->disp,XiWin->screen);
41   XiWin->foreground = BlackPixel(XiWin->disp,XiWin->screen);
42   PetscFunctionReturn(0);
43 }
44 
45 #undef __FUNCT__
46 #define __FUNCT__ "PetscDrawXiClose"
47 PetscErrorCode PetscDrawXiClose(PetscDraw_X *XiWin)
48 {
49   PetscErrorCode ierr;
50 
51   PetscFunctionBegin;
52   if (!XiWin) PetscFunctionReturn(0);
53   ierr = PetscFree(XiWin->font);CHKERRQ(ierr);
54   if (XiWin->disp) {
55 #if defined(PETSC_HAVE_SETJMP_H)
56     jmp_buf              jmpbuf;
57     PetscXIOErrorHandler xioerrhdl;
58     ierr = PetscMemcpy(&jmpbuf,&PetscXIOErrorHandlerJumpBuf,sizeof(jmpbuf));CHKERRQ(ierr);
59     xioerrhdl = PetscSetXIOErrorHandler(PetscXIOErrorHandlerJump);
60     if (!setjmp(PetscXIOErrorHandlerJumpBuf))
61 #endif
62     {
63       XFreeGC(XiWin->disp,XiWin->gc.set);
64       XCloseDisplay(XiWin->disp);
65     }
66     XiWin->disp = NULL;
67 #if defined(PETSC_HAVE_SETJMP_H)
68     (void)PetscSetXIOErrorHandler(xioerrhdl);
69     ierr = PetscMemcpy(&PetscXIOErrorHandlerJumpBuf,&jmpbuf,sizeof(jmpbuf));CHKERRQ(ierr);
70 #endif
71   }
72   PetscFunctionReturn(0);
73 }
74 
75 /*
76    PetscDrawXiSetGC - setup the GC structure
77 */
78 #undef __FUNCT__
79 #define __FUNCT__ "PetscDrawXiSetGC"
80 PetscErrorCode PetscDrawXiSetGC(PetscDraw_X *XiWin,PetscDrawXiPixVal fg)
81 {
82   XGCValues gcvalues;             /* window graphics context values */
83 
84   PetscFunctionBegin;
85   /* Set the graphics contexts */
86   /* create a gc for the ROP_SET operation (writing the fg value to a pixel) */
87   /* (do this with function GXcopy; GXset will automatically write 1) */
88   gcvalues.function   = GXcopy;
89   gcvalues.foreground = fg;
90   XiWin->gc.cur_pix   = fg;
91   XiWin->gc.set       = XCreateGC(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),GCFunction|GCForeground,&gcvalues);
92   if (!XiWin->gc.set) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to create X graphics context");
93   PetscFunctionReturn(0);
94 }
95 
96 /*
97    PetscDrawXiInit - basic setup the draw (display, graphics context, font)
98 */
99 #undef __FUNCT__
100 #define __FUNCT__ "PetscDrawXiInit"
101 PetscErrorCode PetscDrawXiInit(PetscDraw_X *XiWin,const char display[])
102 {
103   PetscErrorCode ierr;
104   PetscFunctionBegin;
105   ierr = PetscDrawXiOpenDisplay(XiWin,display);CHKERRQ(ierr);
106   ierr = PetscDrawXiSetGC(XiWin,XiWin->foreground);CHKERRQ(ierr);
107   ierr = PetscDrawXiFontFixed(XiWin,6,10,&XiWin->font);CHKERRQ(ierr);
108   PetscFunctionReturn(0);
109 }
110 
111 /*
112     Actually display a window at [x,y] with sizes (w,h)
113 */
114 #undef __FUNCT__
115 #define __FUNCT__ "PetscDrawXiDisplayWindow"
116 PetscErrorCode PetscDrawXiDisplayWindow(PetscDraw_X *XiWin,char *label,int x,int y,int w,int h)
117 {
118   unsigned int         wavail,havail;
119   XSizeHints           size_hints;
120   XWindowAttributes    in_window_attributes;
121   XSetWindowAttributes window_attributes;
122   unsigned int         border_width = 0;
123   unsigned long        backgnd_pixel = WhitePixel(XiWin->disp,XiWin->screen);
124   unsigned long        wmask;
125 
126   PetscFunctionBegin;
127   /* get the available widths */
128   wavail = DisplayWidth(XiWin->disp,XiWin->screen);
129   havail = DisplayHeight(XiWin->disp,XiWin->screen);
130   if (w <= 0 || h <= 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"X Window display has invalid height or width");
131   if ((unsigned int)w > wavail) w = wavail;
132   if ((unsigned int)h > havail) h = havail;
133 
134   if (x < 0) x = (int)(wavail - (unsigned int)w + (unsigned int)x);
135   if (y < 0) y = (int)(havail - (unsigned int)h + (unsigned int)y);
136   x = ((unsigned int)x + w > wavail) ? (int)(wavail - (unsigned int)w) : x;
137   y = ((unsigned int)y + h > havail) ? (int)(havail - (unsigned int)h) : y;
138 
139   /* We need XCreateWindow since we may need an visual other than the default one */
140   XGetWindowAttributes(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),&in_window_attributes);
141   window_attributes.background_pixmap = None;
142   window_attributes.background_pixel  = backgnd_pixel;
143   /* No border for now */
144   window_attributes.border_pixmap     = None;
145   /*
146   window_attributes.border_pixel      = border_pixel;
147   */
148   window_attributes.bit_gravity       = in_window_attributes.bit_gravity;
149   window_attributes.win_gravity       = in_window_attributes.win_gravity;
150   /* Backing store is too slow in color systems */
151   window_attributes.backing_store     = NotUseful;
152   window_attributes.backing_pixel     = backgnd_pixel;
153   window_attributes.save_under        = 1;
154   window_attributes.event_mask        = 0;
155   window_attributes.do_not_propagate_mask = 0;
156   window_attributes.override_redirect = 0;
157   window_attributes.colormap          = XiWin->cmap;
158   /* None for cursor does NOT mean none, it means cursor of Parent */
159   window_attributes.cursor            = None;
160 
161   wmask = CWBackPixmap | CWBackPixel    | CWBorderPixmap  | CWBitGravity |
162           CWWinGravity | CWBackingStore | CWBackingPixel  | CWOverrideRedirect |
163           CWSaveUnder  | CWEventMask    | CWDontPropagate |
164           CWCursor     | CWColormap;
165 
166   XiWin->win = XCreateWindow(XiWin->disp,RootWindow(XiWin->disp,XiWin->screen),x,y,w,h,border_width,XiWin->depth,InputOutput,XiWin->vis,wmask,&window_attributes);
167   if (!XiWin->win) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Unable to open X window");
168 
169   /* set window manager hints */
170   {
171     XWMHints      wm_hints;
172     XClassHint    class_hints;
173     XTextProperty windowname,iconname;
174 
175     if (label) XStringListToTextProperty(&label,1,&windowname);
176     else       XStringListToTextProperty(&label,0,&windowname);
177     if (label) XStringListToTextProperty(&label,1,&iconname);
178     else       XStringListToTextProperty(&label,0,&iconname);
179 
180     wm_hints.initial_state = NormalState;
181     wm_hints.input         = True;
182     wm_hints.flags         = StateHint|InputHint;
183 
184     /* These properties can be used by window managers to decide how to display a window */
185     class_hints.res_name  = (char*)"petsc";
186     class_hints.res_class = (char*)"PETSc";
187 
188     size_hints.x          = x;
189     size_hints.y          = y;
190     size_hints.min_width  = 4*border_width;
191     size_hints.min_height = 4*border_width;
192     size_hints.width      = w;
193     size_hints.height     = h;
194     size_hints.flags      = USPosition | USSize | PMinSize;
195 
196     XSetWMProperties(XiWin->disp,XiWin->win,&windowname,&iconname,0,0,&size_hints,&wm_hints,&class_hints);
197     XFree((void*)windowname.value);
198     XFree((void*)iconname.value);
199   }
200 
201   /* make the window visible */
202   XSelectInput(XiWin->disp,XiWin->win,ExposureMask|StructureNotifyMask);
203   XMapWindow(XiWin->disp,XiWin->win);
204 
205   /* some window systems are cruel and interfere with the placement of
206      windows.  We wait here for the window to be created or to die */
207   if (PetscDrawXi_wait_map(XiWin)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB,"Wait for X window failed");
208   PetscFunctionReturn(0);
209 }
210 
211 #undef __FUNCT__
212 #define __FUNCT__ "PetscDrawXiQuickWindow"
213 PetscErrorCode PetscDrawXiQuickWindow(PetscDraw_X *XiWin,char *name,int x,int y,int nx,int ny)
214 {
215   Window         root;
216   unsigned int   w,h,dummy;
217   PetscErrorCode ierr;
218 
219   PetscFunctionBegin;
220   ierr = PetscDrawSetColormap_X(XiWin,(Colormap)0);CHKERRQ(ierr);
221   ierr = PetscDrawXiDisplayWindow(XiWin,name,x,y,nx,ny);CHKERRQ(ierr);
222   XSetWindowBackground(XiWin->disp,XiWin->win,XiWin->background);
223   XClearWindow(XiWin->disp,XiWin->win);
224 
225   XGetGeometry(XiWin->disp,XiWin->win,&root,&x,&y,&w,&h,&dummy,&dummy);
226   XiWin->x = x;
227   XiWin->y = y;
228   XiWin->w = (int)w;
229   XiWin->h = (int)h;
230   PetscFunctionReturn(0);
231 }
232 
233 /*
234    A version from an already defined window
235 */
236 #undef __FUNCT__
237 #define __FUNCT__ "PetscDrawXiQuickWindowFromWindow"
238 PetscErrorCode PetscDrawXiQuickWindowFromWindow(PetscDraw_X *XiWin,Window win)
239 {
240   Window            root;
241   int               x,y;
242   unsigned int      w,h,dummy;
243   XWindowAttributes attributes;
244   PetscErrorCode    ierr;
245 
246   PetscFunctionBegin;
247   XiWin->win = win;
248   XGetWindowAttributes(XiWin->disp,XiWin->win,&attributes);
249   ierr = PetscDrawSetColormap_X(XiWin,attributes.colormap);CHKERRQ(ierr);
250 
251   XGetGeometry(XiWin->disp,XiWin->win,&root,&x,&y,&w,&h,&dummy,&dummy);
252   XiWin->x = x;
253   XiWin->y = y;
254   XiWin->w = (int)w;
255   XiWin->h = (int)h;
256   PetscFunctionReturn(0);
257 }
258 
259 /*
260       PetscDrawXiSetWindowLabel - Sets new label in open window.
261 */
262 #undef __FUNCT__
263 #define __FUNCT__ "PetscDrawXiSetWindowLabel"
264 PetscErrorCode PetscDrawXiSetWindowLabel(PetscDraw_X *XiWin,char *label)
265 {
266   XTextProperty  prop;
267   size_t         len;
268   PetscErrorCode ierr;
269 
270   PetscFunctionBegin;
271   ierr = PetscStrlen(label,&len);CHKERRQ(ierr);
272   XGetWMName(XiWin->disp,XiWin->win,&prop);
273   prop.value  = (unsigned char*)label;
274   prop.nitems = (long)len;
275   XSetWMName(XiWin->disp,XiWin->win,&prop);
276   PetscFunctionReturn(0);
277 }
278 
279 #undef __FUNCT__
280 #define __FUNCT__ "PetscDrawXiSetToBackground"
281 PetscErrorCode PetscDrawXiSetToBackground(PetscDraw_X *XiWin)
282 {
283   PetscFunctionBegin;
284   if (XiWin->gc.cur_pix != XiWin->background) {
285     XSetForeground(XiWin->disp,XiWin->gc.set,XiWin->background);
286     XiWin->gc.cur_pix = XiWin->background;
287   }
288   PetscFunctionReturn(0);
289 
290 }
291 
292 #undef __FUNCT__
293 #define __FUNCT__ "PetscDrawSetSave_X"
294 PetscErrorCode  PetscDrawSetSave_X(PetscDraw draw,const char *filename)
295 {
296   PetscErrorCode ierr;
297 #if defined(PETSC_HAVE_POPEN)
298   PetscMPIInt    rank;
299 #endif
300 
301   PetscFunctionBegin;
302   PetscValidHeaderSpecific(draw,PETSC_DRAW_CLASSID,1);
303 #if defined(PETSC_HAVE_POPEN)
304   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
305   if (!rank) {
306     char  command[PETSC_MAX_PATH_LEN];
307     FILE  *fd;
308     int   err;
309 
310     ierr = PetscMemzero(command,sizeof(command));CHKERRQ(ierr);
311     ierr = PetscSNPrintf(command,PETSC_MAX_PATH_LEN,"rm -fr %s %s.m4v",draw->savefilename,draw->savefilename);CHKERRQ(ierr);
312     ierr = PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fd);CHKERRQ(ierr);
313     ierr = PetscPClose(PETSC_COMM_SELF,fd,&err);CHKERRQ(ierr);
314     ierr = PetscSNPrintf(command,PETSC_MAX_PATH_LEN,"mkdir %s",draw->savefilename);CHKERRQ(ierr);
315     ierr = PetscPOpen(PETSC_COMM_SELF,NULL,command,"r",&fd);CHKERRQ(ierr);
316     ierr = PetscPClose(PETSC_COMM_SELF,fd,&err);CHKERRQ(ierr);
317   }
318 #endif
319   PetscFunctionReturn(0);
320 }
321 
322 
323 #if defined(PETSC_HAVE_AFTERIMAGE)
324 #include <afterimage.h>
325 
326 /* String names of possible Afterimage formats */
327 const char *PetscAfterImageFormats[] = {
328         ".Xpm",
329 	".Xpm.Z",
330 	".Xpm.gz",
331 	".Png",
332 	".Jpeg",
333 	".Xcf", /* Gimp format */
334 	".Ppm",
335 	".Pnm",
336 	"MS Windows Bitmap",
337 	"MS Windows Icon",
338 	"MS Windows Cursor",
339 	".Gif",
340 	".Tiff",
341 	"Afterstep XMLScript",
342 	"Scalable Vector Graphics (SVG)",
343 	".Xbm",
344 	"Targa",
345 	".Pcx",
346 	".HTML",
347 	"XML",
348 	"Unknown"
349 };
350 
351 #undef __FUNCT__
352 #define __FUNCT__ "PetscAfterimageStringToFormat"
353 static PetscErrorCode PetscAfterimageStringToFormat(const char *ext,ASImageFileTypes *format)
354 {
355   PetscInt       i;
356   PetscErrorCode ierr;
357   PetscBool      flg;
358 
359   PetscFunctionBegin;
360   ierr = PetscStrcasecmp(".Jpg",ext,&flg);CHKERRQ(ierr);
361   if (flg) ext = ".Jpeg";
362   for (i=0; i<sizeof(PetscAfterImageFormats)/sizeof(char**); i++) {
363     ierr = PetscStrcasecmp(PetscAfterImageFormats[i],ext,&flg);CHKERRQ(ierr);
364     if (flg) {
365       *format = (ASImageFileTypes)i;
366       PetscFunctionReturn(0);
367     }
368   }
369   *format = ASIT_Unknown;
370   PetscFunctionReturn(0);
371 }
372 
373 #if defined(PETSC_HAVE_SAWS)
374 #include <petscviewersaws.h>
375 /*
376   The PetscAfterimage object and functions are used to maintain a list of file images created by Afterimage that can
377   be displayed by the SAWs webserver.
378 */
379 typedef struct _P_PetscAfterimage *PetscAfterimage;
380 struct _P_PetscAfterimage {
381   PetscAfterimage next;
382   char            *filename;
383   char            *ext;
384   PetscInt        cnt;
385 } ;
386 
387 static PetscAfterimage afterimages = 0;
388 
389 #undef __FUNCT__
390 #define __FUNCT__ "PetscAfterimageDestroy"
391 static PetscErrorCode PetscAfterimageDestroy(void)
392 {
393   PetscErrorCode ierr;
394   PetscAfterimage       afterimage,oafterimage = afterimages;
395 
396   PetscFunctionBegin;
397   while (oafterimage) {
398     afterimage = oafterimage->next;
399     ierr = PetscFree(oafterimage->filename);CHKERRQ(ierr);
400     ierr = PetscFree(oafterimage->ext);CHKERRQ(ierr);
401     ierr = PetscFree(oafterimage);CHKERRQ(ierr);
402     oafterimage = afterimage;
403   }
404   PetscFunctionReturn(0);
405 }
406 
407 #undef __FUNCT__
408 #define __FUNCT__ "PetscAfterimageAdd"
409 static PetscErrorCode PetscAfterimageAdd(const char *filename,const char *ext,PetscInt cnt)
410 {
411   PetscErrorCode   ierr;
412   PetscAfterimage  afterimage,oafterimage = afterimages;
413   PetscBool        flg;
414 
415   PetscFunctionBegin;
416   if (oafterimage){
417     ierr = PetscStrcmp(filename,oafterimage->filename,&flg);CHKERRQ(ierr);
418     if (flg) {
419       oafterimage->cnt = cnt;
420       PetscFunctionReturn(0);
421     }
422     while (oafterimage->next) {
423       oafterimage = oafterimage->next;
424       ierr = PetscStrcmp(filename,oafterimage->filename,&flg);CHKERRQ(ierr);
425       if (flg) {
426         oafterimage->cnt = cnt;
427         PetscFunctionReturn(0);
428       }
429     }
430     ierr = PetscNew(&afterimage);CHKERRQ(ierr);
431     oafterimage->next = afterimage;
432   } else {
433     ierr = PetscNew(&afterimage);CHKERRQ(ierr);
434     afterimages = afterimage;
435   }
436   ierr = PetscStrallocpy(filename,&afterimage->filename);CHKERRQ(ierr);
437   ierr = PetscStrallocpy(ext,&afterimage->ext);CHKERRQ(ierr);
438   afterimage->cnt = cnt;
439   ierr = PetscRegisterFinalize(PetscAfterimageDestroy);CHKERRQ(ierr);
440   PetscFunctionReturn(0);
441 }
442 
443 #endif
444 
445 #undef __FUNCT__
446 #define __FUNCT__ "PetscDrawSave_X"
447 PetscErrorCode PetscDrawSave_X(PetscDraw draw)
448 {
449   PetscDraw_X      *drawx = (PetscDraw_X*)draw->data;
450   XImage           *image;
451   ASImage          *asimage;
452   struct  ASVisual *asv;
453   char             filename[PETSC_MAX_PATH_LEN];
454   PetscErrorCode   ierr;
455   PetscMPIInt      rank;
456   int              depth;
457   ASImageFileTypes format;
458 
459   PetscFunctionBegin;
460   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)draw),&rank);CHKERRQ(ierr);
461   if (rank) PetscFunctionReturn(0);
462   if (!draw->savefilename) PetscFunctionReturn(0);
463   if (draw->savefilecount == -1) {
464     /* The first PetscDrawClear() should happen before any drawing has been done, hence do not save at the first PetscDrawClear() */
465     draw->savefilecount++;
466     PetscFunctionReturn(0);
467   }
468   XSynchronize(drawx->disp, True);
469   depth = DefaultDepth( drawx->disp, drawx->screen );
470   asv   = create_asvisual(drawx->disp, drawx->screen, depth, NULL);if (!asv) SETERRQ(PetscObjectComm((PetscObject)draw),PETSC_ERR_PLIB,"Cannot create AfterImage ASVisual");
471 
472   image   = XGetImage(drawx->disp, drawx->drw ? drawx->drw : drawx->win, 0, 0, drawx->w, drawx->h, AllPlanes, ZPixmap);
473   if (!image) SETERRQ(PetscObjectComm((PetscObject)draw),PETSC_ERR_PLIB,"Cannot XGetImage()");
474   asimage = picture_ximage2asimage (asv,image,0,0);if (!asimage) SETERRQ(PetscObjectComm((PetscObject)draw),PETSC_ERR_PLIB,"Cannot create AfterImage ASImage");
475   if (draw->savesinglefile) {
476     ierr    = PetscSNPrintf(filename,PETSC_MAX_PATH_LEN,"%s/%s%s",draw->savefilename,draw->savefilename,draw->savefilenameext);CHKERRQ(ierr);
477   } else {
478     ierr    = PetscSNPrintf(filename,PETSC_MAX_PATH_LEN,"%s/%s_%d%s",draw->savefilename,draw->savefilename,draw->savefilecount++,draw->savefilenameext);CHKERRQ(ierr);
479   }
480   ierr = PetscAfterimageStringToFormat(draw->savefilenameext,&format);CHKERRQ(ierr);
481   ASImage2file(asimage, 0, filename,format,0);
482 #if defined(PETSC_HAVE_SAWS)
483   {
484     char     body[4096];
485     PetscAfterimage afterimage;
486     size_t   len = 0;
487 
488     ierr = PetscAfterimageAdd(draw->savefilename,draw->savefilenameext,draw->savefilecount-1);CHKERRQ(ierr);
489     afterimage  = afterimages;
490     while (afterimage) {
491       if (draw->savesinglefile) {
492         ierr = PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s%s\" alt=\"None\">",afterimage->filename,afterimage->filename,afterimage->ext);CHKERRQ(ierr);
493       } else {
494         ierr = PetscSNPrintf(body+len,4086-len,"<img src=\"%s/%s_%d%s\" alt=\"None\">",afterimage->filename,afterimage->filename,afterimage->cnt,afterimage->ext);CHKERRQ(ierr);
495       }
496       ierr = PetscStrlen(body,&len);CHKERRQ(ierr);
497       afterimage  = afterimage->next;
498     }
499     ierr = PetscStrcat(body,"<br>\n");CHKERRQ(ierr);
500     if (draw->savefilecount > 0) PetscStackCallSAWs(SAWs_Pop_Body,("index.html",1));
501     PetscStackCallSAWs(SAWs_Push_Body,("index.html",1,body));
502   }
503 #endif
504 
505   XDestroyImage(image);
506   destroy_asvisual(asv,0);
507   PetscFunctionReturn(0);
508 }
509 /*
510    There are routines wanted by AfterImage for PNG files
511  */
512 void crc32(void) {;}
513 void inflateReset(void) {;}
514 void deflateReset(void) {;}
515 void deflateInit2(void) {;}
516 void deflateInit2_(void) {;}
517 void deflate(void) {;}
518 void deflateEnd(void) {;}
519 
520 #endif
521 
522 
523 
524