예제 #1
0
 /**
  * Create Timeline Image
  *
  * @param $date
  * @param $draw     if FALSE return coordinates only, for imagemap
  * @param $translate for translate
  * @param $img_type [normal | small]
  * @return image
  */
 public function createTimelineImage($date, $draw = true, $translate = null, $img_type = 'normal')
 {
     $this->GetDataTimeline($date);
     if (empty($this->atime)) {
         // Nothing data to graph
         return;
     }
     $this->calculateImageData($img_type);
     if (!$draw) {
         $img_map = array();
     }
     $ttf_font_error = 0;
     // созд-е пустого холста
     // Create a new true color image :
     // resource imagecreatetruecolor ( int width, int height )
     $img = ImageCreateTrueColor($this->img_width, $this->img_height);
     if (!$img) {
         // Handle the error
         $this->view->result = null;
         $this->getResponse()->setHeader('Content-Type', 'text/html; charset=utf-8');
         throw new Zend_Exception('Internal ERROR: ImageCreateTrueColor');
         return;
     }
     // цвета
     $white = ImageColorAllocate($img, 255, 255, 255);
     $black = ImageColorAllocate($img, 0, 0, 0);
     $blue = ImageColorAllocate($img, 0x49, 0x74, 0xbc0);
     // массив цветов для полос
     $acolor = array(ImageColorAllocate($img, 0xea, 0xea, 0x33), ImageColorAllocate($img, 0xff, 0xba, 0xba), ImageColorAllocate($img, 0xd0, 0xae, 0xff), ImageColorAllocate($img, 0x9d, 0xed, 0x0), ImageColorAllocate($img, 0xdc, 0xdc, 0xdc));
     $acolor_count = count($acolor);
     // кол-во цветов для рисования полос
     $bg_color = $white;
     $text_color = $black;
     // создание фона для рисования
     // Draw a filled rectangle : bool imagefilledrectangle ( resource image, int x1, int y1, int x2, int y2, int color )
     if ($draw) {
         ImageFilledRectangle($img, 0, 0, $this->img_width, $this->img_height, $bg_color);
     }
     // контур фона
     // Draw a rectangle : bool imagerectangle ( resource image, int x1, int y1, int x2, int y2, int color )
     if ($draw) {
         ImageRectangle($img, 0, 0, $this->img_width - 1, $this->img_height - 1, $blue);
     }
     // --------------------------------- вычерчивание координатной сетки ---------------------------------------
     // ось X
     // Draw a line :
     // bool imageline ( resource image, int x1, int y1, int x2, int y2, int color )
     // $y0, $x0 - начало координат
     $y0 = $y2 = $this->img_height - $this->margin_bottom - $this->margin_top + $this->bar_space;
     $x0 = $this->margin_left;
     if ($draw) {
         ImageLine($img, $x0, $y0, $this->img_width - $this->margin_right, $y2, $blue);
     }
     // ось X
     // вертикальные линии - часы
     // пунктирная линия
     $style_dash = array_merge(array_fill(0, 1, $blue), array_fill(0, 3, IMG_COLOR_TRANSPARENT));
     if ($draw) {
         ImageSetStyle($img, $style_dash);
     }
     $hour1 = ceil(($this->img_width - $x0 - $this->margin_right) / 24);
     // шаг засечек или 1 час в пикселах
     $y2 = 0;
     for ($i = 0; $i <= 23; $i++) {
         $x1 = $x0 + $i * $hour1;
         ImageLine($img, $x1, $y0, $x1, $y2, IMG_COLOR_STYLED);
     }
     if ($img_type == 'normal') {
         // подписи к оси X
         $y1 = $this->img_height - $this->margin_bottom - $this->margin_top + $this->bar_space + $this->font_size;
         for ($i = 0; $i <= 23; $i++) {
             // Draw a string horizontally :
             // bool imagestring ( resource image, int font, int x, int y, string sring, int color )
             // Can be 1, 2, 3, 4, 5 for built-in fonts (where higher numbers corresponding to larger fonts)
             // для учета кол-ва символов в цифрах часов
             if ($i < 10) {
                 $div2 = 10;
             } else {
                 $div2 = 5;
             }
             $x1 = $x0 - $div2 + $i * $hour1;
             if ($draw) {
                 ImageString($img, 4, $x1, $y1, sprintf("% 2d", $i), $blue);
             }
         }
         // X axis title / название оси X
         if (empty($this->font_name)) {
             // use system fixed font / ось подписываем встроенным шрифтом
             if ($draw) {
                 ImageString($img, $this->fixfont, floor($this->img_width / 2), $this->img_height - floor(($this->img_height - $y0) / 2), "Hours", $blue);
             }
             // do not to translate (перевод не нужен)
         } else {
             if ($draw) {
                 @($ares = ImageTtfText($img, $this->font_size, 0, floor($this->img_width / 2), $this->img_height - floor(($this->img_height - $y0) / 3), $blue, $this->font_name, $translate->_("Hours")));
                 if (empty($ares)) {
                     $ttf_font_error = 1;
                     // TTF font not loaded/found
                     if ($draw) {
                         ImageString($img, 4, 5, 5, "Font " . $this->font_name . " not loaded/found.", $black);
                     }
                     // do not to translate (перевод не нужен)
                 }
             }
         }
     }
     //---------------- draw graph (рисуем график) --------------------------------------------
     $yt = $this->margin_top;
     $c = 0;
     for ($i = 0; $i <= $this->bar_count - 1; $i++) {
         $str = '(' . $this->atime[$i]['jobid'] . ') ' . $this->atime[$i]['name'];
         // для заданий не уложившихся в сутки, рисуем знаки с определенной стороны
         switch ($this->atime[$i]['flag']) {
             case -1:
                 $str = '<--' . $str;
                 // задание началось ранее
                 break;
             case 1:
                 $str = $str . '-->';
                 // задание закончилось позднее
                 break;
             case 2:
                 $str = '<--' . $str . '-->';
                 // задание началось ранее и закончилось позднее (очень длинное задание)
                 break;
         }
         // Draw a filled rectangle:
         // bool imagefilledrectangle ( resource image, int x1, int y1, int x2, int y2, int color )
         // полосы
         $yr1 = $yt - ceil($this->font_size / 2) - ceil($this->bar_height / 2);
         $yr2 = $yr1 + $this->bar_height;
         $xr1 = $x0 + floor($hour1 * $this->atime[$i]['h1']);
         $xr2 = $x0 + floor($hour1 * $this->atime[$i]['h2']);
         // если слишком маленькая полоса
         if ($xr2 - $xr1 < 3) {
             $xr2 = $xr1 + 3;
         }
         // цвет
         if ($c > $acolor_count - 1) {
             $c = 0;
         }
         // draw restangle
         if ($draw) {
             ImageFilledRectangle($img, $xr1, $yr1, $xr2, $yr2, $acolor[$c++]);
         }
         // Write text to the image using TrueType fonts :
         // array imagettftext ( resource image, float size, float angle, int x, int y, int color, string fontfile, string text )
         // x - The coordinates given by x and y will define the basepoint of the first character
         // (roughly the lower-left corner of the character).
         // This is different from the imagestring(), where x and y define the upper-left corner of the first character.
         // For example, "top left" is 0, 0.
         // size - The font size. Depending on your version of GD, this should be specified as the pixel size (GD1) or point size (GD2)
         // **************** text *****************
         // array imagettfbbox ( float size, float angle, string fontfile, string text )
         // где расположить текст
         // расчет координат текста
         // левая координата X = $abox[0], правая X = $abox[2]
         if (!$ttf_font_error && !empty($this->font_name)) {
             // TTF font loaded OK
             $abox = ImageTtfBbox($this->font_size, 0, $this->font_name, $str);
             $xt = $xr1 + $this->margin_text_left;
             if ($xt + $abox[2] > $this->img_width) {
                 $xt = $xr2 - $abox[2] - $this->margin_text_left;
                 if (!$draw) {
                     $xt > $xr2 ? $x2 = $xt : ($x2 = $xr2);
                 }
                 // coordinates for imagemap
             } else {
                 if (!$draw) {
                     $xt + $abox[2] > $xr2 ? $x2 = $xt + $abox[2] : ($x2 = $xr2);
                 }
                 // coordinates for imagemap
             }
             // draw text
             if ($draw) {
                 ImageTtfText($img, $this->font_size, 0, $xt, $yt, $text_color, $this->font_name, $str);
             }
         } else {
             // fix font
             $lenfix = strlen($str) * imagefontwidth($this->fixfont);
             if ($xr1 + $lenfix > $this->img_width) {
                 $xt = $xr2 - $lenfix - $this->margin_text_left;
                 if (!$draw) {
                     $xt > $xr2 ? $x2 = $xt : ($x2 = $xr2);
                 }
                 // coordinates for imagemap
             } else {
                 $xt = $xr1;
                 if (!$draw) {
                     $xt + $lenfix > $xr2 ? $x2 = $xt + $lenfix : ($x2 = $xr2);
                 }
                 // coordinates for imagemap
             }
             // draw text
             if ($draw) {
                 ImageString($img, $this->fixfont, $xt, $yr1, $str, $text_color);
             }
         }
         // save coordinates
         if (!$draw) {
             $xt < $xr1 ? $x1 = $xt : ($x1 = $xr1);
             $img_map[$i]['jobid'] = $this->atime[$i]['jobid'];
             $img_map[$i]['name'] = $this->atime[$i]['name'];
             $img_map[$i]['short_desc'] = $this->atime[$i]['short_desc'];
             $img_map[$i]['x1'] = $x1;
             $img_map[$i]['y1'] = $yr1;
             $img_map[$i]['x2'] = $x2;
             $img_map[$i]['y2'] = $yr2;
         }
         $yt = $yt + $this->bar_height + $this->bar_space;
     }
     if ($draw) {
         return $img;
     } else {
         return $img_map;
     }
 }
