]> git.ipfire.org Git - ipfire-2.x.git/commitdiff
rrd graphs: Switch to SVG output format
authorLeo-Andres Hofmann <hofmann@leo-andres.de>
Wed, 4 Aug 2021 11:01:06 +0000 (13:01 +0200)
committerArne Fitzenreiter <arne_f@ipfire.org>
Sun, 5 Sep 2021 17:52:16 +0000 (17:52 +0000)
The vector graphics can be scaled without becoming blurred.

Signed-off-by: Leo-Andres Hofmann <hofmann@leo-andres.de>
Reviewed-by: Bernhard Bitsch <bbitsch@ipfire.org>
Tested-by: Bernhard Bitsch <bbitsch@ipfire.org>
Signed-off-by: Arne Fitzenreiter <arne_f@ipfire.org>
config/cfgroot/graphs.pl
html/cgi-bin/getrrdimage.cgi

index 441d4c483a46a56335dba96d8a83b0f7defae402..02341eb459d04ca9dd37f4d749729f86c4bc324c 100644 (file)
@@ -40,7 +40,7 @@ my $ERROR;
 
 my @GRAPH_ARGS = (
        # Output format
-       "--imgformat", "PNG",
+       "--imgformat", "SVG",
 
        # No border
        "--border", "0",
index c08247c571965ecd51428ba1032b6938ad533895..92f8b585daecc6ea554a29cc15ba3cdffdc95d11 100644 (file)
@@ -21,8 +21,7 @@
 
 use strict;
 use URI;
-use GD;
-use GD::Text::Wrap;
+use Text::Wrap;
 use experimental 'smartmatch';
 
 # debugging
@@ -52,7 +51,7 @@ my $range = lc $query{'range'}; # lower case
 # Check parameters
 unless(($origin =~ /^\w+?\.cgi$/) && ($graph =~ /^[\w\-.,; ]+?$/) && ($range ~~ @Graphs::time_ranges)) {
        # Send HTTP headers
-       _start_png_output();
+       _start_svg_output();
        
        _print_error("URL parameters missing or malformed.");   
        exit;
@@ -76,7 +75,7 @@ unless(($origin ~~ @supported_origins) || ($origin eq "getrrdimage.cgi")) {
 
 ### Create graphs ###
 # Send HTTP headers
-_start_png_output();
+_start_svg_output();
 
 # Graphs are first grouped by their origin.
 # This is because some graph categories require special parameter handling.
@@ -204,46 +203,62 @@ if($graphstatus) {
 
 ###--- Internal functions ---###
 
-# Send HTTP headers and switch to binary output
+# Send HTTP headers
 # (don't print any non-image data to STDOUT afterwards)
-sub _start_png_output {
+sub _start_svg_output {
        print "Cache-Control: no-cache, no-store\n";
-       print "Content-Type: image/png\n";
+       print "Content-Type: image/svg+xml\n";
        print "\n"; # End of HTTP headers
-       binmode(STDOUT);
 }
 
-# Print error message to PNG output
+# Print error message to SVG output
 sub _print_error {
        my ($message) = @_;
-       $message = "- Error -\n \n$message";
-
-       # Create new image with the same size as a graph
-       my $img = GD::Image->new($Graphs::image_size{'width'}, $Graphs::image_size{'height'});
-       $img->interlaced('true');
-
-       # Basic colors
-       my $color_background = $img->colorAllocate(255, 255, 255);
-       my $color_border = $img->colorAllocate(255, 0, 0);
-       my $color_text = $img->colorAllocate(0, 0, 0);
 
-       # Background and border
-       $img->setThickness(2);
-       $img->filledRectangle(0, 0, $img->width, $img->height, $color_background);
-       $img->rectangle(10, 10, $img->width - 10, $img->height - 10, $color_border);
-       
-       # Draw message with line-wrap
-       my $textbox = GD::Text::Wrap->new($img,
-               text => $message,
-               width => ($img->width - 50),
-               color => $color_text,
-               align => 'center',
-               line_space => 5,
-               preserve_nl => 1
+       # Prepare image options
+       my %img = (
+               'width' => $Graphs::image_size{'width'},
+               'height' => $Graphs::image_size{'height'},
+               'text_center' => int($Graphs::image_size{'width'} / 2),
+               'line_height' => 20,
+               'font_family' => "DejaVu Sans, Helvetica, sans-serif" # Matching the IPFire theme
        );
-       $textbox->set_font(gdLargeFont);
-       $textbox->draw(25, 25);
 
-       # Get PNG output
-       print $img->png;
+       # Line-wrap message to fit image (adjust to font width if necessary)
+       local($Text::Wrap::columns) = int($img{'width'} / 10);
+       $message = wrap('', '', $message);
+
+       # Create new image with fixed background and border
+       print <<END
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="$img{'width'}px" height="$img{'height'}px" viewBox="0 0 $img{'width'} $img{'height'}" version="1.1" xmlns="http://www.w3.org/2000/svg">
+       <!-- Background -->
+       <rect width="100%" height="100%" fill="white"/>
+       <rect width="100%" height="100%" fill="none" stroke="red" stroke-width="2" transform="scale(0.95)" transform-origin="center"/>
+       <!-- Message -->
+       <text x="$img{'text_center'}" y="50" font-size="20" font-family="$img{'font_family'}" text-anchor="middle">- $Lang::tr{'error'} -</text>
+       <text x="$img{'text_center'}" y="90" font-size="14" font-family="$img{'font_family'}" text-anchor="middle">
+END
+;
+
+       # Print message lines
+       my $shift_y = 0; # Shifts text along y-axis
+       foreach my $line (split(/\n/, $message)) {
+               if($line ne "") { # Don't create empty tspan elements
+                       print <<END
+               <tspan x="$img{'text_center'}" dy="$shift_y">$line</tspan>
+END
+;
+                       $shift_y = $img{'line_height'};
+               } else { # Create blank lines by summing up unused line height
+                       $shift_y += $img{'line_height'};
+               }
+       }
+
+       # Finish SVG output
+       print <<END
+       </text>
+</svg>
+END
+;
 }