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