예제 #2
0
/**
 * 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, $GEDCOM;
    // check for GD 2.x library
    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 "includes/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);
    if (!file_exists($fontfile)) {
        if (!empty($fontfile)) {
            print "<span class=\"error\">" . $pgv_lang["fontfile_error"] . " : {$fontfile}</span>";
        }
        $fontfile = "./includes/fonts/DejaVuSans.ttf";
    }
    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;
    }
    $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 * 0.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 id=\"fanmap\" name=\"fanmap\">";
    // loop to create fan cells
    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_updated_record($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);
                $person = Person::getInstance($pid);
                $name = $person->getFullName();
                $addname = $person->getAddName();
                //$name = str_replace(array('<span class="starredname">', '</span>'), '', $name);
                //$addname = str_replace(array('<span class="starredname">', '</span>'), '', $addname);
                //$name = str_replace(array('<span class="starredname">', '</span>'), array('<u>', '</u>'), $name); //@@
                //$addname = str_replace(array('<span class="starredname">', '</span>'), array('<u>', '</u>'), $addname); //@@
                // ToDo - print starred names underlined - 1985154
                // Todo - print Arabic letters combined - 1360209
                $text = reverseText($name) . "\n";
                if (!empty($addname)) {
                    $text .= reverseText($addname) . "\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 = unhtmlentitiesrtl($text);
                $text = strip_tags($text);
                //Do we still need?
                // 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((double) $fontsize, 0, $fontfile, $text);
                $textwidth = $bbox[4];
                $deg = $deg1 + 0.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, (double) $fontsize, $tangle, $tx, $ty, $color, $fontfile, $text);
                $imagemap .= "<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
                $tempURL = "javascript://" . htmlspecialchars(strip_tags($name));
                if ($SHOW_ID_NUMBERS) {
                    $tempURL .= " (" . $pid . ")";
                }
                $imagemap .= "\" href=\"{$tempURL}\" ";
                $tempURL = "fanchart.php?rootid={$pid}&PEDIGREE_GENERATIONS={$PEDIGREE_GENERATIONS}&fan_width={$fan_width}&fan_style={$fan_style}";
                if (!empty($view)) {
                    $tempURL .= "&view={$view}";
                }
                $count = 0;
                $lbwidth = 200;
                print "<div id=\"I" . $pid . "." . $count . "links\" style=\"position:absolute; >";
                print "left:" . $tx . "px; top:" . $ty . "px; width: " . $lbwidth . "px; visibility:hidden; z-index:'100';\">";
                print "<table class=\"person_box\"><tr><td class=\"details1\">";
                print "<a href=\"individual.php?pid={$pid}\" class=\"name1\">" . PrintReady($name);
                if (!empty($addname)) {
                    print "<br />" . PrintReady($addname);
                }
                print "</a>";
                print "<br /><a href=\"pedigree.php?rootid={$pid}\" >" . $pgv_lang["index_header"] . "</a>";
                print "<br /><a href=\"descendancy.php?pid={$pid}\" >" . $pgv_lang["descend_chart"] . "</a>";
                if (PGV_USER_GEDCOM_ID) {
                    print "<br /><a href=\"" . encode_url("relationship.php?pid1=" . PGV_USER_GEDCOM_ID . "&pid2={$pid}&ged={$GEDCOM}") . "\" onmouseover=\"clear_family_box_timeout('" . $pid . "." . $count . "');\" onmouseout=\"family_box_timeout('" . $pid . "." . $count . "');\">" . $pgv_lang["relationship_to_me"] . "</a>";
                }
                print "<br /><a href=\"ancestry.php?rootid={$pid}\" onmouseover=\"clear_family_box_timeout('" . $pid . "." . $count . "');\" onmouseout=\"family_box_timeout('" . $pid . "." . $count . "');\">" . $pgv_lang["ancestry_chart"] . "</a>";
                print "<br /><a href=\"compact.php?rootid={$pid}\" onmouseover=\"clear_family_box_timeout('" . $pid . "." . $count . "');\" onmouseout=\"family_box_timeout('" . $pid . "." . $count . "');\">" . $pgv_lang["compact_chart"] . "</a>";
                print "<br /><a href=\"" . encode_url($tempURL) . "\" onmouseover=\"clear_family_box_timeout('" . $pid . "." . $count . "');\" onmouseout=\"family_box_timeout('" . $pid . "." . $count . "');\">" . $pgv_lang["fan_chart"] . "</a>";
                print "<br /><a href=\"hourglass.php?pid={$pid}\" onmouseover=\"clear_family_box_timeout('" . $pid . "." . $count . "');\" onmouseout=\"family_box_timeout('" . $pid . "." . $count . "');\">" . $pgv_lang["hourglass_chart"] . "</a>";
                if ($sosa >= 1) {
                    $famids = find_sfamily_ids($pid);
                    //-- make sure there is more than 1 child in the family with parents
                    $cfamids = find_family_ids($pid);
                    $num = 0;
                    for ($f = 0; $f < count($cfamids); $f++) {
                        $famrec = find_family_record($cfamids[$f]);
                        if ($famrec) {
                            $num += preg_match_all("/1\\s*CHIL\\s*@(.*)@/", $famrec, $smatch, PREG_SET_ORDER);
                        }
                    }
                    if ($famids || $num > 1) {
                        //-- spouse(s) and children
                        for ($f = 0; $f < count($famids); $f++) {
                            $famrec = find_family_record(trim($famids[$f]));
                            if ($famrec) {
                                $parents = find_parents($famids[$f]);
                                if ($parents) {
                                    if ($pid != $parents["HUSB"]) {
                                        $spid = $parents["HUSB"];
                                    } else {
                                        $spid = $parents["WIFE"];
                                    }
                                    $person = Person::getInstance($spid);
                                    if ($person) {
                                        echo '<br /><a href="', $person->getLinkUrl(), '" class="name1">', $person->getFullName(), '</a>';
                                    }
                                }
                                $num = preg_match_all("/1\\s*CHIL\\s*@(.*)@/", $famrec, $smatch, PREG_SET_ORDER);
                                for ($i = 0; $i < $num; $i++) {
                                    $person = Person::getInstance($smatch[$i][1]);
                                    if ($person) {
                                        echo '<br />&nbsp;&nbsp;<a href="', $person->getLinkUrl(), '" class="name1">&lt; ', $person->getFullName(), '</a>';
                                    }
                                }
                            }
                        }
                        //-- siblings
                        for ($f = 0; $f < count($cfamids); $f++) {
                            $famrec = find_family_record($cfamids[$f]);
                            if ($famrec) {
                                $num = preg_match_all("/1\\s*CHIL\\s*@(.*)@/", $famrec, $smatch, PREG_SET_ORDER);
                                if ($num > 2) {
                                    print "<br /><span class=\"name1\">" . $pgv_lang["siblings"] . "</span>";
                                }
                                if ($num == 2) {
                                    print "<br /><span class=\"name1\">" . $pgv_lang["sibling"] . "</span>";
                                }
                                for ($i = 0; $i < $num; $i++) {
                                    $cpid = $smatch[$i][1];
                                    if ($cpid != $pid) {
                                        $person = Person::getInstance($cpid);
                                        if ($person) {
                                            echo '<br />&nbsp;&nbsp;<a href="', $person->getLinkUrl(), '" class="name1"> ', $person->getFullName(), '</a>';
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                print "</td></tr></table>";
                print "</div>";
                $imagemap .= " onclick=\"show_family_box('" . $pid . "." . $count . "', 'relatives'); return false;\"";
                $imagemap .= " onmouseout=\"family_box_timeout('" . $pid . "." . $count . "'); return false;\"";
                $imagemap .= " alt=\"" . PrintReady(strip_tags($name)) . "\" title=\"" . PrintReady(strip_tags($name)) . "\" />";
            }
            $deg1 -= $angle;
            $deg2 -= $angle;
            $sosa--;
        }
        $rx -= $rw;
        $gen--;
    }
    $imagemap .= "</map>";
    echo $imagemap;
    // PGV banner ;-)
    ImageStringUp($image, 1, $fanw - 10, $fanh / 3, PGV_PHPGEDVIEW_URL, $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 = "V" . time();
    unset($_SESSION[$image_name]);
    // statisticsplot.php uses this to hold a file name to send to browser
    $image_title = preg_replace("~<.*>~", "", $name) . " " . $pgv_lang["fan_chart"];
    echo "<p align=\"center\" >";
    echo "<img src=\"imageflush.php?image_type=png&amp;image_name={$image_name}&amp;height={$fanh}&amp;width={$fanw}\" width=\"{$fanw}\" height=\"{$fanh}\" border=\"0\" alt=\"{$image_title}\" title=\"{$image_title}\" usemap=\"#fanmap\" />";
    echo "</p>";
    ImageDestroy($image);
}
예제 #3
0
/**
* print ancestors on a fan chart
* @param array $treeid ancestry pid
* @param int $fanw fan width in px (default=840)
* @param int $fandeg fan size in deg (default=270)
*/
function print_fan_chart($treeid, $fanw = 840, $fandeg = 270)
{
    global $dbh, $tree_id, $db_functions, $fontsize, $date_display;
    global $fan_style, $family_id;
    global $printing, $language, $selected_language;
    global $pers_var, $tree_prefix_quoted;
    global $china_message;
    // check for GD 2.x library
    if (!defined("IMG_ARC_PIE")) {
        print "ERROR: NO GD LIBRARY";
        return false;
    }
    if (!function_exists("ImageTtfBbox")) {
        print "ERROR: NO GD LIBRARY";
        return false;
    }
    if (intval($fontsize) < 2) {
        $fontsize = 7;
    }
    $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 * 0.86);
    }
    $scale = $fanw / 840;
    // 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);
    if ($printing == 1) {
        ImageColorTransparent($image, $white);
    }
    // *** Border colour ***
    $rgb = "";
    if (empty($rgb)) {
        $rgb = "#6E6E6E";
    }
    $grey = ImageColorAllocate($image, hexdec(substr($rgb, 1, 2)), hexdec(substr($rgb, 3, 2)), hexdec(substr($rgb, 5, 2)));
    // *** Text colour ***
    $rgb = "";
    if (empty($rgb)) {
        $rgb = "#000000";
    }
    $color = ImageColorAllocate($image, hexdec(substr($rgb, 1, 2)), hexdec(substr($rgb, 3, 2)), hexdec(substr($rgb, 5, 2)));
    // *** Background colour ***
    $rgb = "";
    if (empty($rgb)) {
        $rgb = "#EEEEEE";
    }
    $bgcolor = ImageColorAllocate($image, hexdec(substr($rgb, 1, 2)), hexdec(substr($rgb, 3, 2)), hexdec(substr($rgb, 5, 2)));
    // *** Man colour ***
    $rgb = "";
    if (empty($rgb)) {
        $rgb = "#B2DFEE";
    }
    $bgcolorM = ImageColorAllocate($image, hexdec(substr($rgb, 1, 2)), hexdec(substr($rgb, 3, 2)), hexdec(substr($rgb, 5, 2)));
    // *** wife colour ***
    $rgb = "";
    if (empty($rgb)) {
        $rgb = "#FFE4C4";
    }
    $bgcolorF = ImageColorAllocate($image, hexdec(substr($rgb, 1, 2)), hexdec(substr($rgb, 3, 2)), hexdec(substr($rgb, 5, 2)));
    // imagemap
    $imagemap = "<map id=\"fanmap\" name=\"fanmap\">";
    // loop to create fan cells
    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);
        ImageFilledArc($image, $cx, $cy, $rx, $rx, $deg1, $deg2, $bgcolor, IMG_ARC_EDGED | IMG_ARC_NOFILL);
        $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][0];
            $birthyr = $treeid[$sosa][1];
            $deathyr = $treeid[$sosa][4];
            $fontpx = $fontsize;
            if ($sosa >= 16 and $fandeg == 180) {
                $fontpx = $fontsize - 1;
            }
            if ($sosa >= 32 and $fandeg != 180) {
                $fontpx = $fontsize - 1;
            }
            if (!empty($pid)) {
                if ($sosa % 2) {
                    $bg = $bgcolorF;
                } else {
                    $bg = $bgcolorM;
                }
                if ($sosa == 1) {
                    if ($treeid[$sosa][5] == "F") {
                        $bg = $bgcolorF;
                    } else {
                        if ($treeid[$sosa][5] == "M") {
                            $bg = $bgcolorM;
                        } else {
                            $bg = $bgcolor;
                            // sex unknown
                        }
                    }
                }
                ImageFilledArc($image, $cx, $cy, $rx, $rx, $deg1, $deg2, $bg, IMG_ARC_PIE);
                if ($gen != 0) {
                    ImageFilledArc($image, $cx, $cy, $rx, $rx, $deg1, $deg2, $grey, IMG_ARC_EDGED | IMG_ARC_NOFILL);
                } else {
                    ImageFilledArc($image, $cx, $cy, $rx, $rx, $deg1, $deg2, $grey, IMG_ARC_NOFILL);
                }
                $name = $pid;
                // check if string is RTL language- if it is, it has to be reversed later on by persian_log2vis()
                $rtlstr = 0;
                //if(preg_match('/(*UTF8)[א-ת]/',$name)!==0 OR preg_match('/(*UTF8)[أ-ى]/',$name)!==0) {
                if (preg_match('/(*UTF8)[א-ת]/', $name) === 1 or preg_match('/(*UTF8)[أ-ى]/', $name) === 1) {
                    // this is either Hebrew, Arabic or Persian -> we have to reverse the text!
                    $rtlstr = 1;
                }
                $fontfile = CMS_ROOTPATH . "include/fanchart/dejavusans.ttf";
                // this default font serves: Latin,Hebrew,Arabic,Persian,Russian
                //if(preg_match('/(*UTF8)\p{Han}/',$name)!==0) {	// String is Chinese so use a Chinese ttf font if present in the folder
                if (preg_match('/(*UTF8)\\p{Han}/', $name) === 1) {
                    // String is Chinese so use a Chinese ttf font if present in the folder
                    if (is_dir(CMS_ROOTPATH . "include/fanchart/chinese")) {
                        $dh = opendir(CMS_ROOTPATH . "include/fanchart/chinese");
                        while (false !== ($filename = readdir($dh))) {
                            //if (strtolower(substr($filename, -3)) == "ttf"){
                            if (strtolower(substr($filename, -3)) == "otf" or strtolower(substr($filename, -3)) == "ttf") {
                                $fontfile = CMS_ROOTPATH . "include/fanchart/chinese/" . $filename;
                            }
                        }
                    }
                    if ($fontfile == CMS_ROOTPATH . "include/fanchart/dejavusans.ttf") {
                        //no Chinese ttf file found
                        $china_message = 1;
                    }
                }
                $text = $name;
                // names
                $text2 = "";
                // dates
                if ($date_display == 1) {
                    // don't show dates
                } else {
                    if ($date_display == 2) {
                        //show years only
                        // years only chosen but we also do this if no place in outer circles
                        $text2 .= substr($birthyr, -4) . " - " . substr($deathyr, -4);
                    } else {
                        if ($date_display == 3) {
                            //show full dates (but not in narrow outer circles!)
                            if ($gen > 5) {
                                $text2 .= substr($birthyr, -4) . " - " . substr($deathyr, -4);
                            } else {
                                if ($gen > 4 and $fan_style != 4) {
                                    $text2 .= substr($birthyr, -4) . " - " . substr($deathyr, -4);
                                } else {
                                    // full dates
                                    if ($birthyr) {
                                        $text2 .= "b." . $birthyr . "\n";
                                    }
                                    if ($deathyr) {
                                        $text2 .= "d." . $deathyr;
                                    }
                                }
                            }
                        }
                    }
                }
                // split and center text by lines
                $wmax = floor($angle * 7 / $fontpx * $scale);
                $wmax = min($wmax, 35 * $scale);
                //35
                //$wmax = floor((90*$wmax)/100);
                if ($gen == 0) {
                    $wmax = min($wmax, 17 * $scale);
                }
                //17
                $text = split_align_text($text, $wmax, $rtlstr, 1, $gen);
                $text2 = split_align_text($text2, $wmax, $rtlstr, 0, $gen);
                if ($rtlstr == 1) {
                    persian_log2vis($text);
                    // converts persian, arab and hebrew text from logical to visual and reverses it
                }
                $text .= "\n" . $text2;
                // text angle
                $tangle = 270 - ($deg1 + $angle / 2);
                if ($gen == 0) {
                    $tangle = 0;
                }
                // calculate text position
                $bbox = ImageTtfBbox((double) $fontpx, 0, $fontfile, $text);
                $textwidth = $bbox[4];
                //4
                $deg = $deg1 + 0.44;
                if ($deg2 - $deg1 > 40) {
                    $deg = $deg1 + ($deg2 - $deg1) / 11;
                }
                // 11
                if ($deg2 - $deg1 > 80) {
                    $deg = $deg1 + ($deg2 - $deg1) / 7;
                }
                //  7
                if ($deg2 - $deg1 > 140) {
                    $deg = $deg1 + ($deg2 - $deg1) / 4;
                }
                //  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, (double) $fontpx, $tangle, $tx, $ty, $color, $fontfile, $text);
                $imagemap .= "<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}";
                if (CMS_SPECIFIC == "Joomla") {
                    $imagemap .= "\" href=\"index.php?option=com_humo-gen&amp;task=family&amp;id=" . $treeid[$sosa][2] . "&amp;main_person=" . $treeid[$sosa][3] . "\"";
                } else {
                    $imagemap .= "\" href=\"family.php?id=" . $treeid[$sosa][2] . "&amp;main_person=" . $treeid[$sosa][3] . "\"";
                }
                //NEW - add first spouse to base person's tooltip
                $spousename = "";
                if ($gen == 0 and $treeid[1][2] != "") {
                    // base person and has spouse
                    if ($treeid[1][5] == "F") {
                        $spouse = "fam_man";
                    } else {
                        $spouse = "fam_woman";
                    }
                    $spouse_result = $dbh->query("SELECT " . $spouse . " FROM humo_families\n\t\t\t\t\t\tWHERE fam_tree_id='" . $tree_id . "' AND fam_gedcomnumber='" . $treeid[1][2] . "'");
                    @($spouseDb = $spouse_result->fetch());
                    // fetch() with no parameter deaults to array which is what we want here
                    @($spouse2Db = $db_functions->get_person($spouseDb[$spouse]));
                    $spouse_cls = new person_cls();
                    $spouse_cls->construct($spouse2Db);
                    $spname = $spouse_cls->person_name($spouse2Db);
                    if ($treeid[1][5] == "F") {
                        $spouse_lan = "SPOUSE_MALE";
                    } else {
                        $spouse_lan = "SPOUSE_FEMALE";
                    }
                    if ($spname != "") {
                        $spousename = "\n(" . __($spouse_lan) . ": " . $spname["standard_name"] . ")";
                    }
                }
                $imagemap .= " alt=\"" . $pid . "\" title=\"" . $pid . $spousename . "\">";
            }
            $deg1 -= $angle;
            $deg2 -= $angle;
            $sosa--;
        }
        $rx -= $rw;
        $gen--;
    }
    $imagemap .= "</map>";
    echo $imagemap;
    $image_title = preg_replace("~<.*>~", "", $name) . "   - " . __('RELOAD FANCHART WITH \'VIEW\' BUTTON ON THE LEFT');
    echo "<p align=\"center\" >";
    if (CMS_SPECIFIC == "Joomla") {
        ImagePng($image, CMS_ROOTPATH . "include/fanchart/tmpimg.png");
        $ext = "?" . time();
        // add random string to file to prevent loading from cache and then replacing which is not nice
        echo "<img src=\"index.php?option=com_humo-gen&task=fanimage&format=raw&nochache=" . $ext . "\" width=\"{$fanw}\" height=\"{$fanh}\" border=\"0\" alt=\"{$image_title}\" title=\"{$image_title}\" usemap=\"#fanmap\">";
    } else {
        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;
        echo "<img src=\"include/fanchart/fanimage.php\" width=\"{$fanw}\" height=\"{$fanh}\" border=\"0\" alt=\"{$image_title}\" title=\"{$image_title}\" usemap=\"#fanmap\">";
    }
    echo "</p>\n";
    ImageDestroy($image);
}