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