00001 #include "coxplot.h"
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 static Display * old_dpy = NULL ;
00013 static X11_colordef * old_cd = NULL ;
00014 static Window old_w = (Window) 0 ;
00015 static GC old_GC ;
00016
00017
00018
00019
00020
00021
00022
00023 static void setup_X11_plotting( Display * dpy , Window w )
00024 {
00025 XGCValues gcv;
00026
00027 if( old_dpy == dpy ){ old_w = w ; return ; }
00028
00029 FREE_X11_colordef(old_cd) ;
00030 old_cd = get_X11_colordef( dpy , w ) ;
00031
00032 if( old_dpy != NULL ) XFreeGC( old_dpy , old_GC ) ;
00033 gcv.function = GXcopy ;
00034 gcv.fill_style = FillSolid ;
00035 old_GC = XCreateGC( dpy , w , GCFunction|GCFillStyle , &gcv ) ;
00036
00037 old_dpy = dpy ; old_w = getwin_from_XDBE(dpy,w) ;
00038 return ;
00039 }
00040
00041
00042
00043
00044
00045
00046
00047 void set_X11_background( Display * dpy , Window w ,
00048 unsigned char rr , unsigned char gg , unsigned char bb )
00049 {
00050 unsigned long pix ;
00051
00052 if( dpy == NULL || w == (Window) 0 ) return ;
00053
00054 setup_X11_plotting( dpy , w ) ;
00055 pix = rgb_to_pixel( rr,gg,bb , old_cd ) ;
00056 XSetWindowBackground( dpy , getwin_from_XDBE(dpy,w) , pix ) ;
00057 return ;
00058 }
00059
00060
00061
00062
00063
00064
00065
00066
00067 static int box_xbot=0 , box_xtop=0 ,
00068 box_ybot=0 , box_ytop=0 ;
00069
00070 void set_memplot_X11_box( int xbot, int ybot, int xtop, int ytop )
00071 {
00072 if( xbot < xtop && ybot < ytop ){
00073 box_xbot = xbot ; box_ybot = ybot ;
00074 box_xtop = xtop ; box_ytop = ytop ;
00075 } else {
00076 box_xbot = box_ybot = box_xtop = box_ytop = 0 ;
00077 }
00078 }
00079
00080
00081
00082
00083
00084
00085
00086 static void drawable_geom( Display *dpy , Drawable ddd ,
00087 int *width , int *height , int *depth )
00088 {
00089 int xx,yy ;
00090 unsigned int ww,hh,bb,dd ;
00091 Window rr ;
00092
00093 XGetGeometry( dpy,ddd , &rr,&xx,&yy,&ww,&hh,&bb,&dd ) ;
00094
00095 if( width != NULL ) *width = ww ;
00096 if( height != NULL ) *height = hh ;
00097 if( depth != NULL ) *depth = dd ;
00098 }
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111 #ifdef LMAX
00112 #undef LMAX
00113 #endif
00114 #define LMAX 1023
00115
00116 static XSegment xseg[LMAX] ;
00117 static int nseg = 0 ;
00118
00119 static void draw_xseg(void) ;
00120
00121 void memplot_to_X11_sef( Display * dpy , Window w , MEM_plotdata * mp ,
00122 int start , int end , int mask )
00123 {
00124 int ii , nline , same ;
00125 float old_thick , old_color , new_color , new_thick ;
00126 float scal,xscal,yscal , xoff,yoff ;
00127 short x1,y1 , x2,y2 ;
00128 int skip ;
00129 int w_width, w_height, w_depth ;
00130 XGCValues gcv ;
00131
00132 int freee = (mask & MEMPLOT_FREE_ASPECT) != 0 ;
00133 int erase = (mask & MEMPLOT_ERASE ) != 0 ;
00134
00135
00136
00137 if( dpy == NULL || w == (Window) 0 || mp == NULL ) return ;
00138 if( start < 0 ) start = 0 ;
00139
00140 nline = MEMPLOT_NLINE(mp) ;
00141 if( nline < 1 || start >= nline ) return ;
00142
00143 if( end <= start || end > nline ) end = nline ;
00144
00145
00146
00147
00148
00149 setup_X11_plotting( dpy , w ) ;
00150
00151
00152
00153 drawable_geom( dpy, getwin_from_XDBE(dpy,w), &w_width,&w_height,&w_depth ) ;
00154
00155 if( w_depth != old_cd->depth ) return ;
00156
00157
00158
00159
00160 if( box_xbot >= box_xtop || box_ybot >= box_ytop ){
00161
00162 xscal = (w_width -0.001) / mp->aspect ;
00163 yscal = (w_height-0.001) / 1.0 ;
00164 xoff = yoff = 0.0 ;
00165
00166 } else {
00167
00168 xscal = box_xtop - box_xbot ;
00169 yscal = box_ytop - box_ybot ;
00170 xoff = box_xbot + 0.0 ;
00171 yoff = box_ybot + 0.0 ;
00172 }
00173
00174 if( !freee ){
00175 if( yscal < xscal ) xscal = yscal ;
00176 else yscal = xscal ;
00177 }
00178 scal = sqrt(fabs(xscal*yscal)) ;
00179
00180 old_color = -1.0 ;
00181 old_thick = -THCODE_INVALID ;
00182
00183 if( erase ){
00184 float rr=1.0 , gg=1.0 , bb=1.0 ;
00185 unsigned long pix ;
00186 pix = rgb_to_pixel( ZO_TO_TFS(rr), ZO_TO_TFS(gg), ZO_TO_TFS(bb), old_cd ) ;
00187 XSetForeground( old_dpy , old_GC , pix ) ;
00188 }
00189
00190
00191
00192
00193 gcv.line_width = 0 ;
00194 gcv.join_style = JoinBevel ;
00195 XChangeGC( old_dpy , old_GC , GCLineWidth | GCJoinStyle , &gcv ) ;
00196
00197
00198
00199 for( ii=start ; ii < end ; ii++ ){
00200
00201 skip = 0 ;
00202
00203
00204
00205 new_color = MEMPLOT_COL(mp,ii) ;
00206 if( !erase && new_color != old_color ){
00207 float rr=COL_TO_RRR(new_color) ,
00208 gg=COL_TO_GGG(new_color) , bb=COL_TO_BBB(new_color) ;
00209 unsigned long pix ;
00210
00211 #if 0
00212 fprintf(stderr,"Changing color to %f %f %f\n",rr,gg,bb) ;
00213 #endif
00214
00215 draw_xseg() ;
00216
00217 pix = rgb_to_pixel( ZO_TO_TFS(rr), ZO_TO_TFS(gg), ZO_TO_TFS(bb), old_cd ) ;
00218 XSetForeground( old_dpy , old_GC , pix ) ;
00219 old_color = new_color ;
00220 }
00221
00222 new_thick = MEMPLOT_TH(mp,ii) ;
00223 if( new_thick < 0.0 ){
00224 int thc = (int)(-new_thick) ;
00225 switch( thc ){
00226
00227 case THCODE_RECT:{
00228 short xb,yb , xt,yt ;
00229 unsigned short w,h ;
00230 x1 = (short)( xoff + xscal * MEMPLOT_X1(mp,ii) ) ;
00231 x2 = (short)( xoff + xscal * MEMPLOT_X2(mp,ii) ) ;
00232 y1 = (short)( yoff + yscal * (1.0 - MEMPLOT_Y1(mp,ii)) ) ;
00233 y2 = (short)( yoff + yscal * (1.0 - MEMPLOT_Y2(mp,ii)) ) ;
00234 if( x1 < x2 ){ xb=x1; xt=x2; } else { xb=x2; xt=x1; }
00235 if( y1 < y2 ){ yb=y1; yt=y2; } else { yb=y2; yt=y1; }
00236 w = xt-xb ; h = yt-yb ;
00237 if( w || h )
00238 #if 0
00239 XFillRectangle( old_dpy,old_w,old_GC , xb,yb,w,h ) ;
00240 #else
00241 XDrawRectangle( old_dpy,old_w,old_GC , xb,yb,w,h ) ;
00242 #endif
00243 else
00244 XDrawPoint( old_dpy,old_w,old_GC , xb,yb ) ;
00245 skip = 1 ;
00246 }
00247 break ;
00248
00249 case THCODE_CIRC:{
00250 int xcor,ycor , xcen,ycen , xrad,yrad ;
00251 unsigned int ww, hh ;
00252 xcen = (int)(xoff + xscal * MEMPLOT_X1(mp,ii) );
00253 ycen = (int)(yoff + yscal * (1.0 - MEMPLOT_Y1(mp,ii)) );
00254 xrad = (int)( xscal * MEMPLOT_X2(mp,ii) );
00255 yrad = (int)( yscal * MEMPLOT_X2(mp,ii) );
00256 xcor = xcen - xrad ; ww = 2*xrad ;
00257 ycor = ycen - yrad ; hh = 2*yrad ;
00258 if( ww || hh )
00259 XDrawArc( old_dpy,old_w,old_GC , xcor,ycor,ww,hh , 0,360*64 ) ;
00260 else
00261 XDrawPoint( old_dpy,old_w,old_GC , xcor,ycor ) ;
00262 skip = 1 ;
00263 }
00264 break ;
00265 }
00266
00267 } else if( new_thick != old_thick ){
00268 int lw = scal * new_thick ;
00269 if( lw < 0 ) lw = 0 ;
00270 #if 0
00271 fprintf(stderr,"Changing thickness: old=%f new=%f\n",old_thick,new_thick) ;
00272 #endif
00273
00274 draw_xseg() ;
00275
00276 gcv.line_width = lw ;
00277 gcv.join_style = JoinBevel ;
00278 XChangeGC( old_dpy , old_GC , GCLineWidth | GCJoinStyle , &gcv ) ;
00279 old_thick = new_thick ;
00280 }
00281
00282 if( nseg == LMAX ) draw_xseg() ;
00283
00284
00285
00286
00287 if( !skip ){
00288 x1 = (short)( xoff + xscal * MEMPLOT_X1(mp,ii) ) ;
00289 x2 = (short)( xoff + xscal * MEMPLOT_X2(mp,ii) ) ;
00290 y1 = (short)( yoff + yscal * (1.0 - MEMPLOT_Y1(mp,ii)) ) ;
00291 y2 = (short)( yoff + yscal * (1.0 - MEMPLOT_Y2(mp,ii)) ) ;
00292
00293
00294
00295 xseg[nseg].x1 = x1 ; xseg[nseg].y1 = y1 ;
00296 xseg[nseg].x2 = x2 ; xseg[nseg].y2 = y2 ; nseg++ ;
00297 }
00298 }
00299
00300
00301
00302 draw_xseg() ;
00303 set_memplot_X11_box(0,0,0,0) ;
00304 return ;
00305 }
00306
00307
00308
00309 static void draw_xseg(void)
00310 {
00311 int jbot,jtop , ii,nj ;
00312 XPoint xpt[LMAX+1] ;
00313
00314 if( nseg <= 0 ) return ;
00315
00316 #if 0
00317 fprintf(stderr,"draw_xseg: %d segments input.\n",nseg) ;
00318 for( ii=0 ; ii < nseg ; ii++ )
00319 fprintf(stderr," %4d: x1=%4d y1=%4d x2=%4d y2=%4d\n",
00320 ii , xseg[ii].x1 , xseg[ii].y1 , xseg[ii].x2 , xseg[ii].y2 ) ;
00321 #endif
00322
00323 jbot = 0 ;
00324 while( jbot < nseg ){
00325
00326
00327
00328 jtop = jbot+1 ;
00329 while( jtop < nseg ){
00330
00331 if( xseg[jtop-1].x2 == xseg[jtop].x1
00332 && xseg[jtop-1].y2 == xseg[jtop].y1 ){ jtop++; continue; }
00333
00334 if( xseg[jtop-1].x2 == xseg[jtop].x2
00335 && xseg[jtop-1].y2 == xseg[jtop].y2 ){
00336
00337 ii = xseg[jtop].x2; xseg[jtop].x2 = xseg[jtop].x1; xseg[jtop].x1 = ii;
00338 ii = xseg[jtop].y2; xseg[jtop].y2 = xseg[jtop].y1; xseg[jtop].y1 = ii;
00339 jtop++; continue;
00340 }
00341
00342 break ;
00343 }
00344
00345
00346
00347
00348
00349 nj = jtop - jbot ;
00350 if( nj > 1 ){
00351 xpt[0].x = xseg[jbot].x1 ; xpt[0].y = xseg[jbot].y1 ;
00352 for( ii=0 ; ii < nj ; ii++ ){
00353 xpt[ii+1].x = xseg[jbot+ii].x2 ; xpt[ii+1].y = xseg[jbot+ii].y2 ;
00354 }
00355 XDrawLines( old_dpy,old_w,old_GC , xpt,nj+1 , CoordModeOrigin ) ;
00356
00357 #if 0
00358 fprintf(stderr,"draw_xseg: XDrawLines for %d\n",nj) ;
00359 #endif
00360
00361 jbot = jtop ; continue ;
00362 }
00363
00364
00365
00366
00367 while( jtop < nseg &&
00368 ( xseg[jtop-1].x2 != xseg[jtop].x1 ||
00369 xseg[jtop-1].y2 != xseg[jtop].y1 ) &&
00370 ( xseg[jtop-1].x2 != xseg[jtop].x2 ||
00371 xseg[jtop-1].y2 != xseg[jtop].y2 ) ) jtop++ ;
00372
00373
00374
00375 XDrawSegments( old_dpy,old_w,old_GC , xseg+jbot , jtop-jbot ) ;
00376
00377 #if 0
00378 fprintf(stderr,"draw_xseg: XDrawSegments for %d\n",jtop-jbot) ;
00379 #endif
00380
00381 jbot = jtop ; continue ;
00382 }
00383
00384 nseg = 0 ; return ;
00385 }
00386
00387
00388
00389
00390
00391
00392 static int highbit(unsigned long ul)
00393 {
00394 int i; unsigned long hb;
00395
00396 hb = 0x80; hb = hb << 24;
00397 for (i=31; ((ul & hb) == 0) && i>=0; i--, ul<<=1);
00398 return i;
00399 }
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409 unsigned long rgb_to_pixel( unsigned char rr , unsigned char gg ,
00410 unsigned char bb , X11_colordef * cd )
00411 {
00412
00413
00414 if( cd->classKRH == TrueColor ){
00415 unsigned long r , g , b , rgb ;
00416
00417 r = (cd->rrshift<0) ? (rr<<(-cd->rrshift))
00418 : (rr>>cd->rrshift) ; r = r & cd->rrmask ;
00419
00420 g = (cd->ggshift<0) ? (gg<<(-cd->ggshift))
00421 : (gg>>cd->ggshift) ; g = g & cd->ggmask ;
00422
00423 b = (cd->bbshift<0) ? (bb<<(-cd->bbshift))
00424 : (bb>>cd->bbshift) ; b = b & cd->bbmask ;
00425
00426 rgb = r | g | b ;
00427 return rgb ;
00428 }
00429
00430
00431
00432
00433
00434 #define RW 2
00435 #define GW 4
00436 #define BW 1
00437
00438 if( cd->classKRH == PseudoColor ){
00439 int ii , rdif,gdif,bdif,dif , ibest,dbest ;
00440
00441 rdif = cd->rr[0] - rr ;
00442 gdif = cd->gg[0] - gg ;
00443 bdif = cd->bb[0] - bb ; dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
00444 if( dif == 0 ) return 0 ;
00445
00446 ibest = 0 ; dbest = dif ;
00447 for( ii=1 ; ii < cd->ncolors ; ii++ ){
00448 rdif = cd->rr[ii] - rr ;
00449 gdif = cd->gg[ii] - gg ;
00450 bdif = cd->bb[ii] - bb ; dif = RW*abs(rdif)+GW*abs(gdif)+BW*abs(bdif) ;
00451 if( dif == 0 ) return ii ;
00452 if( dif < dbest ){ ibest = ii ; dbest = dif ; }
00453 }
00454 return ibest ;
00455 }
00456
00457
00458
00459 return 0 ;
00460 }
00461
00462
00463
00464 static volatile int xwasbad ;
00465
00466 typedef int (*xhandler)(Display *, XErrorEvent *) ;
00467
00468 static int qhandler( Display *dpy , XErrorEvent *xev )
00469 {
00470 xwasbad = 1 ; return 0 ;
00471 }
00472
00473
00474
00475
00476
00477
00478
00479 X11_colordef * get_X11_colordef( Display * display , Window w )
00480 {
00481 Status sss ;
00482 XWindowAttributes xwat ;
00483 XColor * xcol ;
00484 XVisualInfo vinfo , * vin ;
00485 X11_colordef * cd ;
00486 int count , ii ;
00487 xhandler old_handler ;
00488
00489
00490
00491 if( display == NULL || w == (Window) 0 ) return NULL ;
00492
00493
00494
00495
00496
00497
00498 xwat.depth = 0 ;
00499 old_handler = XSetErrorHandler(qhandler) ; xwasbad = 0 ;
00500
00501 XGetWindowAttributes( display, getwin_from_XDBE(display,w), &xwat ) ;
00502
00503 (void) XSetErrorHandler(old_handler) ;
00504
00505 if( xwasbad ){
00506 int xx,yy ; unsigned int ww,hh,bb,dd ; Window rr ;
00507 XGetGeometry( display,w , &rr,&xx,&yy,&ww,&hh,&bb,&dd ) ;
00508 XGetWindowAttributes( display, rr , &xwat ) ;
00509 }
00510 if( xwat.depth == 0 ) return NULL ;
00511
00512
00513
00514 vinfo.visualid = XVisualIDFromVisual(xwat.visual) ;
00515 vin = XGetVisualInfo( display , VisualIDMask , &vinfo , &count ) ;
00516 if( count == 0 || vin == NULL ) return NULL ;
00517
00518
00519 #if defined(__cplusplus) || defined(c_plusplus)
00520 if( vin->c_class == PseudoColor ){
00521 #else
00522 if( vin->class == PseudoColor ){
00523 #endif
00524 int iz ;
00525
00526
00527
00528 cd = (X11_colordef *) malloc( sizeof(X11_colordef) ) ;
00529 cd->classKRH = PseudoColor ;
00530 cd->depth = vin->depth ;
00531
00532
00533
00534 count = vin->colormap_size ;
00535 xcol = (XColor *) malloc( sizeof(XColor) * count ) ;
00536 for( ii=0 ; ii < count ; ii++ ) xcol[ii].pixel = ii ;
00537
00538 XQueryColors( display , xwat.colormap , xcol , count ) ;
00539
00540
00541
00542 cd->ncolors = count ;
00543 cd->rr = (unsigned char *) malloc( count ) ;
00544 cd->gg = (unsigned char *) malloc( count ) ;
00545 cd->bb = (unsigned char *) malloc( count ) ;
00546
00547 for( ii=0 ; ii < count ; ii++ ){
00548 cd->rr[ii] = xcol[ii].red >> 8 ;
00549 cd->gg[ii] = xcol[ii].green >> 8 ;
00550 cd->bb[ii] = xcol[ii].blue >> 8 ;
00551 }
00552
00553
00554
00555 for( iz=0 ; iz < count ; iz++ )
00556 if( cd->rr[iz] == 0 && cd->gg[iz] == 0 && cd->bb[iz] == 0 ) break ;
00557
00558 if( iz < count-1 ){
00559
00560 for( ii=count-1 ; ii > iz ; ii-- )
00561 if( cd->rr[ii] != 0 || cd->gg[ii] != 0 || cd->bb[ii] != 0 ) break ;
00562
00563 count = ii+1 ;
00564
00565 if( count == 1 ){
00566 free(xcol) ; XFree(vin) ; FREE_X11_colordef(cd) ; return NULL ;
00567 }
00568
00569 cd->ncolors = count ;
00570 }
00571
00572 free(xcol) ; XFree(vin) ; return cd ;
00573 }
00574
00575
00576 #if defined(__cplusplus) || defined(c_plusplus)
00577 if( vin->c_class == TrueColor ){
00578 #else
00579 if( vin->class == TrueColor ){
00580 #endif
00581
00582
00583
00584 cd = (X11_colordef *) malloc( sizeof(X11_colordef) ) ;
00585 cd->classKRH = TrueColor ;
00586 cd->depth = vin->depth ;
00587
00588 cd->rrmask = vin->red_mask ;
00589 cd->ggmask = vin->green_mask ;
00590 cd->bbmask = vin->blue_mask ;
00591 cd->rrshift = 7 - highbit(cd->rrmask) ;
00592 cd->ggshift = 7 - highbit(cd->ggmask) ;
00593 cd->bbshift = 7 - highbit(cd->bbmask) ;
00594
00595 cd->rr = cd->gg = cd->bb = NULL ;
00596
00597 XFree(vin) ; return cd ;
00598 }
00599
00600
00601
00602 XFree(vin) ; return NULL ;
00603 }
00604
00605 #ifdef HAVE_XDBE
00606
00607 void init_XDBE( Display * dpy )
00608 {
00609 int sss , ii , jj ;
00610 char * ec ;
00611
00612 if( use_xdbe >= 0 ) return ;
00613
00614 ec = getenv("AFNI_NO_XDBE") ;
00615 if( ec != NULL && (ec[0]=='Y' || ec[0]=='y') ){
00616 use_xdbe = 0 ;
00617 } else {
00618 sss = (int) XdbeQueryExtension( dpy , &ii , &jj ) ;
00619 use_xdbe = (sss != 0 ) ;
00620 }
00621 return ;
00622 }
00623
00624 Window getwin_from_XDBE( Display * dpy , Drawable w )
00625 {
00626 XdbeBackBufferAttributes * bat ;
00627 Window bw ;
00628
00629 if( w == (Window) 0 || use_xdbe <= 0 ) return w ;
00630
00631 bat = XdbeGetBackBufferAttributes( dpy , w ) ;
00632 bw = bat->window ; XFree(bat) ;
00633 if( bw == (Window) 0 ) bw = w ;
00634 return bw ;
00635 }
00636 #endif