|
|
|
Private Message to Jeff: The pointed barbs of ignorance you aim at me are blunted by my shield of knowledge. Besides, while I was vactioning at a luxury, seaside resort with one of the founders of our company, you were exploring the barren wastelands of Oregon and Washington, obviously preferring the company of the spotted owl to that of our revered founder, a fact that I brought to his attention and that he promised to remember when the next round of executive promotions comes up. Should one of our vice presidents retire anytime soon, I fully expect to kiss the XSAR project goodbye!
I have verified that we can implement the static X/Y plot hardcopy generator
as described in the CDR: using code borrowed from the UNIX print-screen
utilities, xwd and xpr, retrieve the X/Y plot's bit-map image
from the X server, convert the image to PostScript, and print it. To test
this approach, I implemented a PRINT
button, a capability now
needed for XSAR.
On UNIX systems, a screen dump is usually created by the xwd(1) program. xwd allows the user to select a window or region on the screen that is to be dumped. It then retrieves the bit-map image of the window or region from the X server and writes it out to a file. xpr(1) is used to print a screen dump. xpr reads the xwd-generated screen dump, converts the image to PostScript, and writes the resulting output to a file, which can then be spooled to a printer.
The source code and an executable for the VMS version of xwd were
already available in the DECWindows examples directory. I obtained the
xpr source code from the MIT X11R4 distribution and ported it to
the VAX (a non-trivial task, thanks to the use of undocumented Xlib
routines not available under VMS). Once I had xwd and
xpr working, I cut and pasted the source code for these programs
to produce two subroutine packages, xwd_util.c
and
xpr_util.c
, that together perform the screen dump function.
For performance reasons, I eliminated the intermediate dump file; the
memory-resident image data gathered by the xwd routines is passed
directly to the xpr routines.
PRINT
Button
Using the new xwd and xpr routines, I added a
print screen
command to my Tcl-based WIMP program:
wmp_print [name] [-output file] [-root] [-xpr options]
This command generates a PostScript screen dump of an arbitrary widget
(specified by its name) or of the entire screen. The xpr options
allow you to control gray-scale representation, size scaling, and other
attributes of the screen dump. For example, the Print 2x2
button on the Min-Max form:
is defined as follows in WIMP:
wmp_button Print_2 -label "Print 2x2" -parent control_row -command {wmp_print minmax_form -output minmax_2 -xpr "-gray 2 -scale 1"}
The WIMP command assigned to the button prints the minmax_form
widget, which is the top-level, row-column widget of the form. The PostScript
dump of the form's image is written to a file, minmax_2.ps
. The
first xpr option, "-gray 2
", specifies 2x2 dithering to
represent 5 levels of gray; the default is to generate a black-and-white image.
A screen dump with 3x3 dithering is also attached. The other xpr option,
"-scale 1
", specifies a one pixel-to-one pixel rendering of the
form; by default, the screen image is enlarged or reduced to fill the entire
page.
The code fragment in wmp_print
that does the printing is
fairly simple:
char *output_file ; /* Output file name. */ char *xpr_options ; /* UNIX-like XPR options. */ void *xwd_image ; /* XWD-generated image. */ Widget top_level ; /* Application shell. */ Widget w ; /* Widget to dump. */ Window window_to_dump ; ... if (w == NULL) /* Entire screen? */ window_to_dump = DefaultRootWindow (XtDisplay (top_level)) ; else /* Partial screen. */ window_to_dump = XtWindow (w) ; /* Get screen image. */ xwd_get_window (top_level, window_to_dump, &xwd_image) ; /* Convert to PostScript. */ xpr_print_window (top_level, xwd_image, output_file, xpr_options) ;
The following times were measured for the generation of the attached screen dumps:
2x2 image: ~15 seconds 3x3 image: ~30 seconds
Screen capture takes less than a second; the remainder of the time is spend
converting the image to PostScript and outputting it to a file. The code
that writes the hex dump of the image to the PostScript file looks inefficient,
so some speed tuning in this department may be possible. The gray-scale
dithering obviously affects the timing. Size scaling, on the other hand,
doesn't affect the timing of the dump or the size of the output file; the
scaling of the image is performed by the PostScript printer. xpr
has a "-compact
" option that uses run-length encoding for white
pixels to produce smaller PostScript files (50% or more in the case of the
Min-Max form), but these compressed files take longer to print.
Two alternatives for more quickly generating screen dumps come to mind. First, rather than going directly to PostScript, a program like Dynamic Display could save the raw image data in an xwd intermediate file and spawn a separate xpr process to convert the image to PostScript. Unfortunately, generating the xwd file is itself rather slow, although speed tuning (e.g., pre-sizing the output file) might help.
A second alternative would be to write a print server. When a
PRINT
button is pushed, the display program would capture the
screen and send its image across a network connection to the print server.
The print server could then, at its own leisure, convert the image to
PostScript without holding up the display program. This approach assumes
that transferring an image over the network would be faster than writing it
to an intermediate file.
After The Fact Note: The XSAR Requirements Document, which I believe
came from the Italian Space Agency (Agenzia Spaziale Italiana), specified
that our GUIs generate PostScript files to be printed on Hewlett-Packard
laser printers fitted out with PostScript interpreter cartridges. We
complied. When our system was installed at the Jet Propulsion Laboratory,
it was notable for how very long it took to print out a page, especially
compared to all the other ASI and European Space Agency equipment. They,
of course, bypassed the PostScript altogether and utilized the HP printers'
native Printer Command Language (PCL). When the complaint about our
system's performance came through, it was a simple matter to specify the
"-device ljet
" option ("ljet
" for HP LaserJets)
to xpr in order to generate PCL directly instead of PostScript.
Voilà: speedy print-outs!
As you can see, the xwd_get_window()
and
xpr_print_window()
functions could be used by XSAR's
hardcopy-generating, X/Y plot program. In fact, if there were a means of
determining when the fields on a page were fully populated (*), a generic
page snap program could be written that would work with both ADT- and
GDT-defined pages. And, if the Dynamic/Static Display program had a way of
accepting artificial input (e.g., simulated PRINT
button
presses), it could be used to generate static page snaps, saving us the
trouble of writing one or more separate programs. Oh, well ... time to
wake up!
(*) Come to think of it, doesn't the static display program have this same problem when automatically stepping from major frame to major frame!