\begindata{text,538858664} \textdsversion{12} \template{default} \define{footnote

advertisement
\begindata{text,538858664}
\textdsversion{12}
\template{default}
\define{footnote
attr:[Flags OverBar Int Set]
attr:[FontSize PreviousFontSize Point -2]}
\define{keyword
}
\define{function
}
\define{para
menu:[Justify~2,Para]
attr:[Indent LeftMargin Cm 43927]}
\define{code
menu:[Justify~2,Code]
attr:[LeftMargin LeftMargin Cm 83230]
attr:[Indent LeftMargin Cm 0]
attr:[FontFamily AndySans Int 0]}
\define{bullist
menu:[Justify~2,Bullist]
attr:[LeftMargin LeftMargin Cm 99414]
attr:[RightMargin RightMargin Cm 83230]
attr:[Indent LeftMargin Cm -16183]
attr:[Tabs TabClear Point 18]
attr:[Tabs TabClear Point 14]
attr:[Tabs LeftAligned Point 7]}
\define{class
}
\define{comment
}
\chapter{The Print Class
}
\code{\keyword{static} \keyword{int}
\function{\bold{print::ProcessView}}(\keyword{
}\leftindent{\keyword{class} view *v,\keyword{
int} print,\keyword{
int} dofork,\keyword{
char} *DocumentName,\keyword{
char} *prarg)
}}
\para{This prints or previews the view \italic{v}. \
The \italic{print} argument specifies a printing mechanism, and also
specifies whether the document is to be printed or previewed. The values
\typewriter{print_PRINTTROFF}, \typewriter{print_PREVIEWTROFF},
\typewriter{print_PRINTPOSTSCRIPT}, and
\typewriter{print_PREVIEWPOSTSCRIPT}
can be used.
If \italic{dofork} is TRUE, the print or preview command will work
asynchronously (in the background.) If \italic{dofork} is FALSE, the
command will execute synchronously, and ProcessView will not return until
the command is complete. Note that printing commands are considered
complete when the print job is successfully queued; but previewing
commands
are often not considered complete until the user has finished looking at
the document and closed the viewing window.
\italic{DocumentName} is a hint. The printing mechanism may use this to
display a filename on a banner page or window title bar. If you set this
to
NULL, \italic{ProcessView} will make something up.
\italic{prarg} is an optional list of extra arguments to be passed
directly
to the printing command. Use NULL to specify no extra arguments. If the
\italic{print} parameter specifies previewing, \italic{prarg} is ignored.
\
}
\code{\keyword{static} \keyword{char} *
\function{\bold{print::GetPrintCmd}}(
\leftindent{\keyword{int} print)
}}
\para{This returns the command which will be used by the operation
specified by \italic{print}. This parameter has the same meaning as in
\italic{ProcessView} (described above.)
You will normally not have to call this function. \
}
\subsection{A Walkthrough of the
PostScript\footnote{\
\begindata{fnote,540716184}
\textdsversion{12}
PostScript is a trademark of Adobe Systems Incorporated.\
\enddata{fnote,540716184}
\view{fnotev,540716184,205,0,0}} Printing System, with Function Calls
}
\para{A printing job is initiated the same way it was in the old
mechanism
-- by a function which is bound to the "Print" menu option. This function
calls \italic{print::ProcessView} with the print parameter set to
\typewriter{print_PRINTPOSTSCRIPT} or
\typewriter{print_PREVIEWPOSTSCRIPT}.}
\para{In this case, \italic{print::ProcessView} sets up the environment
for
a PostScript printing job. This includes: \
}\bullist{\symbol{\^{7}}
write
to;
\symbol{\^{7}}
definitions;
opening a temporary file for \italic{v} to
preparing empty hash tables for v to register fonts and
\symbol{\^{7}}
looking through the print options (page size, print
scale,
landscape mode). \
}It then calls \italic{v}'s main PS printing method,
\italic{view::PrintPSDoc}.
\code{virtual void \bold{view::PrintPSDoc}(
\leftindent{FILE *outfile, \
long pagew, long pageh)
}}
\para{\italic{outfile} is the file that the view will be writing its
output
to. This does \italic{not} include PS comment headers and body headers;
these will be prepended later by the printing mechanism. \
\italic{pagew} and \italic{pageh} give the size of the page that the view
should format its output for (in PS units, 1/72 inch.) This is normally
612
by 792, specifying 8.5"x11"
paper\footnote{\
\begindata{fnote,540719800}
\textdsversion{12}
One of these days it will understand different paper sizes. That day is
not
yet.\
\enddata{fnote,540719800}
\view{fnotev,540719800,206,0,0}}; but this may be altered by the user's
landscape and scaling print options. For example, if landscape mode is
set,
the print mechanism would pass dimensions of 792 by 612 instead. \
The view is now in control of the printing process, and can generate any
PostScript code it wants. However, it must conform to certain
constraints. \
}
\subsection{Methods To Be Called During Printing
}
\para{Each page of output must be preceded by a call to
\italic{print::PSNewPage}.
}
\code{\keyword{static} boolean
\function{\bold{print::PSNewPage}}(\keyword{
}\leftindent{\keyword{int}
pagenum)
}}
\para{The view should set \italic{pagenum} to the number of that page.
(This need not be a simple 1, 2, 3... series; if the document represents
a
single chapter of a book, the page numbering might begin at a higher
number. If the view doesn't maintain a separate notion of page numbering,
and is willing to accept 1, 2, 3..., it can pass in the constant
\typewriter{print_UsualPageNumbering}.) \
\italic{print::PSNewPage} transparently handles several things. \
}
\bullist{\symbol{\^{7}}
begin a new
page of output.
It generates the appropriate PS code to
\symbol{\^{7}}
It generates PS code to handle landscape and scaling
options, so that the view's printing commands come out in the correct
place
on the page.
\symbol{\^{7}}
It compares \italic{pagenum} to the "range of pages to
print" print option. If the page should be printed,
\italic{print::PSNewPage} returns \typewriter{TRUE}. If not, it returns
\typewriter{FALSE}; this tells the view that it must skip generating any
PS
for this page. (not yet implemented)
\symbol{\^{7}}
If an "N-up" print option is set, it can generate PS
commands to scale the page down and move it to the appropriate place on
the
page, or begin a new page of output if this is the Nth page. (not yet
implemented)
\symbol{\^{7}}
Finally, if \italic{view::PrintPSDoc} exits without ever
calling \italic{PSNewPage}, the printing mechanism knows that the view
cannot be printed, and gives an error message. Note that this means that
an
empty view must call \italic{PSNewPage} once, not zero times, to print a
blank page.
}
__________________________________
\para{The view should also register PostScript definitions that it plans
to
use, with the \italic{print::PSRegisterDef} call. By registering them
with
the printing mechanism, it ensures that commands aren't multiply defined
(even if that type of view is printed several times in a document.) It
also
ensures that all commands are defined in the correct place in the final
PostScript (in the prologue, before the first page begins.) It also means
that we do \italic{not} need a static list of headers included in each
document. \
}
\code{\keyword{static} \keyword{void}
\function{\bold{print::PSRegisterDef}}(
\leftindent{\keyword{char}
char}
}}
*procname, \keyword{\
*defstring)
__________________________________
\para{If the view wants more complex PostScript code in the prologue, it
can register a callback procedure to generate arbitrary output. \
}
\code{\keyword{\keyword{typedef} \keyword{void}
(*\bold{print_header_fptr})(\keyword{FILE *outfile, void} *rock);
static} \keyword{void} \function{\bold{print::PSRegisterHeader}}(
\leftindent{char *headname,
print_header_fptr headproc, \keyword{\
void} *rock)}}
\para{The \italic{headname} string is just used to uniquely identify
callbacks. A callback is called only once in the header even if it is
registered several times by different instances of the view. You must
ensure that if \italic{PSRegisterHeader} is called more than once with a
particular headname, the headproc and rock are the same on each call. If
they are not, the results are undefined.
The header that you create should not alter the graphics environment in
any
way. You may not alter the current path, color, transformation, etc. If
you
want to do any of these things, the header should be surrounded by
\typewriter{gsave} and \typewriter{grestore}. (The printing module takes
some precautions to protect the environment against violations of this
rule; but they are not perfect and you should not rely on them.)
Note that definitions registered by \italic{PSRegisterDef} will appear
before text registered by \italic{PSRegisterHeader}. However, you can
make
no other assumptions about the order of items in the PostScript prologue.
}
__________________________________
\para{A similar mechanism, \italic{print::PSRegisterFont}, allows the
view
to register PS fonts that it plans to use. This allows the printing
mechanism to generate a correct \typewriter{%%DocumentFonts} header
comment. \
}
\code{\keyword{static} \keyword{int}
\function{\bold{print::PSRegisterFont}}(
\leftindent{\keyword{char}
*fontname)
}}
\para{The integer returned by \italic{PSRegisterFont} is a key which can
be
conveniently stored to refer to the font. The view can use the command
}\code{fprintf (outfile, "%s%d %d scalefont setfont\\n",
print_PSFontNameID, keyvalue, fontsize);
}to generate a PS command to set the current font to the font whose key
is
\italic{keyvalue} and whose size is \italic{fontsize} points.
__________________________________
\para{Finally, there is a mechanism to register callbacks to clean up
after
the printing job is completed. The printing of text objects is so icky
that, in places, objects are created which must persist through the
entire
printing job.
}
\code{\keyword{\keyword{typedef} \keyword{void}
(*\bold{print_cleanup_fptr})(\keyword{void} *rock);
static} \keyword{void} \function{\bold{print::PSRegisterCleanup}}(
\leftindent{print_cleanup_fptr cleanproc, \keyword{\
void} *rock)
}}
\para{This registers the function pointer and rock; when the job is
completed, each registered pointer will be called and given its rock as
its
argument. Note that each callback is called once for each time it is
registered. (This is different from \italic{PSRegisterHeader}, which
allows
each callback to be called exactly once, even if it is registered several
times.)
}
__________________________________
\para{That sums up what \italic{PrintPSDoc} has to do; use the five
printing callbacks described above, and dump PS code to \italic{outfile}.
Note that the printing callbacks can \italic{only} be called during a
printing job -- that is, within a call to some view's \italic{PrintPSDoc}
method. If they are called under other circumstances, they will return
immediately and have no effect.
}
\subsection{Printing Helper Methods
}
\para{In contrast, the following helper functions are always available.
They may be called when there is no printing job in progress, and they do
not affect the state of the printing job if there is one.
}
__________________________________
\code{\keyword{static} boolean
\function{\bold{print::LookUpColor}}(\keyword{
}\leftindent{\keyword{char} *name, \keyword{\
double} *rval, \keyword{double} *gval, \keyword{double} *bval)
}}
\para{Given the name of a color, return the red, blue, and green values
which comprise it.
}
__________________________________
\code{\keyword{static} \keyword{short}
*\function{\bold{print::EncodeISO8859}}()
}
\para{This returns an encoding vector which maps the ISO8859-1 (Latin-1)
character set to the generic AGP encoding used by the PS printing
mechanism. The vector can be considered a 256-element array of short
ints.
If you have a text character which you know is from a ISO8859-1 text, you
can convert it to an AGP value, using code like the following:
}
\code{char ch; /* this is the original character value */
short *encoding;
short agpval; /* the final result */
encoding = print::EncodeISO8859();
agpval = encoding[(unsigned char)ch];
}
\para{Note particularly the expression \code{encoding[(unsigned
char)ch]}.
The cast to unsigned char is very important -- if \italic{ch} has its
high
bit set, you want to look in the range \italic{encoding[128..255]}, not
\italic{encoding[-128..-1]}.
If the result \italic{agpval} is negative, the character has no printed
representation, and should be treated as a zero-width blank. \
}
\code{\keyword{static} \keyword{short}
*\function{\bold{print::EncodeISO8859}}()
}
\para{This returns an encoding vector which maps the Adobe Symbol
character
set to AGP encoding. \
Note: normally, you will not call either of these functions yourself. The
\italic{LookUpPSFont} function (described below) will look up the
encoding
vector appropriate to any screen font, which you can then use with all
characters displayed in that font.
}
__________________________________
\code{\keyword{static} boolean
\function{\bold{print::LookUpPSFont}}(\keyword{
}\leftindent{\keyword{char}
short}
**encoding, \keyword{\
class} fontdesc
char}
*result, \keyword{\
*fd, \keyword{\
*family, \keyword{long} size, \keyword{long} style)
}}
\para{This function accepts either a AUIS font description \italic{fd},
or
(if \italic{fd} is NULL) a font family name, size, and style. It returns
the name of the PS font which matches that description, and the font's
encoding vector (see above.) All standard AUIS screen fonts use either
the
ISO8859-1 or the Adobe Symbol encodings; so the encoding vector will
mostly
likely be one of the two described in the previous section.
}
__________________________________
\code{\keyword{static} \keyword{struct} font_afm
*\function{\bold{print::GetPSFontAFM}}(\keyword{
}\leftindent{\keyword{char}
*fontname)
}}
\para{Given a PS font name, this loads the AFM (Adobe Font Metric) file
associated with that font and returns a pointer to the result. See below.
}
__________________________________
\code{\keyword{static} \keyword{void}
\function{\bold{print::OutputPSString}}(
\leftindent{FILE *outfile, \keyword{\
char} *str, \keyword{\
int} maxlen)
}}
\para{Takes the string \italic{str} and writes it to \italic{outfile},
using PS string escaping to quote any character which needs to be quoted
in
a PS string literal. It does not write the delimiting parentheses of a PS
string literal. A maximum of \italic{maxlen} characters are written; to
write up to a \\0 delimiter, set \italic{maxlen} to -1.
This function assumes that \italic{str} is already in the PS character
encoding. The caller must ensure the string is encoded before
\italic{OutputPSString} is called. If the string contains only 7-bit
printable ASCII characters, no encoding is necessary. For a more
convenient
way to generate PS from AUIS strings, see \italic{GeneratePSWord}.
}
__________________________________
\code{static double \bold{print::ComputePSCharWidth}(
\leftindent{int
chi, \
struct font_afm *afm, \
int
fontsize)
}}
\para{This returns the width (in PS units) of the character \italic{chi}.
\italic{chi} should be in the AGP encoding; \italic{afm} is the fontmetric
structure for the font you want to measure in, and \italic{fontsize} is
the
point size of the font.
Confused? It works like this. \
}
\code{\keyword{class} fontdesc *yourfontdesc; /* you should have this set
to the font you want to measure */
int size; /* you should have this set to the point-size of the font you
want to measure */
char ch; /* the character you want to measure */
short *encoding;
char psfontname[64];
struct font_afm *afm;
double width; \
print::LookUpPSFont(psfontname, &encoding, yourfontdesc, NULL, 0, 0); /*
looks up the font name and encoding for the fontdesc you provide */
afm = print::GetPSFontAFM(psfontname); /* look up the AFM data */
width = print::ComputePSCharWidth(encoding[(unsigned char)ch], afm,
size);
}
\para{Note particularly the expression \code{encoding[(unsigned
char)ch]}.
The cast to unsigned char is very important -- if \italic{ch} has its
high
bit set, you want to look in the range \italic{encoding[128..255]}, not
\italic{encoding[-128..-1]}.
If you are not working from a particular screen font, you will have to
provide the encoding vector and PS font name yourself. Most text in AUIS
is
ISO8859-1 text. (This includes any text which is 7-bit ASCII. The first
128
characters of the ISO8859-1 encoding are identical to the 7-bit ASCII
characters.) \
To get the ISO8859-1 encoding, use this code:
}\code{short *encoding = print::EncodeISO8859();
}\para{If you want to measure a string using the "symbol" screen font,
use
this instead:
}\code{short *encoding = print::EncodeAdobeSymbol();
}(conveniently, the "symbol" screen font uses the same encoding as the
Adobe Symbol PS font.)
__________________________________
\code{static void \bold{print::GeneratePSWord}(
\leftindent{FILE
char
int
*buf, \
len, \
double
short
xpos, \
*encoding, \
struct font_afm
int
*outfile, \
*afm, \
fontsize)}\leftindent{
}}
\para{This is it -- the routine to generate the PS code to print a text
string. \italic{outfile} is the file to print to; \italic{buf} is the
string; \italic{len} is the number of characters to print; \italic{xpos}
is
the horizontal position (in PS units) to start printing at. \italic{\
encoding} is the encoding vector you got from \italic{LookUpPSFont};
\italic{afm} is the AFM data you got from \italic{GetPSFontAFM};
\italic{fontsize} is the point size of the font. For a full explanation
of
these parameters, see the discussion above about using
\italic{ComputePSCharWidth}.
Note that \italic{buf} should be a buffer to the original string data;
you
do not have to convert the character values by looking them up in
\italic{encoding[]}. The \italic{GeneratePSWord} function does that for
you.
Although this function is called \italic{GeneratePSWord}, it will
correctly
display strings which contain spaces. It will \italic{not} do anything
with
tabs or linefeeds; they will be treated as zero-width blanks, just like
all
other non-printable characters. If you want tabs or linefeeds to behave
sensibly, you will have to break the string up yourself and call
\italic{GeneratePSWord} several times. You will also have to do this if
you
want to put additional whitespace between words (for full justification.)
The vertical (baseline) position of the string is assumed to be stored in
a
PostScript identifier called \code{tY}. Before calling
\italic{GeneratePSWord}, you should output PostScript code such as
}\code{/tY 130.5 store
}\para{(substituting the desired vertical position for
\typewriter{130.5},
of course.) This is efficient in the usual case of printing several words
on the same line. However, remember that \code{tY} is effectively a
global
variable, and other views may store values in it. If your code calls
another view's printing method, the value of \code{tY} will be undefined
after that method returns, and you should store your vertical position
again before your next call to \italic{GeneratePSWord}.
You need not register the definition of \code{tY};
\italic{GeneratePSWord}
will call \code{PSRegisterDef("tY", "0")} to register the definition with
a
dummy value of 0.
}
\subsection{A Word About Dictionaries
}
\para{In PostScript, definitions for identifiers are stored in
dictionaries. Each dictionary has a fixed size; only a given number of
definitions can be stored in each dictionary.
All the definitions that you create using \italic{PSRegisterDef},
\italic{PSRegisterHeader}, and \italic{PSRegisterFont} are stored in a
dictionary called atkDict. That dictionary is opened at the beginning of
the PS file and remains open until the end. It is exactly big enough to
hold all the registered definitions, and no more. This means that if you
place any unregistered "def" statements in the PS output, you will cause
a
"dictionary full"
error.\footnote{\
\begindata{fnote,540749896}
\textdsversion{12}
Warning: ghostscript, the most common PostScript previewer, allows
dictionaries to be overfilled without giving an error. This means that
you
can accidentally create PS files which look correct in ghostscript, but
cause errors when printed or viewed with other software. Be careful.\
\enddata{fnote,540749896}
\view{fnotev,540749896,207,0,0}}
If you want a temporary space in which to store values during your
printing
process, you should register it with \italic{PSRegisterDef,} giving it a
dummy value. Then store values into it using "store" instead of "def".
It is also possible to create your own dictionaries. Use a statement like
}\code{print::PSRegisterDef("yourdictname", "20 dict");
}where \italic{yourdictname} is the name you have chosen and \italic{20}
is
the number of definitions you need. Then you can say
\code{print::PSRegisterHeader("yourheaderid", headerproc, NULL);
}where \italic{yourheaderid} is a unique string and \italic{headerproc}
is
a function which generates PS output like the following:
\code{yourdictname begin
\italic{PS code to define entries
}end
}
\para{This will cause the dictionary to be defined and filled in the PS
prologue. (Remember that if your view appears as an inset, it may appear
more than once, and thus make these registration calls more than once.
Nonetheless, the dictionary will be created and defined exactly once.)
During printing, you may then open and close the dictionary as usual
(using
"begin" and "end") and use the definitions in it. Remember to close any
dictionary you open; this helps prevent possible conflicts between
insets.
Also, if your view is about to call an inset's PrintPSRect method (see
below), you should close any dictionaries you have opened, to avoid
conflicts. \
It is possible to create definitions in the built-in dictionary userdict,
by using the "put" statement. This is not recommended, since there is no
easy way to tell how big userdict is or whether it is full.
}
\subsection{Printing Insets
}
\para{There are at least two different ways that substrate views can
print
their insets. The naive way is that the parent selects a rectangle on the
page, and the child generates PS code that draws an image in that
rectangle. However, there are also insets that are designed solely to be
placed in text; they are not printed on the page, but instead affect how
the text is formatted. Examples of this latter type are page break
insets,
footnotes, and the header/footer inset.
To allow both of these methods, and leave room for others, the new
printing
mechanism introduces the idea of \italic{printtypes}. A printtype is just
a
protocol for the parent and child to negotiate how the printed page will
look. \
If a view has child views, the parent calls each child's
\italic{view::GetPSPrintInterface} method to determine how that child
should be printed.
}
\code{\keyword{virtual} \keyword{void}
*\function{\bold{view::GetPSPrintInterface}}(\keyword{
}\leftindent{\keyword{char} *printtype)
}}
\para{\italic{printtype} is a string which specifies the exact mechanism
the parent is asking about. The child returns non-\typewriter{NULL} if it
can be printed with the given printtype, and \typewriter{NULL} if it
cannot. Depending on the printtype, the returned non-\typewriter{NULL}
value may contain additional information. \
Note that if the child returns NULL, the parent may call
\italic{GetPSPrintInterface} again with a different printtype. A
substrate
may be able to print its children with several different printtypes; it
is
up to the parent to choose one. Similarly, a child view may be able to be
printed with several different printtypes.
AUIS currently supports two printtypes. The naive
draw-yourself-in-a-rectangle printtype is called "\typewriter{generic}";
the protocol by which special insets negotiate with textview is called
"\typewriter{text}".
}
\italic{The \typewriter{generic} protocol}
\para{This is the most common protocol; all the substrates (text, figure,
and table) allow their children to be printed with it, and all the major
data types can be printed as children under it. In fact, it is common
enough that there are methods in class view to support it. \
}
\code{\keyword{virtual} \keyword{void}
\function{\bold{view::DesiredPrintSize}}(\keyword{
}\leftindent{\keyword{long} width, \keyword{long} height, \keyword{\
enum} view_DSpass pass, \keyword{\
long} *desiredwidth, \keyword{long} *desiredheight)
}\keyword{virtual} \keyword{void} \function{\bold{view::PrintPSRect}}(
\leftindent{FILE *outfile, \keyword{\
long} logwidth, \keyword{long} logheight, \keyword{\
struct} rectangle *visrect)
}}
\para{This works as you might expect. \
First the parent verifies that
\italic{child->GetPSPrintInterface("generic")} returns non\typewriter{NULL}
(the returned value is not otherwise meaningful). \
Then the parent calls the child's \italic{DesiredPrintSize} method,
passing
in the dimensions of the rectangle that it intends to give (in PS units,
1/72 inch.) It also passes in a \italic{pass} value which indicates which
dimensions it is willing to be flexible on. The child returns its
preferred
dimensions, which the parent is free to modify or ignore. \
Then the parent calls the child's \italic{PrintPSRect} method.
\italic{logwidth} and \italic{logheight} are the rectangle dimensions the
parent has decided upon. (The rectangle starts at the origin -- the
parent
is responsible for generating PS code which translates this to the
correct
part of the parent's page.) If the parent knows that part of this
rectangle
will be not visible (off the page, for example, or overwritten by other
parts of the image), it may pass this information in by setting
\italic{visrect}. \italic{visrect} is the part of the drawing rectangle
which is actually drawable; the child can optimize by not drawing data
that
lies outside
\italic{visrect}.\footnote{\
\begindata{fnote,540759608}
\textdsversion{12}
\define{italic
menu:[Font~1,Italic~11]
attr:[FontFace Italic Int Set]}
Note that the parent is responsible for setting the PS clipping region
before calling \italic{PrintPSRect}. The child is allowed to ignore
\italic{visrect} and draw outside it, and even to draw outside the main
rectangle.\
\enddata{fnote,540759608}
\view{fnotev,540759608,208,0,0}} \
The parent is reponsible for saving the PS drawing state before a call to
\italic{PrintPSRect}, and restoring it afterwards.
}
\italic{The \typewriter{text} protocol}
\para{A full explanation of this would require a full explanation of the
textview printing algorithm, which is painful. However, in brief, the
call
to \italic{GetPSPrintInterface("text")} returns a pointer to a
\class{\italic{textview_insetdata} }structure, which the child has filled
out to indicate what special behavior it wants from the parent text. The
possibilities include:
}
\bullist{\symbol{\^{7}}
The child provides a textview which the
parent text
should print out at this point (just as if the text had been pasted into
the parent.)
\symbol{\^{7}}
The child provides a character string which the parent
text
should print out at this point. The child may also provide a single style
to be wrapped around the string.
\symbol{\^{7}}
The parent should begin a new page.
\symbol{\^{7}}
print
The child provides a textview which the parent should
as a footnote at this point.
\symbol{\^{7}}
The child provides a header or footer which the parent
should use from this point on.
\symbol{\^{7}}
The child provides a text tag at this point.
\symbol{\^{7}}
The child provides a reference to a given text tag.
}
\para{The first two of these (pasted textview and pasted string) are the
only ones likely to be used by new insets. \
}
\section{Creating Complete PostScript files }\
\para{A complete PostScript file has headers, a sequence of pages
generated by \italic{view::PrintPSDoc} or \italic{view::PrintPSRect}, and
finally some trailers. A print object can be utilized to create a
complete
PostScript file with appropriate headers and trailers. When a
\italic{print} object is created, it does some initialization and opens a
temporary file to receive the contents of the PostScript file that will
be
generated by \italic{view::PrintPS...}. The client uses the
\italic{GetFILE} method to get a pointer to this FILE* object and passes
this as the FILE* argument to the\italic{ view::PrintPS...} methods. The
complete file is then written with a call to \italic{WritePostScript}.
All of the functions defined in earlier sections that can be called while
a
print is in progress can be called while a print object is in existence.
In particular, the definitions registered with the
\italic{PSRegister...}
calls are correctly inserted in the generated file.
In addition methods are available to set the print parameters that would
otherwise be set by the \bold{Printer Setup} menu option. These are the
parameters:
}
\leftindent{\description{Landscape - a boolean.
image a quarter turn counter-clockwise.
When True, rotates the
Scale - a double. Values less than one produce a smaller image and
bigger
values enlarge the image.
PaperSize - two int values.
printed on.
Filename - char *.
print object.
Title - char *.
The width and height of the page to be
The name of the file which will be created by this
The title which will be written in the file's header.}}
The parameters are fetched and set with the following methods:
\code{void \bold{SetLandscape}(boolean v) \
boolean \bold{GetLandscape}() \
void \bold{SetScale}(double v) \
double \bold{GetScale}() \
void \bold{SetPaperSize}(int width, int height) \
void \bold{GetPaperSize}(int *width, int *height) \
void \bold{SetFileName}(char *fnm) \
char *\bold{GetFileName}() \
void \bold{SetTitle}(char *tnm) \
char *\bold{GetTitle}() }\
\para{The method }\
\code{void \bold{SetFromProperties}(
\leftindent{view *v, \
long *pwidth, long *pheight);}}
interrogates the view for any print option properties that may have been
set by \bold{Printer Setup}. The values of *pwidth and *pheight, if
non-NULL, will be set to the width and height for the object to be
printed.
This can differ from the page size because it honors scaling and the
landscape parameter. It is generally best to call this method after
setting the parameters with the explicit methods above.
\para{Actual creation of PostScript code is performed by two methods:}
\code{FILE* \bold{GetFILE}()
boolean \bold{WritePostScript}(
char *filename, \
char *title);}
\italic{GetFILE} returns a \italic{FILE*} value which is for an internal
file utilized by the print object. It is this file into which the
PostScript for pages must be generated. After the PostScript pages have
been written, a call to \italic{WritePostScript} creates a file named
\italic{filename} and having the \italic{title} given. Either of the
arguments can be NULL, in which case the values set by \italic{SetTitle}
or
\italic{SetFilename} will be used. If the file name is not specified in
either way, the print object will try to make up a reasonable name by
searching for a buffer containing the view and using its file name. If
all
else fails, the file will be named by the tmpnam() function; this is
rarely
useful.
\para{The code just below is one way to utilize a print object for
generating a PostScript file. The declaration \italic{print p} is an
automatic declaration and creates a print object when the scope is
entered;
the object is destroyed when the scope exits. The \italic{p.Set...}
calls
set attributes of the print; the call to \italic{SetFromProperties} will
honor any print parameters set for the view (as with the \bold{Printer
Setup} menu item). }\
\code{long pagew, pageh;
print p;
// printing context
p.SetPaperSize(width, height);
p.SetScale(scale/100.0);
p.SetFromProperties(v, &pagew, &pageh);
v->PrintPSDoc(p.GetFILE(), pagew, pageh);
if ( ! p.WritePostScript(tfnm, NULL)) \
;
// should print an error message here
// ... process tfnm
unlink(tfnm);}
Note that there are TWO files involved. The file named \italic{tfnm} is
the desired full PostScript file and is created and written by the call
to
\italic{WritePostScript}. In this application, \italic{tfnm} is a
temporary file, so the client unlinks it when done. The other file is
created by the constructor for the print object and utilized as the FILE
argument to \italic{PrintPSDoc} by the call to \italic{p.GetFILE}. This
file is copied into \italic{tfnm} as part of the \italic{WritePostScript}
operation and is deleted by the destructor for the print object.
\para{Each \italic{print} object can be used only once to create a
PostScript file. To create another file, another \italic{print} object
must be created.
A \italic{print} object may be created even while another already exists.
The most recently created (and not yet deleted) \italic{print} object is
returned by}
\code{static print *\bold{print::GetCurrentPrint()}}
Note that \italic{PSRegister...} calls apply only to the print operation
that is the value of \italic{GetCurrentPrint}. When a print is initiated
by \italic{print::ProcessView}, it creates a \italic{print} object which
becomes the value of \italic{GetCurrentPrint}; this value can be used to
access the data members of that print operation.
\subsection{A Final Word About Coordinates}
\para{There are several places in the printing mechanism (notably the
methods for the "generic" printtype) where rectangles are given in PS
coordinates. This involves a problem. The AUIS struct rectangle has
members
\italic{left}, \italic{top}, \italic{width}, and \italic{height}; this is
because it is usually used with AUIS screen coordinates, whose origin is
in
the top left. But PS coordinates put the origin in the bottom left. What
to
do?
What to do is this: accept the names of the members as correct.
\italic{left} is the X coordinate of the left edge; \italic{width} is the
(positive) width of the rectangle. \italic{top} is the Y coordinate of
the
top edge of the rectangle; \italic{height} is the (positive) height of
the
rectangle. This means that \italic{top} has a \italic{greater} numerical
value than the Y coordinate of the bottom edge. The bottom edge can be
computed as \italic{(top-height)}. This is different from rectangles in
view coordinates, whose bottoms can be computed as \italic{(top+height)}.
This means that many of the macros and functions in
\typewriter{rectangle.h}
cannot be used with PS rectangles. Notably, \italic{rectangle_Bottom}
will
do the wrong thing. However, \italic{rectangle_IsEmptyRect} will work,
because it is still true that a rectangle with negative width or height
is
empty.
Why did I choose to do it this way? Because it confuses me least. It
might
have made more sense to define an entirely new type, and allow C++
type-checking and overloading to take care of the situation. \
}
\enddata{text,538858664}
Download