3 # Render SVG files containing one or more images into an ICO or BMP.
5 # Copyright (C) 2010 Joel Holdsworth
7 # This library is free software; you can redistribute it and/or
8 # modify it under the terms of the GNU Lesser General Public
9 # License as published by the Free Software Foundation; either
10 # version 2.1 of the License, or (at your option) any later version.
12 # This library is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 # Lesser General Public License for more details.
17 # You should have received a copy of the GNU Lesser General Public
18 # License along with this library; if not, write to the Free Software
19 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 # Parse the parameters
28 my $svgFileName = $ARGV[0];
29 my $outFileName = $ARGV[1];
31 die "Cannot open SVG file" unless defined($svgFileName);
32 die "Cannot open output file" unless defined($outFileName);
34 $outFileName =~ m/(.*)\.(.*)/;
37 die "Only BMP, ICO and CUR outputs are supported" unless $ext eq "bmp" or $ext eq "ico" or $ext eq "cur";
39 my $renderedSVGFileName = "$svgFileName.png";
42 # Get the programs from the environment variables
43 my $convert = $ENV{"CONVERT"} || "convert";
44 my $rsvg = $ENV{"RSVG"} || "rsvg";
45 my @icotool_args = ($ENV{"ICOTOOL"} || "icotool", "--create",
46 $ext eq "cur" ?
"--cursor" : "--icon", "-o", $outFileName);
51 unlink $renderedSVGFileName;
52 unlink $_ foreach(@pngFiles);
55 $SIG{"INT"} = "cleanup";
56 $SIG{"HUP"} = "cleanup";
57 $SIG{"TERM"} = "cleanup";
58 $SIG{"__DIE__"} = "cleanup";
60 # run a shell command and die on error
64 system(@args) == 0 or die "@args failed: $?";
69 my($expat, $element, %attr) = @_;
71 # Parse the id for icon/bitmap render directives
73 return unless defined($id);
82 push @icotool_args, "--hotspot-x=$attr{x}", "--hotspot-y=$attr{y}";
87 return unless $id =~ /icon:(\d*)-(\d*)/;
90 } elsif($ext eq "cur") {
91 return unless $id =~ /cursor:(\d*)-(\d*)/;
94 } elsif($ext eq "bmp") {
95 return unless $id =~ /bitmap:(\d*)-(\d*)/;
100 return unless defined($size) and defined($depth);
102 warn "Unexpected depth" unless
103 $depth == 1 or $depth == 4 or $depth == 8 or $depth == 24 or $depth == 32;
104 my $pngFileName = "$outName-$size-$depth.png";
106 if($element eq "svg") {
110 shell
$convert, $renderedSVGFileName, "+matte", $outFileName;
112 shell
$convert, $renderedSVGFileName, $outFileName;
118 # The whole file is tagged
119 $pngFileName = $renderedSVGFileName;
121 } elsif($element eq "rect") {
123 # Extract SVG vector images
126 $width = $attr{'width'};
127 $height = $attr{'height'};
129 if(defined($x) and defined($y)) {
130 if($x =~ /\d*/ and $y =~ /\d*/) {
131 shell
$convert, $renderedSVGFileName, "-crop", "${width}x${height}+$x+$y", "-depth", $depth, $pngFileName;
134 } elsif($element eq "image" ) {
136 # Extract Base64 encoded PNG data to files
137 my $xlinkHref = $attr{'xlink:href'};
138 if(defined($xlinkHref)) {
139 $xlinkHref =~ /data:image\/png
;base64
(.*)/;
140 my $imageEncodedData = $1;
141 if(defined $imageEncodedData) {
142 open(FILE
, '>' . $pngFileName) or die "$!";
143 print FILE decode_base64
($imageEncodedData);
151 if ($width >= 128 && $height >= 128)
153 push @icotool_args, "--raw=$pngFileName";
157 push @icotool_args, $pngFileName;
159 push @pngFiles, $pngFileName;
162 # Render the SVG image
164 push(@rsvgCmd, $rsvg);
165 push(@rsvgCmd, $svgFileName);
166 push(@rsvgCmd, "-o") if ($rsvg eq "rsvg-convert");
167 push(@rsvgCmd, $renderedSVGFileName);
170 # Render the images in the SVG
171 my $parser = new XML
::Parser
(
172 Handlers
=> {Start
=> \
&svg_element_start
});
173 $parser->parsefile("$svgFileName");
175 die "no render directive found in $svgFileName" unless @pngFiles;
179 # Delete the intermediate images