📄 gdchart.c
字号:
/* args */ int setno = 0; /* affects PX() and PY()*/ int _dim_ = ( type == GDC_HILOCLOSE || type == GDC_3DHILOCLOSE || type == GDC_3DCOMBO_HLC_BAR || type == GDC_3DCOMBO_HLC_AREA || type == GDC_COMBO_HLC_BAR || type == GDC_COMBO_HLC_AREA? (num_sets = num_sets * 3): /* 1 more last set is vol*/ type == GDC_COMBO_LINE_BAR || type == GDC_3DCOMBO_LINE_BAR || type == GDC_3DCOMBO_LINE_AREA|| type == GDC_COMBO_LINE_AREA? num_sets:num_sets );#ifdef USE_ALLOCA float **uvals = (float**)alloca (_dim_ * sizeof (float));#else float *uvals[ _dim_];#endif /* USE_ALLOCA */ float *uvol = NULL; int BGColor, LineColor, PlotColor, GridColor, VolColor = 0,#ifdef USE_ALLOCA *ExtVolColor = (int*)alloca (num_points * sizeof (int)),#else ExtVolColor[num_points],#endif /* USE_ALLOCA *//* ArrowDColor,*//* ArrowUColor,*/ AnnoteColor = 0,#ifdef USE_ALLOCA *ExtColor = (int*)alloca (num_sets * num_points * sizeof (int));#else ExtColor[num_sets][num_points];#endif /* USE_ALLOCA */ /* shade colors only with 3D*//* int ExtColorShd[threeD?1:num_sets][threeD?1:num_points];*/ /* compiler limitation*/ int#ifdef USE_ALLOCA *ExtColorShd = (int*)alloca (num_sets * num_points * sizeof (int));#else ExtColorShd[num_sets][num_points];#endif /* USE_ALLOCA */ /* idiot checks */ if( GIFWIDTH<=0 || GIFHEIGHT<=0 || (!gif_fptr && GDC_generate_gif) ) return -1; if( num_points <= 0 ) { out_err( GIFWIDTH, GIFHEIGHT, gif_fptr, GDC_BGColor, GDC_LineColor, "No Data Available" ); return 1; } load_font_conversions(); if( GDC_thumbnail ) { GDC_grid = FALSE; GDC_xaxis = FALSE; GDC_yaxis = FALSE; } /* ----- get args va number of float arrays -----*/ va_start( ap, num_sets ); for( i=0; i<num_sets; ++i ) uvals[i] = va_arg(ap, float*); if( do_vol ) uvol = va_arg(ap, float*); va_end(ap); /* ----- highest & lowest values ----- */ if( GDC_stack_type == GDC_STACK_SUM ) /* need to walk sideways*/ for( j=0; j<num_points; ++j ) { float set_sum = 0.0; for( i=0; i<num_sets; ++i ) if( uvals[i][j] != GDC_NOVALUE ) { set_sum += uvals[i][j]; highest = MAX( highest, set_sum ); lowest = MIN( lowest, set_sum ); } } else if( GDC_stack_type == GDC_STACK_LAYER ) /* need to walk sideways*/ for( j=0; j<num_points; ++j ) { float neg_set_sum = 0.0, pos_set_sum = 0.0; for( i=0; i<num_sets; ++i ) if( uvals[i][j] != GDC_NOVALUE ) { if( uvals[i][j] < 0.0 ) neg_set_sum += uvals[i][j]; else pos_set_sum += uvals[i][j]; } lowest = MIN( lowest, MIN(neg_set_sum,pos_set_sum) ); highest = MAX( highest, MAX(neg_set_sum,pos_set_sum) ); } else for( i=0; i<num_sets; ++i ) for( j=0; j<num_points; ++j ) if( uvals[i][j] != GDC_NOVALUE ) { highest = MAX( uvals[i][j], highest ); lowest = MIN( uvals[i][j], lowest ); } if( GDC_scatter ) for( i=0; i<GDC_num_scatter_pts; ++i ) { highest = MAX( (GDC_scatter+i)->val, highest ); lowest = MIN( (GDC_scatter+i)->val, lowest ); } if( do_vol ) /* for now only one combo set allowed*/ { /* vhighest = 1.0;*/ /* vlowest = 0.0;*/ for( j=0; j<num_points; ++j ) if( uvol[j] != GDC_NOVALUE ) { vhighest = MAX( uvol[j], vhighest ); vlowest = MIN( uvol[j], vlowest ); } if( vhighest == -MAXFLOAT ) /* no values*/ vhighest = 1.0; /* for scaling, need a range*/ else if( vhighest < 0.0 ) vhighest = 0.0; if( vlowest > 0.0 || vlowest == MAXFLOAT ) vlowest = 0.0; /* vol should always start at 0*/ } if( lowest == MAXFLOAT ) lowest = 0.0; if( highest == -MAXFLOAT ) highest = 1.0; /* need a range*/ if( type == GDC_AREA || /* bars and area should always start at 0*/ type == GDC_BAR || type == GDC_3DBAR || type == GDC_3DAREA ) { if( highest < 0.0 ) highest = 0.0; else if( lowest > 0.0 ) /* negs should be drawn from 0*/ lowest = 0.0; } if( GDC_requested_ymin != GDC_NOVALUE && GDC_requested_ymin < lowest ) lowest = GDC_requested_ymin; if( GDC_requested_ymax != GDC_NOVALUE && GDC_requested_ymax > highest ) highest = GDC_requested_ymax; /* ----- graph height and width within the gif height width ----- */ /* grapheight/height is the actual size of the scalable graph */ { int title_hgt = GDC_title? 2 /* title? horizontal text line(s) */ + cnt_nl(GDC_title,(int*)NULL)*GDC_fontc[GDC_title_size].h + 2: 2; int xlabel_hgt = 0; int xtitle_hgt = GDC_xtitle? 1+GDC_fontc[GDC_xtitle_size].h+1: 0; int ytitle_hgt = GDC_ytitle? 1+GDC_fontc[GDC_ytitle_size].h+1: 0; int vtitle_hgt = do_vol&&GDC_ytitle2? 1+GDC_fontc[GDC_ytitle_size].h+1: 0; int ylabel_wth = 0; int vlabel_wth = 0; int xtics = GDC_grid||GDC_xaxis? 1+2: 0; int ytics = GDC_grid||GDC_yaxis? 1+3: 0; int vtics = GDC_yaxis&&do_vol? 3+1: 0;#define HYP_DEPTH ( (double)((GIFWIDTH+GIFHEIGHT)/2) * ((double)GDC_3d_depth)/100.0 )#define RAD_DEPTH ( (double)GDC_3d_angle*2*M_PI/360 ) xdepth_3D = threeD? (int)( cos(RAD_DEPTH) * HYP_DEPTH ): 0; ydepth_3D = threeD? (int)( sin(RAD_DEPTH) * HYP_DEPTH ): 0; xdepth_3Dtotal = xdepth_3D*(GDC_stack_type==GDC_STACK_DEPTH? num_hlc_sets? num_hlc_sets: num_sets: 1 ); ydepth_3Dtotal = ydepth_3D*(GDC_stack_type==GDC_STACK_DEPTH? num_hlc_sets? num_hlc_sets: num_sets: 1 ); annote_hgt = GDC_annotation && *(GDC_annotation->note)? 1 + /* space to note */ (1+GDC_fontc[GDC_annotation_font].h) * /* number of '\n' substrs */ cnt_nl(GDC_annotation->note,&annote_len) + 1 + /* space under note */ 2: 0; /* space to chart */ annote_len *= GDC_fontc[GDC_annotation_font].w; if( GDC_xaxis && xlbl ) { int biggest = 0 - (MAXINT); for( i=0; i<num_points; ++i ) { int len = 0; /* longest "...\n" segment*/ for( len=0, j=0; xlbl[i][j]; ++len, ++j ) if( xlbl[i][j] == '\n' ) { biggest = MAX( len, biggest ); ++num_lf_xlbls; len = 0; } biggest = MAX( len, biggest ); /* last seg*/ } xlabel_hgt = 1+ biggest*GDC_fontc[GDC_xaxisfont_size].w +1; } grapheight = GIFHEIGHT - ( xtics + xtitle_hgt + xlabel_hgt + title_hgt + annote_hgt + ydepth_3Dtotal + 2 ); if( GDC_hard_size && GDC_hard_grapheight ) /* user wants to use his */ grapheight = GDC_hard_grapheight; GDC_hard_grapheight = grapheight; /* before width can be known...*/ /* ----- y labels intervals ----- */ { float tmp_highest; /* possible y gridline points */ 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, 1.0, 2.0, 3.0, 5.0, 10.0, 25.0, 50.0, 100.0, 250.0, 500.0, 1000.0, 2500, 5000.0, 10000.0, 25000.0, 50000.0, 100000.0,500000.0,1000000, 5000000, 10000000 }; #define NUM_YPOINTS (sizeof(ypoints) / sizeof(float)) int max_num_ylbls; int longest_ylblen = 0; /* maximum y lables that'll fit... */ max_num_ylbls = grapheight / (3+GDC_fontc[GDC_yaxisfont_size==GDC_TINY? GDC_yaxisfont_size+1: GDC_yaxisfont_size].h); if( max_num_ylbls < 3 ) { /* gdImageDestroy(im); haven't yet created it */ out_err( GIFWIDTH, GIFHEIGHT, gif_fptr, GDC_BGColor, GDC_LineColor, "Insificient Height" ); return 2; } /* one "space" interval above + below */ for( i=1; i<NUM_YPOINTS; ++i ) /* if( ypoints[i] > ylbl_interval )*/ /* break;*/ if( (highest-lowest)/ypoints[i] < ((float)max_num_ylbls-(1.0+1.0)) * (float)GDC_ylabel_density/100.0 ) break; /* gotta go through the above loop to catch the 'tweeners :-| */ ylbl_interval = GDC_requested_yinterval != GDC_NOVALUE && GDC_requested_yinterval > ypoints[i-1]? GDC_requested_yinterval: ypoints[i-1]; /* perform floating point remainders */ /* gonculate largest interval-point < lowest */ if( lowest != 0.0 && lowest != GDC_requested_ymin ) { if( lowest < 0.0 ) lowest -= ylbl_interval; /* lowest = (lowest-ypoints[0]) -*/ /* ( ( ((lowest-ypoints[0])/ylbl_interval)*ylbl_interval ) -*/ /* ( (float)((int)((lowest-ypoints[0])/ylbl_interval))*ylbl_interval ) );*/ lowest = ylbl_interval * (float)(int)((lowest-ypoints[0])/ylbl_interval); } /* find smallest interval-point > highest */ tmp_highest = lowest; do /* while( (tmp_highest += ylbl_interval) <= highest )*/ { int nmrtr, dmntr, whole; char *price_to_str( float, int*, int*, int*, char* ); int lbl_len; char foo[32]; if( GDC_yaxis ) { /* XPG2 compatibility */ sprintf( foo, do_ylbl_fractions? "%.0f": GDC_ylabel_fmt, tmp_highest ); lbl_len = ylbl_interval<1.0? strlen( price_to_str(tmp_highest, &nmrtr, &dmntr, &whole, do_ylbl_fractions? NULL: GDC_ylabel_fmt) ): strlen( foo ); longest_ylblen = MAX( longest_ylblen, lbl_len ); } } while( (tmp_highest += ylbl_interval) <= highest ); ylabel_wth = longest_ylblen * GDC_fontc[GDC_yaxisfont_size].w; highest = GDC_requested_ymax==GDC_NOVALUE? tmp_highest: MAX( GDC_requested_ymax, highest ); if( do_vol ) { float num_yintrvls = (highest-lowest) / ylbl_interval; /* no skyscrapers */ if( vhighest != 0.0 ) vhighest += (vhighest-vlowest) / (num_yintrvls*2.0); if( vlowest != 0.0 ) vlowest -= (vhighest-vlowest) / (num_yintrvls*2.0); if( GDC_yaxis2 ) { char svlongest[32]; int lbl_len_low = sprintf( svlongest, GDC_ylabel2_fmt? GDC_ylabel2_fmt: "%.0f", vlowest ); int lbl_len_high = sprintf( svlongest, GDC_ylabel2_fmt? GDC_ylabel2_fmt: "%.0f", vhighest ); vlabel_wth = 1 + MAX( lbl_len_low,lbl_len_high ) * GDC_fontc[GDC_yaxisfont_size].w; } } } graphwidth = GIFWIDTH - ( ( (GDC_hard_size && GDC_hard_xorig)? GDC_hard_xorig: ( ytitle_hgt + ylabel_wth + ytics ) ) + vtics + vtitle_hgt + vlabel_wth + xdepth_3Dtotal ); if( GDC_hard_size && GDC_hard_graphwidth ) /* user wants to use his */ graphwidth = GDC_hard_graphwidth; GDC_hard_graphwidth = graphwidth; /* ----- scale to gif size ----- */ /* offset to 0 at lower left (where it should be) */ xscl = (float)(graphwidth-xdepth_3Dtotal) / (float)(num_points + (do_bar?2:0)); yscl = -((float)grapheight) / (float)(highest-lowest); if( do_vol ) { float hilow_diff = vhighest-vlowest==0.0? 1.0: vhighest-vlowest; vyscl = -((float)grapheight) / hilow_diff; vyorig = (float)grapheight + ABS(vyscl) * MIN(vlowest,vhighest) + ydepth_3Dtotal + title_hgt + annote_hgt; } xorig = (float)( GIFWIDTH - ( graphwidth + vtitle_hgt + vtics + vlabel_wth ) ); if( GDC_hard_size && GDC_hard_xorig ) xorig = GDC_hard_xorig; GDC_hard_xorig = xorig;/* yorig = (float)grapheight + ABS(yscl * lowest) + ydepth_3Dtotal + title_hgt;*/ yorig = (float)grapheight + ABS(yscl) * MIN(lowest,highest) + ydepth_3Dtotal + title_hgt + annote_hgt;/*???? if( GDC_hard_size && GDC_hard_yorig ) *//*???? yorig = GDC_hard_yorig;*/ GDC_hard_yorig = yorig; hlf_barwdth = (int)( (float)(PX(2)-PX(1)) * (((float)GDC_bar_width/100.0)/2.0) ); /* used only for bars*/ hlf_hlccapwdth = (int)( (float)(PX(2)-PX(1)) * (((float)GDC_HLC_cap_width/100.0)/2.0) ); } /* scaled, sized, ready*/ /* ----- OK start the graphic ----- */ if( (GDC_hold_img & GDC_REUSE_IMAGE) && GDC_image != (void*)NULL ) im = GDC_image; else im = gdImageCreate( GIFWIDTH, GIFHEIGHT ); BGColor = gdImageColorAllocate( im, l2gdcal(GDC_BGColor) ); LineColor = clrallocate( im, GDC_LineColor ); PlotColor = clrallocate( im, GDC_PlotColor ); GridColor = clrallocate( im, GDC_GridColor ); if( do_vol ) { VolColor = clrallocate( im, GDC_VolColor ); for( i=0; i<num_points; ++i ) if( GDC_ExtVolColor )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -