<?php
/**
 * Displays a fan chart
 *
 * phpGedView: Genealogy Viewer
 * Copyright (C) 2002 to 2003  John Finlay and Others
 *
 * 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 2 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, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * @package PhpGedView
 * @subpackage Charts
 * @version $Id: fanchart.php,v 1.20 2004/12/06 19:56:15 opus27 Exp $
 */
require("config.php");
require("functions_charts.php");
require($PGV_BASE_DIRECTORY . $factsfile["english"]);
if (file_exists($PGV_BASE_DIRECTORY . $factsfile[$LANGUAGE])) require $PGV_BASE_DIRECTORY . $factsfile[$LANGUAGE];

/**
 * split and center text by lines
 *
 * @param string $data input string
 * @param int $maxlen max length of each line
 * @return string $text output string
 */
function split_align_text($data, $maxlen) {
	global $RTLOrd;
	
	$lines = explode("\r\n", $data);
	// more than 1 line : recursive calls
	if (count($lines)>1) {
		$text = "";
		foreach ($lines as $line) $text .= split_align_text($line, $maxlen)."\r\n";
		return $text;
	}
	// process current line word by word
	$split = explode(" ", $data);
	$text = "";
	$line = "";
	// do not split hebrew line
	
	$found = false;
	foreach($RTLOrd as $ord) {
    	if (strpos($data, chr($ord)) !== false) $found=true;
	}
	if ($found) $line=$data;
//	if (strpos($data, chr(215)) !== false || strpos($data, chr(216)) !== false || strpos($data, chr(217)) !== false || strpos($data, chr(218)) !== false || strpos($data, chr(219)) !== false) $line=$data;
	else
	foreach ($split as $word) {
		$len = strlen($line);
		//if (!empty($line) and ord($line{0})==215) $len/=2; // hebrew text
		$wlen = strlen($word);
		// line too long ?
		if (($len+$wlen)<$maxlen) {
			if (!empty($line)) $line .= " ";
			$line .= "$word";
		}
		else {
			$p = max(0,floor(($maxlen-$len)/2));
			if (!empty($line)) {
				$line = str_repeat(" ", $p) . "$line"; // center alignment using spaces
				$text .= "$line\r\n";
			}
			$line = $word;
		}
	}
	// last line
	if (!empty($line)) {
		$len = strlen($line);
    	if (in_array(ord($line{0}),$RTLOrd)) $len/=2;
//		if (ord($line{0})==215 || ord($line{0})==216 || ord($line{0})==217 || ord($line{0})==218 || ord($line{0})==219) $len/=2; // hebrew text
		$p = max(0,floor(($maxlen-$len)/2));
		$line = str_repeat(" ", $p) . "$line"; // center alignment using spaces
		$text .= "$line";
	}
	return $text;
}

/**
 * print ancestors on a fan chart
 *
 * @param array $treeid ancestry pid
 * @param int $fanw fan width in px (default=640)
 * @param int $fandeg fan size in deg (default=270)
 */
function print_fan_chart($treeid, $fanw=640, $fandeg=270) {
	global $PEDIGREE_GENERATIONS, $fan_width, $fan_style;
	global $name, $pgv_lang, $SHOW_ID_NUMBERS, $view, $TEXT_DIRECTION;
	global $stylesheet, $print_stylesheet;
	global $PGV_IMAGE_DIR, $PGV_IMAGES, $LINK_ICONS;

	// check for GD 2.x library
//	if (!function_exists("ImageCreate")) {
	if (!defined("IMG_ARC_PIE")) {
		print "<span class=\"error\">".$pgv_lang["gd_library"]."</span>";
		print " <a href=\"" . $pgv_lang["gd_helplink"] . "\"><img src=\"".$PGV_IMAGE_DIR."/".$PGV_IMAGES["help"]["small"]."\" class=\"icon\" alt=\"\" /></a><br /><br />";
		return false;
	}
	if (!function_exists("ImageTtfBbox")) {
		print "<span class=\"error\">".$pgv_lang["gd_freetype"]."</span>";
		print " <a href=\"" . $pgv_lang["gd_helplink"] . "\"><img src=\"".$PGV_IMAGE_DIR."/".$PGV_IMAGES["help"]["small"]."\" class=\"icon\" alt=\"\" /></a><br /><br />";
		return false;
	}

	// parse CSS file
	include("cssparser.inc.php");
	$css = new cssparser(false);
    if ($view=="preview") $css->Parse($print_stylesheet);
    else $css->Parse($stylesheet);

    // check for fontfile
	$fontfile = $css->Get(".fan_chart","font-family");
	$fontsize = $css->Get(".fan_chart","font-size");
	$fontfile = str_replace("url(", "", $fontfile);
	$fontfile = str_replace(")", "", $fontfile);
	print "\r\n<!-- trace start\r\n font-family\t=\t$fontfile\r\n font-size\t=\t$fontsize";
	print "\r\nDIRNAME(__FILE__)\t=\t". dirname(__FILE__);
	print "\r\ngetcwd()\t=\t". getcwd();
	print "\r\n-->";
	if (!file_exists($fontfile)) {
		if (!empty($fontfile)) print "<span class=\"error\">".$pgv_lang["fontfile_error"]." : $fontfile</span>";
		$fontfile="./fonts/LucidaSansRegular.ttf";
	}
	print "\r\n<!-- trace start\r\n font-family\t=\t$fontfile\r\n-->";
	if ($fontfile{0}!='/') $fontfile = dirname(__FILE__) . "/" . $fontfile;
	if (!file_exists($fontfile)) {
		print "<span class=\"error\">".$pgv_lang["fontfile_error"]." : $fontfile</span>";
		return false;
	}
	if (intval($fontsize)<2) $fontsize = 7;
	print "\r\n<!-- trace start\r\n font-family\t=\t$fontfile\r\n font-size\t=\t$fontsize\r\n-->";
	
	$treesize=count($treeid);
	if ($treesize<1) return;
	
	// generations count
	$gen=log($treesize)/log(2)-1;
	$sosa=$treesize-1;

	// fan size
	if ($fandeg==0) $fandeg=360;
	$fandeg=min($fandeg, 360);
	$fandeg=max($fandeg, 90);
	$cx=$fanw/2-1; // center x
	$cy=$cx; // center y
	$rx=$fanw-1;
	$rw=$fanw/($gen+1);
	$fanh=$fanw; // fan height
	if ($fandeg==180) $fanh=round($fanh*($gen+1)/($gen*2));
	if ($fandeg==270) $fanh=round($fanh*.86);
	$scale=$fanw/640;
	
	// image init
	$image = ImageCreate($fanw, $fanh);
	$black = ImageColorAllocate($image, 0, 0, 0);
	$white = ImageColorAllocate($image, 0xFF, 0xFF, 0xFF);
	ImageFilledRectangle ($image, 0, 0, $fanw, $fanh, $white);
	ImageColorTransparent($image, $white);
	
	$rgb = $css->Get(".fan_chart", "color");
	if (empty($rgb)) $rgb = "#000000";
	$color = ImageColorAllocate($image, hexdec(substr($rgb,1,2)), hexdec(substr($rgb,3,2)), hexdec(substr($rgb,5,2)));

	$rgb = $css->Get(".fan_chart", "background-color");
	if (empty($rgb)) $rgb = "#EEEEEE";
	$bgcolor = ImageColorAllocate($image, hexdec(substr($rgb,1,2)), hexdec(substr($rgb,3,2)), hexdec(substr($rgb,5,2)));

	$rgb = $css->Get(".fan_chart_box", "background-color");
	if (empty($rgb)) $rgb = "#D0D0AC";
	$bgcolorM = ImageColorAllocate($image, hexdec(substr($rgb,1,2)), hexdec(substr($rgb,3,2)), hexdec(substr($rgb,5,2)));

	$rgb = $css->Get(".fan_chart_boxF", "background-color");
	if (empty($rgb)) $rgb = "#D0ACD0";
	$bgcolorF = ImageColorAllocate($image, hexdec(substr($rgb,1,2)), hexdec(substr($rgb,3,2)), hexdec(substr($rgb,5,2)));

	// imagemap
	$imagemap="<map name=\"fanmap\">";
	
	// fan cells
	
	// loop
	while ($gen>=0) {
		// clean current generation area
		$deg2=360+($fandeg-180)/2;
		$deg1=$deg2-$fandeg;
		ImageFilledArc($image, $cx, $cy, $rx, $rx, $deg1, $deg2, $bgcolor, IMG_ARC_PIE);
		$rx-=3;
		
		// calculate new angle
		$p2=pow(2, $gen);
		$angle=$fandeg/$p2;
		$deg2=360+($fandeg-180)/2;
		$deg1=$deg2-$angle;
		// special case for rootid cell
		if ($gen==0) {
			$deg1=90;
			$deg2=360+$deg1;
		}
		
		// draw each cell
		while ($sosa >= $p2) {
			$pid=$treeid[$sosa];
			if (!empty($pid)) {
				$indirec=find_person_record($pid);
				if (!$indirec) $indirec = find_record_in_file($pid);
				 
				if ($sosa%2) $bg=$bgcolorF;
				else $bg=$bgcolorM;
				if ($sosa==1) {
					$bg=$bgcolor; // sex unknown
					if (preg_match("/1 SEX F/", $indirec)>0) $bg=$bgcolorF;
					else if (preg_match("/1 SEX M/", $indirec)>0) $bg=$bgcolorM;
				}
				ImageFilledArc($image, $cx, $cy, $rx, $rx, $deg1, $deg2, $bg, IMG_ARC_PIE);
				if ((!displayDetailsByID($pid))&&(!showLivingNameByID($pid))) {
					$name = $pgv_lang["private"];
					$addname = "";
				}
				else {
					$name = get_person_name($pid);
					$addname = get_add_person_name($pid);
				}
				$text = ltr_string($name) . "\r\n" . ltr_string($addname). "\r\n";
				if (displayDetailsByID($pid)) {
					$birthrec = get_sub_record(1, "1 BIRT", $indirec);
					$ct = preg_match("/2 DATE.*(\d\d\d\d)/", $birthrec, $match);
					if ($ct>0) $text.= trim($match[1]);
					$deathrec = get_sub_record(1, "1 DEAT", $indirec);
					$ct = preg_match("/2 DATE.*(\d\d\d\d)/", $deathrec, $match);
					if ($ct>0) $text.= "-".trim($match[1]);
				}
				$text = unhtmlentities($text);
				$text = strip_tags($text);
				
				// split and center text by lines
				$wmax = floor($angle*7/$fontsize*$scale);
				$wmax = min($wmax, 35*$scale);
				if ($gen==0) $wmax = min($wmax, 17*$scale);
				$text = split_align_text($text, $wmax);

				// text angle
				$tangle = 270-($deg1+$angle/2);
				if ($gen==0) $tangle=0;

				// calculate text position
				$bbox=ImageTtfBbox($fontsize, 0, $fontfile, $text);
				$textwidth = $bbox[4];
				$deg = $deg1+.44;
				if ($deg2-$deg1>40) $deg = $deg1+($deg2-$deg1)/11;
				if ($deg2-$deg1>80) $deg = $deg1+($deg2-$deg1)/7;
				if ($deg2-$deg1>140) $deg = $deg1+($deg2-$deg1)/4;
				if ($gen==0) $deg=180;
				$rad=deg2rad($deg);
				$mr=($rx-$rw/4)/2;
				if ($gen>0 and $deg2-$deg1>80) $mr=$rx/2;
				$tx=$cx + ($mr) * cos($rad);
				$ty=$cy - $mr * -sin($rad);
				if ($sosa==1) $ty-=$mr/2;
				
				// print text
				ImageTtfText($image, $fontsize, $tangle, $tx, $ty, $color, $fontfile, $text);

				$imagemap .= "\r\n<area shape=\"poly\" coords=\"";
				// plot upper points
				$mr=$rx/2;
				$deg=$deg1;
				while ($deg<=$deg2) {
					$rad=deg2rad($deg);
					$tx=round($cx + ($mr) * cos($rad));
					$ty=round($cy - $mr * -sin($rad));
					$imagemap .= "$tx, $ty, ";
					$deg+=($deg2-$deg1)/6;
				}
				// plot lower points
				$mr=($rx-$rw)/2;
				$deg=$deg2;
				while ($deg>=$deg1) {
					$rad=deg2rad($deg);
					$tx=round($cx + ($mr) * cos($rad));
					$ty=round($cy - $mr * -sin($rad));
					$imagemap .= "$tx, $ty, ";
					$deg-=($deg2-$deg1)/6;
				}
				// join first point
				$mr=$rx/2;
				$deg=$deg1;
				$rad=deg2rad($deg);
				$tx=round($cx + ($mr) * cos($rad));
				$ty=round($cy - $mr * -sin($rad));
				$imagemap .= "$tx, $ty";
				// add action url
				$url = "?rootid=$pid&PEDIGREE_GENERATIONS=$PEDIGREE_GENERATIONS&fan_width=$fan_width&fan_style=$fan_style";
				if (!empty($view)) $url .= "&view=$view";
				$imagemap .= "\" href=\"$url\" ";
				if ($sosa==1 and $view!="preview") {
					// merge arrow image
					$imgfile = $PGV_IMAGE_DIR."/".$PGV_IMAGES["darrow"]["other"];
					list($imgx, $imgy, $imgtype, $imgattr) = getimagesize($imgfile);
					if ($imgtype==1 and !function_exists("ImageCreateFromGif")) {
						$imgfile = "images/darrow.png";
						list($imgx, $imgy, $imgtype, $imgattr) = getimagesize($imgfile);
					}
					if ($imgtype==1) $imgsrc = ImageCreateFromGif($imgfile);
					else if ($imgtype==2) $imgsrc = ImageCreateFromJpeg($imgfile);
					else if ($imgtype==3) $imgsrc = ImageCreateFromPng($imgfile);
					ImageCopyMerge($image, $imgsrc, $cx-$imgx/2, $cy+$mr/2, 0, 0, $imgx, $imgy, 100);
					// print popup
					print_childbox_popup($pid, $indirec, $url);
					$imagemap .= "onclick=\"MM_showHideLayers('childbox', 'followmouse', 'toggle', 'childbox'); return false;\" ";
				}
				$imagemap .= " alt=\"$pid\">";
			}
			$deg1-=$angle;
			$deg2-=$angle;
			$sosa--;
		}
		$rx-=$rw;
		$gen--;
	}
	
	$imagemap .= "\r\n</map>";
	echo "\r\n$imagemap";

	// PGV banner ;-)
	ImageStringUp($image, 1, $fanw-10, $fanh/3, "www.phpgedview.net", $color);

	// here we cannot send image to browser ('header already sent')
	// and we dont want to use a tmp file

	// step 1. save image data in a session variable
	ob_start();
	ImagePng($image);
	$image_data = ob_get_contents();
	ob_end_clean();
	$image_data = serialize($image_data);
	unset ($_SESSION['image_data']);
	$_SESSION['image_data']=$image_data;
	
	// step 2. call imageflush.php to read this session variable and display image
	// note: arg "image_name=" is to avoid image miscaching
	$image_name=time();
	$image_title=$name . " " . $pgv_lang["fan_chart"];
	echo "\r\n<p align=\"center\" >";
	echo "<img src=\"imageflush.php?image_type=png&image_name=$image_name\" width=\"$fanw\" height=\"$fanh\" border=\"0\" alt=\"$image_title\" title=\"$image_title\" usemap=\"#fanmap\" />";
	echo "\r\n</p>\r\n";
	ImageDestroy($image);
}

