User:3247's Image Wizard/Scripts/create mvg.pl

 #!/usr/bin/perl
 #
 # create_mvg.pl -  Create line numbers of Munich U-Bahn, bus and tram
 # Copyright (C) 2006 Claus Faerber <claus@faerber.name>
 
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
 # the Free Software Foundation; either version 2 of the License, or (at
 # your option) any later version.
 # 
 # This program is distributed in the hope that it will be useful, but
 # WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY 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, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 # 02110-1301, USA.
 
 # As a special exception, permission is granted to include the
 # source code of this program into a document and copy, distribute
 # and/or modify that document under the terms of the GNU Free
 # Documentation License, Version 1.2 or any later version
 # published by the Free Software Foundation; with no Invariant
 # Sections, no Front-Cover Texts, and no Back-Cover Texts. 
 
 # If you write modifications of your own for this software, it is
 # your choice whether to permit this exception to apply to your
 # modifications. If you do not wish that, delete this exception notice.
 
 use utf8;
 use Data::Dumper;
 use Encode;
 use Math::Trig;
 
 our @data = (
 
   [ 'U1', 'München_U1',	'#270' ],
   [ 'U2', 'München_U2', '#b00' ],
   [ 'U3', 'München_U3', '#e80' ],
   [ 'U4', 'München_U4', '#0ca' ],
   [ 'U5', 'München_U5', '#b70' ],
   [ 'U6', 'München_U6', '#00c' ],
 
   [ 'U7', 'München_U7', '#b70', '#b00' ],
   [ 'U8', 'München_U8', '#b00', '#270' ],
 
   [ 'U8', 'München_U8_MO', '#270', '#b00' ],
 );
 
 our($font_info)=undef;
 our($font_attr)=undef;
 our($font_data)=undef;
 
 our ($x_offset,$y_offset);
 our $path_pos = 0;
 
 sub end_path { if($in_path) { $data .= "Z" if $path_pos; $data .= "\""; $data .= " />\n"; $in_path = undef; }
   $data .= "" if $in_text; $in_text = undef; };
 
 sub start_path {
   return if $in_path;
   $data .= "<path";
     $data .= sprintf " fill=\"%s\"", $path_fill if $path_fill;
     $data .= " fill-rule=\"evenodd\"" if $path_fill;
     $data .= sprintf " stroke=\"%s\"", $path_stroke if $path_stroke;
     $data .= " stroke-width=\"0.25\"" if $path_stroke;
     $data .= " d=\"";
   $in_path = 1; $path_pos = 0;
   spos(undef,undef);
 };
 
 our $scale = 1;
 our($x_offset,$y_offset) = (0,0);
 sub dd { return (shift() * $scale) };
 sub xx { return dd(shift() + $x_offset) };
 sub yy { return dd(shift() + $y_offset) };
 
 our($x_pos,$y_pos)=(undef,undef);
 sub spos { ($x_pos,$y_pos) = @_; };
 sub move { my($pen,$nx,$ny) = @_;
   start_path();
   if($path_pos++ && $pen == 3) { $data .= "Z\n  "; $path_pos = 0; }
   $data .= sprintf "\n    %s %f %f ",
       ($pen == 3 ? 'M' : 'L'), 
       xx($nx), 
       yy($ny) 
     unless $nx==$x_pos && $ny==$y_pos 
       && (defined $x_pos)
       && (defined $y_pos); 
   spos($nx,$ny); 
 };
 
 open FILES, ">files.txt";
 
 foreach (@data)
 {
   my($text,$fn,$col_1,$col_2,$col_t,$col_s) = @{$_};
 
   local ($x_offset,$y_offset) = undef;
 
   print STDERR "$fn.svg\n";
   open STDOUT, ">$fn.svg";
   print '<svg width="1400" height="900" version="1.1" xmlns="http://www.w3.org/2000/svg">',"\n";
   print '<rect width="1400" height="900" fill="'.$col_1.'" />', "\n" unless $col_2;
   print '<path fill="'.$col_1.'" d="M350 300L1400 0 1400 900 0 900Z" />', "\n",
 	'<path fill="'.$col_2.'" d="M0 0L1400 0 0 900Z" />', "\n" if $col_2;
 
   my $font_size = 720;
   open_font('VeraMoBd.svgfont');
 
   my $pathd = write_text(
   	1400/2,
 	900 - (900-$font_size),
 	$font_size,
 	$text);
 
   print '<path fill="'.($col_t||'white').'"';
   print ' fill-rule="evenodd"' if $pathd =~ m/[Zz].*[Zz]/;
   print ' stroke-width="15" stroke="'.$col_s.'"' if $col_s;
   print ' d="'.path_clean($pathd).'" />',"\n";
 
   print '</svg>';
 
   print FILES ">$fn.svg\n";
   print FILES "{{Information\n";
   print FILES "|Description = {{de|Liniennummer der Linie $text der [[:de:U-Bahn München|]].}}".
 	  "{{en|line number sign of line $text of [[:en:Munich U-Bahn|]].}}\n";
   print FILES "|Date = {{subst:CURRENTYEAR}}-{{subst:CURRENTMONTH}}-{{subst:CURRENTDAY2}}\n";
   print FILES "|Source = created with [[:User:3247's Image Wizard/Scripts/create_mvg.pl|create_mvg.pl]]\n";
   print FILES "|Permission = see below\n";
   print FILES "|Author = Claus Färber ([[User:3247|]])\n";
   print FILES "}}\n";
   print FILES "==License==\n";
   print FILES "{{PD-self}}\n";
   print FILES "[[Category:line numbers of Munich U-Bahn]]\n", $type;
 }
 
 exit(0);
 
 sub open_font {
   use XML::Parser;
   new XML::Parser( Handlers => { Start => sub {
   
       my($expat,$name,%attr) = @_;
 
       if($name eq 'font') {
         $font_attr = \%attr;
       }
       elsif($name eq 'missing-glyph') {
         $font_data{'default'} = \%attr;
       }
       elsif($name eq 'glyph') {
         $font_data{$attr{'unicode'}} = \%attr;
       }
       elsif($name eq 'font-face') {
         $font_info = \%attr;
       }
     }} )->parsefile(shift);
 }
 
 our $font_scale;
 
 sub fs_i { return (shift()*1.0) * $font_scale; }
 sub fs { return dd(fs_i(shift)).' '; }
 sub fx { return xx(fs_i(shift) + $text_x).' ';  }
 sub fy { return yy(fs_i(shift)*(-1) + $text_y).' ';  }
 
 sub path_clean
 {
   my $data = shift;
   $data =~ s/,/ /g;
   $data =~ s/\s*([LMTHVCSQAZ])\s*/$1/gei;
   return $data;
 }
 
 sub write_text {
   my ($text_x_x,$text_y_y,$text_size,$string) = @_;
   my $path_data = '';
   
   ($text_x,$text_y) = ($text_x_x,$text_y_y);
 
   my @chars = split //, $string;
   my $last = undef;
   $font_scale = $text_size / ($font_info->{'ascent'} + $font__info->{'descent'});
 
   my $width = 0;
   foreach my $char (@chars) {
     my $char_data = exists $font_data{$char} ? $font_data{$char} : $font_data{'default'};
     $width += ($char_data->{'horiz-adv-x'} || $font_info->{'horiz-adv-x'} || $font_attr->{'horiz-adv-x'}) * $font_scale;
   }
 
   $text_x -= $width / 2.0;
 
   foreach my $char (@chars) {
 	  
     my $char_data = exists $font_data{$char} ? $font_data{$char} : $font_data{'default'};
     my $d = $char_data->{'d'};
 
     $d =~ s/([LMT])\s*([0-9\.-]+)\s*([0-9\.-]+)/ $1.fx($2).fy($3)/ge;
     $d =~ s/([lmt])\s*([0-9\.-]+)\s*([0-9\.-]+)/ $1.fs($2).fs($3)/ge;
     $d =~ s/(H)\s*([0-9\.-]+)/ $1.fx($2)/ge;
     $d =~ s/(V)\s*([0-9\.-]+)/ $1.fy($2)/ge;
     $d =~ s/(h)\s*([0-9\.-]+)/ $1.fs($2)/ge;
     $d =~ s/(v)\s*([0-9\.-]+)/ $1.fs($2)/ge;
     $d =~ s/([C])\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)/ $1.fx($2).fy($3).fx($4).fy($5).fx($6).fy($6)/ge;
     $d =~ s/([c])\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)/ $1.fs($2).fs($3).fs($4).fs($5).fs($6).fs($6)/ge;
     $d =~ s/([SQ])\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)/ $1.fx($2).fy($3).fx($4).fy($5)/ge;
     $d =~ s/([sq])\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)/ $1.fs($2).fs($3).fs($4).fs($5)/ge;
     $d =~ s/([A])\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)/ $1.fs($2).fs($3)."$4 $5 $6".fx($7).fy($8)/ge;
     $d =~ s/([a])\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)\s*([0-9\.-]+)/ $1.fs($2).fs($3)."$4 $5 $6".fs($7).fs($8)/ge;
 
     $path_data .= $d;
     $text_x += ($char_data->{'horiz-adv-x'} || $font_info->{'horiz-adv-x'} || $font_attr->{'horiz-adv-x'}) * $font_scale;
     $last = $_;
   }
 
   return $path_data;
 }