Subject: Re: Suggestion: DRAWINGS on newsgroups
      Date: Sat, 28 Aug 1999 03:58:25 GMT
      From: mzenier@netcom.com (Mark Zenier)
 Organization: Netcom
 Newsgroups: sci.electronics.design, sci.electronics.basics, de.sci.electronics
 

In article <9908271957.06ol@lassie.demon.co.uk>,
David Jordan <dave@lassie.demon.co.uk> wrote:
>It's not that difficult, it took me about an hour to come up with a simple
>viewer written in perl. It uses the GD module so you need to invoke it as:
>
>    ngview < file | xv -
>
>There's a module somewhere that interfaces perl with GTK, maybe I'll try
>that so you don't need to intermediate step of using xv.
>
>The program is less than 100 lines and handles the basics of the format, it
>ignores invalid lines and can cope with split polylines. As it's so short I
>could post it here if anybody wants it, it will be useable on a great
>number of machines as all you need is perl and the GD library.

You beat me by a day and about 50 lines.  I'm using classic (I think
it's Version 4) Perl, and producing postscript for Ghostscript to do
the graphics.

>What I would like to see is a complete description of the format (what does
>the initial '1' mean in the polyline, what does the 'M' mean for text...).

The linewidth, 1 (to 10) , and Medium size font.  A lot of it's at
the end of Franz's web page but there remain some picky details.  Stuff
like what the character size (in pixels) is for each font and where the
location of a character string is relative to the starting coordinates,
and what the dot and dash pattersns are need to be resolved.  (And what
the linewidth of 0 in his version 6.0 example means).

CAUTION: NEWER VERSION BELOW!
=-----------------------------------------------------------