// -- args
if (!isset($fan_style)) $fan_style = 0;
if ($fan_style==0) $fan_style = 3;
if ((!isset($PEDIGREE_GENERATIONS)) || ($PEDIGREE_GENERATIONS == "")) $PEDIGREE_GENERATIONS = $DEFAULT_PEDIGREE_GENERATIONS;

if ($PEDIGREE_GENERATIONS > $MAX_PEDIGREE_GENERATIONS) {
	$PEDIGREE_GENERATIONS = $MAX_PEDIGREE_GENERATIONS;
	$max_generation = true;
}

if ($PEDIGREE_GENERATIONS < 3) {
	$PEDIGREE_GENERATIONS = 3;
	$min_generation = true;
}
$OLD_PGENS = $PEDIGREE_GENERATIONS;

if (!isset($rootid)) $rootid = "";
$rootid = clean_input($rootid);
$rootid = check_rootid($rootid);

// -- size of the chart
if (!isset($fan_width)) $fan_width = "100";
$fan_width=max($fan_width, 50);
$fan_width=min($fan_width, 300);

if ((DisplayDetailsByID($rootid)) || (showLivingNameByID($rootid))) {
	$name = get_person_name($rootid);
	$addname = get_add_person_name($rootid);
}
else {
	$name = $pgv_lang["private"];
	$addname = "";
}
// -- print html header information
//print_header($name . " " . $pgv_lang["fan_chart"]);
print_header(PrintReady($name) . " " . $pgv_lang["fan_chart"]);
if (strlen($name)<30) $cellwidth="420";
else $cellwidth=(strlen($name)*14);
print "\n\t<table class=\"list_table, $TEXT_DIRECTION\"><tr><td width=\"${cellwidth}px\" valign=\"top\">\n\t\t";
if ($view == "preview") print "<h2>" . str_replace("#PEDIGREE_GENERATIONS#", convert_number($PEDIGREE_GENERATIONS), $pgv_lang["gen_fan_chart"]) . ":";
else print "<h2>" . $pgv_lang["fan_chart"] . ":";
//print "<br />".$name;
print "<br />".PrintReady($name);
//if ($addname != "") print "<br />" . $addname;
if ($addname != "") print "<br />" . PrintReady($addname);
print "</h2>";

