#!/usr/bin/perl -w
# -*- Mode: perl; indent-tabs-mode: nil; c-basic-offset: 4  -*-
#############################################################################
## Copyright (C) 2008-2009 Rodney Dawes
##
## Authors: Rodney Dawes <dobey@gnome.org>
##
## This program is free software: you can redistribute it and/or modify it
## under the terms of the GNU General Public License version 2, as published
## by the Free Software Foundation.
##
## This program is distributed in the hope that it will be useful, but
## WITHOUT ANY WARRANTY; without even the implied warranties of
## MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
## PURPOSE.  See the GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License along
## with this program.  If not, see <http://www.gnu.org/licenses/>.

use strict;
use XML::Simple;
use Getopt::Long;

my $PACKAGE = "icontool";
my $VERSION = "0.1.0";

my $inkscape = "inkscape";
my $sizeonly;
my $outdir = "";
my $dirall;

############################################################################
my @default_getopt_config = ("permute", "pass_through", "bundling",
			     "no_auto_abbrev", "no_ignore_case");

Getopt::Long::Configure (@default_getopt_config);
GetOptions ("size|s=s" => \$sizeonly,
            "inkscape|i=s" => \$inkscape,
            "output-dir|o=s" => \$outdir,
            "directory|d=s" => \$dirall);

############################################################################

$outdir =~ s|[/]?$|/|g if ($outdir ne "");

sub render_icons {
    my $filename = shift;

    my $svgdata = XML::Simple::XMLin ($filename,
				      keyattr => [ qw() ],
				      forcearray => [ qw(g rect text) ]);

    foreach my $icon (@{$svgdata->{g}}) {
	my $name;
	my $context;

	foreach my $plate (@{$icon->{g}}) {
	    if (defined $plate->{'inkscape:label'} &&
		$plate->{'inkscape:label'} =~ m/plate(.*)/) {

                # Error out if the 'plate' layer is visible
                # This is to prevent background squares from appearing
                # inside the rendered PNG files
                if (defined $plate->{style} &&
                    $plate->{style} ne "display:none") {
                    die "ERROR: $filename: Plate layer not hidden.\n";
                }

                # Get the icon's name and context so we can render it
                # in the right location on disk
		foreach my $text (@{$plate->{text}}) {
		    if (defined $text->{'inkscape:label'} &&
			$text->{'inkscape:label'} eq "icon-name") {
			$name = $text->{tspan}->{content};
		    } elsif (defined $text->{'inkscape:label'} &&
			$text->{'inkscape:label'} eq "context") {
			$context = $text->{tspan}->{content};
		    }
		}

                # Grab the rectangle inside the plate and tell
                # Inkscape to render the area to our PNG file
		foreach my $box (@{$plate->{rect}}) {
		    if (defined $box->{'inkscape:label'}) {
			my $size = $box->{'inkscape:label'};
			my $dir = "$outdir$size/$context";

                        # Skip this box if the size isn't the requested size
                        next if (defined $sizeonly && $size ne $sizeonly);

			if (! -d $dir) {
			    system ("mkdir -p $dir");
			}

                        # Only redirect STDOUT as STDERR is useful here
			my $cmd = "$inkscape -i $box->{id} -e $dir/$name.png $filename > /dev/null";

                        # Print the context/name.png string to STDOUT
                        # We are doing this until a better cache method can
                        # be implemented, to avoid having to use redirection
                        print "$context/$name.png\n";
			system ($cmd);
		    }
		}
	    }
	}
    }
}

sub usage {
    print "Usage: icontool-render [OPTIONS] <SVGFILE>

  -d, --directory=<dir>     Render all SVGs in <dir>
  -i, --inkscape=<path>     Path to inkscape binary to use
  -o, --output=<dirname>    Directory to output PNGs to
  -s, --size=<size>         Size to render from <SVGFILE>

";

    exit 1;
}

if (defined $ARGV[0]) {
    render_icons ($ARGV[0]);
} elsif (defined $dirall) {
    opendir (DIR, $dirall) || die ("ERROR: Failed to open directory: $dirall");
    my @filelist = readdir (DIR);
    closedir (DIR);

    foreach my $file (@filelist) {
        next if ($file eq "." || $file eq "..");
        render_icons ("$dirall/$file") if ($file =~ m/^(.*).svg[z]?$/);
    }
} else {
    usage ();
}
