home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Archive Magazine 1996
/
ARCHIVE_96.iso
/
discs
/
mag_discs
/
volume_8
/
issue_06
/
risc_os
/
OldPDriver
< prev
next >
Wrap
Text File
|
1988-11-29
|
65KB
|
1,463 lines
This document is intended to tell application authors how to write their
applications so as to make use of the standard RISC OS printer driver
interface. It starts with a general explanation of how the printer drivers
are supposed to be used. Then the SWI interface is described and an example
BASIC procedure is given that shows an application might do its printing. The
final section of the document specifies exactly what VDU sequences and other
plotting operations the application may use while printing.
PRINTER DRIVER PHILOSOPHY
=========================
What the application user sees
------------------------------
RISC OS comes with two printer driver applications, !PSPrinter for PostScript
printers and !DMPrinter for a range of dot matrix printers.
If I possess a PostScript printer and I wish to print, I should do the
following:
Double-click on !PSPrinter. An icon will appear. Menu on this and check
that the settings are right for where the printer is connected, e.g.
net/parallel/serial etc. This setting will be retained in CMOS RAM, so it
need only be done once.
If I wish to print Text files, drag them onto the printer icon. They will get
printed.
If I wish to print from ArcDraw, click Print on the Print dialogue box after
running !PSPrinter. The diagram will be printed. Or, drag the icon from the
Save dialogue box onto the printer icon.
If I wish to print from ArcPaint, it's exactly the same.
If I with to print from any other editor program, it's exactly the same.
If I have a dot matrix printer, run !DMPrinter. Click on the printer icon to
produce a dialogue box of the correct type of printer. Click on the
printer-type field to cycle through the various dot matrix printers
supported, until it reflects mine. If I can't find mine, seek help.
Drivers for other printers will appear, from Acorn and from others, in an
analogous form. New printer drivers will work with all existing applications,
subject to the limitations of any particular printing device.
How and Why
-----------
I use the term "editor" to mean any sort of interactive program that
prepares, changes and processes data files. This includes word processors,
DTP packages, spreadsheets, draw programs, etc. I use the term "Foo" to refer
to any editor program, which operates on "Foo data files": so, substitute
ArcDraw, ArcPaint, or whatever as you read. I use the term "Poo" to refer to
any printer capable of generating graphics, e.g. FX80, Apple LaserWriter,
etc.
In the general case, editors save data in files of their own format, with an
appropriate file type. Only Foo understands Foo data files. Also, different
printers are entirely different from each other, and a pain to drive. If each
editor is to understand each printer, and there are X editors and Y printers
in the world, then:
(a) There is X*Y work to do
(b) If a new printer type comes along, all applications need updating.
Because of this, RISC OS separates printer drivers from editors so that they
are separate programs. This means:
(a) There is X+Y work to do
(b) If a new printer type comes along, once a printer driver has been
written for it, it will work with all applications.
This is clearly a better situation, and is one of the main reasons why
applications working together is important.
How do we achieve this? The main step is to define an interface that all
editors should use when talking to printers, a sort of "virtual printer
interface". All editors then output to this virtual interface, knowing little
of the characteristics of the physical printer itself.
The "virtual printer interface" chosen in RISC OS is to say that the printer
supports a specified subset of the screen graphics primitives. This is
because a WYSIWYG editor (where what you see on the screen is what you get on
paper) will already contain code to render the data file using screen
primitives; provided the application restricts itself to the specified
subset, printing is unlikely to require very much extra code.
There are several reasons why not all the screen primitives are supported by
the virtual printer interface. The main ones are:
(a) Some screen primitives are screen hardware specific (e.g. flashing
colours, hardware palette changes, etc.).
(b) Some screen primitives are very hard or impossible to implement on
common types of printer (e.g. PostScript printers cannot handle
non-overwriting GCOL actions).
(c) Some screen primitives - e.g. flood fill - cannot be split across
multiple boxes and so do not work with the window system. The printer
drivers use a similar interface to the window system and have the same
problems with these calls as it does.
Each printer driver is implemented as a RISC OS relocatable module, which
provides extra SWIs (system calls) concerned with starting, stopping and
controlling a print job. The interface allows the printer driver to ask the
application to render specific rectangles of the picture in any order, to
give the printer driver maximum freedom in manipulating buffer space, etc.
The interface to printer drivers means that an editor is not able to supply
an acceptable user interface for setting printer-specific options such as
quality/draft mode. For this reason, a separate application exists for each
possible printer driver, to allow any printer-specific options to be set.
The printing of plain text is such a basic facility that it is considered
unacceptable to require the loading of ArcEdit. Furthermore, printers tend to
provide a much simpler method for the printing of simple text than the
facilities provided for arbitrary graphics. For this reason, every printer
interface program provides simple facilities for the printing of plain text
files.
THE SWI INTERFACE
=================
To send output to the printer, an application must engage in a dialogue with
the printer driver. Parts of this dialogue is similar to the dialogue with
the window manager when a window requires redrawing. The dialogue can be
summarised as follows:
The application starts by opening a file to receive the printer driver's
output. Typically this file is "printer:", but any file may be used. It
passes this file's handle to SWI PDriver_SelectJob in order to start a print
job.
To output a page, the application then uses SWI PDriver_GiveRectangle to give
the printer driver a list of the rectangles it wants to appear on the page
and where it wants them to appear.
When it has specified all the rectangles it wants printed, it uses SWI
PDriver_DrawPage to ask the printer driver for the first rectangle to be
printed. It then prints this rectangle and uses SWI PDriver_GetRectangle to
get another rectangle to print, until there are no further rectangles to
print. This is very similar to the way an application uses SWI
Wimp_RedrawWindow and SWI Wimp_GetRectangle when redrawing its window.
When all the desired pages have been output in this manner, the application
first uses SWI PDriver_EndJob to end the print job, then closes the output
file.
The full set of printer driver SWIs is as follows:
SWI PDriver_Info (&80140)
-------------------------
Entry: -
Exit: R0 (top 16 bits) identifies general type of printer driven.
Current assignments:
0 = PostScript printers.
1 = FX80 and similar dot matrix printers.
R0 (bottom 16 bits) = 100 * version number of printer driver.
R1 = X pixel resolution of printer driven (pixels/inch).
R2 = Y pixel resolution of printer driven (pixels/inch).
R3 = features word:
Bit 0 set => colour
If bit 0 set, bit 1 set => full colour range not available.
Bit 2 set => only a discrete set of colours supported.
Bit 8 set => cannot handle filled shapes well.
Bit 9 set => cannot handle thick lines well.
Bit 10 set => cannot handle overwriting well.
Bit 24 set => supports the PDriver_ScreenDump call.
Bit 25 set => supports arbitrary transformations (else only
axis-preserving ones).
R4 -> adjectival description of printers supported (a maximum of 20
characters, excluding the zero-termination).
R5 = X halftone resolution (repeats/inch). If no halftoning is done,
this is equal to the value returned in R1.
R6 = Y halftone resolution (repeats/inch). If no halftoning is done,
this is equal to the value returned in R2.
R7 identifies a specific configured printer. Assignments of these
numbers are specific to each printer driver.
Some of these values can be changed by the configuration application
associated with the printer driver (using SWI PDriver_SetInfo). If SWI
PDriver_Info is called while a print job is selected, the values returned are
those that were in effect when that print job was started (i.e. when it was
first selected using PDriver_SelectJob). If SWI PDriver_Info is called when
no print job is active, the values returned are those that would be used for
a new print job.
SWI PDriver_SetInfo (&80141)
----------------------------
Entry: R1 = X pixel resolution of printer driven (pixels/inch).
R2 = Y pixel resolution of printer driven (pixels/inch).
R3 (bit 0) is zero to set monochrome, 1 to set colour. The other
bits of R3 are ignored.
R5 = X halftone resolution (repeats/inch). If no halftoning is to be
done, this should be equal to the value in R1.
R6 = Y halftone resolution (repeats/inch). If no halftoning is to be
done, this should be equal to the value in R2.
R7 identifies a specific configured printer.
Exit: -
The configuration application associated with a particular printer driver
uses this SWI to change the information values associated with subsequent
print jobs. No other application should use this SWI.
SWI PDriver_CheckFeatures (&80142)
----------------------------------
Entry: R0 = features word mask.
R1 = features word value.
Exit: If the features word that PDriver_Info would return in R3 satisfies
((features word) AND R0) = (R1 AND R0), return is normal with all
registers preserved. Otherwise a suitable error is generated, if
appropriate - e.g. no error will be generated if the printer driver
has the ability to support arbitrary rotations and your features
word value merely requests axis-preserving ones.
This call may be used by an application to check that the current printer
driver has the features it requires, and to generate a suitable descriptive
error if it doesn't.
SWI PDriver_PageSize (&80143)
-----------------------------
Entry: -
Exit: R1 = X size of paper, including margins. (Units 1/72000 inch)
R2 = Y size of paper, including margins. (Units 1/72000 inch)
R3 = left edge of printable area of paper, relative to the left edge
of the paper. (Units 1/72000 inch)
R4 = bottom edge of printable area of paper, relative to the bottom
edge of the paper. (Units 1/72000 inch)
R5 = right edge of printable area of paper, relative to the left
edge of the paper. (Units 1/72000 inch)
R6 = top edge of printable area of paper, relative to the bottom
edge of the paper. (Units 1/72000 inch)
An application can use this call to find out how big the paper in use is and
how large the printable area on the paper is. This information can then be
used to decide how to place the data to be printed on the page.
These values can be changed by the configuration application associated with
the printer driver (using SWI PDriver_SetPageSize). If SWI PDriver_PageSize
is called while a print job is selected, the values returned are those that
were in effect when that print job was started (i.e. when it was first
selected using PDriver_SelectJob). If SWI PDriver_PageSize is called when no
print job is active, the values returned are those that would be used for a
new print job.
SWI PDriver_SetPageSize (&80144)
--------------------------------
Entry: R1 = X size of paper, including margins. (Units 1/72000 inch)
R2 = Y size of paper, including margins. (Units 1/72000 inch)
R3 = left edge of printable area of paper, relative to the left edge
of the paper. (Units 1/72000 inch)
R4 = bottom edge of printable area of paper, relative to the bottom
edge of the paper. (Units 1/72000 inch)
R5 = right edge of printable area of paper, relative to the left
edge of the paper. (Units 1/72000 inch)
R6 = top edge of printable area of paper, relative to the bottom
edge of the paper. (Units 1/72000 inch)
Exit: -
The configuration application associated with a particular printer driver
uses this SWI to change the page size values associated with subsequent print
jobs. No other application should use this SWI.
SWI PDriver_SelectJob (&80145)
------------------------------
Entry: R0 = file handle for print job to be selected, or zero to cease
having any print job selected.
R1 is zero or points to a title string for the job. This title
string is terminated by any character outside the range ASCII
32-126.
Exit: R0 = file handle for print job that was previously active, or zero
if no print job was active.
A print job is identified by a file handle, which must be that of a file that
is open for output. The printer output for the job concerned is sent to this
file.
Calling SWI PDriver_SelectJob with R0=0 will cause the current print job (if
any) to be suspended, and the printer driver will cease intercepting plotting
calls.
Calling SWI PDriver_SelectJob with R0 containing a file handle will cause the
current print job (if any) to be suspended, and a print job with the given
file handle to be selected. If a print job with this file handle already
exists, it is resumed; otherwise a new print job is started. The printer
driver will start to intercept plotting calls if it is not already doing so.
Note that this call never ends a print job - to do so, use one of SWI
PDriver_EndJob and SWI PDriver_AbortJob.
The title string pointed to by R1 is treated by different printer drivers in
different ways. It is only ever used if a new print job is being started, not
when an old one is being resumed. Typical uses are:
(a) A simple printer driver might ignore it.
(b) The PostScript printer driver adds a line "%%Title: " followed by the
given title string to the PostScript header it generates.
(c) Printer drivers whose output is destined for an expensive central
printer in a large organisation might use it when generating a cover
sheet for the document.
An application is always entitled not to supply a title (by setting R1=0),
and a printer driver is entitled to ignore any title supplied.
Printer drivers may also use the following OS variables when creating cover
sheets, etc.:
PDriver$For - indicates who the output is intended to go to.
PDriver$Address - indicates where to send the output.
These variables should not contain characters outside the range ASCII 32-126.
If an error occurs during PDriver_SelectJob, the previous job will still be
selected afterwards (though it may have been de-selected and re-selected
during the call).
SWI PDriver_CurrentJob (&80146)
-------------------------------
Entry: -
Exit: R0 = file handle for print job that is currently active, or zero if
no print job is active.
SWI PDriver_FontSWI (&80147)
----------------------------
This SWI is part of the internal interface between the font system and
printer drivers. Applications should not call it.
SWI PDriver_EndJob (&80148)
---------------------------
Entry: R0 = file handle for print job to be ended.
Exit: -
This SWI should be used to end a print job normally. This may result in
further printer output - e.g. the PostScript printer driver will produce the
standard trailer comments.
If the print job being ended is the currently active one, there will be no
current print job after this call (so plotting calls will no longer be
intercepted).
If the print job being ended is not currently active, it will be ended
without altering which print job is currently active or whether plotting
calls are being intercepted.
SWI PDriver_AbortJob (&80149)
-----------------------------
Entry: R0 = file handle for print job to be aborted.
Exit: -
This SWI should be used to end a print job abnormally - it should generally
be called after fatal errors while printing. It will not try to produce any
further printer output - this is important if an error occurs while sending
output to the print job's output file.
If the print job being aborted is the currently active one, there will be no
current print job after this call (so plotting calls will no longer be
intercepted).
If the print job being aborted is not currently active, it will be aborted
without altering which print job is currently active or whether plotting
calls are being intercepted.
SWI PDriver_Reset (&8014A)
--------------------------
Entry: -
Exit: -
This SWI aborts all print jobs known to the printer driver, leaving the
printer driver with no active or suspended print jobs and ensuring that
plotting calls are not being intercepted.
Normal applications shouldn't use this SWI, but it can be useful as an
emergency recovery measure when developing an application.
A call to this SWI is generated automatically if the machine is reset or the
printer driver module is killed or RMTIDYed.
SWI PDriver_GiveRectangle (&8014B)
----------------------------------
Entry: R0 = rectangle identification word. This word is reported back to
the application when it is requested to plot all or part of
this rectangle.
R1 -> 4 word block, containing rectangle to be plotted. Units are OS
units.
R2 -> 4 word block, containing dimensionless transformation to be
applied to the specified rectangle before printing it. The
entries are given as fixed point numbers with 16 binary places,
so the transformation is:
x' = (x * R2!0 + y * R2!8)/2^16
y' = (x * R2!4 + y * R2!12)/2^16
R3 -> 2 word block, containing the position where the bottom left
corner of the rectangle is to be plotted on the printed page.
Units are 1/72000 inch.
R4 = background colour for this rectangle, in the form &BBGGRRXX.
Exit: -
This SWI allows an application to specify a rectangle from its workspace to
be printed, how it is to be transformed and where it is to appear on the
printed page. An application should make one or more calls to SWI
PDriver_GiveRectangle before a call to SWI PDriver_DrawPage and the
subsequent calls to SWI PDriver_GetRectangle. (Multiple calls allow the
application to print multiple rectangles from its workspace to one printed
page - e.g. for "two up" printing).
The printer driver may subsequently ask the application to plot the specified
rectangles or parts thereof in any order it chooses. An application should
not make any assumptions about this order or whether the rectangles it
specifies will be split. (A common reason why a printer driver might split a
rectangle is that it prints the page in strips to avoid using excessively
large page buffers.)
Assuming that a non-zero number of copies is requested and that none of the
requested rectangles go outside the area available for printing, it is
certain to ask the application to plot everything requested at least once. It
may ask for some areas to be plotted more than once, even if only one copy is
being printed, and it may ask for areas marginally outside the requested
rectangles to be plotted (this can typically happen if the boundaries of the
requested rectangles are not on exact device pixel boundaries).
If SWI PDriver_GiveRectangle is used to specify a set of rectangles that
overlap on the output page, the rectangles will be printed in the order of
the SWI PDriver_GiveRectangle calls. For appropriate printers (i.e. most
printers, but not e.g. XY plotters), this means that rectangles supplied via
later PDriver_GiveRectangle calls will overwrite rectangles supplied via
earlier calls.
SWI PDriver_DrawPage (&8014C)
-----------------------------
Entry: R0 = number of copies to print.
R1 -> 4 word block, to receive the rectangle to print.
R2 is zero or contains the page's sequence number within the
document being printed (i.e. 1-n for an n-page document).
R3 is zero or points to a string, terminated by a character in the
ASCII range 33-126 (note spaces are not allowed), which gives
the 'real' page number. (Examples: "23", "viii", "A-1")
Exit: R0 = number of copies still requiring printing. This is zero if and
only if no more plotting is required.
If R0 is non-zero, the area pointed to by R1 has been filled in with
the rectangle that needs to be plotted, and R2 contains the
rectangle identification word for the user-specified rectangle
that this is a part of.
If R0 is zero, the contents of R2 and the area pointed to by R1 are
undefined.
This SWI should be called after all rectangles to be plotted on the current
page have been specified (using SWI PDriver_GiveRectangle). It returns the
first rectangle that the printer driver wants plotted in the area pointed to
by R1. If nothing requires plotting - i.e. if there is no such rectangle - it
returns R0=0.
So the application should stop trying to plot the current page if R0=0, and
continue otherwise. If R0<>0, the fact that R0 is the number of copies still
to be printed is only intended to be used for information purposes (e.g.
putting a "Printing page m of n" message on the screen); as long as it is
non-zero, R0's value does not affect what the application should try to plot.
The information passed in R2 and R3 is not particularly important, though it
helps to make output produced by the PostScript printer driver conform better
to Adobe's structuring conventions. If non-zero values are supplied, they
should be correct. Note that R2 is NOT the sequence number of the page in the
print job, but in the document.
An example: if a document consists of 11 pages, numbered "" (the title page),
"i"-"iii" and "1"-"7", and the application is requested to print the entire
preface part, it should use R2 = 2, 3, 4 and R3 -> "i", "ii", "iii" for the
three pages.
When plotting starts in a rectangle supplied by a printer driver, the printer
driver behaves as though the VDU system is in the following state:
* VDU drivers enabled.
* VDU 5 state has been set up.
* all graphics cursor positions and the graphics origin have been set to
(0,0).
* the current dot pattern for dotted lines plotted via VDU calls is
&AA,&AA,&AA,&AA,&AA,&AA,&AA,&AA, with a repeat length of 8.
* a VDU 5 character size and spacing of 16 OS units by 32 OS units.
* the graphics clipping region has been set to bound the actual area that
is to be plotted. (But note that an application cannot read what this
area is: the printer drivers do not - and cannot - intercept
OS_ReadVduVariables or OS_ReadModeVariable.)
* the area in which plotting will actually take place has been cleared to
the background colour supplied in the corresponding PDriver_GiveRectangle
call, as though a CLG had occurred.
* the cursor movement control bits (i.e. the ones that would be set by
VDU 23,16,...) are set to &40 - i.e. cursor movement is normal, except
that movements beyond the edge of the graphics window in VDU 5 mode do
not generate special actions.
* one OS unit on the paper is 1/180 inch.
This is designed to be as similar as possible to the state set up by the
window manager when redrawing.
SWI PDriver_GetRectangle (&8014D)
---------------------------------
Entry: R1 -> 4 word block, to receive the rectangle to print.
Exit: R0 = number of copies still requiring printing. This is zero if and
only if no more plotting is required.
If R0 is non-zero, the area pointed to by R1 has been filled in with
the rectangle that needs to be plotted, and R2 contains the
rectangle identification word for the user-specified rectangle
that this is a part of.
If R0 is zero, the contents of R2 and the area pointed to by R1 are
undefined.
This SWI should be used after plotting a rectangle returned by a previous
call to SWI PDriver_DrawPage or SWI PDriver_GetRectangle, to get the next
rectangle the printer driver wants plotted. It returns precisely the same
information as PDriver_DrawPage.
SWI PDriver_CancelJob (&8014E)
------------------------------
Entry: R0 = file handle for job to be cancelled.
Exit: -
This SWI causes subsequent attempts to output to the print job associated
with the given file handle to do nothing other than generate the error "Print
job cancelled". An application is expected to respond to this error by
aborting the print job.
SWI PDriver_ScreenDump (&8014F)
-------------------------------
Entry: R0 = file handle of file to receive the dump.
Exit: -
If this SWI is supported (i.e. if bit 24 is set in the value SWI PDriver_Info
returns in R3), this SWI causes the printer driver to output a screen dump to
the file handle supplied in R0. The file concerned should be open for output.
If the SWI is not supported, an error is returned.
SWI PDriver_EnumerateJobs (&80150)
----------------------------------
Entry: R0 = 0 to get file handle of first print job, or file handle of a
print job to get the file handle of the next print job.
Exit: R0 = file handle of print job requested, or 0 if there are no more
print jobs.
This allows the print jobs that exist to be enumerated. The order in which
they appear is undefined.
SWI PDriver_SetPrinter (&80151)
-------------------------------
Entry: Printer-driver specific.
Exit: Printer-driver specific.
This allows the setting of options specific to a particular printer driver.
See the individual printer driver documentation for details.
EXAMPLE BASIC PROCEDURE
=======================
An example BASIC procedure that does a standard "two up" printing job:
DEFPROCprintout(firstpage%, lastpage%, title$, filename$)
:
REM Get SWI numbers used in this procedure.
LOCAL select%, abort%, pagesize%, giverect%, drawpage%, getrect%, end%
SYS "OS_SWINumberFromString",,"PDriver_SelectJob" TO select%
SYS "OS_SWINumberFromString",,"PDriver_AbortJob" TO abort%
SYS "OS_SWINumberFromString",,"PDriver_PageSize" TO pagesize%
SYS "OS_SWINumberFromString",,"PDriver_GiveRectangle" TO giverect%
SYS "OS_SWINumberFromString",,"PDriver_DrawPage" TO drawpage%
SYS "OS_SWINumberFromString",,"PDriver_GetRectangle" TO getrect%
SYS "OS_SWINumberFromString",,"PDriver_EndJob" TO end%
:
REM Open destination file and set up a local error handler that will
REM close it again on an error.
LOCAL H%, O%
H% = OPENOUT(filename$)
LOCAL ERROR
ON ERROR LOCAL:RESTORE ERROR:CLOSE#H%:PROCpasserror
:
REM Start up a print job associated with this file, remembering the
REM handle associated with the previous print job (if any), then set up a
REM a local error handler for it.
SYS select%,H%,title$ TO O%
LOCAL ERROR
ON ERROR LOCAL:RESTORE ERROR:SYSabort%,H%:SYSselect%,O%:PROCpasserror
:
REM Now we decide how two pages are to fit on a piece of paper.
LOCAL left%, bottom%, right%, top%
PROCgetdocumentsize(box%)
SYS pagesize% TO ,,,left%,bottom%,right%,top%
PROCfittwopages(left%,bottom%,right%,top%,box%,matrix%,origin1%,origin2%)
:
REM Start the double page loop
LOCAL page%, copiesleft%, pagetoprint%, white%
white%=&FFFFFF00
FOR page%=firstpage% TO lastpage% STEP 2
:
REM Set up to print two pages, or possibly just one last time around.
SYS giverect%, page%, box%, matrix%, origin1%, white%
IF page%<lastpage% THEN
SYS giverect%, page%+1, box%, matrix%, origin2%, white%
ENDIF
:
REM Start printing. As each printed page corresponds to two document
REM pages, we cannot easily assign any sensible page numbers to printed
REM pages. So we simply pass zeroes to PDriver_DrawPage.
SYS drawpage%,1,box2%,0,0 TO copiesleft%,,pagetoprint%
WHILE copiesleft%<>0
PROCprintpage(pagetoprint%, box2%)
SYS getrect%,,box% TO copiesleft%,,pagetoprint%
ENDWHILE
:
REM End of page loop
NEXT
:
REM All pages have now been printed. Terminate this print job.
SYS end%,H%
:
REM Go back to the first of our local error handlers.
RESTORE ERROR
:
REM And go back to whatever print job was active on entry to this
REM procedure (or to no print job in no print job was active).
SYS select%,O%
:
REM Go back to the caller's error handler.
RESTORE ERROR
:
REM Close the destination file.
CLOSE#H%
ENDPROC
:
DEFPROCpasserror
ERROR ERR,REPORT$+" (from line "+STR$(ERL)+")"
ENDPROC
This uses the following global areas of store:
box%: 4 words
box2%: 4 words
matrix%: 4 words
origin1%: 2 words
origin2%: 2 words
And the following external procedures:
DEFPROCgetdocumentsize(box%)
- fills the area pointed to by 'box%' with the size of a document page in
OS units.
DEFPROCfittwopages(l%, b%, r%, t%, box%, transform%, org1%, org2%)
- given left, bottom, right and top bounds of a piece of paper in units of
1/72000 inch, and a bounding box of a document page in OS units, sets up
a transformation and two origins in the areas pointed to by 'tr%','org1%'
and 'org2%' to print two of those pages on a piece of paper.
DEFPROCdrawpage(page%, box%)
- draw the parts of document page number 'page%' that lie with the box held
in the 4 word area pointed to by 'box%'.
If printing is likely to take a long time and the application does not want
to hold other applications up while it prints, it should regularly use a
sequence like the following during printing:
SYS select%,O%
SYS "Wimp_Poll",mask%,area% TO reason%
<process reason% as appropriate>
SYS select%,H% TO O%
THE VIRTUAL PRINTER INTERFACE
=============================
When a print job is active, the printer driver intercepts the following
vectors:
(a) WrchV (= WriteCV): all character output is received and interpreted by
the printer driver. Many VDU sequences are converted into printer
output to do similar things on the printed page. Some VDU sequences
produce errors. A few are passed through to the real VDU drivers. Only
these last go through the usual output stream selection controlled by
OS_Byte 3.
See the section entitled 'VDU SEQUENCES' below for more details.
(b) SpriteV: most sprite operations are passed on unchanged to the
SpriteExtend module and/or the operating system. Those that do sprite
plotting are intercepted and generate printer output to do similar
sprite plotting on the printed page.
Note that, because of the way vector interception is done, the
SpriteExtend module must be initialised before the printer driver.
See the section entitled 'SPRITE OPERATIONS' below for more details.
(c) DrawV: Draw calls that would not normally plot to the screen are passed
on unchanged to the Draw module. Others are intercepted and, where
possible, used to generate printer output to do similar things on the
printed page. However, some of the intercepted calls cannot be so
treated and instead produce errors.
Note that, because of the way vector interception is done, the
Draw module must be initialised before the printer driver.
See the section entitled 'DRAW MODULE CALLS' below for more details.
(d) ColourV: some ColourTrans calls are intercepted and processed by the
printer driver, others are left to be dealt with by the ColourTrans
module itself.
Note that, because of the way vector interception is done, the
ColourTrans module must be initialised before the printer driver.
See the section entitled 'COLOURTRANS MODULE CALLS' below for more
details.
(e) ByteV: The OS_Byte calls dealing with dot-dash repeat lengths (OS_Byte
163,242,0-64) are intercepted and processed by the printer driver. The
same applies to OS_Byte 218 (read/write bytes in VDU queue).
See the section entitled 'MISCELLANEOUS CALLS' below for more
details.
In addition, the font manager and the printer driver interact to cause many
of the font manager calls to be processed by the printer driver. See the
section entitled 'FONT MANAGER CALLS' below for more details.
VDU SEQUENCES
=============
General rules
-------------
Whenever a print job is active, the printer driver will intercept all
characters sent through WrchV. It will then queue them in the same way as the
VDU drivers do and process complete VDU sequences as they appear. Because the
printer driver will not pick up any data currently in the VDU queue, and may
send sequences of its own to the VDU drivers, a print job should not be
selected with an incomplete sequence in the VDU queue.
Also, because the printer driver may send sequences of its own to the VDU
drivers, the output stream specification set by OS_Byte 3 should be in its
standard state (i.e. as though set by OS_Byte 3,0).
The printer driver will pass the following VDU sequences through to the
normal VDU drivers, either because they control the screen hardware or
because they affect global resources such as the character and ECF
definitions:
VDU 7 - Produce bell sound
VDU 19,l,p,r,g,b - Change hardware palette
VDU 20 - Set default hardware palette
VDU 23,0,n,m| - "Program 6845 registers"
VDU 23,1,n| - Change cursor appearance
VDU 23,2-5,a,b,c,d,e,f,g,h - Set ECF pattern
VDU 23,9-10,n| - Set flash durations
VDU 23,11| - Set default ECF patterns
VDU 23,12-15,a,b,c,d,e,f,g,h - Simple setting of ECF pattern
VDU 23,17,4,m| - Set ECF type
VDU 23,17,6,x;y;| - Set ECF origin
VDU 23,32-255,a,b,c,d,e,f,g,h - Define character
The printer driver will interpret or fault all other VDU sequences. If the
printer driver currently wants a rectangle printed (i.e. if there has been a
call to SWI PDriver_DrawPage or SWI PDriver_GetRectangle and the last such
call returned R0 <> 0), these will result in it producing appropriate output
or errors. Otherwise, the printer driver will keep track of some state
information (e.g. what the current foreground and background colours are),
but will not produce any printer output.
The printer driver will always behave as though it is in VDU 5 state. No text
co-ordinate system is defined, and no scrolling is possible. For these
reasons, the following VDU sequences are faulted:
VDU 4 - exit VDU 5 state
VDU 23,7,m,d,z| - scroll display
VDU 23,8,t1,t2,x1,y1,x2,y2| - clear text block
It is generally meaningless to try to send or echo characters directly to the
printer while printing. Furthermore, attempts to do so are likely to disrupt
the operation of printer drivers. For these reasons, the following VDU
sequences are faulted:
VDU 1,c - send character to printer
VDU 2 - start echoing characters to printer
It is not possible to change the "mode" of a printed page, so the following
VDU sequence is faulted:
VDU 22,m - change display mode
A printer driver cannot be written to deal with undefined or reserved calls,
so the following VDU sequences are faulted:
VDU 23,18-24,... - reserved for Acorn expansion
VDU 23,28-31,... - reserved for use by applications
VDU 25,216-231,... - reserved for Acorn expansion
VDU 25,240-255,... - reserved for use by applications
The following VDU sequences are ignored, either because they normally do
nothing (at least when stuck in VDU 5 mode and not echoing characters to the
printer) or because they have no sensible interpretation when applied to
printed output rather than a screen.
VDU 0 - do nothing
VDU 3 - stop echoing characters to printer
VDU 5 - enter VDU 5 state
VDU 14 - start "paged" display
VDU 15 - end "paged" display
VDU 17,c - define text colour
VDU 23,17,5| - exchange text foreground and background
VDU 27 - do nothing
VDU 28,l,b,r,t - define text window
Colours
-------
Colours are a rather complicated matter. It is strongly recommended that
applications should use SWI ColourTrans_SetGCOL, SWI ColourTrans_SelectTable
and SWI ColourTrans_SetFontColours to set colours, as these will allow the
printer to produce as accurate an approximation as it can to the desired
colour, independently of the screen palette. The GCOL sequence (VDU 18,k,c)
should only be used if absolutely necessary, and the application writer
should be aware of the fact that the printer driver has a simplified
interpretation of the parameters, as follows:
* The fact that the background colour is affected if c >= 128 and the
foreground colour if c < 128 is unchanged.
* If k MOD 8 <> 0, subsequent plots and sprite plots will not do anything.
* If k=0, subsequent plots will cause the colour c MOD 128 (possibly
modified by the current tint) is looked up in the screen palette (at the
time of plotting, not the time the VDU 18,k,c command was issued).
Plotting is done by overwriting with the closest approximation the
printer can produce to the RGB combination found. Subsequent sprite
plotting will be done without use of the sprite's mask.
* If k=8, subsequent plots will be treated the same as k=0 above, except
that sprite plots will be done using the sprite's mask (if any).
* If k=16 or k=24, ECF pattern 1 will be read (at the time of plotting).
Each pixel value in it will be looked up as an RGB combination in the
screen's palette, and the resulting values will be averaged. Plotting
will be done with the closest approximation the printer can produce to
the resulting colour. Sprite plotting is done without using the sprite's
mask if k=16 and using it if k=24.
* The cases k=32 and k=40 are treated similarly to k=16 and k=24, except
that ECF pattern 2 is used.
* The cases k=48 and k=56 are treated similarly to k=16 and k=24, except
that ECF pattern 3 is used.
* The cases k=64 and k=72 are treated similarly to k=16 and k=24, except
that ECF pattern 4 is used.
* The cases k=80 and k=88 are treated similarly to k=16 and k=24, except
that the "giant" ECF pattern is used.
The major problems with the use of VDU 18,k,c to set colours are (a) that
it makes the printer driver output dependent on the current screen mode and
palette; (b) that it artificially limits the printer driver to the number
of colours displayed on the screen (which can be very limiting in a two
colour mode!).
Other techniques that depend on GCOLs (e.g. SWI Font_SetFontColours,
colour-changing sequences in strings passed to Font_Paint, plotting sprites
without a translation table, etc.) have the same problems and are similarly
not recommended.
No operations other than overwriting are permitted, mainly because they
cannot be implemented on many common printers (e.g. PostScript printers).
The treatment of ECF patterns is only intended to allow them to be used to
"mix" colours. (Allowing genuine pattern printing is a possible area for
future printer driver development.)
Note that the printer driver maintains its own foreground and background
colour information. The screen foreground and background colours are not
affected by VDU 18,k,c sequences encountered while a print job is active.
Similarly, VDU 23,17,2-3,t| sequences encountered while a print job is active
do not affect the screen tints, just the printer driver's own tints. VDU
23,17,0-1,t| sequences would only affect the colours of the text tints, so
the printer driver ignores them.
Other graphics state operations
-------------------------------
The VDU 6 and VDU 21 sequences have their normal effects of enabling and
disabling execution (but not parsing) of subsequent VDU sequences. As usual,
the printer driver keeps track of this independently of the VDU drivers.
The cursor movement VDU sequences (i.e. VDU 8-11, VDU 13, VDU 30 and VDU
31,x,y) all update the current graphics position (without updating the
previous graphics positions used in e.g. triangle plotting), precisely as
they do in VDU 5 mode on the screen.
VDU 24,l;b;r;t; will set the printer driver's graphics clipping box. The
rectangle specified should lie completely within the box that was reported on
return from the last call to SWI PDriver_DrawPage or SWI
PDriver_GetRectangle. If this is not the case, it is not defined what will
happen, and different printer drivers may treat it in different ways. This is
analogous to the situation with the window manager: attempts to set a
graphics clipping box outside the rectangle currently being redrawn may be
ignored completely (if they go outside the screen) or may get obeyed (with
consequences that are almost certainly wrong!).
VDU 29,x;y; sets the printer driver's graphics origin.
VDU 26 will reset the printer driver's graphics clipping box to its maximum
size (this is essentially the box reported on return from the last call to
SWI PDriver_DrawPage or SWI PDriver_GetRectangle, but may be slightly
different due to rounding problems when converting from a box expressed in
printer pixels to one expressed in OS units). It also resets its versions of
the graphics origin, the current graphics position and all the previous
graphics positions to (0,0).
VDU 23,6,a,b,c,d,e,f,g,h will set the printer driver's current dot pattern
(for use with lines plotted via VDU 25,16-31,x;y; and VDU 25,48-63,x;y;). The
exact lengths of the dashes and gaps produced may differ between various
printer drivers, and also between the screen and printer drivers, so an
application should not rely on them. However, an application can reasonably
expect each set bit in the pattern to correspond to approximately 2 to 3 OS
units on the printed page.
VDU 23,16,x,y| changes the printer driver's version of the cursor control
flags, and thus how the cursor movement control sequences and BBC-style
character plotting affect the current graphics position. As usual, this is
completely independent of the corresponding flags in the VDU drivers.
However, printer drivers pay no attention to the setting of bit 6 (which
controls whether movements beyond the edge of the graphics window cause
carriage return/line feeds and other cursor movements to be generated
automatically) - they always behave as though it is set. Note that the
Wimp normally sets this bit, and that it is not sensible to have it clear
at any time during a Wimp redraw.
VDU 23,17,7,flags,x;y;| changes the printer driver's version of the size that
BBC-style characters are to be plotted and the spacing that is required
between them. Setting the VDU 4 character size cannot possibly affect the
printer driver's output and so will be ignored completely. As noted below
under 'Plotting operations', a "pixel" is regarded as the size of a screen
pixel for the screen mode that was in effect when the print job was started.
Plotting operations
-------------------
The printer driver regards a "pixel" as having size 2 OS units square (1/90
inch square). The main effect of this is that all PLOT line, PLOT point and
PLOT outline calls will produce lines that are approximately 2 OS units
wide.
However, when translating the character size and spacing information provided
by VDU 23,17,7,... (see above) from pixels to OS units, the screen pixel size
for the screen mode that was in effect when the print job was started is
used. This is done in the expectation that the application is basing its
requested sizes on that screen mode.
The following VDU sequences perform straightforward plotting operations;
printer drivers will produce the corresponding printed output:
VDU 12 - clear graphics window (in VDU 5 state)
VDU 16 - clear graphics window
VDU 25,0-63,x;y; - draw line
VDU 25,64-71,x;y; - draw point
VDU 25,80-87,x;y; - fill triangle
VDU 25,96-103,x;y; - fill axis-aligned rectangle
VDU 25,112-119,x;y; - fill parallelogram
VDU 25,144-151,x;y; - draw circle
VDU 25,152-159,x;y; - fill circle
VDU 25,160-167,x;y; - draw circular arc
VDU 25,168-175,x;y; - fill circular segment
VDU 25,176-183,x;y; - fill cicular sector
VDU 25,192-199,x;y; - draw ellipse
VDU 25,200-207,x;y; - fill ellipse
VDU 32-126 - print characters in BBC-style font
VDU 127 - backspace & delete
VDU 128-255 - print characters in BBC-style font
One difference to note is that most printer drivers will either not do the
rounding to pixel centres normally done by the VDU drivers, or will round to
different pixel centres (probably the centres of their device pixels).
The following VDU sequences are faulted because they cannot be split up
easily across rectangles, and also because they depend on the current picture
contents and so cannot be implemented e.g. on PostScript printers:
VDU 25,72-79,x;y; - horizontal line fill (flood fill primitive)
VDU 25,88-95,x;y; - horizontal line fill (flood fill primitive)
VDU 25,104-111,x;y; - horizontal line fill (flood fill primitive)
VDU 25,120-127,x;y; - horizontal line fill (flood fill primitive)
VDU 25,128-143,x;y; - flood fills
VDU 25,184-191,x;y; - copy/move rectangle
Exception: VDU 25,184,x;y; and VDU 25,188,x;y; are now correctly interpreted
by printer drivers (as being equivalent to VDU 25,0,x;y; and VDU 25,4,x;y;
respectively).
The sprite plotting sequences (VDU 23,27,m,n| and VDU 25,232-239,x;y;) are
converted to the appropriate calls to SWI OS_SpriteOp. These calls will then
be intercepted as normal by the printer driver (see under 'SPRITE OPERATIONS'
below). In addition, the VDU 25,232-239,x;y; sequence causes the printer
driver's graphics position to be updated. Application writers should use
direct calls to SWI OS_SpriteOp in preference to these sequences.
The font manager VDU sequences (VDU 23,25,a,b,c,d,e,f,g,h,
VDU 23,26,a,b,c,d,e,f,g,h,text and VDU 25,208-215,x;y;text) are trapped by
the printer driver and converted into the corresponding font manager SWIs.
These are then handled as normal (see under 'FONT MANAGER CALLS' below). In
addition, the VDU 25,208-215,x;y;text sequence causes the printer driver's
current graphics position to be updated. Again, application writers are
strongly recommended to use the font manager SWIs in preference to these VDU
sequences.
SPRITE OPERATIONS
=================
Printer drivers intercept OS_SpriteOp via the SpriteV vector. Most calls are
simply passed through to the operating system or the SpriteExtend module. The
ones that normally plot to the screen are generally intercepted and used to
generate printer output by the printer driver.
The following reason codes normally involve reading or writing the screen
contents and are not straightforward sprite plotting operations. Because some
printer drivers redirect output to a sprite internally, it is unknown what
the "screen" is during these operations. They are therefore faulted.
2 - screen save
3 - screen load
14 - get sprite from current point on screen
16 - get sprite from specified point on screen
Reason codes that are passed through to the operating system or the
SpriteExtend module are:
8 - read sprite area control block
9 - initialise sprite area
10 - load sprite file
11 - merge sprite file
12 - save sprite file
13 - return name of numbered sprite
15 - create sprite
25 - delete sprite
26 - rename sprite
27 - copy sprite
29 - create mask
30 - remove mask
31 - insert row
32 - delete row
33 - flip about X axis
35 - append sprite
36 - set pointer shape
40 - read sprite size
41 - read pixel colour
42 - write pixel colour
43 - read pixel mask
44 - write pixel mask
45 - insert column
46 - delete column
47 - flip about Y axis
62 - read save area size
The following reason code is passed through to the operating system. In
addition, the printer driver remembers the sprite selected so that VDU
25,232-239,x;y; sequences can be correctly converted to SWI OS_SpriteOp
calls.
24 - select sprite
The following reason codes plot a sprite or its mask, and are converted into
appropriate printer output:
28 - plot sprite at current point on screen
34 - plot sprite at specified point on screen
48 - plot mask at current point on screen
49 - plot mask at specified point on screen
50 - plot mask at specified point on screen, scaled
51 - plot character, scaled
52 - plot sprite at specified point on screen, scaled
53 - plot sprite at specified point on screen, grey scaled
As usual for a printer driver, only some GCOL actions are understood. If the
GCOL action is not divisible by 8, nothing is plotted. If it is divisible by
8, the "overwrite" action is used. If it is divisible by 16, the sprite is
plotted without using its mask; otherwise the mask is used.
The colours used to plot sprite pixels are determined as follows:
* If the call does not allow a pixel translation table, or if no
translation table is supplied, the current screen palette is consulted to
find out what RGB combination the sprite pixel's value corresponds to.
The printer driver then does its best to produce that RGB combination.
Use of this option is not really recommended.
* If a translation table is supplied with the call, the printer driver
assumes that the table contains code values allocated by one of:
SWI ColourTrans_SelectTable with R2 = -1
SWI ColourTrans_ReturnColourNumber
SWI ColourTrans_ReturnColourNumberForMode with R1 = -1
SWI ColourTrans_ReturnOppColourNumber
SWI ColourTrans_ReturnOppColourNumberForMode with R1 = -1
It can therefore look up precisely which RGB combination is supposed to
correspond to each sprite pixel value. Because of the variety of ways in
which printer drivers can allocate these values, the translation table
should always have been set up in the current print job and using these
calls.
If a sprite is printed unscaled, its size on the printed output is the same
as its size would be if it were plotted to the screen in the screen mode that
was in effect at the time that the print job concerned was started. If it is
printed scaled, the scaling factors are applied to this size. This is one of
the few ways in which the printed output does depend on this screen mode (the
main other ones are in interpreting GCOL and TINT values, and in interpreting
VDU 5 character sizes). It is done this way in the expectation that the
application is scaling the sprite for what it believes is the current screen
mode.
Finally, the following two reason codes are intercepted to keep track of
whether plotting output is currently supposed to go to a sprite or to the
screen. If it is supposed to go to a sprite, it really will go to that sprite
- this allows applications to create sprites normally while printing. If it
is supposed to go to the screen, it will be processed by the printer driver.
(Note that printer drivers that redirect output to a sprite internally will
treat this case specially, regarding output as still being destined for the
screen!)
60 - switch output to sprite
61 - switch output to mask
DRAW MODULE CALLS
=================
Printer drivers intercept the DrawV vector and re-interpret those calls whose
purpose is to plot something on the screen, producing appropriate printer
output instead. There are a number of restrictions on the calls that can be
dealt with, mainly due to the limitations of PostScript. Most of the
operations that are disallowed are not particularly useful, fortunately.
Note that the Draw module calls normally use the graphics foreground colour
to plot with and the graphics origin. The printer driver uses its versions of
these values. In particular, this means that the fill colour is subject to
all the restrictions noted elsewhere in this document.
The floating point Draw module calls are not intercepted at present. If and
when the Draw module is upgraded to deal with them, printer drivers will be
similarly upgraded.
SWI Draw_Fill
-------------
Printer drivers can deal with most common calls to this SWI. The
restrictions are:
(a) They cannot deal with fill styles that invoke the positive or negative
winding number rules - i.e. those with bit 0 set.
(b) They cannot deal with a fill style which asks for non-boundary exterior
pixels to be plotted (i.e. which have bit 2 set). Exception: they can
deal with the trivial case in which all of bits 2-5 are set - i.e. if
all pixels in the plane are to be plotted!
(c) They cannot deal with the following values for bits 5-2:
0010 - plot exterior boundary pixels only.
0100 - plot interior boundary pixels only.
1010 - plot exterior boundary and interior non-boundary pixels only.
(d) An application should not rely on there being any difference between
what is printed for the following three values of bits 5-2:
1000 - plot interior non-boundary pixels only.
1100 - plot all interior pixels.
1110 - plot all interior pixels and exterior boundary pixels.
(A printer driver will generally try its best to distinguish these, but
it may not be possible.)
SWI Draw_Stroke
---------------
Again, most common calls to this SWI can be dealt with. The restrictions
on the parameters depend on whether the specified thickness is zero or not:
If the specified thickness is zero, the restrictions are:
(a) Printer drivers cannot deal with a fill style with bits 3-2 equal to 01
- i.e. one that asks for pixels lying on the stroke to be plotted and
those that lie off the stroke not to be.
(b) Most printer drivers will not pay any attention to bit 31 of the fill
style - the one that distinguishes plotting the stroke subpath by
subpath from plotting it all at once.
If the specified thickness is non-zero, the restrictions are:
(a) All the restrictions mentioned under SWI Draw_Fill above.
(b) They cannot deal with bits 5-2 being 0110 - i.e. asking for just the
boundary pixels of the resulting filled path to be plotted.
(c) Most printer drivers will not pay any attention to bit 31 of the fill
style - the one that distinguishes plotting the stroke subpath by
subpath from plotting it all at once.
SWI Draw_StrokePath, SWI Draw_FlattenPath and SWI Draw_TransformPath
--------------------------------------------------------------------
None of these do any plotting; they are all dealt with in the normal way by
the Draw module.
SWI Draw_ProcessPath
--------------------
This SWI is faulted if R7=1 (fill path normally) or R7=2 (fill path subpath
by subpath) on entry. Use the appropriate one of Draw_Fill or Draw_Stroke if
you want to produce printed output. If the operation you're trying to do is
too complicated for them, it almost certainly cannot be handled by e.g. the
PostScript printer driver.
All other values of R7 correspond to calls that don't do any plotting and are
dealt with in the normal way by the Draw module. If you're trying to do
something complicated and you've got enough workspace and RMA, a possible
useful trick is to use SWI Draw_ProcessPath with R7 pointing to an output
buffer, followed by SWI Draw_Fill on the result.
COLOURTRANS MODULE CALLS
========================
The printer driver intercepts calls to the ColourTrans module, via the
ColourV vector. Most of them are passed straight on to the ColourTrans module
- the exceptions are:
SWI ColourTrans_SelectTable with R2 = -1
----------------------------------------
Each RGB combination in the source palette (or implied by it in the case of
256 colour modes) is converted into a colour number as though by SWI
ColourTrans_ReturnColourNumber (see below). The resulting values are placed
in the table.
SWI ColourTrans_SetGCOL
-----------------------
The printer driver's version of the foreground or background colour (as
appropriate) is set. The GCOL actions are interpreted precisely as for the
VDU 18,k,c call (see above). However, rather than looking up a GCOL in the
screen palette at plot time, the exact RGB combination specified in this call
is remembered and used (as accurately as the printer will render it) at plot
time.
After this has been done, the call is effectively converted into SWI
ColourTrans_ReturnGCOL and passed down to the ColourTrans module in order to
set the information returned correctly. Note that this implies that
subsequently using the GCOL returned in a VDU 18,k,c sequence will not
produce the same effect on the colour as this call: it will merely produce
the best approximation the printer can manage to the best approximation the
current screen palette can manage to the specified RGB combination. It is
therefore probably a bad idea to use the values returned.
This call therefore allows the application to make full use of a printer's
colour resolution without having to switch to another screen mode or mess
around with the screen's palette, and without worrying about the effects of a
change in the screen's palette. It is therefore the recommended way to set
the foreground and background colours.
SWI ColourTrans_ReturnColourNumber
----------------------------------
This will return a code value (in the range 0-255) that identifies the
specified RGB combination as accurately as possible to the printer driver.
How this code value is determined may vary from printer driver to printer
driver, and indeed even from print job to print job for the same printer
driver. An application should therefore not make any assumptions about what
these code values mean.
(Most printer drivers implement this by pre-allocating some range of code
values to evenly spaced RGB combinations, then adopting the following
approach:
(a) If the RGB combination is already known about, return the
corresponding code value.
(b) If the RGB combination is not already known about and some code values
are still free, allocate one of the unused code values to the new RGB
combination and return that code value.
(c) If the RGB combination is not already known about and all code values
have been allocated, return the code number whose RGB combination is
as close as possible to the desired RGB combination.
The pre-allocation of evenly spaced RGB combinations will ensure that even
case (c) does not have really terrible results.)
SWI ColourTrans_ReturnColourNumberForMode with R1 = -1
------------------------------------------------------
This is treated exactly the same as SWI ColourTrans_ReturnColourNumber above.
SWI ColourTrans_SetOppGCOL
--------------------------
This behaves like ColourTrans_SetGCOL above, except that the RGB combination
it remembers is the furthest possible RGB combination from the one actually
specified in R0, and it ends by being converted into a call to
ColourTrans_ReturnOppGCOL. Note that there is no guarantee that the GCOL
returned is anywhere near the RGB combination remembered!
SWI ColourTrans_ReturnOppColourNumber
-------------------------------------
This behaves exactly as though ColourTrans_ReturnColourNumber (see above) had
been called with R0 containing the furthest possible RGB combination from the
one actually specified.
SWI ColourTrans_ReturnOppColourNumberForMode with R1 = -1
---------------------------------------------------------
This behaves exactly as though ColourTrans_ReturnColourNumberForMode (see
above) had been called with R1 = -1 and R0 containing the furthest possible
RGB combination from the one actually specified.
SWI ColourTrans_SetFontColours
------------------------------
The printer driver's version of the font colours is set, to as accurate a
representation of the desired RGB combinations as the printer can manage.
After this has been done, the call is effectively converted into SWI
ColourTrans_ReturnFontColours and passed down to the ColourTrans module in
order to set the information returned correctly. Note that this implies that
subsequently using the values returned in a SWI Font_SetFontColours call will
not produce the same effect on the font colours as this call: it will merely
produce the best approximations the printer can manage to the best
approximations the current screen palette can manage to the specified RGB
combinations. It is therefore probably a bad idea to use the values returned.
This call therefore allows the application to make full use of a printer's
colour resolution without having to switch to another screen mode or mess
around with the screen's palette, and without worrying about the effects of a
change in the screen's palette. It is the recommended way to set the font
colours.
FONT MANAGER CALLS
==================
The printer driver interacts with the font manager (via a service call and
SWI PDriver_FontSWI) in such a way that when it is active, calls to the
following SWIs are processed by the printer driver:
SWI Font_Paint
SWI Font_LoseFont
SWI Font_SetFontColours
SWI Font_SetPalette
This enables the printer driver to make SWI Font_Paint produce printer output
rather than affecting the screen.
The use of SWI Font_SetFontColours is not recommended, as it results in the
setting of colours that depend on the current screen palette. Instead, use
SWI ColourTrans_SetFontColours to set font colours to absolute RGB values.
Similarly, the use of colour-changing control sequences in strings passed to
SWI Font_Paint is not recommended.
In addition to the control sequences allowed by current font managers,
printer drivers will be able to handle the following control sequence if
the font manager they are working with can:
19,background red,green,blue,foreground red,green,blue,maximum offset
This gives a way of changing colour in the middle of a string without
sacrificing colour resolution.
(How exactly it does this varies quite markedly between printer drivers: for
instance, most dot matrix printer drivers will probably use the font manager
to write into the sprite they are using to hold the current strip of printed
output, while the PostScript printer driver uses the PostScript prologue to
define a translation from font manager font names to printer fonts.)
MISCELLANEOUS CALLS
===================
OS_Byte 163,242,0-64 are intercepted to set the printer driver version of the
dot pattern repeat length instead of the VDU drivers' version.
OS_Byte 218 is intercepted to act on the printer driver's VDU queue instead
of the VDU drivers' version.
It should be noted that most of the informational calls associated with the
VDU drivers (and OS_ReadVduVariables in particular) will produce undefined
results when a printer driver is active. These results are likely to differ
between printer drivers (in particular, they will vary according to whether
the printer driver plots to a sprite internally and if so, how large the
sprite concerned is).
The only informational calls that the application may rely upon are:
OS_Word 10 - used to read character and ECF definitions.
OS_Word 11 - used to read palette definitions.
OS_ReadPalette - used to read palette definitions.
OS_Byte 218 - when used to read the number of bytes in the VDU queue.