#!/usr/bin/perl
#
# Simple "little language" for building Reed-Kellogg diagrams
# 
# We translate a simple line-oriented input format into .svg
# 
# General notion of input:
#
# ID TYPE x y string
#
# "ID" is an arbitrary identifier used to recover calculated position values later on
# "TYPE" is the kind of diagram component, like "htext" or "otext"
# "x" and "y" are the starting x and y position in svg coordinates
#     (note that these run left-to-right and top-to-bottom
#           from an origin in the upper left corner of the figure)
#
# We are starting with
print "<svg width=\"20cm\" height=\"10cm\" version=\"1.1\">\n";
# and using
#    <text
#     font-family="monospace" 
#     style="font-size:8;" letter-spacing="-0.6pt"
#      baseline-shift="10%" dx="5.71">
# which (at least on my machine in Adobe intepreter)
#  yields 52.5 characters in 200 units, so charwidth ~ 5.71
$charwidth = sprintf("%.2f",200/52.5);
#
# We leave 1.5 charwidth on each side of each horizontal string,
$hmargin = sprintf("%.2f",1.5*$charwidth);
# and a bit more on the left of oblique strings:
$omargin = sprintf("%.2f", 1.8*$charwidth);
#    and we need about 7 units minimum vertical space, sqrt(2*(7^2)) for modifiers
$vmin = 7; $vsmin = sprintf("%.2f", sqrt(2*($vmin**2)));
#
# post-subject line is 4 units below, 6.5 units above
$subjbelow = 4; $subjabove = 6.5;
# object line is 6.5 units above
$objabove = 6.5;
# indirect object line slants 2.5 charwidths to the right in x and y coords:
$iobjinc = 2.5*$charwidth;

