home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
programs
/
printer
/
hwgpost
/
hwgpostlib.doc
< prev
next >
Wrap
Text File
|
1995-02-27
|
21KB
|
502 lines
PostScript shared library interface (post.library, with HWGPOST >= V22.21)
==========================================================================
HWGPOST, Copyright 1993, 1994 Heinz Wrobel, is mostly calling compatible to
Post V1.7, Copyright Adrian Aylward 1991, 1992. But it is a very different
beast inside.
This document is derived from Adrian Aylward's post.library documentation.
Introduction
============
The file "post.library" is an AmigaOS Exec shared library containing a
mostly Level II compliant PostScript interpreter. It is designed to be
shareable between different processes, supporting arbitrarily many
PostScript activations - at least until you run out of memory.
This file should be read in conjunction with the header file "postlib.h".
The standard user interface source files are distributed with old Post 1.7.
Read them as examples for now. If there is different information in this
document or the current headerfile postlib.h or init.ps, the
current information holds.
Activation Records
==================
Simultaneous multiple activations of PostScript are allowed. Before using
post.library you must first open it by a call to OpenLibrary(). To create
an activation you then call PScreateact() which returns a pointer to the
activation record. You can then make calls to the interpreter library,
passing the activation record pointer as an argument. You can create
several activations, possibly from different processes and intermingle
the interpreter calls if you wish. But you CANNOT PASS ACTIVATION RECORDS
BETWEEN PROCESSES! When you have finished with an activation, call
PSdeleteact() to delete it and free the memory it used. When you have
finished with the library call CloseLibrary(); if no other processes have it
open, then Exec can remove it from memory if the space is needed. (N.B. if
the space is not needed, the library will remain in memory in case it is
opened again.)
N.B. the library can only be called from a process, as it calls various
AmigaDOS functions. IT IS NOT PERMISSIBLE TO PASS ACTIVATION RECORDS
BETWEEN PROCESSES! NOTE THIS WELL!
The Parameter Block
===================
The parameter block is the argument to PScreateact(). It is specifies the
addresses of the bitmap planes, size of the page, and the amount of memory
to be allocated for the activation etc ... Its format is defined in detail
in the header file postlib.h.
N.B. all ints are 32 bits, shorts are 16 bits.
The page size is limited to 30000 pixels a side. The densities (pixels per
inch) may be any strictly positive integer value. The y direction may be
set to +1 - if the bitmap rows are in PostScript order (bottom row first)
or -1 - Amiga order (top row first).
page.buf[24] Bitplane pointers, up to 24
page.len Size in bytes of each plane
page.depth Number plane pointers to use
page.flags Special device options
page.bitspercolor How many plane pointers to be used per gun.
page.PSextdevice An optional extension to the device information
page.xbytes Number of bytes in each row
page.xsize Number of pixels in each row
page.ysize Number of rows
page.ybase Base of current band
page.yheight Total height of full page, for band rendering
page.xden X density
page.yden Y density
page.ydir Y direction
To specify how many bitplanes are used per color, you set "bitspercolor" to
the appropriate value. If this value is not set, one bitplane per color is
assumed and only 1, 3, and 4 are permissible as depth in this case.
Example: RGB 3:3:2 => depth=8, bitspercolor=3.
Note that bitspercolor should not exceed 8.
For special use, the page device description can be enhanced by setting
page.PSextdevice. The PSextdevice structure contains the following fields.
flags Extension of the main flags field.
maskbuf If set, must be a plane as in page.buf. For any
rendering you'll get bits set in this mask plane.
This gives you a mask of the actually used places
in the buffer. The mask might be useful for
BltMaskBitMapRastPort() or some such. erasepage
will clear this mask plane.
Kbuf[8] Eight additional plane pointers to allow for true
eight bit CMYK rendering. You need to set the depth
to a value greater 24 for these to be used.
The length of these structures is subject to change. Always set unused fields
to zero.
As a starting point for memory sizes try the values following. (These are
defined in the header file.) For normal PostScript programs the defaults
are perfectly satisfactory. If you specify a value of zero the default
will be used instead; values less than the minimum will be increased.
memvlen 50000 VM
memflen 60000 Font cache
memllen 15000 Path lines
memhlen 20000 Halftones
memplen 60000 Pattern cache
The user data pointer is intended to be used to identify multiple
activations. You can set it to any value you like. The function pointers
are described below.
userdata User data pointer
flushfunc Flush page function pointer
copyfunc Copy page function pointer
The standard input and output streams are the AmigaDOS file handles to be
used by the interpreter for %stdin, %stdout, %stderr. Also the standard
output is used for prompts and the error output for error messages. These
file handles will not be closed by the interpreter even though PostScript
file objects referring to them may be closed.
infh Standard Input file handle
outfh Standard Output file handle
errfh Standard Error file handle
These are for backwards compatibility with the infamous "callextfunc"
operator. You'll find details below.
funcmax Number of external functions
functab Pointer to external function table, or zero
Anything else in the block is reserved and must be set to zero.
Notes on the special device flags
---------------------------------
In the header file "postlib.h" you will find some flag definitions for the
main flag field of the parameter page. They need more explanation.
HWGPOST_DEVx_NOSHADE
Halftoning is in effect suppressed. No halftone screens will be
used. Any color intensity that would cause shading will be rendered
as the next lower color value truly representable within the
bitplanes would. Shading is simply "cut out".
HWGPOST_DEVx_CMYK
Old post.library supported the CMYK color space and operators. When
converting any colors to values passed to the transfer functions,
it creates RGBW values, though, instead of CMYK. With this flag
set, the colorspace mapping algorithm will stay with CMYK and CMYK
will be passed to the transfer functions if applicable.
HWGPOST_DEVx_INVERTOUTPUT
The output of the transfer functions represent the value that
should be rendered into the bitplanes. With this flag set,
these values in the range [0.0;1.0] will effectively reversed with
a simple "shade = 1.0 - shade" before the rendering is set up. This
is the easiest way to create "negative" output and might come in
handy for multiple bitplane color handling, where black should be
"all bits 0" instead of "all bits 1" in the planes.
Function Pointers
=================
There are two function pointers within the parameter block, which are used
when the interpreter needs to call routines supplied by its client. If the
pointers are zero, the calls are skipped.
To help identify calls from multiple activations, the activation record
address is also passed in A0 and the userdata pointer in A1.
flushfunc(D0: int y1, D1: int y2)
Flush the bitmap to the screen. The interpreter calls this function after
a painting operation has updated the bitmap. Then if the output is being
viewed interactively the client can update the screen or window. The
arguments are the range of bitmap rows (y1 ... y2-1) that may have been
updated.
copyfunc(D0: int num)
Copy the page to the output device. The argument is the value of
"#copies", which should be taken into account if the output is to a
printer, but is not meaningful for screen output.
Calling External Functions
==========================
The original "callextfunc" operator of post.library <= V1.7 is no longer
supported even though it is still available in disguise as "@callextfunc".
Use of this operator is strongly discouraged as it might lure you into
making assumptions about internal HWGPOST data representations.
A more general way to call external functions has been devised via the new
"@calluserhook" operator. This operator collects the arguments, passes them
to a "Hook" as defined by the utility.library, records any changes and
returns the result. This is the calling sequence:
mark <args..> <userhookadr> <msgadr> @calluserhook
On return the operand stack will look like this:
mark <args..> <resint>
A number from zero to eight arguments is supported. Only certain PostScript
objects may be passed as arguments: integers, reals, and booleans are
passed as the 32 bit bitpatterns corresponding to their values; strings are
passed as the 32 bit address of their contents with the length as the
following 32 bit integer. (N.B. PostScript strings are terminated by
length; there is no terminating null unless the program puts one there. The
user function may not go beyond the string length!)
<hookadr> and <msgadr> are integers that are used as 32 bit memory address.
If no <msgadr> is needed, just use 0. These addresses should be passed to
the interpreter via the PSintstring() function in full PostScript notation
like "/hookadr 16#780ab44 def" to be used by special PostScript code. It is
advisable to put them into special, private dictionaries.
The argument values passed are put into an array of 32 bit values which is
passed as "objectptr" to the Hook. The return value will be put on the
operand stack as <resint> and any changes to numeric values in the 32 bit
array will be put back into the args on the operand stack. The Hook may
change string contents within the address and length passed to it.
As an example assume this calling sequence:
mark 1 string1 2.5 4 string2 false hookadr 0 @calluserhook
The 32 bit array passed to the hook as object will have these contents:
array[0]: 32 int 1
array[1]: string1: address
array[2]: string1: length
array[3]: IEEE float 2.5
array[4]: 32 int 4
array[5]: string2: address
array[6]: string2: length
array[7]: 0
If the hook function changes array[0] to 3, array[7] to 1, and returns -1,
the resulting operand stack will contain these values:
mark 3 string1 2.5 4 string2 true -1
Changing a string address or length should not be tried. If results are not
needed, a cleartomark will get rid of them easily.
There should not be any assumptions made about internal representation of
objects. For booleans, only 0 and 1 should be used.
N.B. PSintstring() is not guaranteed to work recursively. So calling it
from the hook is not a good idea. The Hook is called on the interpreters
context. If a local near data section is needed, the Hook function is
responsible for setting up A4, e.g. from hook->h_Data. Standard rules for
saving registers apply. Do not assume that A4 contains anything useful!
Calling External Functions with @callextfunc
============================================
The original "callextfunc" operator of post.library <= V1.7 is no longer
supported even though it is still available in disguise as "@callextfunc".
Use of this operator is strongly discouraged as it might lure you into
making assumptions about internal HWGPOST data representations. It is only
here for limited backwards compatibility. Do not use it for new SW!
If you supply an external function table your PostScript program can call
the functions within it by the "@callextfunc" operator. The contents of
the table are the addresses of the function entry points. The functions
must have standard (Lattice, non-registerised) C compatible calling
sequences. They must not assume any useful value in register A4 on entry,
and must preserve A4 and the other C registers on exit.
Unlike with post.library <= 1.7 there is additional information given,
though. To help identify calls from multiple activations, the activation
record address is also passed in A0 and the userdata pointer in A1.
Only certain PostScript objects may be passed as arguments: integers reals
and booleans are passed as the 32 bit bitpatterns corresponding to their
values; arrays and strings are passed as the 32 bit address of their
contents - if the length is required it must be passed separately. (N.B.
PostScript strings are terminated by length; there is no terminating null
unless the program puts one there.)
It is theoretically possible to pass arbitrary objects by including them
within an array, but then you would need to know their PostScript
representation. As the representation has been changed thoroughly for
HWGPOST and will continue to change in the future, this "feature" is of no
use at all!
The "@callextfunc" operator is only inserted into the system dictionary if
a function table is present. So you will not find it if you attempt to
execute it from the standard user interface.
Library Entry points
====================
Prototypes and pragmas for the entry points are defined in the header file.
Create a PostScript activation
------------------------------
D0:int arec = PScreateact(A1:struct PSparm *parm)
The result is the address of the new activation record. If the activation
fails an error code is returned instead - zero if the interpreter failed
to start at all because there was insufficient free memory, or an
interpreter error code if there was an error during initialisation.
Otherwise the result is the address of the activation record. The result
is always returned as an int. If is is greater than errmax then the
activation was successful, and the value is an address; otherwise the
activation failed, and the result is zero or an error code.
Delete a PostScript activation
------------------------------
VOID PSdeleteact(A0:APTR arec)
The activation record is deleted and the associated memory is freed.
Interpret a string or file
--------------------------
D0:int errnum = PSintstring(A0:APTR arec, A1:char *string,
D0:int length, D1:int flags)
Flag bits:
PSFLAGSTRING, PSFLAGGFILE
If PSFLAGSTRING is set, the contents of the string are interpreted
as PostScript source. If the flag PSFLAGFILE is set, the string is
a file name, whose contents are interpreted. If neither of these
flag bits are set the string is ignored, but the other flag bits
still have their effects; if both are set the result is undefined.
PSFLAGINTER
If PSFLAGINTER is set (when interpreting a file), the file is
considered to be interactive. The banner is printed, and the
interpreter prompts for each line of input from the file.
PSFLAGCLEAR
If PSFLAGCLEAR is set, then after interpretation the operand stack
is cleared and the dictionary stack is popped until only the system
and user dictionaries remain. The execution stack is emptied, too.
PSFLAGSAVE
If PSFLAGSAVE is set, job server behaviour is set up for the
current job only. It is functionally equivalent to
(PSFLAGSTARTJOBSERVER| PSFLAGENDJOBSERVER) but you shouldn't use
the job server flags instead if you really want PSFLAGSAVE.
PSFLAGERASE
If PSFLAGERASE is set, then the page is erased. This happens right
at the end, after any vm restore, so the page is erased taking into
account the restored transfer function(s).
PSFLAGSTARTJOBSERVER, PSFLAGENDJOBSERVER
With PSFLAGSTARTJOBSERVER and PSFLAGENDJOBSERVER one can create one
job server run, spanning multiple invocations of PSintstring(). The
former forces a successful startjob with a "false" operand before
running the job, the latter forces a successful startjob with a
"true" operand after running the job and clears out the execution
stack and does some other private things. These flags do not nest.
If you think about using them in a tricky way: Think again and ask
_first_.
This routine is NOT guaranteed to recurse correctly; strange things or
crashes may happen if you try to call it from an external function called
from the same activation.
Signal an interrupt
-------------------
VOID PSsignalint(A0:APTR arec, D0:int flag)
This routine may be called to set an interrupt signal flag to notify the
interpreter of a special condition. The possible flag values are defined in
the header file postlib.h. You may or multiple bit flags together. The
interpreter tests these flags at the head of its main loop, and also within
certain potentially length operators (=, ==, stack and pstack). If a flag
is set it the interpreter will take appropriate action immediately and
automatically clear the corresponding flag bit. You may safely call this
routine at any time during the life of the activation. It is intended to be
called from within your task's exception handler, if the CTRL-C break
signal is set. Unlike with post.library <= V1.7 it is not possible to clear
a flag once it has been set by calling this function. Only the interpreter
will clear a flag bit when it is handled.
Signal a floating point error
-----------------------------
VOID PSsignalfpe(A0:APTR arec)
This routine is intended to be called whenever a floating point trap is
generated by the interpreter. It generates an immediate undefinedresult
error. You must not call it at any other time; if you do you will crash
the machine. It is only useful if you are using the version of the library
compiled for the 68881 FPU or compatible chips. (The software floating
point routines do not generate traps). Before calling the library you
should set up a trap handler and set the bits in the fpcr register to
enable the traps. (If you do not set up the traps, the FPU will substitute
the special value not-a-number for the result and continue. The
undefinedresult error will not be triggered, and results of your program
may be incorrect.) If you application does not use the FPU you can simply
direct all traps to the library, otherwise it is essential that you
ensure that you only call this routine if the trap derived from the library
and not your own code.
Error
-----
VOID PSerror(A0:APTR arec, D0:int errnum)
This routine is intended to be called from within your own flush or copy
page functions, to signal that an error ocurred. You can also call it from
an external function. You must not call it at any other time; if you do, you
will crash the machine. It calls the PostScript error handler and never
returns. The values for the error number are defined in the header file.
Return a text string corresponding to an error name
---------------------------------------------------
D0:const char *str = PSerrstr(A0:int arec, D0:int errnum)
Converts a postscript error number to a text string. Returns NULL if the
number is out of range.
Change device page
------------------
VOID PSsetdevice(A0:APTR arec, A1:struct PSdevice *page)
Note: While "setpagedevice" is not currently available, the effects caused
by PSsetdevice() are _very_ likely to change in many ways when the
time comes. If you feel that you rely on effects other than simply
replacing the device page buffer and dimensions CONTACT ME NOW.
Changes the device page buffer and dimensions. If the clip path is still
set to its initial value (the whole page) it is changed to match the new page
size; otherwise it is unchanged (and may therefore possibly exceed the new
page size). All the clip paths saved on the graphics stack are similarly
changed. The CTM at the topmost saved graphics state (the one returned to
by a "grestoreall" when there are no active VM saves) is reset to match the
new page size and density. Otherwise the CTM is not affected; you will
likely want to execute "initmatrix" afterwards.
The interactions of this routine with the stack of saved graphics states are
complex, leading to unexpected behaviour unless you understand exactly what
is happening. So it is safest to think twice about calling it and always
call it when there are no save's or gsave's active, and then to reinitialise
the CTM immediately.
This routine should not be called from within a character build, kerning,
or imaging procedure.
Problems, Comments, and Bugs
============================
You will find my complete address in the header file "postlib.h". Contact
me if you have any questions or suggestions. Don't rely on empirical
programming.
Heinz Wrobel
<heinz@hwg.muc.de>
*** EOT ***