00001
00002
00003
00004
00005
00006
00007 #include "mcw_graf.h"
00008
00009 #ifndef LABEL_ARG
00010 #define LABEL_ARG(str) \
00011 XtVaTypedArg , XmNlabelString , XmRString , (str) , strlen(str)+1
00012 #endif
00013
00014
00015
00016 #define GRAF_EXTRA 6
00017 #define GRAF_XTICK 16
00018 #define GRAF_NTICK 8
00019
00020
00021
00022 static char *get_popup_label( float,float,float,float , int,int ) ;
00023 static double clock_time(void) ;
00024
00025 MCW_graf * new_MCW_graf( Widget wpar , MCW_DC * dc , char * title ,
00026 gen_func * cbfunc , void * cbdata )
00027 {
00028 MCW_graf * gp ;
00029 Widget rcbox , wf ;
00030 XmString xstr ;
00031 char * curve_label[1] = { "Crv" } ;
00032 int ii ;
00033
00034 gp = myXtNew(MCW_graf) ;
00035
00036
00037
00038 gp->topform = XtVaCreateWidget(
00039 "dialog" , xmFormWidgetClass , wpar ,
00040 XmNinitialResourcesPersistent , False ,
00041 XmNtraversalOn , False ,
00042 NULL ) ;
00043
00044 if( title == NULL || title[0] == '\0' ) title = "Graphing" ;
00045 xstr = XmStringCreateLtoR( title , XmFONTLIST_DEFAULT_TAG );
00046 gp->toplabel = XtVaCreateManagedWidget(
00047 "dialog" , xmLabelWidgetClass , gp->topform ,
00048 XmNtopAttachment , XmATTACH_FORM ,
00049 XmNleftAttachment , XmATTACH_FORM ,
00050 XmNlabelString , xstr ,
00051 XmNrecomputeSize , False ,
00052 XmNmarginWidth , 0 ,
00053 XmNalignment , XmALIGNMENT_BEGINNING ,
00054 XmNinitialResourcesPersistent , False ,
00055 NULL ) ;
00056 XmStringFree(xstr) ;
00057
00058 wf = XtVaCreateWidget( "dialog" , xmFrameWidgetClass , gp->topform ,
00059 XmNshadowType , XmSHADOW_IN ,
00060 XmNshadowThickness , 4 ,
00061 XmNtopAttachment , XmATTACH_WIDGET ,
00062 XmNtopWidget , gp->toplabel ,
00063 XmNleftAttachment , XmATTACH_FORM ,
00064 XmNtraversalOn , False ,
00065 XmNinitialResourcesPersistent , False ,
00066 NULL ) ;
00067 gp->drawer = XtVaCreateManagedWidget(
00068 "dialog" , xmDrawingAreaWidgetClass , wf ,
00069 XmNwidth , GRAF_SIZE ,
00070 XmNheight , GRAF_SIZE + GRAF_EXTRA ,
00071 XmNtraversalOn , False ,
00072 XmNinitialResourcesPersistent , False ,
00073 NULL ) ;
00074 XtManageChild(wf) ;
00075
00076 XtInsertEventHandler( gp->drawer ,
00077
00078 0
00079 | ButtonPressMask
00080 | ExposureMask
00081 ,
00082 FALSE ,
00083 GRAF_drawing_EV ,
00084 (XtPointer) gp ,
00085 XtListTail ) ;
00086
00087
00088
00089 #ifdef BAD_BUTTON3_POPUPS
00090 gp->popmenu = XmCreatePopupMenu( gp->topform, "menu" , NULL , 0 ) ;
00091 #else
00092 gp->popmenu = XmCreatePopupMenu( gp->drawer , "menu" , NULL , 0 ) ;
00093 #endif
00094 gp->poplabel = XtVaCreateManagedWidget(
00095 "help" , xmLabelWidgetClass , gp->popmenu ,
00096 LABEL_ARG("I am a label") ,
00097 XmNinitialResourcesPersistent , False ,
00098 NULL ) ;
00099
00100 rcbox = XtVaCreateWidget(
00101 "dialog" , xmRowColumnWidgetClass , gp->topform ,
00102 XmNpacking , XmPACK_TIGHT ,
00103 XmNadjustLast , False ,
00104 XmNadjustMargin , False ,
00105 XmNnumColumns , 1 ,
00106 XmNtopAttachment , XmATTACH_WIDGET ,
00107 XmNtopWidget , gp->toplabel ,
00108 XmNleftAttachment , XmATTACH_WIDGET ,
00109 XmNleftWidget , wf ,
00110 XmNrightAttachment , XmATTACH_FORM ,
00111 XmNinitialResourcesPersistent , False ,
00112 NULL ) ;
00113
00114 gp->curve_bbox = new_MCW_bbox( rcbox ,
00115 1 , curve_label ,
00116 MCW_BB_check , MCW_BB_noframe ,
00117 GRAF_curve_CB , (XtPointer) gp ) ;
00118
00119 gp->handle_av = new_MCW_arrowval( rcbox , "#" ,
00120 MCW_AV_downup , 2,MAX_GHANDS,4 ,
00121 MCW_AV_notext , 0 ,
00122 GRAF_handle_CB , (XtPointer) gp ,
00123 NULL,NULL ) ;
00124
00125 gp->reset_pb = XtVaCreateManagedWidget(
00126 "dialog" , xmPushButtonWidgetClass , rcbox ,
00127 LABEL_ARG("Line") ,
00128 XmNalignment , XmALIGNMENT_CENTER ,
00129 XmNtraversalOn , False ,
00130 XmNinitialResourcesPersistent , False ,
00131 NULL ) ;
00132
00133 XtAddCallback( gp->reset_pb, XmNactivateCallback, GRAF_reset_CB , gp ) ;
00134
00135 XtManageChild( rcbox ) ;
00136 XtManageChild( gp->topform ) ;
00137
00138
00139
00140 gp->dc = dc ;
00141 gp->cbfunc = cbfunc ;
00142 gp->cbdata = cbdata ;
00143
00144 gp->fg = gp->bg = 0 ;
00145 gp->gwin = (Window) 0 ;
00146
00147 gp->nhands = 4;
00148 gp->spline = 0;
00149 gp->hands[0].x = 0; gp->hands[0].y = 0;
00150 gp->hands[1].x = 64; gp->hands[1].y = 64;
00151 gp->hands[2].x = 192; gp->hands[2].y = 192;
00152 gp->hands[3].x = 255; gp->hands[3].y = 255;
00153
00154 GenerateGrafFunc(gp,0);
00155 memcpy( gp->oldf , gp->func , sizeof(byte)*256 ) ;
00156 gp->yeqx = 1 ;
00157
00158 gp->xbot = gp->xtop = gp->ybot = gp->ytop = 0.0 ;
00159
00160 return gp ;
00161 }
00162
00163
00164
00165
00166
00167 void GRAF_put_setup( MCW_graf * gp , int nh , int * xh , int * yh , int spl )
00168 {
00169 int ii ;
00170
00171 if( gp == NULL ||
00172 nh < 2 || nh > MAX_GHANDS ||
00173 xh == NULL || yh == NULL ) return ;
00174
00175 gp->nhands = nh ;
00176 gp->spline = (spl != 0 ) ;
00177
00178 for( ii=0 ; ii < nh ; ii++ ){
00179 gp->hands[ii].x = xh[ii] ;
00180 gp->hands[ii].y = yh[ii] ;
00181 }
00182
00183 GenerateGrafFunc(gp,1) ; (void) GRAF_changed(gp) ;
00184 return ;
00185 }
00186
00187 void GRAF_get_setup( MCW_graf * gp , int * nh , int * xh , int * yh , int * spl )
00188 {
00189 int ii ;
00190
00191 if( gp == NULL || nh == NULL || xh == NULL || yh == NULL || spl == NULL ) return ;
00192
00193 *nh = gp->nhands ; *spl = gp->spline ;
00194
00195 for( ii=0 ; ii < gp->nhands ; ii++ ){
00196 xh[ii] = gp->hands[ii].x ;
00197 yh[ii] = gp->hands[ii].y ;
00198 }
00199 return ;
00200 }
00201
00202
00203
00204
00205
00206
00207
00208 int GRAF_changed( MCW_graf * gp )
00209 {
00210 int ii , cc=0 , yeqx=1 ;
00211
00212 for( ii=0 ; ii < 256 ; ii++ ){
00213 if( gp->oldf[ii] != gp->func[ii] ){ cc = 1 ; if( !yeqx ) break ; }
00214 if( yeqx && gp->func[ii] != ii ){ yeqx = 0 ; if( cc ) break ; }
00215 }
00216
00217 gp->yeqx = yeqx ;
00218 if( cc ) memcpy( gp->oldf , gp->func , sizeof(byte)*256 ) ;
00219 return cc ;
00220 }
00221
00222
00223
00224
00225
00226 void GRAF_drawing_EV( Widget w , XtPointer client_data ,
00227 XEvent * ev , Boolean * continue_to_dispatch )
00228 {
00229 MCW_graf * gp = (MCW_graf *) client_data ;
00230
00231 if( gp == NULL ) return ;
00232
00233
00234
00235 if( gp->bg == 0 && gp->fg == 0 ){
00236 XtVaGetValues( gp->drawer ,
00237 XmNforeground , &(gp->fg) ,
00238 XmNbackground , &(gp->bg) ,
00239 NULL ) ;
00240 gp->gwin = XtWindow(gp->drawer) ;
00241 }
00242
00243 switch( ev->type ){
00244
00245
00246
00247 case Expose:{
00248 XExposeEvent * event = (XExposeEvent *) ev ;
00249
00250 XSync( gp->dc->display , False ) ;
00251
00252 if( event->count == 0 ){
00253 if( w == gp->drawer ) drawGraf(gp,0) ;
00254 }
00255 }
00256 break ;
00257
00258
00259
00260 case ButtonPress:{
00261 XButtonEvent * event = (XButtonEvent *) ev ;
00262 Window rW,cW ;
00263 int mx,my , but , rx,ry ;
00264 int vertonly, x,y , orighx, orighy, grab,h , newx,newy ;
00265 unsigned int mask ;
00266
00267 int use_popup=0 , opx,opy ;
00268 double ct1,ct2 ;
00269
00270 #undef USE_MyCursor
00271 #ifdef USE_MyCursor
00272 static int need_MyCursor = 1 ;
00273 static Cursor MyCursor ;
00274
00275 if( need_MyCursor ){
00276 Pixmap pix;
00277 static char bits[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
00278 XColor cfg;
00279
00280 cfg.red = cfg.green = cfg.blue = 0;
00281 pix = XCreateBitmapFromData(gp->dc->display, gp->gwin, bits, 8, 8);
00282 MyCursor = XCreatePixmapCursor(gp->dc->display, pix, pix, &cfg, &cfg, 0,0);
00283 XFreePixmap(gp->dc->display, pix);
00284 need_MyCursor = 0 ;
00285 }
00286 #else
00287 # define MyCursor None
00288 #endif
00289
00290 but = event->button ;
00291 if( but == Button2 ) return ;
00292
00293
00294
00295 if( but == Button3 && gp->popmenu != NULL ){
00296 char *str = get_popup_label( gp->xbot,gp->xtop ,
00297 gp->ybot,gp->ytop ,
00298 event->x , event->y ) ;
00299 if( str != NULL ){
00300 MCW_set_widget_label( gp->poplabel , str ) ;
00301 XmMenuPosition( gp->popmenu , event ) ;
00302 XtManageChild ( gp->popmenu ) ;
00303 use_popup = 1 ; ct1 = clock_time() ;
00304 opx = event->x ; opy = event->y ;
00305 }
00306 }
00307
00308
00309
00310 mx = event->x ; my = event->y ;
00311
00312 for (h=0; h<gp->nhands; h++) {
00313 if (PTINRECT(mx*2,(127-my)*2,
00314 gp->hands[h].x-5,gp->hands[h].y-5,11,11)) break;
00315 }
00316
00317 if (h==gp->nhands) return ;
00318
00319
00320
00321 grab = !XGrabPointer(gp->dc->display,
00322 gp->gwin, False, 0, GrabModeAsync,
00323 GrabModeAsync, gp->gwin, MyCursor , (Time) CurrentTime);
00324
00325 orighx = gp->hands[h].x; orighy = gp->hands[h].y;
00326
00327 vertonly = (h==0 || h==(gp->nhands-1));
00328
00329
00330
00331 while( XQueryPointer(gp->dc->display,gp->gwin,&rW,&cW,&rx,&ry,&x,&y,&mask) ){
00332
00333 if( !(mask & Button1Mask) && !(mask & Button3Mask) ) break;
00334
00335
00336
00337
00338 newx = (vertonly) ? orighx : 2*x ;
00339 newy = (y >= 127) ? 0 : 255 - 2*y ;
00340
00341 if( !vertonly ){
00342 if( newx <= gp->hands[h-1].x ) newx = gp->hands[h-1].x + 1 ;
00343 if( newx >= gp->hands[h+1].x ) newx = gp->hands[h+1].x - 1 ;
00344 }
00345
00346 RANGE(newx, 0, 255);
00347 RANGE(newy, 0, 255);
00348
00349
00350 #if 1
00351 x = newx/2 ; y = (255-newy)/2 ;
00352 if( use_popup && (opx != x || opy != y) ){
00353 ct2 = clock_time() ;
00354 if( ct2-ct1 > 0.100 ){
00355 char *str = get_popup_label( gp->xbot,gp->xtop ,
00356 gp->ybot,gp->ytop , x,y ) ;
00357 ct1 = ct2 ; opx = x ; opy = y ;
00358 if( str != NULL ){
00359 MCW_set_widget_label( gp->poplabel , str ) ;
00360 XSync( XtDisplay(gp->drawer) , True ) ;
00361 XmUpdateDisplay( gp->drawer ) ;
00362 }
00363 }
00364 }
00365 #endif
00366
00367
00368
00369 if (newx != gp->hands[h].x || newy != gp->hands[h].y) {
00370
00371 DC_fg_colorpix( gp->dc , gp->bg ) ;
00372 XFillRectangle( gp->dc->display, gp->gwin, gp->dc->myGC ,
00373 (gp->hands[h].x/2)-3, ((255-gp->hands[h].y)/2)-3, 7,7);
00374
00375 gp->hands[h].x = newx; gp->hands[h].y = newy;
00376
00377 drawGraf(gp,1);
00378 GenerateGrafFunc(gp,0);
00379 drawGraf(gp,0);
00380
00381 }
00382
00383 }
00384
00385
00386
00387 if (grab) XUngrabPointer(gp->dc->display, (Time) CurrentTime);
00388
00389
00390
00391 #if 0
00392 if( GRAF_changed(gp) && gp->cbfunc != NULL ) gp->cbfunc(gp,gp->cbdata) ;
00393 #else
00394 if( GRAF_changed(gp) && gp->cbfunc != NULL )
00395 AFNI_CALL_VOID_2ARG( gp->cbfunc , MCW_graf *,gp , void *,gp->cbdata ) ;
00396 #endif
00397
00398 #if 1
00399 if( use_popup ){
00400 XtUnmanageChild( gp->popmenu ) ;
00401 MCW_expose_widget( gp->topform ) ;
00402 }
00403 #endif
00404 }
00405 break ;
00406
00407 }
00408
00409 return ;
00410 }
00411
00412
00413
00414
00415
00416 void drawGraf( MCW_graf * gp , int erase )
00417 {
00418 int i,x,y;
00419 XPoint pts[129], *pt;
00420 XSegment segs[GRAF_NTICK] , *sg ;
00421
00422
00423
00424 DC_fg_colorpix( gp->dc , (erase) ? gp->bg : gp->fg ) ;
00425
00426
00427
00428 for (i=0, pt=pts; i<256; i+=2,pt++) {
00429 pt->x = i/2; pt->y = 127 - (gp->func[i]/2);
00430 if (i==0) i = -1;
00431 }
00432 DC_linewidth( gp->dc , 2 ) ;
00433 XDrawLines( gp->dc->display , gp->gwin ,
00434 gp->dc->myGC , pts, 129, CoordModeOrigin );
00435 DC_linewidth( gp->dc , 0 ) ;
00436
00437 if (erase) return ;
00438
00439
00440
00441 DC_fg_colorpix( gp->dc , gp->bg ) ;
00442
00443 DC_linewidth( gp->dc , 1 ) ;
00444 for (i=0; i<gp->nhands; i++) {
00445 x = gp->hands[i].x/2; y = 127 - gp->hands[i].y/2;
00446 XFillRectangle(gp->dc->display, gp->gwin,
00447 gp->dc->myGC, x-2, y-2, 5,5);
00448 }
00449
00450
00451
00452 DC_fg_colorpix( gp->dc , gp->fg ) ;
00453
00454 for (i=0; i<gp->nhands; i++) {
00455 x = gp->hands[i].x/2; y = 127 - gp->hands[i].y/2;
00456 XDrawPoint(gp->dc->display, gp->gwin, gp->dc->myGC, x, y);
00457 }
00458
00459 for (i=0; i<gp->nhands; i++) {
00460 x = gp->hands[i].x/2; y = 127 - gp->hands[i].y/2;
00461 XDrawRectangle(gp->dc->display, gp->gwin, gp->dc->myGC, x-3, y-3, 6,6);
00462 }
00463 DC_linewidth( gp->dc , 0 ) ;
00464
00465
00466
00467 for( i=0,x=GRAF_XTICK,sg=segs ; x < GRAF_SIZE ; i++,sg++,x+=GRAF_XTICK ){
00468 sg->x1 = x ; sg->y1 = GRAF_SIZE+GRAF_EXTRA-1 ;
00469 sg->x2 = x ; sg->y2 = GRAF_SIZE ;
00470 }
00471 XDrawSegments( gp->dc->display , gp->gwin , gp->dc->myGC , segs , i ) ;
00472
00473 return ;
00474 }
00475
00476
00477
00478
00479
00480 void GRAF_curve_CB( Widget w, XtPointer client_data, XtPointer call_data )
00481 {
00482 MCW_graf * gp = (MCW_graf *) client_data ;
00483 int bval ;
00484
00485 bval = MCW_val_bbox( gp->curve_bbox ) ;
00486 if( bval == gp->spline ) return ;
00487
00488 gp->spline = bval ;
00489 GenerateGrafFunc(gp,1);
00490 #if 0
00491 if( GRAF_changed(gp) && gp->cbfunc != NULL ) gp->cbfunc(gp,gp->cbdata) ;
00492 #else
00493 if( GRAF_changed(gp) && gp->cbfunc != NULL )
00494 AFNI_CALL_VOID_2ARG( gp->cbfunc , MCW_graf *,gp , void *,gp->cbdata ) ;
00495 #endif
00496 return ;
00497 }
00498
00499
00500
00501
00502
00503 void GRAF_reset_CB( Widget w, XtPointer client_data, XtPointer call_data )
00504 {
00505 MCW_graf * gp = (MCW_graf *) client_data ;
00506 int j ;
00507
00508 for( j=0 ; j < gp->nhands ; j++ ) gp->hands[j].y = gp->hands[j].x ;
00509
00510 GenerateGrafFunc(gp,1);
00511 #if 0
00512 if( GRAF_changed(gp) && gp->cbfunc != NULL ) gp->cbfunc(gp,gp->cbdata) ;
00513 #else
00514 if( GRAF_changed(gp) && gp->cbfunc != NULL )
00515 AFNI_CALL_VOID_2ARG( gp->cbfunc , MCW_graf *,gp , void *,gp->cbdata ) ;
00516 #endif
00517 return ;
00518 }
00519
00520
00521
00522
00523
00524 void GRAF_set_func( MCW_graf * gp , byte * func )
00525 {
00526 int i ;
00527
00528 if( gp == NULL ) return ;
00529
00530 if( func != NULL ){
00531 for( i=0 ; i < 256 ; i++ ) gp->func[i] = func[i] ;
00532 } else {
00533 for( i=0 ; i < 256 ; i++ ) gp->func[i] = i ;
00534 }
00535
00536 for( i=0 ; i < gp->nhands ; i++ )
00537 gp->hands[i].y = gp->func[gp->hands[i].x] ;
00538
00539 (void) GRAF_changed(gp) ;
00540 drawGraf(gp,1); drawGraf(gp,0);
00541 return ;
00542 }
00543
00544
00545
00546
00547
00548 void GRAF_handle_CB( MCW_arrowval * av , XtPointer client_data )
00549 {
00550 MCW_graf * gp = (MCW_graf *) client_data ;
00551 int nh = av->ival , j ;
00552
00553 if( nh < 2 || nh > MAX_GHANDS || nh == gp->nhands ){
00554 XBell(gp->dc->display,100) ;
00555 return ;
00556 }
00557
00558 if( nh < gp->nhands ){
00559
00560
00561
00562
00563 int dist, mdist, mpos;
00564
00565 mdist = (gp->hands[1].x - gp->hands[0].x) +
00566 (gp->hands[2].x - gp->hands[1].x);
00567 mpos = 1;
00568
00569 for (j=2; j<gp->nhands-1; j++) {
00570 dist = (gp->hands[j ].x - gp->hands[j-1].x) +
00571 (gp->hands[j+1].x - gp->hands[j].x);
00572 if (dist < mdist) { mdist = dist; mpos = j; }
00573 }
00574
00575
00576
00577 xvbcopy( (char *) &gp->hands[mpos+1] ,
00578 (char *) &gp->hands[mpos] ,
00579 (gp->nhands-mpos-1) * sizeof(XPoint) ) ;
00580
00581 gp->nhands--;
00582
00583 } else if( nh > gp->nhands ){
00584
00585
00586
00587 int lgap, lpos, x, y;
00588
00589 lgap = gp->hands[1].x - gp->hands[0].x;
00590 lpos = 1;
00591 for (j=1; j<gp->nhands-1; j++)
00592 if ((gp->hands[j+1].x - gp->hands[j].x) > lgap) {
00593 lgap = gp->hands[j+1].x - gp->hands[j].x;
00594 lpos = j+1;
00595 }
00596
00597
00598
00599 xvbcopy( (char *) &gp->hands[lpos] ,
00600 (char *) &gp->hands[lpos+1] ,
00601 (gp->nhands - lpos) * sizeof(XPoint) ) ;
00602
00603 x = gp->hands[lpos-1].x + lgap/2;
00604 y = gp->func[x];
00605 gp->hands[lpos].x = x;
00606 gp->hands[lpos].y = y;
00607 gp->nhands++;
00608 }
00609
00610 GenerateGrafFunc(gp,1);
00611 #if 0
00612 if( GRAF_changed(gp) && gp->cbfunc != NULL ) gp->cbfunc(gp,gp->cbdata) ;
00613 #else
00614 if( GRAF_changed(gp) && gp->cbfunc != NULL )
00615 AFNI_CALL_VOID_2ARG( gp->cbfunc , MCW_graf *,gp , void *,gp->cbdata ) ;
00616 #endif
00617 return ;
00618 }
00619
00620
00621
00622
00623
00624 void GenerateGrafFunc( MCW_graf * gp , int redraw )
00625 {
00626 int i,j,k;
00627
00628
00629
00630 for (i=0; i<gp->nhands; i++) {
00631 RANGE(gp->hands[i].x, 0, 255);
00632 RANGE(gp->hands[i].y, 0, 255);
00633 }
00634
00635 gp->hands[0].x = 0; gp->hands[gp->nhands-1].x = 255;
00636 for (i=1; i<gp->nhands-1; i++) {
00637 if (gp->hands[i].x < i) gp->hands[i].x = i;
00638 if (gp->hands[i].x > 256-gp->nhands+i)
00639 gp->hands[i].x = 256-gp->nhands+i;
00640
00641 if (gp->hands[i].x <= gp->hands[i-1].x)
00642 gp->hands[i].x = gp->hands[i-1].x + 1;
00643 }
00644
00645
00646
00647 if (!gp->spline) {
00648 int y,x1,y1,x2,y2;
00649 double yd;
00650
00651 for (i=0; i<gp->nhands-1; i++) {
00652 x1 = gp->hands[ i ].x; y1 = gp->hands[ i ].y;
00653 x2 = gp->hands[i+1].x; y2 = gp->hands[i+1].y;
00654
00655 for (j=x1,k=0; j<=x2; j++,k++) {
00656 yd = ((double) k * (y2 - y1)) / (x2 - x1);
00657 y = y1 + (int) floor(yd + 0.5);
00658 RANGE(y,0,255);
00659 gp->func[j] = y;
00660 }
00661 }
00662 }
00663
00664 else {
00665 static int x[MAX_GHANDS], y[MAX_GHANDS];
00666 double yf[MAX_GHANDS];
00667 double yd;
00668
00669 for (i=0; i<gp->nhands; i++) {
00670 x[i] = gp->hands[i].x; y[i] = gp->hands[i].y;
00671 }
00672
00673 InitSpline(x, y, gp->nhands, yf);
00674
00675 for (i=0; i<256; i++) {
00676 yd = EvalSpline(x, y, yf, gp->nhands, (double) i);
00677 j = (int) floor(yd + 0.5);
00678 RANGE(j,0,255);
00679 gp->func[i] = j;
00680 }
00681 }
00682
00683 if (redraw) {
00684 XClearWindow( gp->dc->display, gp->gwin ) ;
00685 drawGraf(gp,0);
00686 }
00687 }
00688
00689
00690
00691 void InitSpline(int *x,int *y,int n,double *y2)
00692 {
00693
00694
00695
00696
00697 int i,k;
00698 double p,qn,sig,un,u[MAX_GHANDS];
00699
00700 y2[0] = u[0] = 0.0;
00701
00702 for (i=1; i<n-1; i++) {
00703 sig = ((double) x[i]-x[i-1]) / ((double) x[i+1] - x[i-1]);
00704 p = sig * y2[i-1] + 2.0;
00705 y2[i] = (sig-1.0) / p;
00706 u[i] = (((double) y[i+1]-y[i]) / (x[i+1]-x[i])) -
00707 (((double) y[i]-y[i-1]) / (x[i]-x[i-1]));
00708 u[i] = (6.0 * u[i]/(x[i+1]-x[i-1]) - sig*u[i-1]) / p;
00709 }
00710 qn = un = 0.0;
00711
00712 y2[n-1] = (un-qn*u[n-2]) / (qn*y2[n-2]+1.0);
00713 for (k=n-2; k>=0; k--)
00714 y2[k] = y2[k]*y2[k+1]+u[k];
00715 }
00716
00717
00718
00719 extern void FatalError(char * str);
00720
00721 double EvalSpline(int xa[],int ya[],double y2a[],int n,double x)
00722 {
00723 int klo,khi,k;
00724 double h,b,a;
00725
00726 klo = 0;
00727 khi = n-1;
00728 while (khi-klo > 1) {
00729 k = (khi+klo) >> 1;
00730 if (xa[k] > x) khi = k;
00731 else klo = k;
00732 }
00733 h = xa[khi] - xa[klo];
00734 if (h==0.0) FatalError("bad xvalues in splint\n");
00735 a = (xa[khi]-x)/h;
00736 b = (x-xa[klo])/h;
00737 return (a*ya[klo] + b*ya[khi] + ((a*a*a-a)*y2a[klo] +(b*b*b-b)*y2a[khi])
00738 * (h*h) / 6.0);
00739 }
00740
00741
00742
00743
00744 void xvbcopy(char * src, char * dst, size_t len)
00745 {
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755 if (src==dst || len<=0) return;
00756
00757 if (src<dst && src+len>dst) {
00758 src = src + len - 1;
00759 dst = dst + len - 1;
00760 for ( ; len>0; len--, src--, dst--) *dst = *src;
00761 }
00762
00763 else {
00764
00765 for ( ; len>0; len--, src++, dst++) *dst = *src;
00766 }
00767
00768 return ;
00769 }
00770
00771
00772
00773
00774
00775 MCW_pasgraf * new_MCW_pasgraf( Widget wpar , MCW_DC * dc , char * title )
00776 {
00777 MCW_pasgraf * gp ;
00778 Widget wf ;
00779 XmString xstr ;
00780
00781 gp = myXtNew(MCW_pasgraf) ;
00782
00783
00784
00785 gp->topform = XtVaCreateWidget(
00786 "dialog" , xmFormWidgetClass , wpar ,
00787 XmNinitialResourcesPersistent , False ,
00788 XmNtraversalOn , False ,
00789 NULL ) ;
00790
00791 if( title == NULL || title[0] == '\0' ) title = "Graphing" ;
00792 xstr = XmStringCreateLtoR( title , XmFONTLIST_DEFAULT_TAG );
00793 gp->toplabel = XtVaCreateManagedWidget(
00794 "dialog" , xmLabelWidgetClass , gp->topform ,
00795 XmNtopAttachment , XmATTACH_FORM ,
00796 XmNleftAttachment , XmATTACH_FORM ,
00797 XmNlabelString , xstr ,
00798 XmNrecomputeSize , False ,
00799 XmNmarginWidth , 0 ,
00800 XmNalignment , XmALIGNMENT_BEGINNING ,
00801 XmNinitialResourcesPersistent , False ,
00802 NULL ) ;
00803 XmStringFree(xstr) ;
00804
00805 wf = XtVaCreateWidget( "dialog" , xmFrameWidgetClass , gp->topform ,
00806 XmNshadowType , XmSHADOW_IN ,
00807 XmNshadowThickness , 4 ,
00808 XmNtopAttachment , XmATTACH_WIDGET ,
00809 XmNtopWidget , gp->toplabel ,
00810 XmNleftAttachment , XmATTACH_FORM ,
00811 XmNtraversalOn , False ,
00812 XmNinitialResourcesPersistent , False ,
00813 NULL ) ;
00814 gp->drawer = XtVaCreateManagedWidget(
00815 "dialog" , xmDrawingAreaWidgetClass , wf ,
00816 XmNwidth , GRAF_SIZE ,
00817 XmNheight , GRAF_SIZE + GRAF_EXTRA ,
00818 XmNtraversalOn , False ,
00819 XmNinitialResourcesPersistent , False ,
00820 NULL ) ;
00821 XtManageChild(wf) ;
00822
00823 XtInsertEventHandler( gp->drawer ,
00824
00825 0
00826 | ButtonPressMask
00827 | ExposureMask
00828 ,
00829 FALSE ,
00830 GRAF_pasdrawing_EV ,
00831 (XtPointer) gp ,
00832 XtListTail ) ;
00833
00834
00835
00836 #ifdef BAD_BUTTON3_POPUPS
00837 gp->popmenu = XmCreatePopupMenu( gp->topform, "menu" , NULL , 0 ) ;
00838 #else
00839 gp->popmenu = XmCreatePopupMenu( gp->drawer , "menu" , NULL , 0 ) ;
00840 #endif
00841 gp->poplabel = XtVaCreateManagedWidget(
00842 "help" , xmLabelWidgetClass , gp->popmenu ,
00843 LABEL_ARG("I am a label") ,
00844 XmNinitialResourcesPersistent , False ,
00845 NULL ) ;
00846
00847 XtManageChild( gp->topform ) ;
00848
00849
00850
00851 gp->dc = dc ; gp->mode = PASGRAF_LINE ;
00852
00853 gp->fg = gp->bg = 0 ;
00854 gp->gwin = (Window) 0 ;
00855
00856 gp->xbot = gp->xtop = gp->ybot = gp->ytop = 0.0 ;
00857
00858 return gp ;
00859 }
00860
00861
00862
00863
00864
00865 void GRAF_pasdrawing_EV( Widget w , XtPointer client_data ,
00866 XEvent * ev , Boolean * continue_to_dispatch )
00867 {
00868 MCW_pasgraf * gp = (MCW_pasgraf *) client_data ;
00869
00870 if( gp == NULL ) return ;
00871
00872
00873
00874 if( gp->bg == 0 && gp->fg == 0 ){
00875 XtVaGetValues( gp->drawer ,
00876 XmNforeground , &(gp->fg) ,
00877 XmNbackground , &(gp->bg) ,
00878 NULL ) ;
00879 gp->gwin = XtWindow(gp->drawer) ;
00880 }
00881
00882 switch( ev->type ){
00883
00884
00885
00886 case Expose:{
00887 XExposeEvent * event = (XExposeEvent *) ev ;
00888
00889 XSync( gp->dc->display , False ) ;
00890
00891 if( event->count == 0 ){
00892 if( w == gp->drawer ) redraw_MCW_pasgraf(gp) ;
00893 }
00894 }
00895 break ;
00896
00897
00898
00899 case ButtonPress:{
00900 XButtonEvent * event = (XButtonEvent *) ev ;
00901 int mx,my , but ;
00902
00903 but = event->button ;
00904
00905
00906
00907 if( but == Button3 && gp->popmenu != NULL ){
00908 char *str = get_popup_label( gp->xbot,gp->xtop ,
00909 gp->ybot,gp->ytop ,
00910 event->x , event->y ) ;
00911 if( str != NULL ){
00912 MCW_set_widget_label( gp->poplabel , str ) ;
00913 XmMenuPosition( gp->popmenu , event ) ;
00914 XtManageChild ( gp->popmenu ) ;
00915 }
00916 }
00917
00918 if( but != Button1 ) return ;
00919 mx = event->x ; my = event->y ;
00920
00921 NEXT_PASGRAF_MODE(gp) ;
00922 redraw_MCW_pasgraf(gp) ;
00923 }
00924 break ;
00925 }
00926
00927 return ;
00928 }
00929
00930 void redraw_MCW_pasgraf( MCW_pasgraf * gp )
00931 {
00932 XPoint pts[GRAF_SIZE], *pt ;
00933 XSegment segs[GRAF_SIZE] , *sg ;
00934 int i , x ;
00935
00936 if( gp->gwin == (Window) 0 ) return ;
00937
00938 XClearWindow( gp->dc->display, gp->gwin ) ;
00939
00940 DC_fg_colorpix( gp->dc , gp->fg ) ;
00941
00942 switch( gp->mode ){
00943
00944 default:
00945 case PASGRAF_LINE:{
00946
00947 for( i=0, pt=pts ; i < GRAF_SIZE ; i++ , pt++ ){
00948 pt->x = i ; pt->y = GRAF_SIZE - gp->func[i] ;
00949 }
00950 XDrawLines( gp->dc->display , gp->gwin ,
00951 gp->dc->myGC , pts, GRAF_SIZE, CoordModeOrigin );
00952 }
00953 break ;
00954
00955 case PASGRAF_BAR:{
00956
00957 for( i=0, sg=segs ; i < GRAF_SIZE ; i++ , sg++ ){
00958 sg->x1 = i ; sg->y1 = GRAF_SIZE - 1 ;
00959 sg->x2 = i ; sg->y2 = GRAF_SIZE - 1 - gp->func[i] ;
00960 }
00961 XDrawSegments( gp->dc->display , gp->gwin ,
00962 gp->dc->myGC , segs , GRAF_SIZE ) ;
00963 }
00964 break ;
00965 }
00966
00967
00968
00969 for( i=0,x=GRAF_XTICK,sg=segs ; x < GRAF_SIZE ; i++,sg++,x+=GRAF_XTICK ){
00970 sg->x1 = x ; sg->y1 = GRAF_SIZE+GRAF_EXTRA-1 ;
00971 sg->x2 = x ; sg->y2 = GRAF_SIZE ;
00972 }
00973 XDrawSegments( gp->dc->display , gp->gwin , gp->dc->myGC , segs , i ) ;
00974
00975 return ;
00976 }
00977
00978
00979
00980
00981
00982 void set_MCW_pasgraf( MCW_pasgraf * gp , byte * func )
00983 {
00984 int i ;
00985 byte b ;
00986
00987 if( gp == NULL ) return ;
00988
00989 if( func != NULL ){
00990 for( i=0 ; i < GRAF_SIZE ; i++ ){
00991 b = func[i] ;
00992 gp->func[i] = (b < GRAF_SIZE) ? b : (GRAF_SIZE-1) ;
00993 }
00994 } else {
00995 memset( gp->func , 0 , sizeof(byte)*GRAF_SIZE ) ;
00996 }
00997
00998 return ;
00999 }
01000
01001 void MCW_histo_bytes( int nb , byte * bar , int * har )
01002 {
01003 int i ;
01004
01005 if( nb <= 0 || bar == NULL || har == NULL ) return ;
01006
01007 for( i=0 ; i < 256 ; i++ ) har[i] = 0 ;
01008
01009 for( i=0 ; i < nb ; i++ ) har[ bar[i] ]++ ;
01010
01011 return ;
01012 }
01013
01014
01015
01016
01017 void PASGRAF_set_xyrange( MCW_pasgraf *gp , float xb,float xt, float yb,float yt )
01018 {
01019 if( gp == NULL ) return ;
01020 gp->xbot = xb ; gp->xtop = xt ;
01021 gp->ybot = yb ; gp->ytop = yt ;
01022 }
01023
01024
01025
01026 void GRAF_set_xyrange( MCW_graf *gp , float xb,float xt, float yb,float yt )
01027 {
01028 if( gp == NULL ) return ;
01029 gp->xbot = xb ; gp->xtop = xt ;
01030 gp->ybot = yb ; gp->ytop = yt ;
01031 }
01032
01033
01034
01035 static char *get_popup_label( float xbot,float xtop ,
01036 float ybot,float ytop , int x,int y )
01037 {
01038 static char str[128] ;
01039 char xbuf[32],ybuf[32] , *xb,*yb ;
01040 float xx , yy , ff ;
01041
01042 if( x < 0 ) x = 0 ;
01043 else if( x >= GRAF_SIZE ) x = GRAF_SIZE-1 ;
01044 if( y < 0 ) y = 0 ;
01045 else if( y >= GRAF_SIZE ) y = GRAF_SIZE-1 ;
01046
01047 if( xtop != xbot ){
01048 ff = x / (float)(GRAF_SIZE-1) ;
01049 xx = ff*xtop + (1.0-ff)*xbot ;
01050 } else {
01051 xx = x ;
01052 }
01053
01054 if( ytop != ybot ){
01055 ff = y / (float)(GRAF_SIZE-1) ;
01056 yy = ff*ybot + (1.0-ff)*ytop ;
01057 } else {
01058 yy = GRAF_SIZE-1 - y ;
01059 }
01060
01061 AV_fval_to_char( xx,xbuf ); xb = xbuf; if( *xb == ' ' ) xb++;
01062 AV_fval_to_char( yy,ybuf ); yb = ybuf; if( *yb == ' ' ) yb++;
01063 sprintf(str,"%s,%s",xb,yb) ;
01064 return str ;
01065 }
01066
01067
01068
01069 static double clock_time(void)
01070 {
01071 struct timeval new_tval ;
01072 struct timezone tzone ;
01073 static struct timeval old_tval ;
01074 static int first = 1 ;
01075
01076 gettimeofday( &new_tval , &tzone ) ;
01077
01078 if( first ){
01079 old_tval = new_tval ;
01080 first = 0 ;
01081 return 0.0 ;
01082 }
01083
01084 if( old_tval.tv_usec > new_tval.tv_usec ){
01085 new_tval.tv_usec += 1000000 ;
01086 new_tval.tv_sec -- ;
01087 }
01088
01089 return (double)( (new_tval.tv_sec - old_tval.tv_sec )
01090 +(new_tval.tv_usec - old_tval.tv_usec)*1.0e-6 ) ;
01091 }