while (<STDIN>){
 chop;
 print "<!-- $_ -->\n";
 if(/^#/){next;}
 @f = split / +/;
 #
 # Type 1: 
 # ID htext x y <string>
 if($f[1] eq "htext" and $#f >= 6){
  $words = join ' ',splice(@f,6);
  $x1 = eval $f[2]; $y1 = eval $f[3];
  $lmargin = eval $f[4]; $rmargin = eval $f[5];
#  print "*****x1 is $x1 after eval of $f[2], y1 is $y1 after eval of $f[3]\n";
  $nchars = length $words; # note problem with multibyte chars...
  $xsize = $charwidth * $nchars + $lmargin + $rmargin;
  $x2 = sprintf("%.2f", $x1+$xsize);
  print "<!-- Horizontal text |$f[0]| from $x1 $y1 to $x2 $y1 ($words) -->\n";
  print "<path d=\"M $x1 $y1 $x2 $y1\" style=\"stroke: gray; fill: none;\" />\n";
  print "<text x=\"$x1\" y=\"$y1\"\n";
  print "\tfont-family=\"monospace\" style=\"font-size:8;\" letter-spacing=\"-0.6pt\"\n";
  print "\tbaseline-shift=\"10%\" dx=\"$lmargin\">\n";
  print "\t$words\n";
  print "\t</text>\n";
  $lastx = $x2; $lasty = $y1;
  $x1{$f[0]} = $x1; $y1{$f[0]} = $y1;
  $x2{$f[0]} = $lastx; $y2{$f[0]} = $lasty;
 }
 #
 # Type 2:
 # ID otext x y <string>
 elsif($f[1] eq "otext" and $#f >= 4){
  $words = join ' ',splice(@f,4); 
  $x1 = eval $f[2]; $y1 = eval $f[3];
#  print "*****x1 is $x1 after eval of $f[2], y1 is $y1 after eval of $f[3]\n";
  $nchars = length $words; # note problem with multibyte chars...
  $xsize = $charwidth * $nchars + $omargin + $charwidth;
  # line at 45 degrees, x and y increment is sqrt(d^2/2)
  $xinc = sprintf("%.2f",sqrt(($xsize**2)/2));
  $x2 = sprintf("%.2f",$x1+$xinc); $y2 = sprintf("%.2f",$y1+$xinc);
  $pid = "P$f[0]";
  print "<!-- Oblique Text |$f[0]| from $x1 $y1 to $x2 $y2 ($words) -->\n";
  print "<path id=\"$pid\" d=\"M $x1 $y1 l $xinc $xinc\" style=\"stroke: gray; fill: none;\" />\n";
  print "<text x=\"$x1\" y=\"$y1\"\n";
  print "\tfont-family=\"monospace\" style=\"font-size:8;\" letter-spacing=\"-0.6pt\"\n";
  print "\tbaseline-shift=\"10%\" dx=\"$omargin\">\n";
  print "<textPath xlink:href=\"#$pid\">$words</textPath>\n";
  print "\t</text>\n";
  $lastx = $x2; $lasty = $y1;
  $x1{$f[0]} = $x1; $y1{$f[0]} = $y1;
  $x2{$f[0]} = $x2; $y2{$f[0]} = $y2;
 }
 #
 # Type 3:
 # ID vtextdown x1 y1 lmargin rmargin string
 if($f[1] eq "vtextdown" and $#f >= 6){
  $words = join ' ',splice(@f,6);
  $x1 = eval $f[2]; $y1 = eval $f[3];
  $lmargin = eval $f[4]; $rmargin = eval $f[5];
#  print "*****x1 is $x1 after eval of $f[2], y1 is $y1 after eval of $f[3]\n";
  $nchars = length $words; # note problem with multibyte chars...
  $xsize = $charwidth * $nchars + $lmargin + $rmargin;
  $x2 = $x1;
  $y2 = sprintf("%.2f", $y1+$xsize);
  $pid = "P$f[0]";
  print "<!-- Vertical text downwards |$f[0]| from $x1 $y1 to $x2 $y2 ($words) -->\n";
  print "<path id=\"$pid\" d=\"M $x1 $y1 $x2 $y2\" style=\"stroke: gray; stroke-dasharray: 2,1; fill: none;\" />\n";
  print "<text x=\"$x1\" y=\"$y1\"\n";
  print "\tfont-family=\"monospace\" style=\"font-size:8;\" letter-spacing=\"-0.6pt\"\n";
  print "\tbaseline-shift=\"15%\" dx=\"$lmargin\">\n";
  print "<textPath xlink:href=\"#$pid\">$words</textPath>\n";
  print "\t</text>\n";
  $lastx = $x2; $lasty = $y2;
  $x1{$f[0]} = $x1; $y1{$f[0]} = $y1;
  $x2{$f[0]} = $x2; $y2{$f[0]} = $y2
 }
 #
 # Type 4:
 # ID vtextup x1 y1 lmargin rmargin string
 if($f[1] eq "vtextup" and $#f >= 6){
  $words = join ' ',splice(@f,6);
  $x1 = eval $f[2]; $y1 = eval $f[3];
  $lmargin = eval $f[4]; $rmargin = eval $f[5];
#  print "*****x1 is $x1 after eval of $f[2], y1 is $y1 after eval of $f[3]\n";
  $nchars = length $words; # note problem with multibyte chars...
  $xsize = $charwidth * $nchars + $lmargin + $rmargin;
  $x2 = $x1;
  $y2 = sprintf("%.2f", $y1-$xsize);
  $pid = "P$f[0]";
  print "<!-- Vertical text upwards |$f[0]| from $x1 $y1 to $x2 $y2 ($words) -->\n";
  print "<path id=\"$pid\" d=\"M $x1 $y1 $x2 $y2\" style=\"stroke: gray; stroke-dasharray: 2,1; fill: none;\" />\n";
  print "<text x=\"$x1\" y=\"$y1\"\n";
  print "\tfont-family=\"monospace\" style=\"font-size:8;\" letter-spacing=\"-0.6pt\"\n";
  print "\tbaseline-shift=\"15%\" dx=\"$lmargin\">\n";
  print "<textPath xlink:href=\"#$pid\">$words</textPath>\n";
  print "\t</text>\n";
  $lastx = $x2; $lasty = $y2;
  $x1{$f[0]} = $x1; $y1{$f[0]} = $y1;
  $x2{$f[0]} = $x2; $y2{$f[0]} = $y2
 }
 #
 # Type 5:
 # ID line x1 y1 x2 y2
 #     line from arbitrary point to arbitrary point
 #     note that y origin is upper left corner...
 elsif($f[1] eq "line" and $#f == 5){
  $x1 = eval $f[2]; $y1 = eval $f[3]; $x2 = eval $f[4]; $y2 = eval $f[5];
  print "<!-- line |$f[0]| from $x1 $y1 to $x2 $y2 -->\n";
  print "<path d=\"M $x1 $y1 $x2 $y2\" style=\"stroke: gray; fill: none;\" />\n";
  $x1{$f[0]} = $x1; $y1{$f[0]} = $y1;
  $x2{$f[0]} = $x2; $y2{$f[0]} = $y2;

 } 
}
print "</svg>\n";

 

