buildimage: Convert the XML parser to use XML::LibXML.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
05111a34d5
commit
9e0c990be1
170
tools/buildimage
170
tools/buildimage
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
use XML::Parser;
|
use XML::LibXML;
|
||||||
use MIME::Base64;
|
use MIME::Base64;
|
||||||
use File::Copy;
|
use File::Copy;
|
||||||
|
|
||||||
|
@ -58,6 +58,13 @@ $SIG{"HUP"} = "cleanup";
|
||||||
$SIG{"TERM"} = "cleanup";
|
$SIG{"TERM"} = "cleanup";
|
||||||
$SIG{"__DIE__"} = "cleanup";
|
$SIG{"__DIE__"} = "cleanup";
|
||||||
|
|
||||||
|
my %label =
|
||||||
|
(
|
||||||
|
'ico' => 'icon:(\d*)-(\d*)',
|
||||||
|
'cur' => 'cursor:(\d*)-(\d*)',
|
||||||
|
'bmp' => 'bitmap:(\d*)-(\d*)',
|
||||||
|
);
|
||||||
|
|
||||||
# run a shell command and die on error
|
# run a shell command and die on error
|
||||||
sub shell(@)
|
sub shell(@)
|
||||||
{
|
{
|
||||||
|
@ -65,105 +72,18 @@ sub shell(@)
|
||||||
system(@args) == 0 or die "@args failed: $?";
|
system(@args) == 0 or die "@args failed: $?";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub svg_element_start
|
# add an image to the icon/cursor
|
||||||
|
sub add_image($$)
|
||||||
{
|
{
|
||||||
my($expat, $element, %attr) = @_;
|
my ($file, $size) = @_;
|
||||||
|
|
||||||
# Parse the id for icon/bitmap render directives
|
|
||||||
my $id = $attr{'id'};
|
|
||||||
return unless defined($id);
|
|
||||||
|
|
||||||
my $size = 0;
|
|
||||||
my $depth = 0;
|
|
||||||
my $width = 0;
|
|
||||||
my $height = 0;
|
|
||||||
|
|
||||||
if ($id =~ /hotspot:(\d*)/)
|
|
||||||
{
|
|
||||||
$hotspot[$1] = [ $attr{x}, $attr{y} ];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if($ext eq "ico") {
|
|
||||||
return unless $id =~ /icon:(\d*)-(\d*)/;
|
|
||||||
$size = $1;
|
|
||||||
$depth = $2;
|
|
||||||
} elsif($ext eq "cur") {
|
|
||||||
return unless $id =~ /cursor:(\d*)-(\d*)/;
|
|
||||||
$size = $1;
|
|
||||||
$depth = $2;
|
|
||||||
} elsif($ext eq "bmp") {
|
|
||||||
return unless $id =~ /bitmap:(\d*)-(\d*)/;
|
|
||||||
$size = $1;
|
|
||||||
$depth = $2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return unless defined($size) and defined($depth);
|
|
||||||
|
|
||||||
warn "Unexpected depth" unless
|
|
||||||
$depth == 1 or $depth == 4 or $depth == 8 or $depth == 24 or $depth == 32;
|
|
||||||
my $pngFileName = "$outName-$size-$depth.png";
|
|
||||||
|
|
||||||
if($element eq "svg") {
|
|
||||||
|
|
||||||
if ($ext eq "bmp") {
|
|
||||||
if ($depth == 24) {
|
|
||||||
shell $convert, $renderedSVGFileName, "+matte", $outFileName;
|
|
||||||
} else {
|
|
||||||
shell $convert, $renderedSVGFileName, $outFileName;
|
|
||||||
}
|
|
||||||
cleanup();
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
# The whole file is tagged
|
|
||||||
$pngFileName = $renderedSVGFileName;
|
|
||||||
|
|
||||||
} elsif($element eq "rect") {
|
|
||||||
|
|
||||||
# Extract SVG vector images
|
|
||||||
my $x = $attr{'x'};
|
|
||||||
my $y = $attr{'y'};
|
|
||||||
$width = $attr{'width'};
|
|
||||||
$height = $attr{'height'};
|
|
||||||
|
|
||||||
if(defined($x) and defined($y)) {
|
|
||||||
if($x =~ /\d*/ and $y =~ /\d*/) {
|
|
||||||
shell $convert, $renderedSVGFileName, "-crop", "${width}x${height}+$x+$y", "-depth", $depth, $pngFileName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} elsif($element eq "image" ) {
|
|
||||||
|
|
||||||
# Extract Base64 encoded PNG data to files
|
|
||||||
my $xlinkHref = $attr{'xlink:href'};
|
|
||||||
if(defined($xlinkHref)) {
|
|
||||||
$xlinkHref =~ /data:image\/png;base64(.*)/;
|
|
||||||
my $imageEncodedData = $1;
|
|
||||||
if(defined $imageEncodedData) {
|
|
||||||
open(FILE, '>' . $pngFileName) or die "$!";
|
|
||||||
print FILE decode_base64($imageEncodedData);
|
|
||||||
close FILE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defined $hotspot[$size])
|
if (defined $hotspot[$size])
|
||||||
{
|
{
|
||||||
my @coords = @{$hotspot[$size]};
|
my @coords = @{$hotspot[$size]};
|
||||||
push @icotool_args, "--hotspot-x=$coords[0]", "--hotspot-y=$coords[1]";
|
push @icotool_args, "--hotspot-x=$coords[0]", "--hotspot-y=$coords[1]";
|
||||||
}
|
}
|
||||||
|
push @icotool_args, $size >= 128 ? "--raw=$file" : $file;
|
||||||
if ($width >= 128 && $height >= 128)
|
push @pngFiles, $file;
|
||||||
{
|
|
||||||
push @icotool_args, "--raw=$pngFileName";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
push @icotool_args, $pngFileName;
|
|
||||||
}
|
|
||||||
push @pngFiles, $pngFileName;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Render the SVG image
|
# Render the SVG image
|
||||||
|
@ -175,9 +95,67 @@ push(@rsvgCmd, $renderedSVGFileName);
|
||||||
shell @rsvgCmd;
|
shell @rsvgCmd;
|
||||||
|
|
||||||
# Render the images in the SVG
|
# Render the images in the SVG
|
||||||
my $parser = new XML::Parser(
|
my $xml = XML::LibXML->load_xml( location => $svgFileName );
|
||||||
Handlers => {Start => \&svg_element_start});
|
my $xc = XML::LibXML::XPathContext->new($xml);
|
||||||
$parser->parsefile("$svgFileName");
|
$xc->registerNs('x', 'http://www.w3.org/2000/svg');
|
||||||
|
|
||||||
|
if ($ext eq "bmp")
|
||||||
|
{
|
||||||
|
foreach my $element ($xc->findnodes("/x:svg"))
|
||||||
|
{
|
||||||
|
next unless $element->{id} =~ /bitmap:(\d*)-(\d*)/;
|
||||||
|
my $size = $1;
|
||||||
|
my $depth = $2;
|
||||||
|
if ($depth == 24) {
|
||||||
|
shell $convert, $renderedSVGFileName, "+matte", $outFileName;
|
||||||
|
} else {
|
||||||
|
shell $convert, $renderedSVGFileName, $outFileName;
|
||||||
|
}
|
||||||
|
cleanup();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# fetch hotspot rectangles for the various sizes
|
||||||
|
|
||||||
|
if ($ext eq "cur")
|
||||||
|
{
|
||||||
|
foreach my $element ($xc->findnodes("/x:svg/x:rect"))
|
||||||
|
{
|
||||||
|
next unless $element->{id} =~ /hotspot:(\d*)/;
|
||||||
|
$hotspot[$1] = [ $element->{x}, $element->{y} ];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# extract rectangles from the rendered svg
|
||||||
|
|
||||||
|
foreach my $element ($xc->findnodes("/x:svg/*[\@id]"))
|
||||||
|
{
|
||||||
|
next unless $element->{id} =~ /$label{$ext}/;
|
||||||
|
my $size = $1;
|
||||||
|
my $depth = $2;
|
||||||
|
warn "Unexpected depth" unless
|
||||||
|
$depth == 1 or $depth == 4 or $depth == 8 or $depth == 24 or $depth == 32;
|
||||||
|
my $file = "$outName-$size-$depth.png";
|
||||||
|
|
||||||
|
my $x = $element->{x};
|
||||||
|
my $y = $element->{y};
|
||||||
|
my $width = $element->{width};
|
||||||
|
my $height = $element->{height};
|
||||||
|
if ($element->{'xlink:href'})
|
||||||
|
{
|
||||||
|
# extract base64-encoded png image
|
||||||
|
(my $data = $element->{'xlink:href'}) =~ s/data:image\/png;base64//;
|
||||||
|
open FILE, ">$file" or die "$!";
|
||||||
|
print FILE decode_base64($data);
|
||||||
|
close FILE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
shell $convert, $renderedSVGFileName, "-crop", "${width}x${height}+$x+$y", "-depth", $depth, $file;
|
||||||
|
}
|
||||||
|
add_image( $file, $size );
|
||||||
|
}
|
||||||
|
|
||||||
die "no render directive found in $svgFileName" unless @pngFiles;
|
die "no render directive found in $svgFileName" unless @pngFiles;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue