Programming Guide:xppguide

The printer - XbpPrinter() Foundation

Objects of the XbpPrinter class are used for printed output. This requires that a printer driver appropriate for the physical printer be installed.

Basics for printing of graphics

The XbpPrinter class creates a connection to printer drivers, or printer objects, respectively, installed on the system. If a printer object is not correctly configured, correct graphic output to the printer from Xbase++ is not guaranteed. Printer objects are identified in Xbase++ by their name which is displayed underneath a printer icon. An XbpPrinter object controls a printer object and represents the device context for a presentation space in which graphic information is displayed. To set up for printing an image, therefore, the printer device context (XbpPrinter object) is associated with a presentation space. The following user-defined function is suitable for this:

FUNCTION PrinterPS( cPrinterObjectName ) 
   LOCAL oPS, oDC := XbpPrinter():new() 

   oDC:create( cPrinterObjectName ) 

   oPS := XbpPresSpace():new() 
   oPS:create( oDC, oDC:paperSize(), GRA_PU_LOMETRIC ) 
RETURN oPS 

The user-defined function PrinterPS() creates a presentation space associated with a printer device context. It receives as a parameter the name of one of the printer objects installed on the system as a character string and creates an XbpPrinter object that maintains the connection to the printer object. In the function, a new presentation space is created, and the XbpPrinter object is provided as the device context. The return value of the method :paperSize() is used for the page size of the presentation space. This assures that the presentation space and the device context have the same size coordinate systems. Since the paper size is always returned by the method :paperSize() in the units of 1/10 millimeter, the constant GRA_PU_LOMETRIC is specified in the call to oPS:create() to set the same units in the presentation space.

The output of graphics on the printer can be performed using the function PrinterPS() as shown in the following example:

oPS := PrinterPS()                  // presentation space with 
                                    // default printer object 
oPS:device():startDoc()             // start print output 
                                    // (open spooler) 
GraBox( oPS, {0,0}, {1000,1000} )   // draw box 

oPS:device():endDoc()               // end print output 
                                    // (close spooler) 

These four lines of code show the basic procedure for printing graphics. A presentation space associated with an XbpPrinter object (printer device context) must be available. In the example, the method :device() returns the XbpPrinter object and begins the print output using the call to :startDoc(). Generally, print jobs are spooled and :startDoc() opens the spooler. All graphic output which occurs in the presentations space is sent to the spooler. The end of the print job is signalled by the method:endDoc() which closes the spooler.

The function PrinterPS() shows how a presentation space for output on the printer is created, and also shows the basic difficulty of graphic output: the coordinate systems of the output devices "screen" and "printer" differ in things like the units of the coordinate system of the two devices. The following program code illustrates this:

GraBox( oPS, {0,0}, {1000,1000} ) 

This call to GraBox() draws a square with an edge length of 1000 units. How and where the square is displayed depends on the device context associated with the presentation space oPS and on the units for the coordinate system. The device unit for the screen is "pixel" and the square would only partially be visible on screen except at extremely high screen resolution. If a printer is the device context, the unit is 1/10 millimeter and the square would be displayed with 10cm edge length which fits the most common paper formats.

Print text as graphics

The problem of different coordinate systems and units becomes especially obvious when outputting text or characters. The function GraStringAt() draws a character string in a presentation space. The font which is set in the presentation space is significant. There are fonts which can only be output on the screen, others that can only be output on a printer, and others which can be output on either device. When text is output on a printer, fonts which are only for display on screen obviously cannot be used. The following example program illustrates this problem:

#include "Gra.ch" 
#include "Xbp.ch" 

PROCEDURE Main 
   LOCAL oWindowPS, oPrinterPS, oFont, aFontList 
   LOCAL i, imax, nY, nPointSize, cText, aSize 

   // presentation space for window and printer 
   oWindowPS  := SetAppWindow():presSpace() 
   oPrinterPS := PrinterPS() 

   // create font object 
   oFont := XbpFont():new( oWindowPS ) 

   // read list of available fonts 
   aFontList := oFont:list() 

   // output fonts on the printer 
   oPrinterPS:device():startDoc() 

   imax       := Len( aFontList ) 
   nY         := oPrinterPS:device():paperSize()[2] - 100 
   nPointSize := 1 

   FOR i:=1 TO imax 

      // print only universally valid vector fonts 
      IF aFontList[i]:generic .AND. aFontList[i]:vector 

         oFont := aFontList[i] 
         oFont:nominalPointSize := ++nPointSize 

         // create text to print 
         cText := Str( nPointSize, 2 ) + "." + ; 
                       oFont:compoundName 

         // set font for printer 
         GraSetFont( oPrinterPS, oFont ) 

         // calculate size and new y position of the string 
         aSize := GraQueryTextBox( oPrinterPS, cText ) 
         nY    := nY - aSize[1,2] 

         // print string and release font 
         GraStringAt( oPrinterPS, {20,nY}, cText ) 
         oFont:destroy() 

      ENDIF 
   NEXT 

   oPrinterPS:device():endDoc() 
RETURN 

This example program prints the size and name of all vector fonts that can be output on the printer. First, the presentation space of the application window is determined. The function PrinterPS() creates a presentation space which is linked with a printer device context. An XbpFont object is then generated to manage the fonts. The call oFont:list() returns an array containing the font objects for all fonts that can be displayed in a window. The print output then begins. The text to be printed is created in the FOR..NEXT loop. It is only printed when the instance variables :generic and :vector of a font object in the array aFontList both contain .T. (true). This is the prerequisite for fonts that can be displayed in a window and can also be output to scale on a printer. Within the FOR..NEXT loop, font objects which fulfill this prerequisite are passed using GraSetFont() to the presentation space oPrinterPS which is associated with the printer device context. At this point in the example program, the presentation space knows which font is to be printed and the metric data for the size of the letters. Since the point size for a font is increased by one after each pass through the loop, the y position of the character string must continually be adjusted to the height of the letters. The height of the character string cText is determined using the function GraQueryTextBox().

The example program touches on all the problems that must be considered in programming graphic output of text for a printer. Text is output in graphics mode using the function GraStringAt(). In order for the characters to be printed on paper, the output must occur in a presentation space linked with a printer device context (an XbpPrinter object). The font used for the print output is set using an XbpFont object. The available fonts are determined using the :fontList()method of a font object. In the example, all fonts which can be displayed in a presentation space for a window are tested, since the presentation space of the application window is provided to the XbpFont object (XbpFont():new(oWindowPS)). Only device independent vector fonts (:generic and :vector are .T.) can also be used for printing. When :generic and :vector are .T., this indicates that the font can be scaled correctly during printing. The exact position where a character string cText is printed in the example program must be calculated after each pass through the loop using the function GraQuerytextBox(), since the point size of the font is continually changed.

Using XbpPrinter objects to output text or graphics can be summarized as follows:

- The printer object must be installed and configured correctly.

- The output must occur in a presentation space which has an XbpPrinter object as its device context.

- The coordinate system of the XbpPrinter object is based on the unit of 1/10 millimeter.

- The font for the output of text is set using an XbpFont object.

- The size of a character string is determined by GraQueryTextBox().

These five points must always be considered when using XbpPrinter objects or sending graphic output to a printer.

Feedback

If you see anything in the documentation that is not correct, does not match your experience with the particular feature or requires further clarification, please use this form to report a documentation issue.