RelativePosition() public static method

Returns the [x,y] position that is $pos relative to the top, left, bottom and right. When $text is true, returns [x,y,align right]
public static RelativePosition ( $pos, $top, $left, $bottom, $right, $width, $height, $pad, $text = false )
Example #1
0
 /**
  * Parses a position string, returning x and y coordinates
  */
 protected function ParsePosition($pos, $w = 0, $h = 0, $pad = 0)
 {
     $inner = true;
     $parts = preg_split('/\\s+/', $pos);
     if (count($parts)) {
         // if 'outer' is found after 'inner', it takes precedence
         $parts = array_reverse($parts);
         $inner_at = array_search('inner', $parts);
         $outer_at = array_search('outer', $parts);
         if ($outer_at !== false && ($inner_at === false || $inner_at < $outer_at)) {
             $inner = false;
         }
     }
     if ($inner) {
         $t = $this->pad_top;
         $l = $this->pad_left;
         $b = $this->height - $this->pad_bottom;
         $r = $this->width - $this->pad_right;
         // make sure it fits to keep RelativePosition happy
         if ($w > $r - $l) {
             $w = $r - $l;
         }
         if ($h > $b - $t) {
             $h = $b - $t;
         }
     } else {
         $t = $l = 0;
         $b = $this->height;
         $r = $this->width;
     }
     // ParsePosition is always inside canvas or graph
     $pos .= ' inside';
     return Graph::RelativePosition($pos, $t, $l, $b, $r, $w, $h, $pad);
 }
 /**
  * Draws a label
  */
 protected function DrawLabel($dataset, $index, &$gobject)
 {
     if (is_null($gobject['item']) && empty($gobject['content'])) {
         return '';
     }
     if (is_null($gobject['item'])) {
         // convert to string - numbers will confuse TextSize()
         $content = (string) $gobject['content'];
     } else {
         if (is_callable($this->data_label_callback)) {
             $content = call_user_func($this->data_label_callback, $dataset, $gobject['item']->key, $gobject['item']->value);
             if (is_null($content)) {
                 $content = '';
             }
         } else {
             $content = $gobject['item']->Data('label');
         }
         if (is_null($content)) {
             $content = !is_null($gobject['content']) ? $gobject['content'] : $this->units_before_label . Graph::NumString($gobject['item']->value) . $this->units_label;
         }
     }
     if ($content == '') {
         return '';
     }
     $style = $this->graph->DataLabelStyle($dataset, $index, $gobject['item']);
     if (!is_null($gobject['item'])) {
         $this->ItemStyles($style, $gobject['item']);
     } elseif ($dataset === '_user') {
         $this->UserStyles($style, $gobject);
     }
     $type = $style['type'];
     $font_size = max(4, (double) $style['font_size']);
     $space = (double) $style['space'];
     if ($type == 'box' || $type == 'bubble') {
         $label_pad_x = $style['pad_x'];
         $label_pad_y = $style['pad_y'];
     } else {
         $label_pad_x = $label_pad_y = 0;
     }
     // reasonable approximation of the baseline position
     $text_baseline = $font_size * 0.85;
     // get size of label
     list($tw, $th) = Graph::TextSize($content, $font_size, $style['font_adjust'], $this->encoding, $style['angle'], $font_size);
     $label_w = $tw + $label_pad_x * 2;
     $label_h = $th + $label_pad_y * 2;
     $label_wp = $label_w + $space * 2;
     $label_hp = $label_h + $space * 2;
     $pos = NULL;
     if ($dataset === '_user') {
         // user label, so convert coordinates
         $pos = isset($gobject['position']) ? $gobject['position'] : 'above';
         $xy = $this->coords->TransformCoords($gobject['x'], $gobject['y']);
         $gobject['x'] = $xy[0];
         $gobject['y'] = $xy[1];
     } else {
         // try to get position from item
         if (!is_null($gobject['item'])) {
             $pos = $gobject['item']->Data('data_label_position');
         }
         // find out from graph class where this label should go
         if (is_null($pos)) {
             $pos = $this->graph->DataLabelPosition($dataset, $index, $gobject['item'], $gobject['x'], $gobject['y'], $gobject['width'], $gobject['height'], $label_wp, $label_hp);
         }
     }
     // convert position string to an actual location
     list($x, $y, $anchor, $hpos, $vpos) = $res = Graph::RelativePosition($pos, $gobject['y'], $gobject['x'], $gobject['y'] + $gobject['height'], $gobject['x'] + $gobject['width'], $label_w, $label_h, $space, true);
     // if the position is outside, use the alternative colours
     $colour = $style['colour'];
     $back_colour = $style['back_colour'];
     if (strpos($hpos . $vpos, 'o') !== FALSE) {
         if (!empty($style['altcolour'])) {
             $colour = $style['altcolour'];
         }
         if (!empty($style['back_altcolour'])) {
             $back_colour = $style['back_altcolour'];
         }
     }
     $text = array('font-family' => $style['font'], 'font-size' => $font_size, 'fill' => $colour);
     $label_markup = '';
     // rotation
     if ($style['angle'] != 0) {
         // need text size pre-rotation
         list($tbw, $tbh) = Graph::TextSize($content, $font_size, $style['font_adjust'], $this->encoding, 0, $font_size);
         if ($anchor == 'middle') {
             $text['x'] = $x;
         } elseif ($anchor == 'start') {
             $text['x'] = $x + $label_pad_x + ($tw - $tbw) / 2;
         } else {
             $text['x'] = $x - $label_pad_x - ($tw - $tbw) / 2;
         }
         $text['y'] = $y + $label_h / 2 - $tbh / 2 + $text_baseline;
     } else {
         if ($anchor == 'start') {
             $text['x'] = $x + $label_pad_x;
         } elseif ($anchor == 'end') {
             $text['x'] = $x - $label_pad_x;
         } else {
             $text['x'] = $x;
         }
         $text['y'] = $y + $label_pad_y + $text_baseline;
     }
     // make x right for bounding box
     if ($anchor == 'middle') {
         $x -= $label_w / 2;
     } elseif ($anchor == 'end') {
         $x -= $label_w;
     }
     if ($style['angle'] != 0) {
         // rotate text around centre of box
         $rx = $x + $label_w / 2;
         $ry = $y + $label_h / 2;
         $text['transform'] = "rotate({$style['angle']},{$rx},{$ry})";
         /** DEBUG: text position and rotation point 
             $label_markup .= $this->graph->Element('circle',
               array('cx' => $text['x'], 'cy' => $text['y'], 'r' => 2, 'fill' => '#f0f'));
             $label_markup .= $this->graph->Element('circle',
               array('cx' => $rx, 'cy' => $ry, 'r' => 2));
             **/
     }
     if ($anchor != 'start') {
         $text['text-anchor'] = $anchor;
     }
     if (!empty($style['font_weight']) && $style['font_weight'] != 'normal') {
         $text['font-weight'] = $style['font_weight'];
     }
     $surround = array();
     $element = null;
     if ($type == 'box') {
         $element = $this->BoxLabel($x, $y, $label_w, $label_h, $style, $surround);
     } elseif ($type == 'bubble') {
         $style['tail_direction'] = $this->graph->DataLabelTailDirection($dataset, $index, $hpos, $vpos);
         $element = $this->BubbleLabel($x, $y, $label_w, $label_h, $style, $surround);
     } elseif ($type == 'line') {
         $style['tail_direction'] = $this->graph->DataLabelTailDirection($dataset, $index, $hpos, $vpos);
         $element = $this->LineLabel($x, $y, $label_w, $label_h, $style, $surround);
     }
     // if there is a box or bubble, draw it
     if ($element) {
         $surround['stroke'] = $style['stroke'];
         if ($style['stroke_width'] != 1) {
             $surround['stroke-width'] = (double) $style['stroke_width'];
         }
         // add shadow if not completely transparent
         if ($style['shadow_opacity'] > 0) {
             $shadow = $surround;
             $offset = 2 + floor($style['stroke_width'] / 2);
             $shadow['transform'] = "translate({$offset},{$offset})";
             $shadow['fill'] = $shadow['stroke'] = '#000';
             $shadow['opacity'] = $style['shadow_opacity'];
             $label_markup .= $this->graph->Element($element, $shadow);
         }
         $label_markup .= $this->graph->Element($element, $surround);
     }
     if (!empty($back_colour)) {
         $outline = array('stroke-width' => '3px', 'stroke' => $back_colour, 'stroke-linejoin' => 'round');
         $t1 = array_merge($outline, $text);
         $label_markup .= $this->graph->Text($content, $font_size, $t1);
     }
     $label_markup .= $this->graph->Text($content, $font_size, $text);
     $group = array();
     if (isset($gobject['id']) && !is_null($gobject['id'])) {
         $group['id'] = $gobject['id'];
     }
     // start off hidden?
     if ($gobject['click'] == 'show') {
         $group['opacity'] = 1;
     } elseif ($gobject['click'] == 'hide' || $gobject['fade']) {
         $group['opacity'] = 0;
     }
     $label_markup = $this->graph->Element('g', $group, NULL, $label_markup);
     return $label_markup;
 }
 /**
  * Adds a single guideline and its title to content
  */
 protected function BuildGuideline(&$line, &$lines, &$text, &$path, &$d)
 {
     $length = $this->guideline_length;
     $length_units = $this->guideline_length_units;
     if (isset($line['line'])) {
         $this->UpdateAndUnset($length, $line['line'], 'length');
         $this->UpdateAndUnset($length_units, $line['line'], 'length_units');
     }
     if ($length != 0) {
         if ($line['axis'] == 'x') {
             $h = $length;
         } else {
             $w = $length;
         }
     } elseif ($length_units != 0) {
         if ($line['axis'] == 'x') {
             $h = $length_units * $this->y_axes[$this->main_y_axis]->Unit();
         } else {
             $w = $length_units * $this->x_axes[$this->main_x_axis]->Unit();
         }
     }
     $path_data = $this->GuidelinePath($line['axis'], $line['value'], $line['depth'], $x, $y, $w, $h);
     if (!isset($line['line'])) {
         // no special options, add to main path
         $d .= $path_data;
     } else {
         $line_path = array_merge($path, $line['line'], array('d' => $path_data));
         $lines .= $this->Element('path', $line_path);
     }
     if (!empty($line['title'])) {
         $text_pos = $this->guideline_text_position;
         $text_pad = $this->guideline_text_padding;
         $text_angle = $this->guideline_text_angle;
         $text_align = $this->guideline_text_align;
         $font_size = $this->guideline_font_size;
         $font_adjust = $this->guideline_font_adjust;
         if (isset($line['text'])) {
             $this->UpdateAndUnset($text_pos, $line['text'], 'text_position');
             $this->UpdateAndUnset($text_pad, $line['text'], 'text_padding');
             $this->UpdateAndUnset($text_angle, $line['text'], 'text_angle');
             $this->UpdateAndUnset($text_align, $line['text'], 'text_align');
             $this->UpdateAndUnset($font_adjust, $line['text'], 'font_adjust');
             if (isset($line['text']['font-size'])) {
                 $font_size = $line['text']['font-size'];
             }
         }
         list($text_w, $text_h) = $this->TextSize($line['title'], $font_size, $font_adjust, $this->encoding, $text_angle, $font_size);
         list($x, $y, $text_pos_align) = Graph::RelativePosition($text_pos, $y, $x, $y + $h, $x + $w, $text_w, $text_h, $text_pad, true);
         $t = array('x' => $x, 'y' => $y + $font_size);
         if (empty($text_align) && $text_pos_align != 'start') {
             $t['text-anchor'] = $text_pos_align;
         } else {
             $align_map = array('right' => 'end', 'centre' => 'middle');
             if (isset($align_map[$text_align])) {
                 $t['text-anchor'] = $align_map[$text_align];
             }
         }
         if ($text_angle != 0) {
             $rx = $x + $text_h / 2;
             $ry = $y + $text_h / 2;
             $t['transform'] = "rotate({$text_angle},{$rx},{$ry})";
         }
         if (isset($line['text'])) {
             $t = array_merge($t, $line['text']);
         }
         $text .= $this->Text($line['title'], $font_size, $t);
     }
 }