diff options
Diffstat (limited to 'gs/contrib/pcl3/doc/notes.tex')
-rw-r--r-- | gs/contrib/pcl3/doc/notes.tex | 2052 |
1 files changed, 0 insertions, 2052 deletions
diff --git a/gs/contrib/pcl3/doc/notes.tex b/gs/contrib/pcl3/doc/notes.tex deleted file mode 100644 index 33baebcae..000000000 --- a/gs/contrib/pcl3/doc/notes.tex +++ /dev/null @@ -1,2052 +0,0 @@ -%****************************************************************************** -% File: @(#)$Id: notes.tex,v 1.11 2001/02/24 06:00:16 Martin Rel $ -% Contents: Notes an writing a ghostscript device driver -% This is a TeX file using the LaTeX package. -% Author: Martin Lottermoser, Greifswaldstrasse 28, 38124 Braunschweig, -% Germany. E-mail: Martin.Lottermoser@t-online.de. -% -%****************************************************************************** -% -% Copyright (C) 2000, 2001 by Martin Lottermoser -% All rights reserved -% -%****************************************************************************** - -\documentclass[twoside,a4paper]{article} - -% Macros to extract RCS information -\def\RCScontents$#1:#2 ${\ignorespaces#2} -\def\RCSDate$#1: #2/#3/#4 #5${#2--#3--#4} - -% Extracted RCS information. -\setbox0=\hbox{\RCScontents$Locker: $} -\ifdim\wd0=0pt - \edef\Revision{\RCScontents$Revision: 1.11 $} - \edef\Date{\RCSDate$Date: 2001/02/24 06:00:16 $} - \def\BottomInfo{Version \Revision} -\else - \edef\Revision{\RCScontents$Revision: 1.11 $+} - \def\Date{\today} - \def\BottomInfo{Version of \Date} - \def\draft{} -\fi - -% Title page information -\author{Martin Lottermoser\cr - {\tt Martin.Lottermoser@t-online.de}\cr - Greifswaldstra{\ss}e 28\cr - 38124 Braunschweig\cr - Germany} -\title{Notes on Writing a {\it Ghostscript\/} Device Driver for Printers} -\date{Version \Revision\ (\Date)} - -% 25mm margins for A4 -\textwidth=160truemm -\evensidemargin=-0.4truemm \oddsidemargin=\evensidemargin -\topmargin=-0.4truemm -\textheight=247truemm -\advance\textheight by -\headheight -\advance\textheight by -\headsep -\advance\textheight by -\footskip - -% Page layout -\pagestyle{myheadings} -\makeatletter -\markboth{\@title}{\@title} -\def\@oddfoot{{\tiny\sl \BottomInfo\/}\hfil} -\makeatother - -% Paragraph layout -\setlength{\parindent}{0mm } -\setlength{\parskip}{1.5mm plus 0.5mm minus 0.5mm } - -%****************************************************************************** - -% Normal underscore -\catcode`\_=\active -\newcommand{\normalUS}{\catcode`\_=\active \def_{\char`\_}} -\catcode`\_=8 - -% My version of LaTeX does not know that cmtt has braces and substitutes them -% from cmsy. -\newcommand{\lb}{\char"7B} -\newcommand{\rb}{\char"7D} - -% Abbreviations -\newcommand{\gs}{\textit{ghostscript\/}} -\newcommand{\Gs}{\textit{Ghostscript\/}} - -% Markup -\newenvironment{note}{\begin{quote}\small}{\end{quote}} -\newenvironment{program}{\begin{quote} - \normalUS\ttfamily\obeylines\obeyspaces\parskip=0mm \parindent=0mm }% - {\end{quote}} -\newcommand{\ps}[1]{{\sffamily\bfseries #1}} % PostScript names in the text -\renewcommand{\d}[1]{{\bfseries #1}} % definition of a concept or name -\newcommand{\prog}[1]{\texttt{#1}} -\newcommand{\file}[1]{\texttt{#1}} % file names - -\bibliographystyle{plain} - -\hyphenation{ghost-script} - -\newif\ifdraft \draftfalse -\expandafter\ifx\csname draft\endcsname\relax\else \drafttrue \fi - -%****************************************************************************** - -\begin{document} -\maketitle - -\tableofcontents - -%****************************************************************************** - -\section{Introduction} - -This document contains remarks which I consider useful for persons implementing -a \gs\ device driver for printers. -It is based on my experiences and in particular the mistakes I made in -implementing the \textit{hpdj/pcl3\/} driver~\cite{hpdj,pcl3}. -And yes, I have made lots of mistakes, -and I do not guarantee anything about the accuracy of this document either. - -The topics covered in this document can be arranged in the following -categories: -\begin{itemize} - \item Suggestions on how to approach the implementation of a \gs\ device - driver - \item Information which is in my opinion necessary for properly implementing - a driver but which I could not find in \gs's documentation - \item Information I have collected for convenience - \item Parts which logically belong into the design documentation for - the \textit{hpdj/pcl3\/} driver but which have wider applicability -\end{itemize} - -As the title indicates, -this is not an exhaustive introduction on how to write a \gs\ device driver. -You will need to access other documentation as well -(and, of course, do some thinking of your own), -preferably before reading this paper. - -This document is still largely incomplete. %??? - -%============================================================================== - -\subsection{The Most Important Advice on Writing a \Gs\ Device Driver} - -\begin{center} - \bigskip - \begin{picture}(120, 30) - \put(60,15){\oval(120,30)} - \put(60,15){\makebox(0,0){\hfil\Large\em Don't do it!\/\hfil}} - \end{picture} - \bigskip -\end{center} - -You should disregard this advice only if all of the following conditions are -true: -\begin{itemize} - \item You are prepared to spend a substantial amount of time on this task. - \item You have or are prepared to acquire sufficient knowledge of PostScript - to find relevant information in the - {\it PostScript Language Reference\/}~\cite{PostScript3}, - hereafter abbreviated as ``PLR3''. - You must know chapters~6 and~7 (excluding sections~6.3 and~7.1) pretty well. - \item You either know \gs's internal APIs (in particular~\cite{Drivers6.01}) - and programming conventions or are prepared to learn them. - (Obvious, of course, but I still thought I'd better mention it.) - \item You can read large amounts\footnote{% - % Aladdin gs 5.50: 243089 lines for *.c and *.h, 32914 for *.ps. - % loc gave 168705 NLOC for *.c and *.h. - \Gs\ has roughly 250,000~lines of C and 33,000~lines of PostScript - code~[gs~5.50].} - of source code (C and PostScript) written by another person and - locate and understand those sections which are relevant to a problem you - have encountered. - If you wish to write a reliable driver, - you will have to do this much more often than you expect. - \item In view of in particular the amount of time you will have to spend and - the amount of frustration you will experience, - the driver you have in mind will offer new functionality which is worth - this effort. - I would not expect this to be the case unless you have a sufficiently large - group of users. -\end{itemize} -If you conclude from this that my own experiences in writing \gs\ device -drivers were not entirely pleasant, you are right. -In particular, -I have serious doubts about whether the result justifies the effort I put into -it. -This document is an attempt to improve the result-to-effort ratio by making -my experience available to others. - -%============================================================================== - -\subsection{Restrictions} - -This document concerns itself only with printer drivers. -By this I mean devices with the following properties: -\begin{itemize} - \item From the point of view of PostScript, we are dealing with a page device. - \item Processing in the driver can be split into two phases: - \begin{itemize} - \item creating a rasterized representation (pixmap) of the entire page in - memory, - \item converting it into another format appropriate for a particular kind - of hardware or software external to \gs, and - sending the converted data to a file. - \end{itemize} - \item From the point of view of \gs, we are dealing with a device derived - from the {\it prn\/} device. -\end{itemize} - -%============================================================================== - -\subsection{Conventions} - -A word or group of words \d{in this type} has a special meaning. -The meaning is sometimes explained at the point where the term is denoted in -this manner, -but the main purpose is to alert the reader to the existence of a special -meaning connected with these words in the context of PostScript or \gs. - -A reference like ``[gs~$n.m$]'' accompanying a statement means that I have -checked this statement to be true for \gs\ version~$n.m$. -These are typically statements about bugs in \gs\ or -information I could not find in \gs's documentation -but which I obtained from the source code or by experiment. - -%****************************************************************************** - -\section{General Approach} - -%============================================================================== - -\subsection{PostScript First} - -You should base your implementation on those properties of your driver which -will be visible in PostScript. - -One reason is that \gs\ is changing fairly rapidly. -Although some effort is made to remain backward-compatible, -you cannot expect this to be always possible. -If you base your design on PostScript concepts, -the result is much more likely to be able to adapt easily to changes in \gs. -The same applies in areas where \gs\ does not yet correctly or entirely support -the PostScript language definition. - -The second reason is that the PostScript language is well documented and offers -a reasonably broad range of concepts for you to use. -A description of similar coverage at the level of \gs's driver API does not -exist. -You will have to fill conceptual gaps in the latter from the former. - -Finally, you should not dismiss the possibility that you might later want to -write a similar driver for another PostScript interpreter. -Everything which depends on PostScript only could then be reused unchanged, -although I would expect this to happen more on the level of structure and -concepts then with actual lines of code. - -%============================================================================== - -\subsection{Architecture} - -It is almost certain that you'll find that a large part of what you need to -implement is entirely independent of the printer you wish to drive -and could be used for other drivers as well. -This is due to a gap between the functionality offered by the \gs\ kernel and -the functionality needed by most printer drivers. -This gap is only partly closed by the abstract \textit{prn\/} device -and this has led to a certain amount of duplicated code in \gs\ drivers. - -One solution to this problem is to reuse code from another driver. -This is easiest to do if this functionality has been implemented in terms of an -abstract \gs\ device derived from the \textit{prn\/} device. -Your driver can then use this device instead of \textit{prn\/} as its base -device. -The \textit{pcl3\/} driver contains such an intermediate component in the -\textit{eprn\/} (``extended \textit{prn\/}'') device. -Its implementation has about -4700~brutto and 2400~netto lines of code. % pcl3 3.0.2 -This gives you an impression of the size of the functionality gap you would -otherwise have to bridge on your own, -although admittedly not everything implemented in \textit{eprn\/} is -absolutely essential for every printer driver. - -Independent of whether \textit{eprn\/} suits your needs or not, -you should always implement the universal part of your functionality -in a reusable form. - -At the other end of your implementation you should consider encapsulating -printer-specific routines in a form which is largely independent of \gs. -This also makes it easier to reuse this code in other contexts. -The correct level of abstraction for this API is almost certainly near the -point where your driver has obtained a pixmap for the page to be printed and -has to convert it into the printer's language. - -If you introduce these two layers of functionality, -the ``real'' driver will just be the intermediate layer connecting these two. -\begin{note} - In the implementation of my \textit{pcl3\/} driver about - 47~\% of the code belongs to the high-level \textit{eprn\/} device, - 21~\% can be found in the printer-specific backend, - and 32~\% are contained in the intermediate layer. - % This is based on NLOCs. BLOC-based values are even better: 49%, 24%, and - % 27%. This reflects the more extensive documentation I've provided in the - % reusable parts. - % (BLOC, NLOC) as of pcl3 3.0.2: (4658, 2361), (2263, 1084), (2620, 1616). - This means that roughly two thirds of the code could be reused - in other contexts! -\end{note} - -%****************************************************************************** - -\section{Properties of an Output Device in PostScript} - -%============================================================================== - -\subsection{Definition} - -A PostScript interpreter may support several \d{output devices}. -A \d{page device} is a special kind of output device. -Its state is characterized by \d{page device parameters}. - -The \d{current (output) device} is part of the graphics state and can be -inspected with \ps{currentpagedevice}. -A new page device can be selected by calling \ps{setpagedevice}% - \footnote{% - For devices which are not page devices, other methods have to be - employed. - The null device, for example, is installed by calling \ps{nulldevice}.} -and passing the device name as a value for the \ps{OutputDevice} page device -parameter.% - \footnote{% - This does work with \gs\ but it produces a drastically reduced page device - dictionary without, e.g., \ps{HWResolution}~[gs~5.50, gs~6.50]. - The official \gs\ interface for switching output devices from PostScript - is via the non-standard \ps{selectdevice} operator~\cite{Use5.50}.} -This resets all page device parameters to the default values appropriate for -the new device. - -%============================================================================== - -\subsection{Identity and Basic Properties} - -An output device is identified by its name. -If the interpreter supports several output devices, -the \ps{OutputDevice} resource category should contain an entry for each device, -indexed by its name and listing the associated properties in an -\d{output device dictionary}.% - \footnote{\Gs\ does not list its available devices in the \ps{OutputDevice} - resource category~[gs~5.50, gs~6.50]. - Furthermore, although defining an output device dictionary as an external - resource makes it visible to \ps{resourcestatus} and \ps{findresource}, - \gs\ versions before~6.50 will not list it with \ps{resourceforall} unless - you execute \ps{findresource} first~[gs~5.50, gs~6.01]. - This makes \ps{resourceforall} useless. - However, you can obtain the list of supported devices from \gs's - non-standard \ps{devicenames} operator. - } -Section~6.4 of PLR3 contains a list of these properties: -\begin{itemize} - \item media classes - \item page sizes - \item resolutions - \item process colour models - \item trapping details dictionary types -\end{itemize} -It is possible (but there is no corresponding statement in PLR3) -that a PostScript program relies on the assumption that, -if a value is listed as supported, -it is supported independent of the values chosen for other parameters -unless the meaning of the property in question restricts it explicitly to a -particular situation (this is only the case for \ps{DeviceN}). -This is a possible rule for separating output devices. - -Therefore, if you have constraints among the values you wish to support -(e.g., \ps{DeviceGray} can be used at 600\,ppi but \ps{DeviceCMYK} is only -possible at 300\,ppi), -you should consider implementing these groups of unconstrained values -in different output devices. -This might be inconvenient, though, -and I myself have usually disregarded this advice. - -%============================================================================== - -\subsection{Process Colour Models} - -PostScript defines six \d{process colour models}: -\begin{quote} - \ps{DeviceGray}, - \ps{DeviceRGB}, \ps{DeviceRGBK}, - \ps{DeviceCMY}, \ps{DeviceCMYK}, - \ps{DeviceN}. -\end{quote} -A process colour model defines the \d{colorants} used by a device. -\ps{DeviceN} is a parameterized process colour model which has to be -supplemented by an explicit list of colorants (page device parameter -\ps{SeparationColorNames}). -Normally each device has one \d{native process colour model}, -but it may support others.\footnote{ - For example, a monochrome device capable of producing separations might - support the process colour model - \ps{DeviceCMYK}~\cite[page~424]{PostScript3}.} - -Each process colour model has an underlying \d{native colour space}. -Because some process colour models are based on the same colour space -only the following four colour spaces act as native colour spaces: -\begin{quote} - \ps{DeviceGray}, - \ps{DeviceRGB}, - \ps{DeviceCMYK}, - \ps{DeviceN}. -\end{quote} -The colour spaces \ps{DeviceGray}, \ps{DeviceRGB}, and \ps{DeviceCMYK} are -called \d{device colour spaces}. -The colour space \ps{DeviceN} is \emph{not\/} a device colour space -but one of the \d{special colour spaces}. - -Note that a designation like ``\ps{DeviceRGB}'' can therefore denote a -colour space, a native colour space or a process colour model. -You have to find out which before you will be able to correctly understand -the statement containing such a name. - -%============================================================================== - -\subsection{Media Selection} - -\subsubsection{Media Sources} - -PostScript assumes the output device to have several \d{media sources}, -each identified by an integer (\d{position number}). -You will have to decide how to associate these numbers with input trays or -whatever your printer supports. - -Properties of the media currently present in a tray can be stored in the -\ps{InputAttributes} dictionary in the page device dictionary and are -accessed during \d{media selection}. - -If the printer is capable of providing information on the properties of media -currently available in its input trays, -\ps{InputAttributes} should therefore be initialized appropriately -by the driver. - -%------------------------------------------------------------------------------ - -\subsubsection{The Process} - -PostScript's media selection process composes an \d{input media request} from -those among the page device parameters -\ps{PageSize}, \ps{MediaColor}, \ps{MediaWeight}, \ps{MediaType}, -\ps{MediaClass}, and \ps{InsertSheet} -which are not \ps{null} (some devices may add others) and -tries to find a matching entry in \ps{InputAttributes}. -Apart from \ps{MatchAll}, only those parameters which a device -considers for inclusion in a media request should appear in an -\ps{InputAttributes} entry. - -An entry in \ps{InputAttributes} \d{matches} the request if -\begin{itemize} - \item it contains matching entries (equal values, in the case of - \ps{PageSize} with a tolerance of 5~bp) for all parameters in the - request and - \item either - \begin{itemize} - \item does not have a \ps{MatchAll} entry which is \ps{true} or - \item does have a \ps{MatchAll} entry which is \ps{true} and - does not contain any entries in addition to \ps{MatchAll} and those - present in the media request. - \end{itemize} -\end{itemize} -Formally, you can define a relation ``$\leq$'' between two media requests or -\ps{InputAttributes} entries $a$ and~$b$ as follows: -\begin{displaymath} - a \leq b \quad :\Longleftrightarrow \quad - \vtop{\advance\hsize by -4cm - All parameters present in $a$ (except for \ps{MatchAll} in an - \ps{InputAttributes} entry) are also present in~$b$ and have matching - values.} -\end{displaymath} -The match rule can then be rephrased in the following manner: -\begin{quote} - An \ps{InputAttributes} entry~$e$ matches the input media request~$r$ - if and only if $r \leq e$ - except when \ps{MatchAll} is defined and \ps{true} in~$e$. - In the latter case one needs $r = e$. -\end{quote} -A media request is therefore a set of minimal requirements a media source must -satisfy in order for the document to be printed from that source. - -Exceptions are possible if no match is found, -the \ps{Policies} dictionary permits ignoring at least one parameter in the -request, -and a matching request $r' < r$ can be formed. -PLR3 demands that in this case the interpreter must set the ignored -page device parameters to \ps{null}\footnote{% - \Gs\ does not currently do it [gs~6.01].}. -The only exception is \ps{PageSize} which will be set to the value present -in the \ps{InputAttributes} entry selected. -The state of the device thus becomes as if the document had originally -requested~$r'$. - -%------------------------------------------------------------------------------ - -\subsubsection{Selection Parameters Which are also Configuration Parameters} - -Let a ``configuration parameter'' be a page device parameter which influences -the way the output device adapts to the medium, -while a ``selection parameter'' is a parameter considered for inclusion in a -media request. -The 6~standard selection parameters can then be classified as follows: -\begin{itemize} - \item - also a configuration parameter: - \ps{PageSize}, - \ps{MediaClass}, - % Explicitly defined to be an "arbitrary string representing attributes - % of the medium that may require special action by the output device" - % (PLR3 p. 402). - \item - not a configuration parameter: - \ps{InsertSheet}, - \ps{MediaType}, - \item - possibly a configuration parameter: - \ps{MediaColor} (probably not), - \ps{MediaWeight} (probably yes). -\end{itemize} - -If a particular selection parameter is also a configuration parameter, -it must be set correctly for the medium chosen by the media selection process. -Assuming the correct value to be non-null and disregarding the -\ps{PageSize} parameter, -this is the case if and only if the parameter is correctly specified in the -\ps{InputAttributes} entry \emph{and\/} the documents requests the same value: -\begin{itemize} - \item - If the parameter is not specified in \ps{InputAttributes} and a match - results, the value in the page device dictionary will be \ps{null}. - \item - If the parameter is not correctly specified in \ps{InputAttributes}, - the parameter's value in the page device dictionary will either be this - incorrect value or \ps{null}. - \item - If the parameter is correctly specified in \ps{InputAttributes}, - the document requests a different value, - and a match results, - the value will also become \ps{null}. -\end{itemize} -The \ps{PageSize} parameter is different because instead of being set to -\ps{null} when the request cannot be satisfied it is set to the value -belonging to the \ps{InputAttributes} entry chosen. -In my opinion this behaviour would have been desirable for all -configuration parameters considered for selection. - -I wish to draw two conclusions from this dicussion: -\begin{itemize} - \item - If the output device uses a selection parameter for configuration, - the interpreter should be configured such that the \ps{InputAttributes} - entries contain the correct values - and the \ps{Policies} dictionary should not permit the request to be - ignored. - \item - As already mentioned in a footnote, - \gs's behaviour with respect to non-matching parameters is not - currently~[gs~6.01] PostScript-conforming, - hence the preceding discussion does not really apply. - However, I am not aware of any statement in the documentation that this - was a deliberate implementation decision, - hence this behaviour cannot be relied upon. - - Therefore I still conclude that - a \gs\ device should not use selection parameters for configuration - unless the driver can sense these media properties. - - The reason is that the typical execution environment for \gs\ is a - single-user PC with a dedicated printer completely controlled by the user. - If this user inserts media with properties the driver needs to know, - it is unreasonable to require the parameter to be set in two places. -\end{itemize} - -%------------------------------------------------------------------------------ - -\subsubsection{User Interaction via \ps{Policies}} - -The user may set a policy code of~2 in the \ps{Policies} dictionary. -This indicates that a mismatch should result in some kind of device-specific -interaction with an external entity, -for example asking a human operator to insert media of the size requested and -waiting for confirmation. -This is not supported by \gs\ and results in a -\ps{configurationerror}~[gs~5.50] just as for a policy value of~0. -Should it be implemented one day, this will hopefully be independent of -the \gs\ device in question. -You should therefore ignore this feature. - -%------------------------------------------------------------------------------ - -\subsubsection{Automatic Switch to Manual Feed} - -A user might wish to tell the interpreter something like the following: -``I have put A4 sheets into the input tray where they can be fed automatically, -but I am prepared to feed certain other sizes manually''. -The second part of this statement cannot be easily expressed in -\ps{InputAttributes} for two reasons. - -The first and more important one is that you cannot request additional actions -(like setting \ps{ManualFeed} to \ps{true}) to be performed automatically if a -particular media source is selected and certain conditions are met.\footnote{% - One might consider (mis)using the \ps{Install} procedure for this purpose - provided it can determine which source has been selected. - However, there is no standard way for that, - and in addition PLR3 does not say whether it is permitted for - \ps{Install} to call \ps{setpagedevice}. - This is a problem because the latter calls \ps{Install} again.} -The only choices I see are -to make manual feed implicit in the media source by convention or -to provoke a \ps{PageSize} mismatch. -The first possibility must be supported by the driver, -the second requires the user to choose a \ps{PageSize} recovery policy of~2, -possibly combined with a \ps{PolicyReport} procedure setting \ps{ManualFeed} to -\ps{true}. - -The second problem arises if ``certain other sizes'' refers to a list or range -of page sizes. -Lists can only be supported by distributing the individual sizes over several -media sources one at a time, -ranges are permissible with \gs~[gs~5.50] but not in standard PostScript. -If you want to make it possible for the user to specify lists in this -situation, -you must reserve an unlimited set of position numbers for this -special purpose. - -One possible solution to both problems is therefore to let the driver interpret -all negative position numbers as meaning ``manual feed''. - -In deciding how to implement your driver you should, however, -not forget that \ps{InputAttributes} only states which media are currently -available according to the user. -The driver still has to check whether the requested size is acceptable to the -printer. -This reduces the usefulness of specifying lists or ranges for manual feed. -In fact, if one uses \gs's ability to accept a range for \ps{PageSize}, -a single position number with an implied manual feed is probably sufficient. -This is definitely the case if the device supports custom page sizes in such a -way that the total set of supported sizes can be expressed as a single -connected range of media extensions. - -%============================================================================== - -\subsection{Setting up Default User Space} \label{PsUserSpace} - -The PostScript language asserts that default user space is set up in a certain -manner in relation to the medium printed on. -PostScript programs may rely on this relationship. -Most printers, however, can neither control nor react to how the media have -been put into their input trays. -In what follows I assume that this is the case for the printer in question. - -Concerning the extension (height and width irrespective of orientation) of -media, -the \ps{PageSize} entry in the \ps{InputAttributes} dictionary is available for -telling a PostScript interpreter about the media present in an input tray. -This is, however, not sufficient for the interpreter to correctly set up -default user space: -even assuming a sheet to be unmarked and to have indistinguishable sides -this merely reduces the 8~possibilities of putting it into the input tray to -two inequivalent ways (unless it is a square sheet). -They are usually described by reference to the feeding direction as -``short edge first'' and ``long edge first''. -Both lead to equivalent \ps{PageSize} entries in \ps{InputAttributes}. - -The implementation of a PostScript output device for such a printer must -therefore be accompanied by rules stating what the ``right'' ways for putting -media into input trays are. -In order to prevent printing beyond the edges of a sheet, -the minimum is to state whether the interpreter assumes media will be fed short -edge first or long edge first. -A more detailed rule would add a description of default user space on -a sheet lying in the input tray. -This enables the user in addition to reliably position the output with respect -to matter already on the medium (e.g., a watermark). - -\begin{note} - At least three versions of the {\it PostScript Language Reference - Supplement\/}~\cite{PSSupplement2017,PSSupplement3010,PSSupplement3011} - impose special rules - for the location of default user space when printing on envelopes. - In my opinion these rules are undesirable because they require - \textit{the program generating a PostScript page\/} to know - whether printing will be done on envelopes or on ordinary paper - of the same size. - As this has nothing to do with the layout of text within the page, - the program should not need to know this. - But even worse, the rules are chosen such that if one requests landscape - orientation (which is usually desired for envelopes) the standard rule - governing the behaviour of \ps{setpagedevice} (rotate by $+90^\circ$) - actually produces output standing on its head when applied to an envelope - having the flap along its longer edge! - - If, on the other hand, a printer has particular requirements for feeding - envelopes and this does not produce the desired result when keeping to - PostScript's default rules, - the output device should deal with this problem, possibly triggered by a - page device parameter or by imposing the rule that certain page sizes are - always interpreted as envelopes. - - My advice is therefore to ignore these rules, - but you should form your own conclusion based on your printer's requirements. -\end{note} - -All this applies only to a default state for default user space. -This state is characterized by requesting a page in portrait orientation -($\hbox{width} < \hbox{height}$)% - \footnote{It is also assumed that the size requested is available, - otherwise the media selection process might influence the location and - scale of default user space (\ps{PageSize} recovery policies~3 and~4).} -and omitting requests for any of the page device parameters -\ps{LeadingEdge}, \ps{Orientation}, \ps{ImageShift}, -\ps{PageOffset}, \ps{Margins}, \ps{Tumble}, \ps{MirrorPrint}, -and possibly others. -The resulting structure on the sheet is sometimes called the -\d{canonical page in portrait orientation}, -but you should think of this situation as the set of conditions -under which the statement about the position of default user space -on a sheet in the input tray is valid. - -Most of the parameters just mentioned are defined in terms of their effect -with respect to this default orientation. -For example, -on receiving a \ps{PageSize} request for landscape orientation the interpreter -must rotate default user space 90~degrees counterclockwise with respect to -its position for portrait orientation and shift the origin into the -new lower left corner. - -The parameter \ps{LeadingEdge} makes it possible for the user to tell the -interpreter that a sheet has been put into the input tray in a non-standard -way. -Note that different devices can differ in which of the 4~possibilities is the -default: -for an interpreter assuming a short-edge orientation in the input tray it will -be either~0 or~2, -while a long-edge-oriented one will have~1 or~3 as its default. -This argument can be reversed: -specifying which of these values is the default assumed by the interpreter -together with the information which side of the sheet will be printed on -uniquely selects one of the 8 possible orientations in the input tray as the -``right'' one for the default situation. - -The parameter \ps{Orientation} should only be supported by devices -with media of continuously variable page sizes (printing to roll-fed media, -screen displays or file formats): -the values~1 and~3 cannot be supported on cut-sheet media, -and the user can achieve the effect of~2 by choosing a \ps{LeadingEdge} value -differing by~2 from its default. - -You must decide which of these parameters will be supported by your driver. -Note that some are automatically available for every \gs\ device. - -%============================================================================== - -\subsection{Device Coordinates} - -The rules of PostScript about the relative positioning of default user space -and the medium are intended to ensure that a PostScript program need not know -about the device coordinate system. -This information is, however, still accessible to the program: -the operator \ps{defaultmatrix}, for example, -returns the default transformation matrix for the device, -and with this information a PostScript program can unambiguously determine the -position of the device coordinate system with respect to default user space. -Hence the following discussion indeed belongs under the heading of -PostScript-visible properties of the output device. - -When writing your driver you must choose a device coordinate system. -This is no problem; just do it. -However, I am not aware of any statement in PLR3 which states that the -device coordinate system is a fixed property of the output device. -``Fixed'' in this context means ``fixed with respect to the feeding direction'' -or equivalently ``fixed with respect to the default of default user space''. -If you therefore wish to switch your device coordinate system if the user -requests landscape orientation or on any other occasion the user executes -\ps{setpagedevice}, -this is perfectly legitimate. -You might even do it in such a manner that \ps{defaultmatrix} returns the -same value under all circumstances. -This freedom is actually desirable, -because it means that you can choose whatever convention for device coordinates -is the simplest for you to implement depending on the current set of -page device parameters. - -However, if you look at the description of the \ps{PageOffset} and \ps{Margins} -parameters you'll find statements that for \ps{PageOffset} -``the repositioning is typically accomplished by altering the current -transformation matrix, although on some devices it may instead be accomplished -by device-dependent means that are independent of the graphics state -(in particular, of the CTM)''~\cite[page 415]{PostScript3} and that -for \ps{Margins} the latter case is the typical one. -(Incidentally, as both parameters have to be specified with respect to the -direction of the axes of the device coordinate system, -your driver's documentation should tell the user where these axes point to.) -If your device coordinates are fixed with respect to the default default user -space, -you will have to modify the default transformation matrix, -and conversely if you wish the influence of such parameters not to be visible -in the CTM you must shift your device coordinates. - -Concerning \ps{PageOffset} and \ps{Margins} these discussions are, however, -slightly academic because \gs\ implements these parameters for all devices -and does it via modifications of the default transformation matrix -in both cases~[gs~5.50]. -At least for \ps{Margins} you can easily override this behaviour but I wouldn't. - -%============================================================================== - -\subsection{Other Standard Page Device Parameters Describing Device - Capabilities} - -The following page device parameters defined in PLR3 refer to special -hardware functionality: -\begin{quote} - \ps{InsertSheet}, \ps{ManualFeed}, \ps{TraySwitch}, - various parameters for roll-fed media, - \ps{Duplex}, - \ps{Collate}, \ps{Jog}, \ps{OutputFaceUp}, - \ps{MaxSeparations}, \ps{SeparationColorNames}. -\end{quote} -Absence of one of these parameters indicates that the feature is not -supported by the device. -The converse is not true. -You will have to decide which of these features you can support. - -In addition, there exist also position numbers for media destinations -(keys in \ps{OutputAttributes}), -similar to the numbers for media sources. -If your printer has several output destinations your driver should -support them as well. - -%============================================================================== - -\subsection{Non-Standard Page Device Parameters} - -If your driver is going to offer functionality which cannot be expressed in -terms of standard page device parameters, -you will have to define new ones. - -You should take some care not to choose parameter names which can collide with -other definitions. -At the least you should check the current edition of the -{\it PostScript Language Reference Supplement\/}~\cite{PSSupplement3011} -in order to find out whether there is already a semi-standard parameter -for this functionality or one having the intended name but another meaning. - -%****************************************************************************** - -\section{General Properties of a \Gs\ Device} - -Unless there is an explicit reference to a different version, -everything which follows in this and subsequent sections is based on -\gs\ version 5.50. - -%============================================================================== - -\subsection{Definitions} - -A \gs\ device driver defines one or more \d{ghostscript devices}. -A ghostscript device is identified by its name (1~to~8 letters, digits or -underscores, starting with a letter~\cite{Drivers5.50}\footnote{% - These restrictions are probably the combined result of restrictions from - the C~language and from some file systems. - Effectively, this means that you can ignore at least the length restriction - on almost all platforms.}) and characterized by a -C~variable which must be called {\tt gs\_\textit{name}\_device}. -% No italic correction for "name" here; it looks worse. -This is the \d{device structure instance}, -its type is the \d{device structure}. -The device structure instance is a prototype for the data structure -(\d{device instance}, sometimes also called \d{driver instance}) -which is actually used when a device is installed in the graphics state. - -\ifdraft -??? Forwarding device, band device, -life cycle (at which point in a multi-function open call is the device open? -Will partially opened devices be closed?) -\fi - -%============================================================================== - -\subsection{Relation to Output Devices} - -There is a one-to-one correspondence between ghostscript devices and -PostScript output devices supported by \gs. - -Technically, this can be inconvenient if your driver implements lots of -different output devices and you do not wish to clutter \gs's device list -with all these names. -In that case you should introduce sub-devices based on particular parameter -values. -My \textit{hpdj\/} driver for example uses \texttt{hpdj} as the device name but -in addition selects a particular printer model with the -page device parameter \ps{Model}. -As the latter determines which process colour models and page sizes are -supported by the driver, -this parameter in fact distinguishes between output devices within one -ghostscript device. - -If you choose to implement such sub-devices you should try to simulate the -behaviour of \ps{setpagedevice} for \ps{OutputDevice} -(initialization with default values) -whenever the output device is changed. -Your \prog{put\_params} implementation should therefore check for the -sub-device-changing parameters first. -However, you should only reset those parameters which the user can override. -%??? This does not apply to the resolution when set from the -% command line [gs~6.01]. - -%============================================================================== - -\subsection{Device Structure} - -\ifdraft -??? Dynamic memory -\fi - -%------------------------------------------------------------------------------ - -\subsubsection{Device Procedures} - -Among the variables in the device structure are several dealing with functions: -\begin{itemize} - \item The \prog{static\_procs} variable points to a static table of - type \prog{gx\_device\_procs} containing pointers to functions. - It is common to all device instances of the same type. - \item \prog{page\_procs} is of type \prog{gx\_page\_device\_procs}. - This is a table of pointers to functions peculiar to page devices. - \item The \d{device procedure table} \prog{procs} is also of - type \prog{gx\_device\_procs} - (but not a pointer to that type as \prog{static\_procs} is). - The entries in this table (or the functions pointed to) are the - \d{device procedures}. -\end{itemize} - -The function \prog{gx\_device\_set\_procs()} checks whether -\prog{static\_procs} is \prog{NULL} or not. % gsdevice.c -If it is not, -the table pointed to is copied over \prog{procs} and -\prog{static\_procs} is set to \prog{NULL}. - -More important, however, is that almost all \prog{NULL} entries in the -device procedure table are overwritten with default values. -This is done by \prog{gx\_device\_fill\_in\_procs()}. -It first calls \prog{gx\_device\_set\_procs()} -and then replaces null entries for all device procedures except -\prog{fill\_rectangle}~[gs~5.50].\footnote{ - The entries for \prog{image\_data} and \prog{end\_image} are always - overwritten with non-null default values - even if they are non-null to begin with.} - -The list of device procedures is frequently growing. -In \gs\ version~5.50 this table has 43~entries. -Check the definition of \prog{gx\_device\_proc\_struct()} in \file{gxdevcli.h} -for the current list. - -A device procedure should be called by using the \prog{dev\_proc()} macro: -it takes a pointer to a device instance and the name of a device -procedure table field as arguments and is expanded into the entry in the -device procedure table. - -While entries in \prog{*static\_procs} may not change, -the device procedures in \prog{procs} can change during a device's lifetime. -The macro \prog{set\_dev\_proc()} is intended for this purpose. -%??? -%The \textit{prn\/} device, for example, -%sets a number of device procedures for rendering when the device is opened -%(\prog{gdev\_prn_\allocate()}) and restores the old values when the device is -%closed (\prog{gdev\_prn\_tear\_down()}). - -%============================================================================== - -\subsection{\Gs\ Devices in PostScript} - -\subsubsection{Type, \Gs\ Initialization and State} - -\Gs\ introduces a new basic type \ps{devicetype} for representing ghostscript -device (structure) instances. -Instances of this type are composite objects. % See 'ref_type' in iref.h. - -% See gs_init.ps. -On initialization, -\gs\ repeatedly executes the \ps{.getdevice} operator to obtain -all known device structure instances. -It then creates a dictionary \ps{devicedict} in \ps{systemdict} containing -for each device an array of length~2; -the first entry is the device structure instance, % from 'gx_device_list[]' -the second is \ps{null}\footnote{ - Actually, the PostScript initialization code sets the second entry to be - \ps{null} if the device is not writable and - makes it a copy of the first if it is. - However, the implementation of \ps{.getdevice} (\prog{zgetdevice()}) - always returns a read-only object~[gs~5.50]. % See zdevice.c. - % Also tested with gs 5.50 and gs 5.10 binaries. - }. -Entries in \ps{devicedict} have the string returned by \ps{.devicename} as a -key (\prog{dname} field in the device structure). % See zdevice.c. - -The device instance current in the graphics state -can be obtained with the operator -\ps{currentdevice} implemented in \prog{zcurrentdevice()}. - -%------------------------------------------------------------------------------ - -\subsubsection{Switching Devices} - -The procedure \ps{selectdevice} calls first \ps{finddevice} and then -\ps{setdevice}. % Actually, it also calls \ps{.setdefaultscreen}. - -The procedure \ps{finddevice} looks into \ps{devicedict} to find a device by -its name and checks the second entry in the array. -If it is \ps{null}, -the entry is replaced by the result of \ps{copydevice} applied to the first -entry. -In all cases, this second entry is returned. - -\ifdraft -??? TEST: What happens on multiple selection? -\fi - -\ps{copydevice} is a \gs\ operator implemented in \prog{zcopydevice()}. -% See zdevice.c. -The latter calls \prog{gs\_copydevice()} % gsdevice.c -which allocates storage for a new device instance, -calls \prog{gx\_device\_init()} and sets the device variable \prog{is\_open} -to \prog{false}. -The function \prog{gx\_device\_init()} copies the source device instance -storage into the new instance with the exception of the \prog{memory} variable. - -The procedure \ps{setdevice} calls the operator \ps{.setdevice} implemented -in \prog{zsetdevice()}. % zdevice.c -This function calls \prog{gs\_setdevice\_no\_erase()} and clears the -underlying page device. % macro clear_pagedevice() - -\ifdraft -??? What happens with the old device? -\fi - -The function \prog{gs\_setdevice\_no\_erase()} first checks whether the device -is already open. -If not, it calls \prog{gx\_device\_fill\_in\_procs()} and the -\prog{open\_device} device procedure and finally it sets \prog{is\_open = true}. -Then it calls \prog{gs\_setdevice\_no\_init()}, \prog{gs\_initmatrix()} and -\prog{gs\_initclip()}. - -\prog{gs\_setdevice\_no\_init()} sets the colour mapping procedures -in the graphics state from the device's colour mapping procedures -(calling \prog{gx\_set\_cmap\_procs()}). - -%****************************************************************************** - -\section{\Gs\ Device Parameters} - -The variables in a device instance determine the values of its -\d{device parameters}. -These parameters are a subset of the -page device parameters of the corresponding PostScript output device. -The connection between the two and the way in which the device parameters may -be accessed is an area where \gs's documentation is particularly reticent. - -%============================================================================== - -\subsection{Parameter Dictionaries} - -A device parameter is identified by a string, its name. -If a device supports a particular parameter, -it associates a typed value with this name. -\Gs\ has an internal API for dealing with collections of such name-value pairs. - -%------------------------------------------------------------------------------ - -\subsubsection{Types for Parameters} - -The name of a parameter is of type \prog{gs\_param\_name} -which is defined as \prog{const char~*}. - -Each parameter has a type associated with it which is stored in an instance -of type \prog{gs\_param\_type}: -\begin{program} % gsparam.h -typedef enum \lb -\ /* Scalar */ -\ gs_param_type_null, gs_param_type_bool, gs_param_type_int, -\ gs_param_type_long, gs_param_type_float, -\ /* Homogenous collection */ -\ gs_param_type_string, gs_param_type_name, -\ gs_param_type_int_array, gs_param_type_float_array, -\ gs_param_type_string_array, gs_param_type_name_array, -\ /* Heterogenous collection */ -\ gs_param_type_dict, gs_param_type_dict_int_keys, gs_param_type_array -\rb\ gs_param_type; -\end{program} -In addition, there is a macro \prog{gs\_param\_type\_any} which resolves to -an expression of this type and which can be used to denote any type. - -\ifdraft -??? -What is the concept of ``type'' here? PostScript, C, a mixture of both? -Add description of collections. -\fi - -The type \prog{gs\_param\_value} is used to store values of parameters. -It is a \prog{union} of the following C~types: -\begin{quote} - \prog{bool}, \prog{int}, \prog{long}, \prog{float}, - \prog{gs\_param\_string}, % twice - \prog{gs\_param\_int\_array}, \prog{gs\_param\_float\_array}, - \prog{gs\_param\_string\_array}, % twice - \prog{gs\_param\_collection} -\end{quote} - -Finally, the type \prog{gs\_param\_typed\_value} combines a type description -with a value: -\begin{program} % gsparam.h - typedef struct gs_param_typed_value_s \lb - \ gs_param_value value; - \ gs_param_type type; - \rb\ gs_param_typed_value; -\end{program} - -%------------------------------------------------------------------------------ - -\subsubsection{Type and Operations for Parameter Collections} - -A \d{parameter dictionary} represents an unordered collection of -instances of type \prog{gs\_param\_typed\_value} -and is of the C~type \prog{gs\_param\_list} -% (also known as \prog{struct gs\_param\_list\_s}) -or of a type having the same initial storage layout as this type. -This is the same convention as used to simulate type inheritance for -device structures: -\prog{gs\_param\_list} should be -considered as an abstract base class defining access routines for -parameter dictionaries -while its derived types provide implementations for the routines and storage -for the parameters. -This abstract interface is declared in \file{gsparam.h}. - -Concrete implementations of this abstract interface are the following types: -\begin{quote}\begin{flushleft} - \prog{gs\_c\_param\_list}, % gsparam.h - \prog{dict\_param\_list}, % iparam.h - \prog{array\_param\_list}, % iparam.h - \prog{stack\_param\_list}, % iparam.h - \prog{printer\_param\_list\_t} % gdevpsdf.c -\end{flushleft}\end{quote} -The only one of interest to implementors of device drivers is -\prog{stack\_param\_list} because it is used to represent objects on the -operand stack. -\ifdraft -??? More about it later? -\fi - -There exists a macro \prog{gs\_param\_list\_common} to obtain the list of -declarations common to all parameter dictionary types. -It resolves to: -\begin{program} - const gs_param_list_procs *procs; - gs_memory_t *memory; % Actually, the semicolon is not part of the macro. -\end{program} -The \prog{procs} member points to a table of pointers to the -implementation's access methods. -This table contains the following members\footnote{ - I am not aware of any official description for the semantics or behaviour of - these functions at the level of abstraction for \prog{gs\_param\_list}; - the comments in \file{gsparam.h} are insufficient for this purpose. - These descriptions are therefore heavily based on the actual implementation - for \prog{iparam\_list} which is an abstract type between - \prog{gs\_param\_list} and a number of concrete implementations - including \prog{stack\_param\_list}. - }: -\begin{itemize} - \item \prog{int (*xmit\_typed)(gs\_param\_list *, gs\_param\_name, - gs\_param\_typed\_value *);} - - This routine is used to ``transmit'' a value. - This means either to put a value into the dictionary (writing) - or to extract it (reading). - Which direction is chosen depends on the function pointed to, - i.e., unless you modify this pointer you can either read or write the - parameter dictionary but not both. - - A reading implementation of \prog{xmit\_typed} returns zero if the - parameter value was successfully extracted, - one if the parameter does not exist, - and a negative value on error. - A writing implementation returns zero or one on success and - a negative value on error. - - The reading implementation of \prog{xmit\_typed} for - \prog{stack\_param\_list} % Actually, for 'iparam_list'. - keeps track of which parameter was accessed and what the result was. - % See comments in iparam.h and the 'results' field in 'iparam_list' - % [gs 5.50]. - - \ifdraft - ??? Discuss selective writing. - \fi - \item \prog{int (*signal\_error)(gs\_param\_list *, gs\_param\_name, int);} - - This routine is used to associate an error code (the last argument) with - the parameter designated. - A parameter dictionary can for example store this code in the list together - with the parameter's value. - The function must \emph{never\/} be called for a - non-existent parameter [gs~5.50]. - % Looking at iparam.c, this should give a core. - - This routine is in particular intended to be used by functions extracting - values from a parameter dictionary and discovering that - the type is incorrect or the value is outside the permissible range. - \item \prog{int (*commit)(gs\_param\_list *);} - - This function is used to perform some final processing after extracting - all interesting values from a parameter dictionary. - It can for example check that all the parameters present have been - extracted, - i.e., that there are no unknown parameters left in the dictionary. - % ref_param_read_commit() does this if it has been requested. - % If there are undefined parameters, their 'result' codes are set to - % 'e_undefined'. - - The routine returns zero on success and a negative value on error. - \item \prog{int (*next\_key)(gs\_param\_list *, gs\_param\_enumerator\_t *, - gs\_param\_key\_t *);} - - This routine is useful for debugging because it can be used to iterate over - all entries in a parameter dictionary. - The second argument points to an iterator which stores the last position - accessed; - it must have been initialized by calling - \prog{void param\_init\_enumerator(gs\_param\_enumerator\_t *)} before - the first call to this function. - The third argument - (the type is an alias for \prog{gs\_param\_string}) % gs 6.50 - will receive the name of the next parameter if there is - one (return code is zero), - otherwise the return code is~1 (no more parameters) or negative (error). - \item In addition, there are the members - \prog{begin\_xmit\_collection}, - \prog{end\_xmit\_collection}, - \prog{request}, - \prog{requested}, - and - \prog{get\_policy}. -\end{itemize} - -%------------------------------------------------------------------------------ - -\subsubsection{Interface for Drivers} - -The methods in parameter dictionaries are not particularly interesting -from the point of view of writing a driver, -but there are some functions on top of this interface which are. - - -\paragraph{Reading.} - -For reading a value from a parameter dictionary, the basic routine is: -\begin{program} -int param_read_requested_typed(gs_param_list *, gs_param_name, -\ gs_param_typed_value *); -\end{program} -This function expects a requested type to have been filled into the -\prog{type} field of the entry pointed to be the third argument. -It calls the \prog{xmit\_typed} function. -If the latter returns a non-zero exit code, this code is returned. -Otherwise the function checks for a mismatch between the requested and -the actual type -and tries to convert between the two if necessary and possible. -For example, if the actual parameter is of type \prog{gs\_param\_type\_int} -its value can also be extracted as \prog{gs\_param\_type\_long} -or \prog{gs\_param\_type\_float}. % See param_coerce_typed(). -If the types do not match, -a value of \prog{gs\_error\_typecheck} is returned. -Otherwise the result is returned via the \prog{value} field in the -third argument. - -There is a macro \prog{param\_read\_typed()} which effectively calls -\prog{param\_read\_requested\_typed()} with the value -\prog{gs\_param\_type\_any} and -can be used to fetch a parameter value irrespective of its type. -The \prog{type} field in the third argument will contain the actual type. - -Implemented on top of \prog{param\_read\_requested\_typed()} there are several -functions \prog{param\_read\_\textit{type}()} which request and return a value -of a specific type. -For an \prog{int}, the routine is: -\begin{program} -int param_read_int(gs_param_list *, gs_param_name, int *); -\end{program} -These functions should be used in preference to the others. - - -\paragraph{Writing.} - -For writing a parameter there is a macro \prog{param\_write\_typed()} which -should be called as if it were the following function: -\begin{program} - int param_write_typed(gs_param_list *, gs_param_name, - \ gs_param_typed_value *); -\end{program} -The macro is mapped to a call to \prog{xmit\_typed} and returns its return code. - -Again there is a layer of type-specific functions on top of this basic -interface. -For an \prog{int}, the routine is: -\begin{program} -int param_write_int(gs_param_list *, gs_param_name, const int *); -\end{program} -These functions should be preferred. - - -\paragraph{Other Functions.} - -The macros \prog{param\_signal\_error()}, \prog{param\_commit()} and -\prog{param\_get\_next\_key()} -can be called as if they were the following functions: -\begin{program} -int param_signal_error(gs_param_list *, gs_param_name, int); -int param_commit(gs_param_list *); -int param_get_next_key(gs_param_list *, gs_param_enumerator_t *, -\ gs_param_key_t *); -\end{program} -They call the dictionary's \prog{signal\_error}, \prog{commit} and -\prog{next\_key} routines, respectively. - -%============================================================================== - - -\subsection{The Parameter Device Procedures} - -To be described. % ??? - -%============================================================================== - -\subsection{Default Parameters} - -\subsubsection{All Devices} - -The function \prog{gx\_default\_get\_params()} writes the following -parameters into the parameter list it received as an argument~[gs~5.50]: -% See gsdparam.c and gxdevcli.h. -\begin{quote} % ??? Find a better solution. - \normalUS - \def\a{$^*$} % asterisk - \halign{\quad\prog{#}\hfil\quad& \prog{#}\hfil\quad& - \vtop{\raggedright\hsize=5cm #\strut}\hfil\cr - % ??? Improve baseline distance. - \omit\quad Name\hfil & \omit Type and device variable or value\hfil & - Remarks\cr - \noalign{\smallskip\nointerlineskip - \hbox{\dimen0=\hsize \advance\dimen0 by -2em - \quad \vrule depth 0.4pt height 0pt width \dimen0} - \smallskip} - .HWMargins\a& float HWMargins[4]&\cr - .IgnoreNumCopies\a& bool IgnoreNumCopies&\cr - .MarginsHWResolution& float MarginsHWResolution[2]&\cr - .MediaSize\a& float MediaSize[2]&\cr - BitsPerPixel& int color_info.depth&\cr - BlueValues& (int)(color_info.max_color + 1)& - only set if \prog{color\_info.num\_components} is larger than 1.\cr - ColorValues& (long)(1L << color_info.depth)& - only set if \prog{color\_info.num\_components} is larger than 1.\cr - Colors& int color_info.num_components& \cr - GraphicsAlphaBits& int& - a value returned by the device procedure \prog{get_alpha_bits}\cr - GrayValues& (int)(color_info.max_gray + 1)&\cr - GreenValues& (int)(color_info.max_color + 1)& - only set if \prog{color\_info.num\_components} is larger than 1.\cr - HWColorMap& & returned as a string\cr % ??? - HWResolution\a& float HWResolution[2]& \cr - HWSize\a& float [2]& - initialized with \prog{width} and \prog{height} (in this order)\cr - ImagingBBox\a& \textrm{null or} float ImagingBBox[4]& - the type depends on \prog{bool ImagingBBox_set}\cr - Margins\a& float Margins[2]& \cr - Name& const char *dname& treated as a string\cr - NumCopies\a& \textrm{null or} int NumCopies& - only read or written if \prog{NumCopies\_set} is not negative. - The null value is returned if \prog{NumCopies\_set} is zero.\cr - OutputDevice& const char *dname& treated as a name\cr - PageCount& long PageCount& \cr - PageSize\a& float MediaSize[2]& - only set if \prog{PAGESIZE_IS_MEDIASIZE} was defined during - compilation which it is~[gs~5.50].\cr - ProcessColorModel& \vtop{\raggedright\hsize=5cm - \textrm{a name derived from - \prog{color\_info.num\_components}, - see section~\ref{NativeColourSpaces}}\strut}\hfil\cr - RedValues& (int)(color_info.max_color + 1)& - only set if \prog{color\_info.num\_components} is larger than 1.\cr - TextAlphaBits& int& - a value returned by the device procedure \prog{get_alpha_bits}\cr - } -\end{quote} - -The function \prog{gx\_default\_put\_params()} reads the same parameters from -its arguments list, -but copies only some of them into the device instance. -These writable parameters are marked with an asterisk in the preceding list. -The others are accessed in order to check that they are defined at all, -that they have the right type or that their value satisfies certain constraints. -For example, -\ps{PageCount} must be defined and -be either \ps{null} or a \prog{long} value agreeing with the value present -in the \prog{PageCount} field in the device instance. - -In addition the default put procedure also accesses \prog{\%MediaSource} and -\prog{\%MediaDestination} but only to check that these parameters have values -of integer type. - -Before \prog{gx\_default\_put\_params()} actually modifies any parameters it -calls \prog{param\_commit()} for the parameter list after having called all -the necessary routines for reading the known parameters -into temporary variables. -If the commit routine returns a negative value, -processing terminates without making changes in the device structure. - -%------------------------------------------------------------------------------ - -\subsubsection{The \textit{prn\/} Device} - -The function \prog{gdev\_prn\_get\_params()} first calls -\prog{gx\_default\_get\_params()} and then writes the following parameters -into the parameter list it received as an argument: -\begin{quote} % ??? Find a better solution. - \normalUS - \def\a{$^*$} - \halign{\quad\prog{#}\hfil\quad& \prog{#}\hfil\quad& - \vtop{\raggedright\hsize=5cm #\strut}\hfil\cr - % ??? Improve baseline distance. - \omit\quad Name\hfil & \omit Type and device variable or value\hfil & - Remarks\cr - \noalign{\smallskip\nointerlineskip - \hbox{\dimen0=\hsize \advance\dimen0 by -2em - \quad \vrule depth 0.4pt height 0pt width \dimen0} - \smallskip} - BandBufferSpace& long space_params.band.BandBufferSpace& \cr - BandHeight& int space_params.band.BandHeight& \cr - BandWidth& int space_params.band.BandWidth& \cr - BufferSpace& long space_params.BufferSpace& \cr - Duplex\a& \textrm{null or} bool Duplex& - only read or written if \prog{Duplex\_set} is not negative. - A null value is returned if \prog{Duplex\_set} is zero.\cr - MaxBitmap& long space_params.MaxBitmap&\cr - OpenOutputFile\a& bool OpenOutputFile&\cr - OutputFile\a& char fname[]& treated as a string\cr - ReopenPerPage\a& bool ReopenPerPage&\cr - } -\end{quote} -The function \prog{gdev\_prn\_put\_params()} accesses the same parameters -as \prog{gx\_default\_get\_params()} -and finally calls \prog{gx\_default\_put\_params()}. -Only those parameters marked with an asterisk, however, -are usually copied into the device instance. -The others will be copied only -if the field \prog{space\_params.params\_\-are\_\-read\_\-only} is \prog{false} -(then they must also satisfy some constraints), -otherwise their values must agree with those in the device instance. - -In addition the put function also accesses -\prog{InputAttributes} and \prog{OutputAttributes} -and checks that they are dictionaries if defined. - -%============================================================================== - -\subsection{The Basic Access Routines in PostScript} - -A device's parameters can be read with \ps{getdeviceprops} and modified by -\ps{putdeviceprops}~\cite{Language5.50}. -The first is based on the operator \ps{.getdeviceparams}, -the second on \ps{.putdeviceparams}. - -%------------------------------------------------------------------------------ - -\subsubsection{Reading} - -The operator \ps{.getdeviceparams} accepts either a \ps{null} value or a -dictionary of keys\footnote{Values are simply duplicates of the keys.}. -In the second case, only the specified device parameters are fetched. -The operator puts a mark object on the stack and on top of it the -names and values of those parameters which it could find. -If the caller requested a parameter which cannot be found -that request will be ignored without indicating an error. - -\ifdraft -??? CHECK -\fi - -This operator is implemented in \prog{zgetdeviceparams()} which calls -\prog{zget\_device\_params()}, -a function introduced to reduce duplicate code. -% See zdevice.c. -This function first prepares an instance of type \prog{stack\_param\_list} -by connecting it with the operand stack -and then calls \prog{gs\_get\_device\_or\_hardware\_params()} for the device -with this list. - -\ifdraft -??? Discuss selection. -\fi - -The function \prog{gs\_get\_device\_or\_hardware\_params()} calls -\prog{gx\_device\_set\_procs()}, -supplies default values for some device procedures if necessary, -and finally passes the parameter list to the \prog{get\_params} procedure. - -%------------------------------------------------------------------------------ - -\subsubsection{Writing} - -The operator \ps{.putdeviceparams} is implemented in \prog{zputdeviceparams()}. -Its behaviour with respect to unrecognized keys has to be requested as -either to ignore them or to generate an \ps{undefined} error -(as \ps{putdeviceprops} does). - -The implementation first prepares an instance of type \prog{stack\_param\_list} -and then calls \prog{gs\_put\-device\-params()} for the device -with this list. -If the return code is negative (error), the function returns. -Otherwise, some special processing is done under certain circumstances -and finally the macro \prog{clear\_\-page\-device()} is called for the graphics -state. - -\ifdraft -??? Add description of error processing for undefined values. -\fi - -The function \prog{gs\_putdeviceparams()} calls -\prog{gx\_device\_set\_procs()}, -supplies default values for some device procedures if necessary, -and then calls the \prog{put\_params} procedure with the parameter list. -The return code from \prog{gs\_putdeviceparams()} is the code returned by the -device procedure provided it is negative or the device was closed before the -call or it is still open afterwards; -otherwise (no error and the device was open before and is closed afterwards) -the return code is always~1. - -%============================================================================== - -\subsection{Connection with Page Device Parameters} - -%------------------------------------------------------------------------------ - -\subsubsection{The Implementation of \ps{currentpagedevice}} - -The procedure \ps{currentpagedevice} first calls the operator -\ps{.currentpagedevice} which is implemented in \prog{zcurrentpagedevice()}. -If the current device is a page device or acts as a forwarding device -for a page device, -this function returns the dictionary parameter \prog{pagedevice} from -\gs's graphics state. - -If the dictionary returned is empty, \ps{currentpagedevice} -creates a new dictionary from all -parameters returned by \ps{.getdeviceparams} for the page device plus -the following ``required attributes''~[gs~5.50]: -\begin{quote} - % See definition of .requiredattrs in gs_setpd.ps. - \ps{PageOffset}, - \ps{InputAttributes}, - \ps{\%MediaSource}, - \ps{OutputAttributes}, - \ps{\%MediaDestination}, - \ps{Install}, - \ps{BeginPage}, - \ps{EndPage}, - \ps{Policies}. -\end{quote} -The default values for these parameters are overridden if \ps{.getdeviceparams} -returns values for them. -% Remark in gs_setpd.ps 5.50, line 199-200: -% In case of duplicate keys, .dicttomark takes the entry -% lower on the stack, so we can just append the defaults here. -Before returning the resulting dictionary, -\ps{currentpagedevice} also calls \ps{.setpagedevice} (\prog{zsetpagedevice()}) -which sets \prog{pagedevice} in the graphics state. - -If, on the other hand, \ps{.currentpagedevice} returns a dictionary of non-zero -length, -\ps{currentpagedevice} creates and returns a new dictionary constructed from -this and the current values for \ps{.MediaSize} and \ps{PageCount}. -% Definition of .dynamicppkeys in gs_setpd.ps. -If your driver modifies other device parameters except as requested through -\ps{setpagedevice}, -these modifications will therefore not be visible in PostScript. - -\ifdraft -??? Describe when the data are refreshed. -\fi - -%------------------------------------------------------------------------------ - -\subsubsection{The Implementation of \ps{setpagedevice}} - -\ifdraft -\Gs's implementation of \ps{setpagedevice} is fairly complex. -This document lists only some of its properties, -the reader should check the file \file{gs\_setpd.ps} for details. - -??? -\else -To be described. -\fi - -%============================================================================== - -\ifdraft -\subsection{???} - -CLI, overriding, multiple access, \prog{Duplex\_set} problem. -\fi - -%****************************************************************************** - -\section{Pages and Media} - -\subsection{Device Coordinates} \label{DevCoord} - -\Gs's documentation~\cite[section ``Coordinates and types'']{Drivers5.50} -gives the impression that a driver can choose any location for the origin -and orientation of its device coordinate system provided coordinate values -fit into an \prog{int}. -This is misleading. - -Printer drivers based on the \textit{prn\/} device use an internal -pixmap-generating device (a ``memory'' or a ``command list'' device) -for scan conversion. -The device coordinate system for this pixmap uses $x$-values in the range -$[0, \hbox{width}-1]$ and $y$-values in the range $[0, \hbox{height}-1]$. -% ??? Reference. -The width and height values are set from the page size and the resolution -(see \prog{gx\_device\_set\_width\_height()}) % gsdevice.c -and are available in the device instance as the \prog{width} and \prog{height} -fields. -Anything falling outside this area is clipped. % Where? ??? -This clipping happens in addition to the clipping established at PostScript -level. -Therefore you should never put your device coordinate origin in the interior -of the imageable area or outside of the page area. -It also means that the imageable area must be contained in the page area: -the \textit{prn\/} device cannot support ``Extra'' -sizes~\cite[Appendix~B]{PPD4.3}.\footnote{ - A better way would have been to set width and height from page size, - resolution and the hardware margins. - Not only would this have achieved support for ``Extra'' sizes via negative - margins, - it would also almost certainly have forced \gs\ to interpret hardware margins - with respect to device space (see section~\ref{HardwareMargins}).} - -Where a driver's device coordinate system is located on the printed page -depends on where the driver puts the pixels from the pixmap. -It extracts these values by calling one of the following functions to obtain -one or more scan lines (all $x$~pixels for one $y$~value, -$x = 0$ lying in the first byte of the scan line): -\begin{quote} - % Checked with gs 5.50. - \tt\raggedright \parindent=-2em \advance\leftskip by 2em - \noindent\kern-2em - int gdev\_prn\_copy\_scan\_lines(gx\_device\_printer *pdev, int y, - byte *str, \penalty-5 uint size); - - int gdev\_prn\_get\_bits(gx\_device\_printer *pdev, int y, - byte *str, \penalty-5 byte **actual\_data); -\end{quote} - -In most cases the printer's native I/O~interface for raster data -will print a small group of pixel lines, -clear its memory for the next group -and advance the paper by the distance covered. -It will not usually be possible to move backwards. -Hence the first pixel line sent is the one closest to the medium's -\d{leading edge}, -that edge which enters the printer first.\footnote{ - Ah, you noticed the logical gap? - Well, if you find a printer which feeds paper with one edge first and - then starts printing from one of the other edges, - send me a message and I'll be surprised.} -It is also to be expected that the printer prints the pixel line entirely, -starting at the left margin of the imageable area and proceeding to the right. -A convenient position for the device coordinate system is therefore -with the origin in the top left corner\footnote{ - ``Top'' is defined as where the first pixel line is printed (leading edge), - and ``left'' is the edge to the left if you hold the sheet with the - leading edge up and the printed side towards you.} -of the imageable area, -the $x$~axis pointing to the right and the $y$~axis downwards. -The driver can then extract scan lines from the pixmap in the order of -increasing~$y$, -does not need to reverse the order of pixels within the line, -and need not insert or remove pixels at the beginning of raster lines. -With the choice of device coordinates as just described -the leading edge is then the edge close to the $y = 0$ line in device space. - -It is occasionally helpful to distinguish explicitly between the two systems -of device coordinates: -pixmap device coordinates are fixed with respect to the pixmap -(I call this the \d{pixmap device space}) -and the ``real'' device coordinates should be thought of as being attached to -the sheet printed. -The relation between them is established by the driver's source code and the -printer's native I/O~interface. -When programming for \gs\ you usually deal with pixmap device space, -except when setting up the default user space. - -%============================================================================== - -\subsection{Device Space and Default User Space} - -Having fixed the relation between the pixmap's device coordinates and the -printer's interface you still have to set up the default matrix to establish -the correct relation between default user space and -(``real'') device coordinates. - -%------------------------------------------------------------------------------ - -\subsubsection{The \ps{defaultmatrix} Operator} -% Description derived from gs 5.50, checked with gs 6.50. - -\Gs\ implements \ps{defaultmatrix} in \prog{zdefaultmatrix()} % zmatrix.c -which calls \prog{gs\_defaultmatrix()}. -The latter function first checks whether the parameter \prog{ctm\_default\_set} -in the graphics state is set or not. % See gscoord.c. -If it is, the function returns the value of \prog{ctm\_default} in the -graphics state. -If it is not set, -the function obtains the current device from the graphics state, -calls \prog{gs\_deviceinitialmatrix()} for this device, -and performs an additional shift of the coordinate system based on the -values for the \prog{Margins} array in the device instance: -\begin{program} - pmat->tx += - \ dev->Margins[0] * dev->HWResolution[0] / dev->MarginsHWResolution[0]; - pmat->ty += - \ dev->Margins[1] * dev->HWResolution[1] / dev->MarginsHWResolution[1]; -\end{program} - -The function \prog{gs\_deviceinitialmatrix()} % gsdevice.c -first checks whether the -device procedure \prog{get\_initial\_matrix} has been filled in or not -and inserts \prog{gx\_default\_get\_initial\_matrix()} in the procedure list -if not. -It then calls the device procedure \prog{get\_initial\_matrix}. - -Looking from default user space, -the default procedure \prog{gx\_default\_get\_initial\_matrix()} returns a -matrix putting the origin in the top left corner of the page, -the $x$~axis pointing to the right and the $y$~axis downwards. -% See gdevdflt.c. - -The graphics state parameter \prog{ctm\_default} is set in -\prog{gs\_setdefaultmatrix()} only. % gscoord.c -This function in turn is called only from \prog{zsetdefaultmatrix()} which -is the implementation of the \ps{.setdefaultmatrix} operator. -This operator is always (and usually only) called during execution of -\ps{setpagedevice} with the value of the CTM valid -after the possible execution of the \ps{Install} procedure. - -This is the connection between \ps{defaultmatrix} and the -\prog{get\_initial\_matrix} device procedure. -One implication of this relation is that, -if \ps{setpagedevice} is called at least once, -the default matrix will remain fixed until the next call to -\ps{setpagedevice}.\footnote{ - Note that at least one function of the \gs\ kernel - (\prog{gx\_default\_clip\_box()}) - calls the \prog{get\_initial\_matrix} procedure directly - instead of calling \prog{gs\_deviceinitialmatrix()} [gs~6.50]. - I have not investigated whether this could have unwanted consequences.} - -The conclusions to be drawn from this are the following: -\begin{itemize} - \item You need to write your own \prog{get\_initial\_matrix} procedure only - if the device coordinate origin is not in the upper left corner of the - page area as seen from default user space. - \item The driver should not change the default CTM except when - \ps{setpagedevice} is called. - - This means that all parameters the \prog{get\_initial\_matrix} procedure - needs to define default user space should be changed only in the - \prog{put\_params} device procedure. - \item Your implementation of \prog{get\_initial\_matrix} should ignore - \prog{Margins} and any transformation already taken care of in - \ps{setpagedevice} (like \ps{PageOffset}). -\end{itemize} - -\ifdraft -??? Discuss the soft-tumble problem and its solution. -\fi - -%------------------------------------------------------------------------------ - -\subsubsection{The Imageable Area and the Device Coordinate Origin} -\label{HardwareMargins} - -The imageable area of a ghostscript device is described by the \prog{HWMargins} -device variable. -This is an array of four \prog{float}s, -interpreted as distances in~bp from the edges of the page.\footnote{ - The ``canonical margin order'' in \gs, used for several such variables, - is: left, bottom, right, and top, - but this does not tell you which coordinate system defines these directions. - This documentation is missing for several other device structure fields - which require a reference system for their interpretation. - In the case of \prog{HWMargins} one apparently has to look from default user - space (see \prog{gs\_initclip()} in \file{gspath.c}). - In contrast, the standard \texttt{*HWMargins} parameter in PPD files - is explicitly defined with respect to the - feeding direction~\cite[page~114]{PPD4.3}.} -These values can be set by calling: -\begin{program} - void gx_device_set_margins(gx_device *dev, const float *margins, - \ bool move_origin); -\end{program} -If you specify \prog{true} for \prog{move\_origin}, -\gs\ will in addition use the left and top margin values to set the -\prog{Margins} array in such a manner that -the device coordinate origin will be in the top left corner of the imageable -area. -As explained in section~\ref{DevCoord}, -the resulting effect is usually desirable. -However, the way used to achieve it is wrong: -the \prog{Margins} array contains the value of the \ps{Margins} page device -parameter which was introduced to compensate for mechanical misalignments -in a device. -I take this to mean that a value of zero means that no misalignment exists, -a contradiction with the situation achieved by -\prog{gx\_device\_set\_margins()}. -Of course one could tell the user that -when setting \ps{Margins} s/he should take the imageable area into account, -but this becomes a nuisance if the imageable area depends on the -page size. -This is for example the case for Hewlett-Packard's DeskJet printers. - -If you want to position your device coordinate origin in the top left corner -of the imageable area and to leave \ps{Margins} with its standard meaning, -you will therefore have to implement the desired shift of the device coordinate -origin in your driver's \prog{get\_initial\_matrix} device procedure. -This procedure will need to know the top and left margins in device space. - -%------------------------------------------------------------------------------ - -\subsubsection{Landscape Orientation} - -As explained in section~\ref{PsUserSpace}, -the PostScript language requires that -if a user requests landscape orientation -(a \ps{PageSize} value with $\hbox{width} > \hbox{height}$ in a -\ps{setpagedevice} request) -the output device must rotate default user space by $+90^\circ$ with respect -to portrait orientation for the same medium.\footnote{ - I would not consider this rule to be binding for an output device printing - on media of continuously variable dimensions. - In particular, it is certainly inappropriate for a screen viewer and for most - if not all file formats. - But the behaviour is essential for every device printing on - media of discrete sizes.} -However, the only ghostscript drivers I know of which actually do it are -\textit{cljet5\/}~[gs~5.50] and my own \textit{hpdj/pcl3\/} driver. -% I have done an automated check on most of the 137 devices present in gs 5.10 -% as compiled for Debian 2.1 (package gs 5.10-1). The exceptions were the -% screen and file devices lvga256, vgalib, cgmmono, cgm8, and cgm24. The only -% device where an exchange of width and height in the PageSize device parameter -% led to a defaultmatrix with a different orientation was hpdj (cljet5 was not -% among the devices compiled into the excutable). -% Incidentally, hpdj is capable of this only since hpdj 2.2 but at least gave -% an error message before that. -% I have also searched through the gs 5.50 source code for drivers which set -% their own get_initial_matrix() device procedure. I found -% mem_get_initial_matrix(), clj_get_initial_matrix(), pm_get_initial_matrix(), -% win_dib_get_initial_matrix(), and x_get_initial_matrix(). Only -% clj_get_initial_matrix() treats rotation. -% In addition, I have looked for the string "landscape" (irrespective of -% upper/lower case) and found nothing suggestive except in the MS Windows -% viewer gdevwpr2.c where it says: "...does try to set the printer page size -% from the PostScript PageSize, but it isn't working reliably at the moment". - -Your driver can determine that landscape orientation has been requested by -examining the \prog{MediaSize[]} array. -It contains the requested page size in~bp with respect to default user -space.\footnote{ - This interpretation is not documented with the variable's definition - but can be deduced from the fact that it receives the value of the - \ps{PageSize} page device parameter (\prog{gx\_default\_put\_params()}).} -If it is a case of landscape orientation -($\hbox{\prog{MediaSize[0]}} > \hbox{\prog{MediaSize[1]}}$), -you must include a rotation by $+90^\circ$ in your \prog{get\_initial\_matrix} -device procedure and you must modify the \prog{width} and \prog{height} -fields appropriately. - -Unfortunately, \gs's functions \prog{gx\_device\_set\_width\_height()}, -\prog{gx\_device\_set\_resolution()} and \prog{gx\_device\_set\_media\_size()} -all assume that device space and default user space have the same notion about -what is ``vertical'' and what is ``horizontal''. -Hence you must update \prog{width} and \prog{height} directly and guard against -some other instance calling any of these functions and producing inappropriate -values. -The only reliable way I know for this -is to check for this condition in the \prog{open\_device} device procedure and, -if necessary, to reassign \prog{width} and \prog{height} there. -Doing this requires reallocation of storage in the \textit{prn\/} device. - -\ifdraft -??? Problem of the initial matrix routine having the necessary information -\fi - -The same problems arise if your driver supports the \ps{LeadingEdge} page -device parameter because in that case arbitrary orientations of default user -space with respect to device space are possible. - -%============================================================================== - -\subsection{Media Sources and Destinations} - -\Gs~[gs~5.50] sets the page device parameters \ps{\%MediaSource} and -\ps{\%MediaDestination} to the position numbers determined for media source and -media destination respectively -during the process of media selection. - -If your driver supports different media sources or destinations, -its \prog{put\_params} routine should fetch the values of these parameters. - -\Gs\ does support the \ps{MediaPosition} page device parameter for -media selection~[gs~5.50, gs~6.01], -but not by default as a device parameter -(i.e., you must set it with \ps{setpagedevice}, not from the command line), -and you can't use it to select negative position numbers -(this gives a \ps{rangecheck}~[gs~6.01]). - -%============================================================================== - -\ifdraft -\subsection{To be Discussed} %??? - -media sizes, InputAttributes -\fi - -%****************************************************************************** - -\section{\Gs's Colour Treatment} - -%============================================================================== - -\subsection{Native Colour Spaces} \label{NativeColourSpaces} - -\Gs\ does not support \ps{DeviceN} as a native colour space~[gs~5.50]. -The other three possible spaces are supported; -this information is encoded in the \prog{color\_info.num\_components} -device parameter -which can be \prog{1} for \ps{DeviceGray}, -\prog{3} for \ps{DeviceRGB} and \prog{4} in the case of \ps{DeviceCMYK}. - -Note that \prog{gx\_default\_get\_params()} returns these colour space names -as the value of the device parameter -\ps{ProcessColorModel} which will be inappropriate if the device uses, e.g., -the process colour model \ps{DeviceCMY}. -Your driver cannot correct this because -\prog{gx\_default\_put\_params()} signals an error if this -page device parameter has another value than the native colour space name -belonging to the current \prog{color\_info.num\_components} value. -% Source code inspection in gs 5.50. - -%============================================================================== - -\ifdraft - -\subsection{Internal Colour Representation} - -\subsubsection{Colour in the Native Colour Space} - -Colour specifications in a PostScript program can be given in any of the -supported colour spaces. -They are then converted into the native colour space as specified by the -PostScript language definition. -This part is standard and results in certain real numbers -in the range $[0, 1]$. - -??? What are the device colours? Where does \gs\ apply transfer functions? - -For \gs, these -\prog{color\_info.num\_components} floating point numbers are first -converted into instances of type \prog{frac}, -an integer type % (\prog{short}~[gs~6.50]) % gxfrac.h -with the range zero to -$f_1 := 32760 = 2^3 \times 3^2 \times 5 \times 7 \times 13$. -This value is chosen in order to be able to represent -``almost all common fractions'' % gxfrac.h [gs 6.50] -of~1 exactly. -The conversions between \prog{float} and \prog{frac} are defined as follows: -\begin{program} % gxfrac.h in gs 5.50 and 6.50 - \#define frac_1 ((frac)0x7ff8) - \#define frac_1_float ((float)frac_1) - \#define frac2float(fr) ((fr) / frac_1_float) - \#define float2frac(fl) ((frac)(((fl) + 0.5 / frac_1_float) * frac_1_float)) -\end{program} -Assuming infinite precision for floating point arithmetic, -the conversion from a \prog{float}~$x$ to a \prog{frac}~$f$ is therefore -simply: -$$ - f = \left\lfloor x f_1 + {1 \over 2} \right\rfloor -$$ -Looking at the pre-images of the possible results we find that -this map divides the interval $[0, 1]$ into $f_1 + 1$~pieces of unequal length: -the first and the last piece have length $1 / 2 f_1$, -the others have length $1/f_1$. - -\ifdraft -??? Discuss the resulting problems, present the correct solution. -\fi - -??? -are then converted into \d{(device) colour values}, -instances of type \prog{gx\_color\_value}. -This is an unsigned integer type -(at present, it is \prog{unsigned short}~\cite{Drivers6.01}), -and the conversion maps zero to zero and one to -the value of the macro \prog{gx\_max\_color\_value}\footnote{ - This is equal to $2^{\hbox{\prog{gx\_color\_value\_bits}}} - 1$ - where \prog{gx\_color\_value\_bits} is - $8 \times \hbox{\prog{sizeof(gx\_color\_value)}}$ [gs~6.50].}. - % gxcvalue.h - -%------------------------------------------------------------------------------ - -\subsubsection{???} - -??? gx\_color\_index, depth - -%------------------------------------------------------------------------------ - -??? mapping functions (what is called depending on the native colour space) - -%============================================================================== - -\subsection{Intensity Rendering} - -??? \Gs's dithering implementation, 3 possibilities - -%============================================================================== - -\subsection{Process Colour Models} - -??? Example for DeviceCMY. - -\fi % draft - -%****************************************************************************** - -\addcontentsline{toc}{section}{\numberline{}References}\nobreak -\bibliography{Informatik,ghostscript} - -%****************************************************************************** - -\end{document} |