#!/usr/bin/perl
#
#       File:           ng2ps.pl
#       Author:         Mark Zenier
#       Description:    A filter to convert Ing. Franz Glaser's NGpaint simple
#                       graphics format for newsgroup postings to level 1
#                       Postscript.
#       Usage:          Perl => Unix and where else it works
#
#                       ng2ps.pl [width] <input >output
#
#                       width (optional) is in Postscript points (72 per inch),
#                               default is 320  about a half pagewidth
#
#       History:        August 28, 1999   Version 1.2
#
#       Bugs:           Dot and Dash sequences are not matched to NGpaint.
#                       Offsets for text from postion are not set.
#                       font sizes are a random guess.
#                       Proposed extensions (arc and relative distances) are
#                       not implemented.
#                       Just about Zero validity checking is done.
#                       shape fill is untested, any color that you like as
#                       long as it's black.
#                       wrapped lines are not supported.
#
#       Features:       Junk at the start of a line is ignored
#
 

        $scale = ($#ARGV >= 0) ?  $ARGV[0]/320 : 1;
        shift;

        %widthstring = (
                1 => " 1 setlinewidth [] 0 setdash\n",
                2 => " 2 setlinewidth [] 0 setdash\n",
                3 => " 3 setlinewidth [] 0 setdash\n",
                4 => " 4 setlinewidth [] 0 setdash\n",
                5 => " 5 setlinewidth [] 0 setdash\n",
                6 => " 6 setlinewidth [] 0 setdash\n",
                7 => " 7 setlinewidth [] 0 setdash\n",
                8 => " 8 setlinewidth [] 0 setdash\n",
                9 => " 9 setlinewidth [] 0 setdash\n",
                10 => " 10 setlinewidth [] 0 setdash\n",
                DS => " 1 setlinewidth [3 2] 0 setdash\n",
                DT => " 1 setlinewidth [2 2] 0 setdash\n",
                DD => " 1 setlinewidth [3 2 1 2] 0 setdash\n"
        );

        %fontoffset = (
                S => " 0 0 rmoveto ",
                M => " 0 0 rmoveto ",
                B => " 0 0 rmoveto "
        );

        $shapefill = "fill ";

        print <<'HDR-HEREDOC-DELIM';
%!PS-Adobe-1.0
%%Pages: (atend)
%%DocumentFonts: Courier
%%EndComments
/NGPSfont /Courier findfont [6 0 0 -6 0 0] makefont def
/NGPMfont /Courier findfont [8 0 0 -8 0 0] makefont def
/NGPLfont /Courier findfont [16 0 0 -16 0 0] makefont def
HDR-HEREDOC-DELIM

# Move coordinate system up by the height, and flop the x-axis, and magnify

        print "0 ", 200*$scale, " translate\n",
                $scale, " -", $scale, " scale\n";

        print <<'HDR-HEREDOC-DELIM';
NGPMfont setfont
%%EndProlog
HDR-HEREDOC-DELIM

        $currentwidth = "?";
        $currentfont = "M";

while(<>)
{
        if(/L\([^)]*\)/)
        {
                print  "% ", $_ ;
                s/^.*L\(//;
                ($newwidth, $x1, $y1, $endpairs) = split /;/, $_, 4;
                if($newwidth != $currentwidth) { print $widthstring{$newwidth} }
                $currentwidth = $newwidth;
                print $x1, " ", $y1, " moveto ";
                @pairs = split /[;\)]/, $endpairs ;
                for( $index = 0; $index < $#pairs; $index += 2)
                {
                        print $pairs[$index], " ", $pairs[$index+1], " lineto ";
                }
                print "stroke\n";
        }

        elsif( /R\([^\)]*\)/ )
        {
                print  "% ", $_ ;
                s/^.*R\(//;
                ($newwidth, $fill, $x1, $y1, $x2, $y2) = split /[;\)]/;
                if($newwidth != $currentwidth) { print $widthstring{$newwidth};
}
                $currentwidth = $newwidth;
                print $x1, " ", $y1, " moveto ";
                print $x1, " ", $y2, " lineto ";
                print $x2, " ", $y2, " lineto ";
                print $x2, " ", $y1, " lineto ";
                print "closepath ";
                if($fill =~ /F/)
                {
                        print "gsave ", $shapefill, " grestore ";
                }
                print "stroke\n";
        }

        elsif(/E\([^\)]*\)/)
        {
                print  "% ", $_ ;
                s/^.*E\(//;
                ($newwidth, $fill, $x1, $y1, $x2, $y2) = split /[;\)]/;
                if($newwidth != $currentwidth) { print $widthstring{$newwidth};
}
                $currentwidth = $newwidth;
#       create a new coordinate system where the origin is in the center
#       of the ellipse and the x and y dimensions are scaled so that a
#       unit circle is drawn as an ellipse
                print "gsave ";
                $xo = ($x1+$x2)/2;
                $yo = ($y1+$y2)/2;
                print $xo, " ", $yo, " translate ";
                $xs = abs($x1-$x2)/2;
                $ys = abs($y1-$y2)/2;
                print $xs, " ", $ys, " scale ";
                print "0 0 1 0 360 arc closepath\n";
#       unscale so the line isn't real fat
                print 1/$xs, " ", 1/$ys, " scale\n";
                if($fill =~ /F/)
                {
                        print "gsave ", $shapefill, "grestore ";
                }
                print "stroke grestore\n";
#       toss the new coordinate system so the rest of the drawing is ok
        }

        elsif(/T\([^\)]*\)/)
        {
                print  "% ", $_ ;
                s/^.*T\(//;
                ($font, $x1, $y1, $text) = split /[;\)]/ ;
                if($font != $currentfont) { print "NGP", $font, "font
setfont\n";}
                $currentfont = $font;
                print $x1, " ", $y1, " moveto ", $fontoffset{$font};
                $text =~ s/^[^"]*"/(/;
                $text =~ s/"[^"]*$/)/;
                print $text, " show\n";
        }
}

        print <<'TRAILER-DELIM';
showpage
%%Trailer
%%Pages: 1
TRAILER-DELIM

=-----------------------------------------------------------

Mark Zenier  mzenier@eskimo.com  mzenier@netcom.com  Washington State resident


NEWER VERSION

   Subject: Re: Suggestion: DRAWINGS on newsgroups
      Date: Mon, 30 Aug 1999 03:52:43 GMT
      From: mzenier@netcom.com (Mark Zenier)
 Organization:           Netcom
 Newsgroups: sci.electronics.design, sci.electronics.basics, de.sci.electronics
 

In article <935958098.2619.0.pluto.d4ee0662@news.demon.nl>,
Jan Panteltje <jan@panteltje.demon.nl> wrote:
>I have got the perl script working, but ghostview complains about fonts it does
not know,
>any suggestions?

Do a "gs --help" to tell you where the font directory "Fontmap" file is
by following the search path.

In the Fontmap file there are mapping between the either fonts and file
names, or fonts and aliases for the provided fonts.  Looks like this:

/NimbusMonL-Regu        (n022003l.pfb)  ;
/Courier                        /NimbusMonL-Regu        ;

You should be able to either add a alias to an existing font in the
Fontmap file, or change the reference to Courier in the Perl script.

(There is a compile option that causes Ghostscript to either bomb off
when it doesn't find a font, or to just substitute a default font.
That could be changed, too.  Easiest to change the script to use a fixed
width(?) font that you have).

