162 var
$data_colors = array(
'SkyBlue',
'green',
'orange',
'blue',
'orange',
'red',
'violet',
'azure1');
163 var
$error_bar_colors = array(
'SkyBlue',
'green',
'orange',
'blue',
'orange',
'red',
'violet',
'azure1');
187 'draw_setup' => NULL,
188 'draw_image_background' => NULL,
189 'draw_plotarea_background' => NULL,
190 'draw_titles' => NULL,
192 'draw_graph' => NULL,
193 'draw_border' => NULL,
194 'draw_legend' => NULL,
195 'debug_textbox' => NULL,
196 'debug_scale' => NULL,
212 function PHPlot($which_width=600, $which_height=400, $which_output_file=NULL, $which_input_file=NULL)
216 $this->background_done = FALSE;
217 $this->plot_margins_set = FALSE;
219 if ($which_output_file)
222 if ($which_input_file)
225 $this->image_width = $which_width;
226 $this->image_height = $which_height;
228 $this->img = ImageCreate($this->image_width, $this->image_height);
230 return $this->
PrintError(
'PHPlot(): Could not create image resource.');
241 $this->print_image = TRUE;
249 function GetImage($image_filename, &$width, &$height)
252 $size = getimagesize($image_filename);
254 $error =
"Unable to query image file $image_filename";
256 $image_type =
$size[2];
257 switch($image_type) {
259 $img = @ ImageCreateFromGIF ($image_filename);
262 $img = @ ImageCreateFromPNG ($image_filename);
265 $img = @ ImageCreateFromJPEG ($image_filename);
268 $error =
"Unknown image type ($image_type) for image file $image_filename";
272 if (empty($error) && !
$img) {
273 # getimagesize is OK, but GD won't read it. Maybe unsupported format.
274 $error =
"Failed to read image file $image_filename";
276 if (!empty($error)) {
277 return $this->
PrintError(
"GetImage(): $error");
291 $im = $this->
GetImage($which_input_file, $this->image_width, $this->image_height);
296 if (isset($this->img))
297 imagedestroy($this->img);
302 $this->background_done = TRUE;
319 list ($r, $g, $b) = $this->
SetRGBColor($which_color);
320 if (!isset($r))
return NULL;
321 return ImageColorResolve($this->img, $r, $g, $b);
331 list ($r, $g, $b) = $this->
SetRGBColor($which_color);
332 if (!isset($r))
return NULL;
333 $r = max(0, $r - 0x30);
334 $g = max(0, $g - 0x30);
335 $b = max(0, $b - 0x30);
336 return ImageColorResolve($this->img, $r, $g, $b);
351 if (! isset($this->session_set)) {
355 $this->session_set = TRUE;
385 $this->bg_color= $which_color;
387 return isset($this->ndx_bg_color);
395 $this->plot_bg_color= $which_color;
396 $this->ndx_plot_bg_color= $this->
SetIndexColor($this->plot_bg_color);
397 return isset($this->ndx_plot_bg_color);
405 $this->title_color= $which_color;
406 $this->ndx_title_color= $this->
SetIndexColor($this->title_color);
407 return isset($this->ndx_title_color);
415 $this->tick_color= $which_color;
416 $this->ndx_tick_color= $this->
SetIndexColor($this->tick_color);
417 return isset($this->ndx_tick_color);
426 $this->label_color = $which_color;
427 $this->ndx_title_color= $this->
SetIndexColor($this->label_color);
428 return isset($this->ndx_title_color);
437 $this->text_color= $which_color;
438 $this->ndx_text_color= $this->
SetIndexColor($this->text_color);
439 return isset($this->ndx_text_color);
448 $this->light_grid_color= $which_color;
449 $this->ndx_light_grid_color= $this->
SetIndexColor($this->light_grid_color);
450 return isset($this->ndx_light_grid_color);
459 $this->grid_color = $which_color;
460 $this->ndx_grid_color= $this->
SetIndexColor($this->grid_color);
461 return isset($this->ndx_grid_color);
470 $this->i_border = $which_color;
473 return isset($this->ndx_i_border);
485 ImageColorTransparent($this->img, $ndx);
499 if ( is_array($which_color_array) ) {
500 $this->rgb_array = $which_color_array;
502 } elseif ($which_color_array ==
'small') {
503 $this->rgb_array = array(
504 'white' => array(255, 255, 255),
505 'snow' => array(255, 250, 250),
506 'PeachPuff' => array(255, 218, 185),
507 'ivory' => array(255, 255, 240),
508 'lavender' => array(230, 230, 250),
509 'black' => array( 0, 0, 0),
510 'DimGrey' => array(105, 105, 105),
511 'gray' => array(190, 190, 190),
512 'grey' => array(190, 190, 190),
513 'navy' => array( 0, 0, 128),
514 'SlateBlue' => array(106, 90, 205),
515 'blue' => array( 0, 0, 255),
516 'SkyBlue' => array(135, 206, 235),
517 'cyan' => array( 0, 255, 255),
518 'DarkGreen' => array( 0, 100, 0),
519 'green' => array( 0, 255, 0),
520 'YellowGreen' => array(154, 205, 50),
521 'yellow' => array(255, 255, 0),
522 'orange' => array(255, 165, 0),
523 'gold' => array(255, 215, 0),
524 'peru' => array(205, 133, 63),
525 'beige' => array(245, 245, 220),
526 'wheat' => array(245, 222, 179),
527 'tan' => array(210, 180, 140),
528 'brown' => array(165, 42, 42),
529 'salmon' => array(250, 128, 114),
530 'red' => array(255, 0, 0),
531 'pink' => array(255, 192, 203),
532 'maroon' => array(176, 48, 96),
533 'magenta' => array(255, 0, 255),
534 'violet' => array(238, 130, 238),
535 'plum' => array(221, 160, 221),
536 'orchid' => array(218, 112, 214),
537 'purple' => array(160, 32, 240),
538 'azure1' => array(240, 255, 255),
539 'aquamarine1' => array(127, 255, 212)
542 } elseif ($which_color_array ===
'large') {
543 include(
"./rgb.inc.php");
544 $this->rgb_array = $RGBArray;
546 $this->rgb_array = array(
'white' => array(255, 255, 255),
'black' => array(0, 0, 0));
559 if (empty($color_asked)) {
560 $ret_val = array(0, 0, 0);
561 } elseif (count($color_asked) == 3 ) {
562 $ret_val = $color_asked;
563 } elseif ($color_asked[0] ==
'#') {
564 $ret_val = array(hexdec(substr($color_asked, 1, 2)),
565 hexdec(substr($color_asked, 3, 2)),
566 hexdec(substr($color_asked, 5, 2)));
568 } elseif (isset($this->rgb_array[$color_asked])) {
569 $ret_val = $this->rgb_array[$color_asked];
571 return $this->
PrintError(
"SetRGBColor(): Color '$color_asked' is not valid.");
582 if (is_null($which_data) && is_array($this->data_colors)) {
584 }
else if (! is_array($which_data)) {
585 $this->data_colors = ($which_data) ? array($which_data) : array(
'blue',
'red',
'green',
'orange');
587 $this->data_colors = $which_data;
591 foreach ($this->data_colors as $col) {
595 $this->ndx_data_colors[$i] = $ndx;
610 if (is_null($which_br) && is_array($this->data_border_colors)) {
612 }
else if (! is_array($which_br)) {
614 $this->data_border_colors = ($which_br) ? array($which_br) : array(
'black');
616 $this->data_border_colors = $which_br;
620 foreach($this->data_border_colors as $col) {
624 $this->ndx_data_border_colors[$i] = $ndx;
636 if (is_null($which_err) && is_array($this->error_bar_colors)) {
638 }
else if (! is_array($which_err)) {
639 $this->error_bar_colors = ($which_err) ? array($which_err) : array(
'black');
641 $this->error_bar_colors = $which_err;
645 foreach($this->error_bar_colors as $col) {
649 $this->ndx_error_bar_colors[$i] = $ndx;
665 $asked = explode(
'-', $which_style);
667 if (count($asked) < 2) {
668 return $this->
PrintError(
"SetDefaultDashedStyle(): Wrong parameter '$which_style'.");
672 $this->default_dashed_style =
'array( ';
675 foreach($asked as $s) {
677 $this->default_dashed_style .= str_repeat(
'$which_ndxcol,', $s);
679 $this->default_dashed_style .= str_repeat(
'IMG_COLOR_TRANSPARENT,', $s);
684 $this->default_dashed_style = substr($this->default_dashed_style, 0, -1);
685 $this->default_dashed_style .=
')';
698 eval (
"\$style = $this->default_dashed_style;");
699 return imagesetstyle($this->img, $style);
708 if (is_null($which_lw)) {
710 }
else if (is_array($which_lw)) {
712 $this->line_widths = $which_lw;
714 $this->line_widths = array($which_lw);
724 if (is_null($which_ls)) {
726 }
else if ( is_array($which_ls)) {
728 $this->line_styles = $which_ls;
730 $this->line_styles = ($which_ls) ? array($which_ls) : array(
'solid');
746 $this->line_spacing = $which_spc;
758 $this->use_ttf = $which_ttf;
770 if (is_dir($which_path) && is_readable($which_path)) {
771 $this->ttf_path = $which_path;
774 return $this->
PrintError(
"SetTTFPath(): $which_path is not a valid path.");
785 $this->default_ttfont = $which_font;
795 if ($this->use_ttf) {
796 return $this->
SetFont(
'generic',
'', 8)
797 && $this->
SetFont(
'title',
'', 14)
798 && $this->
SetFont(
'legend',
'', 8)
799 && $this->
SetFont(
'x_label',
'', 6)
800 && $this->
SetFont(
'y_label',
'', 6)
801 && $this->
SetFont(
'x_title',
'', 10)
802 && $this->
SetFont(
'y_title',
'', 10);
805 return $this->
SetFont(
'generic', 2)
808 && $this->
SetFont(
'x_label', 1)
809 && $this->
SetFont(
'y_label', 1)
810 && $this->
SetFont(
'x_title', 3)
811 && $this->
SetFont(
'y_title', 3);
825 function SetFont($which_elem, $which_font, $which_size = 12)
828 if ($this->use_ttf) {
830 if (empty($which_font))
836 $path = $this->ttf_path .
'/' . $which_font;
838 return $this->
PrintError(
"SetFont(): Can't find TrueType font $which_font");
842 switch ($which_elem) {
844 $this->generic_font[
'font'] =
$path;
845 $this->generic_font[
'size'] = $which_size;
848 $this->title_font[
'font'] =
$path;
849 $this->title_font[
'size'] = $which_size;
852 $this->legend_font[
'font'] =
$path;
853 $this->legend_font[
'size'] = $which_size;
856 $this->x_label_font[
'font'] =
$path;
857 $this->x_label_font[
'size'] = $which_size;
860 $this->y_label_font[
'font'] =
$path;
861 $this->y_label_font[
'size'] = $which_size;
864 $this->x_title_font[
'font'] =
$path;
865 $this->x_title_font[
'size'] = $which_size;
868 $this->y_title_font[
'font'] =
$path;
869 $this->y_title_font[
'size'] = $which_size;
872 return $this->
PrintError(
"SetFont(): Unknown element '$which_elem' specified.");
879 if ($which_font > 5 || $which_font < 0) {
880 return $this->
PrintError(
'SetFont(): Non-TTF font size must be 1, 2, 3, 4 or 5');
883 switch ($which_elem) {
885 $this->generic_font[
'font'] = $which_font;
886 $this->generic_font[
'height'] = ImageFontHeight($which_font);
887 $this->generic_font[
'width'] = ImageFontWidth($which_font);
890 $this->title_font[
'font'] = $which_font;
891 $this->title_font[
'height'] = ImageFontHeight($which_font);
892 $this->title_font[
'width'] = ImageFontWidth($which_font);
895 $this->legend_font[
'font'] = $which_font;
896 $this->legend_font[
'height'] = ImageFontHeight($which_font);
897 $this->legend_font[
'width'] = ImageFontWidth($which_font);
900 $this->x_label_font[
'font'] = $which_font;
901 $this->x_label_font[
'height'] = ImageFontHeight($which_font);
902 $this->x_label_font[
'width'] = ImageFontWidth($which_font);
905 $this->y_label_font[
'font'] = $which_font;
906 $this->y_label_font[
'height'] = ImageFontHeight($which_font);
907 $this->y_label_font[
'width'] = ImageFontWidth($which_font);
910 $this->x_title_font[
'font'] = $which_font;
911 $this->x_title_font[
'height'] = ImageFontHeight($which_font);
912 $this->x_title_font[
'width'] = ImageFontWidth($which_font);
915 $this->y_title_font[
'font'] = $which_font;
916 $this->y_title_font[
'height'] = ImageFontHeight($which_font);
917 $this->y_title_font[
'width'] = ImageFontWidth($which_font);
920 return $this->
PrintError(
"SetFont(): Unknown element '$which_elem' specified.");
1003 function ProcessTextGD($draw_it, $font_number, $font_width, $font_height, $angle, $x, $y, $color,
1004 $text, $h_factor, $v_factor)
1006 # Break up the text into lines, trim whitespace, find longest line.
1007 # Save the lines and length for drawing below.
1009 foreach (explode(
"\n", $text) as $each_line) {
1010 $lines[] = $line = trim($each_line);
1011 $line_lens[] = $line_len = strlen($line);
1012 if ($line_len > $longest) $longest = $line_len;
1014 $n_lines = count($lines);
1015 $spacing = $this->line_spacing * ($n_lines - 1);
1017 # Width, height are based on font size and longest line, line count respectively.
1018 # These are relative to the text angle.
1019 $total_width = $longest * $font_width;
1020 $total_height = $n_lines * $font_height + $spacing;
1023 if ($angle < 45)
return array($total_width, $total_height);
1024 return array($total_height, $total_width);
1034 $v_factor = $h_factor;
1035 $h_factor = 1 - $temp;
1037 $draw_func =
'ImageStringUp';
1041 $r10 = -1; $r11 = 0;
1045 $draw_func =
'ImageString';
1053 $factor = (int)($total_height * $v_factor);
1054 $xpos = $x - $r01 * $factor;
1055 $ypos = $y - $r11 * $factor;
1057 # Debug callback provides the bounding box:
1060 $bbox_width = $total_height;
1061 $bbox_height = $total_width;
1063 $py = $ypos - (1 - $h_factor) * $total_width;
1065 $bbox_width = $total_width;
1066 $bbox_height = $total_height;
1067 $px = $xpos - $h_factor * $total_width;
1070 $this->
DoCallback(
'debug_textbox', $px, $py, $bbox_width, $bbox_height);
1073 for ($i = 0; $i < $n_lines; $i++) {
1076 $line_len = $line_lens[$i];
1079 $factor = (int)($line_len * $font_width * $h_factor);
1080 $x = $xpos - $r00 * $factor;
1081 $y = $ypos - $r10 * $factor;
1084 $draw_func($this->img, $font_number, $x, $y, $line, $color);
1087 $xpos += $r01 * $interline_step;
1088 $ypos += $r11 * $interline_step;
1109 $text, $h_factor, $v_factor)
1111 # Break up the text into lines, trim whitespace.
1112 # Calculate the total width and height of the text box at 0 degrees.
1113 # This has to be done line-by-line so the interline-spacing is right.
1114 # Save the trimmed line, and its 0-degree height and width for later
1115 # when the text is drawn.
1116 # Note: Total height = sum of each line height plus inter-line spacing
1117 # (which is added after the loop). Total width = width of widest line.
1120 foreach (explode(
"\n", $text) as $each_line) {
1121 $lines[] = $line = trim($each_line);
1122 $bbox = ImageTTFBBox($font_size, 0, $font_file, $line);
1123 $height = $bbox[1] - $bbox[5];
1124 $width = $bbox[2] - $bbox[0];
1125 $total_height += $height;
1126 if ($width > $total_width) $total_width = $width;
1128 $line_heights[] = $height;
1130 $n_lines = count($lines);
1131 $total_height += ($n_lines - 1) * $this->line_spacing;
1133 # Calculate the rotation matrix for the text's angle. Remember that GD points Y down,
1134 # so the sin() terms change sign.
1135 $theta = deg2rad($angle);
1136 $cos_t = cos($theta);
1137 $sin_t = sin($theta);
1138 $r00 = $cos_t; $r01 = $sin_t;
1139 $r10 = -$sin_t; $r11 = $cos_t;
1141 # Make a bounding box of the right size, with upper left corner at (0,0).
1142 # By convention, the point order is: LL, LR, UR, UL.
1143 # Note this is still working with the text at 0 degrees.
1144 $b[0] = 0; $b[1] = $total_height;
1145 $b[2] = $total_width; $b[3] = $b[1];
1146 $b[4] = $b[2]; $b[5] = 0;
1147 $b[6] = $b[0]; $b[7] = $b[5];
1149 # Rotate the bounding box, then offset to the reference point:
1150 for ($i = 0; $i < 8; $i += 2) {
1153 $c[$i] = $x + $r00 * $x_b + $r01 * $y_b;
1154 $c[$i+1] = $y + $r10 * $x_b + $r11 * $y_b;
1157 # Get an orthogonal (aligned with X and Y axes) bounding box around it, by
1158 # finding the min and max X and Y:
1159 $bbox_ref_x = $bbox_max_x = $c[0];
1160 $bbox_ref_y = $bbox_max_y = $c[1];
1161 for ($i = 2; $i < 8; $i += 2) {
1163 if ($x_b < $bbox_ref_x) $bbox_ref_x = $x_b; elseif ($bbox_max_x < $x_b) $bbox_max_x = $x_b;
1165 if ($y_b < $bbox_ref_y) $bbox_ref_y = $y_b; elseif ($bbox_max_y < $y_b) $bbox_max_y = $y_b;
1167 $bbox_width = $bbox_max_x - $bbox_ref_x;
1168 $bbox_height = $bbox_max_y - $bbox_ref_y;
1171 # Return the bounding box, rounded up (so it always contains the text):
1172 return array((
int)ceil($bbox_width), (
int)ceil($bbox_height));
1175 # Calculate the offsets from the supplied reference point to the
1176 # required upper-left corner of the text.
1177 # Start at the reference point at the upper left corner of the bounding
1178 # box (bbox_ref_x, bbox_ref_y) then adjust it for the 9 point alignment.
1179 # h,v_factor are 0,0 for top,left, .5,.5 for center,center, 1,1 for bottom,right.
1180 # $off_x = $bbox_ref_x + $bbox_width * $h_factor - $x;
1181 # $off_y = $bbox_ref_y + $bbox_height * $v_factor - $y;
1182 # Then use that offset to calculate back to the supplied reference point x, y
1183 # to get the text base point.
1184 # $qx = $x - $off_x;
1185 # $qy = $y - $off_y;
1187 $qx = 2 * $x - $bbox_ref_x - $bbox_width * $h_factor;
1188 $qy = 2 * $y - $bbox_ref_y - $bbox_height * $v_factor;
1190 # Check for debug callback. Don't calculate bounding box unless it is wanted.
1192 # Calculate the orthogonal bounding box coordinates for debug testing.
1194 # qx, qy is upper left corner relative to the text.
1195 # Calculate px,py: upper left corner (absolute) of the bounding box.
1196 # There are 4 equation sets for this, depending on the quadrant:
1199 # Quadrant: 0d - 90d:
1200 $px = $qx; $py = $qy - $total_width * $sin_t;
1202 # Quadrant: 90d - 180d:
1203 $px = $qx + $total_width * $cos_t; $py = $qy - $bbox_height;
1207 # Quadrant: 180d - 270d:
1208 $px = $qx - $bbox_width; $py = $qy + $total_height * $cos_t;
1210 # Quadrant: 270d - 360d:
1211 $px = $qx + $total_height * $sin_t; $py = $qy;
1214 $this->
DoCallback(
'debug_textbox', $px, $py, $bbox_width, $bbox_height);
1217 # Since alignment is applied after rotation, which parameter is used
1218 # to control alignment of each line within the text box varies with
1220 # Angle (degrees): Line alignment controlled by:
1221 # -45 < angle <= 45 h_align
1222 # 45 < angle <= 135 reversed v_align
1223 # 135 < angle <= 225 reversed h_align
1224 # 225 < angle <= 315 v_align
1225 if ($cos_t >= $sin_t) {
1226 if ($cos_t >= -$sin_t) $line_align_factor = $h_factor;
1227 else $line_align_factor = $v_factor;
1229 if ($cos_t >= -$sin_t) $line_align_factor = 1-$v_factor;
1230 else $line_align_factor = 1-$h_factor;
1233 # Now we have the start point, spacing and in-line alignment factor.
1234 # We are finally ready to start drawing the text, line by line.
1235 for ($i = 0; $i < $n_lines; $i++) {
1237 # These are height and width at 0 degrees, calculated above:
1238 $height = $line_heights[$i];
1241 # For drawing TTF text, the lower left corner is the base point.
1242 # The adjustment is inside the loop, since lines can have different
1243 # heights. The following also adjusts for horizontal (relative to
1244 # the text) alignment of the current line within the box.
1245 # What is happening is rotation of this vector by the text angle:
1246 # (x = (total_width - line_width) * factor, y = line_height)
1248 $width_factor = ($total_width - $width) * $line_align_factor;
1249 $rx = $qx + $r00 * $width_factor + $r01 * $height;
1250 $ry = $qy + $r10 * $width_factor + $r11 * $height;
1252 # Finally, draw the text:
1253 ImageTTFText($this->img, $font_size, $angle, $rx, $ry, $color, $font_file, $line);
1255 # Step to position of next line.
1256 # This is a rotation of (x=0,y=text_height+line_height) by $angle:
1257 $interline_step = $this->line_spacing + $height;
1258 $qx += $r01 * $interline_step;
1259 $qy += $r11 * $interline_step;
1278 function ProcessText($draw_it, $font, $angle, $x, $y, $color, $text, $halign, $valign)
1282 if ($draw_it)
return TRUE;
1286 # Calculate width and height offset factors using the alignment args:
1287 if ($valign ==
'top') $v_factor = 0;
1288 elseif ($valign ==
'center') $v_factor = 0.5;
1289 else $v_factor = 1.0; #
'bottom'
1290 if ($halign ==
'left') $h_factor = 0;
1291 elseif ($halign ==
'center') $h_factor = 0.5;
1292 else $h_factor = 1.0; #
'right'
1294 if ($this->use_ttf) {
1295 return $this->
ProcessTextTTF($draw_it, $font[
'font'], $font[
'size'],
1296 $angle, $x, $y, $color, $text, $h_factor, $v_factor);
1299 return $this->
ProcessTextGD($draw_it, $font[
'font'], $font[
'width'], $font[
'height'],
1300 $angle, $x, $y, $color, $text, $h_factor, $v_factor);
1314 function DrawText($which_font, $which_angle, $which_xpos, $which_ypos, $which_color, $which_text,
1315 $which_halign =
'left', $which_valign =
'bottom')
1318 $which_font, $which_angle, $which_xpos, $which_ypos,
1319 $which_color, $which_text, $which_halign, $which_valign);
1333 function SizeText($which_font, $which_angle, $which_text)
1337 $which_font, $which_angle, 0, 0, 1, $which_text,
'',
'');
1350 $asked = $this->
CheckOption($format,
'jpg, png, gif, wbmp', __FUNCTION__);
1351 if (!$asked)
return False;
1354 $format_test = IMG_JPG;
1357 $format_test = IMG_PNG;
1360 $format_test = IMG_GIF;
1363 $format_test = IMG_WBMP;
1366 if (!(imagetypes() & $format_test)) {
1367 return $this->
PrintError(
"SetFileFormat(): File format '$format' not supported");
1369 $this->file_format = $asked;
1382 $this->bgmode = $this->
CheckOption($mode,
'tile, centeredtile, scale', __FUNCTION__);
1383 $this->bgimg = $input_file;
1384 return (
boolean)$this->bgmode;
1395 $this->plotbgmode = $this->
CheckOption($mode,
'tile, centeredtile, scale', __FUNCTION__);
1396 $this->plotbgimg = $input_file;
1397 return (
boolean)$this->plotbgmode;
1406 $this->output_file = $which_output_file;
1416 $this->is_inline = (bool)$which_ii;
1427 if ( (! $this->browser_cache) && (! $this->is_inline)) {
1428 header(
'Expires: Mon, 26 Jul 1997 05:00:00 GMT');
1429 header(
'Last-Modified: ' . gmdate(
'D, d M Y H:i:s') .
'GMT');
1430 header(
'Cache-Control: no-cache, must-revalidate');
1431 header(
'Pragma: no-cache');
1434 switch($this->file_format) {
1436 if (! $this->is_inline) {
1437 Header(
'Content-type: image/png');
1439 if ($this->is_inline && $this->output_file !=
'') {
1440 ImagePng($this->img, $this->output_file);
1442 ImagePng($this->img);
1446 if (! $this->is_inline) {
1447 Header(
'Content-type: image/jpeg');
1449 if ($this->is_inline && $this->output_file !=
'') {
1450 ImageJPEG($this->img, $this->output_file);
1452 ImageJPEG($this->img);
1456 if (! $this->is_inline) {
1457 Header(
'Content-type: image/gif');
1459 if ($this->is_inline && $this->output_file !=
'') {
1460 ImageGIF($this->img, $this->output_file);
1462 ImageGIF($this->img);
1467 if (! $this->is_inline) {
1468 Header(
'Content-type: image/wbmp');
1470 if ($this->is_inline && $this->output_file !=
'') {
1471 ImageWBMP($this->img, $this->output_file);
1473 ImageWBMP($this->img);
1478 return $this->
PrintError(
'PrintImage(): Please select an image type!');
1509 if (isset($this->in_error))
return FALSE;
1510 $this->in_error = TRUE;
1513 if (!empty($this->img)) {
1514 $ypos = $this->image_height/2;
1515 $xpos = $this->image_width/2;
1516 $bgcolor = ImageColorResolve($this->img, 255, 255, 255);
1517 $fgcolor = ImageColorResolve($this->img, 0, 0, 0);
1518 ImageFilledRectangle($this->img, 0, 0, $this->image_width, $this->image_height, $bgcolor);
1523 $this->
DrawText($this->generic_font, 0, $xpos, $ypos, $fgcolor,
1524 wordwrap($error_message),
'center',
'center');
1527 } elseif (! $this->is_inline) {
1528 Header(
'HTTP/1.0 500 Internal Server Error');
1530 trigger_error($error_message, E_USER_ERROR);
1531 unset($this->in_error);
1532 return FALSE; # In
case error handler returns, rather than doing
exit().
1541 function DrawError($error_message, $where_x = NULL, $where_y = NULL)
1556 $which_xdlp = $this->
CheckOption($which_xdlp,
'plotdown, plotup, both, xaxis, all, none',
1558 if (!$which_xdlp)
return FALSE;
1559 $this->x_data_label_pos = $which_xdlp;
1560 if ($this->x_data_label_pos !=
'none')
1561 $this->x_tick_label_pos =
'none';
1573 $which_ydlp = $this->
CheckOption($which_ydlp,
'plotleft, plotright, both, yaxis, all, plotin, none',
1575 if (!$which_ydlp)
return FALSE;
1576 $this->y_data_label_pos = $which_ydlp;
1579 if ( ($which_ydlp ==
'plotleft') || ($which_ydlp ==
'plotright') ||
1580 ($which_ydlp ==
'both') || ($which_ydlp ==
'yaxis') ) {
1585 } elseif ($which_ydlp !=
'none') {
1587 $this->y_data_label_pos =
'plotin';
1599 $which_xtlp = $this->
CheckOption($which_xtlp,
'plotdown, plotup, both, xaxis, all, none',
1601 if (!$which_xtlp)
return FALSE;
1602 $this->x_tick_label_pos = $which_xtlp;
1603 if ($which_xtlp !=
'none')
1604 $this->x_data_label_pos =
'none';
1614 $this->y_tick_label_pos = $this->
CheckOption($which_ytlp,
'plotleft, plotright, both, yaxis, all, none',
1625 $this->x_label_type = $this->
CheckOption($which_xlt,
'data, time, title', __FUNCTION__);
1634 $this->y_label_type = $this->
CheckOption($which_ylt,
'data, time', __FUNCTION__);
1640 $this->x_time_format = $which_xtf;
1646 $this->y_time_format = $which_ytf;
1652 $this->decimal_point = $decimal_point;
1653 $this->thousands_sep = $thousands_sep;
1660 $this->x_label_angle = $which_xla;
1666 $this->y_label_angle = $which_yla;
1685 $asked = strtolower(trim($which_opt));
1687 # Look for the supplied value in a comma/space separated list.
1688 if (strpos(
", $which_acc,",
", $asked,") !== False)
1691 $this->
PrintError(
"$which_func(): '$which_opt' not in available choices: '$which_acc'.");
1701 $this->browser_cache = $which_browser_cache;
1710 $this->print_image = $which_pi;
1719 if (is_array($which_leg)) {
1720 $this->legend = $which_leg;
1721 } elseif (! is_null($which_leg)) {
1722 $this->legend[] = $which_leg;
1724 return $this->
PrintError(
"SetLegend(): argument must not be null.");
1735 $this->legend_x_pos = $which_x;
1736 $this->legend_y_pos = $which_y;
1738 unset($this->legend_xy_world);
1752 $this->legend_x_pos = $which_x;
1753 $this->legend_y_pos = $which_y;
1754 $this->legend_xy_world = True;
1768 $this->legend_text_align = $this->
CheckOption($text_align,
'left, right', __FUNCTION__);
1769 if (empty($colorbox_align))
1770 $this->legend_colorbox_align = $this->legend_text_align;
1772 $this->legend_colorbox_align = $this->
CheckOption($colorbox_align,
'left, right, none', __FUNCTION__);
1773 return ((
boolean)$this->legend_text_align && (
boolean)$this->legend_colorbox_align);
1781 $this->plot_border_type = $this->
CheckOption($pbt,
'left, sides, none, full', __FUNCTION__);
1790 $this->image_border_type = $this->
CheckOption($sibt,
'raised, plain', __FUNCTION__);
1800 $this->draw_plot_area_background = (bool)$dpab;
1810 $this->draw_y_grid = (bool)$dyg;
1820 $this->draw_x_grid = (bool)$dxg;
1830 $this->dashed_grid = (bool)$ddg;
1840 $this->draw_x_data_label_lines = (bool)$dxdl;
1851 $this->draw_y_data_label_lines = $dydl;
1861 $this->title_txt = $which_title;
1870 if ($which_xtitle ==
'')
1871 $which_xpos =
'none';
1873 $this->x_title_pos = $this->
CheckOption($which_xpos,
'plotdown, plotup, both, none', __FUNCTION__);
1874 if (!$this->x_title_pos)
return FALSE;
1875 $this->x_title_txt = $which_xtitle;
1885 if ($which_ytitle ==
'')
1886 $which_ypos =
'none';
1888 $this->y_title_pos = $this->
CheckOption($which_ypos,
'plotleft, plotright, both, none', __FUNCTION__);
1889 if (!$this->y_title_pos)
return FALSE;
1890 $this->y_title_txt = $which_ytitle;
1900 $this->shading = (int)$which_s;
1907 'bars, stackedbars, lines, linepoints, area, points, pie, thinbarline, squared',
1918 $this->y_axis_position = (int)$pos;
1928 $this->x_axis_position = (int)$pos;
1935 $this->xscale_type = $this->
CheckOption($which_xst,
'linear, log', __FUNCTION__);
1941 $this->yscale_type = $this->
CheckOption($which_yst,
'linear, log', __FUNCTION__);
1947 $this->x_precision = $which_prec;
1954 $this->y_precision = $which_prec;
1961 $this->error_bar_line_width = $which_seblw;
1968 $this->label_scale_position = $which_blp;
1975 $this->error_bar_size = $which_ebs;
1984 $this->error_bar_shape = $this->
CheckOption($which_ebs,
'tee, line', __FUNCTION__);
1995 if (is_null($which_pt)) {
1997 }
else if (is_array($which_pt)) {
1999 $this->point_shapes = $which_pt;
2002 $this->point_shapes = array($which_pt);
2005 foreach ($this->point_shapes as $shape)
2008 'halfline, line, plus, cross, rect, circle, dot, diamond, triangle, trianglemid, none',
2014 $ps = count($this->point_sizes);
2015 $pt = count($this->point_shapes);
2018 $this->
pad_array($this->point_sizes, $pt);
2019 }
else if ($pt > $ps) {
2020 $this->
pad_array($this->point_shapes, $ps);
2032 if (is_null($which_ps)) {
2034 }
else if (is_array($which_ps)) {
2036 $this->point_sizes = $which_ps;
2039 $this->point_sizes = array($which_ps);
2043 $ps = count($this->point_sizes);
2044 $pt = count($this->point_shapes);
2047 $this->
pad_array($this->point_sizes, $pt);
2048 }
else if ($pt > $ps) {
2049 $this->
pad_array($this->point_shapes, $ps);
2053 for ($i = 0; $i < $pt; $i++) {
2054 if ($this->point_shapes[$i] ==
'diamond' or $this->point_shapes[$i] ==
'triangle') {
2055 if ($this->point_sizes[$i] % 2 != 0) {
2056 $this->point_sizes[$i]++;
2070 $this->draw_broken_lines = (bool)$bl;
2084 if ($which_dt ==
'text-linear') { $which_dt =
'text-data'; }
2085 elseif ($which_dt ==
'linear-linear') { $which_dt =
'data-data'; }
2086 elseif ($which_dt ==
'linear-linear-error') { $which_dt =
'data-data-error'; }
2087 elseif ($which_dt ==
'text-data-pie') { $which_dt =
'text-data-single'; }
2090 $this->data_type = $this->
CheckOption($which_dt,
'text-data, text-data-single, '.
2091 'data-data, data-data-error', __FUNCTION__);
2102 $this->num_data_rows = count($which_dv);
2103 $this->total_records = 0;
2104 $this->records_per_group = 1;
2105 for ($i = 0, $recs = 0; $i < $this->num_data_rows; $i++) {
2107 $this->data[$i] = array_values($which_dv[$i]);
2110 $recs = count($this->data[$i]);
2111 $this->total_records += $recs;
2113 if ($recs > $this->records_per_group)
2114 $this->records_per_group = $recs;
2116 $this->num_recs[$i] = $recs;
2128 $this->
pad_array($this->line_widths, $this->records_per_group);
2129 $this->
pad_array($this->line_styles, $this->records_per_group);
2131 $this->
pad_array($this->data_colors, $this->records_per_group);
2132 $this->
pad_array($this->data_border_colors, $this->records_per_group);
2133 $this->
pad_array($this->error_bar_colors, $this->records_per_group);
2152 if (! is_array($arr)) {
2157 while (
$n <
$size) $arr[
$n++] = $arr[$base++];
2167 if (!isset($this->decimal_point) || !isset($this->thousands_sep)) {
2169 @setlocale(LC_ALL,
'');
2171 $locale = @localeconv();
2172 if (!empty($locale) && isset($locale[
'decimal_point']) &&
2173 isset($locale[
'thousands_sep'])) {
2174 $this->decimal_point = $locale[
'decimal_point'];
2175 $this->thousands_sep = $locale[
'thousands_sep'];
2178 $this->decimal_point =
'.';
2179 $this->thousands_sep =
',';
2182 return number_format($number, $decimals, $this->decimal_point, $this->thousands_sep);
2197 if (!array_key_exists($reason, $this->callbacks))
2199 $this->callbacks[$reason] = array($function, $arg);
2213 if (isset($this->callbacks[$reason]))
2214 return $this->callbacks[$reason][0];
2226 if (!array_key_exists($reason, $this->callbacks))
2228 $this->callbacks[$reason] = NULL;
2243 $args = func_get_args();
2245 if (!isset($this->callbacks[$reason]))
2247 list($function, $args[0]) = $this->callbacks[$reason];
2248 array_unshift($args, $this->img);
2249 # Now args[] looks like: img, passthru, extra args...
2250 call_user_func_array($function, $args);
2269 switch ($this->data_type) {
2271 case 'text-data-single':
2273 $maxx = $this->num_data_rows - 1 ;
2274 $miny = $this->data[0][1];
2278 $minx = $this->data[0][1];
2280 $miny = $this->data[0][2];
2288 if ($this->plot_type ==
'stackedbars') {
2289 $maxmaxy = $minminy = 0;
2296 for ($i=0; $i < $this->num_data_rows; $i++) {
2299 switch ($this->data_type) {
2301 case 'text-data-single':
2303 $maxy = (double)$this->data[$i][$j++];
2304 if ($this->plot_type ==
'stackedbars') {
2309 for (; $j < $this->num_recs[$i]; $j++) {
2310 $val = (double)$this->data[$i][$j];
2311 if ($this->plot_type ==
'stackedbars') {
2314 if ($val > $maxy) $maxy = $val;
2315 if ($val < $miny) $miny = $val;
2321 $val = (double)$this->data[$i][$j++];
2322 if ($val > $maxx) $maxx = $val;
2323 if ($val < $minx) $minx = $val;
2325 $miny = $maxy = (double)$this->data[$i][$j++];
2327 for (; $j < $this->num_recs[$i]; $j++) {
2328 $val = (double)$this->data[$i][$j];
2329 if ($val > $maxy) $maxy = $val;
2330 if ($val < $miny) $miny = $val;
2333 case 'data-data-error':
2335 $val = (double)$this->data[$i][$j++];
2336 if ($val > $maxx) $maxx = $val;
2337 if ($val < $minx) $minx = $val;
2339 $miny = $maxy = (double)$this->data[$i][$j];
2341 for (; $j < $this->num_recs[$i];) {
2343 $val = (double)$this->data[$i][$j++];
2344 if ($val > $maxy) $maxy = $val;
2345 if ($val < $miny) $miny = $val;
2347 $val = (double)$this->data[$i][$j++];
2348 if ($val > $maxe) $maxe = $val;
2350 $val = (double)$this->data[$i][$j++];
2351 if ($val > $mine) $mine = $val;
2353 $maxy = $maxy + $maxe;
2354 $miny = $miny - $mine;
2357 return $this->
PrintError(
"FindDataLimits(): Unknown data type '$this->data_type'.");
2360 $this->data_miny[$i] = $miny;
2361 $this->data_maxy[$i] = $maxy;
2363 if ($miny < $minminy) $minminy = $miny;
2364 if ($maxy > $maxmaxy) $maxmaxy = $maxy;
2367 $this->min_x = $minx;
2368 $this->max_x = $maxx;
2369 $this->min_y = $minminy;
2370 $this->max_y = $maxmaxy;
2373 $this->
DoCallback(
'debug_scale', __FUNCTION__, array(
2374 'min_x' => $this->min_x,
'min_y' => $this->min_y,
2375 'max_x' => $this->max_x,
'max_y' => $this->max_y));
2427 $min_margin = 3 * $gap;
2430 list($unused, $title_height) = $this->
SizeText($this->title_font, 0, $this->title_txt);
2431 list($unused, $x_title_height) = $this->
SizeText($this->x_title_font, 0, $this->x_title_txt);
2432 list($y_title_width, $unused) = $this->
SizeText($this->y_title_font, 90, $this->y_title_txt);
2436 if (!$this->plot_margins_set) {
2437 $this->x_left_margin = $gap;
2438 $this->x_right_margin = $gap;
2439 $this->y_top_margin = $gap;
2440 $this->y_bot_margin = $gap;
2441 if ($title_height > 0)
2442 $this->y_top_margin += $title_height + $gap;
2461 $x_label_height = 0;
2467 $x_label_height = $height;
2480 if ($this->x_axis_position <= $this->plot_min_y)
2481 $x_axis_pos =
'bottom';
2482 elseif ($this->x_axis_position >= $this->plot_max_y)
2483 $x_axis_pos =
'top';
2485 $x_axis_pos =
'none';
2487 if ($this->y_axis_position <= $this->plot_min_x)
2488 $y_axis_pos =
'left';
2489 elseif ($this->y_axis_position >= $this->plot_max_x)
2490 $y_axis_pos =
'right';
2492 $y_axis_pos =
'none';
2498 $this->x_title_top_offset = $gap;
2499 $this->x_title_bot_offset = $gap;
2501 if ($title_height > 0)
2502 $top_margin += $title_height + $gap;
2504 if ($x_title_height > 0) {
2506 if ($pos ==
'plotup' || $pos ==
'both')
2507 $top_margin += $x_title_height + $gap;
2508 if ($pos ==
'plotdown' || $pos ==
'both')
2509 $bot_margin += $x_title_height + $gap;
2516 $top_margin += $x_label_height + $gap;
2517 $this->x_title_top_offset += $x_label_height + $gap;
2523 $bot_margin += $x_label_height + $gap;
2524 $this->x_title_bot_offset += $x_label_height + $gap;
2527 || (
$x_tick_pos ==
'xaxis' && $x_axis_pos ==
'top')) {
2529 $top_margin += $x_tick_len;
2530 $this->x_label_top_offset = $x_tick_len + $gap;
2531 $this->x_title_top_offset += $x_tick_len;
2534 $this->x_label_top_offset = $gap;
2537 || (
$x_tick_pos ==
'xaxis' && $x_axis_pos ==
'bottom')) {
2539 $bot_margin += $x_tick_len;
2540 $this->x_label_bot_offset = $x_tick_len + $gap;
2541 $this->x_title_bot_offset += $x_tick_len;
2544 $this->x_label_bot_offset = $gap;
2548 $this->x_label_axis_offset = $x_tick_len + $gap;
2550 $this->x_label_axis_offset = $gap;
2555 $left_margin = $gap;
2556 $right_margin = $gap;
2557 $this->y_title_left_offset = $gap;
2558 $this->y_title_right_offset = $gap;
2560 if ($y_title_width > 0) {
2562 if ($pos ==
'plotleft' || $pos ==
'both')
2563 $left_margin += $y_title_width + $gap;
2564 if ($pos ==
'plotright' || $pos ==
'both')
2565 $right_margin += $y_title_width + $gap;
2571 $left_margin += $y_label_width + $gap;
2572 $this->y_title_left_offset += $y_label_width + $gap;
2577 $right_margin += $y_label_width + $gap;
2578 $this->y_title_right_offset += $y_label_width + $gap;
2581 || (
$y_tick_pos ==
'yaxis' && $y_axis_pos ==
'left')) {
2583 $left_margin += $y_tick_len;
2584 $this->y_label_left_offset = $y_tick_len + $gap;
2585 $this->y_title_left_offset += $y_tick_len;
2588 $this->y_label_left_offset = $gap;
2591 || (
$y_tick_pos ==
'yaxis' && $y_axis_pos ==
'right')) {
2593 $right_margin += $y_tick_len;
2594 $this->y_label_right_offset = $y_tick_len + $gap;
2595 $this->y_title_right_offset += $y_tick_len;
2598 $this->y_label_right_offset = $gap;
2603 $this->y_label_axis_offset = $y_tick_len + $gap;
2605 $this->y_label_axis_offset = $gap;
2610 if (!$this->plot_margins_set) {
2611 $this->y_top_margin = max($min_margin, $top_margin);
2612 $this->y_bot_margin = max($min_margin, $bot_margin);
2613 $this->x_left_margin = max($min_margin, $left_margin);
2614 $this->x_right_margin = max($min_margin, $right_margin);
2619 $this->
DoCallback(
'debug_scale', __FUNCTION__, array(
2620 'x_label_height' => $x_label_height,
2621 'y_label_width' => $y_label_width,
2622 'x_tick_len' => $x_tick_len,
2623 'y_tick_len' => $y_tick_len,
2624 'x_left_margin' => $this->x_left_margin,
2625 'x_right_margin' => $this->x_right_margin,
2626 'y_top_margin' => $this->y_top_margin,
2627 'y_bot_margin' => $this->y_bot_margin,
2628 'x_label_top_offset' => $this->x_label_top_offset,
2629 'x_label_bot_offset' => $this->x_label_bot_offset,
2630 'y_label_left_offset' => $this->y_label_left_offset,
2631 'y_label_right_offset' => $this->y_label_right_offset,
2632 'x_title_top_offset' => $this->x_title_top_offset,
2633 'x_title_bot_offset' => $this->x_title_bot_offset,
2634 'y_title_left_offset' => $this->y_title_left_offset,
2635 'y_title_right_offset' => $this->y_title_right_offset));
2649 $this->plot_area = array($this->x_left_margin, $this->y_top_margin,
2650 $this->image_width - $this->x_right_margin,
2651 $this->image_height - $this->y_bot_margin);
2652 $this->plot_area_width = $this->plot_area[2] - $this->plot_area[0];
2653 $this->plot_area_height = $this->plot_area[3] - $this->plot_area[1];
2655 $this->
DoCallback(
'debug_scale', __FUNCTION__, $this->plot_area);
2667 $this->x_left_margin = $which_lm;
2668 $this->x_right_margin = $which_rm;
2669 $this->y_top_margin = $which_tm;
2670 $this->y_bot_margin = $which_bm;
2672 $this->plot_margins_set = TRUE;
2689 $this->x_left_margin = $x1;
2690 $this->x_right_margin = $this->image_width - $x2;
2691 $this->y_top_margin = $y1;
2692 $this->y_bot_margin = $this->image_height - $y2;
2694 $this->plot_margins_set = TRUE;
2709 if (isset($this->plot_min_x) && $this->plot_min_x !==
'')
2710 $xmin = $this->plot_min_x;
2711 elseif ($this->data_type ==
'text-data')
2714 $xmin = $this->min_x;
2716 if (isset($this->plot_max_x) && $this->plot_max_x !==
'')
2717 $xmax = $this->plot_max_x;
2718 elseif ($this->data_type ==
'text-data')
2719 $xmax = $this->max_x + 1;
2721 $xmax = $this->max_x;
2725 if (!isset($this->plot_min_y) || $this->plot_min_y ===
'')
2726 $ymin = floor($this->min_y - abs($this->min_y) * 0.1);
2728 $ymin = $this->plot_min_y;
2730 if (!isset($this->plot_max_y) || $this->plot_max_y ===
'')
2731 $ymax = ceil($this->max_y + abs($this->max_y) * 0.1);
2733 $ymax = $this->plot_max_y;
2740 if ($this->yscale_type ==
'log') {
2746 return $this->
PrintError(
'SetPlotAreaWorld(): Log plots need data greater than 0');
2750 if ($ymax <= $ymin) {
2751 return $this->
PrintError(
'SetPlotAreaWorld(): Error in data - max not greater than min');
2754 $this->plot_min_x = $xmin;
2755 $this->plot_max_x = $xmax;
2756 $this->plot_min_y = $ymin;
2757 $this->plot_max_y = $ymax;
2759 $this->
DoCallback(
'debug_scale', __FUNCTION__, array(
2760 'plot_min_x' => $this->plot_min_x,
'plot_min_y' => $this->plot_min_y,
2761 'plot_max_x' => $this->plot_max_x,
'plot_max_y' => $this->plot_max_y));
2774 $this->plot_min_x = $xmin;
2775 $this->plot_max_x = $xmax;
2776 $this->plot_min_y = $ymin;
2777 $this->plot_max_y = $ymax;
2788 $group_width = $this->plot_area_width / $this->num_data_rows;
2794 if ($this->plot_type ==
'stackedbars') {
2805 $this->record_bar_width = $this->group_frac_width * $group_width / $num_spots;
2815 $this->bar_adjust_gap = ($this->record_bar_width - $this->actual_bar_width) / 2;
2836 if ($this->y_axis_position ===
'')
2837 $this->y_axis_position = $this->plot_min_x;
2839 $this->y_axis_position = min(max($this->plot_min_x, $this->y_axis_position), $this->plot_max_x);
2844 if ($this->x_axis_position ===
'') {
2845 if ($this->yscale_type ==
'log')
2846 $this->x_axis_position = 1;
2847 elseif ($this->plot_min_y <= 0 && 0 <= $this->plot_max_y)
2848 $this->x_axis_position = 0;
2850 $this->x_axis_position = $this->plot_min_y;
2852 $this->x_axis_position = min(max($this->plot_min_y, $this->x_axis_position), $this->plot_max_y);
2855 $this->
DoCallback(
'debug_scale', __FUNCTION__, array(
2856 'x_axis_position' => $this->x_axis_position,
2857 'y_axis_position' => $this->y_axis_position));
2868 if ($this->plot_max_x - $this->plot_min_x == 0) {
2871 if ($this->xscale_type ==
'log') {
2872 $this->xscale = ($this->plot_area_width)/(log10($this->plot_max_x) - log10($this->plot_min_x));
2874 $this->xscale = ($this->plot_area_width)/($this->plot_max_x - $this->plot_min_x);
2878 if ($this->plot_max_y - $this->plot_min_y == 0) {
2881 if ($this->yscale_type ==
'log') {
2882 $this->yscale = ($this->plot_area_height)/(log10($this->plot_max_y) - log10($this->plot_min_y));
2884 $this->yscale = ($this->plot_area_height)/($this->plot_max_y - $this->plot_min_y);
2888 if ($this->xscale_type ==
'log') {
2889 $this->plot_origin_x = $this->plot_area[0] - ($this->xscale * log10($this->plot_min_x) );
2891 $this->plot_origin_x = $this->plot_area[0] - ($this->xscale * $this->plot_min_x);
2893 if ($this->yscale_type ==
'log') {
2894 $this->plot_origin_y = $this->plot_area[3] + ($this->yscale * log10($this->plot_min_y));
2896 $this->plot_origin_y = $this->plot_area[3] + ($this->yscale * $this->plot_min_y);
2900 $this->y_axis_x_pixels = $this->
xtr($this->y_axis_position);
2901 $this->x_axis_y_pixels = $this->
ytr($this->x_axis_position);
2904 $this->
DoCallback(
'debug_scale', __FUNCTION__, array(
2905 'xscale' => $this->xscale,
'yscale' => $this->yscale,
2906 'plot_origin_x' => $this->plot_origin_x,
'plot_origin_y' => $this->plot_origin_y,
2907 'y_axis_x_pixels' => $this->y_axis_x_pixels,
2908 'x_axis_y_pixels' => $this->x_axis_y_pixels));
2921 if ($this->xscale_type ==
'log') {
2922 $x_pixels = $this->plot_origin_x + log10($x_world) * $this->xscale ;
2924 $x_pixels = $this->plot_origin_x + $x_world * $this->xscale ;
2926 return round($x_pixels);
2936 if ($this->yscale_type ==
'log') {
2938 $y_pixels = $this->plot_origin_y - log10($y_world) * $this->yscale ;
2940 $y_pixels = $this->plot_origin_y - $y_world * $this->yscale ;
2942 return round($y_pixels);
2959 if ($which ==
'x') {
2962 $data_max = $this->plot_max_x;
2963 $data_min = $this->plot_min_x;
2966 } elseif ($which ==
'y') {
2969 $data_max = $this->plot_max_y;
2970 $data_min = $this->plot_min_y;
2974 return $this->
PrintError(
"CalcTicks: Invalid usage ($which)");
2977 if (!empty($tick_inc)) {
2978 $tick_step = $tick_inc;
2979 } elseif (!empty($num_ticks)) {
2980 $tick_step = ($data_max - $data_min) / $num_ticks;
2982 $tick_step = ($data_max - $data_min) / 10;
2988 $tick_start = (double)$data_min;
2989 $tick_end = (double)$data_max + ($data_max - $data_min) / 10000.0;
2992 $tick_start += $tick_step;
2995 $tick_end -= $tick_step;
2997 return array($tick_start, $tick_end, $tick_step);
3011 list($tick_val, $tick_end, $tick_step) = $this->
CalcTicks($which);
3013 if ($which ==
'x') {
3014 $font = $this->x_label_font;
3016 } elseif ($which ==
'y') {
3017 $font = $this->y_label_font;
3020 return $this->
PrintError(
"CalcMaxTickLabelSize: Invalid usage ($which)");
3027 while ($tick_val <= $tick_end) {
3028 $tick_label = $this->
FormatLabel($which, $tick_val);
3029 list($width, $height) = $this->
SizeText($font, $angle, $tick_label);
3030 if ($width > $max_width) $max_width = $width;
3031 if ($height > $max_height) $max_height = $height;
3032 $tick_val += $tick_step;
3035 $this->
DoCallback(
'debug_scale', __FUNCTION__, array(
3036 'which' => $which,
'height' => $max_height,
'width' => $max_width));
3051 $font = $this->x_label_font;
3057 for ($i = 0; $i < $this->num_data_rows; $i++) {
3058 $label = $this->
FormatLabel(
'x', $this->data[$i][0]);
3059 list($width, $height) = $this->
SizeText($font, $angle, $label);
3060 if ($width > $max_width) $max_width = $width;
3061 if ($height > $max_height) $max_height = $height;
3064 $this->
DoCallback(
'debug_scale', __FUNCTION__, array(
3065 'height' => $max_height,
'width' => $max_width));
3081 if ($which_pos ==
'x') {
3082 switch ($this->x_label_type) {
3084 $lab = @ $this->data[$which_lab][0];
3087 $lab = $this->
number_format($which_lab, $this->x_precision).$this->data_units_text;
3090 $lab = strftime($this->x_time_format, $which_lab);
3093 } elseif ($which_pos ==
'y') {
3094 switch ($this->y_label_type) {
3096 $lab = $this->
number_format($which_lab, $this->y_precision).$this->data_units_text;
3099 $lab = strftime($this->y_time_format, $which_lab);
3118 $this->x_tick_inc = $which_ti;
3119 if (!empty($which_ti)) {
3120 $this->num_x_ticks =
'';
3130 $this->y_tick_inc = $which_ti;
3131 if (!empty($which_ti)) {
3132 $this->num_y_ticks =
'';
3140 $this->num_x_ticks = $which_nt;
3141 if (!empty($which_nt)) {
3142 $this->x_tick_inc =
'';
3149 $this->num_y_ticks = $which_nt;
3150 if (!empty($which_nt)) {
3151 $this->y_tick_inc =
'';
3161 $this->y_tick_pos = $this->
CheckOption($which_tp,
'plotleft, plotright, both, yaxis, none', __FUNCTION__);
3169 $this->x_tick_pos = $this->
CheckOption($which_tp,
'plotdown, plotup, both, xaxis, none', __FUNCTION__);
3178 $this->skip_top_tick = (bool)
$skip;
3187 $this->skip_bottom_tick = (bool)
$skip;
3196 $this->skip_left_tick = (bool)
$skip;
3205 $this->skip_right_tick = (bool)
$skip;
3211 $this->x_tick_length = $which_xln;
3217 $this->y_tick_length = $which_yln;
3223 $this->x_tick_cross = $which_xc;
3229 $this->y_tick_cross = $which_yc;
3244 if (! $this->background_done) {
3245 if (isset($this->bgimg)) {
3246 $this->
tile_img($this->bgimg, 0, 0, $this->image_width, $this->image_height, $this->bgmode);
3248 ImageFilledRectangle($this->img, 0, 0, $this->image_width, $this->image_height,
3249 $this->ndx_bg_color);
3251 $this->background_done = TRUE;
3262 if (isset($this->plotbgimg)) {
3263 $this->
tile_img($this->plotbgimg, $this->plot_area[0], $this->plot_area[1],
3264 $this->plot_area_width, $this->plot_area_height, $this->plotbgmode);
3267 if ($this->draw_plot_area_background) {
3268 ImageFilledRectangle($this->img, $this->plot_area[0], $this->plot_area[1],
3269 $this->plot_area[2], $this->plot_area[3], $this->ndx_plot_bg_color);
3293 if ($mode ==
'scale') {
3294 imagecopyresized($this->img, $im, $xorig, $yorig, 0, 0, $width, $height, $tile_width, $tile_height);
3296 }
else if ($mode ==
'centeredtile') {
3297 $x0 = - floor($tile_width/2);
3298 $y0 = - floor($tile_height/2);
3299 }
else if ($mode =
'tile') {
3307 $tmp = ImageCreate($width, $height);
3309 return $this->
PrintError(
'tile_img(): Could not create image resource.');
3311 for ($x = $x0; $x < $width; $x += $tile_width)
3312 for ($y = $y0; $y < $height; $y += $tile_height)
3313 imagecopy($tmp, $im, $x, $y, 0, 0, $tile_width, $tile_height);
3316 imagecopy($this->img, $tmp, $xorig, $yorig, 0,0, $width, $height);
3331 switch ($this->image_border_type) {
3333 ImageLine($this->img, 0, 0, $this->image_width-1, 0, $this->ndx_i_border);
3334 ImageLine($this->img, 1, 1, $this->image_width-2, 1, $this->ndx_i_border);
3335 ImageLine($this->img, 0, 0, 0, $this->image_height-1, $this->ndx_i_border);
3336 ImageLine($this->img, 1, 1, 1, $this->image_height-2, $this->ndx_i_border);
3337 ImageLine($this->img, $this->image_width-1, 0, $this->image_width-1,
3338 $this->image_height-1, $this->ndx_i_border_dark);
3339 ImageLine($this->img, 0, $this->image_height-1, $this->image_width-1,
3340 $this->image_height-1, $this->ndx_i_border_dark);
3341 ImageLine($this->img, $this->image_width-2, 1, $this->image_width-2,
3342 $this->image_height-2, $this->ndx_i_border_dark);
3343 ImageLine($this->img, 1, $this->image_height-2, $this->image_width-2,
3344 $this->image_height-2, $this->ndx_i_border_dark);
3347 ImageLine($this->img, 0, 0, $this->image_width-1, 0, $this->ndx_i_border_dark);
3348 ImageLine($this->img, $this->image_width-1, 0, $this->image_width-1,
3349 $this->image_height-1, $this->ndx_i_border_dark);
3350 ImageLine($this->img, $this->image_width-1, $this->image_height-1, 0, $this->image_height-1,
3351 $this->ndx_i_border_dark);
3352 ImageLine($this->img, 0, 0, 0, $this->image_height-1, $this->ndx_i_border_dark);
3357 return $this->
PrintError(
"DrawImageBorder(): unknown image_border_type: '$this->image_border_type'");
3372 $xpos = $this->image_width / 2;
3377 $this->
DrawText($this->title_font, 0, $xpos, $ypos,
3378 $this->ndx_title_color, $this->title_txt,
'center',
'top');
3390 if ($this->x_title_pos ==
'none')
3394 $xpos = ($this->plot_area[2] + $this->plot_area[0]) / 2;
3397 if ($this->x_title_pos ==
'plotup' || $this->x_title_pos ==
'both') {
3398 $ypos = $this->plot_area[1] - $this->x_title_top_offset;
3399 $this->
DrawText($this->x_title_font, 0, $xpos, $ypos, $this->ndx_title_color,
3400 $this->x_title_txt,
'center',
'bottom');
3403 if ($this->x_title_pos ==
'plotdown' || $this->x_title_pos ==
'both') {
3404 $ypos = $this->plot_area[3] + $this->x_title_bot_offset;
3405 $this->
DrawText($this->x_title_font, 0, $xpos, $ypos, $this->ndx_title_color,
3406 $this->x_title_txt,
'center',
'top');
3416 if ($this->y_title_pos ==
'none')
3420 $ypos = ($this->plot_area[3] + $this->plot_area[1]) / 2;
3422 if ($this->y_title_pos ==
'plotleft' || $this->y_title_pos ==
'both') {
3423 $xpos = $this->plot_area[0] - $this->y_title_left_offset;
3424 $this->
DrawText($this->y_title_font, 90, $xpos, $ypos, $this->ndx_title_color,
3425 $this->y_title_txt,
'right',
'center');
3427 if ($this->y_title_pos ==
'plotright' || $this->y_title_pos ==
'both') {
3428 $xpos = $this->plot_area[2] + $this->y_title_right_offset;
3429 $this->
DrawText($this->y_title_font, 90, $xpos, $ypos, $this->ndx_title_color,
3430 $this->y_title_txt,
'left',
'center');
3446 ImageLine($this->img, $this->y_axis_x_pixels, $this->plot_area[1],
3447 $this->y_axis_x_pixels, $this->plot_area[3], $this->ndx_grid_color);
3470 ImageLine($this->img, $this->plot_area[0]+1, $this->x_axis_y_pixels,
3471 $this->plot_area[2]-1, $this->x_axis_y_pixels, $this->ndx_grid_color);
3482 if ($this->y_tick_pos ==
'yaxis') {
3483 ImageLine($this->img, $this->y_axis_x_pixels - $this->y_tick_length, $which_ypix,
3484 $this->y_axis_x_pixels + $this->y_tick_cross, $which_ypix, $this->ndx_tick_color);
3488 if (($this->y_tick_pos ==
'plotleft') || ($this->y_tick_pos ==
'both') ) {
3489 ImageLine($this->img, $this->plot_area[0] - $this->y_tick_length, $which_ypix,
3490 $this->plot_area[0] + $this->y_tick_cross, $which_ypix, $this->ndx_tick_color);
3494 if (($this->y_tick_pos ==
'plotright') || ($this->y_tick_pos ==
'both') ) {
3495 ImageLine($this->img, $this->plot_area[2] + $this->y_tick_length, $which_ypix,
3496 $this->plot_area[2] - $this->y_tick_cross, $which_ypix, $this->ndx_tick_color);
3500 if ($this->y_tick_label_pos ==
'yaxis') {
3501 $this->
DrawText($this->y_label_font, $this->y_label_angle,
3502 $this->y_axis_x_pixels - $this->y_label_axis_offset, $which_ypix,
3503 $this->ndx_text_color, $which_ylab,
'right',
'center');
3507 if ($this->y_tick_label_pos ==
'plotleft' || $this->y_tick_label_pos ==
'both') {
3508 $this->
DrawText($this->y_label_font, $this->y_label_angle,
3509 $this->plot_area[0] - $this->y_label_left_offset, $which_ypix,
3510 $this->ndx_text_color, $which_ylab,
'right',
'center');
3513 if ($this->y_tick_label_pos ==
'plotright' || $this->y_tick_label_pos ==
'both') {
3514 $this->
DrawText($this->y_label_font, $this->y_label_angle,
3515 $this->plot_area[2] + $this->y_label_right_offset, $which_ypix,
3516 $this->ndx_text_color, $which_ylab,
'left',
'center');
3531 if ($this->dashed_grid) {
3533 $style = IMG_COLOR_STYLED;
3535 $style = $this->ndx_light_grid_color;
3539 list($y_tmp, $y_end, $delta_y) = $this->
CalcTicks(
'y');
3541 for (;$y_tmp <= $y_end; $y_tmp += $delta_y) {
3543 $y_pixels = $this->
ytr($y_tmp);
3546 if ($this->draw_y_grid) {
3547 ImageLine($this->img, $this->plot_area[0]+1, $y_pixels, $this->plot_area[2]-1, $y_pixels, $style);
3562 if ($this->x_tick_pos ==
'xaxis') {
3563 ImageLine($this->img, $which_xpix, $this->x_axis_y_pixels - $this->x_tick_cross,
3564 $which_xpix, $this->x_axis_y_pixels + $this->x_tick_length, $this->ndx_tick_color);
3568 if ($this->x_tick_pos ==
'plotup' || $this->x_tick_pos ==
'both') {
3569 ImageLine($this->img, $which_xpix, $this->plot_area[1] - $this->x_tick_length,
3570 $which_xpix, $this->plot_area[1] + $this->x_tick_cross, $this->ndx_tick_color);
3574 if ($this->x_tick_pos ==
'plotdown' || $this->x_tick_pos ==
'both') {
3575 ImageLine($this->img, $which_xpix, $this->plot_area[3] + $this->x_tick_length,
3576 $which_xpix, $this->plot_area[3] - $this->x_tick_cross, $this->ndx_tick_color);
3580 if ($this->x_tick_label_pos ==
'xaxis') {
3581 $this->
DrawText($this->x_label_font, $this->x_label_angle,
3582 $which_xpix, $this->x_axis_y_pixels + $this->x_label_axis_offset,
3583 $this->ndx_text_color, $which_xlab,
'center',
'top');
3587 if ($this->x_tick_label_pos ==
'plotup' || $this->x_tick_label_pos ==
'both') {
3588 $this->
DrawText($this->x_label_font, $this->x_label_angle,
3589 $which_xpix, $this->plot_area[1] - $this->x_label_top_offset,
3590 $this->ndx_text_color, $which_xlab,
'center',
'bottom');
3594 if ($this->x_tick_label_pos ==
'plotdown' || $this->x_tick_label_pos ==
'both') {
3595 $this->
DrawText($this->x_label_font, $this->x_label_angle,
3596 $which_xpix, $this->plot_area[3] + $this->x_label_bot_offset,
3597 $this->ndx_text_color, $which_xlab,
'center',
'top');
3612 if ($this->dashed_grid) {
3614 $style = IMG_COLOR_STYLED;
3616 $style = $this->ndx_light_grid_color;
3620 list($x_tmp, $x_end, $delta_x) = $this->
CalcTicks(
'x');
3622 for (;$x_tmp <= $x_end; $x_tmp += $delta_x) {
3624 $x_pixels = $this->
xtr($x_tmp);
3627 if ($this->draw_x_grid) {
3628 ImageLine($this->img, $x_pixels, $this->plot_area[1], $x_pixels, $this->plot_area[3], $style);
3643 switch ($this->plot_border_type) {
3646 ImageLine($this->img, $this->plot_area[0], $this->
ytr($this->plot_min_y),
3647 $this->plot_area[0], $this->
ytr($this->plot_max_y), $this->ndx_grid_color);
3651 ImageLine($this->img, $this->plot_area[2], $this->
ytr($this->plot_min_y),
3652 $this->plot_area[2], $this->
ytr($this->plot_max_y), $this->ndx_grid_color);
3656 ImageLine($this->img, $this->plot_area[0], $this->
ytr($this->plot_min_y),
3657 $this->plot_area[0], $this->
ytr($this->plot_max_y), $this->ndx_grid_color);
3658 ImageLine($this->img, $this->plot_area[2], $this->
ytr($this->plot_min_y),
3659 $this->plot_area[2], $this->
ytr($this->plot_max_y), $this->ndx_grid_color);
3666 ImageRectangle($this->img, $this->plot_area[0], $this->
ytr($this->plot_min_y),
3667 $this->plot_area[2], $this->
ytr($this->plot_max_y), $this->ndx_grid_color);
3678 function DrawDataLabel($which_font, $which_angle, $x_world, $y_world, $which_color, $which_text,
3679 $which_halign =
'center', $which_valign =
'bottom', $x_adjustment=0, $y_adjustment=0)
3681 $data_label = $this->
FormatLabel(
'y', $which_text);
3684 if ( empty($which_font) )
3685 $which_font = $this->x_label_font;
3689 if ( empty($which_color) )
3690 $which_color = $this->ndx_title_color;
3692 $x_pixels = $this->
xtr($x_world) + $x_adjustment;
3693 $y_pixels = $this->
ytr($y_world) + $y_adjustment;
3695 $this->
DrawText($which_font, $which_angle, $x_pixels, $y_pixels,
3696 $which_color, $data_label, $which_halign, $which_valign);
3718 if ($this->x_data_label_pos ==
'plotdown' || $this->x_data_label_pos ==
'both')
3719 $this->
DrawText($this->x_label_font, $this->x_label_angle,
3720 $xpos, $this->plot_area[3] + $this->x_label_bot_offset,
3721 $this->ndx_text_color, $xlab,
'center',
'top');
3724 if ($this->x_data_label_pos ==
'plotup' || $this->x_data_label_pos ==
'both')
3725 $this->
DrawText($this->x_label_font, $this->x_label_angle,
3726 $xpos, $this->plot_area[1] - $this->x_label_top_offset,
3727 $this->ndx_text_color, $xlab,
'center',
'bottom');
3730 if (
$row !== FALSE && $this->draw_x_data_label_lines)
3746 if($this->dashed_grid) {
3748 $style = IMG_COLOR_STYLED;
3750 $style = $this->ndx_light_grid_color;
3754 if ($this->x_data_label_pos ==
'both') {
3755 ImageLine($this->img, $xpos, $this->plot_area[3], $xpos, $this->plot_area[1], $style);
3758 else if ($this->x_data_label_pos ==
'plotdown') {
3759 $ypos = $this->
ytr($this->data_maxy[
$row]);
3760 ImageLine($this->img, $xpos, $ypos, $xpos, $this->plot_area[3], $style);
3763 else if ($this->x_data_label_pos ==
'plotup') {
3764 $ypos = $this->
ytr($this->data_miny[
$row]);
3765 ImageLine($this->img, $xpos, $this->plot_area[1], $xpos, $ypos, $style);
3780 foreach ($this->legend as $line) {
3781 list($width, $unused) = $this->
SizeText($this->legend_font, 0, $line);
3782 if ($width > $max_width) $max_width = $width;
3786 list($char_w, $char_h) = $this->
SizeText($this->legend_font, 0,
'8');
3789 $text_align = isset($this->legend_text_align) ? $this->legend_text_align :
'right';
3790 $colorbox_align = isset($this->legend_colorbox_align) ? $this->legend_colorbox_align :
'right';
3793 $v_margin = $char_h/2;
3797 if ($colorbox_align !=
'none') {
3798 $width = $max_width + 4 * $char_w;
3799 $draw_colorbox = True;
3801 $width = $max_width + 2 * $char_w;
3802 $draw_colorbox = False;
3807 if ( !isset($this->legend_x_pos) || !isset($this->legend_y_pos)) {
3811 } elseif (isset($this->legend_xy_world)) {
3813 $box_start_x = $this->
xtr($this->legend_x_pos);
3814 $box_start_y = $this->
ytr($this->legend_y_pos);
3815 unset($this->legend_xy_world);
3818 $box_start_x = $this->legend_x_pos;
3819 $box_start_y = $this->legend_y_pos;
3823 $box_end_y = $box_start_y + $dot_height*(count($this->legend)) + 2*$v_margin;
3824 $box_end_x = $box_start_x + $width;
3827 ImageFilledRectangle($this->img, $box_start_x, $box_start_y, $box_end_x, $box_end_y, $this->ndx_bg_color);
3828 ImageRectangle($this->img, $box_start_x, $box_start_y, $box_end_x, $box_end_y, $this->ndx_grid_color);
3831 $max_color_index = count($this->ndx_data_colors) - 1;
3834 if (!$draw_colorbox) {
3835 if ($text_align ==
'left')
3836 $x_pos = $box_start_x + $char_w;
3838 $x_pos = $box_end_x - $char_w;
3839 } elseif ($colorbox_align ==
'left') {
3840 $dot_left_x = $box_start_x + $char_w;
3841 $dot_right_x = $dot_left_x + $char_w;
3842 if ($text_align ==
'left')
3843 $x_pos = $dot_left_x + 2 * $char_w;
3845 $x_pos = $box_end_x - $char_w;
3847 $dot_left_x = $box_end_x - 2 * $char_w;
3848 $dot_right_x = $dot_left_x + $char_w;
3849 if ($text_align ==
'left')
3850 $x_pos = $box_start_x + $char_w;
3852 $x_pos = $dot_left_x - $char_w;
3857 $y_pos = $box_start_y + $v_margin + $dot_height;
3859 foreach ($this->legend as $leg) {
3861 $this->
DrawText($this->legend_font, 0, $x_pos, $y_pos,
3862 $this->ndx_text_color, $leg, $text_align,
'bottom');
3863 if ($draw_colorbox) {
3865 $y1 = $y_pos - $dot_height + 1;
3867 ImageFilledRectangle($this->img, $dot_left_x, $y1, $dot_right_x, $y2,
3868 $this->ndx_data_colors[$color_index]);
3870 ImageRectangle($this->img, $dot_left_x, $y1, $dot_right_x, $y2,
3871 $this->ndx_text_color);
3873 $y_pos += $dot_height;
3876 if ($color_index > $max_color_index)
3911 $xpos = $this->plot_area[0] + $this->plot_area_width/2;
3912 $ypos = $this->plot_area[1] + $this->plot_area_height/2;
3913 $diameter = min($this->plot_area_width, $this->plot_area_height);
3914 $radius = $diameter/2;
3917 if ($this->data_type ===
'text-data') {
3918 for ($i = 0; $i < $this->num_data_rows; $i++) {
3919 for ($j = 1; $j < $this->num_recs[$i]; $j++) {
3920 @ $sumarr[$j] += abs($this->data[$i][$j]);
3925 else if ($this->data_type ==
'text-data-single') {
3926 for ($i = 0; $i < $this->num_data_rows; $i++) {
3927 $legend[$i] = $this->data[$i][0];
3928 $sumarr[$i] = $this->data[$i][1];
3931 else if ($this->data_type ==
'data-data') {
3932 for ($i = 0; $i < $this->num_data_rows; $i++) {
3933 for ($j = 2; $j < $this->num_recs[$i]; $j++) {
3934 @ $sumarr[$j] += abs($this->data[$i][$j]);
3939 return $this->
PrintError(
"DrawPieChart(): Data type '$this->data_type' not supported.");
3942 $total = array_sum($sumarr);
3945 return $this->
PrintError(
'DrawPieChart(): Empty data set');
3948 if ($this->shading) {
3949 $diam2 = $diameter / 2;
3953 $max_data_colors = count ($this->data_colors);
3955 for ($h = $this->shading; $h >= 0; $h--) {
3959 foreach ($sumarr as $val) {
3962 $slicecol = $this->ndx_data_colors[$color_index];
3964 $slicecol = $this->ndx_data_dark_colors[$color_index];
3967 $val = 360 * ($val /
$total);
3978 $start_angle = $end_angle;
3982 $arc_start_angle = (int)(360 - $start_angle);
3983 $arc_end_angle = (int)(360 - $end_angle);
3985 if ($arc_start_angle > $arc_end_angle) {
3986 $mid_angle = deg2rad($end_angle - ($val / 2));
3989 ImageFilledArc($this->img, $xpos, $ypos+$h, $diameter, $diam2,
3990 $arc_end_angle, $arc_start_angle,
3991 $slicecol, IMG_ARC_PIE);
3996 if (! $this->shading)
3997 ImageFilledArc($this->img, $xpos, $ypos+$h, $diameter, $diam2,
3998 $arc_end_angle, $arc_start_angle,
3999 $this->ndx_grid_color, IMG_ARC_PIE | IMG_ARC_EDGED |IMG_ARC_NOFILL);
4004 $label_x = $xpos + ($diameter * 1.2 * cos($mid_angle)) * $this->label_scale_position;
4005 $label_y = $ypos+$h - ($diam2 * 1.2 * sin($mid_angle)) * $this->label_scale_position;
4007 $this->
DrawText($this->generic_font, 0, $label_x, $label_y, $this->ndx_grid_color,
4008 $label_txt,
'center',
'center');
4011 if (++$color_index >= $max_data_colors)
4025 if ($this->data_type !=
'data-data-error') {
4026 return $this->
PrintError(
"DrawDotsError(): Data type '$this->data_type' not supported.");
4030 $do_labels = ($this->plot_type !=
'linepoints');
4032 for(
$row = 0, $cnt = 0;
$row < $this->num_data_rows;
$row++) {
4035 $x_now = $this->data[
$row][$record++];
4037 $x_now_pixels = $this->
xtr($x_now);
4040 if ($this->x_data_label_pos !=
'none' && $do_labels)
4044 for ($idx = 0; $record < $this->num_recs[
$row]; $idx++) {
4046 $y_now = $this->data[
$row][$record++];
4047 $this->
DrawDot($x_now, $y_now, $idx, $this->ndx_data_colors[$idx]);
4050 $val = $this->data[
$row][$record++];
4051 $this->
DrawYErrorBar($x_now, $y_now, $val, $this->error_bar_shape,
4052 $this->ndx_error_bar_colors[$idx]);
4054 $val = $this->data[
$row][$record++];
4055 $this->
DrawYErrorBar($x_now, $y_now, -$val, $this->error_bar_shape,
4056 $this->ndx_error_bar_colors[$idx]);
4070 if (!$this->
CheckOption($this->data_type,
'text-data, data-data', __FUNCTION__))
4074 $do_labels = ($this->plot_type !=
'linepoints');
4076 for (
$row = 0, $cnt = 0;
$row < $this->num_data_rows;
$row++) {
4080 if ($this->data_type ==
'data-data')
4081 $x_now = $this->data[
$row][$rec++];
4083 $x_now = 0.5 + $cnt++;
4085 $x_now_pixels = $this->
xtr($x_now);
4088 if ($this->x_data_label_pos !=
'none' && $do_labels)
4092 for($idx = 0;$rec < $this->num_recs[
$row]; $rec++, $idx++) {
4093 if (is_numeric($this->data[$row][$rec])) {
4094 $this->
DrawDot($x_now, $this->data[$row][$rec],
4095 $idx, $this->ndx_data_colors[$idx]);
4108 if (!$this->
CheckOption($this->data_type,
'text-data, data-data', __FUNCTION__))
4111 for (
$row = 0, $cnt = 0;
$row < $this->num_data_rows;
$row++) {
4115 if ($this->data_type ==
'data-data')
4116 $x_now = $this->data[
$row][$rec++];
4118 $x_now = 0.5 + $cnt++;
4120 $x_now_pixels = $this->
xtr($x_now);
4123 if ($this->x_data_label_pos !=
'none')
4127 for($idx = 0;$rec < $this->num_recs[
$row]; $rec++, $idx++) {
4128 if (is_numeric($this->data[$row][$rec])) {
4129 ImageSetThickness($this->img, $this->line_widths[$idx]);
4131 ImageLine($this->img, $x_now_pixels, $this->x_axis_y_pixels, $x_now_pixels,
4132 $this->
ytr($this->data[$row][$rec]), $this->ndx_data_colors[$idx]);
4137 ImageSetThickness($this->img, 1);
4144 function DrawYErrorBar($x_world, $y_world, $error_height, $error_bar_type, $color)
4154 $x1 = $this->
xtr($x_world);
4155 $y1 = $this->
ytr($y_world);
4156 $y2 = $this->
ytr($y_world+$error_height) ;
4158 ImageSetThickness($this->img, $this->error_bar_line_width);
4159 ImageLine($this->img, $x1, $y1 , $x1, $y2, $color);
4161 switch ($error_bar_type) {
4165 ImageLine($this->img, $x1-$this->error_bar_size, $y2, $x1+$this->error_bar_size, $y2, $color);
4168 ImageLine($this->img, $x1-$this->error_bar_size, $y2, $x1+$this->error_bar_size, $y2, $color);
4172 ImageSetThickness($this->img, 1);
4181 function DrawDot($x_world, $y_world, $record, $color)
4184 $record = $record % count ($this->point_shapes);
4186 $half_point = $this->point_sizes[$record] / 2;
4188 $x_mid = $this->
xtr($x_world);
4189 $y_mid = $this->
ytr($y_world);
4191 $x1 = $x_mid - $half_point;
4192 $x2 = $x_mid + $half_point;
4193 $y1 = $y_mid - $half_point;
4194 $y2 = $y_mid + $half_point;
4196 switch ($this->point_shapes[$record]) {
4198 ImageLine($this->img, $x1, $y_mid, $x_mid, $y_mid, $color);
4201 ImageLine($this->img, $x1, $y_mid, $x2, $y_mid, $color);
4204 ImageLine($this->img, $x1, $y_mid, $x2, $y_mid, $color);
4205 ImageLine($this->img, $x_mid, $y1, $x_mid, $y2, $color);
4208 ImageLine($this->img, $x1, $y1, $x2, $y2, $color);
4209 ImageLine($this->img, $x1, $y2, $x2, $y1, $color);
4212 ImageFilledRectangle($this->img, $x1, $y1, $x2, $y2, $color);
4215 ImageArc($this->img, $x_mid, $y_mid, $this->point_sizes[$record], $this->point_sizes[$record],
4219 ImageFilledArc($this->img, $x_mid, $y_mid, $this->point_sizes[$record],
4220 $this->point_sizes[$record], 0, 360, $color, IMG_ARC_PIE);
4223 $arrpoints = array( $x1, $y_mid, $x_mid, $y1, $x2, $y_mid, $x_mid, $y2);
4224 ImageFilledPolygon($this->img, $arrpoints, 4, $color);
4227 $arrpoints = array( $x1, $y_mid, $x2, $y_mid, $x_mid, $y2);
4228 ImageFilledPolygon($this->img, $arrpoints, 3, $color);
4231 $arrpoints = array( $x1, $y1, $x2, $y1, $x_mid, $y_mid);
4232 ImageFilledPolygon($this->img, $arrpoints, 3, $color);
4237 ImageFilledRectangle($this->img, $x1, $y1, $x2, $y2, $color);
4256 $incomplete_data_defaults_to_x_axis = FALSE;
4258 for (
$row = 0, $cnt = 0;
$row < $this->num_data_rows;
$row++) {
4261 if ($this->data_type ==
'data-data')
4262 $x_now = $this->data[
$row][$rec++];
4264 $x_now = 0.5 + $cnt++;
4266 $x_now_pixels = $this->
xtr($x_now);
4269 if ($this->x_data_label_pos !=
'none')
4274 for($idx = 0; $rec < $this->num_recs[
$row]; $rec++, $idx++) {
4275 if (is_numeric($this->data[$row][$rec])) {
4276 $y_now_pixels = $this->
ytr($this->data[$row][$rec]);
4278 $posarr[$idx][] = $x_now_pixels;
4279 $posarr[$idx][] = $y_now_pixels;
4281 $num_points[$idx] = isset($num_points[$idx]) ? $num_points[$idx]+1 : 1;
4285 if (isset ($incomplete_data_defaults_to_x_axis)) {
4286 $posarr[$idx][] = $x_now_pixels;
4287 $posarr[$idx][] = $this->x_axis_y_pixels;
4288 $num_points[$idx] = isset($num_points[$idx]) ? $num_points[$idx]+1 : 1;
4294 $end = count($posarr);
4295 for ($i = 0; $i < $end; $i++) {
4297 $x = $posarr[$i][0];
4298 array_unshift($posarr[$i], $x, $this->x_axis_y_pixels);
4301 $x = $posarr[$i][count($posarr[$i])-2];
4302 array_push($posarr[$i], $x, $this->x_axis_y_pixels);
4304 $num_points[$i] += 2;
4307 ImageFilledPolygon($this->img, $posarr[$i], $num_points[$i], $this->ndx_data_colors[$i]);
4324 $start_lines = array_fill(0, $this->records_per_group, FALSE);
4326 if ($this->data_type ==
'text-data') {
4327 $lastx[0] = $this->
xtr(0);
4328 $lasty[0] = $this->
xtr(0);
4331 for (
$row = 0, $cnt = 0;
$row < $this->num_data_rows;
$row++) {
4334 if ($this->data_type ==
'data-data')
4335 $x_now = $this->data[
$row][$record++];
4337 $x_now = 0.5 + $cnt++;
4339 $x_now_pixels = $this->
xtr($x_now);
4341 if ($this->x_data_label_pos !=
'none')
4344 for ($idx = 0; $record < $this->num_recs[
$row]; $record++, $idx++) {
4345 if (($line_style = $this->line_styles[$idx]) ==
'none')
4347 if (is_numeric($this->data[$row][$record])) {
4348 $y_now_pixels = $this->
ytr($this->data[$row][$record]);
4350 if ($start_lines[$idx] == TRUE) {
4352 ImageSetThickness($this->img, $this->line_widths[$idx]);
4354 if ($line_style ==
'dashed') {
4356 ImageLine($this->img, $x_now_pixels, $y_now_pixels, $lastx[$idx], $lasty[$idx],
4359 ImageLine($this->img, $x_now_pixels, $y_now_pixels, $lastx[$idx], $lasty[$idx],
4360 $this->ndx_data_colors[$idx]);
4364 $lasty[$idx] = $y_now_pixels;
4365 $lastx[$idx] = $x_now_pixels;
4366 $start_lines[$idx] = TRUE;
4369 else if ($this->draw_broken_lines) {
4370 $start_lines[$idx] = FALSE;
4375 ImageSetThickness($this->img, 1);
4386 if ($this->data_type !=
'data-data-error') {
4387 return $this->
PrintError(
"DrawLinesError(): Data type '$this->data_type' not supported.");
4390 $start_lines = array_fill(0, $this->records_per_group, FALSE);
4392 for (
$row = 0, $cnt = 0;
$row < $this->num_data_rows;
$row++) {
4395 $x_now = $this->data[
$row][$record++];
4397 $x_now_pixels = $this->
xtr($x_now);
4400 if ($this->x_data_label_pos !=
'none')
4404 for ($idx = 0; $record < $this->num_recs[
$row]; $idx++) {
4405 if (($line_style = $this->line_styles[$idx]) ==
'none')
4408 $y_now = $this->data[
$row][$record++];
4409 $y_now_pixels = $this->
ytr($y_now);
4411 if ($start_lines[$idx] == TRUE) {
4412 ImageSetThickness($this->img, $this->line_widths[$idx]);
4414 if ($line_style ==
'dashed') {
4416 ImageLine($this->img, $x_now_pixels, $y_now_pixels, $lastx[$idx], $lasty[$idx],
4419 ImageLine($this->img, $x_now_pixels, $y_now_pixels, $lastx[$idx], $lasty[$idx],
4420 $this->ndx_data_colors[$idx]);
4425 $val = $this->data[
$row][$record++];
4426 $this->
DrawYErrorBar($x_now, $y_now, $val, $this->error_bar_shape,
4427 $this->ndx_error_bar_colors[$idx]);
4430 $val = $this->data[
$row][$record++];
4431 $this->
DrawYErrorBar($x_now, $y_now, -$val, $this->error_bar_shape,
4432 $this->ndx_error_bar_colors[$idx]);
4435 $start_lines[$idx] = TRUE;
4437 $lastx[$idx] = $x_now_pixels;
4438 $lasty[$idx] = $y_now_pixels;
4442 ImageSetThickness($this->img, 1);
4456 $start_lines = array_fill(0, $this->records_per_group, FALSE);
4458 if ($this->data_type ==
'text-data') {
4459 $lastx[0] = $this->
xtr(0);
4460 $lasty[0] = $this->
xtr(0);
4463 for (
$row = 0, $cnt = 0;
$row < $this->num_data_rows;
$row++) {
4466 if ($this->data_type ==
'data-data')
4467 $x_now = $this->data[
$row][$record++];
4469 $x_now = 0.5 + $cnt++;
4471 $x_now_pixels = $this->
xtr($x_now);
4473 if ($this->x_data_label_pos !=
'none')
4477 for ($idx = 0; $record < $this->num_recs[
$row]; $record++, $idx++) {
4478 if (is_numeric($this->data[$row][$record])) {
4479 $y_now_pixels = $this->
ytr($this->data[$row][$record]);
4481 if ($start_lines[$idx] == TRUE) {
4483 ImageSetThickness($this->img, $this->line_widths[$idx]);
4485 if ($this->line_styles[$idx] ==
'dashed') {
4487 ImageLine($this->img, $lastx[$idx], $lasty[$idx], $x_now_pixels, $lasty[$idx],
4489 ImageLine($this->img, $x_now_pixels, $lasty[$idx], $x_now_pixels, $y_now_pixels,
4492 ImageLine($this->img, $lastx[$idx], $lasty[$idx], $x_now_pixels, $lasty[$idx],
4493 $this->ndx_data_colors[$idx]);
4494 ImageLine($this->img, $x_now_pixels, $lasty[$idx], $x_now_pixels, $y_now_pixels,
4495 $this->ndx_data_colors[$idx]);
4498 $lastx[$idx] = $x_now_pixels;
4499 $lasty[$idx] = $y_now_pixels;
4500 $start_lines[$idx] = TRUE;
4503 else if ($this->draw_broken_lines) {
4504 $start_lines[$idx] = FALSE;
4509 ImageSetThickness($this->img, 1);
4519 if ($this->data_type !=
'text-data') {
4520 return $this->
PrintError(
'DrawBars(): Bar plots must be text-data: use function SetDataType("text-data")');
4525 $x_first_bar = (($this->records_per_group - 1) * $this->record_bar_width) / 2 - $this->bar_adjust_gap;
4530 $x_now_pixels = $this->
xtr(0.5 +
$row);
4532 if ($this->x_data_label_pos !=
'none')
4536 $x1 = $x_now_pixels - $x_first_bar;
4539 for ($idx = 0; $record < $this->num_recs[
$row]; $record++, $idx++) {
4540 if (is_numeric($this->data[$row][$record])) {
4541 $x2 = $x1 + $this->actual_bar_width;
4543 if ($this->data[$row][$record] < $this->x_axis_position) {
4544 $y1 = $this->x_axis_y_pixels;
4545 $y2 = $this->
ytr($this->data[$row][$record]);
4546 $upgoing_bar = False;
4548 $y1 = $this->
ytr($this->data[$row][$record]);
4549 $y2 = $this->x_axis_y_pixels;
4550 $upgoing_bar = True;
4554 ImageFilledRectangle($this->img, $x1, $y1, $x2, $y2, $this->ndx_data_colors[$idx]);
4556 if ($this->shading) {
4557 ImageFilledPolygon($this->img, array($x1, $y1,
4558 $x1 + $this->shading, $y1 - $this->shading,
4559 $x2 + $this->shading, $y1 - $this->shading,
4560 $x2 + $this->shading, $y2 - $this->shading,
4563 6, $this->ndx_data_dark_colors[$idx]);
4567 ImageRectangle($this->img, $x1, $y1, $x2,$y2, $this->ndx_data_border_colors[$idx]);
4571 if ( $this->y_data_label_pos ==
'plotin') {
4573 $v_align =
'bottom';
4579 $this->
DrawDataLabel($this->y_label_font, NULL, $row+0.5, $this->data[$row][$record],
'',
4580 $this->data[$row][$record],
'center', $v_align,
4581 ($idx + 0.5) * $this->record_bar_width - $x_first_bar, $y_offset);
4586 $x1 += $this->record_bar_width;
4599 if ($this->data_type !=
'text-data') {
4600 return $this->
PrintError(
'DrawStackedBars(): Bar plots must be text-data: use SetDataType("text-data")');
4604 $x_first_bar = $this->record_bar_width / 2 - $this->bar_adjust_gap;
4609 $x_now_pixels = $this->
xtr(0.5 +
$row);
4611 if ($this->x_data_label_pos !=
'none')
4615 $x1 = $x_now_pixels - $x_first_bar;
4616 $x2 = $x1 + $this->actual_bar_width;
4620 for ($idx = 0; $record < $this->num_recs[
$row]; $record++, $idx++) {
4621 if (is_numeric($this->data[$row][$record])) {
4623 $y1 = $this->
ytr(abs($this->data[$row][$record]) + $oldv);
4624 $y2 = $this->
ytr($this->x_axis_position + $oldv);
4625 $oldv += abs($this->data[$row][$record]);
4628 ImageFilledRectangle($this->img, $x1, $y1, $x2, $y2, $this->ndx_data_colors[$idx]);
4630 if ($this->shading) {
4631 ImageFilledPolygon($this->img, array($x1, $y1,
4632 $x1 + $this->shading, $y1 - $this->shading,
4633 $x2 + $this->shading, $y1 - $this->shading,
4634 $x2 + $this->shading, $y2 - $this->shading,
4637 6, $this->ndx_data_dark_colors[$idx]);
4641 ImageRectangle($this->img, $x1, $y1, $x2,$y2, $this->ndx_data_border_colors[$idx]);
4657 return $this->
PrintError(
'DrawGraph(): No image resource allocated');
4659 if (empty($this->data) || ! is_array($this->data)) {
4660 return $this->
PrintError(
"DrawGraph(): No data array");
4662 if ($this->total_records == 0) {
4663 return $this->
PrintError(
'DrawGraph(): Empty data set');
4668 $draw_axes = ($this->plot_type !=
'pie');
4700 $this->
DoCallback(
'draw_plotarea_background');
4707 if ($draw_axes && ! $this->grid_at_foreground) {
4713 switch ($this->plot_type) {
4724 if ( $this->data_type ==
'data-data-error') {
4731 if ( $this->data_type ==
'data-data-error') {
4740 if ( $this->data_type ==
'data-data-error') {
4755 $this->plot_type =
'bars';
4762 if ($draw_axes && $this->grid_at_foreground) {
4773 if ($this->legend) {
4778 if ($this->print_image && !$this->
PrintImage())
4793 if ($which_dvt != 1)
4803 if ($which_dht != 1)
4862 return $this->
SetFont(
'title', $which_size);
4870 $this->
SetFont(
'x_label', $which_size);
4871 $this->
SetFont(
'y_label', $which_size);
4879 return $this->
SetFont(
'generic', $which_size);
4887 return $this->
SetFont(
'x_title', $which_size);
4895 return $this->
SetFont(
'y_title', $which_size);
4960 $this->x_title_pos = $xpos;
4969 $this->y_title_pos = $xpos;
4989 if ($which_dxdl ==
'1' )
5001 $this->plot_area = array($x1, $y1, $x2, $y2);
5002 $this->plot_area_width = $this->plot_area[2] - $this->plot_area[0];
5003 $this->plot_area_height = $this->plot_area[3] - $this->plot_area[1];
5004 $this->y_top_margin = $this->plot_area[1];
5006 if (isset($this->plot_max_x))
5029 if (!$this->error_bar_line_width) {