1 #!/usr/bin/perl
3 # This is a script to render a plain text outline file into SVG.
4 #
5 # Copyright (C) 2006 Bryce Harrington. Available for use under the GPL.
6 #
7 # Usage: outline2svg.pl <presentation.outline> [ --master=template.svg ]
8 #
9 use strict;
10 use Getopt::Long;
11 use Pod::Usage;
12 use SVG::Parser;
13 use vars qw($VERSION);
14 $VERSION = '1.00';
16 our $opt_version = 0;
17 our $opt_help = 0;
18 our $opt_man = 0;
19 our $opt_debug = 1;
20 our $opt_master = "template.svg";
21 our $opt_width = 300;
22 our $opt_height = 200;
23 our $opt_x_margin = 100;
24 our $opt_y_margin = 150;
25 our $opt_font = 'Arial';
26 our $opt_font_family = 'Arial';
27 our $opt_font_size = 24;
29 Getopt::Long::Configure ("bundling", "no_ignore_case");
30 GetOptions(
31 "version|V", # Prints the version and exits
32 "help|h", # Prints a brief help message
33 "man", # Prints a manual page (detailed help)
34 "debug|D=i", # Prints debug messages
35 "master|m=s", # Master template to use
36 "width|w=i", # Page width
37 "height|h=i", # Page height
38 "x-margin|x=i", # Horizontal offset
39 "y-margin|y=i", # Vertical offset
40 "font=s", # Default font name
41 "font-family=s", # Default font family
42 "font-size=s", # Default font size
43 );
45 my $i = 0;
46 my $page = 0;
47 my $filename;
48 my $svg;
50 sub start_page {
51 my $title = shift;
52 end_page();
54 $filename = sprintf("%02d_$title.svg", $page);
55 $filename =~ s/\s+/_/g;
56 $filename =~ s#/#-#g;
57 $filename =~ s#[^\w\:\.\,\+\-]+#_#g;
59 $svg = SVG::Parser->new()->parsefile($opt_master);
60 $svg->comment('Generated by outline2svg');
61 $page++;
62 $i = 0;
63 }
65 sub end_page {
66 if (defined($svg) && defined($filename)) {
67 open(FILE, ">$filename")
68 or die "Could not open '$filename' for writing: $!\n";
69 my $contents = $svg->xmlify();
70 # Work-around bug in SVG::Parser
71 $contents =~ s/�//g;
72 print "$filename\n" if $opt_debug>0;
73 print FILE $contents;
74 close(FILE) || print "Error closing $filename: $!\n";
76 undef $svg;
77 undef $filename;
78 }
79 }
82 my $font = $opt_font;
83 my $font_family = $opt_font_family;
84 my $font_size = $opt_font_size;
85 my $line_spacing = $font_size * 1.5;
87 while (my $line = <>) {
88 chomp($line);
89 $line =~ s/\s+$//; # Trim trailing space
90 my $x = 10;
91 my $style = { 'font' => $font,
92 'font-family' => $font_family,
93 'font-size' => $font_size
94 };
96 # Convert tabs into spaces, otherwise we get errors about invalid char
97 $line =~ s/\t/ /g;
99 # If we've encountered a page marker, increment the page number
100 if ($line =~ /^\* (.*)$/) {
101 my $title = $1;
102 start_page($title);
104 if ($title !~ /^(title|overview)$/i ) {
105 $style->{'font-size'} *= 1.5;
106 $svg->text(id => "title_$i",
107 x => $opt_x_margin,
108 y => $opt_y_margin,
109 'xml:space' => 'preserve',
110 style => $style,
111 )
112 ->cdata($title);
113 }
114 $i++;
116 } elsif (defined($svg)) {
117 my $y = $line_spacing*(1+$i);
119 my $num_leading_spaces = 0;
120 if ($line =~ /^(\s+)/) {
121 $num_leading_spaces = length($1);
123 }
125 if ($num_leading_spaces > 0 &&
126 length($line) > $num_leading_spaces &&
127 length($line) + $num_leading_spaces > 70 &&
128 length($line) + $num_leading_spaces <76 ) {
129 # Looks like user is trying to center this text
130 $line =~ s/^\s+//;
131 $style->{'align'} = 'centered';
132 $style->{'anchor'} = 'middle';
133 $x = $opt_width / 2;
135 } else {
136 while ($line && $line =~ /^\s/) {
137 $line =~ s/^\s//; # Just delete one space at a time
138 $x += 5;
139 }
141 # Create bullets if needed
142 if ($line =~ /^-\s+/) {
143 $line =~ s/^-\s+//;
144 $x += 10;
145 $svg->circle(cx=>$opt_x_margin + $x - ($font_size/2),
146 cy=>$opt_y_margin + $y - ($font_size/3),
147 r=>($font_size/6.0));
148 }
149 }
151 # Convert markup into appropriate SVG-isms
152 $svg->text(id => "text_line_$i",
153 x => $opt_x_margin + $x,
154 y => $opt_y_margin + $y,
155 'xml:space' => 'preserve',
156 style => $style,
157 )
158 ->cdata($line);
159 $i++;
160 }
161 }
162 end_page();
164 #print $svg->xmlify();