This function is the main printer-specific code module and consists of seven parts referred to here as cases: * Pre-Master initialization (Case 5) * Master initialization (Case 0) * Putting the pixels in a buffer (Case 1) * Dumping a pixel buffer to the printer (Case 2) * Closing down (Case 4) * Clearing and initializing the pixel buffer (Case 3) * Switching to the next color(Case 6) (special case for multi-color printers) State Your Case. ---------------- The numbering of the cases reflects the value of each step as a case in a C-language switch statement. It does not denote the order that the functions are executed; the order in which they are listed above denotes that. For each case, Render() receives four long variables as parameters: ct, x, y and status. These parameters are described below for each of the seven cases that Render() must handle. Pre-Master initialization (Case 5) ---------------------------------- Parameters: ct - 0 or pointer to the iodrpreq structure passed to pcdumprport x - io_Special flag from the IODRPReq structure y - 0 When the printer device is first opened, Render() is called with ct set to 0, to give the driver a chance to set up the density values before the actual graphic dump is called. The parameter passed in x will be the io_Special flag which contains the density and other SPECIAL flags. The only flags used at this point are the DENSITY flags, all others should be ignored. Never call PWrite() during this case. When you are finished handling this case, return PDERR_NOERR. Master initialization (Case 0). ------------------------------- Parameters: ct - pointer to a iodrpreq structure x - width (in pixels) of printed picture y - height (in pixels) of printed picture Everything is A-OK. ------------------- At this point the printer device has already checked that the values are within range for the printer. This is done by checking values listed in printertag.asm. The x and y value should be used to allocate enough memory for a command and data buffer for the printer. If the allocation fails, PDERR_BUFFERMEMORY should be returned. In general, the buffer needs to be large enough for the commands and data required for one pass of the print head. These typically take the following form: <start gfx cmd> <data> <end gfx cmd> The <start gfx cmd> should contain any special, one-time initializations that the printer might require such as: * Carriage Return - some printers start printing graphics without returning the printhead. Sending a CR assures that printing will start from the left edge. * Unidirectional - some printers which have a bidirectional mode produce non-matching vertical lines during a graphics dump, giving a wavy result. To prevent this, your driver should set the printer to unidirectional mode. * Clear margins - some printers force graphic dumps to be done within the text margins, thus they should be cleared. * Other commands - enter the graphics mode, set density, etc. Multi-Pass? Don't Forget the Memory. ------------------------------------ In addition to the memory for commands and data, a multi-pass color printer must allocate enough buffer space for each of the different color passes. The printer should never be reset during the master initialization case This will cause problems during multiple dumps. Also, the pointer to the iodrpreq structure in ct should not be used except for those rare printers which require it to do the dump themselves. Return the PDERR_TOOKCONTROL error in that case so that the printer device can exit gracefully. PDERR_TOOKCONTROL, An Error in Name Only. ----------------------------------------- The printer device error code, PDERR_TOOKCONTROL, is not an error at all, but an internal indicator that the printer driver is doing the graphic dump entirely on its own. The printer device can assume the dump has been done. The calling application will not be informed of this, but will receive PDERR_NOERR instead. The example render.c functions listed at the end of this chapter use double buffering to reduce the dump time which is why the allocmem() calls are for BUFSIZE times two, where BUFSIZE represents the amount of memory for one entire print cycle. However, contrary to the example source code, allocating the two buffers independently of each other is recommended. A request for one large block of contiguous memory might be refused. Two smaller requests are more likely to be granted. Putting the pixels in a buffer (Case 1). ---------------------------------------- Parameters: ct - pointer to a PrtInfo structure. x - PCM color code (if the printer is PCC_MULTI_PASS). y - printer row # (the range is 0 to pixel height - 1). In this case, you are passed an entire row of YMCB intensity values (Yellow, Magenta, Cyan, Black). To handle this case, you call the transfer() function in the transfer.c module. you should return PDERR_NOERR after handling this case. The PCM-defines for the x parameter from the file devices/prtgfx.h are pcmyellow, pcmmagenta, pcmcyan and PCMBLACK. Dumping a pixel buffer to the printer (Case 2). ----------------------------------------------- Parameters: ct - 0 x - 0 y - # of rows sent (the range is 1 to NumRows). At this point the data can be Run Length Encoded (RLE) if your printer supports it. If the printer doesn't support RLE, the data should be white-space stripped. This involves scanning the buffer from end to beginning for the position of the first occurrence of a non-zero value. Only the data from the beginning of the buffer to this position should be sent to the printer. This will significantly reduce print times. The value of y can be used to advance the paper the appropriate number of pixel lines if your printer supports that feature. This helps prevent white lines from appearing between graphic dumps. You can also do post-processing on the buffer at this point. For example, if your printer uses the hexadecimal number $03 as a command and requires the sequence $03 $03 to send $03 as data, you would probably want to scan the buffer and expand any $03s to $03 $03 during this case. Of course, you'll need to allocate space somewhere in order to expand the buffer. The error from PWrite() should be returned after this call. Clearing and initializing the pixel buffer (Case 3) --------------------------------------------------- Parameters: ct - 0 x - 0 y - 0 The printer driver does not send blank pixels so you must initialize the buffer to the value your printer uses for blank pixels (usually 0). Clearing the buffer should be the same for all printers. Initializing the buffer is printer specific, and it includes placing the printer-specific control codes in the buffer before and after the data. This call is made before each Case 2 call. Clear your active print buffer - remember you are double buffering - and initialize it if necessary. After this call, PDERR_NOERR should be returned. Closing Down (Case 4). ---------------------- Parameters: ct - error code x - io_Special flag from the iodrpreq structure y - 0 This call is made at the end of the graphic dump or if the graphic dump was cancelled for some reason. At this point you should free the printer buffer memory. You can determine if memory was allocated by checking that the value of PD->pd_PrintBuf is not NULL. If memory was allocated, you must wait for the print buffers to clear (by calling PBothReady) and then deallocate the memory. If the printer - usually a page oriented printer - requires a page eject command, it can be given here. Before you do, though, you should check the special_noformfeed bit in x. don't issue the command if it is set. If the error condition in ct is PDERR_CANCEL, you should not PWrite(). This error indicates that the user is trying to cancel the dump for whatever reason. Each additional PWrite() will generate another printer trouble requester. Obviously, this is not desirable. During this render case PWrite() could be used to: * reset the line spacing. If the printer doesn't have an advance 'n' dots command, then you'll probably advance the paper by changing the line spacing. If you do, set it back to either 6 or 8 lpi (depending on Preferences) when you are finished printing. * set bidirectional mode if you selected unidirectional mode in render Case 0. * set black text; some printers print the text in the last color used, even if it was in graphics mode. * restore the margins if you cancelled the margins in render Case 0. * any other command needed to exit the graphics mode, eject the page, etc. Either PDERR_NOERR or the error from PWrite() should be returned after this call. Switching to the next color (Case 6) ------------------------------------ This call provides support for printers which require that colors be sent in separate passes. When this call is made, you should instruct the printer to advance its color panel. This case is only needed for printers of the type PCC_MULTI_PASS, such as the CalComp ColorMaster.