Permalink
Browse files

Use <g> to simplify SVG and fix styling. Add name attribute file mech…

…anism.

Place rect and text into a g block.
Replace the duplicated rect and text onmouseover with a single g onmouseover.
This reduces the size of the SVG file. It also fixes the loss of the
black border when mousing over the text.

An external file can be used to specify attributes for individual
functions. So, for example, functions can be given links and colors.
  • Loading branch information...
1 parent daa7cf6 commit da9a4bb5aedee0e3a5556e0f173bdc1961f72f17 @timbunce timbunce committed Mar 18, 2013
Showing with 54 additions and 6 deletions.
  1. +54 −6 flamegraph.pl
View
@@ -64,6 +64,7 @@
my $titletext = "Flame Graph"; # centered heading
my $nametype = "Function:"; # what are the names in the data?
my $countname = "samples"; # what are the counts in the data?
+my $nameattrfile; # file holding function attributes
GetOptions(
'fonttype=s' => \$fonttype,
@@ -74,6 +75,7 @@
'title=s' => \$titletext,
'nametype=s' => \$nametype,
'countname=s' => \$countname,
+ 'nameattr=s' => \$nameattrfile,
) or exit 1;
@@ -84,6 +86,19 @@
my $timemax = 0;
my $depthmax = 0;
my %Events;
+my %nameattr;
+
+if ($nameattrfile) {
+ # The name-attribute file format is a function name followed by a tab then
+ # a sequence of tab separated name=value pairs.
+ open my $attrfh, $nameattrfile or die "Can't read $nameattrfile: $!\n";
+ while (<$attrfh>) {
+ chomp;
+ my ($funcname, $attrstr) = split /\t/, $_, 2;
+ die "Invalid format in $nameattrfile" unless defined $attrstr;
+ $nameattr{$funcname} = { map { split /=/, $_, 2 } split /\t/, $attrstr };
+ }
+}
# SVG functions
{ package SVG;
@@ -99,7 +114,7 @@
$self->{svg} .= <<SVG;
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<svg version="1.1" width="$w" height="$h" onload="init(evt)" viewBox="0 0 $w $h" xmlns="http://www.w3.org/2000/svg" >
+<svg version="1.1" width="$w" height="$h" onload="init(evt)" viewBox="0 0 $w $h" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
SVG
}
@@ -113,6 +128,32 @@
return "rgb($r,$g,$b)";
}
+ sub group_start {
+ my ($self, $attr) = @_;
+
+ my @g_attr = map {
+ exists $attr->{$_} ? sprintf(qq/$_="%s"/, $attr->{$_}) : ()
+ } qw(class style onmouseover onmouseout);
+ push @g_attr, $attr->{g_extra} if $attr->{g_extra};
+ $self->{svg} .= sprintf qq/<g %s>\n/, join(' ', @g_attr);
+
+ $self->{svg} .= sprintf qq/<title>%s<\/title>/, $attr->{title}
+ if $attr->{title}; # should be first element within g container
+
+ if ($attr->{href}) {
+ my @a_attr;
+ push @a_attr, sprintf qq/xlink:href="%s"/, $attr->{href} if $attr->{href};
+ push @a_attr, $attr->{a_extra} if $attr->{a_extra};
+ $self->{svg} .= sprintf qq/<a %s>/, join(' ', @a_attr);
+ }
+ }
+
+ sub group_end {
+ my ($self, $attr) = @_;
+ $self->{svg} .= qq/<\/a>\n/ if $attr->{href};
+ $self->{svg} .= qq/<\/g>\n/;
+ }
+
sub filledRectangle {
my ($self, $x1, $y1, $x2, $y2, $fill, $extra) = @_;
$x1 = sprintf "%0.1f", $x1;
@@ -215,8 +256,7 @@ sub flow {
</linearGradient>
</defs>
<style type="text/css">
- rect[rx]:hover { stroke:black; stroke-width:1; }
- text:hover { stroke:black; stroke-width:1; stroke-opacity:0.35; }
+ .func_g:hover { stroke:black; stroke-width:0.5; }
</style>
<script type="text/ecmascript">
<![CDATA[
@@ -267,7 +307,14 @@ sub flow {
$escaped_func =~ s/>/&gt;/g;
$info = "$escaped_func ($samples_txt $countname, $pct%)";
}
- $im->filledRectangle($x1, $y1, $x2, $y2, color("hot"), 'rx="2" ry="2" onmouseover="s(' . "'$info'" . ')" onmouseout="c()"');
+
+ my $nameattr = $nameattr{$func} || {};
+ $nameattr->{class} ||= "func_g";
+ $nameattr->{onmouseover} ||= "s('".$info."')";
+ $nameattr->{onmouseout} ||= "c()";
+ $im->group_start($nameattr);
+
+ $im->filledRectangle($x1, $y1, $x2, $y2, color("hot"), 'rx="2" ry="2"');
if ($width > 50) {
my $chars = int($width / (0.7 * $fontsize));
@@ -276,9 +323,10 @@ sub flow {
$text =~ s/&/&amp;/g;
$text =~ s/</&lt;/g;
$text =~ s/>/&gt;/g;
- $im->stringTTF($black, $fonttype, $fontsize, 0.0, $x1 + 3, 3 + ($y1 + $y2) / 2, $text, "",
- 'onmouseover="s(' . "'$info'" . ')" onmouseout="c()"');
+ $im->stringTTF($black, $fonttype, $fontsize, 0.0, $x1 + 3, 3 + ($y1 + $y2) / 2, $text, "");
}
+
+ $im->group_end($nameattr);
}
print $im->svg;

0 comments on commit da9a4bb

Please sign in to comment.