X-Git-Url: http://git.pk910.de/?p=phpgitweb.git;a=blobdiff_plain;f=htdocs%2Flib%2Fgraph.class.php;fp=htdocs%2Flib%2Fgraph.class.php;h=5cf843eafce637a484dc1d41398722ff3180e504;hp=0000000000000000000000000000000000000000;hb=0a6d29345b57ef71b076003e18d13efd3478764c;hpb=c20b2789b4f1c2da70f33cf2d1e78f55478a6e19 diff --git a/htdocs/lib/graph.class.php b/htdocs/lib/graph.class.php new file mode 100644 index 0000000..5cf843e --- /dev/null +++ b/htdocs/lib/graph.class.php @@ -0,0 +1,389 @@ +. + */ + +class graph_data_generator { + const DOT_TYPE_NORMAL = 'a'; + const DOT_TYPE_MERGE = 'b'; + const DOT_TYPE_INIT = 'c'; + + private $data = array(); + private $graph = array(); + private $max_branches, $brach_id = 1, $branch_id = 1; + + public function __construct() { + $this->max_branches = 10; + $this->data['branches'] = array(); + $this->data['ubranches'] = array(); + } + + public function add_branch($first_id, $name) { + $existing = false; + foreach($this->data['branches'] as &$branch) { + if($branch['next'] == $first_id) { + $existing = true; + $branch['name'][] = $name; + break; + } + } + unset($branch); + if($existing) + continue; + $this->data['branches'][count($this->data['branches'])] = array( + "id" => $this->brach_id++, + "uid" => $this->branch_uid++, + "active" => true, + "sticky" => true, + "name" => array($name), + "next" => $first_id, + "pre_merge" => false + ); + } + + public function parse($commits) { + $brach_id = $this->brach_id; + $branch_uid = $this->branch_id; + $first_commit = (count($this->data['branches']) == 0 ? true : false); + foreach($commits as $commit) { + //get current branch + $commit['merge'] = array(); + $commit['dot_type'] = self::DOT_TYPE_NORMAL; + if($first_commit) { + $first_commit = false; + $this->data['branches'][0] = array(); + $branch = &$this->data['branches'][0]; + $branch['id'] = $brach_id++; + $branch['uid'] = $branch_uid++; + $branch['active'] = true; + } else { + $first = true; + foreach($this->data['branches'] as $id => &$cbranch) { + if($cbranch['next'] == $commit['id']) { + if($first && !$cbranch['pre_merge']) { + $branch = &$this->data['branches'][$id]; + $first = false; + } + } + } + foreach($this->data['branches'] as $id => &$cbranch) { + if($cbranch['next'] == $commit['id']) { + if($first) { + $branch = &$this->data['branches'][$id]; + $first = false; + } else if($cbranch['id'] == $branch['id']) { + } else { + $commit['merge'][] = array("point" => $cbranch['id'], "start" => true, "end" => false); + $cbranch['active'] = false; + if($cbranch['pre_merge']) { + $cbranch['pre_merge_start'] = true; + $cbranch['pre_merge_id'] = $branch['id']; + $this->data['ubranches'][$cbranch['uid']] = $this->data['branches'][$cbranch['id']-1]; + } + } + } + } + unset($cbranch); + if($first) { + $this->data['branches'][count($this->data['branches'])] = array(); + $branch = &$this->data['branches'][count($this->data['branches'])-1]; + $branch['id'] = $brach_id++; + $branch['uid'] = $branch_uid++; + $branch['active'] = true; + $branch['pre_merge'] = false; + + } + } + + if(array_key_exists('parent', $commit) && count($commit['parent']) > 1) { + //merge(s) + for($j = 1; $j < count($commit['parent']); $j++) { + $add = true; + foreach($this->data['branches'] as $cbranch) { + if($cbranch['next'] == $commit['parent'][$j]) { + $add = false; + break; + } + } + if($add) { + $cadd = true; + foreach($this->data['branches'] as $bid => &$cbranch) { + if(!$cbranch['active']) { + $cadd = false; + break; + } + } + if($cadd) { + $this->data['branches'][count($this->data['branches'])] = array(); + $cbranch = &$this->data['branches'][count($this->data['branches'])-1]; + $cbranch['id'] = $brach_id++; + } + $cbranch['uid'] = $branch_uid++; + $cbranch['active'] = true; + $cbranch['pre_merge'] = true; + $cbranch['next'] = $commit['parent'][$j]; + } + $commit['merge'][] = array("point" => $cbranch['id'], "start" => false, "end" => $add); + $commit['dot_type'] = self::DOT_TYPE_MERGE; + $this->data['ubranches'][$cbranch['uid']] = $this->data['branches'][$cbranch['id']-1]; + unset($cbranch); + } + } else if(!array_key_exists('parent', $commit) || count($commit['parent']) == 0) { + $branch['active'] = false; + $commit['dot_type'] = self::DOT_TYPE_INIT; + } + $branch['next'] = (array_key_exists('parent', $commit) ? $commit['parent'][0] : null); + $branch['pre_merge'] = false; + $this->data['ubranches'][$branch['uid']] = $this->data['branches'][$branch['id']-1]; + + $commit['dot'] = $branch['id']; + + foreach($this->data['branches'] as $id => $cbranch) { + $commit['branches'][$id] = $cbranch; + } + + $this->graph[$commit['id']] = $this->graph_data($commit); + //echo$commit['id']." ".$this->get_graph($commit['id'])."\n"; + } + } + + private function graph_data($commit) { + $data = array(); + $data['d'] = array(); + $data['d']['p'] = $commit['dot']; //dot position + $data['d']['type'] = 'a'; + $data['l'] = array(); //lines + $data['br'] = array(); //branches for color check + foreach($commit['branches'] as $branch) { + if($branch['pre_merge'] || $commit['merge']) { + $data['br'][] = $branch['uid']; + } + if($branch['active']) { + if($commit['dot'] == $branch['id']) continue; + $show = true; + if($commit['merge']) { + foreach($commit['merge'] as $merge) { + if($merge['point'] == $branch['id']) { + $show = false; + break; + } + } + } + if(!$show) continue; + if($branch['id'] > $this->max_branches) continue; + $data['l'][] = $branch['id']; + } + } + $data['m'] = array(); //merges + if($commit['merge']) { + foreach($commit['merge'] as $merge) { + $mergepoint = array(); + $mergepoint['hl'] = array(); + $mergepoint['p'] = $merge['point']; + + if($commit['dot'] <= $this->max_branches) + $mergepoint['dd'] = ($commit['dot'] < $merge['point'] ? 'r' : 'l'); + else + $mergepoint['dd'] = 'n'; + + $mergepoint['ml'] = ($merge['start'] ? 1 : 0) + ($merge['end'] ? 2 : 0); + if($merge['point'] <= $this->max_branches) + $mergepoint['md']=($commit['dot'] < $merge['point'] ? 'l' : 'r'); + else + $mergepoint['md'] = 'n'; + $min = ($commit['dot'] < $merge['point'] ? $commit['dot'] : $merge['point']) + 1; + $max = ($commit['dot'] < $merge['point'] ? $merge['point'] : $commit['dot']); + for($i = $min; $i < $max; $i++) { + if($i > $this->max_branches) continue; + $mergepoint['hl'][] = $i; + } + $data['m'][] = $mergepoint; + } + } + $data['d']['type'] = $commit['dot_type']; + return $data; + } + + public function get_graph($id) { + $graph = $this->graph[$id]; + $data = $graph['d']['p'].$graph['d']['type'].count($this->data['branches']).'('.implode(',', $graph['l']).')'; + $first_merge = true; + foreach($graph['m'] as $merge) { + if(!$first_merge) + $data .= '|'; + $first_merge = false; + $data.=$merge['p'].$merge['dd'].$merge['md'].$merge['ml']; + foreach($merge['hl'] as $hline) + $data.=','.$hline; + } + $graph['cs'] = array(); + foreach($graph['br'] as $buid) { + $branch = $this->data['ubranches'][$buid]; + if($branch['pre_merge'] && $branch['pre_merge_start']) + $graph['cs'][] = $branch['id']."=".$branch['pre_merge_id']; + } + if(count($graph['cs'])) { + $data .= '('.implode(',', $graph['cs']).')'; + } + return $data; + } + +} + +class graph_image_generator { + private $max_branches = 10; + private $image; + private $size = 20; + private $tile_size = 20; + private $colors, $color_swap = array(); + + public function generate($data) { + $data = $this->parse_data($data); + if(!$data) + return; + + $this->colors = array( + NULL, + array(255, 0, 0), + array(array(0, 255, 0), array(0, 192, 0)), + array(0, 0, 255), + array(128, 128, 128), + array(128, 128, 0), + array(0, 128, 128), + array(128, 0, 128) + ); + + $count = $data['count']; + if($count > $this->max_branches) + $count = $this->max_branches; + $this->image = imagecreatetruecolor($count * $this->size, $this->size); + $transparentIndex = imagecolorallocate($this->image, 0xFF, 0xFF, 0xFF); + imagefill($this->image, 0, 0, $transparentIndex); + + $this->apply_data($data); + + imagecolortransparent($this->image, $transparentIndex); + + header('Content-Type: image/png'); + imagepng($this->image); + imagedestroy($this->image); + } + + private function parse_data($data) { + //$data = array(); + if(!preg_match("/^([0-9]+)([abc]{1})([0-9]+)\(([^\)]*)\)([a-z0-9,\|]*)(\(([^\)]*)\)|)/i", $data, $matches)) + return null; + + $data = array(); + $data['dot'] = array(); + $data['dot']['pos'] = $matches[1]; + $data['dot']['type'] = $matches[2]; + $data['count'] = $matches[3]; + + if($matches[4] != '') + $data['l'] = explode(',', $matches[4]); + else + $data['l'] = array(); + + $data['m'] = array(); + if($matches[5] != '') { + foreach(explode('|', $matches[5]) as $m) { + $merge = array(); + + if(!preg_match("/^([0-9]+)([rln]{1})([rln]{1})([0123]{1})(.*)/i", $m, $sm)) + return null; + $merge['hl'] = array(); + $merge['pos'] = $sm[1]; + $merge['dd'] = $sm[2]; + $merge['md'] = $sm[3]; + $merge['ml'] = $sm[4]; + if($sm[5] != '') { + $merge['hl'] = explode(',', $sm[5]); + } + $data['m'][] = $merge; + } + } + if($matches[6] != '' && $matches[7] != '') { + foreach(explode(',', $matches[7]) as $cswap) { + $cswap = explode("=", $cswap); + $this->color_swap[$cswap[0]] = $cswap[1]; + } + } + return $data; + } + + function image_set_color($src, $color) { + imagesavealpha($src, true); + imagealphablending($src, false); + // scan image pixels + for ($x = 0; $x < $this->size; $x++) { + for ($y = 0; $y < $this->size; $y++) { + $src_pix = imagecolorat($src,$x,$y); + $src_pix_array = imagecolorsforindex($src, $src_pix); + + imagesetpixel($src, $x, $y, imagecolorallocatealpha($src, $color[0], $color[1], $color[2], $src_pix_array['alpha'])); + } + } + } + + function overlay_image($name, $left, $color = false) { + $image2 = imagecreatefrompng($name); + + if($color) { + $this->image_set_color($image2, $color); + } + imagecopyresampled($this->image, $image2, $left, 0, 0, 0, $this->size, $this->size, $this->tile_size, $this->tile_size); + } + + function get_color($id, $text = false) { + if(array_key_exists($id, $this->color_swap)) + $id = $this->color_swap[$id]; + $color_array = $this->colors[($id - 1) % count($this->colors)]; + if($text && is_array($color_array[0]) && $color_array[1]) + return $color_array[1]; + return (is_array($color_array[0]) ? $color_array[0] : $color_array); + } + + private function apply_data($data) { + foreach($data['l'] as $l) + $this->overlay_image("img/line.png", ($l-1) * $this->size, $this->get_color($l)); + foreach($data['m'] as $m) { + if($m['dd'] == 'r') + $this->overlay_image("img/dot_merge_right.png", ($data['dot']['pos'] - 1) * $this->size, $this->get_color($m['pos'])); + else if($m['dd'] == 'l') + $this->overlay_image("img/dot_merge_left.png", ($data['dot']['pos'] - 1) * $this->size, $this->get_color($m['pos'])); + if($m['md'] == 'r') + $this->overlay_image("img/".(($m['ml'] & 1) ? "branch" : "merge")."_right.png", ($m['pos'] - 1) * $this->size, $this->get_color($m['pos'])); + else if($m['md'] == 'l') + $this->overlay_image("img/".(($m['ml'] & 1) ? "branch" : "merge")."_left.png", ($m['pos'] - 1) * $this->size, $this->get_color($m['pos'])); + if($m['ml'] == 0) + $this->overlay_image("img/line.png", ($m['pos'] - 1) * $this->size, $this->get_color($m['pos'])); + foreach($m['hl'] as $hl) { + $this->overlay_image("img/line_h.png", ($hl - 1) * $this->size, $this->get_color($m['pos'])); + } + } + if($data['dot']['type'] == 'a') + $this->overlay_image("img/dot.png", ($data['dot']['pos'] - 1) * $this->size, $this->get_color($data['dot']['pos'])); + else if($data['dot']['type'] == 'b') + $this->overlay_image("img/dot_merge.png", ($data['dot']['pos'] - 1) * $this->size, $this->get_color($data['dot']['pos'])); + else if($data['dot']['type'] == 'c') + $this->overlay_image("img/dot_init.png", ($data['dot']['pos'] - 1) * $this->size, $this->get_color($data['dot']['pos'])); + + } + +} + +?> \ No newline at end of file