// -- print the form to change the number of displayed generations
if ($view != "preview") {

	?>
	<script language="JavaScript" type="text/javascript">
	<!--
	var pasteto;
	function open_find(textbox) {
		pasteto = textbox;
		findwin = window.open('findid.php', '', 'left=50,top=50,width=450,height=450,resizable=1,scrollbars=1');
	}
	function paste_id(value) {
		pasteto.value=value;
	}
	//-->
	</script>
	<?php
	if (isset($max_generation) == true) print "<span class=\"error\">" . str_replace("#PEDIGREE_GENERATIONS#", convert_number($PEDIGREE_GENERATIONS), $pgv_lang["max_generation"]) . "</span>";
	if (isset($min_generation) == true) print "<span class=\"error\">" . $pgv_lang["min_generation"] . "</span>";
	print "\n\t</td><td><form name=\"people\" method=\"get\" action=\"?\">";
	/**
	print "<input type=\"hidden\" name=\"rootid\" value=\"$rootid\" />";
	print "<input type=\"hidden\" name=\"PEDIGREE_GENERATIONS\" value=\"$PEDIGREE_GENERATIONS\" />";
	print "<input type=\"hidden\" name=\"fan_width\" value=\"$fan_width\" />";
	print "<input type=\"hidden\" name=\"fan_style\" value=\"$fan_style\" />";
	**/
	print "\n\t\t<table class=\"list_table, $TEXT_DIRECTION\">\n\t\t<tr>";
	// rootid
	print "<td class=\"list_label\">&nbsp;" . $pgv_lang["root_person"] . "&nbsp;</td>";
	print "<td class=\"list_value\">";
	print "<input class=\"pedigree_form\" type=\"text\" name=\"rootid\" size=\"3\" value=\"$rootid\" /><font size=\"1\"> <a href=\"javascript:open_find(document.people.rootid);\">" . $pgv_lang["find_id"] . "</a></font> ";
	print_help_link("rootid_help", "qm");
	print "</td>";
	// fan style
	print "<td rowspan=\"3\" class=\"list_value\">";
	print "\n\t\t<table class=\"$TEXT_DIRECTION\" style=\" width: 100%;\">\n\t\t<tr><td class=\"sublinks_cell\" style=\" white-space: nowrap;\">";
	print "<input type=\"radio\" name=\"fan_style\" value=\"2\"";
	if ($fan_style==2) print " checked=\"checked\"";
	print " /> 1/2";
	print "<br /><input type=\"radio\" name=\"fan_style\" value=\"3\"";
	if ($fan_style==3) print " checked=\"checked\"";
	print " /> 3/4";
	print "<br /><input type=\"radio\" name=\"fan_style\" value=\"4\"";
	if ($fan_style==4) print " checked=\"checked\"";
	print " /> 4/4";
	print_help_link("fan_style_help", "qm");
	// submit
	print "</td><td class=\"subheaders\" style=\"width: 60px; vertical-align:bottom;text-align: ".($TEXT_DIRECTION=="rtl"?"left":"right").";\">";
	print "<input type=\"submit\" value=\"" . $pgv_lang["view"] . "\" />";
	print "</td></tr></table>\n";
	print "</td>";
	print "</tr><tr>";
	// generations
	print "<td class=\"list_label\">&nbsp;" . $pgv_lang["generations"] . "&nbsp;</td>";
	print "<td class=\"list_value\">";
	print "<input type=\"text\" name=\"PEDIGREE_GENERATIONS\" size=\"3\" value=\"$OLD_PGENS\" /> ";
	print_help_link("PEDIGREE_GENERATIONS_help", "qm");
	print "</td>";
	print "</tr><tr>";
	// fan width
	print "<td class=\"list_label\">&nbsp;" . $pgv_lang["fan_width"] . "&nbsp;</td>";
	print "<td class=\"list_value\">";
	print "<input type=\"text\" size=\"3\" name=\"fan_width\" value=\"$fan_width\" /> <b>%</b> ";
	print_help_link("fan_width_help", "qm");
	print "</td>";
	print "</tr></table>";
	print "\n\t\t</form><br />";
}
print "</td></tr></table>";

$treeid = ancestry_array($rootid);
print_fan_chart($treeid, 640*$fan_width/100, $fan_style*90);

print_footer();
?>