Ghostview may use an alternate Fontmap file.  It's a command line
option for Ghostscript, so it can be changed.  (It may switch to
a set of X-Windows fonts, I've never used it).

Here's how I've been invoking it (as a script) by |ing from trn:

~mark/NGpaint/ng2ps.pl 640 | gs -q -g640x400 -sDEVICE=pngmono \
-dNOPAUSE -sOutputFile=${1-ngp}.png -

And then I use zvg under svgalib to look at the resulting graphic on
an alternate console.  (My news machine is a 8 Mb 386, and X-Windows is
just too painful on that small a machine).

Here's the latest version.  It handles the elliptical arcs, and supports
some of the proposed stuff, but in a way that Franz has since changed.
I think he plans to use the : instead of the # for line segments with
relative positions.  And I don't know if he plans to use those in the
Rectangle or other shapes in addition to Line specs.  And since I've
never run his program, I still don't know if the font sizes and offsets
are close enough.

=-------------------------------------------------------
#!/usr/bin/perl
#
#       File:           ng2ps.pl
#       Author:         Mark Zenier
#       Description:    A filter to convert Ing. Franz Glaser's NGpaint simple
#                       graphics format for newsgroup postings to level 1
#                       Postscript.
#       Usage:          Perl => Unix and whereever else it works
#
#                       ng2ps.pl [width] <input >output
#
#                       width (optional) is in Postscript points (72 per inch),
#                               default is 320  about a half pagewidth
#
#       History:        August 29, 1999   Version 1.3
#
#       Bugs:           Dot and Dash sequences are not matched to NGpaint.
#                       Offsets for text from postion are not set.
#                       font sizes are a random guess.
#                       shape fill is untested, any color that you like as
#                       long as it's black.
#                       wrapped lines are not supported.
#                       expects fixed 320x200 field for input
 

        $scale = ($#ARGV >= 0) ?  $ARGV[0]/320 : 1;
        shift;

        %widthstring = (
                1 => " 1 setlinewidth [] 0 setdash\n",
                2 => " 2 setlinewidth [] 0 setdash\n",
                3 => " 3 setlinewidth [] 0 setdash\n",
                4 => " 4 setlinewidth [] 0 setdash\n",
                5 => " 5 setlinewidth [] 0 setdash\n",
                6 => " 6 setlinewidth [] 0 setdash\n",
                7 => " 7 setlinewidth [] 0 setdash\n",
                8 => " 8 setlinewidth [] 0 setdash\n",
                9 => " 9 setlinewidth [] 0 setdash\n",
                10 => " 10 setlinewidth [] 0 setdash\n",
                DS => " 1 setlinewidth [3 2] 0 setdash\n",
                DT => " 1 setlinewidth [2 2] 0 setdash\n",
                DD => " 1 setlinewidth [3 2 1 2] 0 setdash\n"
        );

        %fontoffset = (
                S => " 0 0 rmoveto ",
                M => " 0 0 rmoveto ",
                B => " 0 0 rmoveto "
        );

        $shapefill = "fill ";

        print <<'HDR-HEREDOC-DELIM';
%!PS-Adobe-1.0
%%Pages: (atend)
%%DocumentFonts: Courier
%%EndComments
/NGPSfont /Courier findfont [6 0 0 -6 0 0] makefont def
/NGPMfont /Courier findfont [8 0 0 -8 0 0] makefont def
/NGPLfont /Courier findfont [16 0 0 -16 0 0] makefont def
HDR-HEREDOC-DELIM

# Move coordinate system up by the height, and flop the x-axis, and magnify

        print "0 ", 200*$scale, " translate\n",
                $scale, " -", $scale, " scale\n";

        print <<'HDR-HEREDOC-DELIM';
NGPMfont setfont
%%EndProlog
HDR-HEREDOC-DELIM

        $currentwidth = "?";
        $currentfont = "M";

while(<>)
{
        if(/^T\([^\)]*\)/)
        {
                print  "% ", $_ ;
                s/^T\(//;
                ($font, $x1, $y1, $text) = split /[;]/, $_, 4 ;
                if($font != $currentfont && $font =~ /[SMB]/)
                {
                        print "NGP", $font, "font setfont\n";
                        $currentfont = $font;
                }
                print $x1, " ", $y1, " moveto ", $fontoffset{$font};
                $text =~ s/([()])/\\\1/g;
                $text =~ s/^[^"]*"/(/;
                $text =~ s/"[^"]*$/)/;
                print $text, " show\n";
        }

        elsif(/^L\([^)]*\)/)
        {
                print  "% ", $_ ;
                s/^L\(//;
                ($newwidth, $x1, $y1, $endpairs) = split /[;#]/, $_, 4;
                if($newwidth != $currentwidth) { print $widthstring{$newwidth} }
                $currentwidth = $newwidth;
                print $x1, " ", $y1, " moveto ";
# parse both delimiters and number strings for "polylines"
                @pairs = split /([;#\)])/, $endpairs ;
                for( $index = 0; $index < $#pairs; $index += 4)
                {
                        print $pairs[$index], " ", $pairs[$index+2],
#only check middle delimiter, if # both coords are relative, no mixing
                        ($pairs[$index+1] =~ /#/) ? " rlineto ":" lineto " ;
                }
                print "stroke\n";
        }

        elsif( /^R\([^\)]*\)/ )
        {
                print  "% ", $_ ;
                s/^R\(//;
                ($newwidth, $fill, $x1, $y1, $x2, $y2) = split /[;\)]/;
                if($newwidth != $currentwidth) { print $widthstring{$newwidth};
}
                $currentwidth = $newwidth;
                print $x1, " ", $y1, " moveto ";
                print $x1, " ", $y2, " lineto ";
                print $x2, " ", $y2, " lineto ";
                print $x2, " ", $y1, " lineto ";
                print "closepath ";
                if($fill =~ /F/)
                {
                        print "gsave ", $shapefill, " grestore ";
                }
                print "stroke\n";
        }

        elsif(/^E\([^\)]*\)/)
        {
                print  "% ", $_ ;
                s/^E\(//;
                ($newwidth, $fill, $x1, $y1, $x2, $y2) = split /[;\)]/;
                if($x1 != $x2 && $y1 != $y2)
#skip 0 width/height shapes
                {
                        if($newwidth != $currentwidth) { print $widthstring{$newwidth}; }
                        $currentwidth = $newwidth;
        #       create a new coordinate system where the origin is in the center
        #       of the ellipse and the x and y dimensions are scaled so that a
        #       unit circle is drawn as an ellipse
                        print "gsave ";
                        $xo = ($x1+$x2)/2;
                        $yo = ($y1+$y2)/2;
                        print $xo, " ", $yo, " translate ";
                        $xs = abs($x1-$x2)/2;
                        $ys = abs($y1-$y2)/2;
                        print $xs, " ", $ys, " scale ";
                        print "0 0 1 0 360 arc closepath\n";
        #       unscale so the line isn't real fat
                        print 1/$xs, " ", 1/$ys, " scale\n";
                        if($fill =~ /F/)
                        {
                                print "gsave ", $shapefill, "grestore ";
                        }
                        print "stroke grestore\n";
        #       toss the new coordinate system so the rest of the drawing is ok
                }
        }

        elsif(/^A\([^\)]*\)/)
        {
                print  "% ", $_ ;
                s/^A\(//;

                ($newwidth, $fill, $xc, $yc, $x2, $y2, $rest) = split /[;\)]/,$_, 7;

                if($x2 < $xc && $y2 < $yc) { $arcstart = 90; $arcend = 180; }
                if($x2 >= $xc && $y2 < $yc) { $arcstart = 0; $arcend = 90; }
                if($x2 < $xc && $y2 >= $yc) { $arcstart = 180; $arcend = 270; }
                if($x2 >= $xc && $y2 >= $yc) { $arcstart = 270; $arcend = 360; }

                if($rest =~ /[;0-9]/)
                {
                        ($arcstart, $arcend) = split /[;\)]/, $rest;
                }

                if($newwidth != $currentwidth) { print $widthstring{$newwidth};
}
                $currentwidth = $newwidth;
#       create a new coordinate system where the origin is in the center
#       of the ellipse and the x and y dimensions are scaled so that a
#       unit circle is drawn as an ellipse
                print "gsave ";
                print $xc, " ", $yc, " translate ";
                $xs = abs($xc-$x2);
                $ys = abs($yc-$y2);
#flip y axis so that 0 degrees means to the right, increasing counterclockwise
                print $xs, " -", $ys, " scale ";
                print "0 0 1 ", $arcstart, " ", $arcend, " arc\n";
#       unscale so the line isn't real fat
                print 1/$xs, " ", 1/$ys, " scale\n";
                print "stroke grestore\n";
#       toss the new coordinate system so the rest of the drawing is ok
        }

}

        print <<'TRAILER-DELIM';
showpage
%%Trailer
%%Pages: 1
TRAILER-DELIM
=-------------------------------------------------------
Mark Zenier  mzenier@eskimo.com  mzenier@netcom.com  Washington State resident


back to NGpaint page

This page hosted by    Get your own Free Home Page