groff-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Groff-commit] groff ChangeLog MANIFEST Makefile.comm Makefile...


From: Werner LEMBERG
Subject: [Groff-commit] groff ChangeLog MANIFEST Makefile.comm Makefile...
Date: Tue, 26 Jul 2011 17:11:12 +0000

CVSROOT:        /cvsroot/groff
Module name:    groff
Changes by:     Werner LEMBERG <wl>     11/07/26 17:11:12

Modified files:
        .              : ChangeLog MANIFEST Makefile.comm Makefile.in 
                         test-groff.in 
        contrib/pdfmark: pdfmark.ms 
        doc            : Makefile.in Makefile.sub groff.texinfo pic.ms 
        man            : groff_out.man 
        src/devices/grops: grops.man 
        src/preproc/pic: pic.man 
        src/roff/groff : groff.man 
        src/utils/afmtodit: afmtodit.man 
        src/utils/pfbtops: pfbtops.man 
        tmac           : Makefile.sub troffrc 
Added files:
        font/devpdf    : DESC.in Foundry Makefile.sub 
        font/devpdf/util: BuildFoundries.pl Makefile.sub 
        src/devices/gropdf: Makefile.sub TODO gropdf.man gropdf.pl 
        tmac           : pdf.tmac 

Log message:
        Add new output device `gropdf'.
        
        * font/devpdf/*: New device files for gropdf.
        * src/devices/gropdf/*: New device.
        
        * Makefile.comm (install_dev, uninstall_dev): Handle more
        subdirectories.
        * Makefile.in (DEVDIRS, OTHERDIRS, EXTRADIRS): Add directories
        related to gropdf.
        * MANIFEST: Updated.
        * test-groff.in (GROFF_BIN_PATH): Updated.
        
        * tmac/Makefile.sub (NORMALFILES): Updated.
        * tmac/pdf.tmac: New file.
        * tmac/troffrc: Updated.
        
        * doc/groff.texinfo: Document it.
        * doc/Makefile.in, doc/Makefile.sub (groff_bin_dirs): Udpated.
        * doc/pic.ms: Updated.
        
        * man/groff_out.man, src/devices/grops/grops.man,
        src/preproc/pic/pic.man, src/roff/groff/groff.man,
        src/utils/afmtodit/afmtodit.man, src/utils/pfbtops/pfbtops.man:
        Updated.
        
        * contrib/pdfmark/pdfmark.ms: Updated.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/groff/ChangeLog?cvsroot=groff&r1=1.1303&r2=1.1304
http://cvs.savannah.gnu.org/viewcvs/groff/MANIFEST?cvsroot=groff&r1=1.16&r2=1.17
http://cvs.savannah.gnu.org/viewcvs/groff/Makefile.comm?cvsroot=groff&r1=1.42&r2=1.43
http://cvs.savannah.gnu.org/viewcvs/groff/Makefile.in?cvsroot=groff&r1=1.115&r2=1.116
http://cvs.savannah.gnu.org/viewcvs/groff/test-groff.in?cvsroot=groff&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/groff/contrib/pdfmark/pdfmark.ms?cvsroot=groff&r1=1.9&r2=1.10
http://cvs.savannah.gnu.org/viewcvs/groff/doc/Makefile.in?cvsroot=groff&r1=1.26&r2=1.27
http://cvs.savannah.gnu.org/viewcvs/groff/doc/Makefile.sub?cvsroot=groff&r1=1.35&r2=1.36
http://cvs.savannah.gnu.org/viewcvs/groff/doc/groff.texinfo?cvsroot=groff&r1=1.304&r2=1.305
http://cvs.savannah.gnu.org/viewcvs/groff/doc/pic.ms?cvsroot=groff&r1=1.48&r2=1.49
http://cvs.savannah.gnu.org/viewcvs/groff/font/devpdf/DESC.in?cvsroot=groff&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/groff/font/devpdf/Foundry?cvsroot=groff&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/groff/font/devpdf/Makefile.sub?cvsroot=groff&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/groff/font/devpdf/util/BuildFoundries.pl?cvsroot=groff&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/groff/font/devpdf/util/Makefile.sub?cvsroot=groff&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/groff/man/groff_out.man?cvsroot=groff&r1=1.44&r2=1.45
http://cvs.savannah.gnu.org/viewcvs/groff/src/devices/gropdf/Makefile.sub?cvsroot=groff&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/groff/src/devices/gropdf/TODO?cvsroot=groff&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/groff/src/devices/gropdf/gropdf.man?cvsroot=groff&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/groff/src/devices/gropdf/gropdf.pl?cvsroot=groff&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/groff/src/devices/grops/grops.man?cvsroot=groff&r1=1.39&r2=1.40
http://cvs.savannah.gnu.org/viewcvs/groff/src/preproc/pic/pic.man?cvsroot=groff&r1=1.22&r2=1.23
http://cvs.savannah.gnu.org/viewcvs/groff/src/roff/groff/groff.man?cvsroot=groff&r1=1.60&r2=1.61
http://cvs.savannah.gnu.org/viewcvs/groff/src/utils/afmtodit/afmtodit.man?cvsroot=groff&r1=1.19&r2=1.20
http://cvs.savannah.gnu.org/viewcvs/groff/src/utils/pfbtops/pfbtops.man?cvsroot=groff&r1=1.5&r2=1.6
http://cvs.savannah.gnu.org/viewcvs/groff/tmac/Makefile.sub?cvsroot=groff&r1=1.50&r2=1.51
http://cvs.savannah.gnu.org/viewcvs/groff/tmac/troffrc?cvsroot=groff&r1=1.15&r2=1.16
http://cvs.savannah.gnu.org/viewcvs/groff/tmac/pdf.tmac?cvsroot=groff&rev=1.1

Patches:
Index: ChangeLog
===================================================================
RCS file: /cvsroot/groff/groff/ChangeLog,v
retrieving revision 1.1303
retrieving revision 1.1304
diff -u -b -r1.1303 -r1.1304
--- ChangeLog   20 Jul 2011 18:44:50 -0000      1.1303
+++ ChangeLog   26 Jul 2011 17:11:09 -0000      1.1304
@@ -1,3 +1,32 @@
+2011-06-25  Deri James  <address@hidden>
+
+       Add new output device `gropdf'.
+
+       * font/devpdf/*: New device files for gropdf.
+       * src/devices/gropdf/*: New device.
+
+       * Makefile.comm (install_dev, uninstall_dev): Handle more
+       subdirectories.
+       * Makefile.in (DEVDIRS, OTHERDIRS, EXTRADIRS): Add directories
+       related to gropdf.
+       * MANIFEST: Updated.
+       * test-groff.in (GROFF_BIN_PATH): Updated.
+
+       * tmac/Makefile.sub (NORMALFILES): Updated.
+       * tmac/pdf.tmac: New file.
+       * tmac/troffrc: Updated.
+
+       * doc/groff.texinfo: Document it.
+       * doc/Makefile.in, doc/Makefile.sub (groff_bin_dirs): Udpated.
+       * doc/pic.ms: Updated.
+
+       * man/groff_out.man, src/devices/grops/grops.man,
+       src/preproc/pic/pic.man, src/roff/groff/groff.man,
+       src/utils/afmtodit/afmtodit.man, src/utils/pfbtops/pfbtops.man:
+       Updated.
+
+       * contrib/pdfmark/pdfmark.ms: Updated.
+
 2011-07-20  George HELFFRICH  <address@hidden>
 
        Improve line numbering support in tbl and with me macros.

Index: MANIFEST
===================================================================
RCS file: /cvsroot/groff/groff/MANIFEST,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -b -r1.16 -r1.17
--- MANIFEST    30 Dec 2010 22:34:22 -0000      1.16
+++ MANIFEST    26 Jul 2011 17:11:09 -0000      1.17
@@ -1,4 +1,4 @@
-    Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2010
+    Copyright 2001-2006, 2009-2011
       Free Software Foundation, Inc.
 
     Copying and distribution of this file, with or without modification,
@@ -69,6 +69,7 @@
   devlbp        Device for Canon CAPSL laser printers.
   devlj4        Device for HP Laserjet 4, PCL 5, and compatible printers.
   devps         PostScript device.
+  devpdf        PDF device.
   devutf8       Text device for Unicode output.
   util          Utility programs.
 
@@ -84,6 +85,7 @@
   grolbp        Canon printers.
   grolj4        HP Laserjet 4, PCL 5, and compatible printers.
   grops         PostScript output.
+  gropdf        PDF output.
   grotty        Text output.
   xditview      A groff (pre)viewer for the X Window system.
 

Index: Makefile.comm
===================================================================
RCS file: /cvsroot/groff/groff/Makefile.comm,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -b -r1.42 -r1.43
--- Makefile.comm       15 Jan 2011 10:20:53 -0000      1.42
+++ Makefile.comm       26 Jul 2011 17:11:09 -0000      1.43
@@ -1,4 +1,4 @@
-# Copyright (C) 1989-2000, 2002, 2003, 2004, 2006, 2007, 2009, 2010
+# Copyright (C) 1989-2000, 2002-2004, 2006-2011
 #   Free Software Foundation, Inc.
 #      Written by James Clark (address@hidden)
 # 
@@ -246,6 +246,18 @@
          test -d $(DESTDIR)$(fontsubdir)/generate \
            || $(mkinstalldirs) $(DESTDIR)$(fontsubdir)/generate; \
        fi
+       -if test -d $(srcdir)/enc; then \
+         test -d $(DESTDIR)$(fontsubdir)/enc \
+           || $(mkinstalldirs) $(DESTDIR)$(fontsubdir)/enc; \
+       fi
+       -if test -d $(srcdir)/map; then \
+         test -d $(DESTDIR)$(fontsubdir)/map \
+           || $(mkinstalldirs) $(DESTDIR)$(fontsubdir)/map; \
+       fi
+       -if test -d $(srcdir)/util; then \
+         test -d $(DESTDIR)$(fontsubdir)/util \
+           || $(mkinstalldirs) $(DESTDIR)$(fontsubdir)/util; \
+       fi
        -if test -d $(srcdir)/old; then \
          test -d $(DESTDIR)$(oldfontdir) \
            || $(mkinstalldirs) $(DESTDIR)$(oldfontdir); \
@@ -288,6 +300,12 @@
             done
        -test -d $(DESTDIR)$(fontsubdir)/generate \
          && rmdir $(DESTDIR)$(fontsubdir)/generate
+       -test -d $(DESTDIR)$(fontsubdir)/enc \
+         && rmdir $(DESTDIR)$(fontsubdir)/enc
+       -test -d $(DESTDIR)$(fontsubdir)/map \
+         && rmdir $(DESTDIR)$(fontsubdir)/map
+       -test -d $(DESTDIR)$(fontsubdir)/util \
+         && rmdir $(DESTDIR)$(fontsubdir)/util
        -rmdir $(DESTDIR)$(fontsubdir)
        -rmdir $(DESTDIR)$(oldfontsubdir)
 

Index: Makefile.in
===================================================================
RCS file: /cvsroot/groff/groff/Makefile.in,v
retrieving revision 1.115
retrieving revision 1.116
diff -u -b -r1.115 -r1.116
--- Makefile.in 30 Mar 2011 18:08:15 -0000      1.115
+++ Makefile.in 26 Jul 2011 17:11:09 -0000      1.116
@@ -589,6 +589,7 @@
   $(XPROGDIRS)
 DEVDIRS=\
   font/devps \
+  font/devpdf \
   font/devdvi \
   font/devhtml
 ALLTTYDEVDIRS=\
@@ -613,7 +614,9 @@
   contrib/mom \
   contrib/hdtbl \
   contrib/pdfmark \
+  src/devices/gropdf \
   contrib/gdiffmk
+  
 ALLDIRS=\
   $(INCDIRS) \
   $(LIBDIRS) \
@@ -627,6 +630,7 @@
   font/devps/generate \
   font/devdvi/generate \
   font/devlj4/generate \
+  font/devpdf/util \
   doc
 NOMAKEDIRS=\
   m4 \

Index: test-groff.in
===================================================================
RCS file: /cvsroot/groff/groff/test-groff.in,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- test-groff.in       5 Jan 2009 20:10:31 -0000       1.8
+++ test-groff.in       26 Jul 2011 17:11:09 -0000      1.9
@@ -1,6 +1,6 @@
 #! /bin/sh
 #
-# Copyright (C) 1989-2000, 2001, 2002, 2003, 2004, 2005, 2009
+# Copyright (C) 1989-2000, 2001-2005, 2009, 2011
 #   Free Software Foundation, Inc.
 # 
 # This file is part of groff.
@@ -41,6 +41,7 @@
 $builddir/devices/grolj4$SEP\
 $builddir/devices/grolbp$SEP\
 $builddir/devices/grohtml$SEP\
+$builddir/devices/gropdf$SEP\
 $builddir/devices/xditview
 
 XENVIRONMENT=$srcdir/src/devices/xditview/GXditview.ad

Index: contrib/pdfmark/pdfmark.ms
===================================================================
RCS file: /cvsroot/groff/groff/contrib/pdfmark/pdfmark.ms,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -b -r1.9 -r1.10
--- contrib/pdfmark/pdfmark.ms  5 Jan 2009 20:33:54 -0000       1.9
+++ contrib/pdfmark/pdfmark.ms  26 Jul 2011 17:11:09 -0000      1.10
@@ -6,7 +6,7 @@
 
 This file is part of groff, the GNU roff type-setting system.
 
-Copyright (C) 2004, 2005, 2006, 2009 Free Software Foundation, Inc.
+Copyright (C) 2004-2006, 2009, 2011 Free Software Foundation, Inc.
 written by Keith Marshall <address@hidden>
 
 Permission is granted to copy, distribute and/or modify this document
@@ -343,6 +343,10 @@
 .I options \& [-
 .I "file ..." \& "...] "
 .LP
+(Or use the PDF post-processor to avoid using ghostscript,
+.CW -Tpdf\c
+).
+.LP
 It may be noted that the
 .CW pdfmark
 macros have no dependencies on, and no known conflicts with,
@@ -2490,6 +2494,10 @@
 .I "-options ...\&" ] [
 file(s) ...
 .LP
+(Or use the PDF post-processor to avoid using ghostscript,
+.CW -Tpdf\c
+).
+.LP
 When using the
 .CW spdf.tmac
 package, the

Index: doc/Makefile.in
===================================================================
RCS file: /cvsroot/groff/groff/doc/Makefile.in,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -b -r1.26 -r1.27
--- doc/Makefile.in     30 Dec 2010 22:34:22 -0000      1.26
+++ doc/Makefile.in     26 Jul 2011 17:11:09 -0000      1.27
@@ -1,4 +1,4 @@
-# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010
+# Copyright (C) 2002-2007, 2009-2011
 #   Free Software Foundation, Inc.
 #      Written by Werner Lemberg <address@hidden>
 # 
@@ -58,6 +58,7 @@
   $(top_builddir)/src/preproc/soelim \
   $(top_builddir)/src/preproc/html \
   $(top_builddir)/src/devices/grops \
+  $(top_builddir)/src/devices/gropdf \
   $(top_builddir)/src/devices/grodvi \
   $(top_builddir)/src/devices/grotty \
   $(top_builddir)/src/devices/grolj4 \

Index: doc/Makefile.sub
===================================================================
RCS file: /cvsroot/groff/groff/doc/Makefile.sub,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -b -r1.35 -r1.36
--- doc/Makefile.sub    10 Jan 2009 07:48:15 -0000      1.35
+++ doc/Makefile.sub    26 Jul 2011 17:11:09 -0000      1.36
@@ -1,4 +1,4 @@
-# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2009
+# Copyright (C) 2002-2007, 2009, 2011
 #   Free Software Foundation, Inc.
 #      Written by Werner Lemberg <address@hidden>
 # 
@@ -32,6 +32,7 @@
   $(top_builddir)/src/preproc/soelim \
   $(top_builddir)/src/preproc/html \
   $(top_builddir)/src/devices/grops \
+  $(top_builddir)/src/devices/gropdf \
   $(top_builddir)/src/devices/grohtml
 
 FFLAG=-F$(top_builddir)/font -F$(top_srcdir)/font

Index: doc/groff.texinfo
===================================================================
RCS file: /cvsroot/groff/groff/doc/groff.texinfo,v
retrieving revision 1.304
retrieving revision 1.305
diff -u -b -r1.304 -r1.305
--- doc/groff.texinfo   14 Feb 2011 08:26:27 -0000      1.304
+++ doc/groff.texinfo   26 Jul 2011 17:11:09 -0000      1.305
@@ -862,7 +862,7 @@
 Currently, @code{groff} has postprocessors for @sc{PostScript} devices,
 character terminals, address@hidden (for previewing), @TeX{} DVI format,
 HP address@hidden and Canon LBP printers (which use @acronym{CAPSL}),
address@hidden, and @acronym{XHTML}.
address@hidden, @acronym{XHTML}, and PDF.
 
 
 @c =====================================================================
@@ -945,14 +945,14 @@
 @code{geqn}, @code{gtbl}, @code{ggrn}, @code{grap}, @code{gchem},
 @code{grefer}, @code{gsoelim}, or @code{preconv}.
 
-This section only documents options to the @code{groff} front end.
-Many of the arguments to @code{groff} are passed on to @code{gtroff},
+This section only documents options to the @code{groff} front end.  Many
+of the arguments to @code{groff} are passed on to @code{gtroff},
 therefore those are also included.  Arguments to pre- or postprocessors
 can be found in @ref{Invoking gpic}, @ref{Invoking geqn}, @ref{Invoking
-gtbl}, @ref{Invoking ggrn}, @ref{Invoking grefer}, @ref{Invoking
-gchem}, @ref{Invoking gsoelim}, @ref{Invoking preconv}, @ref{Invoking
-grotty}, @ref{Invoking grops}, @ref{Invoking grohtml}, @ref{Invoking
-grodvi}, @ref{Invoking grolj4}, @ref{Invoking grolbp}, and
+gtbl}, @ref{Invoking ggrn}, @ref{Invoking grefer}, @ref{Invoking gchem},
address@hidden gsoelim}, @ref{Invoking preconv}, @ref{Invoking grotty},
address@hidden grops}, @ref{Invoking gropdf}, @ref{Invoking grohtml},
address@hidden grodvi}, @ref{Invoking grolj4}, @ref{Invoking grolbp}, and
 @ref{Invoking gxditview}.
 
 The command line format for @code{groff} is:
@@ -1194,6 +1194,9 @@
 @item ps
 For @sc{PostScript} printers and previewers.
 
address@hidden pdf
+For PDF viewers or printers.
+
 @item dvi
 For @TeX{} DVI format.
 
@@ -1337,7 +1340,7 @@
 @code{tbl}, @code{pic}, @code{eqn}, @code{grn}, @code{chem},
 @code{refer}, and @code{soelim}.  It does not apply to @code{grops},
 @code{grodvi}, @code{grotty}, @code{pre-grohtml}, @code{post-grohtml},
address@hidden, @code{grolj4}, and @code{gxditview}.
address@hidden, @code{grolj4}, @code{gropdf}, and @code{gxditview}.
 
 The default command prefix is determined during the installation
 process.  If a non-GNU troff system is found, prefix @samp{g} is used,
@@ -2534,8 +2537,8 @@
 
 @Defmac {UC, address@hidden, man}
 @cindex @code{man}macros, BSD compatibility
-Alters the footer for use with @acronym{BSD} manpages.  This command
-exists only for compatibility; don't use it.  The argument can be:
+Alters the footer for use with BSD manpages.  This command exists only
+for compatibility; don't use it.  The argument can be:
 
 @table @code
 @item 3
@@ -3876,9 +3879,8 @@
 @DefmacList {[, , ms}
 @DefmacListEnd {], , ms}
 Denotes a reference, to be processed by the @code{refer} preprocessor.
-The @acronym{GNU} @cite{refer(1)} man page provides a comprehensive
-reference to the preprocessor and the format of the bibliographic
-database.
+The GNU @cite{refer(1)} man page provides a comprehensive reference to
+the preprocessor and the format of the bibliographic database.
 @endDefmac
 
 @menu
@@ -8892,10 +8894,10 @@
 
 @cindex PostScript fonts
 @cindex fonts, PostScript
-Currently, fonts for the devices @option{-Tps}, @option{-Tdvi},
address@hidden, @option{-Tlbp}, and the X11 fonts are set up to this
-mechanism.  By default, @code{gtroff} uses the Times family with the
-four styles @samp{R}, @samp{I}, @samp{B}, and @samp{BI}.
+Currently, fonts for the devices @option{-Tps}, @option{-Tpdf},
address@hidden, @option{-Tlj4}, @option{-Tlbp}, and the X11 fonts are
+set up to this mechanism.  By default, @code{gtroff} uses the Times
+family with the four styles @samp{R}, @samp{I}, @samp{B}, and @samp{BI}.
 
 This way, it is possible to use the basic four fonts and to select a
 different font family on the command line (@pxref{Groff Options}).
@@ -9804,7 +9806,8 @@
 The read-only number register @code{.height} contains the font height as
 set by @code{\H}.
 
-Currently, only the @option{-Tps} device supports this feature.
+Currently, only the @option{-Tps} and @option{-Tpdf} devices support
+this feature.
 
 Note that @code{\H} doesn't produce an input token in @code{gtroff}.  As
 a consequence, it can be used in requests like @code{mc} (which expects
@@ -9840,7 +9843,8 @@
 The read-only number register @code{.slant} contains the font slant as
 set by @code{\S}.
 
-Currently, only the @option{-Tps} device supports this feature.
+Currently, only the @option{-Tps} and @option{-Tpdf} devices support
+this feature.
 
 Note that @code{\S} doesn't produce an input token in @code{gtroff}.  As
 a consequence, it can be used in requests like @code{mc} (which expects
@@ -14913,6 +14917,7 @@
 * Special Characters::
 * grotty::
 * grops::
+* gropdf::
 * grodvi::
 * grolj4::
 * grolbp::
@@ -15023,7 +15028,7 @@
 
 @c =====================================================================
 
address@hidden grops, grodvi, grotty, Output Devices
address@hidden grops, gropdf, grotty, Output Devices
 @section @code{grops}
 @cindex @code{grops}, the program
 
@@ -15123,7 +15128,82 @@
 
 @c =====================================================================
 
address@hidden grodvi, grolj4, grops, Output Devices
address@hidden gropdf, grodvi, grops, Output Devices
address@hidden @code{gropdf}
address@hidden @code{gropdf}, the program
+
+The postprocessor @command{gropdf} translates the output from GNU
address@hidden into a form suitable for Adobe PDF devices.  It is fully
+documented on its manual page, @cite{gropdf(1)}.
+
address@hidden
+* Invoking gropdf::
+* Embedding PDF::
address@hidden menu
+
address@hidden 
---------------------------------------------------------------------
+
address@hidden Invoking gropdf, Embedding PDF, gropdf, gropdf
address@hidden Invoking @code{gropdf}
address@hidden invoking @code{gropdf}
address@hidden @code{gropdf}, invoking
+
+The postprocessor @code{gropdf} accepts the following command-line
+options:
+
address@hidden @option
address@hidden -d
+Produce uncompressed PDFs which include debugging comments.
+
address@hidden -e
+This forces @code{gropdf} to embed all used fonts in the PDF,
+even if they are one of the 14 base Adobe fonts.
+
address@hidden address@hidden
+Put the directory @address@hidden/address@hidden in front of the
+search path for the font, prologue and device description files,
+given the target device @var{name}, usually @strong{pdf}.
+
address@hidden address@hidden
+This forces the use of a different font foundry.
+
address@hidden -l
+Use landscape orientation.
+
address@hidden address@hidden
+Set the page dimensions.  Overrides the commands @option{papersize},
address@hidden, and @option{paperwidth} in the @file{DESC}
+file.  See the @cite{groff_font(5)} manual page for details.
+
address@hidden -v
+Print the version number.
address@hidden table
+
address@hidden 
---------------------------------------------------------------------
+
address@hidden Embedding PDF,  , Invoking gropdf, gropdf
address@hidden Embedding PDF
address@hidden embedding PDF
address@hidden PDF, embedding
+
+The escape sequence
+
address@hidden'pdf: pdfpic @var{file} @var{alignment} @var{width} address@hidden
+  address@hidden'}
+
address@hidden
+places a rectangle of the specified @var{width} containing the PDF
+drawing from file @var{file} of desired @var{width} and @var{height} (if
address@hidden is missing or zero then it is scaled proportionally).  If
address@hidden is @code{-L} the drawing is left aligned.  If it is
address@hidden or @code{-R} a @var{linelength} greater than the width of the
+drawing is required as well.  If @var{width} is specified as zero then
+the width is scaled in proportion to the height.
+
+
address@hidden 
=====================================================================
+
address@hidden grodvi, grolj4, gropdf, Output Devices
 @section @code{grodvi}
 @cindex @code{grodvi}, the program
 

Index: doc/pic.ms
===================================================================
RCS file: /cvsroot/groff/groff/doc/pic.ms,v
retrieving revision 1.48
retrieving revision 1.49
diff -u -b -r1.48 -r1.49
--- doc/pic.ms  27 Jan 2011 04:15:42 -0000      1.48
+++ doc/pic.ms  26 Jul 2011 17:11:10 -0000      1.49
@@ -30,7 +30,7 @@
 .\" Eric S. Raymond <address@hidden> in August 1995.  It has been put
 .\" under the GPL in March 2006.
 .\"
-.\"    $Id: pic.ms,v 1.48 2011/01/27 04:15:42 wl Exp $ 
+.\"    $Id: pic.ms,v 1.49 2011/07/26 17:11:10 wl Exp $ 
 .
 .
 .\" Set a proper TeX and LaTeX
@@ -862,7 +862,7 @@
 .B aligned
 attribute.
 This only works if the postprocessor is
-\fBgrops\fP.
+\fBgrops\fP or \fBgropdf\fP.
 Any text associated with an object having the
 .B aligned
 attribute is rotated about the center of the object

Index: man/groff_out.man
===================================================================
RCS file: /cvsroot/groff/groff/man/groff_out.man,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -b -r1.44 -r1.45
--- man/groff_out.man   5 Jan 2009 20:33:55 -0000       1.44
+++ man/groff_out.man   26 Jul 2011 17:11:10 -0000      1.45
@@ -5,8 +5,7 @@
 
 This file is part of groff, the GNU roff type-setting system.
 
-Copyright (C) 1989, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
-              2009
+Copyright (C) 1989, 2001-2009, 2011
 Free Software Foundation, Inc.
 rewritten from scrach 2001 by Bernd Warken <address@hidden>
 
@@ -1560,7 +1559,9 @@
 .P
 This output can be fed into the postprocessor
 .BR grops (@MAN1EXT@)
-to get its representation as a PostScript file.
+to get its representation as a PostScript file, or
+.BR gropdf (@MAN1EXT@)
+to output directly to PDF.
 .
 .
 .IP \[bu] 2m 

Index: src/devices/grops/grops.man
===================================================================
RCS file: /cvsroot/groff/groff/src/devices/grops/grops.man,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -b -r1.39 -r1.40
--- src/devices/grops/grops.man 20 Jan 2010 13:05:01 -0000      1.39
+++ src/devices/grops/grops.man 26 Jul 2011 17:11:11 -0000      1.40
@@ -1,6 +1,5 @@
 .ig
-Copyright (C) 1989-2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008,
-              2009, 2010
+Copyright (C) 1989-2006, 2008-2011
   Free Software Foundation, Inc.
 
 Permission is granted to make and distribute verbatim copies of
@@ -29,6 +28,7 @@
 .
 .de FT
 .  if '\\*(.T'ps' .ft \\$1
+.  if '\\*(.T'pdf' .ft \\$1
 ..
 .
 .

Index: src/preproc/pic/pic.man
===================================================================
RCS file: /cvsroot/groff/groff/src/preproc/pic/pic.man,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -b -r1.22 -r1.23
--- src/preproc/pic/pic.man     19 Jan 2011 05:42:15 -0000      1.22
+++ src/preproc/pic/pic.man     26 Jul 2011 17:11:11 -0000      1.23
@@ -1,5 +1,5 @@
 .ig
-Copyright (C) 1989-2000, 2001, 2002, 2003, 2004, 2007, 2009, 2011
+Copyright (C) 1989-2004, 2007, 2009, 2011
   Free Software Foundation, Inc.
 
 Permission is granted to make and distribute verbatim copies of
@@ -924,7 +924,9 @@
 .B aligned
 attribute.
 This will only work if the postprocessor is
-.BR grops .
+.BR grops ,
+or
+.BR gropdf .
 Any text associated with an object having the
 .B aligned
 attribute will be rotated about the center of the object
@@ -1033,6 +1035,16 @@
 for a list of the available devices.
 .
 .LP
+An alternative may be to use the
+.B \-Tpdf
+option to convert your picture directly into
+.B PDF
+format.
+The MediaBox of the file produced can be controlled by passing a
+.B \-P-p
+papersize to groff.
+.
+.LP
 As the Encapsulated PostScript File Format
 .B EPS
 is getting more and more important, and the conversion wasn't regarded

Index: src/roff/groff/groff.man
===================================================================
RCS file: /cvsroot/groff/groff/src/roff/groff/groff.man,v
retrieving revision 1.60
retrieving revision 1.61
diff -u -b -r1.60 -r1.61
--- src/roff/groff/groff.man    23 Feb 2011 08:17:39 -0000      1.60
+++ src/roff/groff/groff.man    26 Jul 2011 17:11:11 -0000      1.61
@@ -456,6 +456,11 @@
 ps
 PostScript output (postprocessor is
 .BR grops ).
+.
+.TP
+pdf
+Portable Document Format (PDF) output (postprocessor is
+.BR gropdf ).
 .RE
 .RE
 .
@@ -1106,6 +1111,13 @@
 .BR gv (1).
 .
 .TP
+.B pdf
+PDF files; suitable for viewing with tools such as
+.BR evince (1)
+and 
+.BR okular (1).
+.
+.TP
 .B utf8
 Text output using the Unicode (ISO 10646) character set with \%UTF-8
 encoding; see
@@ -1195,6 +1207,10 @@
 .BR grops (@MAN1EXT@)
 for PostScript.
 .
+.TP
+.BR gropdf (@MAN1EXT@)
+for PDF.
+.
 .P
 Combined with the many existing free conversion tools this should
 be sufficient to convert a
@@ -1845,6 +1861,7 @@
 .BR \%grolj4 (@MAN1EXT@),
 .BR \%lj4_font (@MAN5EXT@),
 .BR \%grops (@MAN1EXT@),
+.BR \%gropdf (@MAN1EXT@),
 .BR \%grotty (@MAN1EXT@).
 .
 .TP

Index: src/utils/afmtodit/afmtodit.man
===================================================================
RCS file: /cvsroot/groff/groff/src/utils/afmtodit/afmtodit.man,v
retrieving revision 1.19
retrieving revision 1.20
diff -u -b -r1.19 -r1.20
--- src/utils/afmtodit/afmtodit.man     4 Jun 2010 05:38:49 -0000       1.19
+++ src/utils/afmtodit/afmtodit.man     26 Jul 2011 17:11:12 -0000      1.20
@@ -1,6 +1,5 @@
 .ig
-Copyright (C) 1989-2000, 2001, 2002, 2003, 2005, 2006, 2008, 2009,
-              2010
+Copyright (C) 1989-2003, 2005, 2006, 2008-2011
   Free Software Foundation, Inc.
 
 Permission is granted to make and distribute verbatim copies of
@@ -37,7 +36,7 @@
 .
 .
 .SH NAME
-afmtodit \- create font files for use with groff \-Tps
+afmtodit \- create font files for use with groff \-Tps and \-Tpdf
 .
 .
 .SH SYNOPSIS
@@ -65,8 +64,10 @@
 .
 .SH DESCRIPTION
 .B afmtodit
-creates a font file for use with groff and
-.BR grops .
+creates a font file for use with groff,
+.BR grops ,
+and
+.BR gropdf .
 .
 .B afmtodit
 is written in perl;

Index: src/utils/pfbtops/pfbtops.man
===================================================================
RCS file: /cvsroot/groff/groff/src/utils/pfbtops/pfbtops.man,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -b -r1.5 -r1.6
--- src/utils/pfbtops/pfbtops.man       5 Jan 2009 20:11:15 -0000       1.5
+++ src/utils/pfbtops/pfbtops.man       26 Jul 2011 17:11:12 -0000      1.6
@@ -1,5 +1,5 @@
 .ig
-Copyright (C) 1989-1995, 2001, 2003, 2004, 2009
+Copyright (C) 1989-1995, 2001, 2003, 2004, 2009, 2011
   Free Software Foundation, Inc.
 
 Permission is granted to make and distribute verbatim copies of
@@ -53,7 +53,9 @@
 .LP
 The resulting ASCII format PostScript font can be used with groff.
 It must first be listed in
-.BR @FONTDIR@/devps/download .
+.B @FONTDIR@/devps/download
+and
+.BR @FONTDIR@/devpdf/download .
 .
 .SH OPTIONS
 .TP
@@ -62,7 +64,8 @@
 .
 .
 .SH "SEE ALSO"
-.BR grops (@MAN1EXT@)
+.BR grops (@MAN1EXT@),
+.BR gropdf (@MAN1EXT@)
 .
 .\" Local Variables:
 .\" mode: nroff

Index: tmac/Makefile.sub
===================================================================
RCS file: /cvsroot/groff/groff/tmac/Makefile.sub,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -b -r1.50 -r1.51
--- tmac/Makefile.sub   28 Jan 2011 10:26:33 -0000      1.50
+++ tmac/Makefile.sub   26 Jul 2011 17:11:12 -0000      1.51
@@ -37,6 +37,7 @@
   safer.tmac \
   trace.tmac \
   ps.tmac psold.tmac pspic.tmac psatk.tmac \
+  pdf.tmac \
   dvi.tmac \
   tty.tmac tty-char.tmac \
   latin1.tmac latin2.tmac latin5.tmac latin9.tmac cp1047.tmac \

Index: tmac/troffrc
===================================================================
RCS file: /cvsroot/groff/groff/tmac/troffrc,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -b -r1.15 -r1.16
--- tmac/troffrc        1 Jul 2006 22:49:22 -0000       1.15
+++ tmac/troffrc        26 Jul 2011 17:11:12 -0000      1.16
@@ -10,6 +10,7 @@
 .\" The groff command defines the .X string if the -X option was given.
 .ie r.X .do ds troffrc!ps Xps.tmac
 .el .do ds troffrc!ps ps.tmac
+.do ds troffrc!pdf pdf.tmac
 .do ds troffrc!dvi dvi.tmac
 .do ds troffrc!X75 X.tmac
 .do ds troffrc!X75-12 X.tmac
@@ -25,7 +26,7 @@
 .do if d troffrc!\*[.T] \
 .      do mso \*[troffrc!\*[.T]]
 .do rm troffrc!ps troffrc!Xps troffrc!dvi troffrc!X75 troffrc!X75-12 \
-troffrc!X100 troffrc!X100-12 troffrc!lj4 troff!lbp troffrc!html
+troffrc!X100 troffrc!X100-12 troffrc!lj4 troff!lbp troffrc!html troffrc!pdf
 .
 .\" Test whether we work under EBCDIC and map the no-breakable space
 .\" character accordingly.

Index: font/devpdf/DESC.in
===================================================================
RCS file: font/devpdf/DESC.in
diff -N font/devpdf/DESC.in
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ font/devpdf/DESC.in 26 Jul 2011 17:11:10 -0000      1.1
@@ -0,0 +1,11 @@
+res 72000
+hor 1
+vert 1
+sizescale 1000
+unitwidth 1000
+sizes 1000-10000000 0
+styles R I B BI
+family T
+fonts 8 0 0 0 0 0 0 S ZD
+tcommand
+postpro gropdf

Index: font/devpdf/Foundry
===================================================================
RCS file: font/devpdf/Foundry
diff -N font/devpdf/Foundry
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ font/devpdf/Foundry 26 Jul 2011 17:11:10 -0000      1.1
@@ -0,0 +1,114 @@
+# Foundry file
+
+# Copyright (C) 2011 Free Software Foundation, Inc.
+#      Written by Deri James <address@hidden>
+#
+# This file is part of groff.
+#
+# groff 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 3 of the License, or
+# (at your option) any later version.
+#
+# groff 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, see <http://www.gnu.org/licenses/>.
+
+#=====================================================================
+#Foundry|Name|Searchpath
+foundry||(gs)
+
+# These are just copies of the grops fonts so MUST not have any flags etc set
+
+#Font|IsBase14|Flags|Map|Encoding|File
+AB|N||||URWGothicL-Demi
+ABI|N||||URWGothicL-DemiObli
+AI|N||||URWGothicL-BookObli
+AR|N||||URWGothicL-Book
+BMB|N||||URWBookmanL-DemiBold
+BMBI|N||||URWBookmanL-DemiBoldItal
+BMI|N||||URWBookmanL-LighItal
+BMR|N||||URWBookmanL-Ligh
+CB|Y||||NimbusMonL-Bold
+CBI|Y||||NimbusMonL-BoldObli
+CI|Y||||NimbusMonL-ReguObli
+CR|Y||||NimbusMonL-Regu
+EURO|N||||../devps/freeeuro.pfa
+HB|Y||||NimbusSanL-Bold
+HBI|Y||||NimbusSanL-BoldItal
+HI|Y||||NimbusSanL-ReguItal
+HNB|N||||NimbusSanL-BoldCond
+HNBI|N||||NimbusSanL-BoldCondItal
+HNI|N||||NimbusSanL-ReguCondItal
+HNR|N||||NimbusSanL-ReguCond
+HR|Y||||NimbusSanL-Regu
+NB|N||||CenturySchL-Bold
+NBI|N||||CenturySchL-BoldItal
+NI|N||||CenturySchL-Ital
+NR|N||||CenturySchL-Roma
+PB|N||||URWPalladioL-Bold
+PBI|N||||URWPalladioL-BoldItal
+PI|N||||URWPalladioL-Ital
+PR|N||||URWPalladioL-Roma
+S|Y||||StandardSymL
+TB|Y||||NimbusRomNo9L-Medi
+TBI|Y||||NimbusRomNo9L-MediItal
+TI|Y||||NimbusRomNo9L-ReguItal
+TR|Y||||NimbusRomNo9L-Regu
+ZCMI|N||||URWChanceryL-MediItal
+ZD|Y||||Dingbats
+
+#======================================================================
+
+#Foundry|Name|Searchpath
+foundry|U|(gs) # the URW fonts delivered with ghostscript (may be different)
+
+#Define Flags for afmtodit
+
+r=-i 0 -m
+i=-i 50
+n=-n
+s=-s
+
+#Font|IsBase14|Flags|Map|Encoding|File
+AB|N|r|textmap|text.enc|a010015l.pfb
+ABI|N|i|textmap|text.enc|a010035l.pfb
+AI|N|i|textmap|text.enc|a010033l.pfb
+AR|N|r|textmap|text.enc|a010013l.pfb
+BMB|N|r|textmap|text.enc|b018015l.pfb
+BMBI|N|i|textmap|text.enc|b018035l.pfb
+BMI|N|i|textmap|text.enc|b018032l.pfb
+BMR|N|r|textmap|text.enc|b018012l.pfb
+CB|N|nr|textmap|text.enc|n022004l.pfb
+CBI|N|ni|textmap|text.enc|n022024l.pfb
+CI|N|ni|textmap|text.enc|n022023l.pfb
+CR|N|nr|textmap|text.enc|n022003l.pfb
+HB|N|r|textmap|text.enc|n019004l.pfb
+HBI|N|i|textmap|text.enc|n019024l.pfb
+HI|N|i|textmap|text.enc|n019023l.pfb
+HNB|N|r|textmap|text.enc|n019044l.pfb
+HNBI|N|i|textmap|text.enc|n019064l.pfb
+HNI|N|i|textmap|text.enc|n019063l.pfb
+HNR|N|r|textmap|text.enc|n019043l.pfb
+HR|N|r|textmap|text.enc|n019003l.pfb
+NB|N|r|textmap|text.enc|c059016l.pfb
+NBI|N|i|textmap|text.enc|c059036l.pfb
+NI|N|i|textmap|text.enc|c059033l.pfb
+NR|N|r|textmap|text.enc|c059013l.pfb
+PB|N|r|textmap|text.enc|p052004l.pfb
+PBI|N|i|textmap|text.enc|p052024l.pfb
+PI|N|i|textmap|text.enc|p052023l.pfb
+PR|N|r|textmap|text.enc|p052003l.pfb
+S|N|sr|symbolmap||s050000l.pfb
+TB|N|r|textmap|text.enc|n021004l.pfb
+TBI|N|i|textmap|text.enc|n021024l.pfb
+TI|N|i|textmap|text.enc|n021023l.pfb
+TR|N|r|textmap|text.enc|n021003l.pfb
+ZCMI|N|i|textmap|text.enc|z003034l.pfb
+ZD|N|sr|dingbats.map||d050000l.pfb
+
+#======================================================================

Index: font/devpdf/Makefile.sub
===================================================================
RCS file: font/devpdf/Makefile.sub
diff -N font/devpdf/Makefile.sub
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ font/devpdf/Makefile.sub    26 Jul 2011 17:11:10 -0000      1.1
@@ -0,0 +1,107 @@
+# Copyright (C) 2011 Free Software Foundation, Inc.
+#      Written by Deri James <address@hidden>
+#
+# This file is part of groff.
+#
+# groff 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 3 of the License, or
+# (at your option) any later version.
+#
+# groff 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, see <http://www.gnu.org/licenses/>.
+
+DEV=pdf
+GROFF_FONT_FILES=`cd $(DESTDIR)$(fontsubdir); \
+                  grep -l internalname * | grep -v Makefile.sub`
+ENC_FILES=`cd $(DESTDIR)$(fontsubdir); ls enc`
+MAP_FILES=`cd $(DESTDIR)$(fontsubdir); ls map`
+
+UTILFILES=\
+  BuildFoundries
+
+MOSTLYCLEANADD=\
+  download \
+  DESC \
+  util/BuildFoundries \
+  $(GROFF_FONT_FILES) \
+  $(ENC_FILES) \
+  $(MAP_FILES)
+#MOSTLYCLEANDIRADD=enc map
+
+DEVFILES=\
+  Foundry
+#DEVSCRIPTS=util/BuildFoundries
+
+DISTFILES=\
+  $(DEVFILES) \
+  $(DEVSCRIPTS)
+
+
+# Some `makes' don't predefine RM...
+RM=rm -f
+
+
+all: DESC BuildFoundries
+
+DESC: DESC.in
+       -rm -f DESC
+       cat $(srcdir)/DESC.in >DESC
+       if test "$(PAGE)" = A4; then \
+         echo "papersize a4" >>DESC; \
+       else \
+         echo "papersize letter" >>DESC; \
+       fi
+
+BuildFoundries: util/BuildFoundries.pl $(SH_DEPS_SED_SCRIPT)
+       -test -d util || $(mkinstalldirs) util
+       $(RM) util/$@
+       sed -f $(SH_DEPS_SED_SCRIPT) \
+           -e "s|@VERSION@|$(version)$(revision)|" \
+           -e "s|@PERLPATH@|$(PERLPATH)|" \
+           -e "s|@GROFF_FONT_DIR@|$(fontdir)|" 
$(srcdir)/util/BuildFoundries.pl > util/$@
+       chmod +x util/$@
+
+install_data:
+       -test -d $(DESTDIR)$(fontsubdir) \
+         || $(mkinstalldirs) $(DESTDIR)$(fontsubdir)
+       -test -d $(DESTDIR)$(fontsubdir)/enc \
+         || $(mkinstalldirs) $(DESTDIR)$(fontsubdir)/enc
+       -test -d $(DESTDIR)$(fontsubdir)/map \
+         || $(mkinstalldirs) $(DESTDIR)$(fontsubdir)/map
+       for f in $(MOSTLYCLEANADD); do \
+         $(RM) $(DESTDIR)$(fontsubdir)/$$f; \
+         if test -f $$f; then \
+           $(INSTALL_DATA) $$f $(DESTDIR)$(fontsubdir)/$$f; \
+         else \
+           $(INSTALL_DATA) $(srcdir)/$$f $(DESTDIR)$(fontsubdir)/$$f; \
+         fi; \
+       done
+       $(RM) $@
+       cp -f $(DESTDIR)$(fontdir)/devps/text.enc \
+         $(DESTDIR)$(fontsubdir)/enc
+       cp -f $(srcdir)/../devps/symbolmap \
+         $(DESTDIR)$(fontsubdir)/map
+       cp -f $(DESTDIR)$(fontdir)/devps/generate/dingbats.map \
+         $(DESTDIR)$(fontsubdir)/map
+       cp -f $(DESTDIR)$(fontdir)/devps/generate/textmap \
+         $(DESTDIR)$(fontsubdir)/map
+       cp -f $(DESTDIR)$(fontdir)/devps/generate/symbolchars \
+         $(DESTDIR)$(fontsubdir)/map
+       echo "# foundry ps name psfile" > $(DESTDIR)$(fontsubdir)/download
+       util/BuildFoundries $(DESTDIR)$(fontsubdir) \
+         > $(DESTDIR)$(fontsubdir)/download
+
+uninstall_sub:
+       for f in $(MOSTLYCLEANADD); do \
+         $(RM) $(DESTDIR)$(fontsubdir)/$$f; \
+       done
+       rmdir $(DESTDIR)$(fontsubdir)/enc
+       rmdir $(DESTDIR)$(fontsubdir)/map
+       rmdir $(DESTDIR)$(fontsubdir)/util
+       rmdir $(DESTDIR)$(fontsubdir)

Index: font/devpdf/util/BuildFoundries.pl
===================================================================
RCS file: font/devpdf/util/BuildFoundries.pl
diff -N font/devpdf/util/BuildFoundries.pl
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ font/devpdf/util/BuildFoundries.pl  26 Jul 2011 17:11:10 -0000      1.1
@@ -0,0 +1,439 @@
address@hidden@ -w
+#
+#  BuildFoundries: Given a Foundry file generate groff and download files
+#  Deri James:     Monday 07 Feb 2011
+
+# Copyright (C) 2011 Free Software Foundation, Inc.
+#      Written by Deri James <address@hidden>
+#
+# This file is part of groff.
+#
+# groff 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 3 of the License, or
+# (at your option) any later version.
+#
+# groff 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, see <http://www.gnu.org/licenses/>.
+
+use strict;
+
+my $where=shift||'';
+chdir $where if $where ne '';
+my (%foundry,%flg,@downloadpreamble,%download);
+my $GSpath=FindGSpath();
+my $warn=0;
+my $lct=0;
+my $foundry='';        # the default foundry
+
+LoadDownload("download");
+LoadFoundry("Foundry");
+WriteDownload("download");
+
+exit $warn;
+
+
+sub LoadFoundry
+{
+    my $fn=shift;
+    my $foundrypath='';
+
+    open(F,"<$fn") or die "No $fn file found";
+
+    while (<F>)
+    {
+       chomp;
+       $lct++;
+       s/\r$//;        # in case edited in windows
+
+       s/\s*#.*?$//;   # remove comments
+
+       next if $_ eq '';
+
+       if (m/^[A-Za-z]=/)
+       {
+           my (@f)=split('=');
+           $flg{$f[0]}=$f[1];
+           next;
+       }
+
+       my (@r)=split('\|');
+
+       if (lc($r[0]) eq 'foundry')
+       {
+           $foundry=uc($r[1]);
+           $foundrypath=$r[2];
+       }
+       else
+       {
+           # 0=groff font name
+           # 1=IsBase Y/N (one of PDFs 14 base fonts)
+           # 2=afmtodit flag
+           # 3=map file
+           # 4=encoding file
+           # 5=font file
+           # 6=afm file
+
+           if (!defined($r[6]) or $r[6] eq '')
+           {
+               # if no afm file, have a guess!
+               $r[6]=substr($r[5],0,-3)."afm";
+           }
+
+           my $gfont=($foundry eq '')?$r[0]:"$foundry-$r[0]";
+
+           if ($r[2] eq '')
+           {
+               # Don't run afmtodit, just copy the grops font file
+
+               my $gotf=1;
+
+               if (-r "../devps/$r[0]")
+               {
+                   my $psfont=UseGropsVersion($r[0]);
+                   if 
(!PutDownload($psfont,LocatePF($foundrypath,$r[5]),uc($r[1])))
+                   {
+                       if (uc($r[1]) ne 'Y')
+                       {
+                           $gotf=0;
+                           Msg(0,"Unable to locate font '$r[5]' on the given 
path(s)");
+                           unlink $gfont;      # Unable to find the postscript 
file for the font just created by afmtodit
+                       }
+                   }
+                   print STDERR "Copied grops font $gfont...\n" if $gotf;
+               }
+               else
+               {
+                   Msg(0,"Can't read grops font '$r[0]' for Foundry 
'$foundry'");
+               }
+           }
+           else
+           {
+               # We need to run afmtodit to create this groff font
+               my 
$psfont=RunAfmtodit($gfont,LocateAF($foundrypath,$r[6]),$r[2],$r[3],$r[4]);
+
+               if ($psfont)
+               {
+                   if 
(!PutDownload($psfont,LocatePF($foundrypath,$r[5]),uc($r[1])))
+                   {
+                       unlink $gfont;  # Unable to find the postscript file 
for the font just created by afmtodit
+                   }
+                   else
+                   {
+                       print STDERR "Generated $gfont...\n";
+                   }
+               }
+               else
+               {
+                   Msg(0,"Failed to create groff font '$gfont' by running 
afmtodit");
+               }
+           }
+       }
+    }
+
+    close();
+}
+
+sub RunAfmtodit
+{
+    my $gfont=shift;
+    my $afmfile=shift;
+    my $flags=shift;
+    my $map=shift||'';
+    my $enc=shift||'';
+    my $psfont='';
+
+    $enc="-e 'enc/$enc'" if $enc;
+    $map="'map/$map'" if $map;
+
+    my $cmd='afmtodit -c -dDESC';
+
+    foreach my $f (split('',$flags))
+    {
+       if (!exists($flg{$f}))
+       {
+           Msg(0,"Can't use undefined flag '$f' in calling afmtodit for groff 
font '$gfont'");
+           return('');
+       }
+
+       $cmd.=" $flg{$f}";
+    }
+
+    system("$cmd $enc '$afmfile' $map $gfont 2>/dev/null");
+
+    if ($?)
+    {
+       unlink $gfont;
+       return('');
+    }
+
+    if (open(GF,"<$gfont"))
+    {
+       my (@gf)=(<GF>);
+       my @ps=grep(/^internalname /,@gf);
+       if ($#ps == 0)  # Just 1 match
+       {
+           (undef,$psfont)=split(' ',$ps[0],2);
+           chomp($psfont);
+       }
+       else
+       {
+           Msg(0,"Unexpected format for grops font '$gfont' for Foundry 
'$foundry' - ignoring");
+       }
+
+       close(GF);
+    }
+
+    return($psfont);
+}
+
+sub LocateAF
+{
+    my $path=shift;
+    my $file=shift;
+
+    return(LocateFile($path,$file,1));
+}
+
+sub LocatePF
+{
+    my $path=shift;
+    my $file=shift;
+
+    return(LocateFile($path,$file,0));
+}
+
+sub LocateFile
+{
+    my $path=shift;
+    my $file=shift;
+    my $tryafm=shift;
+
+    if ($file=~m'/')
+    {
+       # path given with file name so no need to search the paths
+
+       if (-r $file)
+       {
+           return($file);
+       }
+
+       if ($tryafm and $file=~s'type1/'afm/'i)
+       {
+           if (-r "$file")
+           {
+               return($file);
+           }
+       }
+
+       return('');
+    }
+
+    if ($path eq '(gs)')
+    {
+       $path=$GSpath;
+    }
+    elsif ($path eq '(tex)')
+    {
+       my $res=`kpsewhich $file`;
+       return '' if $?;
+       chomp($res);
+       return($res);
+    }
+
+    my (@paths)=split(':',$path);
+
+    foreach my $p (@paths)
+    {
+       $p=~s/^\s+//;
+       $p=~s/\s+$//;
+
+       next if $p=~m/^\%rom\%/;        # exclude %rom% paths (from (gs))
+
+       if (-r "$p/$file")
+       {
+           return("$p/$file");
+       }
+
+       if ($tryafm and $p=~s'type1/'afm/'i)
+       {
+           if (-r "$p/$file")
+           {
+               return("$p/$file");
+           }
+       }
+    }
+
+    return('');
+}
+
+sub FindGSpath
+{
+    my (@res)=`gs -h 2>/dev/null`;
+    return '' if $?;
+    my $buildpath='';
+    my $stg=1;
+
+    foreach my $l (@res)
+    {
+       chomp($l);
+
+       if ($stg==1 and $l=~m/^Search path:/)
+       {
+           $stg=2;
+       }
+       elsif ($stg == 2)
+       {
+           if (substr($l,0,1) ne ' ')
+           {
+               $stg=3;
+           }
+           else
+           {
+               $l=~s/^\s+//;
+               $buildpath.=$l;
+           }
+       }
+    }
+
+    return($buildpath);
+}
+
+sub UseGropsVersion
+{
+    my $gfont=shift;
+    my $psfont='';
+
+    if (open(GF,"<../devps/$gfont"))
+    {
+       my (@gf)=(<GF>);
+       my @ps=grep(/^internalname /,@gf);
+       if ($#ps == 0)  # Just 1 match
+       {
+           (undef,$psfont)=split(' ',$ps[0],2);
+           chomp($psfont);
+       }
+       else
+       {
+           Msg(0,"Unexpected format for grops font '$gfont' for Foundry 
'$foundry' - ignoring");
+       }
+
+       close(GF);
+
+       if ($psfont)
+       {
+           if (open(GF,">$gfont"))
+           {
+               local $"='';
+               print GF "@gf";
+               close(GF);
+           }
+           else
+           {
+               $psfont='';
+               Msg(0,"Failed to create new font '$gfont' for Foundry 
'$foundry'");
+           }
+       }
+       else
+       {
+           Msg(0,"Failed to locate postscript internalname in grops font 
'$gfont' for Foundry '$foundry'");
+       }
+
+       close(GF);
+    }
+    else
+    {
+       Msg(0,"Failed to open grops font '$gfont' for Foundry '$foundry'");
+    }
+
+    return($psfont);
+}
+
+sub PutDownload
+{
+    my $psfont=shift;
+    my $pffile=shift;
+    my $IsBase14=shift;
+    my $key="$foundry $psfont";
+
+    delete($download{$key}), return 0 if ($pffile eq '');
+
+    $pffile='*'.$pffile if $IsBase14 eq 'Y'; # This signals to gropdf to only 
edmbed if -e given
+    $download{$key}=$pffile;
+
+    return 1;
+}
+
+sub LoadDownload
+{
+    my $fn=shift;
+    my $top=1;
+
+    return if !open(F,"<$fn");
+
+    while (<F>)
+    {
+       chomp;
+       s/\r$//;        # in case edited in windows
+
+       if ($top and substr($_,0,1) eq '#' or $_ eq '')
+       {
+           # Preserve comments at top of download file
+
+           push(@downloadpreamble,$_);
+           next;
+       }
+
+       $top=0;
+       s/\s*#.*?$//;   # remove comments
+
+       next if $_ eq '';
+
+       my (@r)=split(/\t+/);
+       my $key=$r[1];
+       $key="$r[0] $r[1]";
+       $download{$key}=$r[2];
+    }
+
+    close(F);
+}
+
+sub WriteDownload
+{
+    my $fn=shift;
+    my $top=1;
+
+    open(F,">$fn") or die "Can't Create new file '$fn'";
+
+    print F join("\n",@downloadpreamble),"\n";
+
+    foreach my $k (sort keys %download)
+    {
+       my ($f,$ps)=split(/ /,$k);
+       print F "$f\t$ps\t$download{$k}\n";
+    }
+
+    close(F);
+}
+
+sub Msg
+{
+    my $sev=shift;
+    my $msg=shift;
+
+    if ($sev)
+    {
+       print STDERR "Error: line $lct: $msg\n";
+       exit 2;
+    }
+    else
+    {
+       print STDERR "Warning: line $lct: $msg\n";
+       $warn=1;
+    }
+}

Index: font/devpdf/util/Makefile.sub
===================================================================
RCS file: font/devpdf/util/Makefile.sub
diff -N font/devpdf/util/Makefile.sub
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ font/devpdf/util/Makefile.sub       26 Jul 2011 17:11:10 -0000      1.1
@@ -0,0 +1,38 @@
+# Copyright (C) 2011 Free Software Foundation, Inc.
+#      Written by Deri James <address@hidden>
+#
+# This file is part of groff.
+#
+# groff 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 3 of the License, or
+# (at your option) any later version.
+#
+# groff 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, see <http://www.gnu.org/licenses/>.
+
+DEV=pdf
+UTILFILES=\
+  BuildFoundries
+
+#MOSTLYCLEANADD=BuildFoundries
+
+# Some `makes' don't predefine RM...
+RM=rm -f
+
+
+all: BuildFoundries
+
+
+BuildFoundries: BuildFoundries.pl $(SH_DEPS_SED_SCRIPT)
+       $(RM) $@
+       sed -f $(SH_DEPS_SED_SCRIPT) \
+           -e "s|@VERSION@|$(version)$(revision)|" \
+           -e "s|@PERLPATH@|$(PERLPATH)|" \
+           -e "s|@GROFF_FONT_DIR@|$(fontdir)|" $(srcdir)/BuildFoundries.pl >$@
+       chmod +x $@

Index: src/devices/gropdf/Makefile.sub
===================================================================
RCS file: src/devices/gropdf/Makefile.sub
diff -N src/devices/gropdf/Makefile.sub
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/devices/gropdf/Makefile.sub     26 Jul 2011 17:11:11 -0000      1.1
@@ -0,0 +1,54 @@
+# Copyright (C) 2011 Free Software Foundation, Inc.
+#      Written by Deri James <address@hidden>
+#
+# This file is part of groff.
+#
+# groff 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 3 of the License, or
+# (at your option) any later version.
+#
+# groff 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, see <http://www.gnu.org/licenses/>.
+
+MAN1=\
+  gropdf.n
+
+CMDFILES=\
+  gropdf
+
+MOSTLYCLEANADD=\
+  gropdf \
+  $(MAN1)
+
+# Some `makes' don't predefine RM...
+RM=rm -f
+
+
+all: gropdf 
+
+
+gropdf: gropdf.pl $(SH_DEPS_SED_SCRIPT)
+       $(RM) $@
+       sed -f $(SH_DEPS_SED_SCRIPT) \
+           -e "s|@VERSION@|$(version)$(revision)|" \
+           -e "s|@PERLPATH@|$(PERLPATH)|" \
+           -e "s|@GROFF_FONT_DIR@|$(fontdir)|" $(srcdir)/gropdf.pl >$@
+       chmod +x $@
+
+install_data:
+       -test -d $(DESTDIR)$(bindir) || $(mkinstalldirs) $(DESTDIR)$(bindir)
+       for f in $(CMDFILES); do \
+         $(RM) $(DESTDIR)$(bindir)/$$f; \
+         $(INSTALL_SCRIPT) $$f $(DESTDIR)$(bindir)/$$f; \
+       done
+
+uninstall_sub:
+       for f in $(CMDFILES); do \
+         $(RM) $(DESTDIR)$(bindir)/$$f; \
+       done

Index: src/devices/gropdf/TODO
===================================================================
RCS file: src/devices/gropdf/TODO
diff -N src/devices/gropdf/TODO
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/devices/gropdf/TODO     26 Jul 2011 17:11:11 -0000      1.1
@@ -0,0 +1,31 @@
+pspic.tmac
+----------
+
+Equiv for gropdf is pdfpic (which is dependant on a program
+pdfbb (to extract MediaBox (etc.) from the pdf) which is not written yet!
+Meanwhile you could use \X'pdf: pdfpic filename -L|R|C wid (hgt) (linelen)'
+(-R and -C require a linelen) Wid or hgt may be zero (in which case the same
+scaling as the other axis is used).  The disadvantage of this call (over
+pdfpic macro) is that it is transparent to groff, after placing the image
+the current X/Y position remains what it was, so you need to do your own
+'motion control' (like a .sp) to "step over" the image you just placed.
+
+psfig.tmac
+----------
+
+No equiv for gropdf.
+
+psatk.tmac
+----------
+
+No equiv for gropdf.
+
+-I : search -I directory for included files
+
+-w : set line width
+
+Another \X : \X'ps: exec 0 setlinejoin'\X'ps: exec 0 setlinecap' for mom
+
+Cater for fonts with >255 glyphs (currently  accessing a glyph above 255
+(i.e. \N[260]) causes a fail).  This will be fixed when font subsetting is
+implemented.

Index: src/devices/gropdf/gropdf.man
===================================================================
RCS file: src/devices/gropdf/gropdf.man
diff -N src/devices/gropdf/gropdf.man
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/devices/gropdf/gropdf.man       26 Jul 2011 17:11:11 -0000      1.1
@@ -0,0 +1,1069 @@
+.ig
+Copyright (C) 2011
+  Free Software Foundation, Inc.
+
+Permission is granted to make and distribute verbatim copies of
+this manual provided the copyright notice and this permission notice
+are preserved on all copies.
+
+Permission is granted to copy and distribute modified versions of this
+manual under the conditions for verbatim copying, provided that the
+entire resulting derived work is distributed under the terms of a
+permission notice identical to this one.
+
+Permission is granted to copy and distribute translations of this
+manual into another language, under the above conditions for modified
+versions, except that this permission notice may be included in
+translations approved by the Free Software Foundation instead of in
+the original English.
+..
+.
+.
+.\" Like TP, but if specified indent is more than half
+.\" the current line-length - indent, use the default indent.
+.de Tp
+.  ie \\n(.$=0:((0\\$1)*2u>(\\n(.lu-\\n(.iu)) .TP
+.  el .TP "\\$1"
+..
+.de TQ
+.  br
+.  ns
+.  TP \$1
+..
+.
+.de FT
+.  if '\\*(.T'ps' .ft \\$1
+.  if '\\*(.T'pdf' .ft \\$1
+..
+.
+.
+.TH GROPDF @MAN1EXT@ "@MDATE@" "Groff Version @VERSION@"
+.
+.
+.SH NAME
+.
+gropdf \- PDF driver for groff
+.
+.
+.SH SYNOPSIS
+.
+.SY gropdf
+.OP \-delv
+.OP \-F dir
+\#.OP \-I dir
+.OP \-p papersize
+\#.OP \-w n
+.OP \-fy foundry
+.RI [ files
+.IR .\|.\|. ]
+.YS
+.
+.LP
+It is possible to have whitespace between a command line option and its
+parameter.
+.
+.
+.SH DESCRIPTION
+.
+.B gropdf
+translates the output of GNU
+.B troff
+to PDF.
+.
+Normally
+.B gropdf
+should be invoked by using the groff command
+with a
+.B \-Tpdf
+option.
+.
+If no files are given,
+.B gropdf
+reads the standard input.
+.
+A filename of
+.B \-
+also causes
+.B grops
+to read the standard input.
+.
+PDF output is written to the standard output.
+.
+When
+.B gropdf
+is run by
+.B groff
+options can be passed to
+.B gropdf
+using
+.BR groff 's
+.B \-P
+option.
+.
+.LP
+See section
+.B FONT INSTALLATION
+below for a guide how to install fonts for
+.BR gropdf .
+.
+.
+.SH OPTIONS
+.
+.TP
+.B \-d
+Include debug information as comments within the PDF.
+Also produces an uncompressed PDF.
+.
+.TP
+.B \-e
+Force all fonts to be embedded in the PDF.
+.
+.TP
+.BI \-F dir
+Prepend directory
+.IB dir /dev name
+to the search path for font, and device description files;
+.I name
+is the name of the device, usually
+.BR pdf .
+.
+.\" .TP
+.\" .BI \-I dir
+.\" This option may be used to add a directory to the search path for
+.\" files on the command line and files named in
+.\" .B \[rs]X'ps: import'
+.\" and
+.\" .B \[rs]X'ps: file'
+.\" escapes.
+.\" .
+.\" The search path is initialized with the current directory.
+.\" .
+.\" This option may be specified more than once; the directories are then
+.\" searched in the order specified (but before the current directory).
+.\" .
+.\" If you want to make the current directory be read before other directories,
+.\" add
+.\" .B \-I.\&
+.\" at the appropriate place.
+.\" .
+.\" .IP
+.\" No directory search is performed for files with an absolute file name.
+.\" .
+.\" .TP
+.
+.TP
+.B \-l
+Print the document in landscape format.
+.
+.TP
+.BI \-p paper-size
+Set physical dimension of output medium.
+.
+This overrides the
+.BR papersize ,
+.BR paperlength ,
+and
+.B paperwidth
+commands in the
+.B DESC
+file; it accepts the same arguments as the
+.B papersize
+command.
+.
+See
+.B groff_font (@MAN5EXT@)
+for details.
+.
+.\" .TP
+.\" .BI \-w n
+.\" Lines should be drawn using a thickness of
+.\" .IR n \~\c
+.\" thousandths of an em.
+.\" .
+.\" If this option is not given, the line thickness defaults to 0.04\~em.
+.\" .
+.
+.TP
+.B \-v
+Print the version number.
+.
+.TP
+.BI \-fy foundry
+Set the foundry to use for selecting fonts of the same name.
+.
+.TP
+.B \-e
+Forces gropdf to embed ALL fonts (even the 14 base PDF fonts). 
+.
+.
+.SH USAGE
+.
+The input to
+.B gropdf
+must be in the format output by
+.BR @address@hidden (@MAN1EXT@).
+.
+This is described in
+.BR groff_out (@MAN5EXT@).
+.
+.LP
+In addition, the device and font description files for the device used
+must meet certain requirements:
+.
+The resolution must be an integer multiple of\~72 times the
+.BR sizescale .
+.
+The
+.B pdf
+device uses a resolution of 72000 and a sizescale of 1000.
+.
+.LP
+The device description file must contain a valid paper size; see
+.BR groff_font (@MAN5EXT@)
+for more information.
+.
+.B gropdf
+uses the same Type\~1 Adobe postscript fonts as the
+.B grops
+device driver.
+.
+Although the PDF Standard allows the use of other font types (like TrueType)
+this implementation only accepts the Type\~1 postscript font.
+.
+Fewer Type\~1 fonts are supported natively in PDF documents than
+the standard 35 fonts supported by
+.B grops
+and all postscript printers, but all the fonts are available since any
+which aren't supported natively are automatically embedded in the PDF.
+.
+.LP
+.B gropdf
+supports the concept of foundries, that is different versions of basically
+the same font.
+.
+During install a
+.B Foundry
+file controls where fonts are found and builds
+.B groff
+fonts from the files it discovers on your system.
+.
+.LP
+Each font description file must contain a command
+.
+.IP
+.BI internalname\  psname
+.
+.LP
+which says that the PostScript name of the font is
+.IR psname .
+.
+Lines starting with
+.B #
+and blank lines are ignored.
+.
+The code for each character given in the font file must correspond
+to the code in the default encoding for the font.
+.
+This code can be used with the
+.B \[rs]N
+escape sequence in
+.B troff
+to select the character,
+even if the character does not have a groff name.
+.
+Every character in the font file must exist in the PostScript font, and
+the widths given in the font file must match the widths used
+in the PostScript font.
+.
+.LP
+Note that
+.B gropdf
+is currently only able to display the first 256 glyphs in any font.
+This restriction will be lifted in a later version.
+.
+.\" .LP
+.\" Note that
+.\" .B grops
+.\" is able to display all glyphs in a PostScript font, not only 256.
+.\" .I enc_file
+.\" (or the default encoding if no encoding file specified) just defines the
+.\" order of glyphs for the first 256 characters; all other glyphs are
+.\" accessed with additional encoding vectors which
+.\" .B grops
+.\" produces on the fly.
+.
+.LP
+.B gropdf
+can automatically include the downloadable fonts necessary
+to print the document.
+.
+Fonts may be in PFA or PFB format.
+.LP
+.
+Any downloadable fonts which should, when required, be included by
+.B gropdf
+must be listed in the file
+.BR @FONTDIR@/devpdf/download ;
+this should consist of lines of the form
+.
+.IP
+.I
+foundry font filename
+.
+.LP
+where
+.I foundry
+is the foundry name or blank for the default foundry.
+.
+.I font
+is the PostScript name of the font,
+and
+.I filename
+is the name of the file containing the font;
+lines beginning with
+.B #
+and blank lines are ignored;
+fields must be separated by tabs;
+.I filename
+is searched for using the same mechanism that is used
+for groff font metric files.
+.
+The
+.B download
+file itself is also searched for using this mechanism;
+currently, only the first found file in the font path is used.
+.
+Foundry names are usually a single character (such as `U' for the URW
+Foundry) or blank for the default foundry.
+.
+This default uses the same fonts as
+.B ghostscript
+uses when it embeds fonts in a PDF file.
+.
+.LP
+In the default setup there are styles called
+.BR R ,
+.BR I ,
+.BR B ,
+and
+.B BI
+mounted at font positions 1 to\~4.
+.
+The fonts are grouped into families
+.BR A ,
+.BR BM ,
+.BR C ,
+.BR H ,
+.BR HN ,
+.BR N ,
+.BR P ,
+and\~\c
+.B T
+having members in each of these styles:
+.
+.RS
+.TP
+.B AR
+.FT AR
+AvantGarde-Book
+.FT
+.
+.TQ
+.B AI
+.FT AI
+AvantGarde-BookOblique
+.FT
+.
+.TQ
+.B AB
+.FT AB
+AvantGarde-Demi
+.FT
+.
+.TQ
+.B ABI
+.FT ABI
+AvantGarde-DemiOblique
+.FT
+.
+.TQ
+.B BMR
+.FT BMR
+Bookman-Light
+.FT
+.
+.TQ
+.B BMI
+.FT BMI
+Bookman-LightItalic
+.FT
+.
+.TQ
+.B BMB
+.FT BMB
+Bookman-Demi
+.FT
+.
+.TQ
+.B BMBI
+.FT BMBI
+Bookman-DemiItalic
+.FT
+.
+.TQ
+.B CR
+.FT CR
+Courier
+.FT
+.
+.TQ
+.B CI
+.FT CI
+Courier-Oblique
+.FT
+.
+.TQ
+.B CB
+.FT CB
+Courier-Bold
+.FT
+.
+.TQ
+.B CBI
+.FT CBI
+Courier-BoldOblique
+.FT
+.
+.TQ
+.B HR
+.FT HR
+Helvetica
+.FT
+.
+.TQ
+.B HI
+.FT HI
+Helvetica-Oblique
+.FT
+.
+.TQ
+.B HB
+.FT HB
+Helvetica-Bold
+.FT
+.
+.TQ
+.B HBI
+.FT HBI
+Helvetica-BoldOblique
+.FT
+.
+.TQ
+.B HNR
+.FT HNR
+Helvetica-Narrow
+.FT
+.
+.TQ
+.B HNI
+.FT HNI
+Helvetica-Narrow-Oblique
+.FT
+.
+.TQ
+.B HNB
+.FT HNB
+Helvetica-Narrow-Bold
+.FT
+.
+.TQ
+.B HNBI
+.FT HNBI
+Helvetica-Narrow-BoldOblique
+.FT
+.
+.TQ
+.B NR
+.FT NR
+NewCenturySchlbk-Roman
+.FT
+.
+.TQ
+.B NI
+.FT NI
+NewCenturySchlbk-Italic
+.FT
+.
+.TQ
+.B NB
+.FT NB
+NewCenturySchlbk-Bold
+.FT
+.
+.TQ
+.B NBI
+.FT NBI
+NewCenturySchlbk-BoldItalic
+.FT
+.
+.TQ
+.B PR
+.FT PR
+Palatino-Roman
+.FT
+.
+.TQ
+.B PI
+.FT PI
+Palatino-Italic
+.FT
+.
+.TQ
+.B PB
+.FT PB
+Palatino-Bold
+.FT
+.
+.TQ
+.B PBI
+.FT PBI
+Palatino-BoldItalic
+.FT
+.
+.TQ
+.B TR
+.FT TR
+Times-Roman
+.FT
+.
+.TQ
+.B TI
+.FT TI
+Times-Italic
+.FT
+.
+.TQ
+.B TB
+.FT TB
+Times-Bold
+.FT
+.
+.TQ
+.B TBI
+.FT TBI
+Times-BoldItalic
+.FT
+.RE
+.
+.LP
+There is also the following font which is not a member of a family:
+.
+.RS
+.TP
+.B ZCMI
+.FT ZCMI
+ZapfChancery-MediumItalic
+.FT
+.RE
+.
+.LP
+There are also some special fonts called
+.B S
+for the PS Symbol font. The lower case greek characters are automatically
+slanted (to match the SymbolSlanted font (SS) available to postscript).
+.
+Zapf Dingbats is available as
+.BR ZD ,
+the "hand pointing left" glyph (\[rs]lh) is available since it
+has been defined using the \[rs]X'pdf: xrev' extension which reverses the
+direction of letters within words.
+.
+.LP
+The default color for
+.B \[rs]m
+and
+.B \[rs]M
+is black; for colors defined in the `rgb' color space
+.B setrgbcolor
+is used, for `cmy' and `cmyk'
+.BR setcmykcolor ,
+and for `gray'
+.BR setgray .
+.
+Note that
+.B setcmykcolor
+is a PostScript LanguageLevel\~2 command and thus not available on some
+older printers.
+.
+.LP
+.B gropdf
+understands some of the X\~commands produced using the
+.B \[rs]X
+escape sequences supported by
+.B grops.
+Specifically it supports:-
+.
+.TP
+.B "\[rs]X'ps: invis'"
+Suppress output.
+.
+.TP
+.B "\[rs]X'ps: endinvis'"
+Stop suppressing output.
+.
+.TP
+.B "\[rs]X'ps: exec gsave currentpoint 2 copy translate \fIn\fP rotate neg 
exch neg exch translate'"
+where
+.I n
+is the angle of rotation.
+This is to support the
+.I align
+command in
+.BR gpic .
+.
+.TP
+.B "\[rs]X'ps: exec grestore'"
+Again used by
+.B gpic
+to restore after rotation.
+.
+.TP
+.BI "\[rs]X'ps: ... pdfmark'"
+All the
+.I pdfmark
+macros installed by using
+.I -m pdfmark
+or
+.I -m mspdf
+(see documentation in `pdfmark.pdf').
+A subset of these macros are installed automatically when you use
+.B -Tpdf
+so you should not need to use `-m pdfmark' for using most of the PDF
+functionality.
+.
+.LP
+All other
+.B ps:
+tags are silently ignored.
+.
+.LP
+One
+.B \[rs]X
+special used by the DVI driver is also recognised:
+.
+.TP
+.BI \[rs]X'papersize= paper-size '
+where the
+.I paper-size
+parameter is the same as the
+.B papersize
+command.
+.
+See
+.BR groff_font (@MAN5EXT@)
+for details.
+This means that you can alter the page size at will within the PDF file
+being created by
+.BR gropdf .
+.
+If you do want to change the paper size, it must be done before you start
+creating the page.
+.
+.LP
+In addition,
+.B gropdf
+supports its own suite of
+.B pdf:
+tags.
+.
+The following tags are supported:
+.
+.TP
+.BI "\[rs]X'pdf: pdfpic " "file alignment width height line-length" '
+Place an image of the specified
+.I width
+containing the PDF drawing from file 
+.I file
+of desired 
+.I width
+and
+.I height
+(if 
+.I height
+is missing or zero then it is scaled proportionally).
+.
+If 
+.I alignment
+is
+.B \-L
+the drawing is left aligned.
+.
+If it is
+.B \-C
+or
+.B \-R
+a
+.I linelength
+greater than the width of the drawing is required as well.
+.
+If 
+.I width
+is specified as zero then the width is scaled in proportion to the height.
+.
+.\" .IP
+.\" See
+.\" .BR groff_tmac (@MAN5EXT@)
+.\" for a description of the
+.\" .B PSPIC
+.\" macro which provides a convenient high-level interface for inclusion of
+.\" PostScript graphics.
+.
+.TP
+.B \[rs]X'pdf: xrev'
+This toggles a flag which reverses the direction of printing
+.IR "letter by letter" ,
+i.e., each separate letter is reversed, not the entire word.
+.
+This is useful for reversing the direction of glyphs in the Dingbats font.
+.
+To return to normal printing repeat the command again.
+.
+.TP
+.BI "\[rs]X'pdf: markstart " "/ANN definition" '
+The macros which support PDF Bookmarks use this call internally to start the
+definition of bookmark hotspot (user will have called
+`.pdfhref\~L' with the text which will become the `hot spot' region).
+.
+Normally this is never used except from within the pdfmark macros.
+.
+.TP
+.B \[rs]X'pdf: markend'
+The macros which support PDF Bookmarks use this call internally to stop the
+definition of bookmark hotspot (user will have called
+`.pdfhref\~L' with the text which will become the `hot spot' region).
+.
+Normally this is never used except from within the pdfmark macros.
+.
+.TP
+.B \[rs]X'pdf: marksuspend'
+.TQ
+.B \[rs]X'pdf: markrestart'
+If you are using page traps to produce headings, footings, etc., you need to
+use these in case a `hot spot' crosses a page boundary, otherwise any text
+output by the heading or footing macro will be marked as part of the `hot
+spot'.
+.
+To stop this happening just place
+`.pdfmarksuspend' and `.pdfmarkrestart' at the start and end of the page trap 
macro,
+respectively.
+.
+(These are just convenience macros which emit the \[rs]X code.
+.
+These macros must only be used within page traps.)
+.
+.SS Importing graphics
+.
+.B gropdf
+only supports importing other PDF files as graphics.
+.
+But that PDF file may contain any of the graphic formats supported by the PDF
+standard (such as JPEG, PNG, GIF, etc.).
+.
+So any application which outputs PDF can be used as an embedded file in
+.BR gropdf .
+.
+The PDF file you wish to insert must be a single page and the drawing must
+just fit inside the media size of the PDF file.
+.
+So, in
+.BR inkscape (1)
+or
+.BR gimp (1)
+(for example) make sure the canvas size just fits the image.
+.
+.LP
+The PDF parser used in
+.B gropdf
+has not been rigorously tested with all possible applications which produce
+PDFs.
+.
+If you find a single page PDF which fails to import properly, it is worth
+running it through the
+.
+.BR pdftk (1)
+program by issuing the command:
+.
+.RS
+.LP
+.B pdftk
+.I oldfile.pdf
+.B output
+.I newfile.pdf
+.RE
+.
+.LP
+You may find that
+.I newfile.pdf
+will now load successfully.
+.
+.SS TrueType and other font formats
+.
+.B gropdf
+does not support TrueType fonts natively within the PDF files it generates
+(but does support any fonts if they are in an imported PDF).
+.
+However, TrueType fonts can be used with
+.B gropdf
+if converted first to
+.B Type\~42
+format, a special PostScript wrapper equivalent to the PFA format mentioned
+in
+.BR \%pfbtops (@MAN1EXT@).
+.
+There are several different methods to generate a Type\~42
+wrapper and most of them involve the use of a PostScript
+interpreter such as Ghostscript \[en] see
+.BR gs (1).
+.
+.LP
+Yet, the easiest method involves the use of the application
+.BR ttftot42 (1).
+.
+This program uses
+.BR freetype (3)
+(version 1.3.1) to generate Type\~42
+font wrappers and well-formed AFM files that can be fed to the
+.BR \%afmtodit (@MAN1EXT@)
+script to create appropriate metric files.
+.
+The resulting font wrappers should be added to groff's
+.B download
+file.
+.
+.B ttftot42
+source code can be downloaded from
+.UR ftp://\:www.giga.or.at/\:pub/\:nih/\:ttftot42/
+ftp://\:www.giga.or.at/\:pub/\:nih/\:ttftot42/
+.UE .
+.
+.LP
+Another solution for creating Type\~42 wrappers is to use FontForge,
+available from
+.UR http://\:fontforge.sf.net
+http://\:fontforge.sf.net
+.UE .
+.
+This font editor can convert most outline font formats.
+.
+.
+.SH FONT INSTALLATION
+.
+This section gives a summary of the above explanations; it can serve
+as a step-by-step font installation guide for
+.BR gropdf .
+.
+.ds BU \[bu]\ \ \"
+.de LI
+.IP "" 4
+\h'-\w'\*[BU]'u'\*[BU]\c
+..
+.LI
+Convert your font to something groff understands.
+.
+This is either a PostScript Type\~1 font in either PFA or PFB format or a
+PostScript Type\~42 font, together with an AFM file.
+.
+.IP
+The very first line in a PFA/PFB file contains this:
+.
+.RS
+.IP
+.B %!PS-AdobeFont-1.0:
+.RE
+.
+.IP
+A PFB file has this also in the first line, but the string is
+preceded with some binary bytes.
+.
+.IP
+The very first characters in a Type\~42 font file look like this:
+.
+.RS
+.IP
+.B %!PS-TrueTypeFont
+.RE
+.
+.IP
+This is a wrapper format for TrueType fonts.
+.
+Old PS printers might not support it (this is, they don't have a
+built-in TrueType font interpreter).
+.
+.IP
+For TrueType fonts, try
+.B ttftot42
+or
+.BR fontforge .
+For all other font formats use
+.B fontforge
+which can convert most outline font formats.
+.
+.LI
+Convert the AFM file to a groff font description file with the
+.BR \%afmtodit (@MAN1EXT@)
+program.
+.
+An example call is
+.
+.RS
+.IP
+afmtodit Foo-Bar-Bold.afm map/textmap FBB
+.RE
+.
+.IP
+which converts the metric file `Foo-Bar-Bold.afm' to the groff
+font `FBB'.
+.
+If you have a font family which comes with normal, bold, italic,
+and bold italic faces, it is recommended to use the letters
+.BR R ,
+.BR B ,
+.BR I ,
+and
+.BR BI ,
+respectively, as postfixes in the groff font names to make groff's
+`.fam' request work.
+.
+An example is groff's built-in Times-Roman font: The font family name
+is
+.BR T ,
+and the groff font names are
+.BR TR ,
+.BR TB ,
+.BR TI ,
+and
+.BR TBI .
+.
+.LI
+Install both the groff font description files and the fonts in a
+`devpdf' subdirectory of the font path which groff finds.
+.
+See the
+.B ENVIRONMENT
+section in the
+.BR troff (@MAN1EXT@)
+man page which lists the actual value of the font path.
+.
+Note that groff doesn't use the AFM files (but it is a good idea to
+store them anyway).
+.
+.LI
+Register all fonts which must be downloaded to the printer in the
+`devpdf/download' file.
+.
+Only the first occurrence of this file in the font path is read.
+.
+This means that you should copy the default `download' file to the
+first directory in your font path and add your fonts there.
+.
+To continue the above example we assume that the PS font name for
+Foo-Bar-Bold.pfa is `XY-Foo-Bar-Bold' (the PS font name is stored in the
+.B internalname
+field in the `FBB' file) and belongs to foundry `F', thus the following
+line should be added to `download':
+.
+.RS
+.IP
+.B F XY-Foo-Bar-Bold Foo-Bar-Bold.pfa
+.
+.LP
+Use a tab character to separate the fields, and the
+`foundry' field should be null for the default foundry.
+.RE
+.
+.
+.SH ENVIRONMENT
+.
+.TP
+.SM
+.B GROFF_FONT_PATH
+A list of directories in which to search for the
+.BI dev name
+directory in addition to the default ones.
+.
+If, in the `download' file, the
+font file has been specified with a full path, no directories are searched.
+.
+See
+.BR @address@hidden (@MAN1EXT@)
+and
+.BR \%groff_font (@MAN5EXT@)
+for more details.
+.
+.
+.SH FILES
+.
+.Tp \w'address@hidden@/devpdf/download'u+2n
+.B @FONTDIR@/devpdf/DESC
+Device description file.
+.
+.TP
+.BI @FONTDIR@/devpdf/ F
+Font description file for font\~\c
+.IR F .
+.
+.TP
+.BI @FONTDIR@/devpdf/ U-F
+Font description file for font\~\c
+.I F
+(using foundry\~\c
+.I U
+rather than the default foundry).
+.
+.TP
+.B @FONTDIR@/devpdf/download
+List of downloadable fonts.
+.
+.TP
+.B @FONTDIR@/devpdf/Foundry
+A Perl script used during install to locate suitable fonts.
+.
+.TP
+.B @FONTDIR@/devpdf/enc/text.enc
+Encoding used for text fonts.
+.
+.TP
+.B @MACRODIR@/pdf.tmac
+Macros for use with
+.BR gropdf ;
+automatically loaded by
+.BR troffrc .
+.
+.\" .TP
+.\" .B @MACRODIR@/pspic.tmac
+.\" Definition of
+.\" .B PSPIC
+.\" macro,
+.\" automatically loaded by
+.\" .BR ps.tmac .
+.\" .
+.
+.
+.SH "SEE ALSO"
+.
+.BR \%afmtodit (@MAN1EXT@),
+.BR groff (@MAN1EXT@),
+.BR grops (@MAN1EXT@),
+.BR @address@hidden (@MAN1EXT@),
+.BR grops (@MAN1EXT@),
+.BR \%pfbtops (@MAN1EXT@),
+.BR \%groff_out (@MAN5EXT@),
+.BR \%groff_font (@MAN5EXT@),
+.BR \%groff_char (@MAN7EXT@),
+.BR \%groff_tmac (@MAN5EXT@)
+.
+.
+.
+.\" Local Variables:
+.\" mode: nroff
+.\" End:

Index: src/devices/gropdf/gropdf.pl
===================================================================
RCS file: src/devices/gropdf/gropdf.pl
diff -N src/devices/gropdf/gropdf.pl
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ src/devices/gropdf/gropdf.pl        26 Jul 2011 17:11:11 -0000      1.1
@@ -0,0 +1,2928 @@
address@hidden@ -w
+#
+#      gropdf          : PDF post processor for groff
+#      Deri James      : 4th May 2009
+#
+
+# Copyright (C) 2011 Free Software Foundation, Inc.
+#      Written by Deri James <address@hidden>
+#
+# This file is part of groff.
+#
+# groff 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 3 of the License, or
+# (at your option) any later version.
+#
+# groff 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, see <http://www.gnu.org/licenses/>.
+
+use strict;
+use Getopt::Long;
+use Compress::Zlib;
+
+my %cfg;
+
+$cfg{GROFF_VERSION}='@VERSION@';
+$cfg{GROFF_FONT_PATH}='@GROFF_FONT_DIR@';
+
+my @obj;       # Array of PDF objects
+my $objct=0;   # Count of Objects
+my $fct=0;     # Output count
+my %fnt;       # Used fonts
+my $lct=0;     # Input Line Count
+my $src_name='';
+my %env;       # Current environment
+my %fontlst;   # Fonts Loaded
+my $rot=0;     # Portrait
+my %desc;      # Contents of DESC
+my %download;  # Contents of downlopad file
+my $pages;     # Pointer to /Pages object
+my $devnm='devpdf';
+my $cpage;     # Pointer to current pages
+my $cpageno=0; # Object no of current page
+my $cat;       # Pointer to catalogue
+my $dests;     # Pointer to Dests
+my @mediabox=(0,0,595,842);
+my @defaultmb=(0,0,595,842);
+my $stream=''; # Current Text/Graphics stream
+my $cftsz=10;  # Current font sz
+my $cft;       # Current Font
+my $lwidth=1;  # current linewidth
+my $textcol='';        # Current groff text
+my $fillcol='';        # Current groff fill
+my $curfill='';        # Current PDF fill
+my $strkcol='';
+my $curstrk='';
+my @lin=();    # Array holding current line of text
+my @ahead=();  # Buffer used to hol the next line
+my $mode='g';  # Graphic (g) or Text (t) mode;
+my $xpos=0;    # Current X position
+my $ypos=0;    # Current Y position
+my $tmxpos=0;
+my $widtbl;    # Pointer to width table for current font size
+my $origwidtbl; # Pointer to width table
+my $krntbl;    # Pointer to kern table
+my $matrix="1 0 0 1";
+my $whtsz;     # Current width of a space
+my $poschg=0;  # V/H pending
+my $fontchg=0; # font change pending
+my $tnum=2;    # flatness of B-Spline curve
+my $tden=3;    # flatness of B-Spline curve
+my $linewidth=40;
+my $w_flg=0;
+my $nomove=0;
+my $pendmv=0;
+my $gotT=0;
+my $suppress=0;        # Suppress processing?
+my %incfil;    # Included Files
+my @outlev=([0,undef,0,0]);    # Structure pdfmark /OUT entries
+my address@hidden;
+my $Foundry='';
+my $xrev=0;    # Reverse x direction of font
+my $matrixchg=0;
+my $wt=-1;
+my $thislev=1;
+my $mark=undef;
+my $suspendmark=undef;
+my $n_flg=1;
+
+my %ppsz=(     'ledger'=>[1224,792],
+               'legal'=>[612,1008],
+               'letter'=>[612,792],
+               'a0'=>[2384,3370],
+               'a1'=>[1684,2384],
+               'a2'=>[1191,1684],
+               'a3'=>[842,1191],
+               'a4'=>[595,842],
+               'a5'=>[420,595],
+               'a6'=>[297,420],
+               'a7'=>[210,297],
+               'a8'=>[148,210],
+               'a9'=>[105,148],
+               'a10'=>[73,105],
+               'isob0'=>[2835,4008],
+               'isob1'=>[2004,2835],
+               'isob2'=>[1417,2004],
+               'isob3'=>[1001,1417],
+               'isob4'=>[709,1001],
+               'isob5'=>[499,709],
+               'isob6'=>[354,499],
+               'c0'=>[2599,3677],
+               'c1'=>[1837,2599],
+               'c2'=>[1298,1837],
+               'c3'=>[918,1298],
+               'c4'=>[649,918],
+               'c5'=>[459,649],
+               'c6'=>[323,459] );
+
+
+my $fd;
+my $frot;
+my $fpsz;
+my $embedall=0;
+my $debug=0;
+my $version=0;
+
+#Load_Config();
+
+GetOptions("F=s" => \$fd, 'l' => \$frot, 'p=s' => \$fpsz, 'd!' => \$debug, 'v' 
=> \$version, 'e' => \$embedall, 'fy=s' => \$Foundry);
+
+print "GNU gropdf (groff) version $cfg{GROFF_VERSION}\n", exit if $version;
+
+# Search for 'font directory': paths in -f opt, shell var GROFF_FONT_PATH, 
default paths
+
+my $fontdir=$cfg{GROFF_FONT_PATH};
+$fontdir=$ENV{GROFF_FONT_PATH}.':'.$fontdir if exists($ENV{GROFF_FONT_PATH});
+$fontdir=$fd.':'.$fontdir if defined($fd);
+
+$rot=90 if $frot;
+$matrix="0 1 -1 0" if $frot;
+
+LoadDownload();
+LoadDesc();
+
+my $unitwidth=$desc{unitwidth};
+my $papersz=$desc{papersize};
+$papersz=$fpsz if $fpsz;
+
+$env{FontHT}=0;
+$env{FontSlant}=0;
+MakeMatrix();
+
+if (substr($papersz,0,1) eq '/' and -r $papersz)
+{
+       if (open(P,"<$papersz"))
+       {
+               while (<P>)
+               {
+                       chomp;
+                       s/# .*//;
+                       next if $_ eq '';
+                       $papersz=$_;
+                       last
+               }
+
+               close(P);
+       }
+}
+
+if ($papersz=~m/([\d.]+)([cipP]),([\d.]+)([cipP])/)
+{
+       @address@hidden(0,0,ToPoints($1,$2),ToPoints($3,$4));
+}
+elsif (exists($ppsz{$papersz}))
+{
+       @address@hidden(0,0,$ppsz{$papersz}->[0],$ppsz{$papersz}->[1]);
+}
+
+my (@dt)=localtime(time);
+my $dt=PDFDate(address@hidden);
+
+my %info=('Creator' => "(groff version $cfg{GROFF_VERSION})",
+                                                               'Producer' => 
"(gropdf version $cfg{GROFF_VERSION})",
+                                                               'ModDate' => 
"($dt)",
+                                                               'CreationDate' 
=> "($dt)");
+while (<>)
+{
+       chomp;
+       $lct++;
+       
+       do      # The ahead buffer behaves like 'ungetc'
+       {{
+               if (scalar(@ahead))
+               {
+                       $_=shift(@ahead);
+               }
+               
+
+               my $cmd=substr($_,0,1);
+               next if $cmd eq '#';    # just a comment
+               my $lin=substr($_,1);
+
+               while ($cmd eq 'w')
+               {
+                       $cmd=substr($lin,0,1);
+                       $lin=substr($lin,1);
+                       $w_flg=1 if $gotT;
+               }
+               
+               $lin=~s/^\s+//;
+#              $lin=~s/\s#.*?$//;      # remove comment
+               $stream.="\% $_\n" if $debug;
+
+               do_x($lin),next if ($cmd eq 'x');
+               next if $suppress;
+               do_p($lin),next if ($cmd eq 'p');
+               do_f($lin),next if ($cmd eq 'f');
+               do_s($lin),next if ($cmd eq 's');
+               do_m($lin),next if ($cmd eq 'm');
+               do_D($lin),next if ($cmd eq 'D');
+               do_V($lin),next if ($cmd eq 'V');
+               do_v($lin),next if ($cmd eq 'v');
+               do_t($lin),next if ($cmd eq 't');
+               do_C($lin),next if ($cmd eq 'C');
+               do_c($lin),next if ($cmd eq 'c');
+               do_N($lin),next if ($cmd eq 'N');
+               do_h($lin),next if ($cmd eq 'h');
+               do_H($lin),next if ($cmd eq 'H');
+               do_n($lin),next if ($cmd eq 'n');
+               
+               my $tmp=scalar(@ahead);
+       }} until scalar(@ahead) == 0;
+       
+}
+
+
+if ($cpageno > 0)
+{
+       PutObj($cpageno);
+       OutStream($cpageno+1);
+}
+
+
+PutOutlines(address@hidden);
+
+PutObj(1);
+
+my $info=BuildObj(++$objct,\%info);
+
+PutObj($objct);
+
+foreach my $o (3..$objct)
+{
+       PutObj($o) if (!exists($obj[$o]->{XREF}));
+}
+
+#my $encrypt=BuildObj(++$objct,{'Filter' => '/Standard', 'V' => 1, 'R' => 2, 
'P' => 252});
+#PutObj($objct);
+PutObj(2);
+
+my $xrefct=$fct;
+
+$objct+=1;
+print "xref\n0 $objct\n0000000000 65535 f \n";
+
+foreach my $xr (@obj)
+{
+       next if !defined($xr);
+       printf("%010d 00000 n \n",$xr->{XREF});
+}
+
+print "trailer\n<<\n/Info $info\n/Root 1 0 R\n/Size 
$objct\n>>\nstartxref\n$fct\n\%\%EOF\n\% Pages=$pages->{Count}\n";
+
+
+sub MakeMatrix
+{
+       my $fontxrev=shift||0;
+       my @mat=($frot)?(0,1,-1,0):(1,0,0,1);
+
+       if (!$frot)
+       {
+               if ($env{FontHT} != 0)
+               {
+                       $mat[3]=sprintf('%.3f',$env{FontHT}/$cftsz);
+               }
+
+               if ($env{FontSlant} != 0)
+               {
+                       my $slant=$env{FontSlant};
+                       $slant*=$env{FontHT}/$cftsz if $env{FontHT} != 0;
+                       my $ang=rad($slant);
+
+                       $mat[2]=sprintf('%.3f',sin($ang)/cos($ang));
+               }
+
+               if ($fontxrev)
+               {
+                       $mat[0]=-$mat[0];
+               }
+       }
+
+       $matrix=join(' ',@mat);
+       $matrixchg=1;
+}
+
+sub PutOutlines
+{
+       my $o=shift;
+       my $outlines;
+       
+       if ($#{$o} > 0)
+       {
+               # We've got Outlines to deal with
+               my $openct=$curoutlev->[0]->[2];
+               
+               while ($thislev-- > 1)
+               {
+                       my $nxtoutlev=$curoutlev->[0]->[1];
+                       $nxtoutlev->[0]->[2]+=$openct if 
$curoutlev->[0]->[3]==1;
+                       $openct=0 if $nxtoutlev->[0]->[3]==-1;
+                       $curoutlev=$nxtoutlev;
+               }
+               
+               $cat->{Outlines}=BuildObj(++$objct,{'Count' => 
abs($o->[0]->[0])+$o->[0]->[2]});
+               $outlines=$obj[$objct]->{DATA};
+       }
+       else
+       {
+               return;
+       }
+
+       SetOutObj($o);
+
+       $outlines->{First}=$o->[1]->[2];
+       $outlines->{Last}=$o->[$#{$o}]->[2];
+
+       LinkOutObj($o,$cat->{Outlines});
+}
+
+sub SetOutObj
+{
+       my $o=shift;
+
+       for my $j (1..$#{$o})
+       {
+               my $ono=BuildObj(++$objct,$o->[$j]->[0]);
+               $o->[$j]->[2]=$ono;
+
+               SetOutObj($o->[$j]->[1]) if $#{$o->[$j]->[1]} > -1;
+       }
+}
+
+sub LinkOutObj
+{
+       my $o=shift;
+       my $parent=shift;
+
+       for my $j (1..$#{$o})
+       {
+               my $op=GetObj($o->[$j]->[2]);
+               
+               $op->{Next}=$o->[$j+1]->[2] if ($j < $#{$o});
+               $op->{Prev}=$o->[$j-1]->[2] if ($j > 1);
+               $op->{Parent}=$parent;
+
+               if ($#{$o->[$j]->[1]} > -1)
+               {
+                       
$op->{Count}=$o->[$j]->[1]->[0]->[2]*$o->[$j]->[1]->[0]->[3];# if 
exists($op->{Count}) and $op->{Count} > 0;
+                       $op->{First}=$o->[$j]->[1]->[1]->[2];
+                       $op->{Last}=$o->[$j]->[1]->[$#{$o->[$j]->[1]}]->[2];
+                       LinkOutObj($o->[$j]->[1],$o->[$j]->[2]);
+               }
+       }
+}
+
+sub GetObj
+{
+       my $ono=shift;
+       ($ono)=split(' ',$ono);
+       return($obj[$ono]->{DATA});
+}
+               
+       
+
+sub PDFDate
+{
+       my $dt=shift;
+       return(sprintf("D:%04d%02d%02d%02d%02d%02d% 
+02d'00'",$dt->[5]+1900,$dt->[4]+1,$dt->[3],$dt->[2],$dt->[1],$dt->[0],( 
localtime time() + 3600*( 12 - (gmtime)[2] ) )[2] - 12));
+}
+
+sub ToPoints
+{
+       my $num=shift;
+       my $unit=shift;
+
+       if ($unit eq 'i')
+       {
+               return($num*72);
+       }
+       elsif ($unit eq 'c')
+       {
+               return int($num*72/2.54);
+       }
+       elsif ($unit eq 'm')    # millimetres
+       {
+               return int($num*72/25.4);
+       }
+       elsif ($unit eq 'p')
+       {
+               return($num);
+       }
+       elsif ($unit eq 'P')
+       {
+               return($num*6);
+       }
+       else
+       {
+               Msg(1,"Unknown scaling factor '$unit'");
+       }
+}
+
+sub Load_Config
+{
+       open(CFG,"<gropdf_config") or die "Can't open config file: $!";
+
+       while (<CFG>)
+       {
+               chomp;
+               my ($key,$val)=split(/ ?= ?/);
+
+               $cfg{$key}=$val;
+       }
+
+       close(CFG);
+}
+
+sub LoadDownload
+{
+       my $f;
+       
+       OpenFile(\$f,$fontdir,"download");
+       Msg(1,"Failed to open 'download'") if !defined($f);
+
+       while (<$f>)
+       {
+               chomp;
+               s/#.*$//;
+               next if $_ eq '';
+               my ($foundry,$name,$file)=split(/\t+/);
+               if (substr($file,0,1) eq '*')
+               {
+                       next if !$embedall;
+                       $file=substr($file,1);
+               }
+               
+               $download{"$foundry $name"}=$file;
+       }
+
+       close($f);
+}
+
+sub OpenFile
+{
+       my $f=shift;
+       my $dirs=shift;
+       my $fnm=shift;
+
+       if (substr($fnm,0,1)  eq '/')
+       {
+               return if -r "$fnm" and open($$f,"<$fnm");
+       }
+       
+       my (@dirs)=split(':',$dirs);
+
+       foreach my $dir (@dirs)
+       {
+               last if -r "$dir/$devnm/$fnm" and open($$f,"<$dir/$devnm/$fnm");
+       }
+}
+
+sub LoadDesc
+{
+       my $f;
+       
+       OpenFile(\$f,$fontdir,"DESC");
+       Msg(1,"Failed to open 'DESC'") if !defined($f);
+       
+       while (<$f>)
+       {
+               chomp;
+               s/#.*$//;
+               next if $_ eq '';
+               my ($name,$prms)=split(' ',$_,2);
+               $desc{lc($name)}=$prms;
+       }
+       
+       close($f);
+}
+
+sub rad  { $_[0]*3.14159/180 }
+
+my $InPicRotate=0;
+
+sub do_x
+{
+       my $l=shift;
+       my ($xcmd,@xprm)=split(' ',$l);
+       $xcmd=substr($xcmd,0,1);
+
+       if ($xcmd eq 'T')
+       {
+               Msg(0,"Expecting a pdf pipe (got $xprm[0])") if $xprm[0] ne 
substr($devnm,3);
+       }
+       elsif ($xcmd eq 'f')    # Register Font
+       {
+               $xprm[1]="${Foundry}-$xprm[1]" if $Foundry ne '';
+               LoadFont($xprm[0],$xprm[1]);
+       }
+       elsif ($xcmd eq 'F')    # Source File (for errors)
+       {
+               $env{SourceFile}=$xprm[0];
+       }
+       elsif ($xcmd eq 'H')    # FontHT
+       {
+               $xprm[0]/=$unitwidth;
+               $xprm[0]=0 if $xprm[0] == $cftsz;
+               $env{FontHT}=$xprm[0];
+               MakeMatrix();
+       }
+       elsif ($xcmd eq 'S')    # FontSlant
+       {
+               $env{FontSlant}=$xprm[0];
+               MakeMatrix();
+       }
+       elsif ($xcmd eq 'i')    # Initialise
+       {
+               $objct++;
+               @address@hidden;
+               BuildObj($objct,{'Pages' => BuildObj($objct+1,
+                                                     {'Kids' => [],
+                                                     'Count' => 0,
+                                                     'Type' => '/Pages',
+                                                     'Rotate' => $rot,
+                                                     'MediaBox' => 
address@hidden,
+                                                     'Resources' =>
+                                                               {'Font' => {},
+                                                               'ProcSet' => 
['/PDF', '/Text', '/ImageB', '/ImageC', '/ImageI']}
+                                                     }
+                                                     ),
+                         'Type' =>  '/Catalog'});
+               
+               $cat=$obj[$objct]->{DATA};
+               $objct++;
+               $pages=$obj[2]->{DATA};
+               Put("%PDF-1.4\n%âãÏÓ\n");
+       }
+       elsif ($xcmd eq 'X')
+       {
+               # There could be extended args
+               do
+               {{
+                       LoadAhead(1);
+                       if (substr($ahead[0],0,1) eq '+')
+                       {
+                               $l.="\n".substr($ahead[0],1);
+                               shift(@ahead);
+                       }
+               }} until $#ahead==0;
+
+               ($xcmd,@xprm)=split(' ',$l);
+               $xcmd=substr($xcmd,0,1);
+               
+               if ($xprm[0]=~m/^(.+:)(.+)/)
+               {
+                       splice(@xprm,1,0,$2);
+                       $xprm[0]=$1;
+               }
+               
+               my $par=join(' ',@xprm[1..$#xprm]);
+               
+               if ($xprm[0] eq 'ps:')
+               {
+                       if ($xprm[1] eq 'invis')
+                       {
+                               $suppress=1;
+                       }
+                       elsif ($xprm[1] eq 'endinvis')
+                       {
+                               $suppress=0;
+                       }
+                       elsif ($par=~m/exec gsave currentpoint 2 copy translate 
(.+) rotate neg exch neg exch translate/)
+                       {
+                               # This is added by gpic to rotate a single 
object
+                               
+                               my $theta=-rad($1);
+
+                               IsGraphic();
+                               my ($curangle,$hyp)=RtoP($xpos,GraphY($ypos));
+                               my ($x,$y)=PtoR($theta+$curangle,$hyp);
+                               $stream.="q\n".sprintf("%.3f %.3f %.3f %.3f 
%.3f %.3f 
cm",cos($theta),sin($theta),-sin($theta),cos($theta),$xpos-$x,GraphY($ypos)-$y)."\n";
+                               $InPicRotate=1;
+                       }
+                       elsif ($par=~m/exec grestore/ and $InPicRotate)
+                       {
+                               IsGraphic();
+                               $stream.="Q\n";
+                               $InPicRotate=0;
+                       }
+                       elsif ($par=~m/\[(.+) pdfmark/)
+                       {
+                               my $pdfmark=$1;
+                               $pdfmark=~s((\d{4,6}) 
u)(sprintf("%.1f",$1/$desc{sizescale}))eg;
+
+                               if ($pdfmark=~m/(.+) \/DOCINFO/)
+                               {
+                                       my @xwds=split(' ',"<< $1 >>");
+                                       my 
$docinfo=ParsePDFValue(address@hidden);
+
+                                       foreach my $k (keys %{$docinfo})
+                                       {
+                                               $info{$k}=$docinfo->{$k} if $k 
ne 'Producer';
+                                       }
+                               }
+                               elsif ($pdfmark=~m/(.+) \/DOCVIEW/)
+                               {
+                                       my @xwds=split(' ',"<< $1 >>");
+                                       my 
$docview=ParsePDFValue(address@hidden);
+                                       
+                                       foreach my $k (keys %{$docview})
+                                       {
+                                               $cat->{$k}=$docview->{$k} if 
!exists($cat->{$k});
+                                       }
+                               }
+                               elsif ($pdfmark=~m/(.+) \/DEST/)
+                               {
+                                       my @xwds=split(' ',"<< $1 >>");
+                                       my $dest=ParsePDFValue(address@hidden);
+                                       foreach my $v (@{$dest->{View}})
+                                       {
+                                               $v=GraphY(abs($v)) if 
substr($v,0,1) eq '-';
+                                       }
+                                       unshift(@{$dest->{View}},"$cpageno 0 
R");
+
+                                       if (!defined($dests))
+                                       {
+                                               
$cat->{Dests}=BuildObj(++$objct,{});
+                                               $dests=$obj[$objct]->{DATA};
+                                       }
+
+                                       my $k=substr($dest->{Dest},1);
+                                       $dests->{$k}=$dest->{View};
+                               }
+                               elsif ($pdfmark=~m/(.+) \/ANN/)
+                               {
+                                       my $l=$1;
+                                       $l=~s/Color/C/;
+                                       $l=~s/Action/A/;
+                                       $l=~s/Title/T/;
+                                       $l=~s'/Subtype /URI'/S /URI';
+                                       my @xwds=split(' ',"<< $l >>");
+                                       my 
$annotno=BuildObj(++$objct,ParsePDFValue(address@hidden));
+                                       my $annot=$obj[$objct];
+                                       $annot->{DATA}->{Type}='/Annot';
+                                       FixRect($annot->{DATA}->{Rect}); # Y 
origin to ll
+                                       push(@{$cpage->{Annots}},$annotno);
+                               }
+                               elsif ($pdfmark=~m/(.+) \/OUT/)
+                               {
+                                       my @xwds=split(' ',"<< $1 >>");
+                                       my $out=ParsePDFValue(address@hidden);
+
+                                       my $this=[$out,[]];
+
+                                       if (exists($out->{Level}))
+                                       {
+                                               my $lev=abs($out->{Level});
+                                               my $levsgn=sgn($out->{Level});
+                                               delete($out->{Level});
+
+                                               if ($lev > $thislev)
+                                               {
+                                                       my 
$thisoutlev=$curoutlev->[$#{$curoutlev}]->[1];
+                                                       
$thisoutlev->[0]=[0,$curoutlev,0,$levsgn];
+                                                       $curoutlev=$thisoutlev;
+                                                       $thislev++;
+                                               }
+                                               elsif ($lev < $thislev)
+                                               {
+                                                       my 
$openct=$curoutlev->[0]->[2];
+
+                                                       while ($thislev > $lev)
+                                                       {
+                                                               my 
$nxtoutlev=$curoutlev->[0]->[1];
+                                                               
$nxtoutlev->[0]->[2]+=$openct if $curoutlev->[0]->[3]==1;
+                                                               $openct=0 if 
$nxtoutlev->[0]->[3]==-1;
+                                                               
$curoutlev=$nxtoutlev;
+                                                               $thislev--;
+                                                       }
+                                               }
+                                               
+                                               push(@{$curoutlev},$this);
+                                               $curoutlev->[0]->[2]++;
+                                       }
+                                       else
+                                       {
+                                               while ($curoutlev->[0]->[0] == 
0 and defined($curoutlev->[0]->[1]))
+                                               {
+                                                       
$curoutlev=$curoutlev->[0]->[1];
+                                               }
+
+                                               $curoutlev->[0]->[0]--;
+                                               $curoutlev->[0]->[2]++;
+                                               push(@{$curoutlev},$this);
+
+
+                                               if (exists($out->{Count}) and 
$out->{Count} != 0)
+                                               {
+                                                       
push(@{$this->[1]},[abs($out->{Count}),$curoutlev,0,sgn($out->{Count})]);
+                                                       $curoutlev=$this->[1];
+
+                                                       if ($out->{Count} > 0)
+                                                       {
+                                                               my 
$p=$curoutlev;
+
+                                                               while 
(defined($p))
+                                                               {
+                                                                       
$p->[0]->[2]+=$out->{Count};
+                                                                       
$p=$p->[0]->[1];
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+               elsif (lc($xprm[0]) eq 'pdf:')
+               {
+                       if (lc($xprm[1]) eq 'import')
+                       {
+                               my $fil=$xprm[2];
+                               my $llx=$xprm[3];
+                               my $lly=$xprm[4];
+                               my $urx=$xprm[5];
+                               my $ury=$xprm[6];
+                               my $wid=$xprm[7];
+                               my $hgt=$xprm[8]||-1;
+                               my $mat=[1,0,0,1,0,0];
+                               
+                               if (!exists($incfil{$fil}))
+                               {
+                                       if ($fil=~m/\.pdf$/)
+                                       {
+                                               
$incfil{$fil}=LoadPDF($fil,$mat,$wid,$hgt,"import");
+                                       }
+                                       elsif ($fil=~m/\.swf$/)
+                                       {
+                                               my $xscale=$wid/($urx-$llx+1);
+                                               my 
$yscale=($hgt<=0)?$xscale:($hgt/($ury-$lly+1));
+                                               $hgt=($ury-$lly+1)*$yscale;
+                                               
+                                               if ($rot)
+                                               {
+                                                       $mat->[3]=$xscale;
+                                                       $mat->[0]=$yscale;
+                                               }
+                                               else
+                                               {
+                                                       $mat->[0]=$xscale;
+                                                       $mat->[3]=$yscale;
+                                               }
+                                               
+                                               
$incfil{$fil}=LoadSWF($fil,[$llx,$lly,$urx,$ury],$mat);
+                                       }
+                                       else
+                                       {
+                                               Msg(0,"Unknown filetype 
'$fil'");
+                                               return undef;
+                                       }
+                               }
+                               
+                               if (defined($incfil{$fil}))
+                               {
+                                       IsGraphic();
+                                       if ($fil=~m/\.pdf$/)
+                                       {
+                                               my $bbox=$incfil{$fil}->[1];
+                                               my 
$xscale=$wid/($bbox->[2]-$bbox->[0]+1);
+                                               my 
$yscale=($hgt<=0)?$xscale:($hgt/($bbox->[3]-$bbox->[1]+1));
+                                               $stream.="q $xscale 0 0 $yscale 
".PutXY($xpos,$ypos)." cm";
+                                               $stream.=" 0 1 -1 0 0 0 cm" if 
$rot;
+                                               $stream.=" /$incfil{$fil}->[0] 
Do Q\n";
+                                       }
+                                       elsif ($fil=~m/\.swf$/)
+                                       {
+                                               $stream.=PutXY($xpos,$ypos)." m 
/$incfil{$fil} Do\n";
+                                       }
+                               }
+                       }
+                       elsif (lc($xprm[1]) eq 'pdfpic')
+                       {
+                               my $fil=$xprm[2];
+                               my $flag=uc($xprm[3]);
+                               my $wid=GetPoints($xprm[4]);
+                               my $hgt=GetPoints($xprm[5]||-1);
+                               my $ll=GetPoints($xprm[6]||0);
+                               my $mat=[1,0,0,1,0,0];
+                               
+                               if (!exists($incfil{$fil}))
+                               {
+                                       
$incfil{$fil}=LoadPDF($fil,$mat,$wid,$hgt,"pdfpic");
+                               }
+                               
+                               if (defined($incfil{$fil}))
+                               {
+                                       IsGraphic();
+                                       my $bbox=$incfil{$fil}->[1];
+                                       my 
$xscale=$wid/($bbox->[2]-$bbox->[0]+1);
+                                       my 
$yscale=($hgt<=0)?$xscale:($hgt/($bbox->[3]-$bbox->[1]+1));
+                                       $xscale=($wid<=0)?$yscale:$xscale;
+                                       $xscale=$yscale if $yscale < $xscale;
+                                       $yscale=$xscale if $xscale < $yscale;
+                                       $wid=($bbox->[2]-$bbox->[0]+1)*$xscale;
+                                       $hgt=($bbox->[3]-$bbox->[1]+1)*$yscale;
+
+                                       if ($flag eq '-C' and $ll > $wid)
+                                       {
+                                               $xpos+=int(($ll-$wid)/2);
+                                       }
+                                       elsif ($flag eq '-R' and $ll > $wid)
+                                       {
+                                               $xpos+=$ll-$wid;
+                                       }
+                                       
+                                       $ypos+=$hgt;
+                                       $stream.="q $xscale 0 0 $yscale 
".PutXY($xpos,$ypos)." cm";
+                                       $stream.=" 0 1 -1 0 0 0 cm" if $rot;
+                                       $stream.=" /$incfil{$fil}->[0] Do Q\n";
+                               }
+                       }
+                       elsif (lc($xprm[1]) eq 'xrev')
+                       {
+                               $xrev=!$xrev;
+                       }
+                       elsif (lc($xprm[1]) eq 'markstart')
+                       {
+                               $mark={'rst' => $xprm[2]/$unitwidth, 'rsb' => 
$xprm[3]/$unitwidth, 'xpos' => $xpos,
+                                                        'ypos' => $ypos, 
'pdfmark' => join(' ',@xprm[4..$#xprm])};
+                       }
+                       elsif (lc($xprm[1]) eq 'markend')
+                       {
+                               PutHotSpot($xpos) if defined($mark);
+                               $mark=undef;
+                       }
+                       elsif (lc($xprm[1]) eq 'marksuspend')
+                       {
+                               $suspendmark=$mark;
+                               $mark=undef;
+                       }
+                       elsif (lc($xprm[1]) eq 'markrestart')
+                       {
+                               $mark=$suspendmark;
+                               $suspendmark=undef;
+                       }
+               }
+               elsif (lc(substr($xprm[0],0,9)) eq 'papersize')
+               {
+                       my ($px,$py)=split(',',substr($xprm[0],10));
+                       $px=GetPoints($px);
+                       $py=GetPoints($py);
+                       @mediabox=(0,0,$px,$py);
+                       my @address@hidden;
+                       $matrixchg=1;
+                       $cpage->address@hidden;
+               }
+       }
+}
+
+sub PutHotSpot
+{
+       my $endx=shift;
+       my $l=$mark->{pdfmark};
+       $l=~s/Color/C/;
+       $l=~s/Action/A/;
+       $l=~s'/Subtype /URI'/S /URI';
+       my @xwds=split(' ',"<< $l >>");
+       my $annotno=BuildObj(++$objct,ParsePDFValue(address@hidden));
+       my $annot=$obj[$objct];
+       $annot->{DATA}->{Type}='/Annot';
+       
$annot->{DATA}->{Rect}=[$mark->{xpos},$mark->{ypos}-$mark->{rsb},$endx,$mark->{ypos}-$mark->{rst}];
+       FixRect($annot->{DATA}->{Rect}); # Y origin to ll
+       push(@{$cpage->{Annots}},$annotno);
+}
+       
+sub sgn
+{
+       return(1) if $_[0] > 0;
+       return(-1) if $_[0] < 0;
+       return(0);
+}
+
+sub FixRect
+{
+       my $rect=shift;
+
+       return if !defined($rect);
+       $rect->[1]=GraphY($rect->[1]);
+       $rect->[3]=GraphY($rect->[3]);
+}
+
+sub GetPoints
+{
+       my $val=shift;
+
+       $val=ToPoints($1,$2) if ($val=~m/(-?[\d.]+)([cipn])/);
+
+       return $val;
+}
+
+# Although the PDF reference mentions XObject/Form as a way of incorporating 
an external PDF page into
+# the current PDF, it seems not to work with any current PDF reader (although 
I am told (by Leonard Rosenthol,
+# who helped author the PDF ISO standard) that Acroread 9 does support it, 
empiorical observation shows otherwise!!).
+# So... do it the hard way - full PDF parser and merge required objects!!!
+
+# sub BuildRef
+# {
+#      my $fil=shift;
+#      my $bbox=shift;
+#      my $mat=shift;
+#      my $wid=($bbox->[2]-$bbox->[0])*$mat->[0];
+#      my $hgt=($bbox->[3]-$bbox->[1])*$mat->[3];
+# 
+#      if (!open(PDF,"<$fil"))
+#      {
+#              Msg(0,"Failed to open '$fil'");
+#              return(undef);
+#      }
+# 
+#      my (@f)=(<PDF>);
+# 
+#      close(PDF);
+# 
+#      $objct++;
+#      my $xonm="XO$objct";
+#      
+#      $pages->{'Resources'}->{'XObject'}->{$xonm}=BuildObj($objct,{'Type' => 
'/XObject',
+#                                                                  'Subtype' 
=> '/Form',
+#                                                                  'BBox' => 
$bbox,
+#                                                                  'Matrix' => 
$mat,
+#                                                                  'Resources' 
=> $pages->{'Resources'},
+#                                                                  'Ref' => 
{'Page' => '1',
+#                                                                              
'F' => BuildObj($objct+1,{'Type' => '/Filespec',
+#                                                                              
                          'F' => "($fil)",
+#                                                                              
                          'EF' => {'F' => BuildObj($objct+2,{'Type' => 
'/EmbeddedFile'})}
+#                                                                              
})
+#                                                                  }
+#                                                              });
+# 
+#      $obj[$objct]->{STREAM}="q 1 0 0 1 0 0 cm
+# q BT
+# 1 0 0 1 0 0 Tm
+# .5 g .5 G
+# /F5 20 Tf
+# (Proxy) Tj
+# ET Q
+# 0 0 m 72 0 l s
+# Q\n";
+#                                                              
+# #    $obj[$objct]->{STREAM}=PutXY($xpos,$ypos)." m 
".PutXY($xpos+$wid,$ypos)." l ".PutXY($xpos+$wid,$ypos+$hgt)." l 
".PutXY($xpos,$ypos+$hgt)." l f\n";
+#      $obj[$objct+2]->{STREAM}=join('',@f);
+#      PutObj($objct);
+#      PutObj($objct+1);
+#      PutObj($objct+2);
+#      $objct+=2;
+#      return($xonm);
+# }
+
+sub LoadSWF
+{
+       my $fil=shift;
+       my $bbox=shift;
+       my $mat=shift;
+       my $wid=($bbox->[2]-$bbox->[0])*$mat->[0];
+       my $hgt=($bbox->[3]-$bbox->[1])*$mat->[3];
+       my (@path)=split('/',$fil);
+       my $node=pop(@path);
+
+       if (!open(PDF,"<$fil"))
+       {
+               Msg(0,"Failed to open '$fil'");
+               return(undef);
+       }
+
+       my (@f)=(<PDF>);
+
+       close(PDF);
+
+       $objct++;
+       my $xonm="XO$objct";
+
+       $pages->{'Resources'}->{'XObject'}->{$xonm}=BuildObj($objct,{'Type' => 
'/XObject', 'BBox' => $bbox, 'Matrix' => $mat, 'FormType' => 1, 'Subtype' => 
'/Form', 'Length' => 0, 'Type' => "/XObject"});
+       $obj[$objct]->{STREAM}='';
+       PutObj($objct);
+       $objct++;
+       my $asset=BuildObj($objct,{'EF' => {'F' => BuildObj($objct+1,{})},
+                                  'F' => "($node)",
+                                  'Type' => '/Filespec',
+                                  'UF' => "($node)"});
+
+       PutObj($objct);
+       $objct++;
+       $obj[$objct]->{STREAM}=join('',@f);
+       PutObj($objct);
+       $objct++;
+       my $config=BuildObj($objct,{'Instances' => [BuildObj($objct+1,{'Params' 
=> { 'Binding' => '/Background'}, 'Asset' => $asset})],
+                                   'Subtype' => '/Flash'});
+
+       PutObj($objct);
+       $objct++;
+       PutObj($objct);
+       $objct++;
+
+       my ($x,$y)=split(' ',PutXY($xpos,$ypos));
+
+       push(@{$cpage->{Annots}},BuildObj($objct,{'RichMediaContent' => 
{'Subtype' => '/Flash', 'Configurations' => [$config], 'Assets' => {'Names' => 
[ "($node)", $asset ] }},
+                                                 'P' => "$cpageno 0 R",
+                                                 'RichMediaSettings' => { 
'Deactivation' => { 'Condition' => '/PI',
+                                                                               
                'Type' => '/RichMediaDeactivation'},
+                                                                          
'Activation' => {    'Condition' => '/PV',
+                                                                               
                'Type' => '/RichMediaActivation'}},
+                                                 'F' => 68,
+                                                 'Subtype' => '/RichMedia',
+                                                 'Type' => '/Annot',
+                                                 'Rect' => "[ $x $y 
".($x+$wid)." ".($y+$hgt)." ]",
+                                                 'Border' => [0,0,0]}));
+
+       PutObj($objct);
+
+       return $xonm;
+}
+
+sub LoadPDF
+{
+       my $pdfnm=shift;
+       my $wid=shift;
+       my $hgt=shift;
+       my $type=shift;
+       my $mat=[1,0,0,1,0,0];
+       my $pdf;
+       my $pdftxt='';
+       my $strmlen=0;
+       my $curobj=-1;
+       my $instream=0;
+       my $cont;
+
+       if (!open(PD,"<$pdfnm"))
+       {
+               Msg(0,"Failed to open PDF '$pdfnm'");
+               return undef;
+       }
+
+       my $hdr=<PD>;
+
+       $/="\r" if (length($hdr) > 10);
+
+       while (<PD>)
+       {
+               chomp;
+
+               s/\n//;
+               
+               if (m/endstream(\s+.*)?$/)
+               {
+                       $instream=0;
+                       $_="endstream";
+                       $_.=$1 if defined($1)
+               }
+
+               next if $instream;
+               
+               if (m'/Length\s+(\d+)(\s+\d+\s+R)?')
+               {
+                       if (!defined($2))
+                       {
+                               $strmlen=$1;
+                       }
+                       else
+                       {
+                               $strmlen=0;
+                       }
+               }
+               
+               if (m'^(\d+) \d+ obj')
+               {
+                       $curobj=$1;
+                       $pdf->[$curobj]->{OBJ}=undef;
+               }
+
+               if (m'stream\s*$' and ! m/^endstream/)
+               {
+                       if ($curobj > -1)
+                       {
+                               
$pdf->[$curobj]->{STREAMPOS}=[tell(PD),$strmlen];
+                               seek(PD,$strmlen,1);
+                               $instream=1;
+                       }
+                       else
+                       {
+                               Msg(0,"Parsing PDF '$pdfnm' failed");
+                               return undef;
+                       }
+               }
+
+               $pdftxt.=$_.' ';
+       }
+
+       close(PD);
+
+       open(PD,"<$pdfnm");
+#      $pdftxt=~s/\]/ \]/g;
+       my (@pdfwds)=split(' ',$pdftxt);
+       my $wd;
+
+       while ($wd=nextwd(address@hidden),length($wd))
+       {
+               if ($wd=~m/\d+/ and defined($pdfwds[1]) and 
$pdfwds[1]=~m/^obj(.*)/)
+               {
+                       $curobj=$wd;
+                       shift(@pdfwds); shift(@pdfwds);
+                       unshift(@pdfwds,$1) if defined($1) and length($1);
+                       $pdf->[$curobj]->{OBJ}=ParsePDFObj(address@hidden);
+               }
+               elsif ($wd eq 'trailer' and !exists($pdf->[0]->{OBJ}))
+               {
+                       $pdf->[0]->{OBJ}=ParsePDFObj(address@hidden);
+               }
+               else
+               {
+#                      print "Skip '$wd'\n";
+               }
+       }
+
+       my $catalog=${$pdf->[0]->{OBJ}->{Root}};
+       my $page=FindPage(1,$pdf);
+       my $xobj=++$objct;
+
+       # Load the streamas
+
+       foreach my $o (@{$pdf})
+       {
+               if (exists($o->{STREAMPOS}))
+               {
+                       my $l;
+
+                       $l=$o->{OBJ}->{Length} if exists($o->{OBJ}->{Length});
+
+                       $l=$pdf->[$$l]->{OBJ} if (defined($l) && ref($l) eq 
'OBJREF');
+
+                       Msg(1,"Unable to determine length of stream 
address@hidden>{STREAMPOS}->[0]") if !defined($l);
+
+                       sysseek(PD,$o->{STREAMPOS}->[0],0);
+                       Msg(0,'Failed to read all the stream') if $l != 
sysread(PD,$o->{STREAM},$l);
+
+                       if (exists($o->{OBJ}->{'Filter'}) and 
$o->{OBJ}->{'Filter'} eq '/FlateDecode')
+                       {
+                               
$o->{STREAM}=Compress::Zlib::uncompress($o->{STREAM});
+                               delete($o->{OBJ }->{'Filter'});
+                       }
+               }
+       }
+
+       close(PD);
+       
+       # Find BBox
+       my $BBox;
+       my $insmap={};
+
+       foreach my $k (qw( MediaBox ArtBox TrimBox BleedBox CropBox ))
+       {
+               $BBox=FindKey($pdf,$page,$k);
+               last if $BBox;
+       }
+
+       $BBox=[0,0,595,842] if !defined($BBox);
+
+       my $xscale=$wid/($BBox->[2]-$BBox->[0]+1);
+       my $yscale=($hgt<=0)?$xscale:($hgt/($BBox->[3]-$BBox->[1]+1));
+       $hgt=($BBox->[3]-$BBox->[1]+1)*$yscale;
+
+       if ($type eq "import")
+       {
+               $mat->[0]=$xscale;
+               $mat->[3]=$yscale;
+       }
+       
+       # Find Resource
+
+       my $res=FindKey($pdf,$page,'Resources');
+       my $xonm="XO$xobj";
+
+       # Map inserted objects to current PDF
+
+       MapInsValue($pdf,$page,'',$insmap,$xobj,$pdf->[$page]->{OBJ});
+#
+#      Many PDFs include 'Resources' at the 'Page' level but if 'Resources' is 
held at a higher level (i.e 'Pages')
+#      then we need to include its objects as well.
+#
+       MapInsValue($pdf,$page,'',$insmap,$xobj,$res) if 
!exists($pdf->[$page]->{OBJ}->{Resources});
+       
+       # Copy Resources
+
+       my %incres=%{$res};
+
+       $incres{ProcSet}=['/PDF', '/Text', '/ImageB', '/ImageC', '/ImageI'];
+
+       ($mat->[4],$mat->[5])=split(' ',PutXY($xpos,$ypos));
+       $pages->{'Resources'}->{'XObject'}->{$xonm}=BuildObj($xobj,{'Type' => 
'/XObject', 'BBox' => $BBox, 'Name' => "/$xonm", 'FormType' => 1, 'Subtype' => 
'/Form', 'Length' => 0, 'Type' => "/XObject", 'Resources' => \%incres});
+
+       BuildStream($xobj,$pdf,$pdf->[$page]->{OBJ}->{Contents});
+               
+       return([$xonm,$BBox] );
+}
+
+sub BuildStream
+{
+       my $xobj=shift;
+       my $pdf=shift;
+       my $val=shift;
+       my $strm='';
+       my $objs;
+       my $refval=ref($val);
+
+       if ($refval eq 'OBJREF')
+       {
+               push(@{$objs}, $val);
+       }
+       elsif ($refval eq 'ARRAY')
+       {
+               $objs=$val;
+       }
+       else
+       {
+               Msg(0,"unexpected 'Contents'");
+       }
+
+       foreach my $o (@{$objs})
+       {
+               $strm.="\n" if $strm;
+               $strm.=$pdf->[$$o]->{STREAM} if exists($pdf->[$$o]->{STREAM});
+       }
+
+       $obj[$xobj]->{STREAM}=$strm;
+}
+       
+
+sub MapInsHash
+{
+       my $pdf=shift;
+       my $o=shift;
+       my $insmap=shift;
+       my $parent=shift;
+       my $val=shift;
+       
+
+       foreach my $k (keys(%{$val}))
+       {
+               MapInsValue($pdf,$o,$k,$insmap,$parent,$val->{$k}) if $k ne 
'Contents';
+       }
+}
+
+sub MapInsValue
+{
+       my $pdf=shift;
+       my $o=shift;
+       my $k=shift;
+       my $insmap=shift;
+       my $parent=shift;
+       my $val=shift;
+       my $refval=ref($val);
+
+       if ($refval eq 'OBJREF')
+       {
+               if ($k ne 'Parent')
+               {
+                       if (!exists($insmap->{IMP}->{$$val}))
+                       {
+                               $objct++;
+                               $insmap->{CUR}->{$objct}=$$val;
+                               $insmap->{IMP}->{$$val}=$objct;
+                               $obj[$objct]->{DATA}=$pdf->[$$val]->{OBJ};
+                               $obj[$objct]->{STREAM}=$pdf->[$$val]->{STREAM} 
if exists($pdf->[$$val]->{STREAM});
+                               
MapInsValue($pdf,$$val,'',$insmap,$o,$pdf->[$$val]->{OBJ});
+                       }
+                       
+                       $$val=$insmap->{IMP}->{$$val};
+               }
+               else
+               {
+                       $$val=$parent;
+               }
+       }
+       elsif ($refval eq 'ARRAY')
+       {
+               foreach my $v (@{$val})
+               {
+                       MapInsValue($pdf,$o,'',$insmap,$parent,$v)
+               }
+       }
+       elsif ($refval eq 'HASH')
+       {
+               MapInsHash($pdf,$o,$insmap,$parent,$val);
+       }
+
+}
+
+sub FindKey
+{
+       my $pdf=shift;
+       my $page=shift;
+       my $k=shift;
+
+       if (exists($pdf->[$page]->{OBJ}->{$k}))
+       {
+               my $val=$pdf->[$page]->{OBJ}->{$k};
+               $val=$pdf->[$$val]->{OBJ} if ref($val) eq 'OBJREF';
+               return($val);
+       }
+       else
+       {
+               if (exists($pdf->[$page]->{OBJ}->{Parent}))
+               {
+                       
return(FindKey($pdf,${$pdf->[$page]->{OBJ}->{Parent}},$k));
+               }
+       }
+
+       return(undef);
+}
+
+sub FindPage
+{
+       my $wantpg=shift;
+       my $pdf=shift;
+       my $catalog=${$pdf->[0]->{OBJ}->{Root}};
+       my $pages=${$pdf->[$catalog]->{OBJ}->{Pages}};
+       
+       return(NextPage($pdf,$pages,\$wantpg));
+}
+
+sub NextPage
+{
+       my $pdf=shift;
+       my $pages=shift;
+       my $wantpg=shift;
+       my $ret;
+
+       if ($pdf->[$pages]->{OBJ}->{Type} eq '/Pages')
+       {
+               foreach my $kid (@{$pdf->[$pages]->{OBJ}->{Kids}})
+               {
+                       $ret=NextPage($pdf,$$kid,$wantpg);
+                       last if $$wantpg<=0;
+               }
+       }
+       elsif ($pdf->[$pages]->{OBJ}->{Type} eq '/Page')
+       {
+               $$wantpg--;
+               $ret=$pages;
+       }
+
+       return($ret);
+}
+
+sub nextwd
+{
+       my $pdfwds=shift;
+
+       my $wd=shift(@{$pdfwds});
+
+       return('') if !defined($wd);
+       
+       if ($wd=~m/^(.*?)(<<|>>|\[|\])(.*)/)
+       {
+               if (defined($1) and length($1))
+               {
+                       unshift(@{$pdfwds},$3) if defined($3) and length($3);
+                       unshift(@{$pdfwds},$2);
+                       $wd=$1;
+               }
+               else
+               {
+                       unshift(@{$pdfwds},$3) if defined($3) and length($3);
+                       $wd=$2;
+               }
+       }
+       
+       return($wd);
+}
+
+sub ParsePDFObj
+{
+       
+       my $pdfwds=shift;
+       my $rtn;
+       my $wd;
+
+       while ($wd=nextwd($pdfwds),length($wd))
+       {
+               if ($wd eq 'stream' or $wd eq 'endstream')
+               {
+                       next;
+               }
+               elsif ($wd eq 'endobj' or $wd eq 'startxref')
+               {
+                       last;
+               }
+               else
+               {
+                       unshift(@{$pdfwds},$wd);
+                       $rtn=ParsePDFValue($pdfwds);
+               }
+       }
+
+       return($rtn);
+}
+
+sub ParsePDFHash
+{
+       my $pdfwds=shift;
+       my $rtn={};
+       my $wd;
+       
+       while ($wd=nextwd($pdfwds),length($wd))
+       {
+               if ($wd eq '>>')
+               {
+                       last;
+               }
+
+               my (@w)=split('/',$wd,3);
+
+               if ($w[0])
+               {
+                       Msg(0,"PDF Dict Key '$wd' does not start with '/'");
+                       exit 1;
+               }
+               else
+               {
+                       unshift(@{$pdfwds},"/$w[2]") if $w[2];
+                       $wd=$w[1];
+                       (@w)=split('\(',$wd,2);
+                       $wd=$w[0];
+                       unshift(@{$pdfwds},"($w[1]") if defined($w[1]);
+                       (@w)=split('\<',$wd,2);
+                       $wd=$w[0];
+                       unshift(@{$pdfwds},"<$w[1]") if defined($w[1]);
+
+                       $rtn->{$wd}=ParsePDFValue($pdfwds);
+               }
+       }
+
+       return($rtn);
+}
+
+sub ParsePDFValue
+{
+       my $pdfwds=shift;
+       my $rtn;
+       my $wd=nextwd($pdfwds);
+
+       if ($wd=~m/^\d+$/ and $pdfwds->[0]=~m/^\d+$/ and 
$pdfwds->[1]=~m/^R(\]|\>|\/)?/)
+       {
+               shift(@{$pdfwds});
+               if (defined($1) and length($1))
+               {
+                       $pdfwds->[0]=substr($pdfwds->[0],1);
+               }
+               else
+               {
+                       shift(@{$pdfwds});
+               }
+               return(bless(\$wd,'OBJREF'));
+       }
+
+       if ($wd eq '<<')
+       {
+               return(ParsePDFHash($pdfwds));
+       }
+
+       if ($wd eq '[')
+       {
+               return(ParsePDFArray($pdfwds));
+       }
+
+       if ($wd=~m/(.*?)(\(.*)$/)
+       {
+               if (defined($1) and length($1))
+               {
+                       unshift(@{$pdfwds},$2);
+                       $wd=$1;
+               }
+               else
+               {
+                       return(ParsePDFString($wd,$pdfwds));
+               }
+       }
+
+       if ($wd=~m/(.*?)(\<.*)$/)
+       {
+               if (defined($1) and length($1))
+               {
+                       unshift(@{$pdfwds},$2);
+                       $wd=$1;
+               }
+               else
+               {
+                       return(ParsePDFHexString($wd,$pdfwds));
+               }
+       }
+
+       if ($wd=~m/(.+?)(\/.*)$/)
+       {
+               if (defined($2) and length($2))
+               {
+                       unshift(@{$pdfwds},$2);
+                       $wd=$1;
+               }
+       }
+
+       return($wd);
+}
+
+sub ParsePDFString
+{
+       my $wd=shift;
+       my $rtn='';
+       my $pdfwds=shift;
+       my $lev=0;
+
+       while (length($wd))
+       {
+               $rtn.=' ' if length($rtn);
+
+               while ($wd=~m/(?<!\\)\(/g) {$lev++;}
+               while ($wd=~m/(?<!\\)\)/g) {$lev--;}
+               
+               
+               if ($lev<=0 and $wd=~m/^(.*?\))([^)]+)$/)
+               {
+                       unshift(@{$pdfwds},$2) if defined($2) and length($2);
+                       $wd=$1;
+               }
+
+               $rtn.=$wd;
+               
+               last if $lev <= 0;
+
+               $wd=nextwd($pdfwds);
+       }
+
+       return($rtn);
+}
+
+sub ParsePDFHexString
+{
+       my $wd=shift;
+       my $rtn='';
+       my $pdfwds=shift;
+       my $lev=0;
+       
+       if ($wd=~m/^(<.+?>)(.*)/)
+       {
+               unshift(@{$pdfwds},$2) if defined($2) and length($2);
+               $rtn=$1;
+       }
+       
+       return($rtn);
+}
+
+sub ParsePDFArray
+{
+       my $pdfwds=shift;
+       my $rtn=[];
+       my $wd;
+       
+       while (1)
+       {
+               $wd=ParsePDFValue($pdfwds);
+               last if $wd eq ']' or length($wd)==0;
+               push(@{$rtn},$wd);
+       }
+
+       return($rtn);
+}
+               
+sub Msg
+{
+       my ($lev,$msg)address@hidden;
+
+       print STDERR "$env{SourceFile}: " if exists($env{SourceFile});
+       print STDERR "$msg\n";
+       exit 1 if $lev;
+}
+
+sub PutXY
+{
+       my ($x,$y)=(@_);
+       
+       if ($frot)
+       {
+               return("$y $x");
+       }
+       else
+       {
+               $y=$mediabox[3]-$y;
+               return("$x $y");
+       }
+}
+
+sub GraphY
+{
+       my $y=shift;
+       
+       if ($frot)
+       {
+               return($y);
+       }
+       else
+       {
+               return($mediabox[3]-$y);
+       }
+}
+
+sub Put
+{
+       my $msg=shift;
+       
+       print $msg;
+       $fct+=length($msg);
+}
+
+sub PutObj
+{
+       my $ono=shift;
+       my $msg="$ono 0 obj ";
+       $obj[$ono]->{XREF}=$fct;
+       if (exists($obj[$ono]->{STREAM}))
+       {
+               if (!$debug)
+               {
+                       
$obj[$ono]->{STREAM}=Compress::Zlib::compress($obj[$ono]->{STREAM});
+                       $obj[$ono]->{DATA}->{'Filter'}=['/FlateDecode'];
+               }
+               
+               $obj[$ono]->{DATA}->{'Length'}=length($obj[$ono]->{STREAM});
+       }
+       PutField(\$msg,$obj[$ono]->{DATA});
+       PutStream(\$msg,$ono) if exists($obj[$ono]->{STREAM});
+       Put($msg."endobj\n");
+}
+
+sub PutStream
+{
+       my $msg=shift;
+       my $ono=shift;
+       
+       # We could 'flate' here
+       $$msg.="stream\n$obj[$ono]->{STREAM}endstream\n";
+}
+
+sub PutField
+{
+       my $pmsg=shift;
+       my $fld=shift;
+       my $term=shift||"\n";
+       my $typ=ref($fld);
+
+       if ($typ eq '')
+       {
+               $$pmsg.="$fld$term";
+       }
+       elsif ($typ eq 'ARRAY')
+       {
+               $$pmsg.='[';
+               foreach my $cell (@{$fld})
+               {
+                       PutField($pmsg,$cell,' ');
+               }
+               $$pmsg.="]$term";
+       }
+       elsif ($typ eq 'HASH')
+       {
+               $$pmsg.='<< ';
+               foreach my $key (sort keys %{$fld})
+               {
+                       $$pmsg.="/$key ";
+                       PutField($pmsg,$fld->{$key});
+               }
+               $$pmsg.=">>$term";
+       }
+       elsif ($typ eq 'OBJREF')
+       {
+               $$pmsg.="$$fld 0 R$term";
+       }
+}
+
+sub BuildObj
+{
+       my $ono=shift;
+       my $val=shift;
+
+       $obj[$ono]->{DATA}=$val;
+
+       return("$ono 0 R ");
+}
+
+sub LoadFont
+{
+       my $fontno=shift;
+       my $fontnm=shift;
+       my $ofontnm=$fontnm;
+
+       return $fontlst{$fontno}->{OBJ} if (exists($fontlst{$fontno}));
+
+       my $f;
+       OpenFile(\$f,$fontdir,"$fontnm");
+
+       if (!defined($f) and $Foundry)
+       {
+               # Try with no foundry
+               $fontnm=~s/.*?-//;
+               OpenFile(\$f,$fontdir,$fontnm);
+       }
+       
+       Msg(1,"Failed to open font '$ofontnm'") if !defined($f);
+
+       my $foundry='';
+       $foundry=$1 if $fontnm=~m/^(.*?)-/;
+       my $stg=1;
+       my %fnt;
+       my @fntbbox=(0,0,0,0);
+       my $capheight=0;
+       my $lastchr=0;
+       my $t1flags=0;
+       my $fixwid=-1;
+       my $ascent=0;
+       my $charset='';
+
+       while (<$f>)
+       {
+               chomp;
+
+               s/^ +//;
+               s/^#.*// if $stg == 1;
+               next if $_ eq '';
+               
+               if ($stg == 1)
+               {
+                       my ($key,$val)=split(' ',$_,2);
+
+                       $key=lc($key);
+                       $stg=2,next if $key eq 'kernpairs';
+                       $stg=3,next if lc($_) eq 'charset';
+                       
+                       $fnt{$key}=$val
+               }
+               elsif ($stg == 2)
+               {
+                       $stg=3,next if lc($_) eq 'charset';
+
+                       my ($ch1,$ch2,$k)=split;
+                       $fnt{KERN}->{$ch1}->{$ch2}=$k;
+               }
+               else
+               {
+                       my (@r)=split;
+                       my (@p)=split(',',$r[1]);
+
+                       if ($r[1] eq '"')
+                       {
+                               $fnt{GNM}->{$r[0]}=$lastchr;
+                               next;
+                       }
+                       
+                       $r[0]='u0020' if $r[3] == 32;
+                       next if $r[3] >255;
+                       $fnt{GNM}->{$r[0]}=$r[3];
+                       $fnt{GNO}->[$r[3]]='/'.$r[4];
+                       $fnt{WID}->[$r[3]]=$p[0];
+                       $lastchr=$r[3] if $r[3] > $lastchr;
+                       $fixwid=$p[0] if $fixwid == -1;
+                       $fixwid=-2 if $fixwid > 0 and $p[0] != $fixwid;
+
+                       $fntbbox[1]=-$p[2] if defined($p[2]) and -$p[2] < 
$fntbbox[1];
+                       $fntbbox[2]=$p[0] if $p[0] > $fntbbox[2];
+                       $fntbbox[3]=$p[1] if defined($p[1]) and $p[1] > 
$fntbbox[3];
+                       $ascent=$p[1] if defined($p[1]) and $p[1] > $ascent and 
$r[3] >= 32 and $r[3] < 128;
+                       $charset.='/'.$r[4] if defined($r[4]);
+                       $capheight=$p[1] if length($r[4]) == 1 and $r[4] ge 'A' 
and $r[4] le 'Z' and $p[1] > $capheight;
+               }
+       }
+
+       close($f);
+
+       unshift(@{$fnt{GNO}},0);
+
+       foreach my $glyph (@{$fnt{GNO}})
+       {
+               $glyph='/.notdef' if !defined($glyph);
+       }
+       
+       foreach my $w (@{$fnt{WID}})
+       {
+               $w=0 if !defined($w);
+       }
+       
+       my $fno=0;
+       my $slant=0;
+       $slant=-$fnt{'slant'} if exists($fnt{'slant'});
+       $fnt{'spacewidth'}=700 if !exists($fnt{'spacewidth'});
+
+       $t1flags|=2**0 if $fixwid > -1;
+       $t1flags|=(exists($fnt{'special'}))?2**2:2**5;
+       $t1flags|=2**6 if $slant != 0;
+       my $fontkey="$foundry $fnt{internalname}";
+       
+       if (exists($download{$fontkey}))
+       {
+               # Not a Base Font
+               my ($l1,$l2,$l3,$t1stream)=GetType1($download{$fontkey});
+               Msg(0,"Incorrect font format for '$fontkey' ($l1)") if 
!defined($t1stream);
+               $fno=++$objct;
+               $fontlst{$fontno}->{OBJ}=BuildObj($objct,
+                                                 {'Type' => '/Font',
+                                                 'Subtype' => '/Type1',
+                                                 'BaseFont' => 
'/'.$fnt{internalname},
+                                                 'Widths' => $fnt{WID},
+                                                 'FirstChar' => 0,
+                                                 'LastChar' => $lastchr,
+                                                 'Encoding' => 
BuildObj($objct+1,
+                                                                         
{'Type' => '/Encoding',
+                                                                         
'Differences' => $fnt{GNO}
+                                                                         }
+                                                                         ),
+                                                 'FontDescriptor' => 
BuildObj($objct+2,
+                                                                               
{'Type' => '/FontDescriptor',
+                                                                               
'FontName' => '/'.$fnt{internalname},
+                                                                               
'Flags' => $t1flags,
+                                                                               
'FontBBox' => address@hidden,
+                                                                               
'ItalicAngle' => $slant,
+                                                                               
'Ascent' => $ascent,
+                                                                               
'Descent' => $fntbbox[1],
+                                                                               
'CapHeight' => $capheight,
+                                                                               
'StemV' => 0,
+                                                                               
'CharSet' => "($charset)",
+                                                                               
'FontFile' => BuildObj($objct+3,
+                                                                               
                        {'Length1' => $l1,
+                                                                               
                        'Length2' => $l2,
+                                                                               
                        'Length3' => $l3
+                                                                               
                        }
+                                                                               
                        )
+                                                                               
}
+                                                                               
)
+                                                 }
+                                                 );
+                                                 
+               $objct+=3;
+               $fontlst{$fontno}->{NM}='/F'.$fontno;
+               
$pages->{'Resources'}->{'Font'}->{'F'.$fontno}=$fontlst{$fontno}->{OBJ};
+               $fontlst{$fontno}->{FNT}=\%fnt;
+               $obj[$objct]->{STREAM}=$t1stream;
+               
+       }
+       else
+       {
+               $fno=++$objct;
+               $fontlst{$fontno}->{OBJ}=BuildObj($objct,
+                                                 {'Type' => '/Font',
+                                                 'Subtype' => '/Type1',
+                                                 'BaseFont' => 
'/'.$fnt{internalname},
+                                                 'Encoding' => 
BuildObj($objct+1,
+                                                                        
{'Type' => '/Encoding',
+                                                                         
'Differences' => $fnt{GNO}
+                                                                        }
+                                                                        )
+                                                 }
+                                               );
+               $objct+=1;
+               $fontlst{$fontno}->{NM}='/F'.$fontno;
+               
$pages->{'Resources'}->{'Font'}->{'F'.$fontno}=$fontlst{$fontno}->{OBJ};
+               $fontlst{$fontno}->{FNT}=\%fnt;
+       }
+
+       PutObj($fno);
+       PutObj($fno+1);
+       PutObj($fno+2) if defined($obj[$fno+2]);
+       PutObj($fno+3) if defined($obj[$fno+3]);
+}
+
+sub GetType1
+{
+       my $file=shift;
+       my ($l1,$l2,$l3);               # Return lengths
+       my ($head,$body,$tail);         # Font contents
+       my $f;
+
+       OpenFile(\$f,$fontdir,"$file");
+       Msg(1,"Failed to open '$file'") if !defined($f);
+
+       my $l=<$f>;
+
+       if (substr($l,0,1) eq "\x80")
+       {
+               # PFB file
+               sysseek($f,0,0);
+               my $hdr='';
+               $l1=$l2=$l3=0;
+               my $typ=0;
+               my $data='';
+               my $sl=0;
+
+               while ($typ != 3)
+               {
+                       my $chk=sysread($f,$hdr,6);
+
+                       if ($chk < 2)
+                       {
+                               # eof($f) uses buffered i/o (since file was 
open not sysopen)
+                               # which screws up next sysread. So this will 
terminate loop if font
+                               # has no terminating section type 3.
+                               last if $l3;
+                               return(5,$l2,$l3,undef);
+                       }
+                       
+                       $typ=ord(substr($hdr,1,1));
+
+                       if ($chk == 6)
+                       {
+                               $sl=unpack('L',substr($hdr,2,4));
+                               $chk=sysread($f,$data,$sl);
+                               return(1,$l2,$l3,undef) if $chk != $sl;
+                       }
+
+                       if ($typ == 1)
+                       {
+                               if ($l2 == 0)
+                               {
+                                       # First text bit(s) must be head
+                                       $head.=$data;
+                                       $l1+=$sl;
+                               }
+                               else
+                               {
+                                       # A text bit after the binary sections 
must be tail
+                                       $tail.=$data;
+                                       $l3+=$sl;
+                               }
+                       }
+                       elsif ($typ == 2)
+                       {
+                               return(2,$l2,$l3,undef) if $l3; # Found a 
binary bit after the tail
+                               $body.=$data;
+                               $l2+=$sl;
+                       }
+                       elsif ($typ != 3)
+                       {
+                               # What segment type is this!
+                               return(3,$l2,$l3,undef);
+                       }
+               }
+
+               close($f);
+               return($l1,$l2,$l3,"$head$body$tail");
+       }
+
+       my (@lines)=(<$f>);
+       unshift(@lines,$l);
+
+       close($f);
+
+       Msg(1,"Font file '$file' must be an Adobe type 1 font file") if 
$lines[0]!~m/\%\!PS.Adobe/i;
+       $head=$body=$tail='';
+       
+       foreach my $line (@lines)
+       {
+               if (!defined($l1))
+               {
+                       if (length($line) > 19 and $line=~s/^(currentfile 
eexec)//)
+                       {
+                               $head.=$1;
+                               $l1=length($head);
+                               redo;
+                       }
+                       
+                       $head.=$line;
+                       
+                       if ($line=~m/eexec$/)
+                       {
+                               #                               chomp($head);
+                               #                               $head.="\x0d";
+                               $l1=length($head);
+                       }
+               }
+               elsif (!defined($l2))
+               {
+                       #$line=~s/(\0\0)0+$/&1/;
+                       if ($line=~m/^0+$/)
+                       {
+                               $l2=length($body);
+                               $tail=$line;
+                       }
+                       else
+                       {
+                               chomp($line);
+                               $body.=pack('H*',$line);
+                       }
+               }
+               else
+               {
+                       $tail.=$line;
+               }
+       }
+       
+       $l1=length($head);
+       $l2=length($body);
+       $l3=length($tail);
+       
+       return($l1,$l2,$l3,"$head$body$tail");
+}
+
+
+sub OutStream
+{
+       my $ono=shift;
+
+       IsGraphic();
+       $stream.="Q\n";
+       $obj[$ono]->{STREAM}=$stream;
+       $obj[$ono]->{DATA}->{Length}=length($stream);
+       $stream='';
+       PutObj($ono);
+}
+
+sub do_p
+{
+       # Start of pages
+
+       if ($cpageno > 0)
+       {
+               PutObj($cpageno);
+               OutStream($cpageno+1);
+       }
+       
+       $cpageno=++$objct;
+
+       push(@{$pages->{Kids}},BuildObj($objct,
+                                        {'Type' => '/Page',
+                                        'Group' => {'CS' => '/DeviceRGB', 'S' 
=> '/Transparency'},
+                                        'Parent' => '2 0 R',
+                                        'Contents' => [ BuildObj($objct+1,
+                                                               {'Length' => 0}
+                                                               ) ],
+                                        }
+                                        )
+           );
+       $objct+=1;
+       $cpage=$obj[$cpageno]->{DATA};
+       $pages->{'Count'}++;
+       $stream="q 1 0 0 1 0 0 cm\n";
+       $mode='g';
+       $curfill='';
+       @address@hidden;
+}
+
+sub do_f
+{
+       my $par=shift;
+
+#      IsText();
+       $cft="$par";
+       $fontchg=1;
+#      $stream.="/F$cft $cftsz Tf\n" if $cftsz;
+       $widtbl=CacheWid($par);
+       $origwidtbl=$fontlst{$par}->{FNT}->{WID};
+       $krntbl=$fontlst{$par}->{FNT}->{KERN};
+}
+
+sub CacheWid
+{
+       my $par=shift;
+
+       if (!defined($fontlst{$par}->{CACHE}->{$cftsz}))
+       {
+               
$fontlst{$par}->{CACHE}->{$cftsz}=BuildCache($fontlst{$par}->{FNT}->{WID});
+       }
+       
+       return($fontlst{$par}->{CACHE}->{$cftsz});
+}
+
+sub BuildCache
+{
+       my $wid=shift;
+       return([]);
+       my @cwid;
+
+       foreach my $w (@{$wid})
+       {
+               push(@cwid,$w*$cftsz);
+       }
+
+       return(address@hidden);
+}
+
+sub IsText
+{
+       if ($mode eq 'g')
+       {
+               $xpos+=$pendmv/$unitwidth;
+               $stream.="q BT\n$matrix ".PutXY($xpos,$ypos)." Tm\n";
+               $poschg=0;
+               $fontchg=0;
+               $pendmv=0;
+               $matrixchg=0;
+               $tmxpos=$xpos;
+               $stream.=$textcol."\n", $curfill=$textcol if $textcol ne 
$curfill;
+               if (defined($cft))
+               {
+                       $whtsz=$fontlst{$cft}->{FNT}->{spacewidth}*$cftsz;
+                       $stream.="/F$cft $cftsz Tf\n";
+               }
+       }
+
+       if ($poschg or $matrixchg)
+       {
+               PutLine(0) if $matrixchg;
+               $stream.="$matrix ".PutXY($xpos,$ypos)." Tm\n", $poschg=0;
+               $tmxpos=$xpos;
+               $matrixchg=0;
+       }
+
+       if ($fontchg)
+       {
+               PutLine(0);
+               $whtsz=$fontlst{$cft}->{FNT}->{spacewidth}*$cftsz;
+               $stream.="/F$cft $cftsz Tf\n" if $cftsz and defined($cft);
+               $fontchg=0;
+       }
+
+       $mode='t';
+}
+
+sub IsGraphic
+{
+       if ($mode eq 't')
+       {
+               PutLine();
+               $stream.="ET Q\n";
+               $xpos+=($pendmv-$nomove)/$unitwidth;
+               $pendmv=0;
+               $nomove=0;
+               $stream.=$strkcol."\n", $curstrk=$strkcol if $strkcol ne 
$curstrk;
+               $curfill=$fillcol;
+       }
+       $mode='g';
+}
+
+sub do_s
+{
+       my $par=shift;
+       $par/=$unitwidth;
+
+       if ($par != $cftsz and defined($cft))
+       {
+               PutLine();
+               $cftsz=$par;
+#              $stream.="/F$cft $cftsz Tf\n";
+               $fontchg=1;
+               $widtbl=CacheWid($cft);
+       }
+}
+
+sub do_m
+{
+       # Groff uses /m[] for text & graphic stroke, and /M[] (DF?) for graphic 
fill.
+       # PDF uses G/RG/K for graphic stroke, and g/rg/k for text & graphic 
fill.
+       #
+       # This means that we must maintain g/rg/k state separately for text 
colour & graphic fill (this is
+       # probably why 'gs' maintains seperate graphic states for text & 
graphics when distilling PS -> PDF).
+       #
+       # To facilitate this:-
+       #
+       #       $textcol        = current groff stroke colour
+       #       $fillcol        = current groff fill colour
+       #       $curfill        = current PDF fill colour
+       
+       my $par=shift;
+       my $mcmd=substr($par,0,1);
+
+       $par=substr($par,1);
+       $par=~s/^ +//;
+       
+#      IsGraphic();
+
+       $textcol=set_col($mcmd,$par,0);
+       $strkcol=set_col($mcmd,$par,1);
+
+       if ($mode eq 't')
+       {
+               PutLine();
+               $stream.=$textcol."\n";
+               $curfill=$textcol;
+       }
+       else
+       {
+               $stream.="$strkcol\n";
+               $curstrk=$strkcol;
+       }
+}
+
+sub set_col
+{
+       my $mcmd=shift;
+       my $par=shift;
+       my $upper=shift;
+       my @oper=('g','k','rg');
+
+       @oper=('G','K','RG') if $upper;
+
+       if ($mcmd eq 'd')
+       {
+               # default colour
+               return("0 $oper[0]");
+       }
+       
+       my (@c)=split(' ',$par);
+       
+       if ($mcmd eq 'c')
+       {
+               # Text CMY
+               return(($c[0]/65535).' '.($c[1]/65535).' '.($c[2]/65535)." 0 
$oper[1]");
+       }
+       elsif ($mcmd eq 'k')
+       {
+               # Text CMYK
+               return(($c[0]/65535).' '.($c[1]/65535).' '.($c[2]/65535).' 
'.($c[3]/65535)." $oper[1]");
+       }
+       elsif ($mcmd eq 'g')
+       {
+               # Text Grey
+               return(($c[0]/65535)." $oper[0]");
+       }
+       elsif ($mcmd eq 'r')
+       {
+               # Text RGB0
+               return(($c[0]/65535).' '.($c[1]/65535).' '.($c[2]/65535)." 
$oper[2]");
+       }
+}
+       
+sub do_D
+{
+       my $par=shift;
+       my $Dcmd=substr($par,0,1);
+       
+       $par=substr($par,1);
+       $xpos+=$pendmv/$unitwidth;
+       $pendmv=0;
+       
+       IsGraphic();
+
+       if ($Dcmd eq 'F')
+       {
+               my $mcmd=substr($par,0,1);
+               
+               $par=substr($par,1);
+               $par=~s/^ +//;
+               
+               $fillcol=set_col($mcmd,$par,0);
+               $stream.="$fillcol\n";
+               $curfill=$fillcol;
+       }
+       elsif ($Dcmd eq 'f')
+       {
+               my $mcmd=substr($par,0,1);
+               
+               $par=substr($par,1);
+               $par=~s/^ +//;
+               ($par)=split(' ',$par);
+               
+               if ($par >= 0 and $par <= 1000)
+               {
+                       $fillcol=set_col('g',int((1000-$par)*65535/1000),0);
+               }
+               else
+               {
+                       $fillcol=lc($textcol);
+               }
+
+               $stream.="$fillcol\n";
+               $curfill=$fillcol;
+       }
+       elsif ($Dcmd eq '~')
+       {
+               # B-Spline
+               my (@p)=split(' ',$par);
+               my ($nxpos,$nypos);
+               
+               foreach my $p (@p) { $p/=$unitwidth; }
+               $stream.=PutXY($xpos,$ypos)." m\n";
+               $xpos+=($p[0]/2);
+               $ypos+=($p[1]/2);
+               $stream.=PutXY($xpos,$ypos)." l\n";
+               
+               for (my $i=0; $i < $#p-1; $i+=2)
+               {
+                       $nxpos=(($p[$i]*$tnum)/(2*$tden));
+                       $nypos=(($p[$i+1]*$tnum)/(2*$tden));
+                       $stream.=PutXY(($xpos+$nxpos),($ypos+$nypos))." ";
+                       $nxpos=($p[$i]/2 + ($p[$i+2]*($tden-$tnum))/(2*$tden));
+                       $nypos=($p[$i+1]/2 + 
($p[$i+3]*($tden-$tnum))/(2*$tden));
+                       $stream.=PutXY(($xpos+$nxpos),($ypos+$nypos))." ";
+                       $nxpos=(($p[$i]-$p[$i]/2) + $p[$i+2]/2);
+                       $nypos=(($p[$i+1]-$p[$i+1]/2) + $p[$i+3]/2);
+                       $stream.=PutXY(($xpos+$nxpos),($ypos+$nypos))." c\n";
+                       $xpos+=$nxpos;
+                       $ypos+=$nypos;
+               }
+               
+               $xpos+=($p[$#p-1]-$p[$#p-1]/2);
+               $ypos+=($p[$#p]-$p[$#p]/2);
+               $stream.=PutXY($xpos,$ypos)." l\nS\n";
+               $poschg=1;
+       }
+       elsif ($Dcmd eq 'p' or $Dcmd eq 'P')
+       {
+               # B-Spline
+               my (@p)=split(' ',$par);
+               my ($nxpos,$nypos);
+               
+               foreach my $p (@p) { $p/=$unitwidth; }
+               $stream.=PutXY($xpos,$ypos)." m\n";
+               
+               for (my $i=0; $i < $#p; $i+=2)
+               {
+                       $xpos+=($p[$i]);
+                       $ypos+=($p[$i+1]);
+                       $stream.=PutXY($xpos,$ypos)." l\n";
+               }
+
+               if ($Dcmd eq 'p')
+               {
+                       $stream.="s\n";
+               }
+               else
+               {
+                       $stream.="f\n";
+               }
+               $poschg=1;
+       }
+       elsif ($Dcmd eq 'c')
+       {
+               # Stroke circle
+               $par=substr($par,1);
+               my (@p)=split(' ',$par);
+               
+               DrawCircle($p[0],$p[0]);
+               $stream.="s\n";
+               $poschg=1;
+       }
+       elsif ($Dcmd eq 'C')
+       {
+               # Fill circle
+               $par=substr($par,1);
+               my (@p)=split(' ',$par);
+               
+               DrawCircle($p[0],$p[0]);
+               $stream.="f\n";
+               $poschg=1;
+       }
+       elsif ($Dcmd eq 'e')
+       {
+               # Stroke ellipse
+               $par=substr($par,1);
+               my (@p)=split(' ',$par);
+               
+               DrawCircle($p[0],$p[1]);
+               $stream.="s\n";
+               $poschg=1;
+       }
+       elsif ($Dcmd eq 'E')
+       {
+               # Fill ellipse
+               $par=substr($par,1);
+               my (@p)=split(' ',$par);
+               
+               DrawCircle($p[0],$p[1]);
+               $stream.="f\n";
+               $poschg=1;
+       }
+       elsif ($Dcmd eq 'l')
+       {
+               # Line To
+               $par=substr($par,1);
+               my (@p)=split(' ',$par);
+               
+               foreach my $p (@p) { $p/=$unitwidth; }
+               $stream.=PutXY($xpos,$ypos)." m\n";
+               $xpos+=$p[0];
+               $ypos+=$p[1];
+               $stream.=PutXY($xpos,$ypos)." l\n";
+               
+               $stream.="s\n";
+               $poschg=1;
+       }
+       elsif ($Dcmd eq 't')
+       {
+               # Line Thickness
+               $par=substr($par,1);
+               my (@p)=split(' ',$par);
+               
+               foreach my $p (@p) { $p/=$unitwidth; }
+               #               $xpos+=$p[0]*100;               # WTF!!!
+               #int lw = 
((font::res/(72*font::sizescale))*linewidth*env->size)/1000;
+               
$p[0]=(($desc{res}/(72*$desc{sizescale}))*$linewidth*$cftsz)/1000 if $p[0] < 0;
+               $lwidth=$p[0];
+               $stream.="$p[0] w\n";
+               $poschg=1;
+       }
+       elsif ($Dcmd eq 'a')
+       {
+               # Arc
+               $par=substr($par,1);
+               my (@p)=split(' ',$par);
+               my $rad180=3.14159;
+               my $rad360=$rad180*2;
+               my $rad90=$rad180/2;
+
+               foreach my $p (@p) { $p/=$unitwidth; }
+
+               # Documentation is wrong. Groff does not use Dh1,Dv1 as centre 
of the circle!
+
+               my $centre=adjust_arc_centre(address@hidden);
+
+               # Using formula here : http://www.tinaja.com/glib/bezcirc2.pdf
+               # First calculate angle between start and end point
+
+               my ($startang,$r)=RtoP(-$centre->[0],$centre->[1]);
+               my 
($endang,$r2)=RtoP(($p[0]+$p[2])-$centre->[0],-($p[1]+$p[3]-$centre->[1]));
+               $endang+=$rad360 if $endang < $startang;
+               my $totang=($endang-$startang)/4;       # do it in 4 pieces
+
+               # Now 1 piece
+
+               my $x0=cos($totang/2);
+               my $y0=sin($totang/2);
+               my $x3=$x0;
+               my $y3=-$y0;
+               my $x1=(4-$x0)/3;
+               my $y1=((1-$x0)*(3-$x0))/(3*$y0);
+               my $x2=$x1;
+               my $y2=-$y1;
+
+               # Rotate to start position and draw 4 pieces
+
+               foreach my $j (0..3)
+               {
+                       
PlotArcSegment($totang/2+$startang+$j*$totang,$r,$xpos+$centre->[0],GraphY($ypos+$centre->[1]),$x0,$y0,$x1,$y1,$x2,$y2,$x3,$y3);
+               }
+
+               $xpos+=$p[0]+$p[2];
+               $ypos+=$p[1]+$p[3];
+
+               $poschg=1;
+       }
+}
+
+sub deg
+{
+       return int($_[0]*180/3.14159);
+}
+
+sub adjust_arc_centre
+{
+       # Taken from geometry.cpp
+       
+       # We move the center along a line parallel to the line between
+       # the specified start point and end point so that the center
+       # is equidistant between the start and end point.
+       # It can be proved (using Lagrange multipliers) that this will
+       # give the point nearest to the specified center that is equidistant
+       # between the start and end point.
+
+       my $p=shift;
+       my @c;
+       my $x = $p->[0] + $p->[2];      # (x, y) is the end point
+       my $y = $p->[1] + $p->[3];
+       my $n = $x*$x + $y*$y;
+       if ($n != 0)
+       {
+               $c[0]= $p->[0];
+               $c[1] = $p->[1];
+               my $k = .5 - ($c[0]*$x + $c[1]*$y)/$n;
+               $c[0] += $k*$x;
+               $c[1] += $k*$y;
+               return(address@hidden);
+       }
+       else
+       {
+               return(undef);
+       }
+}
+
+
+sub PlotArcSegment
+{
+       my 
($ang,$r,$transx,$transy,$x0,$y0,$x1,$y1,$x2,$y2,$x3,$y3)address@hidden;
+       my $cos=cos($ang);
+       my $sin=sin($ang);
+  my @mat=($cos,$sin,-$sin,$cos,0,0);
+       my $lw=$lwidth/$r;
+       
+       $stream.="q $r 0 0 $r $transx $transy cm ".join(' ',@mat)." cm $lw w 
$x0 $y0 m $x1 $y1 $x2 $y2 $x3 $y3 c S Q\n";
+}
+
+sub DrawCircle
+{
+       my $hd=shift;
+       my $vd=shift;
+       my $hr=$hd/2/$unitwidth;
+       my $vr=$vd/2/$unitwidth;
+       my $kappa=0.5522847498;
+       $hd/=$unitwidth;
+       $vd/=$unitwidth;
+       
+
+       $stream.=PutXY(($xpos+$hd),$ypos)." m\n";
+       $stream.=PutXY(($xpos+$hd),($ypos+$vr*$kappa))." 
".PutXY(($xpos+$hr+$hr*$kappa),($ypos+$vr))." 
".PutXY(($xpos+$hr),($ypos+$vr))." c\n";
+       $stream.=PutXY(($xpos+$hr-$hr*$kappa),($ypos+$vr))." 
".PutXY(($xpos),($ypos+$vr*$kappa))." ".PutXY(($xpos),($ypos))." c\n";
+       $stream.=PutXY(($xpos),($ypos-$vr*$kappa))." 
".PutXY(($xpos+$hr-$hr*$kappa),($ypos-$vr))." 
".PutXY(($xpos+$hr),($ypos-$vr))." c\n";
+       $stream.=PutXY(($xpos+$hr+$hr*$kappa),($ypos-$vr))." 
".PutXY(($xpos+$hd),($ypos-$vr*$kappa))." ".PutXY(($xpos+$hd),($ypos))." c\n";
+       $xpos+=$hd;
+
+       $poschg=1;
+}
+
+sub FindCircle
+{
+       my ($x1,$y1,$x2,$y2,$x3,$y3)address@hidden;
+       my ($Xo, $Yo);
+       
+       my $x=$x2+$x3;
+       my $y=$y2+$y3;
+       my $n=$x**2+$y**2;
+
+       if ($n)
+       {
+               my $k=.5-($x2*$x + $y2*$y)/$n;
+               return(sqrt($n),$x2+$k*$x,$y2+$k*$y);
+       }
+       else
+       {
+               return(-1);
+       }
+       
+}
+
+sub PtoR
+{
+       my ($theta,$r)address@hidden;
+       
+       return($r*cos($theta),$r*sin($theta));
+}
+
+sub RtoP
+{
+       my ($x,$y)address@hidden;
+       
+       return(atan2($y,$x),sqrt($x**2+$y**2));
+}
+
+sub PutLine
+{
+
+       my $f=shift;
+
+       IsText() if !defined($f);
+       
+       return if (scalar(@lin) == 0) or (!defined($lin[0]->[0]) and $#lin == 
0);
+
+#      $stream.="% --- wht=$whtsz, pend=$pendmv, nomv=$nomove\n" if $debug;
+       $pendmv-=$nomove;
+       $lin[$#lin]->[1]=-$pendmv/$cftsz if ($pendmv != 0);
+
+       if (0)
+       {
+               if (scalar(@lin) == 1 and (!defined($lin[0]->[1]) or 
$lin[0]->[1] == 0))
+               {
+                       $stream.="($lin[0]->[0]) Tj\n";
+               }
+               else
+               {
+                       $stream.="[";
+                       
+                       foreach my $wd (@lin)
+                       {
+                               $stream.="($wd->[0]) " if defined($wd->[0]);
+                               $stream.="$wd->[1] " if defined($wd->[1]) and 
$wd->[1] != 0;
+                       }
+                       
+                       $stream.="] TJ\n";
+               }
+       }
+       else
+       {
+               if (scalar(@lin) == 1 and (!defined($lin[0]->[1]) or 
$lin[0]->[1] == 0))
+               {
+                       $stream.="0 Tw ($lin[0]->[0]) Tj\n";
+               }
+               else
+               {
+                       if ($wt>=-1 or $#lin == 0 or $lin[0]->[1]>=0)
+                       {
+                               $stream.="0 Tw [";
+
+                               foreach my $wd (@lin)
+                               {
+                                       $stream.="($wd->[0]) " if 
defined($wd->[0]);
+                                       $stream.="$wd->[1] " if 
defined($wd->[1]) and $wd->[1] != 0;
+                               }
+
+                               $stream.="] TJ\n";
+                       }
+                       else
+                       {
+       #                       $stream.="\%dg  0 Tw [";
+       #
+       #                       foreach my $wd (@lin)
+       #                       {
+       #                               $stream.="($wd->[0]) " if 
defined($wd->[0]);
+       #                               $stream.="$wd->[1] " if 
defined($wd->[1]) and $wd->[1] != 0;
+       #                       }
+       #
+       #                       $stream.="] TJ\n";
+       #
+       #                               my $wt=$lin[0]->[1]||0;
+
+       #                       while ($wt < -$whtsz/$cftsz)
+       #                       {
+       #                               $wt+=$whtsz/$cftsz;
+       #                       }
+
+                               $stream.=sprintf( "%.3f Tw 
",-($whtsz+$wt*$cftsz)/$unitwidth );
+                               $stream.="[(";
+
+                               foreach my $wd (@lin)
+                               {
+                                       my $wwt=$wd->[1]||0;
+
+                                       while ($wwt <= $wt+.1)
+                                       {
+                                               $wwt-=$wt;
+                                               $wd->[0].=' ';
+                                       }
+
+                                       if (abs($wwt) < .1 or $wwt == 0)
+                                       {
+                                               $stream.="$wd->[0]" if 
defined($wd->[0]);
+                                       }
+                                       else
+                                       {
+                                               $stream.="$wd->[0]) $wwt (" if 
defined($wd->[0]);
+                                       }
+                               }
+                               $stream.=")] TJ\n";
+                       }
+               }
+       }
+
+       @lin=();
+       $xpos+=$pendmv/$unitwidth;
+       $pendmv=0;
+       $nomove=0;
+       $wt=-1;
+}
+
+sub  LoadAhead
+{
+       my $no=shift;
+
+       foreach my $j (1..$no)
+       {
+               my $lin=<>;
+               chomp($lin);
+               $lct++;
+               
+               push(@ahead,$lin);
+               $stream.="%% $lin\n" if $debug;
+       }
+}
+
+sub do_V
+{
+       my $par=shift;
+
+       if ($mode eq 't')
+       {
+               PutLine();
+       }
+       else
+       {
+               $xpos+=$pendmv/$unitwidth;
+               $pendmv=0;
+       }
+       
+       $ypos=$par/$unitwidth;
+       
+       LoadAhead(1);
+       
+       if (substr($ahead[0],0,1) eq 'H')
+       {
+               $xpos=substr($ahead[0],1)/$unitwidth;
+               
+               @ahead=();
+               
+       }
+
+       $nomove=$pendmv=0;
+       $poschg=1;
+}
+
+sub do_v
+{
+       my $par=shift;
+       
+       PutLine();
+       
+       $ypos+=$par/$unitwidth;
+               
+       $poschg=1;
+}
+
+sub TextWid
+{
+       my $txt=shift;
+       my $w=0;
+
+       foreach my $c (split('',$txt))
+       {
+               my $cn=ord($c);
+               $widtbl->[$cn]=$origwidtbl->[$cn]*$cftsz if 
!defined($widtbl->[$cn]);
+               $w+=$widtbl->[$cn];
+       }
+
+       return($w/$unitwidth);
+}
+
+sub do_t
+{
+       my $par=shift;
+       my $wid=TextWid($par);
+
+       $par=reverse(split('',$par)) if $xrev;
+       if ($n_flg and defined($mark))
+       {
+               $mark->{ypos}=$ypos;
+               $mark->{xpos}=$xpos;
+       }
+
+       $n_flg=0;
+       IsText();
+       
+       $xpos+=$wid;
+       $xpos+=($pendmv-$nomove)/$unitwidth;
+       
+       $stream.="% == '$par'=$wid 'xpos=$xpos\n" if $debug;
+       $par=~s/\\/\\\\/g;
+       $par=~s/\)/\\)/g;
+       $par=~s/\(/\\(/g;
+
+       # $pendmv = 'h' move since last 't'
+       # $nomove = width of char(s) added by 'C', 'N' or 'c'
+       # $w-flg  = 'w' seen since last t
+
+       if ($fontchg)
+       {
+               PutLine();
+               $whtsz=$fontlst{$cft}->{FNT}->{spacewidth}*$cftsz;
+               $stream.="/F$cft $cftsz Tf\n", $fontchg=0 if $fontchg && 
defined($cft);
+       }
+
+       $gotT=1;
+
+       $stream.="% --- wht=$whtsz, pend=$pendmv, nomv=$nomove\n" if $debug;
+       
+#      if ($w_flg && $#lin > -1)
+#      {
+#              $lin[$#lin]->[0].=' ';
+#              $pendmv-=$whtsz;
+#              $dontglue=1 if $pendmv==0;
+#      }
+
+       $wt=-$pendmv/$cftsz if $w_flg and $wt==-1;
+       $pendmv-=$nomove;
+       $nomove=0;
+       $w_flg=0;
+
+       if ($xrev)
+       {
+               PutLine(0) if $#lin > -1;
+               MakeMatrix(1);
+               $stream.="$matrix ".PutXY($xpos,$ypos)." Tm\n", $poschg=0;
+               $stream.="0 Tw ";
+               $stream.="($par) Tj\n";
+               MakeMatrix();
+               $stream.="$matrix ".PutXY($xpos,$ypos)." Tm\n", $poschg=0;
+               $matrixchg=0;
+               return;
+       }
+       
+       if ($pendmv)
+       {
+               if ($#lin == -1)
+               {
+                       push(@lin,[undef,-$pendmv/$cftsz]);
+               }
+               else
+               {
+                       $lin[$#lin]->[1]=-$pendmv/$cftsz;
+               }
+               
+               push(@lin,[$par,undef]);
+#              $xpos+=$pendmv/$unitwidth;
+               $pendmv=0
+       }
+       else
+       {
+               if ($#lin == -1)
+               {
+                       push(@lin,[$par,undef]);
+               }
+               else
+               {
+                       $lin[$#lin]->[0].=$par;
+               }
+       }
+}
+
+sub do_h
+{
+       $pendmv+=shift;
+}
+
+sub do_H
+{
+       my $par=shift;
+       
+       if ($mode eq 't')
+       {
+               PutLine();
+       }
+       else
+       {
+               $xpos+=$pendmv/$unitwidth;
+               $pendmv=0;
+       }
+
+       my $newx=$par/$unitwidth;
+       $stream.=sprintf("%.3f",$newx-$tmxpos)." 0 Td\n" if $mode eq 't';
+       $tmxpos=$xpos=$newx;
+       $pendmv=$nomove=0;
+}
+
+sub do_C
+{
+       my $par=shift;
+       my $nm;
+       
+       ($par,$nm)=FindChar($par);
+
+       do_t($par);
+       $nomove=$nm;
+}
+
+sub FindChar
+{
+       my $chnm=shift;
+
+       if (exists($fontlst{$cft}->{FNT}->{GNM}->{$chnm}))
+       {
+               my $ch=$fontlst{$cft}->{FNT}->{GNM}->{$chnm};
+               return(chr($ch),$fontlst{$cft}->{FNT}->{WID}->[$ch]*$cftsz);
+       }
+       else
+       {
+               return(' ');
+       }
+}
+
+sub do_c
+{
+       my $par=shift;
+
+       push(@ahead,substr($par,1));
+       $par=substr($par,0,1);
+       my $ch=ord($par);
+       do_t($ch);
+       $nomove=$fontlst{$cft}->{FNT}->{WID}->[$ch]*$cftsz;
+}
+
+sub do_N
+{
+       my $par=shift;
+
+       do_t(chr($par));
+       $nomove=$fontlst{$cft}->{FNT}->{WID}->[$par]*$cftsz;
+}
+
+sub do_n
+{
+       $gotT=0;
+       PutLine();
+       $pendmv=$nomove=0;
+       $n_flg=1;
+       @lin=();
+       PutHotSpot($xpos) if defined($mark);
+}

Index: tmac/pdf.tmac
===================================================================
RCS file: tmac/pdf.tmac
diff -N tmac/pdf.tmac
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tmac/pdf.tmac       26 Jul 2011 17:11:12 -0000      1.1
@@ -0,0 +1,738 @@
+.\" pdf.tmac
+.\"
+.mso ps.tmac
+.
+.de pdf:SS
+.      char \\$1 \\S'16'\\$1\\S'0'
+..
+.pdf:SS \[+h]
+.pdf:SS \[ts]
+.pdf:SS \[*a]
+.pdf:SS \[*b]
+.pdf:SS \[*x]
+.pdf:SS \[*d]
+.pdf:SS \[*e]
+.pdf:SS \[*f]
+.pdf:SS \[*g]
+.pdf:SS \[*y]
+.pdf:SS \[*i]
+.pdf:SS \[+f]
+.pdf:SS \[*k]
+.pdf:SS \[*l]
+.pdf:SS \[*m]
+.pdf:SS \[*n]
+.pdf:SS \[*o]
+.pdf:SS \[*p]
+.pdf:SS \[*h]
+.pdf:SS \[*r]
+.pdf:SS \[*s]
+.pdf:SS \[*t]
+.pdf:SS \[*u]
+.pdf:SS \[+p]
+.pdf:SS \[*w]
+.pdf:SS \[*c]
+.pdf:SS \[*q]
+.pdf:SS \[*z]
+.char \[lh] \X'pdf: xrev'\[rh]\X'pdf: xrev'
+.nr pdf:bm.nl 1
+.de pdfmark
+. nop \!x X ps:exec [\\$* pdfmark
+..
+.de pdf:warn
+. tm \\n(.F:\\n(.c: macro warning: \\$*
+..
+.de pdf:error
+. tm \\n(.F:\\n(.c: macro error: \\$*
+..
+.de pdfinfo
+.\" -------------------------------------------------------------------
+.\" Usage:
+.\"   .pdfinfo /FieldName field content ...
+.\" Examples:
+.\"   .pdfinfo /Title   A PDF Document
+.\"   .pdfinfo /Author  Keith Marshall
+.\" -------------------------------------------------------------------
+.\"
+.ds pdf:meta.field \\$1
+.shift
+.ie '\\n(.z'' .pdfmark \\*[pdf:meta.field] (\\$*) /DOCINFO
+.el \!.pdfmark \\*[pdf:meta.field] (\\$*) /DOCINFO
+.rm pdf:meta.field
+..
+.de pdfview
+.\" -------------------------------------------------------------------
+.\" Usage:
+.\"   .pdfview view parameters ...
+.\" Examples:
+.\"   .pdfview /PageMode /UseOutlines
+.\"   .pdfview /Page 2 /View [/FitH \n(.p u]
+.\" -------------------------------------------------------------------
+.\"
+.ie '\\n(.z'' .pdfmark \\$* /DOCVIEW
+.el \!.pdfmark \\$* /DOCVIEW
+..
+.\" =====================================================================
+.\" Module PDFNOTE: Insert "Sticky Note" Style Comments in a PDF Document
+.\" =====================================================================
+.\"
+.\" "PDFNOTE.WIDTH" and "PDFNOTE.HEIGHT" set the preferred size for
+.\" display of the "sticky note" pane, when opened.  Acrobat Reader
+.\" seems not to honour these -- perhaps GhostScript doesn't encode
+.\" them correctly!  Anyway, let's set some suitable default values,
+.\" in case the user has a set up which does work as advertised.
+.\"
+.nr PDFNOTE.WIDTH  3.5i
+.nr PDFNOTE.HEIGHT 2.0i
+.\"
+.\" "pdf:bbox" defines the expression used to set the size and location
+.\" of the bounding rectangle for display of notes and link "hot-spots".
+.\" This is defined, such that a note is placed at troff's current text
+.\" position on the current page, with its displayed image size defined
+.\" by the "PDFNOTE.WIDTH" and "PDFNOTE.HEIGHT" registers, while the
+.\" bounds for a link "hot-spot" are matched to the text region which
+.\" defines the "hot-spot".
+.\"
+.ds pdf:bbox \\n[pdf:llx] u \\n[pdf:lly] u \\n[pdf:urx] u \\n[pdf:ury] u
+.\"
+.\" Getting line breaks into the text of a PDFNOTE is tricky -- we need
+.\" to get a "\n" into the Postscript stream, but three levels of "\" are
+.\" swallowed, when we invoke "pdfnote".  The following definition of "PDFLB",
+.\" (for LineBreak), is rather ugly, but does allow us to use
+.\"
+.\"    .pdfnote  Some text.\*[PDFLB]Some more text, on a new line.
+.\"
+.ds PDFLB \\\\\\\\\\\\\\\\n
+.\"
+.de pdfnote
+.\" ----------------------------------------------------------------------
+.\" Usage:
+.\"   .pdfnote [-T "Text for Title"] Text of note ...
+.\" ----------------------------------------------------------------------
+.\"
+.\" First, compute the bounding rectangle,
+.\" for this PDFNOTE instance
+.\"
+.   mk pdf:ury
+.   nr pdf:llx \\n(.k+\\n(.o+\\n[.in]
+.   nr pdf:lly \\n[pdf:ury]-\\n[PDFNOTE.HEIGHT]
+.   nr pdf:urx \\n[pdf:llx]+\\n[PDFNOTE.WIDTH]
+.   ds pdf:note.instance /Rect [\\*[pdf:bbox]]
+.\"
+.\" Parse any specified (recognisable) PDFNOTE options
+.\"
+.   while dpdf:note\\$1 \{\
+.      pdf:note\\$1 \\$@
+.      shift \\n[pdf:note.argc]
+.      \}
+.\"
+.\" Emit the note, and clean up
+.\"
+.   pdfmark \\*[pdf:note.instance] /Subtype /Text /Contents (\\$*) /ANN
+.   rm pdf:note.instance
+.   rr pdf:note.argc
+..
+.de pdf:note-T
+.nr pdf:note.argc 2
+.as pdf:note.instance " /Title (\\$2)
+..
+.\" =====================================================================
+.\" Module PDFBOOKMARK: Add an Outline Reference in the PDF Bookmark Pane
+.\" =====================================================================
+.\"
+.\" "PDFBOOKMARK.VIEW" controls how the document will be displayed,
+.\" when the user selects a bookmark.  This default setting will fit
+.\" the page width to the viewing window, with the bookmarked entry
+.\" located at the top of the viewable area.
+.\"
+.ds PDFBOOKMARK.VIEW /FitH -\\n[PDFPAGE.Y] u
+.\"
+.\" "PDFOUTLINE.FOLDLEVEL" controls how the document outline will be
+.\" displayed.  It is a number, defining the maximum heading level
+.\" which will be visible, without outline expansion by the user, in
+.\" the initial view of the document outline.  Assuming that no sane
+.\" document will ever extend to 10,000 levels of nested headings,
+.\" this initial default value causes outlines to be fully expanded.
+.\"
+.nr PDFOUTLINE.FOLDLEVEL 10000
+.\"
+.\" The actual job of creating an outline reference
+.\" is performed by the "pdfbookmark" macro.
+.\"
+.de pdfbookmark
+.\" ------------------------------------------------------------------
+.\" Usage:
+.\"   .pdfbookmark [-T tag] level "Text of Outline Entry"
+.\"
+.\"   $1 = nesting level for bookmark (1 is top level)
+.\"   $2 = text for bookmark, (in PDF viewer bookmarks list)
+.\" ------------------------------------------------------------------
+.\"
+.ie '\\n(.z'' \{\
+.\"
+.\" When we are at the top diversion level, i.e. actually emitting text
+.\" to the output device stream, then we compute the location of, and
+.\" plant this bookmark immediately.
+.\"
+.   \" Make the bookmark name "untagged" by default,
+.   \" then parse any specified options, to set a "tag", if required
+.   \"
+.      ds pdf:href-T
+.      while dpdf:href.opt\\$1 \{\
+.         pdf:href.opt\\$1 \\$@
+.         shift \\n[pdf:href.argc]
+.         \}
+.      rr pdf:href.argc
+.   \"
+.   \" If we found "--" to mark the end of the options, discard it
+.   \"
+.      if '\\$1'--' .shift
+.   \"
+.      nr pdf:bm.lev 0+\\$1
+.      if \\n[pdf:bm.lev]==0 .nr pdf:bm.lev 1
+.      if \\n[pdf:bm.lev]>\\n[PDFOUTLINE.FOLDLEVEL] .nr pdf:bm.lev 
\\n[pdf:bm.lev]*-1
+.      nr pdf:bm.abslev 0+\\n[pdf:bm.lev]
+.      if \\n[pdf:bm.lev]<0 .nr pdf:bm.abslev 0+\\n[pdf:bm.abslev]*-1
+.      if \\n[pdf:bm.abslev]>\\n[pdf:bm.nl] .nr pdf:bm.nl \\n[pdf:bm.nl]+1
+.      ie \\n[pdf:bm.abslev]>\\n[pdf:bm.nl] \{\
+.        pdf:warn adjusted level \\n[pdf:bm.abslev] bookmark; should be <= 
\\n[pdf:bm.nl]
+.        nr pdf:bm.abslev 0+\\n[pdf:bm.nl]
+.      \}
+.      el .nr pdf:bm.nl \\n[pdf:bm.abslev]
+.      if \\n[pdf:bm.lev]<0 .nr pdf:bm.abslev \\n[pdf:bm.abslev]*-1
+.      nr pdf:bm.lev 0+\\n[pdf:bm.abslev]
+.      rr pdf:bm.abslev
+.      shift
+.   \"
+.   \" Increment the bookmark serialisation index
+.   \" in order to generate a uniquely serialised bookmark name,
+.   \" ( which we return in the string "PDFBOOKMARK.NAME" ),
+.   \"
+.      nr pdf:bm.nr +1
+.      ie '\\*[pdf:href-T]'' .ds PDFBOOKMARK.NAME pdf:bm\\n[pdf:bm.nr]
+.      el .ds PDFBOOKMARK.NAME \\*[pdf:href-T]
+.      pdf:href.sety
+.         ds pdf:cleaned \\$*
+.         ev pdfcln
+.         nf
+.         box pdf:clean
+.         nop \\$*
+.         sp -1
+.         box
+.         asciify pdf:clean
+.         ds pdf:cleaned \\*[pdf:clean]
+.         ev
+.      ds pdf:look(\\*[PDFBOOKMARK.NAME]) \\*[pdf:cleaned]
+.      if dPDF.EXPORT .tm .ds pdf:look(\\*[PDFBOOKMARK.NAME]) \\*[pdf:cleaned]
+.      pdfmark /Dest /\\*[PDFBOOKMARK.NAME] /View [\\*[PDFBOOKMARK.VIEW]] /DEST
+.      pdfmark /Dest /\\*[PDFBOOKMARK.NAME] /Title (\\*[pdf:cleaned]) /Level 
\\n[pdf:bm.lev] /OUT
+.      pdf:href.options.clear
+.      rr PDFPAGE.Y
+.      rm pdf:cleaned
+.      rm pdf:clean
+.      \}
+.   \}
+.el \{\
+.\"
+.\" But when we are collecting a diversion which will be written out later,
+.\" then we must defer bookmark placement, until we emit the diversion.
+.\" (don't rely on $0 == pdfbookmark here; it may be a volatile alias).
+.\"
+.   nop \!.pdfbookmark \\$@
+.   \}
+..
+.\"
+.\" =============================================================
+.\" Module PDFHREF: Create Hypertext References in a PDF Document
+.\" =============================================================
+.\"
+.\" "PDFHREF.VIEW" controls how the document will be displayed,
+.\" when the user follows a link to a named reference.
+.\"
+.ds PDFHREF.VIEW     /FitH -\\n[PDFPAGE.Y] u
+.\"
+.\" This default setting will fit the page width to the viewing
+.\" window, with the bookmarked entry located close to the top
+.\" of the viewable area.  "PDFHREF.VIEW.LEADING" controls the
+.\" actual distance below the top of the viewing window, where
+.\" the reference will be positioned; 5 points is a reasonable
+.\" default offset.
+.\"
+.nr PDFHREF.VIEW.LEADING  5.0p
+.\"
+.\" Yuk!!!
+.\" PDF view co-ordinates are mapped from the bottom left corner,
+.\" of the page, whereas page printing co-ordinates are mapped
+.\" conventionally, from top left.
+.\"
+.\" Macro "pdf:href.sety" transforms the vertical position of the
+.\" last printed baseline, from the printing co-ordinate domain to
+.\" the PDF view domain.
+.\"
+.de pdf:href.sety
+.\" ----------------------------------------------------------------
+.\" Usage:
+.\"   .pdf:href.sety
+.\" ----------------------------------------------------------------
+.\"
+.\" This computation yields the vertical view co-ordinate
+.\" in groff's basic units; don't forget to append grops' "u"
+.\" conversion operator, when writing the pdfmark!
+.\"
+.nr PDFPAGE.Y \\n(nl+\\n[PDFHREF.VIEW.LEADING]
+..
+.\" When we create a link "hot-spot" ...
+.\" "PDFHREF.LEADING" sets the distance above the top of the glyph
+.\" bounding boxes, in each line of link text, over which the link
+.\" hot-spot will extend, while "PDFHREF.HEIGHT" sets the hot-spot
+.\" height, PER LINE of text occupied by the reference.
+.\"
+.\" Since most fonts specify some leading space within the bounding
+.\" boxes of their glyphs, a better appearance may be achieved when
+.\" NEGATIVE leading is specified for link hot-spots;  indeed, when
+.\" the default 10pt Times font is used, -1.0 point seems to be a
+.\" reasonable default value for "PDFHREF.LEADING" -- it may be
+.\" changed, if desired.
+.\"
+.\" "PDFHREF.HEIGHT" is initially set as one vertical spacing unit;
+.\" note that it is defined as a string, so it will adapt to changes
+.\" in the vertical spacing.  Changing it is NOT RECOMMENDED.
+.\"
+.nr PDFHREF.LEADING -1.0p
+.ds PDFHREF.HEIGHT   1.0v
+.\"
+.\" PDF readers generally place a rectangular border around link
+.\" "hot-spots".  Within text, this looks rather ugly, so we set
+.\" "PDFHREF.BORDER" to suppress it -- the three zeroes represent
+.\" the border parameters in the "/Border [0 0 0]" PDFMARK string,
+.\" and may be changed to any valid form, as defined in Adobe's
+.\" PDFMARK Reference Manual.
+.\"
+.ds PDFHREF.BORDER   0 0 0
+.\"
+.\" "PDFHREF.COLOUR" (note British spelling) defines the colour to
+.\" be used for display of link "hot-spots".  This will apply both
+.\" to borders, if used, and, by default to text; however, actual
+.\" text colour is set by "PDFHREF.TEXT.COLOUR", which may be reset
+.\" independently of "PDFHREF.COLOUR", to achieve contrasting text
+.\" and border colours.
+.\"
+.\" "PDFHREF.COLOUR" must be set to a sequence of three values,
+.\" each in the range 0.0 .. 1.0, representing the red, green, and
+.\" blue components of the colour specification in the RGB colour
+.\" domain, which is shared by "groff" and the PDF readers.
+.\"
+.ds PDFHREF.COLOUR   0.35 0.00 0.60
+.defcolor pdf:href.colour rgb \*[PDFHREF.COLOUR]
+.\"
+.\" "PDFHREF.TEXT.COLOUR", on the other hand, is simply defined
+.\" using any "groff" colour name -- this default maps it to the
+.\" same colour value as "PDFHREF.COLOUR".
+.\"
+.ds PDFHREF.TEXT.COLOUR  pdf:href.colour
+.\"
+.\" Accommodate users who prefer the American spelling, COLOR, to
+.\" the British spelling, COLOUR.
+.\"
+.als PDFHREF.COLOR       PDFHREF.COLOUR
+.als PDFHREF.TEXT.COLOR  PDFHREF.TEXT.COLOUR
+.\"
+.\" All PDF "Hypertext" reference capabilities are accessed
+.\" through the "pdfhref" macro
+.\"
+.de pdfhref
+.\" -----------------------------------------------------------------
+.\" Usage:
+.\"   .pdfhref <subcommand [options ...] [parameters ...]> ...
+.\" -----------------------------------------------------------------
+.\"
+.\"
+.\" Loop over all subcommands specified in the argument list
+.\"
+.   while \\n(.$ \{\
+.   \"
+.   \" Initially, assume each subcommand will complete successfully
+.   \"
+.      nr pdf:href.ok 1
+.   \"
+.   \" Initialise -E and -X flags in the OFF state
+.   \"
+.      nr pdf:href-E 0
+.      nr pdf:href-X 0
+.   \"
+.   \" Handle the case where subcommand is specified as "-class",
+.   \" setting up appropriate macro aliases for subcommand handlers.
+.   \"
+.      if dpdf*href\\$1       .als pdf*href      pdf*href\\$1
+.      if dpdf*href\\$1.link  .als pdf*href.link pdf*href\\$1.link
+.      if dpdf*href\\$1.file  .als pdf*href.file pdf*href\\$1.file
+.   \"
+.   \" Repeat macro alias setup
+.   \" for the case where the subcommand is specified as "class",
+.   \" (without a leading hyphen)
+.   \"
+.      if dpdf*href-\\$1      .als pdf*href      pdf*href-\\$1
+.      if dpdf*href-\\$1.link .als pdf*href.link pdf*href-\\$1.link
+.      if dpdf*href-\\$1.file .als pdf*href.file pdf*href-\\$1.file
+.   \"
+.   \" Process one subcommand ...
+.   \"
+.      ds pdf*href.class \\$1
+.      ie dpdf*href \{\
+.      \"
+.      \" Subcommand "class" is recognised ...
+.      \" discard the "class" code from the argument list,
+.      \" set the initial argument count to swallow all arguments,
+.      \" and invoke the selected subcommand handler.
+.      \"
+.         shift
+.         nr pdf:argc \\n(.$
+.         pdf*href \\$@
+.      \"
+.      \" When done,
+.      \" discard all arguments actually consumed by the handler,
+.      \" before proceeding to the next subcommand (if any).
+.      \"
+.         shift \\n[pdf:argc]
+.      \}
+.      el \{\
+.      \"
+.      \" Subcommand "class" is not recognised ...
+.      \" issue a warning, and discard the entire argument list,
+.      \" so aborting this "pdfhref" invocation
+.      \"
+.         pdf:warn \\$0: undefined reference class '\\$1' ignored
+.         shift \\n(.$
+.         \}
+.   \"
+.   \" Clean up temporary reference data,
+.   \" to ensure it doesn't propagate to any future reference
+.   \"
+.      rm pdf*href pdf:href.link pdf:href.files
+.      rr pdf:href-E
+.      pdf:href.options.clear
+.      \}
+.   rr pdf:href.ok
+..
+.\"
+.\" Macros "pdf:href.flag" and "pdf:href.option"
+.\" provide a generic mechanism for switching on flag type options,
+.\" and for decoding options with arguments, respectively
+.\"
+.de pdf:href.flag
+.\" ----------------------------------------------------------------------
+.\" ----------------------------------------------------------------------
+.nr pdf:href\\$1 1
+.nr pdf:href.argc 1
+..
+.de pdf:href.option
+.\" ----------------------------------------------------------------------
+.\" ----------------------------------------------------------------------
+.ds pdf:href\\$1 \\$2
+.nr pdf:href.argc 2
+..
+.\"
+.\" Valid PDFHREF options are simply declared
+.\" by aliasing option handlers to "pdf:href.option",
+.\" or to "pdf:href.flag", as appropriate
+.\"
+.als pdf:href.opt-A pdf:href.option   \" affixed text
+.als pdf:href.opt-D pdf:href.option   \" destination name
+.als pdf:href.opt-E pdf:href.flag     \" echo link descriptor
+.als pdf:href.opt-F pdf:href.option   \" remote file specifier
+.als pdf:href.opt-N pdf:href.option   \" reference name
+.als pdf:href.opt-P pdf:href.option   \" prefixed text
+.als pdf:href.opt-T pdf:href.option   \" bookmark "tag"
+.\"
+.\" For references to another document file
+.\" we also need to support OS dependent file name specifiers
+.\"
+.als pdf:href.opt-DF pdf:href.option  \" /DOSFile specifier
+.als pdf:href.opt-MF pdf:href.option  \" /MacFile specifier
+.als pdf:href.opt-UF pdf:href.option  \" /UnixFile specifier
+.als pdf:href.opt-WF pdf:href.option  \" /WinFile specifier
+.\"
+.\" Macro "pdf:href.options.clear" ensures that ALL option
+.\" argument strings are deleted, after "pdfhref" has completed
+.\" all processing which depends on them
+.\"
+.de pdf:href.options.clear
+.\" -----------------------------------------------------------------
+.\" Usage:
+.\"   .pdf:href.options.clear [option ...]
+.\" -----------------------------------------------------------------
+.\"
+.\" When an option list is specified ...
+.\"
+.ie \\n(.$ \{\
+.   \"
+.   \" then loop through the list,
+.   \" deleting each specified option argument string in turn
+.   \"
+.   while \\n(.$ \{\
+.      if dpdf:href-\\$1 .rm pdf:href-\\$1
+.      shift
+.      \}
+.   \}
+.\"
+.\" ... but when no list is specified,
+.\" then recurse, to clear all known option argument strings
+.\"
+.el .pdf:href.options.clear A D F N P T DF MF UF WF
+..
+.\"
+.\" Macro "pdf*href-M" is the handler invoked by "pdfhref", when
+.\" called with the "M" reference class specifier, to create a
+.\" named cross reference mark, and to emit a cross reference
+.\" data record, as specified by "PDFHREF.INFO".
+.\"
+.de pdf*href-M
+.\" -----------------------------------------------------------------
+.\" Usage:
+.\"   .pdfhref M [-N name | -D name] [-E] descriptive text ...
+.\" -----------------------------------------------------------------
+.\"
+.\" Initially, declare the -D and -N string options as empty,
+.\" so we avoid warning messages when we try to use them, and find
+.\" that they are undefined.
+.\"
+.ds pdf:href-D
+.ds pdf:href-N
+.\"
+.\" Parse, interpret, and strip any specified options from the
+.\" argument list.  (Note that only options with a declared handler
+.\" will be processed; there is no provision for detecting invalid
+.\" options -- anything which is not recognised is assumed to start
+.\" the "descriptive text" component of the argument list).
+.\"
+.while dpdf:href.opt\\$1 \{\
+.   pdf:href.opt\\$1 \\$@
+.   shift \\n[pdf:href.argc]
+.   \}
+.\"
+.\" If we found "--", to mark the end of the options,
+.\" then we should discard it.
+.\"
+.if '\\$1'--' .shift
+.\"
+.\" All PDF reference markers MUST be named. The name may have been
+.\" supplied using the "-N Name" option, (or the "-D Name" option);
+.\" if not, deduce it from the first "word" in the "descriptive text",
+.\" if any, and set the marker -- if we still can't identify the name
+.\" for the destination, then this marker will not be created.
+.\"
+.pdf*href.set \\*[pdf:href-N] \\*[pdf:href-D] \\$1
+.\"
+.\"
+.\" Irrespective of whether this marker is created, or not,
+.\" the descriptive text will be copied to the groff output stream,
+.\" provided the "-E" option was specified
+.\"
+.if \\n[pdf:href-E] \&\\$*
+..
+.de pdf*href-F
+.\"do nothing
+..
+.\"
+.de pdf*href.set
+.\" ----------------------------------------------------------------------
+.\" ----------------------------------------------------------------------
+.ie \\n(.$ \{\
+.   \"
+.   \" a marker name has been supplied ...
+.   \" if we are formatting for immediate output,
+.   \" emit PDFMARK code to establish the associated view
+.   \"
+.   ie '\\n(.z'' \{\
+.      pdf:href.sety
+.      pdfmark /Dest /\\$1 /View [\\*[PDFHREF.VIEW]] /DEST
+.      ds PDFHREF.NAME \\$1
+.      rr PDFPAGE.Y
+.      \}
+.   \"
+.   \" but, when formatting a diversion ...
+.   \" delay output of the PDFMARK code, until the diversion
+.   \" is eventually written out
+.   \"
+.   el \!.\\$0 \\$@
+.   \"
+.   \}
+.el \{\
+.   \" marker is unnamed ...
+.   \" issue error message; do not emit reference data
+.   \"
+.   pdf:warn pdfhref destination marker must be named
+.   \}
+..
+.\"
+.de pdf*href
+.\" ------------------------------------------------------------------
+.\" Usage:
+.\"   .pdf*href class [options ...] [link text ...]
+.\" ------------------------------------------------------------------
+.\"
+.\" First, we initialise an empty string, which will be affixed to
+.\" the end of the "link text".  (This is needed to cancel the effect
+.\" of a "\c" escape, which is placed at the end of the "link text"
+.\" to support the "-A" option -- any text supplied by the user, when
+.\" the "-A" option is specified, will replace this empty string).
+.\"
+.ds pdf:href-A
+.\"
+.\" Now we interpret, and remove any specified options from the
+.\" argument list.  (Note that only options with a declared handler
+.\" will be processed;  there is no provision for detecting invalid
+.\" options -- anything which is not recognised is assumed to start
+.\" the "link text" component of the argument list).
+.\"
+.while dpdf:href.opt\\$1 \{\
+.   pdf:href.opt\\$1 \\$@
+.   shift \\n[pdf:href.argc]
+.   \}
+.\"
+.\" If we found "--", to mark the end of the options, then we should
+.\" discard it.
+.\"
+.if '\\$1'--' .shift
+.\"
+.\" All PDF link classes REQUIRE a named destination.  This may have
+.\" been supplied using the "-D Name" option, but, if not, deduce it
+.\" from the first "word" in the "link text", if any -- if we still
+.\" can't identify the destination, then set "pdf:href.ok" to zero,
+.\" so this link will not be created.
+.\"
+.if !dpdf:href-D .pdf:href.option -D \\$1
+.if '\\*[pdf:href-D]'' \{\
+.   pdf:error pdfhref has no destination
+.   nr pdf:href.ok 0
+.   \}
+.\"
+.\" Now, initialise a string, defining the PDFMARK code sequence
+.\" to create the reference, using the appropriate type indicators.
+.\"
+.ds pdf:href.link /Subtype /Link \\*[pdf*href.link]
+.\"
+.\" And now, we have no further use for "pdf*href.link".
+.\"
+.rm pdf*href.link
+.\"
+.\" If the user specified any "link prefix" text, (using the "-P text"
+.\" option), then emit it BEFORE processing the "link text" itself.
+.\"
+.if dpdf:href-P \&\\*[pdf:href-P]\c
+.ie \\n[pdf:href.ok] \{\
+.   \"
+.   \" This link is VALID (so far as we can determine) ...
+.   \" Modify the "link text" argument specification, as required,
+.   \" to include any pre-formatted cross reference information
+.   \"
+.   ie \\n(.$ \{\
+.      \"
+.      \" One or more "link text" argument(s) are present,
+.      \" so, set the link description from the argument(s) ...
+.      \"
+.      ds PDFHREF.DESC \\\\$*
+.      \}
+.   el \{\
+.      ie dpdf:look(\\*[pdf:href-D]) .ds PDFHREF.DESC 
\\*[pdf:look(\\*[pdf:href-D])]
+.      el .ds PDFHREF.DESC Unknown
+.      \}
+.   \" Apply border and colour specifications to the PDFMARK string
+.   \" definition, as required.
+.   \"
+.   if dPDFHREF.BORDER .as pdf:href.link " /Border [\\*[PDFHREF.BORDER]]
+.   if dPDFHREF.COLOUR .as pdf:href.link " /Color  [\\*[PDFHREF.COLOUR]]
+.   \"
+.   \" Emit the "link text", in its appropriate colour, marking the
+.   \" limits of its bounding box(es), as the before and after output
+.   \" text positions.
+.   \"
+.   if dPDFHREF.COLOUR .defcolor pdf:href.colour rgb \\*[PDFHREF.COLOUR]
+.   nr pdf:bm.width \\w'\\*[PDFHREF.DESC]'
+.   nop \&\m[\\*[PDFHREF.TEXT.COLOUR]]\X'pdf: markstart \\n[rst] \\n[rsb]  
\\*[pdf:href.link]'\\*[PDFHREF.DESC]\X'pdf: markend'\m[]\c
+.   \"
+.   \" Clean up the temporary registers and strings, used to
+.   \" compute the "hot-spot" bounds, and format the reference,
+.   \"
+.   rm PDFHREF.DESC PDFHREF.TEXT
+.   \}
+.\"
+.\" But when we identify an INVALID link ...
+.\" We simply emit the "link text", with no colour change, no border,
+.\" and no associated "hot-spot".
+.\"
+.el \&\\$*\c
+.\"
+.\" And then, if the user specified any affixed text, (using the
+.\" "-A text" option), we tack it on at the end.
+.\"
+.nop \&\\*[pdf:href-A]
+..
+.\" Macro "pdf*href-I" is used for one time initialisation of special
+.\" "pdfhref" features; (currently, only the above page trap hook is
+.\" supported, but it is implemented with one level of indirection, to
+.\" accommodate possible future expansion).
+.
+.de pdf*href-I
+.\" ----------------------------------------------------------------------
+.\" Usage:
+.\"   .pdfhref I -<option> <optarg> [-<option> <optarg>] ...
+.\" ----------------------------------------------------------------------
+.\"
+.\" Loop over all arguments, in pairs ...
+.
+.while \\n(.$ \{\
+.   \"
+.   \" handing them off to their respective initialisers,
+.   \" when suitable initialisers exist, or complaining otherwise.
+.   \"
+.   ie dpdf*href\\$1.init .pdf*href\\$1.init \\$2
+.   el .pdf*error pdfhref:init: unknown feature '\\$1'
+.   shift 2
+.   \}
+..
+.\" Before we can use the page break "hook", we need to initialise it
+.\" as an addendum to a regular page break trap. To ensure that we don't
+.\" compromise the user's page trap setup, we leave the onus for this
+.\" initialisation with the user, but we provide the "pdf*href-PT.init"
+.\" macro, (invoked by ".pdfhref I -PT <macro-name>"), to implement a
+.\" suitable initialisation action.
+.\"
+.\"
+.\" "pdf*href-L" is the generic handler for creating references to
+.\" named destinations in PDF documents.  It supports both local
+.\" references, to locations within the same document, through its
+.\" "pdf*href-L.link" attribute, and also references to locations
+.\" in any other PDF document, through "pdf*href-L.file".
+.\"
+.als pdf*href-L      pdf*href
+.ds  pdf*href-L.link /Dest /\\\\*[pdf:href-D]
+.ds  pdf*href-L.file /Action /GoToR \\\\*[pdf:href.files] \\*[pdf*href-L.link]
+.\"
+.\" "pdf*href-O" is the "official" handler for creating PDF
+.\" document outlines.  It is simply an alias to "pdfbookmark",
+.\" which may also be invoked directly, if preferred.  Neither
+.\" a "pdf*href-O.link" nor a "pdf*href-O.file" attribute is
+.\" required.
+.\"
+.als pdf*href-O      pdfbookmark
+.\"
+.\" "pdf*href-W" is the generic handler for creating references to
+.\" web resources, (or any resource specified by a uniform resource
+.\" identifier).  Such resource links are fully specified by the
+.\" "pdf*href-W.link" attribute.
+.\"
+.als pdf*href-W      pdf*href
+.ds  pdf*href-W.link /Action << /Subtype /URI /URI (\\\\*[pdf:href-D]) >>
+.nr pdf:bm.nl 0
+.\"
+.\" "pdfmarksuspend" and "pdfmarkrestart" should be used in any page trap
+.\" macros to prevent output from the page trap macro being considered part
+.\" of a 'hot spot' when it crosses a page boundary.
+.de pdfmarksuspend
+.nop \!x X pdf: marksuspend
+..
+.de pdfmarkrestart
+.nop \!x X pdf: markrestart
+..
+.\"
+.\" pdf.tmac: end of file / vim: ft=groff



reply via email to

[Prev in Thread] Current Thread [Next in Thread]