diff options
author | Michael Larabel <michael@phx-laptop.(none)> | 2008-11-27 11:02:12 -0500 |
---|---|---|
committer | Michael Larabel <michael@phx-laptop.(none)> | 2008-11-27 11:02:12 -0500 |
commit | 41c3d53a7f3e5bd1f62164e927fd77ef92f3de59 (patch) | |
tree | d34e29c75e7e594a5d3cb9074d96602661f6a2d9 | |
parent | a60a7fe1ee47c0175d30184029fc3ddbfd52a81b (diff) | |
download | phoronix-test-suite-upstream-41c3d53a7f3e5bd1f62164e927fd77ef92f3de59.tar.gz phoronix-test-suite-upstream-41c3d53a7f3e5bd1f62164e927fd77ef92f3de59.tar.xz phoronix-test-suite-upstream-41c3d53a7f3e5bd1f62164e927fd77ef92f3de59.zip |
pts-core: Add support for dynamically loading objects from
sub-directories of pts-core/objects/
(Forgot to git-add to previous commit)
-rw-r--r-- | pts-core/objects/pts_Graph/pts_BarGraph.php | 120 | ||||
-rw-r--r-- | pts-core/objects/pts_Graph/pts_CustomGraph.php | 72 | ||||
-rw-r--r-- | pts-core/objects/pts_Graph/pts_Graph.php | 900 | ||||
-rw-r--r-- | pts-core/objects/pts_Graph/pts_LineGraph.php | 146 | ||||
-rw-r--r-- | pts-core/objects/pts_Graph/pts_MultiPassFailGraph.php | 127 | ||||
-rw-r--r-- | pts-core/objects/pts_Graph/pts_PassFailGraph.php | 99 | ||||
-rw-r--r-- | pts-core/objects/tandem_Xml/pts_test_tandem_XmlReader.php | 53 | ||||
-rw-r--r-- | pts-core/objects/tandem_Xml/tandem_XmlReader.php | 309 | ||||
-rw-r--r-- | pts-core/objects/tandem_Xml/tandem_XmlWriter.php | 199 |
9 files changed, 2025 insertions, 0 deletions
diff --git a/pts-core/objects/pts_Graph/pts_BarGraph.php b/pts-core/objects/pts_Graph/pts_BarGraph.php new file mode 100644 index 0000000..b928b49 --- /dev/null +++ b/pts-core/objects/pts_Graph/pts_BarGraph.php @@ -0,0 +1,120 @@ +<?php + +/* + Phoronix Test Suite + URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/ + Copyright (C) 2008, Phoronix Media + Copyright (C) 2008, Michael Larabel + pts_BarGraph.php: The bar graph object that extends pts_Graph.php. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +class pts_BarGraph extends pts_CustomGraph +{ + var $identifier_width = -1; + var $minimum_identifier_font = 7; + + public function __construct($title, $sub_title, $y_axis_title) + { + parent::__construct($title, $sub_title, $y_axis_title); + $this->graph_type = "BAR_GRAPH"; + } + protected function render_graph_pre_init() + { + // Do some common work to this object + $identifier_count = count($this->graph_identifiers); + $this->identifier_width = floor(($this->graph_left_end - $this->graph_left_start) / $identifier_count); + + $longest_string = $this->find_longest_string($this->graph_identifiers); + $width = $this->identifier_width - 8; + $this->graph_font_size_identifiers = $this->text_size_bounds($longest_string, $this->graph_font, $this->graph_font_size_identifiers, $this->minimum_identifier_font, $width); + + if($this->graph_font_size_identifiers == $this->minimum_identifier_font) + { + $this->update_graph_dimensions($this->graph_attr_width, $this->graph_attr_height + $this->text_string_width($longest_string, $this->graph_font, 9)); + } + } + protected function render_graph_identifiers() + { + $px_from_top_start = $this->graph_top_end - 5; + $px_from_top_end = $this->graph_top_end + 5; + + for($i = 0; $i < count($this->graph_identifiers); $i++) + { + $px_bound_left = $this->graph_left_start + ($this->identifier_width * $i); + $px_bound_right = $px_bound_left + $this->identifier_width; + + if($i == 0) + { + $this->draw_line($this->graph_image, $px_bound_left, $px_from_top_start, $px_bound_left, $px_from_top_end, $this->graph_color_notches); + } + + if($i == (count($this->graph_identifiers) - 1) && $px_bound_right != $this->graph_left_end) + { + $px_bound_right = $this->graph_left_end; + } + + $this->draw_line($this->graph_image, $px_bound_right, $px_from_top_start, $px_bound_right, $px_from_top_end, $this->graph_color_notches); + + if($this->graph_font_size_identifiers == $this->minimum_identifier_font) + { + $this->write_text_left($this->graph_identifiers[$i], 9, $this->graph_color_headers, $px_bound_left + ceil($this->identifier_width / 2), $px_from_top_end, $px_bound_left + ceil($this->identifier_width / 2), $px_from_top_end, true); + } + else + { + $this->write_text_center($this->graph_identifiers[$i], $this->graph_font_size_identifiers, $this->graph_color_headers, $px_bound_left, $px_from_top_end - 5, $px_bound_right, $px_from_top_end - 5, false, true); + } + } + } + protected function render_graph_bars() + { + $bar_count = count($this->graph_data); + $bar_width = floor($this->identifier_width / $bar_count) - ($bar_count * 16); + + for($i_o = 0; $i_o < $bar_count; $i_o++) + { + $paint_color = $this->next_paint_color(); + + for($i = 0; $i < count($this->graph_data[$i_o]); $i++) + { + $value = $this->trim_double($this->graph_data[$i_o][$i], 2); + $graph_size = round(($value / $this->graph_maximum_value) * ($this->graph_top_end - $this->graph_top_start)); + $value_plot_top = $this->graph_top_end + 1 - $graph_size; + + $px_bound_left = $this->graph_left_start + ($this->identifier_width * $i) + ($bar_width * $i_o) + 8; + $px_bound_right = $px_bound_left + $bar_width; + + if($value_plot_top < 1) + { + $value_plot_top = 1; + } + + $this->draw_rectangle_border($this->graph_image, $px_bound_left, $value_plot_top - 1, $px_bound_right, $this->graph_top_end - 1, $this->graph_color_body_light); + $this->draw_rectangle($this->graph_image, $px_bound_left + 1, $value_plot_top, $px_bound_right - 1, $this->graph_top_end - 1, $paint_color); + + if($graph_size > 20) + { + $this->write_text_center($this->graph_data[$i_o][$i], $this->graph_font_size_bars, $this->graph_color_body_text, $px_bound_left, $value_plot_top + 3, $px_bound_right, $value_plot_top + 3); + } + } + } + } + protected function render_graph_result() + { + $this->render_graph_bars(); + } +} + +?> diff --git a/pts-core/objects/pts_Graph/pts_CustomGraph.php b/pts-core/objects/pts_Graph/pts_CustomGraph.php new file mode 100644 index 0000000..59432f2 --- /dev/null +++ b/pts-core/objects/pts_Graph/pts_CustomGraph.php @@ -0,0 +1,72 @@ +<?php + +/* + Phoronix Test Suite + URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/ + Copyright (C) 2008, Phoronix Media + Copyright (C) 2008, Michael Larabel + pts_CustomGraph.php: A pass-through extension extending pts_Graph that over-rides attributes with the PTS user configuration options. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +class pts_CustomGraph extends pts_Graph +{ + function __construct($Title, $SubTitle, $YTitle) + { + if(is_file(PTS_USER_DIR . "graph-config.xml")) + { + $file = file_get_contents(PTS_USER_DIR . "graph-config.xml"); + } + else + { + $file = ""; + } + + $read_config = new tandem_XmlReader($file); + + $this->graph_attr_width = pts_read_graph_config(P_GRAPH_SIZE_WIDTH, null, $read_config); // Graph width + $this->graph_attr_height = pts_read_graph_config(P_GRAPH_SIZE_HEIGHT, null, $read_config); // Graph height + $this->graph_attr_big_border = pts_read_graph_config(P_GRAPH_BORDER, null, $read_config) == "TRUE"; // Graph border + + // Colors + $this->graph_color_notches = pts_read_graph_config(P_GRAPH_COLOR_NOTCHES, null, $read_config); // Color for notches + $this->graph_color_text = pts_read_graph_config(P_GRAPH_COLOR_TEXT, null, $read_config); // Color for text + $this->graph_color_border = pts_read_graph_config(P_GRAPH_COLOR_BORDER, null, $read_config); // Color for border (if used) + $this->graph_color_main_headers = pts_read_graph_config(P_GRAPH_COLOR_MAINHEADERS, null, $read_config); // Color of main text headers + $this->graph_color_headers = pts_read_graph_config(P_GRAPH_COLOR_HEADERS, null, $read_config); // Color of other headers + $this->graph_color_background = pts_read_graph_config(P_GRAPH_COLOR_BACKGROUND, null, $read_config); // Color of background + $this->graph_color_body = pts_read_graph_config(P_GRAPH_COLOR_BODY, null, $read_config); // Color of graph body + $this->graph_color_body_text = pts_read_graph_config(P_GRAPH_COLOR_BODYTEXT, null, $read_config); // Color of graph body text + $this->graph_color_body_light = pts_read_graph_config(P_GRAPH_COLOR_ALTERNATE, null, $read_config); // Color of the border around graph bars (if doing a bar graph) + + $this->graph_color_paint = explode(", ", pts_read_graph_config(P_GRAPH_COLOR_PAINT, null, $read_config)); // Colors to use for the bars / lines, one color for each key + + // Text + $this->graph_watermark_text = pts_read_graph_config(P_GRAPH_WATERMARK, null, $read_config); // watermark + $this->graph_font = pts_read_graph_config(P_GRAPH_FONT_TYPE, null, $read_config); // TTF file name + $this->graph_font_size_heading = pts_read_graph_config(P_GRAPH_FONT_SIZE_HEADERS, null, $read_config); // Font size of headings + $this->graph_font_size_bars = pts_read_graph_config(P_GRAPH_FONT_SIZE_TEXT, null, $read_config); // Font size for text on the bars/objects + $this->graph_font_size_identifiers = pts_read_graph_config(P_GRAPH_FONT_SIZE_IDENTIFIERS, null, $read_config); // Font size of identifiers + $this->graph_font_size_sub_heading = pts_read_graph_config(P_GRAPH_FONT_SIZE_SUBHEADERS, null, $read_config); // Font size of headers + $this->graph_font_size_axis_heading = pts_read_graph_config(P_GRAPH_FONT_SIZE_AXIS, null, $read_config); // Font size of axis headers + + $this->graph_attr_big_border = pts_read_graph_config(P_GRAPH_RENDERBORDER, null, $read_config); // Border around graph or not + $this->graph_attr_marks = pts_read_graph_config(P_GRAPH_MARKCOUNT, null, $read_config); // Number of marks to make on vertical axis + + parent::__construct($Title, $SubTitle, $YTitle); + } +} + +?> diff --git a/pts-core/objects/pts_Graph/pts_Graph.php b/pts-core/objects/pts_Graph/pts_Graph.php new file mode 100644 index 0000000..5a280d9 --- /dev/null +++ b/pts-core/objects/pts_Graph/pts_Graph.php @@ -0,0 +1,900 @@ +<?php + +/* + Phoronix Test Suite + URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/ + Copyright (C) 2008, Phoronix Media + Copyright (C) 2008, Michael Larabel + pts_Graph.php: The core graph object that is used by the different graphing objects. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +class pts_Graph +{ + // Defaults + var $graph_attr_marks = 6; // Number of marks to make on vertical axis + var $graph_attr_width = 580; // Graph width + var $graph_attr_height = 300; // Graph height + var $graph_attr_big_border = false; // Border around graph or not + + var $graph_left_start = 20; // Distance in px to start graph from left side + var $graph_left_end_opp = 10; // Distance in px to end graph from right side + var $graph_top_start = 60; // Distance in px to start graph from top side + var $graph_top_end_opp = 22; // Distance in px to end graph from bottom side + + // Colors + var $graph_color_notches = "#000000"; // Color for notches + var $graph_color_text = "#000000"; // Color for text + var $graph_color_border = "#000000"; // Color for border (if used) + var $graph_color_main_headers = "#2b6b29"; // Color of main text headers + var $graph_color_headers = "#2b6b29"; // Color of other headers + var $graph_color_background = "#FFFFFF"; // Color of background + var $graph_color_body = "#8b8f7c"; // Color of graph body + var $graph_color_body_text = "#FFFFFF"; // Color of graph body text + var $graph_color_body_light = "#B0B59E"; // Color of the border around graph bars (if doing a bar graph) + + var $graph_color_paint = array("#3B433A", "#BB2413", "#FF9933", "#006C00", "#5028CA"); // Colors to use for the bars / lines, one color for each key + + // Text + var $graph_font = "Sans.ttf"; // TTF file name + var $graph_font_size_tick_mark = 10; // Tick mark size + var $graph_font_size_key = 9; // Size of height for keys + var $graph_font_size_heading = 18; // Font size of headings + var $graph_font_size_bars = 12; // Font size for text on the bars/objects + var $graph_font_size_identifiers = 11; // Font size of identifiers + var $graph_font_size_sub_heading = 12; // Font size of headers + var $graph_font_size_axis_heading = 11; // Font size of axis headers + var $graph_watermark_text = "PHORONIX-TEST-SUITE.COM"; // Text for watermark in upper right hand corner. If null, no watermark will display + var $graph_version = ""; + var $graph_proportion = ""; + + // CHANGE DIRECTORY FOR TTF FONT LOCATION INSIDE __construct FUNCTION + + // Not user-friendly changes below this line + var $graph_body_image = false; + var $graph_hide_identifiers = false; + var $graph_show_key = false; + var $graph_background_lines = false; + var $graph_type = "GRAPH"; + var $graph_value_type = "NUMERICAL"; + var $graph_image; + var $graph_maximum_value; + + var $graph_output = null; + var $graph_renderer = "PNG"; + var $graph_data = array(); + var $graph_data_title = array(); + var $graph_color_paint_index = -1; + var $graph_identifiers; + var $graph_title; + var $graph_sub_title; + var $graph_y_title; + var $graph_y_title_hide = false; + var $graph_top_end; + var $graph_left_end; + + var $graph_internal_identifiers = array(); + + public function __construct($title, $sub_title, $y_axis_title) + { + $this->graph_title = $title; + $this->graph_sub_title = $sub_title; + $this->graph_y_title = $y_axis_title; + + $this->update_graph_dimensions(-1, -1, true); + + // Directory for TTF Fonts + if(defined("FONT_DIR")) + { + putenv("GDFONTPATH=" . FONT_DIR); + } + else if(($font_env = getenv("FONT_DIR")) != false) + { + putenv("GDFONTPATH=" . $font_env); + } + else + { + putenv("GDFONTPATH=" . getcwd()); + } + } + public function setRenderer($renderer) + { + if($renderer == "SVG") + { + $this->graph_renderer = "SVG"; + $this->graph_left_start += 10; + } + else + { + $this->graph_renderer = "PNG"; + } + } + public function getRenderer() + { + return $this->graph_renderer; + } + + // + // Load Functions + // + + public function loadGraphIdentifiers($data_array) + { + $this->graph_identifiers = $data_array; + } + public function hideGraphIdentifiers() + { + $this->graph_hide_identifiers = true; + } + public function loadGraphVersion($data) + { + if(!empty($data)) + { + $this->graph_version = "Phoronix Test Suite " . $data; + } + } + public function loadGraphProportion($data) + { + if($data == "LIB") + { + $this->graph_proportion = "Less Is Better"; + } + //else if($data == "HIB") + // $this->graph_proportion = "More Is Better"; + } + public function loadGraphData($data_array) + { + loadGraphValues($data_array); + } + public function loadGraphValues($data_array, $data_title = null) + { + for($i = 0; $i < count($data_array); $i++) + { + if(is_float($data_array[$i])) + { + $data_array[$i] = $this->trim_double($data_array[$i], 2); + } + } + + array_push($this->graph_data, $data_array); + + if(!empty($data_title)) + { + array_push($this->graph_data_title, $data_title); + } + } + public function setGraphBackgroundPNG($file) + { + $img = $this->read_png_image($file); + + if($img != false) + { + $this->graph_body_image = $img; + } + } + public function renderGraph() + { + $this->graph_maximum_value = $this->maximum_graph_value(); + + // Make room for tick markings, left hand side + if($this->graph_value_type == "NUMERICAL") + { + $this->graph_left_start += $this->text_string_width($this->graph_maximum_value, $this->graph_font, $this->graph_font_size_tick_mark) + 2; + } + + if($this->graph_hide_identifiers == true) + { + $this->graph_top_end += $this->graph_top_end_opp / 2; + } + + // Do the actual work + $this->render_graph_pre_init(); + $this->render_graph_init(); + $this->render_graph_base(); + + if(!$this->graph_hide_identifiers) + { + $this->render_graph_identifiers(); + } + + if($this->graph_value_type == "NUMERICAL") + { + $this->render_graph_value_ticks(); + } + + $this->render_graph_key(); + $this->render_graph_result(); + $this->render_graph_watermark(); + $this->return_graph_image(); + } + public function addInternalIdentifier($identifier, $value) + { + $this->graph_internal_identifiers[$identifier] = $value; + } + public function saveGraphToFile($file) + { + $this->graph_output = $file; + } + + // + // Misc Functions + // + + protected function next_paint_color() + { + if($this->graph_color_paint_index + 1 < count($this->graph_color_paint)) + { + $this->graph_color_paint_index += 1; + } + else + { + $this->graph_color_paint_index = 0; + } + + return $this->graph_color_paint[$this->graph_color_paint_index]; + } + protected function reset_paint_index() + { + $this->graph_color_paint_index = -1; + } + protected function maximum_graph_value() + { + $maximum = $this->graph_attr_marks; + + foreach($this->graph_data as $graph_set) + { + foreach($graph_set as $set_item) + { + if((is_numeric($set_item) && $set_item > $maximum) || (!is_numeric($set_item) && strlen($set_item) > strlen($maximum))) + { + $maximum = $set_item; + } + } + } + + if(is_numeric($maximum)) + { + $maximum = (floor(round($maximum * 1.35) / $this->graph_attr_marks) + 1) * $this->graph_attr_marks; + } + + return $maximum; + } + protected function text_string_width($string, $font, $size) + { + $dimensions = $this->text_string_dimensions($string, $font, $size); + return $dimensions[0]; + } + protected function text_string_height($string, $font, $size) + { + $dimensions = $this->text_string_dimensions($string, $font, $size); + return $dimensions[1]; + } + protected function text_size_bounds($string, $font, $font_size, $minimum_font_size, $bound_width, $bound_height = -1) + { + while($font_size > $minimum_font_size && ($this->text_string_width($string, $font, $font_size) > $bound_width || ($bound_height > 0 && $this->text_string_height($string, $font, $font_size) > $bound_height))) + { + $font_size -= 0.5; + } + + return $font_size; + } + protected function find_longest_string($string_r) + { + $longest_string = ""; + $longest_string_length = 0; + + foreach($string_r as $one_string) + { + if(($new_length = strlen($one_string)) > $longest_string_length) + { + $longest_string = $one_string; + $longest_string_length = $new_length; + } + } + + return $longest_string; + } + protected function update_graph_dimensions($width = -1, $height = -1, $recalculate_offsets = false) + { + // Allow render area to be increased, but not decreased + if($width > $this->graph_attr_width) + { + $this->graph_attr_width = $width; + } + if($height > $this->graph_attr_height) + { + $this->graph_attr_height = $height; + } + + if($recalculate_offsets) + { + $this->graph_top_end = $this->graph_attr_height - $this->graph_top_end_opp; + $this->graph_left_end = $this->graph_attr_width - $this->graph_left_end_opp; + } + } + + // + // Render Functions + // + + protected function render_graph_pre_init() + { + return; + } + protected function render_graph_init() + { + $this->update_graph_dimensions(); + $this->graph_image = $this->init_blank_image($this->graph_attr_width, $this->graph_attr_height); + + // Initalize Colors + + $this->graph_color_notches = $this->convert_hex_to_type($this->graph_color_notches); + $this->graph_color_text = $this->convert_hex_to_type($this->graph_color_text); + $this->graph_color_border = $this->convert_hex_to_type($this->graph_color_border); + $this->graph_color_main_headers = $this->convert_hex_to_type($this->graph_color_main_headers); + $this->graph_color_headers = $this->convert_hex_to_type($this->graph_color_headers); + $this->graph_color_background = $this->convert_hex_to_type($this->graph_color_background); + $this->graph_color_body = $this->convert_hex_to_type($this->graph_color_body); + $this->graph_color_body_text = $this->convert_hex_to_type($this->graph_color_body_text); + $this->graph_color_body_light = $this->convert_hex_to_type($this->graph_color_body_light); + + for($i = 0; $i < count($this->graph_color_paint); $i++) + { + $this->graph_color_paint[$i] = $this->convert_hex_to_type($this->graph_color_paint[$i]); + } + + // Background Color + $this->draw_rectangle($this->graph_image, 0, 0, $this->graph_attr_width, $this->graph_attr_height, $this->graph_color_background); + + if($this->graph_attr_big_border == true) + { + $this->draw_rectangle_border($this->graph_image, 0, 0, $this->graph_attr_width - 1, $this->graph_attr_height - 1, $this->graph_color_border); + } + } + protected function render_graph_base() + { + if(count($this->graph_data_title) > 1 || $this->graph_show_key == true) + { + $num_key_lines = ceil(count($this->graph_data_title) / 4); + $this->graph_top_start = $this->graph_top_start + 8 + ($num_key_lines * 11); + } + + $this->draw_rectangle($this->graph_image, $this->graph_left_start, $this->graph_top_start, $this->graph_left_end, $this->graph_top_end, $this->graph_color_body); + $this->draw_rectangle_border($this->graph_image, $this->graph_left_start, $this->graph_top_start, $this->graph_left_end, $this->graph_top_end, $this->graph_color_notches); + + if($this->graph_body_image != false) + { + $this->image_copy_merge($this->graph_image, $this->graph_body_image, $this->graph_left_start + (($this->graph_left_end - $this->graph_left_start) / 2) - imagesx($this->graph_body_image) / 2, $this->graph_top_start + (($this->graph_top_end - $this->graph_top_start) / 2) - imagesy($this->graph_body_image) / 2); + } + + // Text + $this->write_text_right($this->graph_version, 7, $this->graph_color_body_light, $this->graph_left_end, $this->graph_top_start - 9, $this->graph_left_end, $this->graph_top_start - 9); + $this->write_text_center($this->graph_title, $this->graph_font_size_heading, $this->graph_color_main_headers, $this->graph_left_start, 4, $this->graph_left_end, 4); + $this->write_text_center($this->graph_sub_title, $this->graph_font_size_sub_heading, $this->graph_color_main_headers, $this->graph_left_start, 26, $this->graph_left_end, 26, false, true); + + if(!empty($this->graph_y_title) && !$this->graph_y_title_hide) + { + $str = $this->graph_y_title; + + if(!empty($this->graph_proportion)) + { + if(!empty($str)) + { + $str .= ", "; + } + + $str .= $this->graph_proportion; + } + + $this->write_text_left($str, 7, $this->graph_color_main_headers, $this->graph_left_start, $this->graph_top_start - 9, $this->graph_left_start, $this->graph_top_start - 9); + } + } + protected function render_graph_value_ticks() + { + $tick_width = ($this->graph_top_end - $this->graph_top_start) / $this->graph_attr_marks; + $px_from_left_start = $this->graph_left_start - 5; + $px_from_left_end = $this->graph_left_start + 5; + + $display_value = 0; + + for($i = 0; $i < $this->graph_attr_marks; $i++) + { + $px_from_top = $this->graph_top_end - ($tick_width * $i); + + $this->draw_line($this->graph_image, $px_from_left_start, $px_from_top, $px_from_left_end, $px_from_top, $this->graph_color_notches); + + $this->write_text_right($display_value, $this->graph_font_size_tick_mark, $this->graph_color_text, $px_from_left_start - 1, $px_from_top - 2, $px_from_left_start - 1, $px_from_top - 2); + + if($i != 0 && $this->graph_background_lines == true) + { + $line_width = 6; + for($y = $px_from_left_end + $line_width; $y < $this->graph_left_end; $y += ($line_width * 2)) + { + if($y + $line_width < $this->graph_left_end) + { + $this->draw_line($this->graph_image, $y, $px_from_top, $y += $line_width, $px_from_top, $this->graph_color_body_light); + } + else + { + $this->draw_line($this->graph_image, $y, $px_from_top, $y += ($this->graph_left_end - $y) - 1, $px_from_top, $this->graph_color_body_light); + } + } + } + + $display_value += $this->trim_double($this->graph_maximum_value / $this->graph_attr_marks, 2); + } + } + protected function render_graph_identifiers() + { + return; + } + protected function render_graph_result() + { + return; + } + protected function render_graph_key() + { + if(count($this->graph_data_title) < 2 && $this->graph_show_key == false) + { + return; + } + + $key_counter = 0; + $component_y = $this->graph_top_start - 20; + $this->reset_paint_index(); + + for($i = 0; $i < count($this->graph_data_title); $i++) + { + if(!empty($this->graph_data_title)) + { + $this_color = $this->next_paint_color(); + $key_counter += 1; + $key_offset = $key_counter % 4; + + $component_x = $this->graph_left_start + 15 + (($this->graph_left_end - $this->graph_left_start) / 4) * $key_offset; + + $this->write_text_left($this->graph_data_title[$i], $this->graph_font_size_key, $this_color, $component_x, $component_y, $component_x, $component_y); + + $this->draw_rectangle($this->graph_image, $component_x - 13, $component_y - 5, $component_x - 3, $component_y + 5, $this_color); + $this->draw_rectangle_border($this->graph_image, $component_x - 13, $component_y - 5, $component_x - 3, $component_y + 5, $this->graph_color_notches); + + if($key_counter % 4 == 0) + { + $component_y -= 12; + } + } + } + $this->reset_paint_index(); + } + protected function render_graph_watermark() + { + if(!empty($this->graph_watermark_text)) + { + $this->write_text_right($this->graph_watermark_text, 10, $this->graph_color_text, $this->graph_left_end - 2, $this->graph_top_start + 8, $this->graph_left_end - 2, $this->graph_top_start + 8); + } + } + protected function return_graph_image() + { + $this->render_image($this->graph_image, $this->graph_output, 5); + $this->deinit_image($this->graph_image); + } + protected function trim_double($double, $accuracy = 2) + { + // Set precision for a variable's points after the decimal spot + $return = explode(".", $double); + + if(count($return) == 1) + { + $return[1] = "00"; + } + + if(count($return) == 2 && $accuracy > 0) + { + $strlen = strlen($return[1]); + + if($strlen > $accuracy) + { + $return[1] = substr($return[1], 0, $accuracy); + } + else if($strlen < $accuracy) + { + for($i = $strlen; $i < $accuracy; $i++) + { + $return[1] .= '0'; + } + } + + $return = $return[0] . "." . $return[1]; + } + else + { + $return = $return[0]; + } + + return $return; + } + + + // + // Renderer-specific Functions + // + + protected function init_blank_image($width, $height) + { + if($this->graph_renderer == "PNG") + { + $img = imagecreate($width, $height); + + imageinterlace($img, true); + + if(function_exists("imageantialias")) + { + imageantialias($img, true); + } + } + else if($this->graph_renderer == "SVG") + { + $img = "<?xml version=\"1.0\"?>\n<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">\n"; + + foreach($this->graph_internal_identifiers as $key => $value) + { + $img .= "<!-- " . $key . ": " . $value . " -->\n"; + } + + $img .= "<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" viewbox=\"0 0 " . $width . " " . $height . "\" width=\"" . $width . "\" height=\"" . $height . "\">\n\n"; + } + + return $img; + } + protected function render_image(&$img_object, $output_file = null, $quality = 0) + { + if($this->graph_renderer == "PNG") + { + imagepng($img_object, $output_file, $quality); + } + else if($this->graph_renderer == "SVG") + { + $img_object .= "\n\n</svg>"; + + if($output_file != null) + { + @file_put_contents($output_file, $img_object); + } + } + } + protected function read_png_image($file) + { + if($this->graph_renderer == "PNG") + { + $img = @imagecreatefrompng($file); + } + else + { + $img = null; + } + + return $img; + } + protected function deinit_image(&$img_object) + { + if($this->graph_renderer == "PNG") + { + imagedestroy($img_object); + } + else if($this->graph_renderer == "SVG") + { + $img_object = null; + } + } + protected function convert_hex_to_type($hex) + { + if($this->graph_renderer == "PNG") + { + $color = imagecolorallocate($this->graph_image, hexdec(substr($hex, 1, 2)), hexdec(substr($hex, 3, 2)), hexdec(substr($hex, 5, 2))); + } + else if($this->graph_renderer == "SVG") + { + $color = $hex; + } + + return $color; + } + protected function write_text_left($text_string, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate = false) + { + if(empty($text_string)) + { + return; + } + + if($this->graph_renderer == "PNG") + { + $ttf_dimensions = $this->text_string_dimensions($text_string, $this->graph_font, $font_size); + $ttf_width = $ttf_dimensions[0]; + $ttf_height = $ttf_dimensions[1]; + + if($rotate == false) + { + $text_x = $bound_x1; + $text_y = $bound_y1 + round($ttf_height / 2); + $rotation = 0; + } + else + { + $text_x = $bound_x1 - round($ttf_height / 4); + $text_y = $bound_y1 + round($ttf_height / 2); + $rotation = 270; + } + imagettftext($this->graph_image, $font_size, $rotation, $text_x, $text_y, $font_color, $this->graph_font, $text_string); + } + else if($this->graph_renderer == "SVG") + { + $ttf_dimensions = $this->text_string_dimensions($text_string, $this->graph_font, $font_size); + $ttf_width = $ttf_dimensions[0]; + $ttf_height = $ttf_dimensions[1]; + + if($rotate == false) + { + $text_x = $bound_x1; + $text_y = $bound_y1 + round($ttf_height / 2); + $rotation = 0; + } + else + { + $text_x = $bound_x1 - round($ttf_height / 4); + $text_y = $bound_y1 + round($ttf_height / 2); + $rotation = 270; + } + $this->write_svg_text($this->graph_image, $font_size, $rotation, $text_x, $text_y, $font_color, $this->graph_font, $text_string, "LEFT"); + } + } + protected function write_text_right($text_string, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate_text = false) + { + if(empty($text_string)) + { + return; + } + + if($this->graph_renderer == "PNG") + { + $ttf_dimensions = $this->text_string_dimensions($text_string, $this->graph_font, $font_size); + $ttf_width = $ttf_dimensions[0]; + $ttf_height = $ttf_dimensions[1]; + + if($rotate_text == false) + { + $rotation = 0; + } + else + { + $rotation = 90; + } + + $text_x = $bound_x2 - $ttf_width; + $text_y = $bound_y1 + round($ttf_height / 2); + + imagettftext($this->graph_image, $font_size, $rotation, $text_x, $text_y, $font_color, $this->graph_font, $text_string); + } + else if($this->graph_renderer == "SVG") + { + $ttf_dimensions = $this->text_string_dimensions($text_string, $this->graph_font, $font_size); + $ttf_width = $ttf_dimensions[0]; + $ttf_height = $ttf_dimensions[1]; + + $bound_x1 -= 2; + $bound_x2 -= 2; + + if($rotate_text == false) + { + $rotation = 0; + } + else + { + $rotation = 90; + } + + $text_x = $bound_x2 - $ttf_width; + $text_y = $bound_y1 + round($ttf_height / 2); + + $this->write_svg_text($this->graph_image, $font_size, $rotation, $text_x, $text_y, $font_color, $this->graph_font, $text_string, "RIGHT"); + } + } + protected function write_text_center($text_string, $font_size, $font_color, $bound_x1, $bound_y1, $bound_x2, $bound_y2, $rotate_text = false, $big_type = false) + { + if(empty($text_string)) + { + return; + } + + if($this->graph_renderer == "PNG") + { + if($bound_x1 != $bound_x2) + { + while($this->text_string_width($this->trim_double($text_string, 2), $this->graph_font, $font_size) > abs($bound_x2 - $bound_x1 - 3)) + { + $font_size -= 0.5; + } + } + + $ttf_dimensions = $this->text_string_dimensions(strtoupper($text_string), $this->graph_font, $font_size, $big_type); + $ttf_height = $ttf_dimensions[1]; + + $ttf_dimensions = $this->text_string_dimensions($text_string, $this->graph_font, $font_size, $big_type); + $ttf_width = $ttf_dimensions[0]; + + if($rotate_text == false) + { + $rotation = 0; + $text_x = (($bound_x2 - $bound_x1) / 2) + $bound_x1 - round($ttf_width / 2); + $text_y = $bound_y1 + $ttf_height; + } + else + { + $rotation = 90; + $text_x = $bound_x1 + $ttf_height; + $text_y = (($bound_y2 - $bound_y1) / 2) + $bound_y1 + round($ttf_width / 2); + } + + imagettftext($this->graph_image, $font_size, $rotation, $text_x, $text_y, $font_color, $this->graph_font, $text_string); + } + else if($this->graph_renderer == "SVG") + { + // $font_size = $this->graph_font_size_bars; + // while($this->text_string_width($this->trim_double($this->graph_maximum_value, 3), $this->graph_font, $font_size) > ($bar_width - 6)) + // $font_size -= 0.5; + + $ttf_dimensions = $this->text_string_dimensions(strtoupper($text_string), $this->graph_font, $font_size, $big_type); + $ttf_height = $ttf_dimensions[1]; + + $ttf_dimensions = $this->text_string_dimensions($text_string, $this->graph_font, $font_size, $big_type); + $ttf_width = $ttf_dimensions[0]; + + if($rotate_text == false) + { + $rotation = 0; + $text_x = (($bound_x2 - $bound_x1) / 2) + $bound_x1 - round($ttf_width / 2); + $text_y = $bound_y1 + $ttf_height; + } + else + { + $rotation = 90; + $text_x = $bound_x1 + $ttf_height; + $text_y = (($bound_y2 - $bound_y1) / 2) + $bound_y1 + round($ttf_width / 2); + } + + $this->write_svg_text($this->graph_image, $font_size, $rotation, $text_x, $text_y, $font_color, $this->graph_font, $text_string, "CENTER"); + } + } + protected function write_svg_text(&$img_object, $font_size, $rotation, $text_x, $text_y, $color, $font, $string, $orientation = "LEFT") + { + $font_size += 1.5; + $baseline = "middle"; + + if($rotation != 0) + { + $text_y = (0 - ($text_y / 2)); + $text_x = $text_y + 5; + } + + switch($orientation) + { + case "CENTER": + $text_anchor = "middle"; + $baseline = "text-before-edge"; + break; + case "RIGHT": + $text_anchor = "end"; + break; + case "LEFT": + default: + $text_anchor = "start"; + break; + } + + // TODO: Implement $font through style="font-family: $font;" + $img_object .= "<text x=\"" . round($text_x) . "\" y=\"" . round($text_y) . "\" fill=\"" . $color . "\" transform=\"rotate(" . (360 - $rotation) . ", " . $rotation . ", 0)\" font-size=\"" . $font_size . "\" text-anchor=\"" . $text_anchor . "\" dominant-baseline=\"" . $baseline . "\">" . $string . "</text>\n"; + } + protected function draw_rectangle(&$img_object, $x1, $y1, $width, $height, $background_color) + { + if($this->graph_renderer == "PNG") + { + imagefilledrectangle($img_object, $x1, $y1, $width, $height, $background_color); + } + else if($this->graph_renderer == "SVG") + { + $width = $width - $x1; + $height = $height - $y1; + + if($width < 0) + { + $x1 += $width; + } + if($height < 0) + { + $y1 += $height; + } + + $img_object .= "<rect x=\"" . round($x1) . "\" y=\"" . round($y1) . "\" width=\"" . abs(round($width)) . "\" height=\"" . abs(round($height)) . "\" fill=\"" . $background_color . "\" />\n"; + } + } + protected function draw_rectangle_border(&$img_object, $x1, $y1, $width, $height, $color) + { + if($this->graph_renderer == "PNG") + { + imagerectangle($img_object, $x1, $y1, $width, $height, $color); + } + else if($this->graph_renderer == "SVG") + { + $img_object .= "<rect x=\"" . round($x1) . "\" y=\"" . round($y1) . "\" width=\"" . round($width - $x1) . "\" height=\"" . round($height - $y1) . "\" fill=\"transparent\" stroke=\"" . $color . "\" stroke-width=\"1px\" />\n"; + } + } + protected function draw_line(&$img_object, $left_start, $top_start, $from_left, $from_top, $color, $line_width = 1) + { + if($this->graph_renderer == "PNG") + { + for($i = 0; $i < $line_width; $i++) + { + imageline($img_object, $left_start, $top_start + $i, $from_left, $from_top + $i, $color); + } + } + else if($this->graph_renderer == "SVG") + { + for($i = 0; $i < $line_width; $i++) + { + $img_object .= "<line x1=\"" . round($left_start) . "\" y1=\"" . round($top_start + $i) . "\" x2=\"" . round($from_left) . "\" y2=\"" . round($from_top + $i) . "\" stroke=\"" . $color . "\" stroke-width=\"1px\" />\n"; + } + } + } + protected function image_copy_merge(&$img_object, $source_img_object, $to_x, $to_y, $source_x = 0, $source_y = 0, $width = -1, $height = -1) + { + if($this->graph_renderer == "PNG") + { + if($width == -1) + { + $width = imagesx($source_img_object); + } + if($height == -1) + { + $height = imagesy($source_img_object); + } + + imagecopy($img_object, $source_img_object, $to_x, $to_y, $source_x, $source_y, $width, $height); + } + } + protected function text_string_dimensions($string, $font, $size, $Big = false) + { + if($this->graph_renderer == "PNG" && function_exists("imagettfbbox")) + { + $box_array = imagettfbbox($size, 0, $font, $string); + $box_width = $box_array[4] - $box_array[6]; + + if($Big) + { + $box_array = imagettfbbox($size, 0, $font, "AZ@![]()@|_"); + } + $box_height = $box_array[1] - $box_array[7]; + } + else if($this->graph_renderer == "SVG") + { + // TODO: This needs to be implemented + $box_height = 0; + $box_width = 0; + } + + // Width x Height + return array($box_width, $box_height); + } +} + +?> diff --git a/pts-core/objects/pts_Graph/pts_LineGraph.php b/pts-core/objects/pts_Graph/pts_LineGraph.php new file mode 100644 index 0000000..140b693 --- /dev/null +++ b/pts-core/objects/pts_Graph/pts_LineGraph.php @@ -0,0 +1,146 @@ +<?php + +/* + Phoronix Test Suite + URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/ + Copyright (C) 2008, Phoronix Media + Copyright (C) 2008, Michael Larabel + pts_LineGraph.php: The line graph object that extends pts_Graph.php. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +class pts_LineGraph extends pts_CustomGraph +{ + var $identifier_width = -1; + var $minimum_identifier_font = 7; + + public function __construct($title, $sub_title, $y_axis_title) + { + parent::__construct($title, $sub_title, $y_axis_title); + $this->graph_type = "LINE_GRAPH"; + $this->graph_show_key = true; + $this->graph_background_lines = true; + } + protected function render_graph_pre_init() + { + // Do some common work to this object + $identifier_count = count($this->graph_identifiers) + 1; + $this->identifier_width = ($this->graph_left_end - $this->graph_left_start) / $identifier_count; + + $longest_string = $this->find_longest_string($this->graph_identifiers); + $width = $this->identifier_width - 2; + $this->graph_font_size_identifiers = $this->text_size_bounds($longest_string, $this->graph_font, $this->graph_font_size_identifiers, $this->minimum_identifier_font, $width); + + if($this->graph_font_size_identifiers == $this->minimum_identifier_font) + { + $this->update_graph_dimensions($this->graph_attr_width, $this->graph_attr_height + $this->text_string_width($longest_string, $this->graph_font, 9)); + } + } + protected function render_graph_identifiers() + { + $px_from_top_start = $this->graph_top_end - 5; + $px_from_top_end = $this->graph_top_end + 5; + + for($i = 0; $i < count($this->graph_identifiers); $i++) + { + $px_from_left = $this->graph_left_start + ($this->identifier_width * ($i + 1)); + + $this->draw_line($this->graph_image, $px_from_left, $px_from_top_start, $px_from_left, $px_from_top_end, $this->graph_color_notches); + + if($this->graph_font_size_identifiers == $this->minimum_identifier_font) + { + $this->write_text_left($this->graph_identifiers[$i], 9, $this->graph_color_headers, $px_from_left, $px_from_top_end + 2, $px_from_left, $px_from_top_end + 2, true); + } + else + { + $this->write_text_center($this->graph_identifiers[$i], $this->graph_font_size_identifiers, $this->graph_color_headers, $px_from_left, $px_from_top_end + 2, $px_from_left, $px_from_top_end + 2); + } + } + } + protected function renderGraphLines() + { + for($i_o = 0; $i_o < count($this->graph_data); $i_o++) + { + $previous_placement = -1; + $previous_offset = -1; + $paint_color = $this->next_paint_color(); + + $point_counter = count($this->graph_data[$i_o]); + for($i = 0; $i < $point_counter; $i++) + { + $value = $this->graph_data[$i_o][$i]; + $value_plot_top = $this->graph_top_end + 1 - round(($value / $this->graph_maximum_value) * ($this->graph_top_end - $this->graph_top_start)); + $px_from_left = $this->graph_left_start + ($this->identifier_width * ($i + 1)); + + if($px_from_left > $this->graph_left_end) + { + $px_from_left = $this->graph_left_end - 1; + } + + if($value_plot_top >= $this->graph_top_end) + { + $value_plot_top = $this->graph_top_end - 1; + } + + if($previous_placement != -1 && $previous_offset != -1) + { + $this->draw_line($this->graph_image, $previous_offset, $previous_placement, $px_from_left, $value_plot_top, $paint_color, 2); + } + + if($i == 0) + { + $this->draw_line($this->graph_image, $this->graph_left_start + 1, $value_plot_top, $px_from_left, $value_plot_top, $paint_color, 2); + } + else if($i == ($point_counter - 1)) + { + $this->draw_line($this->graph_image, $px_from_left, $value_plot_top, $this->graph_left_end - 1, $value_plot_top, $paint_color, 2); + } + + $previous_placement = $value_plot_top; + $previous_offset = $px_from_left; + } + + if($point_counter < 10) + { + $previous_placement = -1; + $previous_offset = -1; + + for($i = 0; $i < $point_counter; $i++) + { + $value = $this->graph_data[$i_o][$i]; + $value_plot_top = $this->graph_top_end + 1 - round(($value / $this->graph_maximum_value) * ($this->graph_top_end - $this->graph_top_start)); + $px_from_left = $this->graph_left_start + ($this->identifier_width * ($i + 1)); + + $this->render_graph_pointer($px_from_left, $value_plot_top); + + $previous_placement = $value_plot_top; + $previous_offset = $px_from_left; + } + } + } + } + protected function render_graph_result() + { + $this->renderGraphLines(); + } + protected function render_graph_pointer($x, $y) + { + $this->draw_line($this->graph_image, $x - 5, $y - 5, $x + 5, $y + 5, $this->graph_color_notches); + $this->draw_line($this->graph_image, $x + 5, $y - 5, $x - 5, $y + 5, $this->graph_color_notches); + $this->draw_rectangle($this->graph_image, $x - 2, $y - 2, $x + 3, $y + 3, $this->graph_color_notches); + } +} + +?> diff --git a/pts-core/objects/pts_Graph/pts_MultiPassFailGraph.php b/pts-core/objects/pts_Graph/pts_MultiPassFailGraph.php new file mode 100644 index 0000000..bc7109d --- /dev/null +++ b/pts-core/objects/pts_Graph/pts_MultiPassFailGraph.php @@ -0,0 +1,127 @@ +<?php + +/* + Phoronix Test Suite + URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/ + Copyright (C) 2008, Phoronix Media + Copyright (C) 2008, Michael Larabel + pts_PassFailGraph.php: An abstract graph object extending pts_Graph for showing results in a pass/fail scenario. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +class pts_MultiPassFailGraph extends pts_CustomGraph +{ + public function __construct($title, $sub_title, $y_axis_title) + { + $this->graph_y_title_hide = true; + parent::__construct($title, $sub_title, $y_axis_title); + $this->graph_type = "MULTI_PASS_FAIL"; + $this->graph_value_type = "ABSTRACT"; + $this->graph_hide_identifiers = true; + } + protected function render_graph_passfail() + { + $identifier_count = count($this->graph_identifiers); + $vertical_border = 20; + $horizontal_border = 14; + $heading_height = 24; + $graph_width = $this->graph_left_end - $this->graph_left_start - ($horizontal_border * 2); + $graph_height = $this->graph_top_end - $this->graph_top_start - ($vertical_border * 2) - $heading_height; + $line_height = floor($graph_height / $identifier_count); + + $pass_color = $this->next_paint_color(); + $fail_color = $this->next_paint_color(); + + $main_width = floor($graph_width * .24); + $main_font_size = $this->graph_font_size_bars; + $main_greatest_length = $this->find_longest_string($this->graph_identifiers); + + $width = $main_width - 8; + $height = $line_height - 4; + $main_font_size = $this->text_size_bounds($main_greatest_length, $this->graph_font, $main_font_size, 4, $width, $height); + + if(($new_size = $this->text_string_width($main_greatest_length, $this->graph_font, $main_font_size)) < ($main_width - 12)) + { + $main_width = $new_size + 10; + } + + $identifiers_total_width = $graph_width - $main_width - 2; + + $headings = explode(",", $this->graph_y_title); + $identifiers_width = floor($identifiers_total_width / count($headings)); + $headings_font_size = $this->graph_font_size_bars; + while(($this->text_string_width($this->find_longest_string($headings), $this->graph_font, $headings_font_size) > ($identifiers_width - 2)) || $this->text_string_height($this->graph_maximum_value, $this->graph_font, $headings_font_size) > ($line_height - 4)) + { + $headings_font_size -= 0.5; + } + + for($j = 0; $j < count($this->graph_data[0]); $j++) + { + $results = array_reverse(explode(",", $this->graph_data[0][$j])); + $line_ttf_height = $this->text_string_height("AZ@![]()@|_", $this->graph_font, $this->graph_font_size_bars); + for($i = 0; $i < count($headings) && $i < count($results); $i++) + { + if($results[$i] == "PASS") + { + $paint_color = $pass_color; + } + else + { + $paint_color = $fail_color; + } + + $this_bottom_end = $this->graph_top_start + $vertical_border + (($j + 1) * $line_height) + $heading_height + 1; + + if($this_bottom_end >= $this->graph_top_end - $vertical_border) + { + $this_bottom_end = $this->graph_top_end - $vertical_border - 1; + } + else if($j == (count($this->graph_data[0]) - 1) && $this_bottom_end < $this->graph_top_end - $vertical_border) + { + $this_bottom_end = $this->graph_top_end - $vertical_border - 1; + } + + $this->draw_rectangle($this->graph_image, $this->graph_left_end - $horizontal_border - ($i * $identifiers_width), $this->graph_top_start + $vertical_border + ($j * $line_height) + $heading_height, $this->graph_left_end - $horizontal_border - (($i + 1) * $identifiers_width), $this_bottom_end, $paint_color); + $this->write_text_center($results[$i], $this->graph_font_size_bars, $this->graph_color_body_text, $this->graph_left_end - $horizontal_border - ($i * $identifiers_width) - $identifiers_width, $this->graph_top_start + $vertical_border + ($j * $line_height) + $heading_height + ($line_height / 2) - ($line_ttf_height / 2), $this->graph_left_end - $horizontal_border - ($i * $identifiers_width), $this->graph_top_start + $vertical_border + ($j * $line_height) + $heading_height + ($line_height / 2) - ($line_ttf_height / 2)); + } + } + + $headings = array_reverse($headings); + $line_ttf_height = $this->text_string_height("AZ@![]()@|_", $this->graph_font, $headings_font_size); + for($i = 0; $i < count($headings); $i++) + { + $this->draw_line($this->graph_image, $this->graph_left_end - $horizontal_border - (($i + 1) * $identifiers_width), $this->graph_top_start + $vertical_border, $this->graph_left_end - $horizontal_border - (($i + 1) * $identifiers_width), $this->graph_top_end - $vertical_border, $this->graph_color_body_light); + $this->write_text_center($headings[$i], $headings_font_size, $this->graph_color_headers, $this->graph_left_end - $horizontal_border - ($i * $identifiers_width) - $identifiers_width, $this->graph_top_start + $vertical_border + ($heading_height / 2) - ($line_ttf_height / 2), $this->graph_left_end - $horizontal_border - ($i * $identifiers_width), $this->graph_top_start + $vertical_border + ($heading_height / 2) - ($line_ttf_height / 2)); + } + + $line_ttf_height = $this->text_string_height("AZ@![]()@|_", $this->graph_font, $main_font_size); + for($i = 0; $i < count($this->graph_identifiers); $i++) + { + $this->draw_line($this->graph_image, $this->graph_left_start + $horizontal_border, $this->graph_top_start + $vertical_border + ($i * $line_height) + $heading_height, $this->graph_left_end - $horizontal_border, $this->graph_top_start + $vertical_border + ($i * $line_height) + $heading_height, $this->graph_color_body_light); + $this->write_text_right($this->graph_identifiers[$i], $main_font_size, $this->graph_color_headers, $this->graph_left_start + $horizontal_border + $main_width, $this->graph_top_start + $vertical_border + ($i * $line_height) + $heading_height + ($line_height / 2) - 2, $this->graph_left_start + $horizontal_border + $main_width, $this->graph_top_start + $vertical_border + ($i * $line_height) + $heading_height + ($line_height / 2) - 2, false); + } + + $this->draw_line($this->graph_image, $this->graph_left_start + $horizontal_border, $this->graph_top_start + $vertical_border, $this->graph_left_end - $horizontal_border, $this->graph_top_start + $vertical_border, $this->graph_color_body_light); + $this->draw_line($this->graph_image, $this->graph_left_start + $horizontal_border, $this->graph_top_start + $vertical_border, $this->graph_left_start + $horizontal_border, $this->graph_top_end - $vertical_border, $this->graph_color_body_light); + $this->draw_line($this->graph_image, $this->graph_left_end - $horizontal_border, $this->graph_top_start + $vertical_border, $this->graph_left_end - $horizontal_border, $this->graph_top_end - $vertical_border, $this->graph_color_body_light); + $this->draw_line($this->graph_image, $this->graph_left_start + $horizontal_border, $this->graph_top_end - $vertical_border, $this->graph_left_end - $horizontal_border, $this->graph_top_end - $vertical_border, $this->graph_color_body_light); + } + protected function render_graph_result() + { + $this->render_graph_passfail(); + } +} + +?> diff --git a/pts-core/objects/pts_Graph/pts_PassFailGraph.php b/pts-core/objects/pts_Graph/pts_PassFailGraph.php new file mode 100644 index 0000000..cb466fd --- /dev/null +++ b/pts-core/objects/pts_Graph/pts_PassFailGraph.php @@ -0,0 +1,99 @@ +<?php + +/* + Phoronix Test Suite + URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/ + Copyright (C) 2008, Phoronix Media + Copyright (C) 2008, Michael Larabel + pts_PassFailGraph.php: An abstract graph object extending pts_Graph for showing results in a pass/fail scenario. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +class pts_PassFailGraph extends pts_CustomGraph +{ + public function __construct($title, $sub_title, $y_axis_title) + { + parent::__construct($title, $sub_title, $y_axis_title); + $this->graph_type = "PASS_FAIL"; + $this->graph_value_type = "ABSTRACT"; + $this->graph_hide_identifiers = true; + $this->graph_data_title = array("PASSED", "FAILED"); + } + protected function render_graph_passfail() + { + $identifier_count = count($this->graph_identifiers); + $vertical_border = 18; + $horizontal_border = 10; + $spacing = 8; + $columns = 1; + $graph_width = $this->graph_left_end - $this->graph_left_start - ($horizontal_border * 2); + $graph_height = $this->graph_top_end - $this->graph_top_start - ($vertical_border * 1.5); + $font_size = $this->graph_font_size_bars * 1.5; + + $pass_color = $this->next_paint_color(); + $fail_color = $this->next_paint_color(); + + for($i = 2; $i <= sqrt($identifier_count); $i++) + { + if(intval($identifier_count / $i) == ($identifier_count / $i)) + { + $columns = $i; + } + } + + $identifiers_per_column = $identifier_count / $columns; + $identifier_height = floor(($graph_height - (($identifiers_per_column - 1) * $spacing)) / $identifiers_per_column); + $identifier_width = floor(($graph_width - (($columns - 1) * $spacing)) / $columns); + + $width = $identifier_width - 8; + $height = $line_height - 4; + $main_font_size = $this->text_size_bounds($this->graph_maximum_value, $this->graph_font, $font_size, 4, $width, $height); + + for($c = 0; $c < $columns; $c++) + { + for($i = 0; $i < $identifiers_per_column; $i++) + { + $element_i = ($c * $identifiers_per_column) + $i; + $this_identifier = $this->graph_identifiers[$element_i]; + $this_value = $this->graph_data[0][$element_i]; + + $this_horizontal_start = $this->graph_left_start + $horizontal_border + ($c * ($identifier_width + $spacing)); + $this_horizontal_end = $this->graph_left_start + $horizontal_border + ($c * ($identifier_width + $spacing)) + $identifier_width; + $this_vertical_start = $this->graph_top_start + $vertical_border + ($i * ($identifier_height + $spacing)); + $this_vertical_end = $this->graph_top_start + $vertical_border + ($i * ($identifier_height + $spacing)) + $identifier_height; + + if($this_value == "PASS") + { + $paint_color = $pass_color; + } + else + { + $paint_color = $fail_color; + } + + $this->draw_rectangle_border($this->graph_image, $this_horizontal_start, $this_vertical_start, $this_horizontal_end, $this_vertical_end, $this->graph_color_body_light); + $this->draw_rectangle($this->graph_image, $this_horizontal_start + 1, $this_vertical_start + 1, $this_horizontal_end - 1, $this_vertical_end - 1, $paint_color); + + $this->write_text_center($this_identifier, $font_size, $this->graph_color_body_text, $this_horizontal_start, $this_vertical_start + (($this_vertical_end - $this_vertical_start) / 2) - ($this->text_string_height($this_identifier, $this->graph_font, $font_size) / 2), $this_horizontal_end, $this_vertical_start + (($this_vertical_end - $this_vertical_start) / 2) - ($this->text_string_height($this_identifier, $this->graph_font, $font_size) / 2)); + } + } + } + protected function render_graph_result() + { + $this->render_graph_passfail(); + } +} + +?> diff --git a/pts-core/objects/tandem_Xml/pts_test_tandem_XmlReader.php b/pts-core/objects/tandem_Xml/pts_test_tandem_XmlReader.php new file mode 100644 index 0000000..096b356 --- /dev/null +++ b/pts-core/objects/tandem_Xml/pts_test_tandem_XmlReader.php @@ -0,0 +1,53 @@ +<?php + +/* + Phoronix Test Suite + URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/ + Copyright (C) 2008, Phoronix Media + Copyright (C) 2004-2008, Michael Larabel + pts_test_tandem_XmlReader.php: The XML reading object for the Phoronix Test Suite with optimizations for handling test profiles + + Additional Notes: A very simple XML parser with a few extras... Does not currently support attributes on tags, etc. + A work in progress. This was originally designed for just some select needs in the past. No XML validation is done with this parser, etc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +class pts_test_tandem_XmlReader extends tandem_XmlReader +{ + function handleXmlZeroTagFallback($xml_tag) + { + // Cascading Test Profiles for finding a tag within an XML file being extended by another XML file + $fallback_value = $this->tag_fallback_value; + + if(!empty($this->xml_file_name)) + { + $test_extends = $this->getValue(P_TEST_CTPEXTENDS, null, null, true, true); + + if(!empty($test_extends) && pts_is_test($test_extends)) + { + $test_below_parser = new pts_test_tandem_XmlReader(pts_location_test($test_extends)); + $test_below_tag = $test_below_parser->getXMLValue($xml_tag); + + if(!empty($test_below_tag)) + { + $fallback_value = $test_below_tag; + } + } + } + + return $fallback_value; + } +} +?> diff --git a/pts-core/objects/tandem_Xml/tandem_XmlReader.php b/pts-core/objects/tandem_Xml/tandem_XmlReader.php new file mode 100644 index 0000000..7bc6707 --- /dev/null +++ b/pts-core/objects/tandem_Xml/tandem_XmlReader.php @@ -0,0 +1,309 @@ +<?php + +/* + Phoronix Test Suite + URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/ + Copyright (C) 2008, Phoronix Media + Copyright (C) 2004-2008, Michael Larabel + tandem_XmlReader.php: The XML reading object for the Phoronix Test Suite. + + Additional Notes: A very simple XML parser with a few extras... Does not currently support attributes on tags, etc. + A work in progress. This was originally designed for just some select needs in the past. No XML validation is done with this parser, etc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +class tandem_XmlReader +{ + var $xml_data = ""; // XML contents + var $xml_file_time = null; // File modification time + var $xml_file_name = null; // File name + + var $xml_cache_file = false; // Cache the entire XML file being parsed? + var $xml_cache_tags = true; // Cache the tags that are being called? + + var $tag_fallback_value = null; // Fallback value if tag is not present + + static $tag_cache = null; // The cache for the tag cache + static $file_cache = null; // The cache for the file cache + + function __construct($read_xml, $cache_support = true) + { + if(is_readable($read_xml)) + { + if($cache_support) + { + $this->xml_cache_file = false; + $this->xml_cache_tags = false; + } + + // If you are going to be banging XML files hard through the course of the script, you will want to flush the PHP file cache + // clearstatcache(); + + $this->xml_file_time = filemtime($read_xml); + $this->xml_file_name = $read_xml; + + if($this->xml_cache_file && isset(self::$file_cache[$this->xml_file_name][$this->xml_file_time])) + { + $this->xml_data = self::$file_cache[$this->xml_file_name][$this->xml_file_time]; + } + + if(empty($this->xml_data)) + { + $this->xml_data = file_get_contents($read_xml); + + if($this->xml_cache_file) + { + self::$file_cache[$this->xml_file_name][$this->xml_file_time] = $this->xml_data; + } + } + } + else + { + $this->xml_cache_file = false; + $this->xml_cache_tags = false; + $this->xml_data = $read_xml; + } + } + function getStatement($statement) + { + return $this->listStatements(true, $statement); + } + function listStatements($perform_search = false, $search_query = "") + { + $return_r = array(); + $comment_statements = $this->parseLineCommentsFromFile(); + + foreach($comment_statements as $statement) + { + $name = substr($statement, 0, strpos($statement, ":")); + $name = trim(strstr($name, " ")); + + if($perform_search && !empty($search_query)) + { + if($name == $search_query) + { + $value = trim(substr(strstr($statement, ":"), 1)); + array_push($return_r, $value); + } + } + else + { + array_push($return_r, $name); + } + } + + return $return_r; + } + function getXMLValue($xml_tag) + { + return $this->getValue($xml_tag); + } + function isDefined($xml_tag) + { + return $this->getValue($xml_tag) != null; + } + function getValue($xml_path, $xml_tag = null, $xml_match = null, $cache_tag = true, $is_fallback_call = false) + { + if($xml_tag == null) + { + $xml_tag = $xml_path; + } + if($xml_match == null) + { + $xml_match = $this->xml_data; + } + + if($this->xml_cache_tags && $cache_tag && isset(self::$tag_cache[$this->xml_file_name][$this->xml_file_time][$xml_tag])) + { + $xml_match = self::$tag_cache[$this->xml_file_name][$this->xml_file_time][$xml_tag]; + } + else + { + foreach(explode("/", $xml_tag) as $xml_step) + { + $xml_match = $this->parseXMLString($xml_step, $xml_match, false); + + if($xml_match == false) + { + if($is_fallback_call != true) + { + $xml_match = $this->handleXmlZeroTagFallback($xml_path); + } + else + { + $xml_match = $this->tag_fallback_value; + } + } + } + + if($this->xml_cache_tags && $cache_tag) + { + self::$tag_cache[$this->xml_file_name][$this->xml_file_time][$xml_tag] = $xml_match; + } + } + + return $xml_match; + } + function parseXMLString($xml_tag, $to_parse, $multi_search = true) + { + $return = false; + $temp_r = array(); + $temp = $to_parse; + + $open_tag = "<" . $xml_tag . ">"; + $close_tag = "</" . $xml_tag . ">"; + $open_tag_length = strlen($open_tag); + $close_tag_length = strlen($close_tag); + + do + { + $return = null; + + if(($start = strpos($temp, $open_tag)) !== false) + { + $temp = substr($temp, $start + $open_tag_length); + + if(($end = strpos($temp, $close_tag)) !== false) + { + $return = substr($temp, 0, $end); + $temp = substr($temp, strlen($return) + $close_tag_length); + } + } + + if($return != null) + { + array_push($temp_r, $return); + } + } + while($return != null && $multi_search); + + if(count($temp_r) > 0) + { + $return = $temp_r; + + if($multi_search == false) + { + $return = $return[0]; + } + } + + return $return; + } + function parseLineCommentsFromFile($read_from = null) + { + if(empty($read_from)) + { + $read_from = $this->xml_data; + } + + $return_r = array(); + $temp = $read_from; + + do + { + $return = null; + + if(($start = strpos($temp, "<!--")) !== false) + { + $temp = substr($temp, $start + 4); + + if(($end = strpos($temp, "-->")) !== false) + { + $return = substr($temp, 0, $end); + $temp = substr($temp, strlen($return) + 3); + } + } + + if($return != null) + { + array_push($return_r, $return); + } + } + while($return != null); + + return $return_r; + } + function handleXmlZeroTagFallback($xml_tag) + { + return $this->tag_fallback_value; + } + function getXMLValues($xml_tag) + { + return $this->getXMLArrayValues($xml_tag); + } + function getXMLArrayValues($xml_tag) + { + return $this->getArrayValues($xml_tag, $this->xml_data); + } + function getArrayValues($xml_tag, $xml_match) + { + $xml_steps = explode("/", $xml_tag); + $xml_steps_count = count($xml_steps); + $this_xml = $xml_match; + + for($i = 0; $i < ($xml_steps_count - 2); $i++) + { + $this_xml = $this->getValue($xml_tag, $xml_steps[$i], $this_xml, false); + } + + $xml_matches = $this->parseXMLString($xml_steps[($xml_steps_count - 2)], $this_xml); + $xml_matches_count = count($xml_matches); + + $return_r = array(); + $extraction_tags = explode(",", end($xml_steps)); + $extraction_tags_count = count($extraction_tags); + + for($i = 0; $i < $xml_matches_count; $i++) + { + if($extraction_tags_count == 1) + { + $this_item = $this->getValue($xml_tag, $extraction_tags[0], $xml_matches[$i], false); + array_push($return_r, $this_item); + } + else + { + if($i == 0) + { + foreach($extraction_tags as $extract) + { + $return_r[$extract] = array(); + } + } + + foreach($extraction_tags as $extract) + { + $this_item = $this->getValue($xml_tag, $extract, $xml_matches[$i], false); + array_push($return_r[$extract], $this_item); + } + } + } + return $return_r; + } + function setFileCaching($do_cache) + { + $this->xml_cache_file = ($do_cache == true); + } + function setTagCaching($do_cache) + { + $this->xml_cache_tags = ($do_cache == true); + } + function setCaching($do_cache) + { + $this->setFileCaching($do_cache); + $this->setTagCaching($do_cache); + } +} + +?> diff --git a/pts-core/objects/tandem_Xml/tandem_XmlWriter.php b/pts-core/objects/tandem_Xml/tandem_XmlWriter.php new file mode 100644 index 0000000..78a8c5e --- /dev/null +++ b/pts-core/objects/tandem_Xml/tandem_XmlWriter.php @@ -0,0 +1,199 @@ +<?php + +/* + Phoronix Test Suite + URLs: http://www.phoronix.com, http://www.phoronix-test-suite.com/ + Copyright (C) 2008, Phoronix Media + Copyright (C) 2004-2008, Michael Larabel + tandem_XmlReader.php: The XML writing object for the Phoronix Test Suite. + + Additional Notes: A very simple XML writer with a few extras... Does not support attributes on tags, etc. + A work in progress. This was originally designed for just some select needs in the past. It does support linking to an XSL as + well as whether to format the XML or not, etc. Also provides a MD5 checksum of the XML body. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +class tandem_XmlWriter +{ + var $xml_objects = array(); + var $xml_string_paths = array(); + var $xml_statements = array(); + + var $xml_checksum = false; + var $format_xml = true; + var $xsl_binding = null; + + function __construct($nice_formatting = true) + { + $this->format_xml = ($nice_formatting == true); + } + function setXslBinding($url) + { + $this->xsl_binding = $url; + } + function writeXmlCheckSum() + { + $this->xml_checksum = true; + } + function addXmlObject($xml_location, $unique_identifier = 0, $xml_value = "", $std_step = null, $step_id = null) + { + $xml_array = array(); + $alt_step = -1; + $steps = 0; + + if($std_step == null) + { + $std_step = 2; + } + if($step_id == null) + { + $step_id = $unique_identifier; + } + + if(array_search($unique_identifier . "," . $xml_location, $this->xml_string_paths) !== false) + { + $alt_step = 2; + } + else + { + array_push($this->xml_string_paths, $unique_identifier . "," . $xml_location); + } + + $xml_steps = explode('/', $xml_location); + foreach(array_reverse($xml_steps) as $current_tag) + { + $steps++; + + if(empty($xml_array)) + { + $xml_array = $xml_value; + } + if(!empty($current_tag)) + { + $xml_array = array("$current_tag" => $xml_array); + } + + if($steps == $std_step) + { + $xml_array = array("id_" . $unique_identifier => $xml_array); + } + if($steps == $alt_step) + { + $xml_array = array("id_" . $step_id => $xml_array); + } + } + + $this->xml_objects = array_merge_recursive($this->xml_objects, $xml_array); + } + function addStatement($name, $value) + { + array_push($this->xml_statements, trim($name . ": " . $value)); + } + function getXMLStatements() + { + $return_string = ""; + $statements_to_print = array_reverse($this->xml_statements); + + foreach($statements_to_print as $statement) + { + $return_string .= "<!-- " . $statement . " -->\n"; + } + + return $return_string; + } + function getXML() + { + $formatted_xml = $this->getXMLBelow($this->xml_objects, 0); + + $this->addStatement("Generated", date("Y-m-d H:i:s")); + + if($this->xml_checksum) + { + $this->addStatement("Checksum", md5($formatted_xml)); + } + + return "<?xml version=\"1.0\"?>\n" . $this->getXSL() . $this->getXMLStatements() . $formatted_xml; + } + function getXSL() + { + $str = ""; + + if($this->xsl_binding != null) + { + $str = "<?xml-stylesheet type=\"text/xsl\" href=\"" . $this->xsl_binding . "\" ?>\n"; + } + + return $str; + } + function getJustXML() + { + return $this->getXMLBelow($this->xml_objects, 0); + } + function getXMLBelow($statement_name, $times_deep) + { + $formatted_xml = ""; + + foreach($statement_name as $key => $value) + { + if(!is_array($value)) + { + $formatted_xml .= $this->getXMLTabs($times_deep) . "<" . $key . ">" . $value . "</" . $key . ">" . $this->getXMLBreaks(); + } + else + { + if(substr($key, 0, 3) === "id_") + { + $formatted_xml .= $this->getXMLBelow($value, $times_deep); + } + else + { + $formatted_xml .= $this->getXMLTabs($times_deep) . "<" . $key . ">" . $this->getXMLBreaks(); + $formatted_xml .= $this->getXMLBelow($value, $times_deep + 1); + $formatted_xml .= $this->getXMLTabs($times_deep) . "</" . $key . ">" . $this->getXMLBreaks(); + } + } + } + + return $formatted_xml; + } + function getXMLTabs($times_deep) + { + $format = ""; + + if($this->format_xml) + { + $format = str_repeat("\t", $times_deep); + } + + return $format; + } + function getXMLBreaks() + { + $format = ""; + + if($this->format_xml) + { + $format = "\n"; + } + + return $format; + } + function debugDumpArray() + { + return $this->xml_objects; + } +} + +?> |