#!/usr/bin/perl -w # Example 7-2. SVG presentations # # First create a directory called slideshow1 # Usage: perl example7-2.pl ./example7-2input.xml # use strict; use XML::Simple; # Used to parse the XML input use XML::Writer; # Used to write the SVG output use IO::Scalar; # Allows you to easily redirect # output from a filehandle to a scalar my $height = 400; my $width = 600; my $titlesize = 36; my $parser = new XML::Simple(); my $slideshow = $parser->XMLin($ARGV[0]); my @slides = dereference($slideshow->{'slide'}); my $dir = $slideshow->{'subdir'}; my $n = 0; # the current slide my $max = $#slides+1; # the total number of slides foreach my $s (@slides) { my $y = 0; $n++; my $textblock = new IO::Scalar; my $writer = XML::Writer->new(OUTPUT=>$textblock); $writer->setDataMode(1); $writer->setDataIndent(2); $writer->startTag('svg', # Start an SVG element width=>"2000", height=> "2000"); $writer->startTag('text', transform => "translate(0, $titlesize)", style => "font-size:$titlesize;". "font-weight:bold;fill:#000000"); $writer->characters($s->{'title'}); $writer->endTag('text'); # Close the text element $y += $titlesize + 10; # track the current y position my @blocks = dereference($s->{'block'}); foreach my $b (@blocks) { if ($b->{'type'} eq 'textline') { $y +=18; $writer->startTag('text', transform => "translate(0, $y)", style => 'font-size:18;fill:#000000'); $writer->characters($b->{'content'}); $writer->endTag('text'); } if ($b->{'type'} eq 'bulletlist') { $y += 4; # give it a little space my @bullets = dereference($b->{'bullet'}); foreach my $bulleted_text (@bullets) { $y += 18; $writer->startTag('text', transform => "translate(20, $y)", style => 'font-size:18;fill:#000000'); print $textblock "• "; # A Unicode bullet $writer->characters($bulleted_text); $writer->endTag('text'); } $y += 4; # Add more space after the list } } $writer->endTag('svg'); # Close the 'text block' SVG graphic $writer->end(); my $scale =1; if ($y > ($height-40)) { $scale = ($height-40)/$y; } my $toplevel = new IO::Scalar; $writer = XML::Writer->new(OUTPUT=>$toplevel); $writer->setDataMode(1); $writer->setDataIndent(2); $writer->startTag('svg', height => $height, width => $width, 'xmlns:xlink'=>"http://www.w3.org/1999/xlink"); $writer->emptyTag('rect', # Draw a colored background height => $height, width => $width, fill => '#EEEEEE'); if (defined($s->{'image'})) { # Add the image $writer->startTag('image', x => 20, y => 20, width => 100, height => 100, 'xlink:href' => $s->{'image'}); $writer->endTag('image'); } $writer->startTag('g', id => 'SlideBody', transform => "translate(130, 20) scale($scale)"); print $toplevel $textblock; $writer->endTag('g'); # End the group my $prev = $n-1; my $next = $n+1; unless ($prev < 1) { # Previous button $writer->startTag('a', 'xlink:href' => "slide$prev.svg" ); $writer->startTag('text', transform => "translate(20, 380)", style => 'font-size:72;fill:#000000'); print $toplevel "←"; # A Unicode left arrow $writer->endTag('text'); $writer->endTag('a'); } unless ($next > $max) { # Next button $writer->startTag('a', 'xlink:href' => "slide$next.svg" ); $writer->startTag('text', transform => "translate(20, 360)", style => 'font-size:72;fill:#000000'); print $toplevel "→"; # A Unicode right arrow $writer->endTag('text'); $writer->endTag('a'); } $writer->endTag('svg'); $writer->end(); open(OUT, ">$dir/slide$n.svg") or die "Couldn't open $dir/slide$n.svg!"; print OUT $toplevel; close OUT; } sub dereference { my $ref = shift; if (ref($ref) eq 'ARRAY') { return (@$ref); } else { return ($ref); } }