1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536 |
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
- <html>
- <head>
- <title>The interface between Ghostscript and device drivers</title>
- <!-- $Id: Drivers.htm,v 1.21.2.2 2002/02/01 05:31:24 raph Exp $ -->
- <!-- Originally: drivers.txt -->
- <link rel="stylesheet" type="text/css" href="gs.css" title="Ghostscript Style">
- </head>
- <body>
- <!-- [1.0 begin visible header] ============================================ -->
- <!-- [1.1 begin headline] ================================================== -->
- <h1>The interface between Ghostscript and device drivers</h1>
- <!-- [1.1 end headline] ==================================================== -->
- <!-- [1.2 begin table of contents] ========================================= -->
- <h2>Table of contents</h2>
- <blockquote><ul>
- <li><a href="#Adding_drivers">Adding a driver</a>
- <li><a href="#KISS">Keeping things simple</a>
- <li><a href="#Structure">Driver structure</a>
- <ul>
- <li><a href="#Structure_definition">Structure definition</a>
- <li><a href="#Sophisticated">For sophisticated developers only</a>
- </ul>
- <li><a href="#coordinates_and_types">Coordinates and types</a>
- <ul>
- <li><a href="#Coordinate_system">Coordinate system</a>
- <li><a href="#Color_definition">Color definition</a>
- <li><a href="#Types">Types</a>
- </ul>
- <li><a href="#Coding_conventions">Coding conventions</a>
- <ul>
- <li><a href="#Allocating_storage">Allocating storage</a>
- <li><a href="#Driver_instance_allocation">Driver instance allocation</a>
- </ul>
- <li><a href="#Printer_drivers">Printer drivers</a>
- <li><a href="#Driver_procedures">Driver procedures</a>
- <ul>
- <li><a href="#Life_cycle">Life cycle</a>
- <li><a href="#Open_close">Open, close, sync, copy</a>
- <li><a href="#Color_mapping">Color and alpha mapping</a>
- <li><a href="#Pixel_level_drawing">Pixel-level drawing</a>
- <ul>
- <li><a href="#Bitmap_imaging">Bitmap imaging</a>
- <li><a href="#Pixmap_imaging">Pixmap imaging</a>
- <li><a href="#Compositing">Compositing</a>
- [<a href="#S_spec">S</a>, <a href="#T_spec">T</a>, <a href="#F_spec">f</a>,
- <a href="#Compositing_notes">Notes</a>]
- </ul>
- <li><a href="#Polygon_level_drawing">Polygon-level drawing</a>
- <li><a href="#High_level_drawing">High-level drawing</a>
- <ul>
- <li><a href="#Paths">Paths</a>
- <li><a href="#Images">Images</a> [<a href="#Images_notes">Notes</a>]
- <li><a href="#Text">Text</a> [<a href="#Text_notes">Notes</a>]
- </ul>
- <li><a href="#Reading_bits_back">Reading bits back</a>
- <li><a href="#Parameters">Parameters</a>
- <ul>
- <li><a href="#Default_CRD_parameters">Default color rendering dictionary (CRD) parameters</a>
- </ul>
- <li><a href="#External_fonts">External fonts</a>
- <li><a href="#Page_devices">Page devices</a>
- <li><a href="#Miscellaneous">Miscellaneous</a>
- </ul>
- </ul></blockquote>
- <!-- [1.2 end table of contents] =========================================== -->
- <!-- [1.3 begin hint] ====================================================== -->
- <p>For other information, see the <a href="Readme.htm">Ghostscript
- overview</a> and the documentation on <a href="Make.htm">how to build
- Ghostscript</a>.
- <!-- [1.3 end hint] ======================================================== -->
- <hr>
- <!-- [1.0 end visible header] ============================================== -->
- <!-- [2.0 begin contents] ================================================== -->
- <h2><a name="Adding_drivers"></a>Adding a driver</h2>
- <p>
- To add a driver to Ghostscript, first pick a name for your device, say
- "<b><tt>smurf</tt></b>". (Device names must be 1 to 8 characters, begin
- with a letter, and consist only of letters, digits, and underscores. Case
- is significant: all current device names are lower case.) Then all you
- need do is edit <b><tt>contrib.mak</tt></b> in two places.
- <ol>
- <li>The list of devices, in the section headed "Catalog". Add
- <b><tt>smurf</tt></b> to the list.
- <li>The section headed "Device drivers".
- <p>
- Suppose the files containing the smurf driver are called
- "<b><tt>joe</tt></b>" and "<b><tt>fred</tt></b>". Then you should add the
- following lines:
- <blockquote>
- <pre># ------ The SMURF device ------ #
- smurf_=$(GLOBJ)joe.$(OBJ) $(GLOBJ)fred.$(OBJ)
- $(DD)smurf.dev: $(smurf_)
- $(SETDEV) $(DD)smurf $(smurf_)
- $(GLOBJ)joe.$(OBJ) : $(GLSRC)joe.c
- $(GLCC) $(GLO_)joe.$(OBJ) $(C_) $(GLSRC)joe.c
- $(GLOBJ)fred.$(OBJ) : $(GLSRC)fred.c
- $(GLCC) $(GLO_)fred.$(OBJ) $(C_) $(GLSRC)fred.c</pre>
- </blockquote>
- <p>
- and whatever <b><tt>joe.c</tt></b> and <b><tt>fred.c</tt></b> depend on.
- If the smurf driver also needs special libraries, for instance a library
- named "<b><tt>gorf</tt></b>", then the entry should look like this:
- <blockquote>
- <pre>$(DD)smurf.dev : $(smurf_)
- $(SETDEV) $(DD)smurf $(smurf_)
- $(ADDMOD) $(DD)smurf -lib gorf</pre>
- </blockquote>
- <p>
- If, as will usually be the case, your driver is a printer driver (as
- <a href="#Printer_drivers">discussed below</a>), the device entry should
- look like this:
- <blockquote>
- <pre>$(DD)smurf.dev : $(smurf_) $(GLD)page.dev
- $(SETPDEV) $(DD)smurf $(smurf_)</pre>
- </blockquote>
- <p>
- or
- <blockquote>
- <pre>$(DD)smurf.dev : $(smurf_) $(GLD)page.dev
- $(SETPDEV) $(DD)smurf $(smurf_)
- $(ADDMOD) $(DD)smurf -lib gorf</pre>
- </blockquote>
- <p>
- Note that the space before the :, and the explicit compilation rules for the
- .c files, are required for portability,
- </ol>
- <hr>
- <h2><a name="KISS"></a>Keeping things simple</h2>
- <p>
- If you want to add a simple device (specifically, a monochrome printer), you
- probably don't need to read the rest of this document; just use the code in
- an existing driver as a guide. The Epson and Canon BubbleJet drivers <a
- href="../src/gdevepsn.c">gdevepsn.c</a> and <a
- href="../src/gdevbj10.c">gdevbj10.c</a> are good models for dot-matrix
- printers, which require presenting the data for many scan lines at once; the
- DeskJet/LaserJet drivers in <a href="../src/gdevdjet.c">gdevdjet.c</a> are
- good models for laser printers, which take a single scan line at a time but
- support data compression. For color printers, there are unfortunately no
- good models: the two major color inkjet printer drivers, <a
- href="../src/gdevcdj.c">gdevcdj.c</a> and <a
- href="../src/gdevstc.c">gdevstc.c</a>, are far too complex to read.
- <p>
- On the other hand, if you're writing a driver for some more esoteric
- device, you probably do need at least some of the information in the rest
- of this document. It might be a good idea for you to read it in
- conjunction with one of the existing drivers.
- <p>
- Duplication of code, and sheer volume of code, is a serious maintenance and
- distribution problem for Ghostscript. If your device is similar to an
- existing one, try to implement your driver by adding some parameterization
- to an existing driver rather than by copying code to create an entirely new
- source module. <a href="../src/gdevepsn.c">gdevepsn.c</a> and <a
- href="../src/gdevdjet.c">gdevdjet.c</a> are good examples of this approach.
- <hr>
- <h2><a name="Structure"></a>Driver structure</h2>
- <p>
- A device is represented by a structure divided into three parts:
- <ul>
- <li>procedures that are (normally) shared by all instances of each device;
- <li>parameters that are present in all devices but may be different for
- each device or instance; and
- <li>device-specific parameters that may be different for each instance.
- </ul>
- <p>
- Normally the procedure structure is defined and initialized at compile
- time. A prototype of the parameter structure (including both generic and
- device-specific parameters) is defined and initialized at compile time, but
- is copied and filled in when an instance of the device is created. Both of
- these structures should be declared as <b><tt>const</tt></b>, but for backward
- compatibility reasons the latter is not.
- <p>
- The <b><tt>gx_device_common</tt></b> macro defines the common structure
- elements, with the intent that devices define and export a structure along
- the following lines. Do not fill in the individual generic parameter values
- in the usual way for C structures: use the macros defined for this purpose
- in <a href="../src/gxdevice.h">gxdevice.h</a> or, if applicable, <a
- href="../src/gdevprn.h">gdevprn.h</a>.
- <blockquote>
- <pre>typedef struct smurf_device_s {
- gx_device_common;
- <b><em>... device-specific parameters ...</em></b>
- } smurf_device;
- smurf_device gs_smurf_device = {
- <b><em>... macro for generic parameter values ...,</em></b>
- { <b><em>... procedures ...</em></b> }, /* std_procs */
- <b><em>... device-specific parameter values if any ...</em></b>
- };</pre>
- </blockquote>
- <p>
- The device structure instance <b>must</b> have the name
- <b><tt>gs_smurf_device</tt></b>, where <b><tt>smurf</tt></b> is the device
- name used in <b><tt>contrib.mak</tt></b>. <b><tt>gx_device_common</tt></b>
- is a macro consisting only of the element definitions.
- <p>
- All the device procedures are called with the device as the first argument.
- Since each device type is actually a different structure type, the device
- procedures must be declared as taking a <b><tt>gx_device *</tt></b> as
- their first argument, and must cast it to
- <b><tt>smurf_device *</tt></b> internally. For example, in the code
- for the "memory" device, the first argument to all routines is called
- <b><tt>dev</tt></b>, but the routines actually use <b><tt>mdev</tt></b> to
- refer to elements of the full structure, using the following standard
- initialization statement at the beginning of each procedure:
- <blockquote>
- <pre>gx_memory_device *const mdev = (gx_device_memory *)dev;</pre>
- </blockquote>
- <p>
- (This is a cheap version of "object-oriented" programming: in C++, for
- example, the cast would be unnecessary, and in fact the procedure table
- would be constructed by the compiler.)
- <h3><a name="Structure_definition"></a>Structure definition</h3>
- <p>
- You should consult the definition of struct <b><tt>gx_device_s</tt></b> in
- <a href="../src/gxdevice.h">gxdevice.h</a> for the complete details of the
- generic device structure. Some of the most important members of this
- structure for ordinary drivers are:
- <blockquote><table cellpadding=0 cellspacing=0>
- <tr valign=top> <td><b><tt>const char *dname;</tt></b>
- <td>
- <td>The device name
- <tr valign=top> <td><b><tt>bool is_open;</tt></b>
- <td>
- <td>True if device has been opened
- <tr valign=top> <td><b><tt>gx_device_color_info color_info;</tt></b>
- <td>
- <td>Color information
- <tr valign=top> <td><b><tt>int width;</tt></b>
- <td>
- <td>Width in pixels
- <tr valign=top> <td><b><tt>int height;</tt></b>
- <td>
- <td>Height in pixels
- </table></blockquote>
- <p>
- The name in the structure (<b><tt>dname</tt></b>) should be the same as the
- name in <a href="../src/contrib.mak">contrib.mak</a>.
- <h3><a name="Sophisticated"></a>For sophisticated developers only</h3>
- <p>
- If for any reason you need to change the definition of the basic device
- structure, or to add procedures, you must change the following places:
- <blockquote><ul>
- <li>This document and the <a href="News.htm">news document</a> (if you want
- to keep the documentation up to date).
- <li>The definition of <b><tt>gx_device_common</tt></b> and the procedures
- in <a href="../src/gxdevcli.h">gxdevcli.h</a>.
- <li>Possibly, the default forwarding procedures declared in
- <a href="../src/gxdevice.h">gxdevice.h</a> and implemented in
- <a href="../src/gdevnfwd.c">gdevnfwd.c</a>.
- <li>The device procedure record completion routines in
- <a href="../src/gdevdflt.c">gdevdflt.c</a>.
- <li>Possibly, the default device implementation in
- <a href="../src/gdevdflt.c">gdevdflt.c</a>,
- <a href="../src/gdevddrw.c">gdevddrw.c</a>, and
- <a href="../src/gxcmap.c">gxcmap.c</a>.
- <li>The bounding box device in <a href="../src/gdevbbox.c">gdevbbox.c</a>
- (probably just adding <b><tt>NULL</tt></b> procedure entries if the
- new procedures don't produce output).
- <li>These devices that must have complete (non-defaulted) procedure vectors:
- <ul>
- <li>The null device in <a href="../src/gdevnfwd.c">gdevnfwd.c</a>.
- <li>The command list "device" in <a href="../src/gxclist.c">gxclist.c</a>.
- This is not an actual device; it only defines procedures.
- <li>The "memory" devices in <a href="../src/gdevmem.h">gdevmem.h</a> and
- <b><tt>gdevm*.c</tt></b>.
- <li>The halftoning device in <a href="../src/gdevht.c">gdevht.c</a>.
- </ul>
- <li>The clip list accumulation "device" in
- <a href="../src/gxacpath.c">gxacpath.c</a>.
- <li>The clipping "devices" <a href="../src/gxclip.c">gxclip.c</a>,
- <a href="../src/gxclip2.c">gxclip2.c</a>,
- and <a href="../src/gxclipm.c">gxclipm.c</a>.
- <li>The pattern accumulation "device" in
- <a href="../src/gxpcmap.c">gxpcmap.c</a>.
- <li>The hit detection "device" in <a href="../src/gdevhit.c">gdevhit.c</a>.
- <li>The generic printer device macros in
- <a href="../src/gdevprn.h">gdevprn.h</a>.
- <li>The generic printer device code in
- <a href="../src/gdevprn.c">gdevprn.c</a>.
- <li>The RasterOp source device in
- <a href="../src/gdevrops.c">gdevrops.c</a>.
- </ul></blockquote>
- <p>
- You may also have to change the code for
- <b><tt>gx_default_get_params</tt></b> or
- <b><tt>gx_default_put_params</tt></b> in <a
- href="../src/gsdparam.c">gsdparam.c</a>.
- <p>
- You should not have to change any of the real devices in the standard
- Ghostscript distribution (listed in <a href="../src/devs.mak">devs.mak</a>
- and <a href="../src/contrib.mak">contrib.mak</a>) or any of your own
- devices, because all of them are supposed to use the macros in <a
- href="../src/gxdevice.h">gxdevice.h</a> or <a
- href="../src/gdevprn.h">gdevprn.h</a> to define and initialize their state.
- <hr>
- <h2><a name="coordinates_and_types"></a>Coordinates and types</h2>
- <h3><a name="Coordinate_system"></a>Coordinate system</h3>
- <p>
- Since each driver specifies the initial transformation from user
- coordinates to device coordinates, the driver can use any coordinate system
- it wants, as long as a device coordinate will fit in an
- <b><tt>int</tt></b>. (This is only an issue on DOS systems, where ints are
- only 16 bits. User coordinates are represented as floats.) Most current
- drivers use a coordinate system with (0,0) in the upper left corner, with
- <b><em>X</em></b> increasing to the right and <b><em>Y</em></b> increasing
- toward the bottom. However, there is supposed to be nothing in the rest of
- Ghostscript that assumes this, and indeed some drivers use a coordinate
- system with (0,0) in the lower left corner.
- <p>
- Drivers must check (and, if necessary, clip) the coordinate parameters given
- to them: they should not assume the coordinates will be in bounds. The
- <b><tt>fit_fill</tt></b> and <b><tt>fit_copy</tt></b> macros in <a
- href="../src/gxdevice.h">gxdevice.h</a> are very helpful in doing this.
- <h3><a name="Color_definition"></a>Color definition</h3>
- <p>
- Ghostscript represents colors internally as RGB or CMYK values. In
- communicating with devices, however, it assumes that each device has a
- palette of colors identified by integers (to be precise, elements of type
- <b><tt>gx_color_index</tt></b>). Drivers may provide a uniformly spaced
- gray ramp or color cube for halftoning, or they may do their own color
- approximation, or both.
- <p>
- The <b><tt>color_info</tt></b> member of the device structure defines the
- color and gray-scale capabilities of the device. Its type is defined as
- follows:
- <blockquote>
- <pre>typedef struct gx_device_color_info_s {
- int num_components; /* 1 = gray only, 3 = RGB, */
- /* 4 = CMYK */
- int depth; /* # of bits per pixel */
- gx_color_value max_gray; /* # of distinct gray levels -1 */
- gx_color_value max_rgb; /* # of distinct color levels -1 */
- /* (only relevant if num_comp. > 1) */
- gx_color_value dither_gray; /* size of gray ramp for halftoning */
- gx_color_value dither_rgb; /* size of color cube ditto */
- /* (only relevant if num_comp. > 1) */
- } gx_device_color_info;</pre>
- </blockquote>
- <p>
- The following macros (in <a href="../src/gxdevice.h">gxdevice.h</a>) provide
- convenient shorthands for initializing this structure for ordinary
- black-and-white or color devices:
- <blockquote>
- <b><tt>#define dci_black_and_white</tt></b> ...<br>
- <b><tt>#define dci_color(depth,maxv,dither)</tt></b> ...
- </blockquote>
- <p>
- The idea is that a device has a certain number of gray levels
- (<b><tt>max_gray</tt></b>+1) and a certain number of colors
- (<b><tt>max_rgb</tt></b>+1) that it can produce directly. When Ghostscript
- wants to render a given RGB or CMYK color as a device color, it first tests
- whether the color is a gray level (if <b><tt>num_components</tt></b> is 1,
- it converts all colors to gray levels), and if so:
- <blockquote>
- If <b><tt>max_gray</tt></b> is large (>= 31), Ghostscript asks the
- device to approximate the gray level directly. If the device returns a
- valid <b><tt>gx_color_index</tt></b>, Ghostscript uses it. Otherwise,
- Ghostscript assumes that the device can represent
- <b><tt>dither_gray</tt></b> distinct gray levels, equally spaced along the
- diagonal of the color cube, and uses the two nearest ones to the desired
- color for halftoning.
- </blockquote>
- <p>
- If the color is not a gray level:
- <blockquote>
- If <b><tt>max_rgb</tt></b> is large (>= 31), Ghostscript asks the device
- to approximate the color directly. If the device returns a valid
- <b><tt>gx_color_index</tt></b>, Ghostscript uses it. Otherwise,
- Ghostscript assumes that the device can represent
- <blockquote>
- <b><tt>dither_rgb</tt></b> × <b><tt>dither_rgb</tt></b> × <b><tt>dither_rgb</tt></b>
- </blockquote>
- <p>
- distinct colors, equally spaced throughout the color cube, and uses two of
- the nearest ones to the desired color for halftoning.
- </blockquote>
- <h3><a name="Types"></a>Types</h3>
- <p>
- Here is a brief explanation of the various types that appear as parameters
- or results of the drivers.
- <dl>
- <dt><b><tt>gx_color_value</tt></b> (defined in <b><tt>gxdevice.h</tt></b>)
- <dd>This is the type used to represent RGB or CMYK color values. It is
- currently equivalent to unsigned short. However, Ghostscript may use less
- than the full range of the type to represent color values:
- <b><tt>gx_color_value_bits</tt></b> is the number of bits actually used,
- and <b><tt>gx_max_color_value</tt></b> is the maximum value, equal to
- (2^<small><sup><b><tt>gx_max_color_value_bits</tt></b></sup></small>)-1.
- </dl>
- <dl>
- <dt><b><tt>gx_device</tt></b> (defined in <b><tt>gxdevice.h</tt></b>)
- <dd>This is the device structure, as explained above.
- </dl>
- <dl>
- <dt><b><tt>gs_matrix</tt></b> (defined in <b><tt>gsmatrix.h</tt></b>)
- <dd>This is a 2-D homogeneous coordinate transformation matrix, used by
- many Ghostscript operators.
- </dl>
- <dl>
- <dt><b><tt>gx_color_index</tt></b> (defined in <b><tt>gxdevice.h</tt></b>)
- <dd>This is meant to be whatever the driver uses to represent a device
- color. For example, it might be an index in a color map, or it might be R,
- G, and B values packed into a single integer. Ghostscript doesn't ever do
- any computations with <b><tt>gx_color_index</tt></b> values: it gets them
- from <b><tt>map_rgb_color</tt></b> or <b><tt>map_cmyk_color</tt></b> and
- hands them back as arguments to several other procedures. The special
- value <b><tt>gx_no_color_index</tt></b> (defined as
- <b><tt>(gx_color_index)(-1)</tt></b> ) means "transparent" for some of
- the procedures. The type definition is simply:
- <blockquote><b><tt>
- typedef unsigned long gx_color_index;
- </tt></b></blockquote>
- </dl>
- <dl>
- <dt><b><tt>gs_param_list</tt></b> (defined in <a
- href="../src/gsparam.h">gsparam.h</a>)
- <dd>This is a parameter list, which is used to read and set attributes in a
- device. See the comments in <a href="../src/gsparam.h">gsparam.h</a>, and
- the <a href="#Parameters">description of the <b><tt>get_params</tt></b> and
- <b><tt>put_params</tt></b> procedures</a> below, for more detail.
- </dl>
- <dl>
- <dt><b><tt>gx_tile_bitmap</tt></b> (defined in
- <a href="../src/gxbitmap.h">gxbitmap.h</a>)
- <br><b><tt>gx_strip_bitmap</tt></b> (defined in
- <a href="../src/gxbitmap.h">gxbitmap.h</a>)
- <dd>These structure types represent bitmaps to be used as a tile for
- filling a region (rectangle). <b><tt>gx_tile_bitmap</tt></b> is an older
- type lacking <b><tt>shift</tt></b> and <b><tt>rep_shift</tt></b>;
- <b><tt>gx_strip_bitmap</tt></b> has superseded it, and it should not be
- used in new code. Here is a copy of the relevant part of the file:
- <blockquote>
- <pre>/*
- * Structure for describing stored bitmaps.
- * Bitmaps are stored bit-big-endian (i.e., the 2^7 bit of the first
- * byte corresponds to x=0), as a sequence of bytes (i.e., you can't
- * do word-oriented operations on them if you're on a little-endian
- * platform like the Intel 80x86 or VAX). Each scan line must start on
- * a (32-bit) word boundary, and hence is padded to a word boundary,
- * although this should rarely be of concern, since the raster and width
- * are specified individually. The first scan line corresponds to y=0
- * in whatever coordinate system is relevant.
- *
- * For bitmaps used as halftone tiles, we may replicate the tile in
- * X and/or Y, but it is still valuable to know the true tile dimensions
- * (i.e., the dimensions prior to replication). Requirements:
- * width % rep_width = 0
- * height % rep_height = 0
- *
- * For halftones at arbitrary angles, we provide for storing the halftone
- * data as a strip that must be shifted in X for different values of Y.
- * For an ordinary (non-shifted) halftone that has a repetition width of
- * W and a repetition height of H, the pixel at coordinate (X,Y)
- * corresponds to halftone pixel (X mod W, Y mod H), ignoring phase;
- * for a shifted halftone with shift S, the pixel at (X,Y) corresponds
- * to halftone pixel ((X + S * floor(Y/H)) mod W, Y mod H). Requirements:
- * strip_shift < rep_width
- * strip_height % rep_height = 0
- * shift = (strip_shift * (size.y / strip_height)) % rep_width
- */
- typedef struct gx_strip_bitmap_s {
- byte *data;
- int raster; /* bytes per scan line */
- gs_int_point size; /* width, height */
- gx_bitmap_id id;
- ushort rep_width, rep_height; /* true size of tile */
- ushort strip_height;
- ushort strip_shift;
- ushort shift;
- } gx_strip_bitmap;</pre>
- </blockquote>
- </dl>
- <hr>
- <h2><a name="Coding_conventions"></a>Coding conventions</h2>
- <p>
- All the driver procedures defined below that return <b><tt>int</tt></b>
- results return 0 on success, or an appropriate negative error code in the
- case of error conditions. The error codes are defined in <a
- href="../src/gserrors.h">gserrors.h</a>; they correspond directly to the
- errors defined in the PostScript language reference manuals. The most
- common ones for drivers are:
- <blockquote><dl>
- <dt><b><tt>gs_error_invalidfileaccess</tt></b>
- <dd>An attempt to open a file failed.
- <dt><b><tt>gs_error_ioerror</tt></b>
- <dd>An error occurred in reading or writing a file.
- <dt><b><tt>gs_error_limitcheck</tt></b>
- <dd>An otherwise valid parameter value was too large for the
- implementation.
- <dt><b><tt>gs_error_rangecheck</tt></b>
- <dd>A parameter was outside the valid range.
- <dt><b><tt>gs_error_VMerror</tt></b>
- <dd>An attempt to allocate memory failed. (If this happens, the procedure
- should release all memory it allocated before it returns.)
- </dl></blockquote>
- <p>
- If a driver does return an error, rather than a simple return statement it
- should use the <b><tt>return_error</tt></b> macro defined in <a
- href="../src/gx.h">gx.h</a>, which is automatically included by <a
- href="../src/gdevprn.h">gdevprn.h</a> but not by <a
- href="../src/gserrors.h">gserrors.h</a>. For example
- <blockquote><b><tt>
- return_error(gs_error_VMerror);
- </tt></b></blockquote>
- <h3><a name="Allocating_storage"></a>Allocating storage</h3>
- <p>
- While most drivers (especially printer drivers) follow a very similar
- template, there is one important coding convention that is not obvious from
- reading the code for existing drivers: driver procedures must not use
- <b><tt>malloc</tt></b> to allocate any storage that stays around after the
- procedure returns. Instead, they must use <b><tt>gs_malloc</tt></b> and
- <b><tt>gs_free</tt></b>, which have slightly different calling conventions.
- (The prototypes for these are in <a href="../src/gsmemory.h">gsmemory.h</a>,
- which is included in <a href="../src/gx.h">gx.h</a>, which is included in <a
- href="../src/gdevprn.h">gdevprn.h</a>.) This is necessary so that
- Ghostscript can clean up all allocated memory before exiting, which is
- essential in environments that provide only single-address-space
- multi-tasking (some versions of Microsoft Windows).
- <blockquote>
- <pre>char *gs_malloc(uint num_elements, uint element_size,
- const char *client_name);</pre>
- </blockquote>
- <p>
- Like <b><tt>calloc</tt></b>, but unlike <b><tt>malloc</tt></b>,
- <b><tt>gs_malloc</tt></b> takes an element count and an element size. For
- structures, <b><tt>num_elements</tt></b> is 1 and
- <b><tt>element_size</tt></b> is <b><tt>sizeof</tt></b> the structure; for
- byte arrays, <b><tt>num_elements</tt></b> is the number of bytes and
- <b><tt>element_size</tt></b> is 1. Unlike <b><tt>calloc</tt></b>,
- <b><tt>gs_malloc</tt></b> does <b>not</b> clear the block of storage.
- <p>
- The <b><tt>client_name</tt></b> is used for tracing and debugging. It must
- be a real string, not <b><tt>NULL</tt></b>. Normally it is the name of the
- procedure in which the call occurs.
- <blockquote>
- <pre>void gs_free(char *data, uint num_elements, uint element_size,
- const char *client_name);</pre>
- </blockquote>
- <p>
- Unlike <b><tt>free</tt></b>, <b><tt>gs_free</tt></b> demands that
- <b><tt>num_elements</tt></b> and element_size be supplied. It also
- requires a client name, like <b><tt>gs_malloc</tt></b>.
- <h3><a name="Driver_instance_allocation"></a>Driver instance allocation</h3>
- <p>
- All driver instances allocated by Ghostscript's standard allocator must
- point to a "structure descriptor" that tells the garbage collector how to
- trace pointers in the structure. For drivers registered in the normal way
- (using the makefile approach described above), no special care is needed as
- long as instances are created only by calling the
- <b><tt>gs_copydevice</tt></b> procedure defined in <a
- href="../src/gsdevice.h">gsdevice.h</a>. If you have a need to define
- devices that are not registered in this way, you must fill in the stype
- member in any dynamically allocated instances with a pointer to the same
- structure descriptor used to allocate the instance. For more information
- about structure descriptors, see <a href="../src/gsmemory.h">gsmemory.h</a>
- and <a href="../src/gsstruct.h">gsstruct.h</a>.
- <hr>
- <h2><a name="Printer_drivers"></a>Printer drivers</h2>
- <p>
- Printer drivers (which include drivers that write some kind of raster file)
- are especially simple to implement. Of the driver procedures defined in the
- next section, they only need implement two: <b><tt>map_rgb_color</tt></b>
- (or <b><tt>map_cmyk_color</tt></b>) and <b><tt>map_color_rgb</tt></b>. In
- addition, they must implement a <b><tt>print_page</tt></b> or
- <b><tt>print_page_copies</tt></b> procedure. There are macros in <a
- href="../src/gdevprn.h">gdevprn.h</a> that generate the device structure for
- such devices, of which the simplest is <b><tt>prn_device</tt></b>; for an
- example, see <a href="../src/gdevbj10.c">gdevbj10.c</a>. If you are writing
- a printer driver, we suggest you start by reading <a
- href="../src/gdevprn.h">gdevprn.h</a> and the <a
- href="#Color_mapping">subsection on "Color mapping"</a> below; you may be
- able to ignore all the rest of the driver procedures.
- <p>
- The <b><tt>print_page</tt></b> procedures are defined as follows:
- <blockquote>
- <pre>int (*print_page)(P2(gx_device_printer *, FILE *))
- int (*print_page_copies)(P3(gx_device_printer *, FILE *, int))</pre>
- </blockquote>
- <p>
- This procedure must read out the rendered image from the device and write
- whatever is appropriate to the file. To read back one or more scan lines
- of the image, the <b><tt>print_page</tt></b> procedure must call one of the
- following procedures:
- <blockquote>
- <pre>int gdev_prn_copy_scan_lines(P4(gx_device_printer *pdev, int y, byte *str,
- uint size)</pre>
- </blockquote>
- <p>
- For this procedure, <b><tt>str</tt></b> is where the data should be copied to, and <b><tt>size</tt></b> is
- the size of the buffer starting at <b><tt>str</tt></b>. This procedure returns the number
- of scan lines copied, or <0 for an error. <b><tt>str</tt></b> need not be aligned.
- <blockquote>
- <pre>int gdev_prn_get_bits(gx_device_printer *pdev, int y, byte *str,
- byte **actual_data)</pre>
- </blockquote>
- <p>
- This procedure reads out exactly one scan line. If the scan line is
- available in the correct format already, <b><tt>*actual_data</tt></b> is
- set to point to it; otherwise, the scan line is copied to the buffer
- starting at <b><tt>str</tt></b>, and <b><tt>*actual_data</tt></b> is set to
- <b><tt>str</tt></b>. This saves a copying step most of the time.
- <b><tt>str</tt></b> need not be aligned; however, if
- <b><tt>*actual_data</tt></b> is set to point to an existing scan line, it
- will be aligned. (See the description of the <b><tt>get_bits</tt></b>
- procedure below for more details.)
- <p>
- In either case, each row of the image is stored in the form described in
- the comment under <b><tt>gx_tile_bitmap</tt></b> above; each pixel takes
- the number of bits specified as <b><tt>color_info.depth</tt></b> in the
- device structure, and holds values returned by the device's
- <b><tt>map_</tt></b>{<b><tt>rgb</tt></b>,<b><tt>cmyk</tt></b>}<b><tt>_color</tt></b>
- procedure.
- <p>
- The <b><tt>print_page</tt></b> procedure can determine the number of bytes
- required to hold a scan line by calling:
- <blockquote>
- <pre>uint gdev_prn_raster(P1(gx_device_printer *))</pre>
- </blockquote>
- <p>
- For a very simple concrete example, we suggest reading the code in
- <b><tt>bit_print_page</tt></b> in <a href="../src/gdevbit.c">gdevbit.c</a>.
- <p>
- If the device provides <b><tt>print_page</tt></b>, Ghostscript will call
- <b><tt>print_page</tt></b> the requisite number of times to print the
- desired number of copies; if the device provides
- <b><tt>print_page_copies</tt></b>, Ghostscript will call
- <b><tt>print_page_copies</tt></b> once per page, passing it the desired
- number of copies.
- <hr>
- <h2><a name="Driver_procedures"></a>Driver procedures</h2>
- <p>
- Most of the procedures that a driver may implement are optional. If a
- device doesn't supply an optional procedure <b><tt>WXYZ</tt></b>, the entry
- in the procedure structure may be either <b><tt>gx_default_WXYZ</tt></b>,
- for instance <b><tt>gx_default_tile_rectangle</tt></b>, or
- <b><tt>NULL</tt></b> or 0. (The device procedure must also call the
- <b><tt>gx_default_</tt></b> procedure if it doesn't implement the function
- for particular values of the arguments.) Since C compilers supply 0 as the
- value for omitted structure elements, this convention means that statically
- initialized procedure structures continue to work even if new (optional)
- members are added.
- <h3><a name="Life_cycle"></a>Life cycle</h3>
- <p>
- A device instance begins life in a closed state. In this state, no output
- operations will occur. Only the following procedures may be called:
- <blockquote><b><tt>
- open_device<br>
- finish_copydevice<br>
- get_initial_matrix<br>
- get_params<br>
- put_params<br>
- get_hardware_params
- </tt></b></blockquote>
- <p>
- When <b><tt>setdevice</tt></b> installs a device instance in the graphics
- state, it checks whether the instance is closed or open. If the instance
- is closed, <b><tt>setdevice</tt></b> calls the open routine, and then sets
- the state to open. There is currently no user-accessible operation to
- close a device instance. Device instances are only closed when they are
- about to be freed, which occurs in three situations:
- <ul>
- <li>When a <b><tt>restore</tt></b> occurs, if the instance was created since
- the corresponding <b><tt>save</tt></b> and is in a VM being restored. I.e.,
- if the instance was created in local VM since a <b><tt>save</tt></b>, it
- will always be closed and freed by the corresponding
- <b><tt>restore</tt></b>; if it was created in global VM, it will only be
- closed by the outermost <b><tt>restore</tt></b>, regardless of the save
- level at the time the instance was created.
- <li>By the garbage collector, if the instance is no longer accessible.
- <li>When Ghostscript exits (terminates).
- </ul>
- <h3><a name="Open_close"></a>Open, close, sync, copy</h3>
- <dl>
- <dt><b><tt>int (*open_device)(P1(gx_device *))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Open the device: do any initialization associated with making the device
- instance valid. This must be done before any output to the device. The
- default implementation does nothing. <b>NOTE</b>: Clients should never call
- a device's <b><tt>open_device</tt></b> procedure directly: they should
- always call <b><tt>gs_opendevice</tt></b> instead.
- </dl>
- <dl>
- <dt><b><tt>int (*finish_copydevice)(P2(gx_device *dev, const gx_device
- *from_dev))</tt></b> <b><em>[OPTIONAL]</em></b> <dd>Perform any cleanup
- required after <b><tt>copydevice</tt></b> has created a new device instance
- by copying <b><tt>from_dev</tt></b>. If the copy operation should not be
- allowed, this procedure should return an error; the copy will be freed. The
- default implementation allows copying the device prototype, but does not
- allow copying device instances, because instances may contain internal
- pointers that should not be shared between copies, and there is no way to
- determine this from outside the device. <b>NOTE</b>: Clients should never
- call a device's <b><tt>finish_copydevice</tt></b> procedure: this procedure
- is only intended for use by <b><tt>gs_copydevice[2]</tt></b>.
- </dl>
- <dl>
- <dt><b><tt>void (*get_initial_matrix)(P2(gx_device *, gs_matrix *))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Construct the initial transformation matrix mapping user coordinates
- (nominally 1/72 inch per unit) to device coordinates. The default
- procedure computes this from width, height, and
- [<b><tt>xy</tt></b>]<b><tt>_pixels_per_inch</tt></b> on the assumption that
- the origin is in the upper left corner, that is
- <blockquote>
- <b><tt>xx</tt></b> = <b><tt>x_pixels_per_inch</tt></b>/72, <b><tt>xy</tt></b> = 0,<br>
- <b><tt>yx = 0, yy = -y_pixels_per_inch</tt></b>/72,<br>
- <b><tt>tx = 0, ty = height</tt></b>.
- </blockquote>
- </dl>
- <dl>
- <dt><b><tt>int (*sync_output)(P1(gx_device *))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Synchronize the device. If any output to the device has been
- buffered, send or write it now. Note that this may be called several times
- in the process of constructing a page, so printer drivers should <b>not</b>
- implement this by printing the page. The default implementation does
- nothing.
- </dl>
- <dl>
- <dt><b><tt>int (*output_page)(P3(gx_device *, int num_copies, int flush))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Output a fully composed page to the device. The
- <b><tt>num_copies</tt></b> argument is the number of copies that should be
- produced for a hardcopy device. (This may be ignored if the driver has
- some other way to specify the number of copies.) The <b><tt>flush</tt></b>
- argument is true for <b><tt>showpage</tt></b>, false for
- <b><tt>copypage</tt></b>. The default definition just calls
- <b><tt>sync_output</tt></b>. Printer drivers should implement this by
- printing and ejecting the page.
- </dl>
- <dl>
- <dt><b><tt>int (*close_device)(P1(gx_device *))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Close the device: release any associated resources. After this, output
- to the device is no longer allowed. The default implementation does
- nothing. <b>NOTE</b>: Clients should never call a device's
- <b><tt>close_device</tt></b> procedure directly: they should always call
- <b><tt>gs_closedevice</tt></b> instead.
- </dl>
- <h3><a name="Color_mapping"></a>Color and alpha mapping</h3>
- <p>
- A given driver normally implements either <b><tt>map_rgb_color</tt></b> or
- <b><tt>map_cmyk_color</tt></b>, but not both. Black-and-white drivers need
- implement neither. Note that the <b><tt>map_xxx_color</tt></b> procedures
- must not return <b><tt>gx_no_color_index</tt></b> (all 1s).
- <p>
- Note that code in the Ghostscript library may cache the results of calling
- one or more of the color mapping procedures. If the result returned by any
- of these procedures would change (other than as a result of a change made by
- the driver's <b><tt>put_params</tt></b> procedure), the driver must call
- <b><tt>gx_device_decache_colors(dev)</tt></b>.
- <dl>
- <dt><b><tt>gx_color_index (*map_rgb_color)(P4(gx_device *,
- gx_color_value red, gx_color_value green,
- gx_color_value blue))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Map a RGB color to a device color. The range of legal values of the
- RGB arguments is 0 to <b><tt>gx_max_color_value</tt></b>. The default
- algorithm uses the <b><tt>map_cmyk_color</tt></b> procedure if the driver
- supplies one, otherwise returns 1 if any of the values exceeds
- <b><tt>gx_max_color_value</tt></b> / 2, 0 otherwise.
- <p>
- Ghostscript assumes that for devices that have color capability (that is,
- <b><tt>color_info.num_components</tt></b> > 1),
- <b><tt>map_rgb_color</tt></b> returns a color index for a gray level (as
- opposed to a non-gray color) iff red = green = blue.
- </dl>
- <dl>
- <dt><b><tt>gx_color_index (*map_cmyk_color)(P5(gx_device *,
- gx_color_value cyan, gx_color_value magenta,
- gx_color_value yellow, gx_color_value black))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Map a CMYK color to a device color. The range of legal values of the
- CMYK arguments is 0 to <b><tt>gx_max_color_value</tt></b>. The default
- algorithm calls the <b><tt>map_rgb_color</tt></b> procedure, with suitably
- transformed arguments.
- <p>
- Ghostscript assumes that for devices that have color capability (that is,
- <b><tt>color_info.num_components</tt></b> > 1),
- <b><tt>map_cmyk_color</tt></b> returns a color index for a gray level (as
- opposed to a non-gray color) iff cyan = magenta = yellow.
- </dl>
- <dl>
- <dt><b><tt>int (*map_color_rgb)(P3(gx_device *,
- gx_color_index color, gx_color_value rgb[3]))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Map a device color code to RGB values. The default algorithm returns
- (0 if <b><tt>color</tt></b>==0 else <b><tt>gx_max_color_value</tt></b>) for
- all three components.
- </dl>
- <dl>
- <dt><b><tt>gx_color_index (*map_rgb_alpha_color)(P5(gx_device *,
- gx_color_value red, gx_color_value green,
- gx_color_value blue, gx_color_value alpha))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Map a RGB color and an opacity value to a device color. The range of
- legal values of the RGB and alpha arguments is 0 to
- <b><tt>gx_max_color_value</tt></b>; <b><tt>alpha</tt></b> = 0 means
- transparent, <b><tt>alpha</tt></b> = <b><tt>gx_max_color_value</tt></b>
- means fully opaque. The default is to use the
- <b><tt>map_rgb_color</tt></b> procedure and ignore alpha.
- <p>
- Note that if a driver implements <b><tt>map_rgb_alpha_color</tt></b>, it
- must also implement <b><tt>map_rgb_color</tt></b>, and must implement them
- in such a way that
- <b><tt>map_rgb_alpha_color(dev, r, g, b, gx_max_color_value)</tt></b>
- returns the same value as
- <b><tt>map_rgb_color(dev, r, g, b)</tt></b>.
- </dl>
- <dl>
- <dt><b><tt>int (*map_color_rgb_alpha)(P3(gx_device *,
- gx_color_index color, gx_color_value rgba[4]))</tt></b>
- <b><em>[OPTIONAL]</em></b>
- <dd>Map a device color code to RGB and alpha values. The default
- implementation calls <b><tt>map_color_rgb</tt></b> and fills in
- <b><tt>gx_max_color_value</tt></b> for alpha.
- <p>
- Note that if a driver implements <b><tt>map_color_rgb_alpha</tt></b>, it
- must also implement <b><tt>map_color_rgb</tt></b>, and must implement them
- in such a way that the first 3 values returned by
- <b><tt>map_color_rgb_alpha</tt></b> are the same as the values returned by
- <b><tt>map_color_rgb</tt></b>.
- <p>
- Note that CMYK devices currently do not support variable opacity; alpha is
- ignored on such devices.
- </dl>
- <dl>
- <dt><b><tt>typedef enum { go_text,
- go_graphics } graphic_object_type; int
- (*get_alpha_bits)(P4(gx_device *dev,
- graphic_object_type type))</tt></b> <b><em>[OPTIONAL] [OBSOLETE]</em></b>
- <dd>This procedure is no longer used: it is replaced by the
- color_info.anti_alias member of the driver structure. However, it still
- appears in the driver procedure vector for backward compatibility. It
- should never be called, and drivers should not implement it.
- </dl>
- <h3><a name="Pixel_level_drawing"></a>Pixel-level drawing</h3>
- <p>
- This group of drawing operations specifies data at the pixel level. All
- drawing operations use device coordinates and device color values.
- <dl>
- <dt><b><tt>int (*fill_rectangle)(P6(gx_device *, int x,
- int y, int width, int height,
- gx_color_index color))</tt></b>
- <dd>Fill a rectangle with a color. The set of pixels filled is {(px,py) |
- x <= px < x + width and y <= py < y + height}. In other words,
- the point <em>(x,y)</em> is included in the rectangle, as are
- <em>(x+w-1,y)</em>, <em>(x,y+h-1)</em>, and <em>(x+w-1,y+h-1)</em>, but
- <b><em>not</em></b> <em>(x+w,y)</em>, <em>(x,y+h)</em>, or
- <em>(x+w,y+h)</em>. If <b><tt>width</tt></b> <= 0 or
- height <= 0, <b><tt>fill_rectangle</tt></b> should return 0
- without drawing anything.
- <p>
- Note that <b><tt>fill_rectangle</tt></b> is the only non-optional procedure
- in the driver interface.
- </dl>
- <h4><a name="Bitmap_imaging"></a>Bitmap imaging</h4>
- <p>
- Bitmap (or pixmap) images are stored in memory in a nearly standard way.
- The first byte corresponds to <em>(0,0)</em> in the image coordinate
- system: bits (or polybit color values) are packed into it left to right.
- There may be padding at the end of each scan line: the distance from one
- scan line to the next is always passed as an explicit argument.
- <dl>
- <dt><b><tt>int (*copy_mono)(P11(gx_device *,
- const unsigned char *data, int data_x, int raster,
- gx_bitmap_id id, int x, int y, int width,
- int height, gx_color_index color0,
- gx_color_index color1))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Copy a monochrome image (similar to the PostScript image operator).
- Each scan line is raster bytes wide. Copying begins at
- (<b><tt>data_x</tt></b>,0) and transfers a rectangle of the given width and
- height to the device at device coordinate <em>(x,y)</em>. (If the transfer
- should start at some non-zero y value in the data, the caller can adjust
- the data address by the appropriate multiple of the raster.) The copying
- operation writes device color <b><tt>color0</tt></b> at each 0-bit, and
- <b><tt>color1</tt></b> at each 1-bit: if <b><tt>color0</tt></b> or
- <b><tt>color1</tt></b> is <b><tt>gx_no_color_index</tt></b>, the device
- pixel is unaffected if the image bit is 0 or 1 respectively. If
- <b><tt>id</tt></b> is different from <b><tt>gx_no_bitmap_id</tt></b>, it
- identifies the bitmap contents unambiguously; a call with the same
- <b><tt>id</tt></b> will always have the same <b><tt>data</tt></b>,
- <b><tt>raster</tt></b>, and data contents.
- <p>
- This operation, with
- <b><tt>color0</tt></b> = <b><tt>gx_no_color_index</tt></b>, is
- the workhorse for text display in Ghostscript, so implementing it
- efficiently is very important.
- </dl>
- <dl>
- <dt><b><tt>int (*tile_rectangle)(P10(gx_device *,
- const gx_tile_bitmap *tile, int x, int y,
- int width, int height, gx_color_index color0,
- gx_color_index color1, int phase_x, int phase_y))</tt></b>
- <b><em>[OPTIONAL] [OBSOLETE]</em></b>
- <dd>This procedure is still supported, but has been superseded by
- <b><tt>strip_tile_rectangle</tt></b>. New drivers should implement
- <b><tt>strip_tile_rectangle</tt></b>; if they cannot cope with non-zero
- shift values, they should test for this explicitly and call the default
- implementation (<b><tt>gx_default_strip_tile_rectangle</tt></b>) if
- shift != 0. Clients should call
- <b><tt>strip_tile_rectangle</tt></b>, not <b><tt>tile_rectangle</tt></b>.
- </dl>
- <dl>
- <dt><b><tt>int (*strip_tile_rectangle)(P10(gx_device *,
- const gx_strip_bitmap *tile, int x, int y,
- int width, int height, gx_color_index color0,
- gx_color_index color1, int phase_x, int phase_y))</tt></b>
- <b><em>[OPTIONAL]</em></b>
- <dd>Tile a rectangle. Tiling consists of doing multiple
- <b><tt>copy_mono</tt></b> operations to fill the rectangle with copies of
- the tile. The tiles are aligned with the device coordinate system, to
- avoid "seams". Specifically, the (<b><tt>phase_x</tt></b>,
- <b><tt>phase_y</tt></b>) point of the tile is aligned with the origin of
- the device coordinate system. (Note that this is backwards from the
- PostScript definition of halftone phase.) <b><tt>phase_x</tt></b> and
- <b><tt>phase_y</tt></b> are guaranteed to be in the range
- <em>[0..</em><b><tt>tile->width</tt></b><em>)</em> and
- <em>[0..</em><b><tt>tile->height</tt></b><em>)</em> respectively.
- <p>
- If <b><tt>color0</tt></b> and <b><tt>color1</tt></b> are both
- <b><tt>gx_no_color_index</tt></b>, then the tile is a color pixmap, not a
- bitmap: see the next section.
- <p>
- This operation is the workhorse for halftone filling in Ghostscript, so
- implementing it efficiently for solid tiles (that is, where either
- <b><tt>color0</tt></b> and <b><tt>color1</tt></b> are both
- <b><tt>gx_no_color_index</tt></b>, for colored halftones, or neither one is
- <b><tt>gx_no_color_index</tt></b>, for monochrome halftones) is very
- important.
- </dl>
- <h4><a name="Pixmap_imaging"></a>Pixmap imaging</h4>
- <p>
- Pixmaps are just like bitmaps, except that each pixel occupies more than
- one bit. All the bits for each pixel are grouped together (this is
- sometimes called "chunky" or "Z" format). For <b><tt>copy_color</tt></b>,
- the number of bits per pixel is given by the
- <b><tt>color_info.depth</tt></b> parameter in the device structure: the
- legal values are 1, 2, 4, 8, 16, 24, or 32. The pixel values are device
- color codes (that is, whatever it is that <b><tt>map_rgb_color</tt></b>
- returns).
- <dl>
- <dt><b><tt>int (*copy_color)(P9(gx_device *,
- const unsigned char *data, int data_x, int raster,
- gx_bitmap_id id, int x, int y, int width,
- int height))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Copy a color image with multiple bits per pixel. The raster is in
- bytes, but <b><tt>x</tt></b> and <b><tt>width</tt></b> are in pixels, not
- bits. If <b><tt>id</tt></b> is different from
- <b><tt>gx_no_bitmap_id</tt></b>, it identifies the bitmap contents
- unambiguously; a call with the same <b><tt>id</tt></b> will always have the
- same <b><tt>data</tt></b>, <b><tt>raster</tt></b>, and data contents.
- <p>
- We do not provide a separate procedure for tiling with a pixmap; instead,
- <b><tt>tile_rectangle</tt></b> can also take colored tiles. This is
- indicated by the <b><tt>color0</tt></b> and <b><tt>color1</tt></b>
- arguments' both being <b><tt>gx_no_color_index</tt></b>. In this case, as
- for <b><tt>copy_color</tt></b>, the <b><tt>raster</tt></b> and
- <b><tt>height</tt></b> in the "bitmap" are interpreted as for real bitmaps,
- but the <b><tt>x</tt></b> and <b><tt>width</tt></b> are in pixels, not
- bits.
- </dl>
- <h4><a name="Compositing"></a>Compositing</h4>
- <p>
- In addition to direct writing of opaque pixels, devices must also support
- compositing. Currently two kinds of compositing are defined
- (<b><tt>RasterOp</tt></b> and alpha-based), but more may be added in the
- future.
- <blockquote>
- <b><em>THIS AREA OF THE INTERFACE IS SOMEWHAT UNSTABLE: USE AT YOUR OWN
- RISK.</em></b>
- </blockquote>
- <dl>
- <dt><b><tt>int (*copy_alpha)(P11(gx_device *dev,
- const unsigned char *data, int data_x, int raster,
- gx_bitmap_id id, int x, int y, int width,
- int height, gx_color_index color, int depth))</tt></b>
- <b><em>[OPTIONAL]</em></b>
- <dd>This procedure is somewhat misnamed: it was added to the interface
- before we really understood alpha channel and compositing.
- <p>
- Fill a given region with a given color modified by an individual alpha
- value for each pixel. For each pixel, this is equivalent to
- alpha-compositing with a source pixel whose alpha value is obtained from
- the pixmap (<b><tt>data</tt></b>, <b><tt>data_x</tt></b>, and
- <b><tt>raster</tt></b>) and whose color is the given color (which has
- <b><em>not</em></b> been premultiplied by the alpha value), using the Sover
- rule. <b><tt>depth</tt></b>, the number of bits per alpha value, is either
- 2 or 4, and in any case is always a value returned by a previous call on
- the <b><tt>get_alpha_bits</tt></b> procedure. Note that if
- <b><tt>get_alpha_bits</tt></b> always returns 1, this procedure will never
- be called.
- </dl>
- <dl>
- <dt><b><tt>int (*create_compositor)(P5(dev_t *dev,
- gx_device_t **pcdev, const gs_composite_t *pcte,
- const gs_imager_state *pis, gs_memory_t *memory))</tt></b>
- <b><em>[OPTIONAL]</em></b>
- <dd>Create a new device (called a "compositing device" or "compositor")
- that will composite data written to it with the device's existing data,
- according to the compositing function defined by <b><tt>*pcte</tt></b>.
- Devices will normally implement this in one of the following standard ways:
- <ul>
- <li>Devices that don't do any imaging and don't forward any imaging
- operations (for example, the null device, the hit detection device, and the
- clipping list accumulation device) simply return themselves, which
- effectively ignores the compositing function.
- <li>"Leaf" devices that do imaging and have no special optimizations for
- compositing (for example, some memory devices) ask the
- <b><tt>gs_composite_t</tt></b> to create a default compositor.
- <li>Leaf devices that can implement some kinds of compositing operation
- efficiently (for example, monobit memory devices and RasterOp) inspect the
- type and values of <b><tt>*pcte</tt></b> to determine whether it specifies
- such an operation: if so, they create a specialized compositor, and if not,
- they ask the <b><tt>gs_composite_t</tt></b> to create a default compositor.
- </ul>
- <p>
- Other kinds of forwarding devices, which don't fall into any of these
- categories, require special treatment. In principle, what they do is ask
- their target to create a compositor, and then create and return a copy of
- themselves with the target's new compositor as the target of the copy.
- There is a possible default implementation of this approach: if the
- original device was <b>D</b> with target <b>T</b>, and <b>T</b> creates a
- compositor <b>C</b>, then the default implementation creates a device
- <b>F</b> that for each operation temporarily changes <b>D</b>'s target to
- <b>C</b>, forwards the operation to <b>D</b>, and then changes <b>D</b>'s
- target back to <b>T</b>. However, the Ghostscript library currently only
- creates a compositor with an imaging forwarding device as target in a few
- specialized situations (banding, and bounding box computation), and these
- are handled as special cases.
- <p>
- Note that the compositor may have a different color space, color
- representation, or bit depth from the device to which it is compositing.
- For example, alpha-compositing devices use standard-format chunky color
- even if the underlying device doesn't.
- <p>
- Closing a compositor frees all of its storage, including the compositor
- itself. However, since the <b><tt>create_compositor</tt></b> call may
- return the same device, clients must check for this case, and only call the
- close procedure if a separate device was created.
- </dl>
- <p>
- <font size="+1">
- <b><em>[strip_]copy_rop WILL BE SUPERSEDED BY COMPOSITORS</em></b>
- </font>
- <dl>
- <dt><b><tt>int (*copy_rop)(P15(gx_device *dev,
- const byte *sdata, int sourcex, uint sraster,
- gx_bitmap_id id, const gx_color_index *scolors,
- const gx_tile_bitmap *texture,
- const gx_color_index *tcolors, int x, int y,
- int width, int height, int phase_x, int phase_y,
- int command))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>This procedure is still supported, but has been superseded by
- <b><tt>strip_copy_rop</tt></b>. New drivers should implement
- <b><tt>strip_copy_rop</tt></b>; if they cannot cope with non-zero shift
- values in the texture, they should test for this explicitly and call the
- default implementation (<b><tt>gx_default_strip_copy_rop</tt></b>) if
- shift != 0. Clients should call <b><tt>strip_copy_rop</tt></b>,
- not <b><tt>copy_rop</tt></b>.
- </dl>
- <dl>
- <dt><b><tt>int (*strip_copy_rop)(P15(gx_device *dev,
- const byte *sdata, int sourcex, uint sraster,
- gx_bitmap_id id, const gx_color_index *scolors,
- const gx_strip_bitmap *texture,
- const gx_color_index *tcolors, int x, int y,
- int width, int height, int phase_x, int phase_y,
- int command))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Combine an optional source image <b>S</b> (as for
- <b><tt>copy_mono</tt></b> or <b><tt>copy_color</tt></b>) and an optional
- texture <b>T</b> (a tile, as for <b><tt>tile_rectangle</tt></b>) with the
- existing bitmap or pixmap <b>D</b> held by the driver, pixel by pixel,
- using any 3-input Boolean operation as modified by "transparency" flags:
- schematically, set <b>D = f(D,S,T)</b>, computing <b>f</b> in RGB
- space rather than using actual device pixel values. <b>S</b> and <b>T</b>
- may each (independently) be a solid color, a bitmap with "foreground" and
- "background" colors, or a pixmap. This is a complex (and currently rather
- slow) operation. The arguments are as follows:
- <blockquote><table cellpadding=0 cellspacing=0>
- <tr valign=top> <td><b><tt>dev</tt></b>
- <td>
- <td>the device, as for all driver procedures
- <tr valign=top> <td><b><tt>sdata</tt></b>, <b><tt>sourcex</tt></b>, <b><tt>sraster</tt></b>, <b><tt>id</tt></b>, <b><tt>scolors</tt></b>
- <td>
- <td>specify <b>S</b>, <a href="#S_spec">see below</a>
- <tr valign=top> <td><b><tt>texture</tt></b>, <b><tt>tcolors</tt></b>
- <td>
- <td>specify <b>T</b>, <a href="#T_spec">see below</a>
- <tr valign=top> <td><b><tt>x</tt></b>, <b><tt>y</tt></b>, <b><tt>width</tt></b>, <b><tt>height</tt></b>
- <td>
- <td>as for the other copy and fill procedures
- <tr valign=top> <td><b><tt>phase_x</tt></b>, <b><tt>phase_y</tt></b>
- <td>
- <td>part of <b>T</b> specification, <a href="#T_spec">see below</a>
- <tr valign=top> <td><b><tt>command</tt></b>
- <td>
- <td><a href="#F_spec">see below</a>
- </table></blockquote>
- </dl>
- <h5><a name="S_spec"></a>The source specification S</h5>
- <p>
- As noted above, the source <b>S</b> may be a solid color, a bitmap, or a
- pixmap. If <b>S</b> is a solid color:
- <ul>
- <li><b><tt>sdata</tt></b>, <b><tt>sourcex</tt></b>,
- <b><tt>sraster</tt></b>, and <b><tt>id</tt></b> are irrelevant.
- <li><b><tt>scolors</tt></b> points to two <b><tt>gx_color_index</tt></b>
- values; <b><tt>scolors[0]</tt></b> = <b><tt>scolors[1]</tt></b> = the
- color.
- </ul>
- <p>
- If <b>S</b> is a bitmap:
- <ul>
- <li><b><tt>sdata</tt></b>, <b><tt>sourcex</tt></b>,
- <b><tt>sraster</tt></b>, and <b><tt>id</tt></b> arguments are as for
- <b><tt>copy_mono</tt></b> or <b><tt>copy_color</tt></b>
- (<b><tt>data</tt></b>, <b><tt>data_x</tt></b>, <b><tt>raster</tt></b>,
- <b><tt>id</tt></b>), and specify a source bitmap.
- <li><b><tt>scolors</tt></b> points to two <b><tt>gx_color_index</tt></b>
- values; <b><tt>scolors[0]</tt></b> is the background color (the color
- corresponding to 0-bits in the bitmap), <b><tt>scolors[1]</tt></b> is the
- foreground color (the color corresponding to 1-bits in the bitmap).
- </ul>
- <p>
- If <b>S</b> is a pixmap:
- <ul>
- <li><b><tt>sdata</tt></b>, <b><tt>sourcex</tt></b>,
- <b><tt>sraster</tt></b>, and <b><tt>id</tt></b> arguments are as for
- <b><tt>copy_mono</tt></b> or <b><tt>copy_color</tt></b>
- (<b><tt>data</tt></b>, <b><tt>data_x</tt></b>, <b><tt>raster</tt></b>,
- <b><tt>id</tt></b>), and specify a source pixmap whose depth is the same as
- the depth of the destination.
- <li><b><tt>scolors</tt></b> is <b><tt>NULL</tt></b>.
- </ul>
- <p>
- Note that if the source is a bitmap with background=0 and foreground=1, and
- the destination is 1 bit deep, then the source can be treated as a pixmap
- (scolors=<b><tt>NULL</tt></b>).
- <h5><a name="T_spec"></a>The texture specification T</h5>
- <p>
- Similar to the source, the texture <b>T</b> may be a solid color, a bitmap,
- or a pixmap. If <b>T</b> is a solid color:
- <ul>
- <li>The texture pointer is irrelevant.
- <li><b><tt>tcolors</tt></b> points to two <b><tt>gx_color_index</tt></b>
- values; <b><tt>tcolors[0]</tt></b> = <b><tt>tcolors[1]</tt></b> = the
- color.
- </ul>
- <p>
- If <b>T</b> is a bitmap:
- <ul>
- <li>The texture argument points to a <b><tt>gx_tile_bitmap</tt></b>, as for
- the <b><tt>tile_rectangle</tt></b> procedure. Similarly,
- <b><tt>phase_x</tt></b> and <b><tt>phase_y</tt></b> specify the offset of
- the texture relative to the device coordinate system origin, again as for
- <b><tt>tile_rectangle</tt></b>. The tile is a bitmap (1 bit per pixel).
- <li><b><tt>tcolors</tt></b> points to two <b><tt>gx_color_index</tt></b>
- values; <b><tt>tcolors[0]</tt></b> is the background color (the color
- corresponding to 0-bits in the bitmap), <b><tt>tcolors[1]</tt></b> is the
- foreground color (the color corresponding to 1-bits in the bitmap).
- </ul>
- <p>
- If <b>T</b> is a pixmap:
- <ul>
- <li>The texture argument points to a <b><tt>gx_tile_bitmap</tt></b> whose
- depth is the same as the depth of the destination.
- <li>tcolors is <b><tt>NULL</tt></b>.
- </ul>
- <p>
- Again, if the texture is a bitmap with background=0 and foreground=1, and
- the destination depth is 1, the texture bitmap can be treated as a pixmap
- (tcolors=<b><tt>NULL</tt></b>).
- <p>
- Note that while a source bitmap or pixmap has the same width and height as
- the destination, a texture bitmap or pixmap has its own width and height
- specified in the <b><tt>gx_tile_bitmap</tt></b> structure, and is
- replicated or clipped as needed.
- <h5><a name="F_spec"></a>The function specification f</h5>
- <p>
- "Command" indicates the raster operation and transparency as follows:
- <blockquote><table cellpadding=0 cellspacing=0>
- <tr valign=bottom>
- <th>Bits
- <td>
- <td>
- <tr valign=top> <td>7-0
- <td>
- <td>raster op
- <tr valign=top> <td>8
- <td>
- <td>0 if source opaque, 1 if source transparent
- <tr valign=top> <td>9
- <td>
- <td>0 if texture opaque, 1 if texture transparent
- <tr valign=top> <td>?-10
- <td>
- <td>unused, must be 0
- </table></blockquote>
- <p>
- The raster operation follows the Microsoft and H-P specification. It is an
- 8-element truth table that specifies the output value for each of the
- possible 2×2×2 input values as follows:
- <blockquote><table cellpadding=0 cellspacing=0>
- <tr valign=bottom>
- <th>Bit
- <td>
- <th>Texture
- <td>
- <th>Source
- <td>
- <th>Destination
- <tr> <td colspan=7><hr>
- <tr valign=top> <td align=center>7
- <td>
- <td align=center>1
- <td>
- <td align=center>1
- <td>
- <td align=center>1
- <tr valign=top> <td align=center>6
- <td>
- <td align=center>1
- <td>
- <td align=center>1
- <td>
- <td align=center>0
- <tr valign=top> <td align=center>5
- <td>
- <td align=center>1
- <td>
- <td align=center>0
- <td>
- <td align=center>1
- <tr valign=top> <td align=center>4
- <td>
- <td align=center>1
- <td>
- <td align=center>0
- <td>
- <td align=center>0
- <tr valign=top> <td align=center>3
- <td>
- <td align=center>0
- <td>
- <td align=center>1
- <td>
- <td align=center>1
- <tr valign=top> <td align=center>2
- <td>
- <td align=center>0
- <td>
- <td align=center>1
- <td>
- <td align=center>0
- <tr valign=top> <td align=center>1
- <td>
- <td align=center>0
- <td>
- <td align=center>0
- <td>
- <td align=center>1
- <tr valign=top> <td align=center>0
- <td>
- <td align=center>0
- <td>
- <td align=center>0
- <td>
- <td align=center>0
- </table></blockquote>
- <p>
- Transparency affects the output in the following way. A source or texture
- pixel is considered transparent if its value is all 1s (for instance, 1 for
- bitmaps, <tt>0xffffff</tt> for 24-bit RGB pixmaps) <b><em>and</em></b> the
- corresponding transparency bit is set in the command. For each pixel, the
- result of the Boolean operation is written into the destination iff neither
- the source nor the texture pixel is transparent. (Note that the H-P
- RasterOp specification, on which this is based, specifies that if the
- source and texture are both all 1s and the command specifies transparent
- source and opaque texture, the result <b><em>should</em></b> be written in
- the output. We think this is an error in the documentation.)
- <h5><a name="Compositing_notes"></a>Notes</h5>
- <p>
- <b><tt>copy_rop</tt></b> is defined to operate on pixels in RGB space,
- again following the H-P and Microsoft specification. For devices that
- don't use RGB (or gray-scale with black = 0, white = all 1s) as their
- native color representation, the implementation of <b><tt>copy_rop</tt></b>
- must convert to RGB or gray space, do the operation, and convert back (or
- do the equivalent of this). Here are the <b><tt>copy_rop</tt></b>
- equivalents of the most important previous imaging calls. We assume the
- declaration:
- <blockquote><b><tt>
- static const gx_color_index white2[2] = { 1, 1 };
- </tt></b></blockquote>
- <p>
- Note that <b><tt>rop3_S</tt></b> may be replaced by any other Boolean operation.
- For monobit devices, we assume that black = 1.
- <blockquote>
- <pre>/* For all devices: */
- (*fill_rectangle)(dev, x, y, w, h, color) ==>
- { gx_color_index colors[2];
- colors[0] = colors[1] = color;
- (*dev_proc(dev, copy_rop))(dev, NULL, 0, 0, gx_no_bitmap_id, colors,
- NULL, colors /*irrelevant*/,
- x, y, w, h, 0, 0, rop3_S);
- }
- /* For black-and-white devices only: */
- (*copy_mono)(dev, base, sourcex, sraster, id,
- x, y, w, h, (gx_color_index)0, (gx_color_index)1) ==>
- (*dev_proc(dev, copy_rop))(dev, base, sourcex, sraster, id, NULL,
- NULL, white2 /*irrelevant*/,
- x, y, w, h, 0, 0, rop3_S);
- /* For color devices, where neither color0 nor color1 is gx_no_color_index: */
- (*copy_mono)(dev, base, sourcex, sraster, id,
- x, y, w, h, color0, color1) ==>
- { gx_color_index colors[2];
- colors[0] = color0, colors[1] = color1;
- (*dev_proc(dev, copy_rop))(dev, base, sourcex, sraster, id, colors,
- NULL, white2 /*irrelevant*/,
- x, y, w, h, 0, 0, rop3_S);
- }
- /* For black-and-white devices only: */
- (*copy_mono)(dev, base, sourcex, sraster, id,
- x, y, w, h, gx_no_color_index, (gx_color_index)1) ==>
- (*dev_proc(dev, copy_rop))(dev, base, sourcex, sraster, id, NULL,
- NULL, white2 /*irrelevant*/,
- x, y, w, h, 0, 0,
- rop3_S | lop_S_transparent);
- /* For all devices: */
- (*copy_color)(dev, base, sourcex, sraster, id,
- x, y, w, h) ==> [same as first copy_mono above]
- /* For black-and-white devices only: */
- (*tile_rectangle)(dev, tile, x, y, w, h,
- (gx_color_index)0, (gx_color_index)1, px, py) ==>
- (*dev_proc(dev, copy_rop))(dev, NULL, 0, 0, gx_no_bitmap_id,
- white2 /*irrelevant*/,
- tile, NULL,
- x, y, w, h, px, py, rop3_T)
- </pre></blockquote>
- <h3><a name="Polygon_level_drawing"></a>Polygon-level drawing</h3>
- <p>
- In addition to the pixel-level drawing operations that take integer device
- coordinates and pure device colors, the driver interface includes
- higher-level operations that draw polygons using fixed-point coordinates,
- possibly halftoned colors, and possibly a non-default logical operation.
- <p>
- The <b><tt>fill_</tt></b>* drawing operations all use the center-of-pixel
- rule: a pixel is colored iff its center falls within the polygonal region
- being filled. If a pixel center <em>(X+0.5,Y+0.5)</em> falls exactly on
- the boundary, the pixel is filled iff the boundary is horizontal and the
- filled region is above it, or the boundary is not horizontal and the filled
- region is to the right of it.
- <dl>
- <dt><b><tt>int (*fill_trapezoid)(P10(gx_device *dev,
- const gs_fixed_edge *left, const gs_fixed_edge *right,
- fixed ybot, fixed ytop, bool swap_axes,
- const gx_drawing_color *pdcolor,
- gs_logical_operation_t lop))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Fill a trapezoid. The bottom and top edges are parallel to the x
- axis, and are defined by <b><tt>ybot</tt></b> and <b><tt>ytop</tt></b>,
- respectively. The left and right edges are defined by <b><tt>left</tt></b>
- and <b><tt>right</tt></b>. Both of these respresent lines (<b><tt>gs_fixed_edge</tt></b>
- is defined in <a href="../src/gxdevcli.h">gxdevcli.h</a> and consists
- of <b><tt>gs_fixed_point</tt></b> <b><tt>start</tt></b> and <b><tt>end</tt></b> points).
- The y coordinates of these lines need not have any specific relation to
- <b><tt>ybot</tt></b> and <b><tt>ytop</tt></b>. The routine is defined this way so
- that the filling algorithm can subdivide edges and still guarantee
- that the exact same pixels will be filled. If
- <b><tt>swap_axes</tt></b> is set, the meanings of X and Y are
- interchanged.
- </dl>
- <dl>
- <dt><b><tt>int (*fill_parallelogram)(P9(gx_device *dev,
- fixed px, fixed py, fixed ax, fixed ay, fixed bx,
- fixed by, const gx_drawing_color *pdcolor,
- gs_logical_operation_t lop))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Fill a parallelogram whose corners are <em>(px,py)</em>,
- <em>(px+ax,py+ay)</em>, <em>(px+bx,py+by)</em>, and
- <em>(px+ax+bx,py+ay+by)</em>. There are no constraints on the values of
- any of the parameters, so the parallelogram may have any orientation
- relative to the coordinate axes.
- </dl>
- <dl>
- <dt><b><tt>int (*fill_triangle)(P9(gx_device *dev, fixed px,
- fixed py, fixed ax, fixed ay, fixed bx, fixed by,
- const gx_drawing_color *pdcolor,
- gs_logical_operation_t lop))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Fill a triangle whose corners are <em>(px,py)</em>,
- <em>(px+ax,py+ay)</em>, and <em>(px+bx,py+by)</em>.
- </dl>
- <dl>
- <dt><b><tt>int (*draw_thin_line)(P7(gx_device *dev,
- fixed fx0, fixed fy0, fixed fx1, fixed fy1,
- const gx_drawing_color *pdcolor,
- gs_logical_operation_t lop))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Draw a one-pixel-wide line from <em>(fx0,fy0)</em> to
- <em>(fx1,fy1)</em>.
- </dl>
- <dl>
- <dt><b><tt>int (*draw_line)(P6(gx_device *dev, int x0, int y0,
- int x1, int y1, gx_color_index color))</tt></b>
- <b><em>[OPTIONAL] [OBSOLETE]</em></b>
- <dd>This procedure is no longer used: it is replaced by the draw_thin_line
- procedure. However, still appears in the driver procedure vector for
- backward compatibility. It should never be called, and drivers should not
- implement it.
- </dl>
- <h3><a name="High_level_drawing"></a>High-level drawing</h3>
- <p>
- In addition to the lower-level drawing operations described above, the
- driver interface provides a set of high-level operations. Normally these
- will have their default implementation, which converts the high-level
- operation to the low-level ones just described; however, drivers that
- generate high-level output formats such as CGM, or communicate with devices
- that have firmware for higher-level operations such as polygon fills, may
- implement these high-level operations directly. For more details, please
- consult the source code, specifically:
- <blockquote><table cellpadding=0 cellspacing=0>
- <tr valign=top> <th align=left>Header
- <td>
- <th align=left>Defines
- <tr valign=top> <td><a href="../src/gxpaint.h">gxpaint.h</a>
- <td>
- <td><b><tt>gx_fill_params</tt></b>, <b><tt>gx_stroke_params</tt></b>
- <tr valign=top> <td><a href="../src/gxfixed.h">gxfixed.h</a>
- <td>
- <td><b><tt>fixed</tt></b>, <b><tt>gs_fixed_point</tt></b> (used by
- <b><tt>gx_*_params</tt></b>)
- <tr valign=top> <td><a href="../src/gxistate.h">gxistate.h</a>
- <td>
- <td><b><tt>gs_imager_state</tt></b> (used by <b><tt>gx_*_params</tt></b>)
- <tr valign=top> <td><a href="../src/gxline.h">gxline.h</a>
- <td>
- <td><b><tt>gx_line_params</tt></b> (used by <b><tt>gs_imager_state</tt></b>)
- <tr valign=top> <td><a href="../src/gslparam.h">gslparam.h</a>
- <td>
- <td>line cap/join values (used by <b><tt>gx_line_params</tt></b>)
- <tr valign=top> <td><a href="../src/gxmatrix.h">gxmatrix.h</a>
- <td>
- <td><b><tt>gs_matrix_fixed</tt></b> (used by <b><tt>gs_imager_state</tt></b>)
- <tr valign=top> <td><a href="../src/gspath.h">gspath.h</a>, <a href="../src/gxpath.h">gxpath.h</a>, <a href="../src/gzpath.h">gzpath.h</a>
- <td>
- <td><b><tt>gx_path</tt></b>
- <tr valign=top> <td><a href="../src/gxcpath.h">gxcpath.h</a>, <a href="../src/gzcpath.h">gzcpath.h</a>
- <td>
- <td><b><tt>gx_clip_path</tt></b>
- </table></blockquote>
- <p>
- For a minimal example of how to implement the high-level drawing operations,
- see <a href="../src/gdevtrac.c">gdevtrac.c</a>.
- <h4><a name="Paths"></a>Paths</h4>
- <dl>
- <dt><b><tt>int (*fill_path)(P6(gx_device *dev,
- const gs_imager_state *pis, gx_path *ppath,
- const gx_fill_params *params,
- const gx_drawing_color *pdcolor,
- const gx_clip_path *pcpath))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Fill the given path, clipped by the given clip path, according to the
- given parameters, with the given color. The clip path pointer may be
- <b><tt>NULL</tt></b>, meaning do not clip.
- </dl>
- <dl>
- <dt><b><tt>int (*stroke_path)(P6(gx_device *dev,
- const gs_imager_state *pis, gx_path *ppath,
- const gx_stroke_params *params,
- const gx_drawing_color *pdcolor,
- const gx_clip_path *pcpath))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Stroke the given path, clipped by the given clip path, according to the
- given parameters, with the given color. The clip path pointer may be
- <b><tt>NULL</tt></b>, meaning not to clip.
- </dl>
- <dl>
- <dt><b><tt>int (*fill_mask)(P13(gx_device *dev,
- const byte *data, int data_x, int raster,
- gx_bitmap_id id, int x, int y, int width,
- int height, const gx_drawing_color *pdcolor, int depth,
- int command, const gx_clip_path *pcpath))</tt></b>
- <b><em>[OPTIONAL]</em></b>
- <dd>Color the 1-bits in the given mask (or according to the alpha values,
- if <b><tt>depth</tt></b> > 1), clipped by the given clip path,
- with the given color and logical operation. The clip path pointer may be
- <b><tt>NULL</tt></b>, meaning do not clip. The parameters
- <b><tt>data</tt></b>, ..., <b><tt>height</tt></b> are as for
- <b><tt>copy_mono</tt></b>; depth is as for <b><tt>copy_alpha</tt></b>;
- command is as for <b><tt>copy_rop</tt></b>.
- </dl>
- <h4><a name="Images"></a>Images</h4>
- <p>
- Similar to the high-level interface for fill and stroke graphics, a high-level
- interface exists for bitmap images. The procedures in this part of the
- interface are optional.
- <p>
- Bitmap images come in a variety of types, corresponding closely (but not
- precisely) to the PostScript ImageTypes. The generic or common part of all
- bitmap images is defined by:
- <blockquote>
- <pre>typedef struct {
- const gx_image_type_t *type;
- gs_matrix ImageMatrix;
- } gs_image_common_t;</pre>
- </blockquote>
- <p>
- Bitmap images that supply data (all image types except
- <b><tt>image_type_from_device</tt></b> (2)) are defined by:
- <blockquote>
- <pre>#define gs_image_max_components 5
- typedef struct {
- << gs_image_common_t >>
- int Width;
- int Height;
- int BitsPerComponent;
- float Decode[gs_image_max_components * 2];
- bool Interpolate;
- } gs_data_image_t;</pre>
- </blockquote>
- <p>
- Images that supply pixel (as opposed to mask) data are defined by:
- <blockquote>
- <pre>typedef enum {
- /* Single plane, chunky pixels. */
- gs_image_format_chunky = 0,
- /* num_components planes, chunky components. */
- gs_image_format_component_planar = 1,
- /* BitsPerComponent * num_components planes, 1 bit per plane */
- gs_image_format_bit_planar = 2
- } gs_image_format_t;
- typedef struct {
- << gs_data_image_t >>
- const gs_color_space *ColorSpace;
- bool CombineWithColor;
- } gs_pixel_image_t;</pre>
- </blockquote>
- <p>
- Ordinary PostScript Level 1 or Level 2 (<b><tt>ImageType</tt></b> 1) images
- are defined by:
- <blockquote>
- <pre>typedef enum {
- /* No alpha. */
- gs_image_alpha_none = 0,
- /* Alpha precedes color components. */
- gs_image_alpha_first,
- /* Alpha follows color components. */
- gs_image_alpha_last
- } gs_image_alpha_t;
- typedef struct {
- << gs_pixel_image_t >>
- bool ImageMask;
- bool adjust;
- gs_image_alpha_t Alpha;
- } gs_image1_t;
- typedef gs_image1_t gs_image_t;</pre>
- </blockquote>
- <p>
- Of course, standard PostScript images don't have an alpha component. For
- more details, consult the source code in <a
- href="../src/gsiparam.h">gsiparam.h</a> and <b><tt>gsiparm*.h</tt></b>,
- which define parameters for an image.
- <p>
- The <b><tt>begin[_typed_]image</tt></b> driver procedures create image
- enumeration structures. The common part of these structures consists of:
- <blockquote>
- <pre>typedef struct gx_image_enum_common_s {
- const gx_image_type_t *image_type;
- const gx_image_enum_procs_t *procs;
- gx_device *dev;
- gs_id id;
- int num_planes;
- int plane_depths[gs_image_max_planes]; /* [num_planes] */
- int plane_widths[gs_image_max_planes] /* [num_planes] */
- } gx_image_enum_common_t;</pre>
- </blockquote>
- <p>
- where <b><tt>procs</tt></b> consists of:
- <blockquote>
- <pre>typedef struct gx_image_enum_procs_s {
- /*
- * Pass the next batch of data for processing.
- */
- #define image_enum_proc_plane_data(proc)\
- int proc(P4(gx_device *dev,\
- gx_image_enum_common_t *info, const gx_image_plane_t *planes,\
- int height))
- image_enum_proc_plane_data((*plane_data));
- /*
- * End processing an image, freeing the enumerator.
- */
- #define image_enum_proc_end_image(proc)\
- int proc(P3(gx_device *dev,\
- gx_image_enum_common_t *info, bool draw_last))
- image_enum_proc_end_image((*end_image));
- /*
- * Flush any intermediate buffers to the target device.
- * We need this for situations where two images interact
- * (currently, only the mask and the data of ImageType 3).
- * This procedure is optional (may be 0).
- */
- #define image_enum_proc_flush(proc)\
- int proc(P1(gx_image_enum_common_t *info))
- image_enum_proc_flush((*flush));
- } gx_image_enum_procs_t;</pre>
- </blockquote>
- <p> In other words, <b><tt>begin[_typed]_image</tt></b> sets up an
- enumeration structure that contains the procedures that will process the
- image data, together with all variables needed to maintain the state of the
- process. Since this is somewhat tricky to get right, if you plan to create
- one of your own you should probably read an existing implementation of
- <b><tt>begin[_typed]_image</tt></b>, such as the one in <a
- href="../src/gdevbbox.c">gdevbbox.c</a> or <a
- href="../src/gdevps.c">gdevps.c</a>.
- <p>
- The data passed at each call of <b><tt>image_plane_data</tt></b> consists of
- one or more planes, as appropriate for the type of image.
- <b><tt>begin[_typed]_image</tt></b> must initialize the
- <b><tt>plane_depths</tt></b> array in the enumeration structure with the
- depths (bits per element) of the planes. The array of
- <b><tt>gx_image_plane_t</tt></b> structures passed to each call of
- <b><tt>image_plane_data</tt></b> then defines where the data are stored, as
- follows:
- <blockquote>
- <pre>typedef struct gx_image_plane_s {
- const byte *data;
- int data_x;
- uint raster;
- } gx_image_plane_t;</pre>
- </blockquote>
- <dl>
- <dt><b><tt>int (*begin_image)(P9(gx_device *dev,
- const gs_imager_state *pis, const gs_image_t *pim,
- gs_image_format_t format, gs_int_rect *prect,
- const gx_drawing_color *pdcolor,
- const gx_clip_path *pcpath, gs_memory_t *memory,
- gx_image_enum_common_t **pinfo))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Begin the transmission of an image. Zero or more calls of
- <b><tt>image_plane_data</tt></b> will follow, and then a call of
- <b><tt>end_image</tt></b>. The parameters of <b><tt>begin_image</tt></b>
- are as follows:
- <blockquote><table cellpadding=0 cellspacing=0>
- <tr valign=top> <td><b><tt>pis</tt></b>
- <td>
- <td>pointer to an imager state. The only relevant elements of the
- imager state are the CTM (coordinate transformation matrix),
- the logical operation (<b><tt>RasterOp</tt></b> or
- transparency), and the color rendering information.
- <tr valign=top> <td><b><tt>pim</tt></b>
- <td>
- <td>pointer to the <b><tt>gs_image_t</tt></b> structure that
- defines the image parameters
- <tr valign=top> <td><b><tt>format</tt></b>
- <td>
- <td>defines how pixels are represented for
- <b><tt>image_plane_data</tt></b>. See the description of
- <b><tt>image_plane_data</tt></b> below
- <tr valign=top> <td><b><tt>prect</tt></b>
- <td>
- <td>if not <b><tt>NULL</tt></b>, defines a subrectangle of the
- image; only the data for this subrectangle will be passed to
- <b><tt>image_plane_data</tt></b>, and only this subrectangle should
- be drawn
- <tr valign=top> <td><b><tt>pdcolor</tt></b>
- <td>
- <td>defines a drawing color, only needed for masks or if
- <b><tt>CombineWithColor</tt></b> is true
- <tr valign=top> <td><b><tt>pcpath</tt></b>
- <td>
- <td>if not <b><tt>NULL</tt></b>, defines an optional clipping path
- <tr valign=top> <td><b><tt>memory</tt></b>
- <td>
- <td>defines the allocator to be used for allocating bookkeeping
- information
- <tr valign=top> <td><b><tt>pinfo</tt></b>
- <td>
- <td>the implementation should return a pointer to its state
- structure here
- </table></blockquote>
- <p>
- <b><tt>begin_image</tt></b> is expected to allocate a structure for its
- bookkeeping needs, using the allocator defined by the memory parameter, and
- return it in <b><tt>*pinfo</tt></b>. <b><tt>begin_image</tt></b> should not assume that
- the structures in <b><tt>*pim</tt></b>, <b><tt>*prect</tt></b>, or
- <b><tt>*pdcolor</tt></b> will survive the call on
- <b><tt>begin_image</tt></b> (except for the color space in
- <b><tt>*pim->ColorSpace</tt></b>): it should copy any necessary parts of
- them into its own bookkeeping structure. It may, however, assume that
- <b><tt>*pis</tt></b>, <b><tt>*pcpath</tt></b>, and of course
- <b><tt>*memory</tt></b> will live at least until <b><tt>end_image</tt></b>
- is called.
- <p>
- <b><tt>begin_image</tt></b> returns 0 normally, or 1 if the image does not
- need any data. In the latter case, <b><tt>begin_image</tt></b> does not
- allocate an enumeration structure.
- </dl>
- <dl>
- <dt><b><tt>int (*begin_typed_image)(P9(gx_device *dev,
- const gs_imager_state *pis, const gs_matrix *pmat,
- const gs_image_common_t *pim, gs_int_rect *prect,
- const gx_drawing_color *pdcolor,
- const gx_clip_path *pcpath, gs_memory_t *memory,
- gx_image_enum_common_t **pinfo))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>This has the same function as <b><tt>begin_image</tt></b>, except
- <ul>
- <li>The image may be of any <b><tt>ImageType</tt></b>, not only
- <b><tt>image_type_simple</tt></b> (1);
- <li>The image format is included in the image structure, not supplied as a
- separate argument;
- <li>The optional <b><tt>pmat</tt></b> argument provides a matrix that
- substitutes for the one in the imager state;
- <li>For mask images, if <b><tt>pmat</tt></b> is not <b><tt>NULL</tt></b>
- and the color is pure, <b><tt>pis</tt></b> may be <b><tt>NULL</tt></b>.
- </ul>
- </dl>
- <p>
- The actual transmission of data uses the procedures in the enumeration
- structure, not driver procedures, since the handling of the data usually
- depends on the image type and parameters rather than the device. These
- procedures are specified as follows.
- <dl>
- <dt><b><tt>int (*image_plane_data)(P4(gx_device *dev,
- gx_image_enum_common_t *info,
- const gx_image_plane_t *planes, int height))</tt></b>
- <dd>This call provides more of the image source data: specifically,
- <b><tt>height</tt></b> rows, with <b><tt>Width</tt></b> pixels supplied for
- each row.
- <p>
- The data for each row are packed big-endian within each byte, as for
- <b><tt>copy_color</tt></b>. The <b><tt>data_x</tt></b> (starting X position
- within the row) and <b><tt>raster</tt></b> (number of bytes per row) are
- specified separately for each plane, and may include some padding at the
- beginning or end of each row. Note that for non-mask images, the input data
- may be in any color space and may have any number of bits per component (1,
- 2, 4, 8, 12); currently mask images always have 1 bit per component, but in
- the future, they might allow multiple bits of alpha. Note also that each
- call of <b><tt>image_plane_data</tt></b> passes complete pixels: for example, for
- a chunky image with 24 bits per pixel, each call of
- <b><tt>image_plane_data</tt></b> passes 3N bytes of data (specifically,
- 3 × Width × height).
- <p>
- The interpretation of planes depends on the <b><tt>format</tt></b> member of
- the <b><tt>gs_image[_common]_t</tt></b> structure:
- <ul>
- <li>If the format is <b><tt>gs_image_format_chunky</tt></b>,
- <b><tt>planes[0].data</tt></b> points to data in "chunky" format, in which
- the components follow each other (for instance, RGBRGBRGB....)
- <li>If the format is <b><tt>gs_image_format_component_planar</tt></b>,
- <b><tt>planes[0 .. N-1].data</tt></b> point to data for the
- <b><em>N</em></b> components (for example, <b><em>N</em></b>=3 for RGB
- data); each plane contains samples for a single component, for instance,
- RR..., GG..., BB.... Note that the planes are divided by component, not by
- bit: for example, for 24-bit RGB data, <b><em>N</em></b>=3, with 8-bit
- values in each plane of data.
- <li>If the format is <b><tt>gs_image_format_bit_planar</tt></b>,
- <b><tt>planes[0 .. N*B-1].data</tt></b> point to data for the
- <b><em>N</em></b> components of <b><em>B</em></b> bits each (for example,
- <b><em>N</em></b>=3 and <b><em>B</em></b>=4 for RGB data with 4 bits per
- component); each plane contains samples for a single bit, for instance, R0
- R1 R2 R3 G0 G1 G2 G3 B0 B1 B2 B3. Note that the most significant bit of
- each plane comes first.
- </ul>
- <p>
- If, as a result of this call, <b><tt>image_plane_data</tt></b> has been called with all
- the data for the (sub-)image, it returns 1; otherwise, it returns 0 or an
- error code as usual.
- <p>
- <b><tt>image_plane_data</tt></b>, unlike most other procedures that take bitmaps as
- arguments, does not require the data to be aligned in any way.
- <p>
- Note that for some image types, different planes may have different
- numbers of bits per pixel, as defined in the <b><tt>plane_depths</tt></b> array.
- </dl>
- <dl>
- <dt><b><tt>int (*end_image)(P3(gx_device *dev, void *info,
- bool draw_last))</tt></b>
- <dd>Finish processing an image, either because all data have been supplied
- or because the caller has decided to abandon this image.
- <b><tt>end_image</tt></b> may be called at any time after
- <b><tt>begin_image</tt></b>. It should free the info structure and any
- subsidiary structures. If <b><tt>draw_last</tt></b> is true, it should
- finish drawing any buffered lines of the image.
- </dl>
- <h5><a name="Images_notes"></a>Notes</h5>
- <p>
- While there will almost never be more than one image enumeration in
- progress -- that is, after a <b><tt>begin_image</tt></b>,
- <b><tt>end_image</tt></b> will almost always be called before the next
- <b><tt>begin_image</tt></b> -- driver code should not rely on this
- property; in particular, it should store all information regarding the
- image in the info structure, not in the driver structure.
- <p>
- Note that if <b><tt>begin_[typed_]image</tt></b> saves its parameters in
- the info structure, it can decide on each call whether to use its own
- algorithms or to use the default implementation. (It may need to call
- <b><tt>gx_default_begin</tt></b>/<b><tt>end_image</tt></b> partway
- through.) [A later revision of this document may include an example here.]
- <h4><a name="Text"></a>Text</h4>
- <p>
- The third high-level interface handles text. As for images, the interface
- is based on creating an enumerator which then may execute the operation in
- multiple steps. As for the other high-level interfaces, the procedures are
- optional.
- <dl>
- <dt><b><tt>int (*text_begin)(P9(gx_device *dev,
- gs_imager_state *pis, const gs_text_params_t *text,
- gs_font *font, gx_path *path,
- const gx_device_color *pdcolor,
- const gx_clip_path *pcpath, gs_memory_t *memory,
- gs_text_enum_t **ppte))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>
- Begin processing text, by creating a state structure and storing it in
- <b><tt>*ppte</tt></b>. The parameters of <b><tt>text_begin</tt></b> are as
- follows:
- </dl>
- <blockquote><table cellpadding=0 cellspacing=0>
- <tr valign=top> <td><b><tt>dev</tt></b>
- <td>
- <td>The usual pointer to the device.
- <tr valign=top> <td><b><tt>pis</tt></b>
- <td>
- <td>A pointer to an imager state. All elements may be relevant,
- depending on how the text is rendered.
- <tr valign=top> <td><b><tt>text</tt></b>
- <td>
- <td>A pointer to the structure that defines the text operation
- and parameters. See <a href="../src/gstext.h">gstext.h</a> for details.
- <tr valign=top> <td><b><tt>font</tt></b>
- <td>
- <td>Defines the font for drawing.
- <tr valign=top> <td><b><tt>path</tt></b>
- <td>
- <td>Defines the path where the character outline will be appended
- (if the text operation includes <b><tt>TEXT_DO_...PATH</tt></b>),
- and whose current point indicates where drawing should occur
- and will be updated by the string width (unless the text
- operation includes <b><tt>TEXT_DO_NONE</tt></b>).
- <tr valign=top> <td><b><tt>pdcolor</tt></b>
- <td>
- <td>Defines the drawing color for the text. Only relevant if
- the text operation includes <b><tt>TEXT_DO_DRAW</tt></b>.
- <tr valign=top> <td><b><tt>pcpath</tt></b>
- <td>
- <td>If not <b><tt>NULL</tt></b>, defines an optional clipping path.
- Only relevant if the text operation includes
- <b><tt>TEXT_DO_DRAW</tt></b>.
- <tr valign=top> <td><b><tt>memory</tt></b>
- <td>
- <td>Defines the allocator to be used for allocating bookkeeping
- information.
- <tr valign=top> <td><b><tt>ppte</tt></b>
- <td>
- <td>The implementation should return a pointer to its state
- structure here.
- </table></blockquote>
- <p>
- <b><tt>text_begin</tt></b> must allocate a structure for its bookkeeping
- needs, using the allocator defined by the <b><tt>memory</tt></b> parameter,
- and return it in <b><tt>*ppte</tt></b>. <b><tt>text_begin</tt></b> may
- assume that the structures passed as parameters will survive until text
- processing is complete.
- <p>
- Clients should not call the driver <b><tt>text_begin</tt></b> procedure
- directly. Instead, they should call <b><tt>gx_device_text_begin</tt></b>,
- which takes the same parameters and also initializes certain common elements
- of the text enumeration structure, or <b><tt>gs_text_begin</tt></b>, which
- takes many of the parameters from a graphics state structure. For details,
- see <a href="../src/gstext.h">gstext.h</a>.
- <p>
- The actual processing of text uses the procedures in the enumeration
- structure, not driver procedures, since the handling of the text may depend
- on the font and parameters rather than the device. Text processing may also
- require the client to take action between characters, either because the
- client requested it (<b><tt>TEXT_INTERVENE</tt></b> in the operation) or
- because rendering a character requires suspending text processing to call an
- external package such as the PostScript interpreter. (It is a deliberate
- design decision to handle this by returning to the client, rather than
- calling out of the text renderer, in order to avoid potentially unknown
- stack requirements.) Specifically, the client must call the following
- procedures, which in turn call the procedures in the text enumerator.
- <dl>
- <dt><b><tt>int gs_text_process(P1(gs_text_enum_t *pte))</tt></b>
- <dd>Continue processing text. This procedure may return 0 or a negative
- error code as usual, or one of the following values (see
- <a href="../src/gstext.h">gstext.h</a> for details).
- <blockquote><table cellpadding=0 cellspacing=0>
- <tr valign=top> <td><b><tt>TEXT_PROCESS_RENDER</tt></b>
- <td>The client must cause the current character to be rendered.
- This currently only is used for PostScript Type 0-4 fonts
- and their CID-keyed relatives.
- <tr valign=top> <td><b><tt>TEXT_PROCESS_INTERVENE</tt></b>
- <td>The client has asked to intervene between characters.
- This is used for <b><tt>cshow</tt></b> and <b><tt>kshow</tt></b>.
- </table></blockquote>
- </dl>
- <dl>
- <dt><b><tt>int gs_text_release(P2(gs_text_enum_t *pte,
- client_name_t cname))</tt></b> <dd>Finish processing text and release
- all associated structures. Clients must call this procedure after
- <b><tt>gs_text_process</tt></b> returns 0 or an error, and may call it at
- any time.
- </dl>
- <p>
- There are numerous other procedures that clients may call during text
- processing. See <a href="../src/gstext.h">gstext.h</a> for details.
- <h5><a name="Text_notes"></a>Notes</h5>
- <p>
- Note that unlike many other optional procedures, the default implementation
- of <b><tt>text_begin</tt></b> cannot simply return: like the default
- implementation of <b><tt>begin[_typed]_image</tt></b>, it must create and
- return an enumerator. Furthermore, the implementation of the
- <b><tt>process</tt></b> procedure (in the enumerator structure, called by
- <b><tt>gs_text_process</tt></b>) cannot simply return without doing
- anything, even if it doesn't want to draw anything on the output. See the
- comments in <a href="../src/gxtext.h">gxtext.h</a> for details.
- <h3><a name="Reading_bits_back"></a>Reading bits back</h3>
- <dl>
- <dt><b><tt>int (*get_bits_rectangle)(P4(gx_device *dev,
- const gs_int_rect *prect, gs_get_bits_params_t *params,
- gs_int_rect **unread))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>
- Read a rectangle of bits back from the device. The <b><tt>params</tt></b>
- structure consists of:
- <table cellpadding=0 cellspacing=0>
- <tr valign=top> <td><b><tt>options</tt></b>
- <td>
- <td>the allowable formats for returning the data
- <tr valign=top> <td><b><tt>data[32]</tt></b>
- <td>
- <td>pointers to the returned data
- <tr valign=top> <td><b><tt>x_offset</tt></b>
- <td>
- <td>the X offset of the first returned pixel in data
- <tr valign=top> <td><b><tt>raster</tt></b>
- <td>
- <td>the distance between scan lines in the returned data
- </table>
- <p>
- <b><tt>options</tt></b> is a bit mask specifying what formats the client is
- willing to accept. (If the client has more flexibility, the implementation
- may be able to return the data more efficiently, by avoiding representation
- conversions.) The options are divided into groups.
- <blockquote><dl>
- <dt><b><em>alignment</em></b>
- <dd>Specifies whether the returned data must be aligned in the normal
- manner for bitmaps, or whether unaligned data are acceptable.
- <dt><b><em>pointer or copy</em></b>
- <dd>Specifies whether the data may be copied into storage provided by the
- client and/or returned as pointers to existing storage. (Note that if
- copying is not allowed, it is much more likely that the implementation will
- return an error, since this requires that the client accept the data in the
- implementation's internal format.)
- <dt><b><em>X offset</em></b>
- <dd>Specifies whether the returned data must have a specific X offset
- (usually zero, but possibly other values to avoid skew at some later stage
- of processing) or whether it may have any X offset (which may avoid skew in
- the <b><tt>get_bits_rectangle</tt></b> operation itself).
- <dt><b><em>raster</em></b>
- <dd>Specifies whether the raster (distance between returned scan lines)
- must have its standard value, must have some other specific value, or may
- have any value. The standard value for the raster is the device width
- padded out to the alignment modulus when using pointers, or the minimum
- raster to accommodate the X offset + width when copying (padded out to the
- alignment modulus if standard alignment is required).
- <dt><b><em>format</em></b>
- <dd>Specifies whether the data are returned in chunky (all components of a
- single pixel together), component-planar (each component has its own scan
- lines), or bit-planar (each bit has its own scan lines) format.
- <dt><b><em>color space</em></b>
- <dd>Specifies whether the data are returned as native device pixels, or in
- a standard color space. Currently the only supported standard space is
- RGB.
- <dt><b><em>standard component depth</em></b>
- <dd>Specifies the number of bits per component if the data are returned in
- the standard color space. (Native device pixels use
- <b><tt>dev</tt></b>-><b><tt>color_info.depth</tt></b> bits per pixel.)
- <dt><b><em>alpha</em></b>
- <dd>Specifies whether alpha channel information should be returned as the
- first component, the last component, or not at all. Note that for devices
- that have no alpha capability, the returned alpha values will be all 1s.
- </dl></blockquote>
- <p>
- The client may set more than one option in each of the above groups; the
- implementation will choose one of the selected options in each group to
- determine the actual form of the returned data, and will update
- <b><tt>params[].options</tt></b> to indicate the form. The returned
- <b><tt>params[].options</tt></b> will normally have only one option set per
- group.
- <p>
- For further details on <b><tt>params</tt></b>, see <a
- href="../src/gxgetbit.h">gxgetbit.h</a>. For further details on
- <b><tt>options</tt></b>, see <a href="../src/gxbitfmt.h">gxbitfmt.h</a>.
- <p>
- Define w = <b><tt>prect</tt></b>->q.x - <b><tt>prect</tt></b>->p.x, h
- = <b><tt>prect</tt></b>->q.y - <b><tt>prect</tt></b>->p.y. If the
- bits cannot be read back (for example, from a printer), return
- <b><tt>gs_error_unknownerror</tt></b>; if raster bytes is not enough space
- to hold <b><tt>offset_x</tt></b> + w pixels, or if the source rectangle
- goes outside the device dimensions (p.x < 0 || p.y < 0 || q.x >
- <b><tt>dev</tt></b>->width || q.y > <b><tt>dev</tt></b>->height),
- return <b><tt>gs_error_rangecheck</tt></b>; if any regions could not be
- read, return <b><tt>gs_error_ioerror</tt></b> if unpainted is
- <b><tt>NULL</tt></b>, otherwise the number of rectangles (see below);
- otherwise return 0.
- <p>
- The caller supplies a buffer of <b><tt>raster</tt></b> × h
- bytes starting at <b><tt>data[0]</tt></b> for the returned data in chunky
- format, or <b><em>N</em></b> buffers of
- <b><tt>raster</tt></b> × h bytes starting at
- <b><tt>data[0]</tt></b> through
- <b><tt>data[</tt></b><b><em>N-1</em></b><b><tt>]</tt></b> in planar format
- where <b><em>N</em></b> is the number of components or bits. The contents
- of the bits beyond the last valid bit in each scan line (as defined by w)
- are unpredictable. data need not be aligned in any way. If
- <b><tt>x_offset</tt></b> is non-zero, the bits before the first valid bit
- in each scan line are undefined. If the implementation returns pointers to
- the data, it stores them into <b><tt>data[0]</tt></b> or
- <b><tt>data[</tt></b><b><em>0..N-1</em></b><b><tt>]</tt></b>.
- <p>
- If not all the source data are available (for example, because the source
- was a partially obscured window and backing store was not available or not
- used), or if the rectangle does not fall completely within the device's
- coordinate system, any unread bits are undefined, and the value returned
- depends on whether unread is <b><tt>NULL</tt></b>. If unread is
- <b><tt>NULL</tt></b>, return <b><tt>gs_error_ioerror</tt></b>; in this case,
- some bits may or may not have been read. If unread is not
- <b><tt>NULL</tt></b>, allocate (using <b><tt>dev</tt></b>->memory) and
- fill in a list of rectangles that could not be read, store the pointer to
- the list in <b><tt>*unread</tt></b>, and return the number of rectangles; in
- this case, all bits not listed in the rectangle list have been read back
- properly. The list is not sorted in any particular order, but the
- rectangles do not overlap. Note that the rectangle list may cover a
- superset of the region actually obscured: for example, a lazy implementation
- could return a single rectangle that was the bounding box of the region.
- </dl>
- <dl>
- <dt><b><tt>int (*get_bits)(P4(gx_device *dev, int y,
- byte *data, byte **actual_data))</tt></b>
- <b><em>[OPTIONAL]</em></b>
- <dd>Read scan line <b><tt>y</tt></b> of bits back from the device into the
- area starting at data. This call is functionally equivalent to
- <blockquote>
- <pre>(*get_bits_rectangle)
- (dev, {0, y, dev->width, y+1},
- {(GB_ALIGN_ANY | (GB_RETURN_COPY | GB_RETURN_POINTER) | GB_OFFSET_0 |
- GB_RASTER_STANDARD | GB_FORMAT_CHUNKY | GB_COLORS_NATIVE |
- GB_ALPHA_NONE),
- {data}})</pre></blockquote>
- <p>
- with the returned value of
- <b><tt>params</tt></b>-><b><tt>data[0]</tt></b> stored in
- <b><tt>*actual_data</tt></b>, and will in fact be implemented this way if
- the device defines a <b><tt>get_bits_rectangle</tt></b> procedure and does
- not define one for <b><tt>get_bits</tt></b>. (If
- <b><tt>actual_data</tt></b> is <b><tt>NULL</tt></b>,
- <b><tt>GB_RETURN_POINTER</tt></b> is omitted from the options.)
- </dl>
- <h3><a name="Parameters"></a>Parameters</h3>
- <p>
- Devices may have an open-ended set of parameters, which are simply pairs
- consisting of a name and a value. The value may be of various types:
- integer (int or long), boolean, float, string, name, <b><tt>NULL</tt></b>,
- array of integer, array of float, or arrays or dictionaries of mixed types.
- For example, the <b><tt>Name</tt></b> of a device is a string; the
- <b><tt>Margins</tt></b> of a device is an array of two floats. See
- <a href="../src/gsparam.h">gsparam.h</a> for more details.
- <p>
- If a device has parameters other than the ones applicable to all devices
- (or, in the case of printer devices, all printer devices), it must provide
- <b><tt>get_params</tt></b> and <b><tt>put_params</tt></b> procedures. If
- your device has parameters beyond those of a straightforward display or
- printer, we strongly advise using the <b><tt>_get_params</tt></b> and
- <b><tt>_put_params</tt></b> procedures in an existing device (for example,
- <a href="../src/gdevcdj.c">gdevcdj.c</a> or <a
- href="../src/gdevbit.c">gdevbit.c</a>) as a model for your own code.
- <dl>
- <dt><b><tt>int (*get_params)(P2(gx_device *dev,
- gs_param_list *plist))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Read the parameters of the device into the parameter list at
- <b><tt>plist</tt></b>, using the <b><tt>param_write_*</tt></b>
- macros or procedures defined in <a href="../src/gsparam.h">gsparam.h</a>.
- </dl>
- <dl>
- <dt><b><tt>int (*get_hardware_params)(P2(gx_device *dev,
- gs_param_list *plist))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Read the hardware-related parameters of the device into the parameter
- list at plist. These are any parameters whose values are under control of
- external forces rather than the program -- for example, front panel
- switches, paper jam or tray empty sensors, etc. If a parameter involves
- significant delay or hardware action, the driver should only determine the
- value of the parameter if it is "requested" by the
- <b><tt>gs_param_list</tt></b> [<b><tt>param_requested</tt></b>(plist,
- <b><tt>key_name</tt></b>)]. This function may cause the asynchronous
- rendering pipeline (if enabled) to be drained, so it should be used
- sparingly.
- </dl>
- <dl>
- <dt><b><tt>int (*put_params)(P2(gx_device *dev,
- gs_param_list *plist))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Set the parameters of the device from the parameter list at
- <b><tt>plist</tt></b>, using the <b><tt>param_read_</tt></b>*
- macros/procedures defined in <a href="../src/gsparam.h">gsparam.h</a>. All
- <b><tt>put_params</tt></b> procedures must use a "two-phase commit"
- algorithm; see <a href="../src/gsparam.h">gsparam.h</a> for details.
- </dl>
- <h4><a name="Default_CRD_parameters"></a>Default color rendering
- dictionary (CRD) parameters</h4>
- <p>
- Drivers that want to provide one or more default CIE color rendering
- dictionaries (CRDs) can do so through <b><tt>get_params</tt></b>. To do
- this, they create the CRD in the usual way (normally using the
- <b><tt>gs_cie_render1_build</tt></b> and <b><tt>_initialize</tt></b>
- procedures defined in <a href="../src/gscrd.h">gscrd.h</a>), and then write
- it as a parameter using <b><tt>param_write_cie_render1</tt></b> defined in
- <a href="../src/gscrdp.h">gscrdp.h</a>. However, the TransformPQR procedure
- requires special handling. If the CRD uses a TransformPQR procedure
- different from the default (identity), the driver must do the following:
- <ul>
- <li>The TransformPQR element of the CRD must include a
- <b><tt>proc_name</tt></b>, and optionally <b><tt>proc_data</tt></b>. The
- <b><tt>proc_name</tt></b> is an arbitrary name chosen by the driver to
- designate the particular TransformPQR function. It must not be the same as
- any device parameter name; we strongly suggest it include the device name,
- for instance, "<b><tt>bitTPQRDefault</tt></b>".
- <li>For each such named TransformPQR procedure, the driver's
- <b><tt>get_param</tt></b> procedure must provide a parameter of the same
- name. The parameter value must be a string whose bytes are the actual
- procedure address.
- </ul>
- <p>
- For a complete example, see the <b><tt>bit_get_params</tt></b> procedure in
- <a href="../src/gdevbit.c">gdevbit.c</a>. Note that it is essential that
- the driver return the CRD or the procedure address only if specifically
- requested (<b><tt>param_requested(...)</tt></b> > 0); otherwise, errors
- will occur.
- <h3><a name="External_fonts"></a>External fonts</h3>
- <p>
- Drivers may include the ability to display text. More precisely, they may
- supply a set of procedures that in turn implement some font and text
- handling capabilities, described in <a href="Xfonts.htm">a separate
- document</a>. The link between the two is the driver procedure that
- supplies the font and text procedures:
- <dl>
- <dt><b><tt>xfont_procs *(*get_xfont_procs)(P1(gx_device *dev))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Return a structure of procedures for handling external fonts and text
- display. A <b><tt>NULL</tt></b> value means that this driver doesn't
- provide this capability.
- </dl>
- <p>
- For technical reasons, a second procedure is also needed:
- <dl>
- <dt><b><tt>gx_device *(*get_xfont_device)(P1(gx_device *dev))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Return the device that implements <b><tt>get_xfont_procs</tt></b> in a
- non-default way for this device, if any. Except for certain special
- internal devices, this is always the device argument.
- </dl>
- <h3><a name="Page_devices"></a>Page devices</h3>
- <dl>
- <dt><b><tt>gx_device *(*get_page_device)(P1(gx_device *dev))</tt></b>
- <b><em>[OPTIONAL]</em></b>
- <dd>According to the Adobe specifications, some devices are "page devices"
- and some are not. This procedure returns <b><tt>NULL</tt></b> if the
- device is not a page device, or the device itself if it is a page device.
- In the case of forwarding devices, <b><tt>get_page_device</tt></b> returns
- the underlying page device (or <b><tt>NULL</tt></b> if the underlying
- device is not a page device).
- </dl>
- <h3><a name="Miscellaneous"></a>Miscellaneous</h3>
- <dl>
- <dt><b><tt>int (*get_band)(P3(gx_device *dev, int y,
- int *band_start))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>If the device is a band device, this procedure stores in
- <b><tt>*band_start</tt></b> the scan line (device Y coordinate) of the band
- that includes the given Y coordinate, and returns the number of scan lines
- in the band. If the device is not a band device, this procedure returns 0.
- The latter is the default implementation.
- </dl>
- <dl>
- <dt><b><tt>void (*get_clipping_box)(P2(gx_device *dev,
- gs_fixed_rect *pbox))</tt></b> <b><em>[OPTIONAL]</em></b>
- <dd>Stores in <b><tt>*pbox</tt></b> a rectangle that defines the device's
- clipping region. For all but a few specialized devices, this is
- <em>((0,0),(width,height))</em>.
- </dl>
- <!-- [2.0 end contents] ==================================================== -->
- <!-- [3.0 begin visible trailer] =========================================== -->
- <hr>
- <p>
- <small>Copyright © 1996, 2000 Aladdin Enterprises.
- All rights reserved.</small>
- <p>
- <small>This file is part of AFPL Ghostscript. See the
- <a href="Public.htm">Aladdin Free Public License</a> (the "License") for
- full details of the terms of using, copying, modifying, and redistributing
- AFPL Ghostscript.</small>
- <p>
- <small>Ghostscript version 7.04, 31 January 2002
- <!-- [3.0 end visible trailer] ============================================= -->
- </body>
- </html>
|