/**
* 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;
}