[comp.lang.postscript] Interrogating PS printers to find loaded fonts

paul@frcs.UUCP (Paul Nash) (08/20/90)

I have a problem, for which I would like to ask advice.  I am in the
process of developing an intelligent printer spooler, which takes
various inputs and translates them to PostScript output, which is
then fed to a PostScript device.  The device can be high or low
resolution, and can have any number of resident fonts.  I need to be
able to download fonts under control of the spooler, if such fonts
are needed in the print job and are not resident.  Obviously, a
downloaded font will remain in the printer's memory until that memory
is needed for, say, another font.

Is there any way in which I can interrogate the printer (via a serial
port) to find out either which fonts are available or whether a
specific font is available?  I do not want to download the font afresh
every time the print job calls for it!

Alternatively, is there any way to determine how long a font will
remain in RAM in the printer?  If I know how much RAM a printer has,
can I tell how many fonts can be downloaded before it starts to throw
out unused fonts?  Is the algorithm used know (LRU, oldest first,
whatever)?

My newsfeed is a tad erratic, so I would appreciate it if anyone who
has any answers (even RTFM, if they will just give a page number, or
title & author) could e-mail me.  I will summarise (once I have
something that works :-).  I _do_ read this group, though, so if you
would rather post I _should_ get it.

Thanks in advance,
	Paul
	
	-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
Paul Nash		paul@frcs.UUCP		ddsw1!proxima!frcs!paul

phillips@tegra.COM (Steve Phillips) (08/22/90)

In article <53@frcs.UUCP> paul@frcs.UUCP (Paul Nash) writes:
>I have a problem, for which I would like to ask advice.  I am in the
>process of developing an intelligent printer spooler, which takes
>various inputs and translates them to PostScript output, which is
>then fed to a PostScript device.  The device can be high or low
>resolution, and can have any number of resident fonts.  I need to be
>able to download fonts under control of the spooler, if such fonts
>are needed in the print job and are not resident.  Obviously, a
>downloaded font will remain in the printer's memory until that memory
>is needed for, say, another font.

That's not so obvious.  PostScript doesn't have any automatic
method for removing unused fonts - they just work with the
save/restore mechanism like everything else in PostScript.
In other words, if you download a font with your job without
doing an exitserver, the font will disappear at the end of the
job.  This is because in normal "server mode" operation the
printer does a save before each job and a restore afterwards.
If you exit server mode before downloading the font (say
"serverdict begin 0 exitserver") the font will stay loaded
until the printer is turned off or reset.

By the way, if you download the font in exitserver mode, make
sure you reenter server mode before sending down the actual job
to be printed.  If you're running over a serial port, just send
a control-D (ASCII 4) to do this.  Otherwise the job might mess
things up so that future jobs don't run correctly.

>Is there any way in which I can interrogate the printer (via a serial
>port) to find out either which fonts are available or whether a
>specific font is available?  I do not want to download the font afresh
>every time the print job calls for it!

Try the following piece of code:

    % Get list of memory-resident fonts.
    FontDirectory { pop == } forall

    % Search for disk-based fonts.  First, make sure the
    % printer supports the filenameforall operator.
    systemdict /filenameforall known {
        % List all disk-resident fonts.
        (fonts/*) { 
            % String is of the form (fonts/fontname).
            % Strip off "fonts/" prefix.
            dup length 6 sub 6 exch getinterval % Strip 1st 6 characters.
            ==  % Print it out.
        } 100 string filenameforall
    } if

-- 
============================================================================
Steve Phillips                                         Tegra-Varityper, Inc.
tegra!phillips@uunet.com                               Billerica, MA
============================================================================

orthlieb@adobe.COM (Carl Orthlieb) (08/23/90)

In article <53@frcs.UUCP> paul@frcs.UUCP (Paul Nash) writes:
>I have a problem, for which I would like to ask advice.  I am in the
>process of developing an intelligent printer spooler, which takes
>various inputs and translates them to PostScript output, which is
>then fed to a PostScript device.  The device can be high or low
>resolution, and can have any number of resident fonts.  I need to be
>able to download fonts under control of the spooler, if such fonts
>are needed in the print job and are not resident.  Obviously, a
>downloaded font will remain in the printer's memory until that memory
>is needed for, say, another font.

I think you have a slight misconception here as to how a font works.  It is 
true that the font cache (which caches rasterized characters) does have 
a scheme to remove bitmap characters on an LRU-like basis.  These characters,
however, are not the font itself, the font is defined in VM like any other
composite object.

A font outline that is downloaded into VM (outside of the server loop using
the exitserver command) stays there until the printer is powered off, or 
on Level 2 printers, until it is removed via undefinefont. 

Fonts that are downloaded as part of a document obey the normal save-restore 
rules. The server loop puts a save-restore around any job that comes in, 
so the maximum length of time that the font can remain in VM is for the 
length of the job.

>Is there any way in which I can interrogate the printer (via a serial
>port) to find out either which fonts are available or whether a
>specific font is available?  I do not want to download the font afresh
>every time the print job calls for it!

You will have to check the printer each time for the fonts in question
(the printer may have been powered off or reset). The proper way to do
this is through the PPD (PostScript Printer Description) file mechanism.

These are files that contain fragments of PostScript code (for each type
of printer) that can perform printer specific tasks. Querying which fonts
are on a printer may vary from printer to printer depending on the
hardware available (VM, hard disks, etc.). A complete description of the
PPD file mechanism is available from our server (it's in the Documents
directory and called PPDformat.ps). Also available are PPD files for 
most of the PostScript printers in existence; these can be found in the 
PPDFiles directory.

Here is the fragment of code found under the *?FontQuery: key in the 
LaserWriter NTX PPD file; it queries for specific fonts on the printer. 
Simply leave the font names on the stack and execute this code:

save  4 dict begin /sv exch def
/str (fonts/                              ) def
/st2 128 string def
{
  count 0 gt {
    dup st2 cvs (/) print print (:) print
    dup FontDirectory exch known {pop (Yes)}{
     str exch st2 cvs dup length /len exch def
     6 exch putinterval str 0 len 6 add getinterval mark exch
     { } st2 filenameforall counttomark 0 gt {
      cleartomark (Yes)}{cleartomark (No)}ifelse
    }ifelse = flush
  }{ exit } ifelse
} bind loop 
(*) = flush
sv end restore

The next chunk of code actually produces a list of all fonts available
on the printer.  Warning: this can be extremely time consuming on
printers that have a hard disk.  One of our printers here has a Font 
Folio disk attached to it and takes 5 minutes to execute this query.
This query is found under the *?FontList key in the PPD file:

save  2 dict begin /sv exch def
/str 128 string def
FontDirectory { pop == } bind forall flush 
/filenameforall where { 
 pop save (fonts/*) { 
  dup length 6 sub 6 exch getinterval cvn ==  
 } bind str filenameforall flush restore
} if 
(*) = flush
sv end restore

What you really want to do is write a PPD parser and query each printer
properly, based on the code found in the PPD file for that printer.  There
are lots of other neat things that you can do with a PPD parser, like 
printer rerouting.

Printer specific features, like papertrays, pagesizes, duplex, etc. are
activated differently depending on the printer.  Documents that use these
features are bound to a particular printer, they can not be rerouted (the
job may not execute on a different printer). If the document composer was
smart enough to encapsulate the feature in %%Begin(End)Feature: comments
then your spooler could take advantage of this.

For example,
	Destination printer: IBM Laser Printer, document composer writes:
		%%BeginFeature: *setpapertray legal
		statusdict begin legaltray end
		%%EndFeature

	If the job was rerouted, your spooler could examine the
	document, and use the PPD file to replace the code in
	between the two comments.

	New target printer: IBM Personal Page Printer, spooler produces:
		%%BeginFeature: *setpapertray legal
		legal
		%%EndFeature

This is just a small example of what your spooler could be doing.  Check out
the new red book when it's available.  Appendix G contains a revised version
of the Document Structuring Conventions (the %% comments), and talks about
document manager (spooler) services like range printing, page reversal,
font and resource optimization, parallel printing, page breakout, etc.

In the mean time, you might want to check out another document on the
server that talks about font downloading called supportingfonts.ps in
the Documents directory.

Carl 8-)