#include "gdc.h"Go to the source code of this file.
Data Structures | |
| struct | GDC_ANNOTATION_T |
| struct | GDC_SCATTER_T |
Defines | |
| #define | MAX_NOTE_LEN 19 |
| #define | EXTERND extern |
Enumerations | |
| enum | GDC_CHART_T { GDC_LINE, GDC_AREA, GDC_BAR, GDC_HILOCLOSE, GDC_COMBO_LINE_BAR, GDC_COMBO_HLC_BAR, GDC_COMBO_LINE_AREA, GDC_COMBO_HLC_AREA, GDC_3DHILOCLOSE, GDC_3DCOMBO_LINE_BAR, GDC_3DCOMBO_LINE_AREA, GDC_3DCOMBO_HLC_BAR, GDC_3DCOMBO_HLC_AREA, GDC_3DBAR, GDC_3DAREA, GDC_3DLINE } |
| enum | GDC_STACK_T { GDC_STACK_DEPTH, GDC_STACK_SUM, GDC_STACK_BESIDE, GDC_STACK_LAYER } |
| enum | GDC_HLC_STYLE_T { GDC_HLC_DIAMOND = 1, GDC_HLC_CLOSE_CONNECTED = 2, GDC_HLC_CONNECTING = 4, GDC_HLC_I_CAP = 8 } |
| enum | GDC_SCATTER_IND_T { GDC_SCATTER_TRIANGLE_DOWN, GDC_SCATTER_TRIANGLE_UP } |
Functions | |
| EXTERND enum GDC_font_size GDC_title_size | DEFAULTO (GDC_MEDBOLD) |
| EXTERND enum GDC_font_size GDC_yaxisfont_size | DEFAULTO (GDC_SMALL) |
| EXTERND char *GDC_ylabel_fmt | DEFAULTO (NULL) |
| EXTERND short GDC_xlabel_spacing | DEFAULTO (5) |
| EXTERND char GDC_ylabel_density | DEFAULTO (80) |
| EXTERND float GDC_requested_ymin | DEFAULTO (0) |
| EXTERND char GDC_0Shelf | DEFAULTO (TRUE) |
| EXTERND GDC_STACK_T GDC_stack_type | DEFAULTO (GDC_STACK_DEPTH) |
| EXTERND float GDC_3d_depth | DEFAULTO (5.0) |
| EXTERND unsigned char GDC_3d_angle | DEFAULTO (45) |
| EXTERND unsigned char GDC_bar_width | DEFAULTO (75) |
| EXTERND GDC_HLC_STYLE_T GDC_HLC_style | DEFAULTO (GDC_HLC_CLOSE_CONNECTED) |
| EXTERND unsigned char GDC_HLC_cap_width | DEFAULTO (25) |
| EXTERND GDC_ANNOTATION_T *GDC_annotation | DEFAULTO ((GDC_ANNOTATION_T *) NULL) |
| EXTERND GDC_SCATTER_T *GDC_scatter | DEFAULTO ((GDC_SCATTER_T *) NULL) |
| EXTERND char GDC_thumbnail | DEFAULTO (FALSE) |
| EXTERND float GDC_thumbval | DEFAULTO (-100000) |
| EXTERND unsigned long GDC_BGColor | DEFAULTO (0x000000L) |
| EXTERND unsigned long GDC_GridColor | DEFAULTO (0xA0A0A0L) |
| EXTERND unsigned long GDC_LineColor | DEFAULTO (GDC_DFLTCOLOR) |
| EXTERND unsigned long GDC_VolColor | DEFAULTO (0xA0A0FFL) |
| EXTERND unsigned long *GDC_ExtVolColor | DEFAULTO ((unsigned long *) NULL) |
| EXTERND char *GDC_BGImage | DEFAULTO ((char *) NULL) |
| int | out_graph (short gifwidth, short gifheight, FILE *gif_fptr, GDC_CHART_T type, int num_points, char *xlbl[], int num_sets,...) |
Variables | |
| EXTERND char * | GDC_ytitle |
| EXTERND char * | GDC_xtitle |
| EXTERND char * | GDC_ytitle2 |
| EXTERND char * | GDC_title |
| EXTERND char * | GDC_thumblabel |
| enum GDC_CHART_T |
Definition at line 12 of file gdchart.h.
00012 { 00013 GDC_LINE, 00014 GDC_AREA, 00015 GDC_BAR, 00016 GDC_HILOCLOSE, 00017 GDC_COMBO_LINE_BAR, /* aka, VOL[ume] */ 00018 GDC_COMBO_HLC_BAR, 00019 GDC_COMBO_LINE_AREA, 00020 GDC_COMBO_HLC_AREA, 00021 GDC_3DHILOCLOSE, 00022 GDC_3DCOMBO_LINE_BAR, 00023 GDC_3DCOMBO_LINE_AREA, 00024 GDC_3DCOMBO_HLC_BAR, 00025 GDC_3DCOMBO_HLC_AREA, 00026 GDC_3DBAR, 00027 GDC_3DAREA, 00028 GDC_3DLINE 00029 } GDC_CHART_T;
| enum GDC_HLC_STYLE_T |
Definition at line 38 of file gdchart.h.
00038 { 00039 GDC_HLC_DIAMOND = 1, 00040 GDC_HLC_CLOSE_CONNECTED = 2, /* can't be used w/ CONNECTING */ 00041 GDC_HLC_CONNECTING = 4, /* can't be used w/ CLOSE_CONNECTED */ 00042 GDC_HLC_I_CAP = 8 00043 } GDC_HLC_STYLE_T; /* can be OR'd */
| enum GDC_SCATTER_IND_T |
Definition at line 53 of file gdchart.h.
00053 { 00054 GDC_SCATTER_TRIANGLE_DOWN, 00055 GDC_SCATTER_TRIANGLE_UP 00056 } GDC_SCATTER_IND_T;
| enum GDC_STACK_T |
Definition at line 31 of file gdchart.h.
00031 { 00032 GDC_STACK_DEPTH, /* "behind" (even non-3D) */ 00033 GDC_STACK_SUM, 00034 GDC_STACK_BESIDE, 00035 GDC_STACK_LAYER 00036 } GDC_STACK_T; /* applies only to num_lines > 1 */
| EXTERND char* GDC_BGImage DEFAULTO | ( | (char *) | NULL | ) |
| EXTERND unsigned long* GDC_ExtVolColor DEFAULTO | ( | (unsigned long *) | NULL | ) |
| EXTERND unsigned long GDC_VolColor DEFAULTO | ( | 0xA0A0FFL | ) |
| EXTERND unsigned long GDC_LineColor DEFAULTO | ( | GDC_DFLTCOLOR | ) |
| EXTERND unsigned long GDC_GridColor DEFAULTO | ( | 0xA0A0A0L | ) |
| EXTERND unsigned long GDC_BGColor DEFAULTO | ( | 0x000000L | ) |
| EXTERND float GDC_thumbval DEFAULTO | ( | - | 100000 | ) |
| EXTERND char GDC_thumbnail DEFAULTO | ( | FALSE | ) |
| EXTERND GDC_SCATTER_T* GDC_scatter DEFAULTO | ( | (GDC_SCATTER_T *) | NULL | ) |
| EXTERND GDC_ANNOTATION_T* GDC_annotation DEFAULTO | ( | (GDC_ANNOTATION_T *) | NULL | ) |
| EXTERND unsigned char GDC_HLC_cap_width DEFAULTO | ( | 25 | ) |
| EXTERND GDC_HLC_STYLE_T GDC_HLC_style DEFAULTO | ( | GDC_HLC_CLOSE_CONNECTED | ) |
| EXTERND unsigned char GDC_bar_width DEFAULTO | ( | 75 | ) |
| EXTERND unsigned char GDC_3d_angle DEFAULTO | ( | 45 | ) |
| EXTERND float GDC_3d_depth DEFAULTO | ( | 5. | 0 | ) |
| EXTERND GDC_STACK_T GDC_stack_type DEFAULTO | ( | GDC_STACK_DEPTH | ) |
| EXTERND char GDC_0Shelf DEFAULTO | ( | TRUE | ) |
| EXTERND float GDC_requested_ymin DEFAULTO | ( | 0 | ) |
| EXTERND char GDC_ylabel_density DEFAULTO | ( | 80 | ) |
| EXTERND short GDC_xlabel_spacing DEFAULTO | ( | 5 | ) |
| EXTERND char* GDC_ylabel_fmt DEFAULTO | ( | NULL | ) |
| EXTERND enum GDC_font_size GDC_yaxisfont_size DEFAULTO | ( | GDC_SMALL | ) |
| EXTERND enum GDC_font_size GDC_title_size DEFAULTO | ( | GDC_MEDBOLD | ) |
| int out_graph | ( | short | gifwidth, | |
| short | gifheight, | |||
| FILE * | gif_fptr, | |||
| GDC_CHART_T | type, | |||
| int | num_points, | |||
| char * | xlbl[], | |||
| int | num_sets, | |||
| ... | ||||
| ) |
Definition at line 359 of file gdchart.cpp.
References ABS, cnt_nl(), FALSE, GDC_3DAREA, GDC_3DBAR, GDC_3DCOMBO_HLC_AREA, GDC_3DCOMBO_HLC_BAR, GDC_3DCOMBO_LINE_AREA, GDC_3DCOMBO_LINE_BAR, GDC_3DHILOCLOSE, GDC_3DLINE, GDC_AREA, GDC_BAR, GDC_COMBO_HLC_AREA, GDC_COMBO_HLC_BAR, GDC_COMBO_LINE_AREA, GDC_COMBO_LINE_BAR, GDC_fontc, GDC_generate_gif, GDC_HILOCLOSE, GDC_hold_img, GDC_image, GDC_NOVALUE, GDC_REUSE_IMAGE, GDC_STACK_DEPTH, GDC_STACK_LAYER, GDC_STACK_SUM, GDC_TINY, GDC_title, GDC_xtitle, GDC_ytitle, GDC_ytitle2, gdImageColorAllocate(), gdImageCopy(), gdImageCopyResized(), gdImageCreate(), gdImageCreateFromGif(), gdImageSX, gdImageSY, HYP_DEPTH, l2gdcal, load_font_conversions(), MAX, MIN, NUM_YPOINTS, out_err(), price_to_str(), PX, and RAD_DEPTH.
Referenced by main().
00368 { 00369 #ifndef WIN32 00370 va_list ap; 00371 int i, j, k; 00372 00373 int graphwidth; 00374 int grapheight; 00375 gdImagePtr im; 00376 gdImagePtr bg_img = NULL; 00377 00378 float xorig, yorig, vyorig; 00379 float yscl = 0.0; 00380 float vyscl = 0.0; 00381 float xscl = 0.0; 00382 float vhighest = -MAXFLOAT; 00383 float vlowest = MAXFLOAT; 00384 float highest = -MAXFLOAT; 00385 float lowest = MAXFLOAT; 00386 gdPoint volpoly[4]; 00387 00388 char do_vol = ( type == GDC_COMBO_HLC_BAR || // aka: combo 00389 type == GDC_COMBO_HLC_AREA || 00390 type == GDC_COMBO_LINE_BAR || 00391 type == GDC_COMBO_LINE_AREA || 00392 type == GDC_3DCOMBO_HLC_BAR || 00393 type == GDC_3DCOMBO_HLC_AREA|| 00394 type == GDC_3DCOMBO_LINE_BAR|| 00395 type == GDC_3DCOMBO_LINE_AREA ); 00396 char threeD = ( type == GDC_3DAREA || 00397 type == GDC_3DLINE || 00398 type == GDC_3DBAR || 00399 type == GDC_3DHILOCLOSE || 00400 type == GDC_3DCOMBO_HLC_BAR || 00401 type == GDC_3DCOMBO_HLC_AREA|| 00402 type == GDC_3DCOMBO_LINE_BAR|| 00403 type == GDC_3DCOMBO_LINE_AREA ); 00404 char num_hlc_sets = 00405 ( type == GDC_COMBO_HLC_BAR || 00406 type == GDC_COMBO_HLC_AREA || 00407 type == GDC_3DCOMBO_HLC_BAR || 00408 type == GDC_3DCOMBO_HLC_AREA|| 00409 type == GDC_3DHILOCLOSE || 00410 type == GDC_HILOCLOSE )? num_sets: 0; 00411 char do_bar = ( type == GDC_3DBAR || // offset X objects to leave 00412 type == GDC_BAR ); // room at X(0) and X(n) 00413 // i.e., not up against Y axes 00414 char do_ylbl_fractions = // %f format not given, or 00415 ( !GDC_ylabel_fmt || // format doesn't have a %,g,e,E,f or F 00416 strlen(GDC_ylabel_fmt) == strcspn(GDC_ylabel_fmt,"%geEfF") ); 00417 float ylbl_interval = 0.0; 00418 int num_lf_xlbls = 0; 00419 int xdepth_3Dtotal = 0; 00420 int ydepth_3Dtotal = 0; 00421 int xdepth_3D = 0; // affects PX() 00422 int ydepth_3D = 0; // affects PY() and PV() 00423 int hlf_barwdth = 0; // half bar widths 00424 int hlf_hlccapwdth = 0; // half cap widths for HLC_I_CAP and DIAMOND 00425 int annote_len = 0, 00426 annote_hgt = 0; 00427 00428 /* args */ 00429 int setno = 0; // affects PX() and PY() 00430 00431 #ifdef WIN32 00432 float *uvals[1000]; 00433 #else 00434 float *uvals[ type == GDC_HILOCLOSE || 00435 type == GDC_3DHILOCLOSE || 00436 type == GDC_3DCOMBO_HLC_BAR || 00437 type == GDC_3DCOMBO_HLC_AREA || 00438 type == GDC_COMBO_HLC_BAR || 00439 type == GDC_COMBO_HLC_AREA? num_sets *= 3: // 1 more last set is vol 00440 type == GDC_COMBO_LINE_BAR || 00441 type == GDC_3DCOMBO_LINE_BAR || 00442 type == GDC_3DCOMBO_LINE_AREA|| 00443 type == GDC_COMBO_LINE_AREA? num_sets: // 1 more last set is vol 00444 num_sets ]; 00445 #endif 00446 float *uvol; 00447 00448 int BGColor, 00449 LineColor, 00450 PlotColor, 00451 GridColor, 00452 VolColor, 00453 ExtVolColor[num_points], 00454 ThumbDColor, 00455 ThumbLblColor, 00456 ThumbUColor, 00457 // ArrowDColor, 00458 // ArrowUColor, 00459 AnnoteColor, 00460 ExtColor[num_sets][num_points]; 00461 // shade colors only with 3D 00462 // int ExtColorShd[threeD?1:num_sets][threeD?1:num_points]; // compiler limitation 00463 int ExtColorShd[num_sets][num_points]; 00464 00465 /* idiot checks */ 00466 if( GIFWIDTH<=0 || GIFHEIGHT<=0 || (!gif_fptr && GDC_generate_gif) ) 00467 return -1; 00468 if( num_points <= 0 ) 00469 { 00470 out_err( GIFWIDTH, GIFHEIGHT, gif_fptr, GDC_BGColor, GDC_LineColor, "No Data Available" ); 00471 return 1; 00472 } 00473 00474 load_font_conversions(); 00475 if( GDC_thumbnail ) 00476 { 00477 GDC_grid = FALSE; 00478 GDC_xaxis = FALSE; 00479 GDC_yaxis = FALSE; 00480 } 00481 00482 // ----- get args va number of float arrays ----- 00483 va_start( ap, num_sets ); 00484 for( i=0; i<num_sets; ++i ) 00485 uvals[i] = va_arg(ap, float*); 00486 if( do_vol ) 00487 uvol = va_arg(ap, float*); 00488 va_end(ap); 00489 00490 /* ----- highest & lowest values ----- */ 00491 if( GDC_stack_type == GDC_STACK_SUM ) // need to walk sideways 00492 for( j=0; j<num_points; ++j ) 00493 { 00494 float set_sum = 0.0; 00495 for( i=0; i<num_sets; ++i ) 00496 if( uvals[i][j] != GDC_NOVALUE ) 00497 { 00498 set_sum += uvals[i][j]; 00499 highest = MAX( highest, set_sum ); 00500 lowest = MIN( lowest, set_sum ); 00501 } 00502 } 00503 else 00504 if( GDC_stack_type == GDC_STACK_LAYER ) // need to walk sideways 00505 for( j=0; j<num_points; ++j ) 00506 { 00507 float neg_set_sum = 0.0, 00508 pos_set_sum = 0.0; 00509 for( i=0; i<num_sets; ++i ) 00510 if( uvals[i][j] != GDC_NOVALUE ) 00511 if( uvals[i][j] < 0.0 ) 00512 neg_set_sum += uvals[i][j]; 00513 else 00514 pos_set_sum += uvals[i][j]; 00515 lowest = MIN( lowest, MIN(neg_set_sum,pos_set_sum) ); 00516 highest = MAX( highest, MAX(neg_set_sum,pos_set_sum) ); 00517 } 00518 else 00519 for( i=0; i<num_sets; ++i ) 00520 for( j=0; j<num_points; ++j ) 00521 if( uvals[i][j] != GDC_NOVALUE ) 00522 { 00523 highest = MAX( uvals[i][j], highest ); 00524 lowest = MIN( uvals[i][j], lowest ); 00525 } 00526 if( GDC_scatter ) 00527 for( i=0; i<GDC_num_scatter_pts; ++i ) 00528 { 00529 highest = MAX( (GDC_scatter+i)->val, highest ); 00530 lowest = MIN( (GDC_scatter+i)->val, lowest ); 00531 } 00532 if( do_vol ) // for now only one combo set allowed 00533 { 00534 // vhighest = 1.0; 00535 // vlowest = 0.0; 00536 for( j=0; j<num_points; ++j ) 00537 if( uvol[j] != GDC_NOVALUE ) 00538 { 00539 vhighest = MAX( uvol[j], vhighest ); 00540 vlowest = MIN( uvol[j], vlowest ); 00541 } 00542 if( vhighest == -MAXFLOAT ) // no values 00543 vhighest = 1.0; // for scaling, need a range 00544 else 00545 if( vhighest < 0.0 ) 00546 vhighest = 0.0; 00547 if( vlowest > 0.0 || vlowest == MAXFLOAT ) 00548 vlowest = 0.0; // vol should always start at 0 00549 } 00550 00551 if( lowest == MAXFLOAT ) 00552 lowest = 0.0; 00553 if( highest == -MAXFLOAT ) 00554 highest = 1.0; // need a range 00555 if( type == GDC_AREA || // bars and area should always start at 0 00556 type == GDC_BAR || 00557 type == GDC_3DBAR || 00558 type == GDC_3DAREA ) 00559 if( highest < 0.0 ) 00560 highest = 0.0; 00561 else 00562 if( lowest > 0.0 ) // negs should be drawn from 0 00563 lowest = 0.0; 00564 00565 if( GDC_requested_ymin != GDC_NOVALUE && GDC_requested_ymin < lowest ) 00566 lowest = GDC_requested_ymin; 00567 if( GDC_requested_ymax != GDC_NOVALUE && GDC_requested_ymax > highest ) 00568 highest = GDC_requested_ymax; 00569 00570 00571 /* ----- graph height and width within the gif height width ----- */ 00572 /* grapheight/height is the actual size of the scalable graph */ 00573 { 00574 int title_hgt = GDC_title? 2 /* title? horizontal text line(s) */ 00575 + cnt_nl(GDC_title,(int*)NULL)*GDC_fontc[GDC_title_size].h 00576 + 2: 00577 2; 00578 int xlabel_hgt = 0; 00579 int xtitle_hgt = GDC_xtitle? 1+GDC_fontc[GDC_xtitle_size].h+1: 0; 00580 int ytitle_hgt = GDC_ytitle? 1+GDC_fontc[GDC_ytitle_size].h+1: 0; 00581 int vtitle_hgt = do_vol&&GDC_ytitle2? 1+GDC_fontc[GDC_ytitle_size].h+1: 0; 00582 int ylabel_wth = 0; 00583 int vlabel_wth = 0; 00584 00585 int xtics = GDC_grid||GDC_xaxis? 1+2: 0; 00586 int ytics = GDC_grid||GDC_yaxis? 1+3: 0; 00587 int vtics = GDC_yaxis&&do_vol? 3+1: 0; 00588 00589 00590 #define HYP_DEPTH ( (double)((GIFWIDTH+GIFHEIGHT)/2) * ((double)GDC_3d_depth)/100.0 ) 00591 #define RAD_DEPTH ( (double)GDC_3d_angle*2*M_PI/360 ) 00592 xdepth_3D = threeD? (int)( cos(RAD_DEPTH) * HYP_DEPTH ): 0; 00593 ydepth_3D = threeD? (int)( sin(RAD_DEPTH) * HYP_DEPTH ): 0; 00594 xdepth_3Dtotal = xdepth_3D*(GDC_stack_type==GDC_STACK_DEPTH? num_hlc_sets? num_hlc_sets: 00595 num_sets: 00596 1 ); 00597 ydepth_3Dtotal = ydepth_3D*(GDC_stack_type==GDC_STACK_DEPTH? num_hlc_sets? num_hlc_sets: 00598 num_sets: 00599 1 ); 00600 annote_hgt = GDC_annotation && *(GDC_annotation->note)? 00601 1 + /* space to note */ 00602 (1+GDC_fontc[GDC_annotation_font].h) * /* number of '\n' substrs */ 00603 cnt_nl(GDC_annotation->note,&annote_len) + 00604 1 + /* space under note */ 00605 2: 0; /* space to chart */ 00606 annote_len *= GDC_fontc[GDC_annotation_font].w; 00607 00608 if( GDC_xaxis && xlbl ) 00609 { 00610 int biggest = -MAXINT; 00611 00612 for( i=0; i<num_points; ++i ) 00613 { 00614 int len = 0; 00615 // longest "...\n" segment 00616 for( len=0, j=0; xlbl[i][j]; ++len, ++j ) 00617 if( xlbl[i][j] == '\n' ) 00618 { 00619 biggest = MAX( len, biggest ); 00620 ++num_lf_xlbls; 00621 len = 0; 00622 } 00623 biggest = MAX( len, biggest ); // last seg 00624 } 00625 xlabel_hgt = 1+ biggest*GDC_fontc[GDC_xaxisfont_size].w +1; 00626 } 00627 00628 grapheight = GIFHEIGHT - ( xtics + 00629 xtitle_hgt + 00630 xlabel_hgt + 00631 title_hgt + 00632 annote_hgt + 00633 ydepth_3Dtotal + 00634 2 ); 00635 if( GDC_hard_size && GDC_hard_grapheight ) /* user wants to use his */ 00636 grapheight = GDC_hard_grapheight; 00637 GDC_hard_grapheight = grapheight; 00638 // before width can be known... 00639 /* ----- y labels intervals ----- */ 00640 { 00641 float tmp_highest; 00642 /* possible y gridline points */ 00643 float ypoints[] = { 1.0/64.0, 1.0/32.0, 1.0/16.0, 1.0/8.0, 1.0/4.0, 1.0/2.0, 00644 1.0, 2.0, 3.0, 5.0, 10.0, 25.0, 00645 50.0, 100.0, 250.0, 500.0, 1000.0, 2500, 5000.0, 00646 10000.0, 25000.0, 50000.0, 100000.0,500000.0,1000000, 5000000, 00647 10000000 }; 00648 #define NUM_YPOINTS (sizeof(ypoints) / sizeof(float)) 00649 int max_num_ylbls; 00650 int longest_ylblen = 0; 00651 /* maximum y lables that'll fit... */ 00652 max_num_ylbls = grapheight / (3+GDC_fontc[GDC_yaxisfont_size==GDC_TINY? GDC_yaxisfont_size+1: 00653 GDC_yaxisfont_size].h); 00654 if( max_num_ylbls < 3 ) 00655 { 00656 /* gdImageDestroy(im); haven't yet created it */ 00657 out_err( GIFWIDTH, GIFHEIGHT, 00658 gif_fptr, 00659 GDC_BGColor, GDC_LineColor, 00660 "Insificient Height" ); 00661 return 2; 00662 } 00663 00664 /* one "space" interval above + below */ 00665 for( i=1; i<NUM_YPOINTS; ++i ) 00666 // if( ypoints[i] > ylbl_interval ) 00667 // break; 00668 if( (highest-lowest)/ypoints[i] < ((float)max_num_ylbls-(1.0+1.0)) 00669 * (float)GDC_ylabel_density/100.0 ) 00670 break; 00671 /* gotta go through the above loop to catch the 'tweeners :-| */ 00672 00673 ylbl_interval = GDC_requested_yinterval != GDC_NOVALUE && 00674 GDC_requested_yinterval > ypoints[i-1]? GDC_requested_yinterval: 00675 ypoints[i-1]; 00676 00677 /* perform floating point remainders */ 00678 /* gonculate largest interval-point < lowest */ 00679 if( lowest != 0.0 && 00680 lowest != GDC_requested_ymin ) 00681 { 00682 if( lowest < 0.0 ) 00683 lowest -= ylbl_interval; 00684 // lowest = (lowest-ypoints[0]) - 00685 // ( ( ((lowest-ypoints[0])/ylbl_interval)*ylbl_interval ) - 00686 // ( (float)((int)((lowest-ypoints[0])/ylbl_interval))*ylbl_interval ) ); 00687 lowest = ylbl_interval * (float)(int)((lowest-ypoints[0])/ylbl_interval); 00688 } 00689 /* find smallest interval-point > highest */ 00690 tmp_highest = lowest; 00691 do // while( (tmp_highest += ylbl_interval) <= highest ) 00692 { 00693 int nmrtr, dmntr, whole; 00694 char *price_to_str( float, int*, int*, int*, char* ); 00695 int lbl_len; 00696 char foo[32]; 00697 00698 if( GDC_yaxis ) 00699 { /* XPG2 compatibility */ 00700 sprintf( foo, do_ylbl_fractions? "%.0f": GDC_ylabel_fmt, tmp_highest ); 00701 lbl_len = ylbl_interval<1.0? strlen( price_to_str(tmp_highest, 00702 &nmrtr, 00703 &dmntr, 00704 &whole, 00705 do_ylbl_fractions? NULL: GDC_ylabel_fmt) ): 00706 strlen( foo ); 00707 longest_ylblen = MAX( longest_ylblen, lbl_len ); 00708 } 00709 } while( (tmp_highest += ylbl_interval) <= highest ); 00710 ylabel_wth = longest_ylblen * GDC_fontc[GDC_yaxisfont_size].w; 00711 highest = GDC_requested_ymax==GDC_NOVALUE? tmp_highest: 00712 MAX( GDC_requested_ymax, highest ); 00713 00714 if( do_vol ) 00715 { 00716 float num_yintrvls = (highest-lowest) / ylbl_interval; 00717 /* no skyscrapers */ 00718 if( vhighest != 0.0 ) 00719 vhighest += (vhighest-vlowest) / (num_yintrvls*2.0); 00720 if( vlowest != 0.0 ) 00721 vlowest -= (vhighest-vlowest) / (num_yintrvls*2.0); 00722 00723 if( GDC_yaxis2 ) 00724 { 00725 char svlongest[32]; 00726 int lbl_len_low = sprintf( svlongest, GDC_ylabel2_fmt? GDC_ylabel2_fmt: "%.0f", vlowest ); 00727 int lbl_len_high = sprintf( svlongest, GDC_ylabel2_fmt? GDC_ylabel2_fmt: "%.0f", vhighest ); 00728 vlabel_wth = 1 00729 + MAX( lbl_len_low,lbl_len_high ) * GDC_fontc[GDC_yaxisfont_size].w; 00730 } 00731 } 00732 } 00733 00734 graphwidth = GIFWIDTH - ( ( (GDC_hard_size && GDC_hard_xorig)? GDC_hard_xorig: 00735 ( ytitle_hgt + 00736 ylabel_wth + 00737 ytics ) ) 00738 + vtics 00739 + vtitle_hgt 00740 + vlabel_wth 00741 + xdepth_3Dtotal ); 00742 if( GDC_hard_size && GDC_hard_graphwidth ) /* user wants to use his */ 00743 graphwidth = GDC_hard_graphwidth; 00744 GDC_hard_graphwidth = graphwidth; 00745 00746 /* ----- scale to gif size ----- */ 00747 /* offset to 0 at lower left (where it should be) */ 00748 xscl = (float)(graphwidth-xdepth_3Dtotal) / (float)(num_points + (do_bar?2:0)); 00749 yscl = -((float)grapheight) / (float)(highest-lowest); 00750 if( do_vol ) 00751 { 00752 float hilow_diff = vhighest-vlowest==0.0? 1.0: vhighest-vlowest; 00753 00754 vyscl = -((float)grapheight) / hilow_diff; 00755 vyorig = (float)grapheight 00756 + ABS(vyscl) * MIN(vlowest,vhighest) 00757 + ydepth_3Dtotal 00758 + title_hgt 00759 + annote_hgt; 00760 } 00761 xorig = (float)( GIFWIDTH - ( graphwidth + 00762 vtitle_hgt + 00763 vtics + 00764 vlabel_wth ) ); 00765 if( GDC_hard_size && GDC_hard_xorig ) 00766 xorig = GDC_hard_xorig; 00767 GDC_hard_xorig = xorig; 00768 // yorig = (float)grapheight + ABS(yscl * lowest) + ydepth_3Dtotal + title_hgt; 00769 yorig = (float)grapheight 00770 + ABS(yscl) * MIN(lowest,highest) 00771 + ydepth_3Dtotal 00772 + title_hgt 00773 + annote_hgt; 00774 //???? if( GDC_hard_size && GDC_hard_yorig ) /* vyorig too? */ 00775 //???? yorig = GDC_hard_yorig; 00776 GDC_hard_yorig = yorig; 00777 00778 hlf_barwdth = (int)( (float)(PX(2)-PX(1)) * (((float)GDC_bar_width/100.0)/2.0) ); // used only for bars 00779 hlf_hlccapwdth = (int)( (float)(PX(2)-PX(1)) * (((float)GDC_HLC_cap_width/100.0)/2.0) ); 00780 } 00781 // scaled, sized, ready 00782 00783 00784 /* ----- OK start the graphic ----- */ 00785 if( (GDC_hold_img & GDC_REUSE_IMAGE) && 00786 GDC_image != NULL ) 00787 im = (gdImage *)GDC_image; 00788 else 00789 im = gdImageCreate( GIFWIDTH, GIFHEIGHT ); 00790 00791 00792 BGColor = gdImageColorAllocate( im, l2gdcal(GDC_BGColor) ); 00793 LineColor = clrallocate( im, GDC_LineColor ); 00794 PlotColor = clrallocate( im, GDC_PlotColor ); 00795 GridColor = clrallocate( im, GDC_GridColor ); 00796 if( do_vol ) 00797 { 00798 VolColor = clrallocate( im, GDC_VolColor ); 00799 for( i=0; i<num_points; ++i ) 00800 if( GDC_ExtVolColor ) 00801 ExtVolColor[i] = clrallocate( im, GDC_ExtVolColor[i] ); 00802 else 00803 ExtVolColor[i] = VolColor; 00804 } 00805 // ArrowDColor = gdImageColorAllocate( im, 0xFF, 0, 0 ); 00806 // ArrowUColor = gdImageColorAllocate( im, 0, 0xFF, 0 ); 00807 if( GDC_annotation ) 00808 AnnoteColor = clrallocate( im, GDC_annotation->color ); 00809 00810 /* attempt to import optional background image */ 00811 if( GDC_BGImage ) 00812 { 00813 FILE *in = fopen(GDC_BGImage, "rb"); 00814 if( !in ) 00815 { 00816 ; // Cant load background image, drop it 00817 } 00818 else 00819 { 00820 if( bg_img = gdImageCreateFromGif(in) ) // = 00821 { 00822 int bgxpos = gdImageSX(bg_img)<GIFWIDTH? GIFWIDTH/2 - gdImageSX(bg_img)/2: 0, 00823 bgypos = gdImageSY(bg_img)<GIFHEIGHT? GIFHEIGHT/2 - gdImageSY(bg_img)/2: 0; 00824 00825 00826 if( gdImageSX(bg_img) > GIFWIDTH || // resize only if too big 00827 gdImageSY(bg_img) > GIFHEIGHT ) // [and center] 00828 { 00829 gdImageCopyResized( im, bg_img, // dst, src 00830 bgxpos, bgypos, // dstX, dstY 00831 0, 0, // srcX, srcY 00832 GIFWIDTH, GIFHEIGHT, // dstW, dstH 00833 GIFWIDTH, GIFHEIGHT ); // srcW, srcH 00834 } 00835 else // just center 00836 gdImageCopy( im, bg_img, // dst, src 00837 bgxpos, bgypos, // dstX, dstY 00838 0, 0, // srcX, srcY 00839 GIFWIDTH, GIFHEIGHT ); // W, H 00840 } 00841 fclose(in); 00842 } 00843 } 00844 00845 for( j=0; j<num_sets; ++j ) 00846 for( i=0; i<num_points; ++i ) 00847 if( GDC_ExtColor ) 00848 { 00849 unsigned long ext_clr = *(GDC_ExtColor+num_points*j+i); 00850 00851 ExtColor[j][i] = clrallocate( im, ext_clr ); 00852 if( threeD ) 00853 ExtColorShd[j][i] = clrshdallocate( im, ext_clr ); 00854 } 00855 else if( GDC_SetColor ) 00856 { 00857 int set_clr = GDC_SetColor[j]; 00858 ExtColor[j][i] = clrallocate( im, set_clr ); 00859 if( threeD ) 00860 ExtColorShd[j][i] = clrshdallocate( im, set_clr ); 00861 } 00862 else 00863 { 00864 ExtColor[j][i] = PlotColor; 00865 if( threeD ) 00866 ExtColorShd[j][i] = clrshdallocate( im, GDC_PlotColor ); 00867 } 00868 00869 00870 if( GDC_transparent_bg ) 00871 gdImageColorTransparent( im, BGColor ); 00872 00873 if( GDC_title ) 00874 { 00875 int tlen; 00876 int titlecolor = clrallocate( im, GDC_TitleColor ); 00877 00878 cnt_nl( GDC_title, &tlen ); 00879 GDCImageStringNL( im, 00880 &GDC_fontc[GDC_title_size], 00881 GIFWIDTH/2 - tlen*GDC_fontc[GDC_title_size].w/2, 00882 0, 00883 GDC_title, 00884 titlecolor, 00885 GDC_JUSTIFY_CENTER ); 00886 } 00887 if( GDC_xtitle ) 00888 { 00889 int titlecolor = GDC_XTitleColor==GDC_DFLTCOLOR? 00890 PlotColor: clrallocate( im, GDC_XTitleColor ); 00891 gdImageString( im, 00892 GDC_fontc[GDC_xtitle_size].f, 00893 GIFWIDTH/2 - strlen(GDC_xtitle)*GDC_fontc[GDC_xtitle_size].w/2, 00894 GIFHEIGHT-GDC_fontc[GDC_xtitle_size].h-1, 00895 (unsigned char *)GDC_xtitle, 00896 titlecolor ); 00897 } 00898 00899 00900 /* ----- start drawing ----- */ 00901 /* ----- backmost first - grid & labels ----- */ 00902 if( GDC_grid || GDC_yaxis ) 00903 { /* grid lines & y label(s) */ 00904 float tmp_y = lowest; 00905 int labelcolor = GDC_YLabelColor==GDC_DFLTCOLOR? 00906 LineColor: clrallocate( im, GDC_YLabelColor ); 00907 int label2color = GDC_YLabel2Color==GDC_DFLTCOLOR? 00908 VolColor: clrallocate( im, GDC_YLabel2Color ); 00909 00910 /* step from lowest to highest puting in labels and grid at interval points */ 00911 /* since now "odd" intervals may be requested, try to step starting at 0, */ 00912 /* if lowest < 0 < highest */ 00913 for( i=-1; i<=1; i+=2 ) // -1, 1 00914 { 00915 if( i == -1 ) if( lowest >= 0.0 ) // all pos plotting 00916 continue; 00917 else 00918 tmp_y = MIN( 0, highest ); // step down to lowest 00919 00920 if( i == 1 ) if( highest <= 0.0 ) // all neg plotting 00921 continue; 00922 else 00923 tmp_y = MAX( 0, lowest ); // step up to highest 00924 00925 00926 // if( !(highest > 0 && lowest < 0) ) // doesn't straddle 0 00927 // { 00928 // if( i == -1 ) // only do once: normal 00929 // continue; 00930 // } 00931 // else 00932 // tmp_y = 0; 00933 00934 do // while( (tmp_y (+-)= ylbl_interval) < [highest,lowest] ) 00935 { 00936 int n, d, w; 00937 char *price_to_str( float, int*, int*, int*, char* ); 00938 char nmrtr[3+1], dmntr[3+1], whole[8]; 00939 char all_whole = ylbl_interval<1.0? FALSE: TRUE; 00940 00941 char *ylbl_str = price_to_str( tmp_y,&n,&d,&w, 00942 do_ylbl_fractions? NULL: GDC_ylabel_fmt ); 00943 if( do_ylbl_fractions ) 00944 { 00945 sprintf( nmrtr, "%d", n ); 00946 sprintf( dmntr, "%d", d ); 00947 sprintf( whole, "%d", w ); 00948 } 00949 00950 if( GDC_grid ) 00951 { 00952 int x1, x2, y1, y2; 00953 // int gridline_clr = tmp_y == 0.0? LineColor: GridColor; 00954 // tics 00955 x1 = PX(0); y1 = PY(tmp_y); 00956 gdImageLine( im, x1-2, y1, x1, y1, GridColor ); 00957 setno = GDC_stack_type==GDC_STACK_DEPTH? num_hlc_sets? num_hlc_sets: 00958 num_sets: 00959 1; // backmost 00960 x2 = PX(0); y2 = PY(tmp_y); // w/ new setno 00961 gdImageLine( im, x1, y1, x2, y2, GridColor ); // depth for 3Ds 00962 gdImageLine( im, x2, y2, PX(num_points-1+(do_bar?2:0)), y2, GridColor ); 00963 setno = 0; // set back to foremost 00964 } 00965 if( GDC_yaxis ) 00966 if( do_ylbl_fractions ) 00967 { 00968 if( w || (!w && !n && !d) ) 00969 { 00970 gdImageString( im, 00971 GDC_fontc[GDC_yaxisfont_size].f, 00972 PX(0)-2-strlen(whole)*GDC_fontc[GDC_yaxisfont_size].w 00973 - ( (!all_whole)? 00974 (strlen(nmrtr)*GDC_fontc[GDC_yaxisfont_size-1].w + 00975 GDC_fontc[GDC_yaxisfont_size].w + 00976 strlen(nmrtr)*GDC_fontc[GDC_yaxisfont_size-1].w) : 00977 1 ), 00978 PY(tmp_y)-GDC_fontc[GDC_yaxisfont_size].h/2, 00979 (unsigned char *)whole, 00980 labelcolor ); 00981 } 00982 if( n ) 00983 { 00984 gdImageString( im, 00985 GDC_fontc[GDC_yaxisfont_size-1].f, 00986 PX(0)-2-strlen(nmrtr)*GDC_fontc[GDC_yaxisfont_size-1].w 00987 -GDC_fontc[GDC_yaxisfont_size].w 00988 -strlen(nmrtr)*GDC_fontc[GDC_yaxisfont_size-1].w + 1, 00989 PY(tmp_y)-GDC_fontc[GDC_yaxisfont_size].h/2 + 1, 00990 (unsigned char *)nmrtr, 00991 labelcolor ); 00992 gdImageString( im, 00993 GDC_fontc[GDC_yaxisfont_size].f, 00994 PX(0)-2-GDC_fontc[GDC_yaxisfont_size].w 00995 -strlen(nmrtr)*GDC_fontc[GDC_yaxisfont_size-1].w, 00996 PY(tmp_y)-GDC_fontc[GDC_yaxisfont_size].h/2, 00997 (unsigned char *)"/", 00998 labelcolor ); 00999 gdImageString( im, 01000 GDC_fontc[GDC_yaxisfont_size-1].f, 01001 PX(0)-2-strlen(nmrtr)*GDC_fontc[GDC_yaxisfont_size-1].w - 2, 01002 PY(tmp_y)-GDC_fontc[GDC_yaxisfont_size].h/2 + 3, 01003 (unsigned char *) dmntr, 01004 labelcolor ); 01005 } 01006 } 01007 else 01008 gdImageString( im, 01009 GDC_fontc[GDC_yaxisfont_size].f, 01010 PX(0)-2-strlen(ylbl_str)*GDC_fontc[GDC_yaxisfont_size].w, 01011 PY(tmp_y)-GDC_fontc[GDC_yaxisfont_size].h/2, 01012 (unsigned char *)ylbl_str, 01013 labelcolor ); 01014 01015 01016 if( do_vol && GDC_yaxis2 ) 01017 { 01018 char vylbl[16]; 01019 /* opposite of PV(y) */ 01020 sprintf( vylbl, 01021 GDC_ylabel2_fmt? GDC_ylabel2_fmt: "%.0f", 01022 ((float)(PY(tmp_y)+(setno*ydepth_3D)-vyorig))/vyscl ); 01023 01024 setno = GDC_stack_type==GDC_STACK_DEPTH? num_hlc_sets? num_hlc_sets: 01025 num_sets: 01026 1; // backmost 01027 gdImageLine( im, PX(num_points-1+(do_bar?2:0)), PY(tmp_y), 01028 PX(num_points-1+(do_bar?2:0))+3, PY(tmp_y), GridColor ); 01029 if( atof(vylbl) == 0.0 ) /* rounding can cause -0 */ 01030 strcpy( vylbl, "0" ); 01031 gdImageString( im, 01032 GDC_fontc[GDC_yaxisfont_size].f, 01033 PX(num_points-1+(do_bar?2:0))+6, 01034 PY(tmp_y)-GDC_fontc[GDC_yaxisfont_size].h/2, 01035 (unsigned char *)vylbl, 01036 label2color ); 01037 setno = 0; 01038 } 01039 } 01040 while( ((i>0) && ((tmp_y += ylbl_interval) < highest)) || 01041 ((i<0) && ((tmp_y -= ylbl_interval) > lowest)) ); 01042 } 01043 01044 /* catch last (bottom) grid line - specific to an "off" requested interval */ 01045 if( GDC_grid && threeD ) 01046 { 01047 setno = GDC_stack_type==GDC_STACK_DEPTH? num_hlc_sets? num_hlc_sets: 01048 num_sets: 01049 1; // backmost 01050 gdImageLine( im, PX(0), PY(lowest), PX(num_points-1+(do_bar?2:0)), PY(lowest), GridColor ); 01051 setno = 0; // set back to foremost 01052 } 01053 01054 /* vy axis title */ 01055 if( do_vol && GDC_ytitle2 ) 01056 { 01057 int titlecolor = GDC_YTitle2Color==GDC_DFLTCOLOR? 01058 VolColor: clrallocate( im, GDC_YTitle2Color ); 01059 gdImageStringUp( im, 01060 GDC_fontc[GDC_ytitle_size].f, 01061 GIFWIDTH-(1+GDC_fontc[GDC_ytitle_size].h), 01062 strlen(GDC_ytitle2)*GDC_fontc[GDC_ytitle_size].w/2 + 01063 grapheight/2, 01064 (unsigned char *)GDC_ytitle2, 01065 titlecolor ); 01066 } 01067 01068 /* y axis title */ 01069 if( GDC_yaxis && GDC_ytitle ) 01070 { 01071 int ytit_len = strlen(GDC_ytitle)*GDC_fontc[GDC_ytitle_size].w; 01072 int titlecolor = GDC_YTitleColor==GDC_DFLTCOLOR? 01073 PlotColor: clrallocate( im, GDC_YTitleColor ); 01074 gdImageStringUp( im, 01075 GDC_fontc[GDC_ytitle_size].f, 01076 0, 01077 GIFHEIGHT/2 + ytit_len/2, 01078 (unsigned char *)GDC_ytitle, 01079 titlecolor ); 01080 } 01081 } 01082 01083 /* interviening set grids */ 01084 /* 0 < setno < num_sets non-inclusive, they've already been covered */ 01085 if( GDC_grid && threeD ) 01086 { 01087 for( setno=(GDC_stack_type==GDC_STACK_DEPTH? num_hlc_sets? num_hlc_sets: num_sets: 1) - 1; 01088 setno > 0; 01089 --setno ) 01090 { 01091 gdImageLine( im, PX(0), PY(lowest), PX(0), PY(highest), GridColor ); 01092 gdImageLine( im, PX(0), PY(lowest), PX(num_points-1+(do_bar?2:0)), PY(lowest), GridColor ); 01093 } 01094 setno = 0; 01095 } 01096 01097 if( ( GDC_grid || GDC_0Shelf ) && /* line color grid at 0 */ 01098 ( (lowest < 0.0 && highest > 0.0) || 01099 (lowest < 0.0 && highest > 0.0) ) ) 01100 { 01101 int x1, x2, y1, y2; 01102 // tics 01103 x1 = PX(0); y1 = PY(0); 01104 gdImageLine( im, x1-2, y1, x1, y1, LineColor ); 01105 setno = GDC_stack_type==GDC_STACK_DEPTH? num_hlc_sets? num_hlc_sets: 01106 num_sets: 01107 1; // backmost 01108 x2 = PX(0); y2 = PY(0); // w/ new setno 01109 gdImageLine( im, x1, y1, x2, y2, LineColor ); // depth for 3Ds 01110 gdImageLine( im, x2, y2, PX(num_points-1+(do_bar?2:0)), y2, LineColor ); 01111 setno = 0; // set back to foremost 01112 } 01113 01114 01115 /* x ticks and xlables */ 01116 if( GDC_grid || GDC_xaxis ) 01117 { 01118 int num_xlbls = /* maximum x lables that'll fit */ 01119 /* each xlbl + avg due to num_lf_xlbls */ 01120 graphwidth / 01121 ( (GDC_xlabel_spacing==MAXSHORT?0:GDC_xlabel_spacing)+GDC_fontc[GDC_xaxisfont_size].h + 01122 (num_lf_xlbls*(GDC_fontc[GDC_xaxisfont_size].h-1))/num_points ); 01123 int labelcolor = GDC_XLabelColor==GDC_DFLTCOLOR? 01124 LineColor: clrallocate( im, GDC_XLabelColor ); 01125 01126 for( i=0; i<num_points+(do_bar?2:0); ++i ) 01127 if( (i%(1+num_points/num_xlbls) == 0) || // # x labels are regulated 01128 (num_xlbls >= num_points) || 01129 GDC_xlabel_spacing == MAXSHORT ) 01130 { 01131 int xi = do_bar? i-1: i; 01132 01133 if( GDC_grid ) 01134 { 01135 int x1, x2, y1, y2; 01136 // tics 01137 x1 = PX(i); y1 = PY(lowest); 01138 gdImageLine( im, x1, y1, x1, y1+2, GridColor ); 01139 setno = GDC_stack_type==GDC_STACK_DEPTH? num_hlc_sets? num_hlc_sets: 01140 num_sets: 01141 1; // backmost 01142 x2 = PX(i); y2 = PY(lowest); 01143 gdImageLine( im, x1, y1, x2, y2, GridColor ); // depth perspective 01144 gdImageLine( im, x2, y2, x2, PY(highest), GridColor ); 01145 setno = 0; // reset to foremost 01146 } 01147 01148 if( !do_bar || (i>0 && xi<num_points) ) 01149 if( GDC_xaxis && xlbl && xlbl[xi] && *(xlbl[xi]) ) 01150 { 01151 /* waiting for GDCImageStringUpNL() */ 01152 #define LBX GDC_fontc[GDC_xaxisfont_size] 01153 int xlen = 0; 01154 short xstrs_num = cnt_nl( xlbl[xi], &xlen ); 01155 char sub_xlbl[xlen+1]; 01156 // int xlbl_strt = -1+ PX((float)i+(float)(do_bar?((float)num_points/(float)num_xlbls):0.0)) - (int)((float)(LBX.h-2)*((float)xstrs_num/2.0)); 01157 int xlbl_strt = -1+ PX(i) - (int)((float)(LBX.h-2)*((float)xstrs_num/2.0)); 01158 01159 xlen = -1; 01160 xstrs_num = -1; 01161 j = -1; 01162 do 01163 { 01164 ++j; 01165 ++xlen; 01166 sub_xlbl[xlen] = xlbl[xi][j]; 01167 if( xlbl[xi][j] == '\n' || 01168 xlbl[xi][j] == '\0' ) 01169 { 01170 sub_xlbl[xlen] = '\0'; 01171 ++xstrs_num; 01172 gdImageStringUp( im, 01173 LBX.f, 01174 xlbl_strt + (LBX.h-1)*xstrs_num, 01175 PY(lowest) + 2 + 1 + LBX.w*xlen, 01176 (unsigned char *)sub_xlbl, 01177 labelcolor ); 01178 xlen = -1; 01179 } 01180 } while( xlbl[xi][j] ); 01181 #undef LBX 01182 } 01183 } 01184 } 01185 01186 /* ----- solid poly region (volume) ----- */ 01187 /* so that grid lines appear under solid */ 01188 if( do_vol ) 01189 { 01190 setno = GDC_stack_type==GDC_STACK_DEPTH? num_hlc_sets? num_hlc_sets: 01191 num_sets: 01192 1; // backmost 01193 if( type == GDC_COMBO_HLC_BAR || 01194 type == GDC_COMBO_LINE_BAR || 01195 type == GDC_3DCOMBO_LINE_BAR || 01196 type == GDC_3DCOMBO_HLC_BAR ) 01197 { 01198 if( uvol[0] != GDC_NOVALUE ) 01199 draw_3d_bar( im, PX(0), PX(0)+hlf_barwdth, 01200 PV(0), PV(uvol[0]), 01201 0, 0, 01202 ExtVolColor[0], 01203 ExtVolColor[0] ); 01204 for( i=1; i<num_points-1; ++i ) 01205 if( uvol[i] != GDC_NOVALUE ) 01206 draw_3d_bar( im, PX(i)-hlf_barwdth, PX(i)+hlf_barwdth, 01207 PV(0), PV(uvol[i]), 01208 0, 0, 01209 ExtVolColor[i], 01210 ExtVolColor[i] ); 01211 if( uvol[i] != GDC_NOVALUE ) 01212 draw_3d_bar( im, PX(i)-hlf_barwdth, PX(i), 01213 PV(0), PV(uvol[i]), 01214 0, 0, 01215 ExtVolColor[i], 01216 ExtVolColor[i] ); 01217 } 01218 else 01219 if( type == GDC_COMBO_HLC_AREA || 01220 type == GDC_COMBO_LINE_AREA || 01221 type == GDC_3DCOMBO_LINE_AREA|| 01222 type == GDC_3DCOMBO_HLC_AREA ) 01223 for( i=1; i<num_points; ++i ) 01224 if( uvol[i-1] != GDC_NOVALUE && uvol[i] != GDC_NOVALUE ) 01225 draw_3d_area( im, PX(i-1), PX(i), 01226 PV(0), PV(uvol[i-1]), PV(uvol[i]), 01227 0, 0, 01228 ExtVolColor[i], 01229 ExtVolColor[i] ); 01230 setno = 0; 01231 } // volume polys done 01232 01233 if( GDC_annotation && threeD ) /* back half of annotation line */ 01234 { 01235 int x1 = PX(GDC_annotation->point+(do_bar?1:0)), 01236 y1 = PY(lowest); 01237 setno = GDC_stack_type==GDC_STACK_DEPTH? num_hlc_sets? num_hlc_sets: 01238 num_sets: 01239 1; // backmost 01240 gdImageLine( im, x1, y1, PX(GDC_annotation->point+(do_bar?1:0)), PY(lowest), AnnoteColor ); 01241 gdImageLine( im, PX(GDC_annotation->point+(do_bar?1:0)), PY(lowest), 01242 PX(GDC_annotation->point+(do_bar?1:0)), PY(highest)-2, AnnoteColor ); 01243 setno = 0; 01244 } 01245 01246 /* ---------- start plotting the data ---------- */ 01247 switch( type ) 01248 { 01249 case GDC_3DBAR: /* depth, width, y interval need to allow for whitespace between bars */ 01250 case GDC_BAR: 01251 /* --------- */ 01252 switch( GDC_stack_type ) 01253 { 01254 case GDC_STACK_DEPTH: 01255 for( setno=num_sets-1; setno>=0; --setno ) // back sets first PX, PY depth 01256 for( i=0; i<num_points; ++i ) 01257 if( uvals[setno][i] != GDC_NOVALUE ) 01258 draw_3d_bar( im, PX(i+(do_bar?1:0))-hlf_barwdth, PX(i+(do_bar?1:0))+hlf_barwdth, 01259 PY(0), PY(uvals[setno][i]), 01260 xdepth_3D, ydepth_3D, 01261 ExtColor[setno][i], 01262 threeD? ExtColorShd[setno][i]: ExtColor[setno][i] ); 01263 setno = 0; 01264 break; 01265 01266 case GDC_STACK_LAYER: 01267 { 01268 float lasty[num_points]; 01269 j = 0; 01270 // for( i=0; i<num_points; ++i ) 01271 // if( uvals[j][i] != GDC_NOVALUE ) 01272 // { 01273 // lasty[i] = uvals[j][i]; 01274 // draw_3d_bar( im, PX(i+(do_bar?1:0))-hlf_barwdth, PX(i+(do_bar?1:0))+hlf_barwdth, 01275 // PY(0), PY(uvals[j][i]), 01276 // xdepth_3D, ydepth_3D, 01277 // ExtColor[j][i], 01278 // threeD? ExtColorShd[j][i]: ExtColor[j][i] ); 01279 // } 01280 for( i=0; i<num_points; ++i ) 01281 { 01282 struct BS barset[num_sets]; 01283 float lasty_pos = 0.0; 01284 float lasty_neg = 0.0; 01285 int k; 01286 01287 for( j=0, k=0; j<num_sets; ++j ) 01288 { 01289 if( uvals[j][i] != GDC_NOVALUE ) 01290 { 01291 if( uvals[j][i] < 0.0 ) 01292 { 01293 barset[k].y1 = lasty_neg; 01294 barset[k].y2 = uvals[j][i] + lasty_neg; 01295 lasty_neg = barset[k].y2; 01296 } 01297 else 01298 { 01299 barset[k].y1 = lasty_pos; 01300 barset[k].y2 = uvals[j][i] + lasty_pos; 01301 lasty_pos = barset[k].y2; 01302 } 01303 barset[k].clr = ExtColor[j][i]; 01304 barset[k].shclr = threeD? ExtColorShd[j][i]: ExtColor[j][i]; 01305 ++k; 01306 } 01307 } 01308 qsort( barset, k, sizeof(struct BS), barcmpr ); 01309 01310 for( j=0; j<k; ++j ) 01311 { 01312 draw_3d_bar( im, 01313 PX(i+(do_bar?1:0))-hlf_barwdth, PX(i+(do_bar?1:0))+hlf_barwdth, 01314 PY(barset[j].y1), PY(barset[j].y2), 01315 xdepth_3D, ydepth_3D, 01316 barset[j].clr, 01317 barset[j].shclr ); 01318 } 01319 } 01320 } 01321 break; 01322 01323 case GDC_STACK_BESIDE: 01324 { // h/.5, h/1, h/1.5, h/2, ... 01325 int new_barwdth = (int)( (float)hlf_barwdth / ((float)num_sets/2.0) ); 01326 for( i=0; i<num_points; ++i ) 01327 for( j=0; j<num_sets; ++j ) 01328 if( uvals[j][i] != GDC_NOVALUE ) 01329 draw_3d_bar( im, PX(i+(do_bar?1:0))-hlf_barwdth+new_barwdth*j+1, 01330 PX(i+(do_bar?1:0))-hlf_barwdth+new_barwdth*(j+1), 01331 PY(0), PY(uvals[j][i]), 01332 xdepth_3D, ydepth_3D, 01333 ExtColor[j][i], 01334 threeD? ExtColorShd[j][i]: ExtColor[j][i] ); 01335 } 01336 break; 01337 } 01338 break; 01339 01340 case GDC_LINE: 01341 case GDC_COMBO_LINE_BAR: 01342 case GDC_COMBO_LINE_AREA: 01343 for( j=num_sets-1; j>=0; --j ) 01344 for( i=1; i<num_points; ++i ) 01345 if( uvals[j][i-1] != GDC_NOVALUE && uvals[j][i] != GDC_NOVALUE ) 01346 { 01347 gdImageLine( im, PX(i-1), PY(uvals[j][i-1]), PX(i), PY(uvals[j][i]), ExtColor[j][i] ); 01348 gdImageLine( im, PX(i-1), PY(uvals[j][i-1])+1, PX(i), PY(uvals[j][i])+1, ExtColor[j][i] ); 01349 } 01350 else 01351 { 01352 if( uvals[j][i-1] != GDC_NOVALUE ) 01353 gdImageSetPixel( im, PX(i-1), PY(uvals[j][i-1]), ExtColor[j][i] ); 01354 if( uvals[j][i] != GDC_NOVALUE ) 01355 gdImageSetPixel( im, PX(i), PY(uvals[j][i]), ExtColor[j][i] ); 01356 } 01357 break; 01358 01359 case GDC_3DLINE: 01360 case GDC_3DCOMBO_LINE_BAR: 01361 case GDC_3DCOMBO_LINE_AREA: 01362 { 01363 int y1[num_sets], 01364 y2[num_sets]; 01365 01366 for( i=1; i<num_points; ++i ) 01367 { 01368 if( GDC_stack_type == GDC_STACK_DEPTH ) 01369 { 01370 for( j=num_sets-1; j>=0; --j ) 01371 if( uvals[j][i-1] != GDC_NOVALUE && 01372 uvals[j][i] != GDC_NOVALUE ) 01373 { 01374 setno = j; 01375 y1[j] = PY(uvals[j][i-1]); 01376 y2[j] = PY(uvals[j][i]); 01377 01378 draw_3d_line( im, 01379 PY(0), 01380 PX(i-1), PX(i), 01381 &(y1[j]), &(y2[j]), 01382 xdepth_3D, ydepth_3D, 01383 1, 01384 &(ExtColor[j][i]), 01385 &(ExtColorShd[j][i]) ); 01386 setno = 0; 01387 } 01388 } 01389 else 01390 if( GDC_stack_type == GDC_STACK_BESIDE || 01391 GDC_stack_type == GDC_STACK_SUM ) // all same plane 01392 { 01393 int set; 01394 int clr[num_sets], 01395 clrshd[num_sets]; 01396 float usey1 = 0.0, 01397 usey2 = 0.0; 01398 for( j=0,set=0; j<num_sets; ++j ) 01399 if( uvals[j][i-1] != GDC_NOVALUE && 01400 uvals[j][i] != GDC_NOVALUE ) 01401 { 01402 if( GDC_stack_type == GDC_STACK_SUM ) 01403 { 01404 usey1 += uvals[j][i-1]; 01405 usey2 += uvals[j][i]; 01406 } 01407 else 01408 { 01409 usey1 = uvals[j][i-1]; 01410 usey2 = uvals[j][i]; 01411 } 01412 y1[set] = PY(usey1); 01413 y2[set] = PY(usey2); 01414 clr[set] = ExtColor[j][i]; 01415 clrshd[set] = ExtColorShd[j][i]; /* fred */ 01416 ++set; 01417 } 01418 draw_3d_line( im, 01419 PY(0), 01420 PX(i-1), PX(i), 01421 y1, y2, 01422 xdepth_3D, ydepth_3D, 01423 set, 01424 clr, 01425 clrshd ); 01426 } 01427 } 01428 } 01429 break; 01430 01431 case GDC_AREA: 01432 case GDC_3DAREA: 01433 switch( GDC_stack_type ) 01434 { 01435 case GDC_STACK_SUM: 01436 { 01437 float lasty[num_points]; 01438 j = 0; 01439 for( i=1; i<num_points; ++i ) 01440 if( uvals[j][i] != GDC_NOVALUE ) 01441 { 01442 lasty[i] = uvals[j][i]; 01443 if( uvals[j][i-1] != GDC_NOVALUE ) 01444 draw_3d_area( im, PX(i-1), PX(i), 01445 PY(0), PY(uvals[j][i-1]), PY(uvals[j][i]), 01446 xdepth_3D, ydepth_3D, 01447 ExtColor[j][i], 01448 threeD? ExtColorShd[j][i]: ExtColor[j][i] ); 01449 } 01450 for( j=1; j<num_sets; ++j ) 01451 for( i=1; i<num_points; ++i ) 01452 if( uvals[j][i] != GDC_NOVALUE && uvals[j][i-1] != GDC_NOVALUE ) 01453 { 01454 draw_3d_area( im, PX(i-1), PX(i), 01455 PY(lasty[i]), PY(lasty[i-1]+uvals[j][i-1]), PY(lasty[i]+uvals[j][i]), 01456 xdepth_3D, ydepth_3D, 01457 ExtColor[j][i], 01458 threeD? ExtColorShd[j][i]: ExtColor[j][i] ); 01459 lasty[i] += uvals[j][i]; 01460 } 01461 } 01462 break; 01463 01464 case GDC_STACK_BESIDE: // behind w/o depth 01465 for( j=num_sets-1; j>=0; --j ) // back sets 1st (setno = 0) 01466 for( i=1; i<num_points; ++i ) 01467 if( uvals[j][i-1] != GDC_NOVALUE && uvals[j][i] != GDC_NOVALUE ) 01468 draw_3d_area( im, PX(i-1), PX(i), 01469 PY(0), PY(uvals[j][i-1]), PY(uvals[j][i]), 01470 xdepth_3D, ydepth_3D, 01471 ExtColor[j][i], 01472 threeD? ExtColorShd[j][i]: ExtColor[j][i] ); 01473 break; 01474 01475 case GDC_STACK_DEPTH: 01476 default: 01477 for( setno=num_sets-1; setno>=0; --setno ) // back sets first PX, PY depth 01478 for( i=1; i<num_points; ++i ) 01479 if( uvals[setno][i-1] != GDC_NOVALUE && uvals[setno][i] != GDC_NOVALUE ) 01480 draw_3d_area( im, PX(i-1), PX(i), 01481 PY(0), PY(uvals[setno][i-1]), PY(uvals[setno][i]), 01482 xdepth_3D, ydepth_3D, 01483 ExtColor[setno][i], 01484 threeD? ExtColorShd[setno][i]: ExtColor[setno][i] ); 01485 setno = 0; 01486 } 01487 break; 01488 01489 case GDC_3DHILOCLOSE: 01490 case GDC_3DCOMBO_HLC_BAR: 01491 case GDC_3DCOMBO_HLC_AREA: 01492 { 01493 gdPoint poly[4]; 01494 for( j=num_hlc_sets-1; j>=0; --j ) 01495 { 01496 for( i=1; i<num_points+1; ++i ) 01497 if( uvals[CLOSESET+j*3][i-1] != GDC_NOVALUE ) 01498 { 01499 if( (GDC_HLC_style & GDC_HLC_I_CAP) && // bottom half of 'I' 01500 uvals[LOWSET+j*3][i-1] != GDC_NOVALUE ) 01501 { 01502 SET_3D_POLY( poly, PX(i-1)-hlf_hlccapwdth, PX(i-1)+hlf_hlccapwdth, 01503 PY(uvals[LOWSET+j*3][i-1]), PY(uvals[LOWSET+j*3][i-1]), 01504 xdepth_3D, ydepth_3D ); 01505 gdImageFilledPolygon( im, poly, 4, ExtColor[LOWSET+j*3][i-1] ); 01506 gdImagePolygon( im, poly, 4, ExtColorShd[LOWSET+j*3][i-1] ); 01507 } 01508 // all HLC have vert line 01509 if( uvals[LOWSET+j*3][i-1] != GDC_NOVALUE ) 01510 { // bottom 'half' 01511 SET_3D_POLY( poly, PX(i-1), PX(i-1), 01512 PY(uvals[LOWSET+j*3][i-1]), PY(uvals[CLOSESET+j*3][i-1]), 01513 xdepth_3D, ydepth_3D ); 01514 gdImageFilledPolygon( im, poly, 4, ExtColor[LOWSET+j*3][i-1] ); 01515 gdImagePolygon( im, poly, 4, ExtColorShd[LOWSET+j*3][i-1] ); 01516 } 01517 if( uvals[HIGHSET+j*3][i-1] != GDC_NOVALUE ) 01518 { // top 'half' 01519 SET_3D_POLY( poly, PX(i-1), PX(i-1), 01520 PY(uvals[CLOSESET+j*3][i-1]), PY(uvals[HIGHSET+j*3][i-1]), 01521 xdepth_3D, ydepth_3D ); 01522 gdImageFilledPolygon( im, poly, 4, ExtColor[HIGHSET+j*3][i-1] ); 01523 gdImagePolygon( im, poly, 4, ExtColorShd[HIGHSET+j*3][i-1] ); 01524 } 01525 // line at close 01526 gdImageLine( im, PX(i-1), PY(uvals[CLOSESET+j*3][i-1]), 01527 PX(i-1)+xdepth_3D, PY(uvals[CLOSESET+j*3][i-1])-ydepth_3D, 01528 ExtColorShd[CLOSESET+j*3][i-1] ); 01529 // top half 'I' 01530 if( !( (GDC_HLC_style & GDC_HLC_DIAMOND) && 01531 (PY(uvals[HIGHSET+j*3][i-1]) > PY(uvals[CLOSESET+j*3][i-1])-hlf_hlccapwdth) ) && 01532 uvals[HIGHSET+j*3][i-1] != GDC_NOVALUE ) 01533 if( GDC_HLC_style & GDC_HLC_I_CAP ) 01534 { 01535 SET_3D_POLY( poly, PX(i-1)-hlf_hlccapwdth, PX(i-1)+hlf_hlccapwdth, 01536 PY(uvals[HIGHSET+j*3][i-1]), PY(uvals[HIGHSET+j*3][i-1]), 01537 xdepth_3D, ydepth_3D ); 01538 gdImageFilledPolygon( im, poly, 4, ExtColor[HIGHSET+j*3][i-1] ); 01539 gdImagePolygon( im, poly, 4, ExtColorShd[HIGHSET+j*3][i-1] ); 01540 } 01541 01542 if( i < num_points && 01543 uvals[CLOSESET+j*3][i] != GDC_NOVALUE ) 01544 { 01545 if( GDC_HLC_style & GDC_HLC_CLOSE_CONNECTED ) /* line from prev close */ 01546 { 01547 SET_3D_POLY( poly, PX(i-1), PX(i), 01548 PY(uvals[CLOSESET+j*3][i-1]), PY(uvals[CLOSESET+j*3][i-1]), 01549 xdepth_3D, ydepth_3D ); 01550 gdImageFilledPolygon( im, poly, 4, ExtColor[CLOSESET+j*3][i] ); 01551 gdImagePolygon( im, poly, 4, ExtColorShd[CLOSESET+j*3][i] ); 01552 } 01553 else // CLOSE_CONNECTED and CONNECTING are mutually exclusive 01554 if( GDC_HLC_style & GDC_HLC_CONNECTING ) /* thin connecting line */ 01555 { 01556 int y1 = PY(uvals[CLOSESET+j*3][i-1]), 01557 y2 = PY(uvals[CLOSESET+j*3][i]); 01558 draw_3d_line( im, 01559 PY(0), 01560 PX(i-1), PX(i), 01561 &y1, &y2, // rem only 1 set 01562 xdepth_3D, ydepth_3D, 01563 1, 01564 &(ExtColor[CLOSESET+j*3][i]), 01565 &(ExtColorShd[CLOSESET+j*3][i]) ); 01566 // edge font of it 01567 gdImageLine( im, PX(i-1), PY(uvals[CLOSESET+j*3][i-1]), 01568 PX(i), PY(uvals[CLOSESET+j*3][i]), 01569 ExtColorShd[CLOSESET+j*3][i] ); 01570 } 01571 // top half 'I' again 01572 if( PY(uvals[CLOSESET+j*3][i-1]) <= PY(uvals[CLOSESET+j*3][i]) && 01573 uvals[HIGHSET+j*3][i-1] != GDC_NOVALUE ) 01574 if( GDC_HLC_style & GDC_HLC_I_CAP ) 01575 { 01576 SET_3D_POLY( poly, PX(i-1)-hlf_hlccapwdth, PX(i-1)+hlf_hlccapwdth, 01577 PY(uvals[HIGHSET+j*3][i-1]), PY(uvals[HIGHSET+j*3][i-1]), 01578 xdepth_3D, ydepth_3D ); 01579 gdImageFilledPolygon( im, poly, 4, ExtColor[HIGHSET+j*3][i-1] ); 01580 gdImagePolygon( im, poly, 4, ExtColorShd[HIGHSET+j*3][i-1] ); 01581 } 01582 } 01583 if( GDC_HLC_style & GDC_HLC_DIAMOND ) 01584 { // front 01585 poly[0].x = PX(i-1)-hlf_hlccapwdth; 01586 poly[0].y = PY(uvals[CLOSESET+j*3][i-1]); 01587 poly[1].x = PX(i-1); 01588 poly[1].y = PY(uvals[CLOSESET+j*3][i-1])+hlf_hlccapwdth; 01589 poly[2].x = PX(i-1)+hlf_hlccapwdth; 01590 poly[2].y = PY(uvals[CLOSESET+j*3][i-1]); 01591 poly[3].x = PX(i-1); 01592 poly[3].y = PY(uvals[CLOSESET+j*3][i-1])-hlf_hlccapwdth; 01593 gdImageFilledPolygon( im, poly, 4, ExtColor[CLOSESET+j*3][i-1] ); 01594 gdImagePolygon( im, poly, 4, ExtColorShd[CLOSESET+j*3][i-1] ); 01595 // bottom side 01596 SET_3D_POLY( poly, PX(i-1), PX(i-1)+hlf_hlccapwdth, 01597 PY(uvals[CLOSESET+j*3][i-1])+hlf_hlccapwdth, 01598 PY(uvals[CLOSESET+j*3][i-1]), 01599 xdepth_3D, ydepth_3D ); 01600 gdImageFilledPolygon( im, poly, 4, ExtColorShd[CLOSESET+j*3][i-1] ); 01601 // gdImagePolygon( im, poly, 4, ExtColor[CLOSESET+j*3][i-1] ); 01602 // top side 01603 SET_3D_POLY( poly, PX(i-1), PX(i-1)+hlf_hlccapwdth, 01604 PY(uvals[CLOSESET+j*3][i-1])-hlf_hlccapwdth, 01605 PY(uvals[CLOSESET+j*3][i-1]), 01606 xdepth_3D, ydepth_3D ); 01607 gdImageFilledPolygon( im, poly, 4, ExtColor[CLOSESET+j*3][i-1] ); 01608 gdImagePolygon( im, poly, 4, ExtColorShd[CLOSESET+j*3][i-1] ); 01609 } 01610 } 01611 } 01612 } 01613 break; 01614 01615 case GDC_HILOCLOSE: 01616 case GDC_COMBO_HLC_BAR: 01617 case GDC_COMBO_HLC_AREA: 01618 for( j=num_hlc_sets-1; j>=0; --j ) 01619 { 01620 for( i=0; i<num_points; ++i ) 01621 if( uvals[CLOSESET+j*3][i] != GDC_NOVALUE ) 01622 { /* all HLC have vert line */ 01623 if( uvals[LOWSET+j*3][i] != GDC_NOVALUE ) 01624 gdImageLine( im, PX(i), PY(uvals[CLOSESET+j*3][i]), 01625 PX(i), PY(uvals[LOWSET+j*3][i]), 01626 ExtColor[LOWSET+(j*3)][i] ); 01627 if( uvals[HIGHSET+j*3][i] != GDC_NOVALUE ) 01628 gdImageLine( im, PX(i), PY(uvals[HIGHSET+j*3][i]), 01629 PX(i), PY(uvals[CLOSESET+j*3][i]), 01630 ExtColor[HIGHSET+j*3][i] ); 01631 01632 if( GDC_HLC_style & GDC_HLC_I_CAP ) 01633 { 01634 if( uvals[LOWSET+j*3][i] != GDC_NOVALUE ) 01635 gdImageLine( im, PX(i)-hlf_hlccapwdth, PY(uvals[LOWSET+j*3][i]), 01636 PX(i)+hlf_hlccapwdth, PY(uvals[LOWSET+j*3][i]), 01637 ExtColor[LOWSET+j*3][i] ); 01638 if( uvals[HIGHSET+j*3][i] != GDC_NOVALUE ) 01639 gdImageLine( im, PX(i)-hlf_hlccapwdth, PY(uvals[HIGHSET+j*3][i]), 01640 PX(i)+hlf_hlccapwdth, PY(uvals[HIGHSET+j*3][i]), 01641 ExtColor[HIGHSET+j*3][i] ); 01642 } 01643 if( GDC_HLC_style & GDC_HLC_DIAMOND ) 01644 { 01645 gdPoint cd[4]; 01646 01647 cd[0].x = PX(i)-hlf_hlccapwdth; cd[0].y = PY(uvals[CLOSESET+j*3][i]); 01648 cd[1].x = PX(i); cd[1].y = PY(uvals[CLOSESET+j*3][i])+hlf_hlccapwdth; 01649 cd[2].x = PX(i)+hlf_hlccapwdth; cd[2].y = PY(uvals[CLOSESET+j*3][i]); 01650 cd[3].x = PX(i); cd[3].y = PY(uvals[CLOSESET+j*3][i])-hlf_hlccapwdth; 01651 gdImageFilledPolygon( im, cd, 4, ExtColor[CLOSESET+j*3][i] ); 01652 } 01653 } 01654 for( i=1; i<num_points; ++i ) 01655 if( uvals[CLOSESET+j*3][i-1] != GDC_NOVALUE && uvals[CLOSESET+j*3][i] != GDC_NOVALUE ) 01656 { 01657 if( GDC_HLC_style & GDC_HLC_CLOSE_CONNECTED ) // line from prev close 01658 gdImageLine( im, PX(i-1), PY(uvals[CLOSESET+j*3][i-1]), 01659 PX(i), PY(uvals[CLOSESET+j*3][i-1]), 01660 ExtColor[CLOSESET+j*3][i] ); 01661 else // CLOSE_CONNECTED and CONNECTING are mutually exclusive 01662 if( GDC_HLC_style & GDC_HLC_CONNECTING ) // thin connecting line 01663 gdImageLine( im, PX(i-1), PY(uvals[CLOSESET+j*3][i-1]), 01664 PX(i), PY(uvals[CLOSESET+j*3][i]), 01665 ExtColor[CLOSESET+j*3][i] ); 01666 } 01667 } 01668 break; 01669 } 01670 setno = 0; 01671 01672 /* ---------- scatter points over all other plots ---------- */ 01673 /* scatters, by their very nature, don't lend themselves to standard array of points */ 01674 /* also, this affords the opportunity to include scatter points onto any type of chart */ 01675 /* drawing of the scatter point should be an exposed function, so the user can */ 01676 /* use it to draw a legend, and/or add their own */ 01677 if( GDC_scatter ) 01678 { 01679 int scatter_clr[GDC_num_scatter_pts]; 01680 gdPoint ct[3]; 01681 01682 for( i=0; i<GDC_num_scatter_pts; ++i ) 01683 { 01684 int hlf_scatterwdth = (int)( (float)(PX(2)-PX(1)) 01685 * (((float)((GDC_scatter+i)->width)/100.0)/2.0) ); 01686 int scat_x = PX( (GDC_scatter+i)->point + (do_bar?1:0) ), 01687 scat_y = PY( (GDC_scatter+i)->val ); 01688 01689 if( (GDC_scatter+i)->point >= num_points || // invalid point 01690 (GDC_scatter+i)->point < 0 ) 01691 continue; 01692 scatter_clr[i] = clrallocate( im, (GDC_scatter+i)->color ); 01693 01694 switch( (GDC_scatter+i)->ind ) 01695 { 01696 case GDC_SCATTER_TRIANGLE_UP: 01697 ct[0].x = scat_x; 01698 ct[0].y = scat_y; 01699 ct[1].x = scat_x - hlf_scatterwdth; 01700 ct[1].y = scat_y + hlf_scatterwdth;; 01701 ct[2].x = scat_x + hlf_scatterwdth; 01702 ct[2].y = scat_y + hlf_scatterwdth; 01703 if( !do_bar ) 01704 if( (GDC_scatter+i)->point == 0 ) 01705 ct[1].x = scat_x; 01706 else 01707 if( (GDC_scatter+i)->point == num_points-1 ) 01708 ct[2].x = scat_x; 01709 gdImageFilledPolygon( im, ct, 3, scatter_clr[i] ); 01710 break; 01711 case GDC_SCATTER_TRIANGLE_DOWN: 01712 ct[0].x = scat_x; 01713 ct[0].y = scat_y; 01714 ct[1].x = scat_x - hlf_scatterwdth; 01715 ct[1].y = scat_y - hlf_scatterwdth;; 01716 ct[2].x = scat_x + hlf_scatterwdth; 01717 ct[2].y = scat_y - hlf_scatterwdth; 01718 if( !do_bar ) 01719 if( (GDC_scatter+i)->point == 0 ) 01720 ct[1].x = scat_x; 01721 else 01722 if( (GDC_scatter+i)->point == num_points-1 ) 01723 ct[2].x = scat_x; 01724 gdImageFilledPolygon( im, ct, 3, scatter_clr[i] ); 01725 break; 01726 } 01727 } 01728 } 01729 01730 01731 // overlay with a value and an arrow (e.g., total daily change) 01732 #ifdef THUMB_VALS 01733 /* put thmbl and thumbval over vol and plot lines */ 01734 if( thumbnail ) 01735 { 01736 int n, d, w; 01737 char thmbl[32]; 01738 char *price_to_str( float, int*, int*, int* ); 01739 char nmrtr[3+1], dmntr[3+1], whole[8]; 01740 01741 char *dbg = price_to_str( ABS(thumbval),&n,&d,&w ); 01742 sprintf( nmrtr, "%d", n ); 01743 sprintf( dmntr, "%d", d ); 01744 sprintf( whole, "%d", w ); 01745 01746 gdImageString( im, 01747 gdFontSmall, 01748 graphwidth/2-strlen(thumblabel)*SFONTWDTH/2, 01749 1, 01750 thumblabel, 01751 ThumbLblColor ); 01752 if( w || n ) 01753 { 01754 int chgcolor = thumbval>0.0? ThumbUColor: ThumbDColor; 01755 int thmbvalwidth = SFONTWDTH + // up/down arrow 01756 (w?strlen(whole)*SFONTWDTH: 0) + // whole 01757 (n?strlen(nmrtr)*TFONTWDTH + // numerator 01758 SFONTWDTH + // / 01759 strlen(dmntr)*TFONTWDTH: // denominator 01760 0); // no frac part 01761 01762 smallarrow( im, graphwidth/2-thmbvalwidth/2, SFONTHGT, thumbval>0.0, chgcolor ); 01763 if( w ) 01764 { 01765 gdImageString( im, 01766 gdFontSmall, 01767 (graphwidth/2-thmbvalwidth/2)+SFONTWDTH, 01768 SFONTHGT+2, 01769 whole, 01770 chgcolor ); 01771 } 01772 if( n ) 01773 { 01774 gdImageString( im, 01775 gdFontTiny, 01776 (graphwidth/2-thmbvalwidth/2) + // start 01777 SFONTWDTH + // arrow 01778 (w? strlen(whole)*SFONTWDTH: 0) + // whole 01779 2, 01780 SFONTHGT+2-2, 01781 nmrtr, 01782 chgcolor ); 01783 gdImageChar ( im, 01784 gdFontSmall, 01785 (graphwidth/2-thmbvalwidth/2) + // start 01786 SFONTWDTH + // arrow 01787 (w? strlen(whole)*SFONTWDTH: 0) + // whole 01788 strlen(nmrtr)*TFONTWDTH, // numerator 01789 SFONTHGT+2, 01790 '/', 01791 chgcolor ); 01792 gdImageString( im, 01793 gdFontTiny, 01794 (graphwidth/2-thmbvalwidth/2) + // start 01795 SFONTWDTH + // arrow 01796 (w? strlen(whole)*SFONTWDTH: 0) + // whole 01797 strlen(nmrtr)*TFONTWDTH + // numerator 01798 SFONTWDTH - 3, // / 01799 SFONTHGT+2+4, 01800 dmntr, 01801 chgcolor ); 01802 } 01803 } 01804 } // thumblabel, thumbval 01805 #endif 01806 01807 /* box it off */ 01808 /* after plotting so the outline covers any plot lines */ 01809 if( GDC_border ) 01810 { 01811 gdImageLine( im, PX(0), PY(lowest), PX(num_points-1+(do_bar?2:0)), PY(lowest), LineColor ); 01812 01813 setno = GDC_stack_type==GDC_STACK_DEPTH? num_hlc_sets? num_hlc_sets: num_sets: 1; 01814 gdImageLine( im, PX(0), PY(highest), PX(num_points-1+(do_bar?2:0)), PY(highest), LineColor ); 01815 setno = 0; 01816 } 01817 if( GDC_border ) 01818 { 01819 int x1, y1, x2, y2; 01820 01821 x1 = PX(0); 01822 y1 = PY(highest); 01823 x2 = PX(num_points-1+(do_bar?2:0)); 01824 y2 = PY(lowest); 01825 gdImageLine( im, x1, PY(lowest), x1, y1, LineColor ); 01826 01827 setno = GDC_stack_type==GDC_STACK_DEPTH? num_hlc_sets? num_hlc_sets: num_sets: 1; 01828 gdImageLine( im, x1, y1, PX(0), PY(highest), LineColor ); 01829 // if( !GDC_grid || do_vol || GDC_thumbnail ) // grid leaves right side Y open 01830 { 01831 gdImageLine( im, x2, y2, PX(num_points-1+(do_bar?2:0)), PY(lowest), LineColor ); 01832 gdImageLine( im, PX(num_points-1+(do_bar?2:0)), PY(lowest), 01833 PX(num_points-1+(do_bar?2:0)), PY(highest), LineColor ); 01834 } 01835 setno = 0; 01836 } 01837 01838 if( GDC_0Shelf && threeD && /* front of 0 shelf */ 01839 ( (lowest < 0.0 && highest > 0.0) || 01840 (lowest < 0.0 && highest > 0.0) ) ) 01841 { 01842 int x2 = PX( num_points-1+(do_bar?2:0) ), 01843 y2 = PY( 0 ); 01844 01845 gdImageLine( im, PX(0), PY(0), x2, y2, LineColor ); // front line 01846 setno = GDC_stack_type==GDC_STACK_DEPTH? num_hlc_sets? num_hlc_sets: num_sets: 01847 1; // backmost 01848 // depth for 3Ds 01849 gdImageLine( im, x2, y2, PX(num_points-1+(do_bar?2:0)), PY(0), LineColor ); 01850 setno = 0; // set back to foremost 01851 } 01852 01853 if( GDC_annotation ) /* front half of annotation line */ 01854 { 01855 int x1 = PX(GDC_annotation->point+(do_bar?1:0)), 01856 y1 = PY(highest); 01857 int x2; 01858 // front line 01859 gdImageLine( im, x1, PY(lowest)+1, x1, y1, AnnoteColor ); 01860 if( threeD ) 01861 { // on back plane 01862 setno = GDC_stack_type==GDC_STACK_DEPTH? num_hlc_sets? num_hlc_sets: num_sets: 1; 01863 x2 = PX(GDC_annotation->point+(do_bar?1:0)); 01864 // prspective line 01865 gdImageLine( im, x1, y1, x2, PY(highest), AnnoteColor ); 01866 } 01867 else // for 3D done with back line 01868 { 01869 x2 = PX(GDC_annotation->point+(do_bar?1:0)); 01870 gdImageLine( im, x1, y1, x1, y1-2, AnnoteColor ); 01871 } 01872 /* line-to and note */ 01873 if( *(GDC_annotation->note) ) // any note? 01874 { 01875 if( GDC_annotation->point >= (num_points/2) ) /* note to the left */ 01876 { 01877 gdImageLine( im, x2, PY(highest)-2, 01878 x2-annote_hgt/2, PY(highest)-2-annote_hgt/2, 01879 AnnoteColor ); 01880 GDCImageStringNL( im, 01881 &GDC_fontc[GDC_annotation_font], 01882 x2-annote_hgt/2-1-annote_len - 1, 01883 PY(highest)-annote_hgt+1, 01884 GDC_annotation->note, 01885 AnnoteColor, 01886 GDC_JUSTIFY_RIGHT ); 01887 } 01888 else /* note to right */ 01889 { 01890 gdImageLine( im, x2, PY(highest)-2, 01891 x2+annote_hgt/2, PY(highest)-2-annote_hgt/2, 01892 AnnoteColor ); 01893 GDCImageStringNL( im, 01894 &GDC_fontc[GDC_annotation_font], 01895 x2+annote_hgt/2+1 + 1, 01896 PY(highest)-annote_hgt+1, 01897 GDC_annotation->note, 01898 AnnoteColor, 01899 GDC_JUSTIFY_LEFT ); 01900 } 01901 } 01902 setno = 0; 01903 } 01904 01905 01906 /* usually GDC_generate_gif is used in conjunction with hard or hold options */ 01907 if( GDC_generate_gif ) 01908 { 01909 fflush(gif_fptr); // clear anything buffered 01910 gdImageGif( im, gif_fptr ); 01911 } 01912 01913 if( bg_img ) 01914 gdImageDestroy(bg_img); 01915 if( GDC_hold_img & GDC_EXPOSE_IMAGE ) 01916 GDC_image = (void*)im; 01917 else 01918 gdImageDestroy(im); 01919 return 0; 01920 #endif 01921 }
| EXTERND char* GDC_thumblabel |
| EXTERND char* GDC_xtitle |
| EXTERND char* GDC_ytitle |
| EXTERND char* GDC_ytitle2 |
1.5.1