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
172
tools/buildimage
172
tools/buildimage
|
@ -20,7 +20,7 @@
|
|||
|
||||
use strict;
|
||||
use warnings;
|
||||
use XML::Parser;
|
||||
use XML::LibXML;
|
||||
use MIME::Base64;
|
||||
use File::Copy;
|
||||
|
||||
|
@ -58,6 +58,13 @@ $SIG{"HUP"} = "cleanup";
|
|||
$SIG{"TERM"} = "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
|
||||
sub shell(@)
|
||||
{
|
||||
|
@ -65,105 +72,18 @@ sub shell(@)
|
|||
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) = @_;
|
||||
|
||||
# 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;
|
||||
}
|
||||
|
||||
my ($file, $size) = @_;
|
||||
|
||||
if (defined $hotspot[$size])
|
||||
{
|
||||
my @coords = @{$hotspot[$size]};
|
||||
push @icotool_args, "--hotspot-x=$coords[0]", "--hotspot-y=$coords[1]";
|
||||
}
|
||||
|
||||
if ($width >= 128 && $height >= 128)
|
||||
{
|
||||
push @icotool_args, "--raw=$pngFileName";
|
||||
}
|
||||
else
|
||||
{
|
||||
push @icotool_args, $pngFileName;
|
||||
}
|
||||
push @pngFiles, $pngFileName;
|
||||
push @icotool_args, $size >= 128 ? "--raw=$file" : $file;
|
||||
push @pngFiles, $file;
|
||||
}
|
||||
|
||||
# Render the SVG image
|
||||
|
@ -175,9 +95,67 @@ push(@rsvgCmd, $renderedSVGFileName);
|
|||
shell @rsvgCmd;
|
||||
|
||||
# Render the images in the SVG
|
||||
my $parser = new XML::Parser(
|
||||
Handlers => {Start => \&svg_element_start});
|
||||
$parser->parsefile("$svgFileName");
|
||||
my $xml = XML::LibXML->load_xml( location => $svgFileName );
|
||||
my $xc = XML::LibXML::XPathContext->new($xml);
|
||||
$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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue