Previous: 11 Tabulated output for screen or printer
Next: 13 Large fonts and dual monitors
In this section:
There are three generic cases to consider:
Most Fortran programmers who are used to a lineprinter expect to just continue printing line after line with the text just missing the perforated lines that have made the sheets fold into the paper box (i.e. the paper is probably sprocket-fed, fanfold paper). Even printing on a printer that takes discrete sheets, the same principle applied in the past. Under Windows, however, your application treats each page as a separate entity, and you have to do assemble everything on the page before it can be printed. In effect, each page is one large graphic.
A first issue to consider is whether or not you wish to print on the default printer, as explained in the previous chapter. The method of readying a printer to accept graphics is similar, but different in detail.
Then, if you have not already done so, you must determine the critical printer parameters, most notably the size of the printable area in pixels in each direction and also the effective dots per inch. The use of dots per inch will certainly frustrate any programmer whose experience is exclusively in metric, but the useful conversion factor is that 1 inch is 25.4 mm. Programmers will also have a certain amount of frustration with the use of points, because an inch is 72 points. The net result of these units is that there is unlikely to be in exact number of pixels in a point or an inch, except in the case of some Epson printers where the dots per inch setting can be 144 or 288 (or some larger multiple) and therefore there is a precise number of pixels per point. There is never an equivalent in mm.
To print pages as graphics the printer can either be the default printer or one selected by the user and in the example below, I have done this via a subroutine call. Either subroutine returns an integer number called a handle, and this handle is subsequently used firstly for Windows to load all the parameters for that printer, referred to as the device context, and these parameters can be obtained from the device context using the subroutine GET_CURRENT_DC@ using its handle as a parameter in the subroutine call. Subsequently, the device capabilities are found.
IF (iPrint_on_Default .EQ. 1) THEN IB = OPEN_PRINTER1@ (jHDC) ELSE IB = OPEN_PRINTER@ (jHDC) ENDIF IF (IB .EQ. 0) RETURN ! IB is equal to zero if the call failed
At this point, the properties of the printer can be found:
CALL GET_CURRENT_DC@ (jHDC) CALL USE_RGB_COLOURS@ (0,1) ! This works, but … C CALL USE_RGB_COLOURS@ (0,.true.) ! This is the correct form ixdpi = GetDeviceCaps (jHDC, LOGPIXELSX) iydpi = GetDeviceCaps (jHDC, LOGPIXELSY) jXRES = GetDeviceCaps (IHND_PRN, HORZRES) jYRES = GetDeviceCaps (IHND_PRN, VERTRES)
LOGPIXELSX, LOGPIXELSY, HORZRES and VERTRES are parameters whose values are set in the .INS files. Perhaps at this time the printer orientation might be set, using:
CALL SET_PRINTER_ORIENTATION@ (0) ! Portrait
CALL SET_PRINTER_ORIENTATION@ (1) ! Landscape
ClearWin+, at this point, must be directed towards the printer page as its drawing surface, which is done using the function SELECT_GRAPHICS_OBJECT@, as in the following, using the correct handle:
IA = SELECT_GRAPHICS_OBJECT@ (jHDC)
The default entry in the Windows’ print spooler is that the job is a ClearWin+ printout, but it is more useful to set the name of the print job by setting the string yourself, as in this example where the string is 'SCAMPS Major Control Report' and PRINTER_DOCUMENT is the parameter defined in the .INS file for this purpose:
CALL SET_CLEARWIN_STRING@ (PRINTER_DOCUMENT, & 'SCAMPS Major Control Report')
These lines of code have been taken from a working program where what is to be printed (for notice board display purposes) uses the Arial font with height and width set in points, and a line spacing LineStep of 1/3 of an inch with margins Margin of 1/2 an inch:
CALL SELECT_FONT@ ('Arial') CALL SIZE_IN_POINTS@ (24,12) LineStep = iydpi / 3.0D0 ! 24 point out of 72 point in dpi Margin = ixdpi / 2.0D0
Every time a page is filled, the following call is required to start a new page:
On completion of the print run it is desirable to close the printer. Doing so ensures that the last page is printed.
CALL CLOSE_PRINTER@ (jHDC)
An issue always comes to the fore when printing with proportionally spaced fonts and that is the difficulty of getting columns aligned with tabulated numbers. While this can be resolved by switching to a monospaced font, the net result is comparatively ugly and not one that looks like the output from a Windows program. The solution is to position the text after measuring the size of the text using GET_TEXT_SIZE@11. With columns of real numbers, they should be aligned on the decimal point which generally requires the measurement of the section of a text string before the decimal point and printing that separately from the section that follows.
The paper size will determine how many lines at what heights can be printed and a decision can also be taken as to whether to print multiple pages or scale everything to fit on one page.
I call the resulting pages ‘reports’ and given the effort taken in measuring everything to fit, it does seem to me that it is only worth the effort if the information is valuable. To make sure that a user doesn’t cut, paste and photocopy a fake report, I suggest placing a faint watermark on each page, numbering each page with a note of the total page count, adding the date and time it was printed, and possibly even adding information such as a logo or company name. Perhaps my caution in this respect is from having seen too much paperwork in which numbers have been ‘fiddled’, usually after a failure when blame and costs must be attributed to someone else.
Printing a whole page with a single drawing on it is comparatively simple, because the image will be cropped to the printable area of the paper and it is only a matter of initialising the graphics printer, interrogating the driver to find out the printable area and DPI settings, calculating the scales and then repeating the drawing exercise that was used previously to generate the screen image.
Engineering drawings usually have some sort of drawn border together with a title block giving information such as the drawing number, the project name, details of who produced the drawing and revision information. The border is provided so that the recipient will know that they have the complete drawing and not some piece cropped from a larger drawing. Many engineering drawings have a scale that also needs to be provided. Information such as this takes up space on the paper, for which allowance must be made. The details of this additional material depend on the nature of the application.
The DPI setting is returned generally honestly by the GetDeviceCaps function, and so is the size of the printable area in pixels. I had an unfortunate experience with some Xerox A3 printers which originally returned the printable area dimensions in mm, returned fake values after a driver update. There is at least one large country in the world where people either don’t know or care what millimetres are, and I imagine that the updated driver came from there. The return values for A3 paper were 240x271mm which is arrant nonsense. Otherwise, and as originally bought, the printers were fine.
When a printed page contains a graphical image as well as some text, that image may well be cropped from part of a larger illustration. There are techniques for cropping images, but you do not need to apply them in the normal run of things so long as you draw that image first, you can then blank out parts of the page into which unwanted elements of the image project by overwriting them with white rectangles. In that way you can, for example, increase the binding margin as well as ensuring that where the text will be placed is clear white underneath. The text itself may need some very careful consideration when using a proportionally spaced font as described in section 12.1.
In the above, I have assumed that the graphical part is drawn at the time the page is printed. Of course, there is a case – perhaps – for pre-preparing some graphics elements as bitmaps, and placing those instead of drawing the object. The problem then arises that the bitmaps have to be drawn at numerous sizes to cope with different printer resolutions, and that means in turn that when incorporated into a program executable via its RESOURCES, the effect on the size of the executable can be dramatic. It may be that the effect has to be suffered with something like a company logo, but for things such a North arrows, scale bars, legends etc, it is better that they are drawn when required. On screen, the use of pre-prepared bitmaps is generally to be preferred as they are inevitably much smaller in size (measuring bytes), and various graphical effects such as drop shadows, 3D effects, smoothing of edges and so on can be included easily.
One thing to beware of when using a laser printer is that the toner is fused to the paper with heat. Large areas of dense colour may be too large to be effectively fused, and the result of that is that the layer of toner may not adhere properly to the paper and may become detached or crack when the paper is handled. Worse still, some of the toner having slightly melted and formed a sheet may detach itself inside the printer with consequent bad effects. I speculate that there is a limit to how much heat printers can generate without actually setting the paper on fire.
Inkjet printers also have issues when printing large areas in saturated colours in that the wet ink makes the paper soggy, especially if standard office 80 g/m² copier paper is used. Up to a point the issue may well be resolved by using thicker and heavier weight papers, or even papers that are coated and sold as photo quality. Paper that has been saturated by the liquid ink normally stretches at the very least and you do not get perfectly flat paper afterwards.
Both laser printers and inkjet printers are usually perfectly at home printing text where the coverage of the paper is quite small. The problems with both arise with large areas of saturated colour. On-screen, saturated colours work extremely well, but it is worth lightening shades when printing on typical office printers using standard weight office copier paper. Colours in ClearWin+ graphics are specified with RGB colour triplets. Printers typically use four colours or more, cyan, magenta, yellow and black (CMYK) and instead of the RGB colour system which is additive, the CMYK system is subtractive. Inkjet printers that are sold as capable of printing photos may have extra colours, such as in my Epson all-in-one combined printer and scanner that also has black, light magenta and light cyan cartridges. Another side effect of using very saturated colours can be an excessive consumption of toner or ink, and as today printers are normally sold cheaply with the manufacturer recouping some of the expense by overcharging for supplies, then even if the printer or paper is not damaged, the cost of printing with saturated colours does increase dramatically.
It is possible to find equivalents for RGB triplets in terms of CMYK, but in general, lightening shades depends on increasing the values of the RGB elements in ways that always seem to me to be a bit counterintuitive, but one should remember that black is (0,0,0) and white is (255,255,255). For example, blue is (0,0,255) but to make a lighter blue we can increase the R and G so that a light sky blue might be (135,206,255). The whole business of colour spaces is something that you may need to research independently. There does not seem to be a simple algorithm to make the colours seen on the screen become lighter for printing, and it may well be worth only choosing relatively light shades for on screen display anyway.
A way of avoiding areas of dense saturated colour is to revert to the use of fill textures such as hatching or crosshatching, but they are not provided as standard facilities in ClearWin. Some of the basics of hatching irregular areas are covered in ‘High-resolution computer graphics using Fortran 77’ by Angell and Griffiths (Macmillan), a book that is probably now out of print but like so many can be obtained second-hand from online booksellers. One should be aware of overuse of textures because they can make a graphic look extremely congested and worse still, amateurish. So much so that the noted author Edward Tufte in his acclaimed books refers to them as ‘chart junk’. One simply had to use chart junk in the days of monochrome-only printing. An issue that is easy to forget is to omit to send the appropriate command to finish printing the last page of a print job, in which case it may come out only when the printer is used again, and with a mix of the last page of the old job on the first page of the new.
Under Windows it is also a good idea to name the print job so that if the printer for it is, for example off-line, and the print job is held up in the print spooler, then you can recognise what it is.
It is always a good idea to format printed pages from any application with due regard to the size and shape of the printer. Sometimes it is necessary to provide some type of traceability to the results of a computation, and my advice is therefore to print either as a header or as a footer on every page the name of the application that had generated the output including its version number and the time and date when the output was generated. It is also very useful to pre-calculate how many sheets will be printed and to identify each one with ‘Page number X of Y’ (or perhaps using my predilection for IMPLICIT type, ‘Page number I of N’).
The disadvantage of printing like a lineprinter is that unless printing on pre-printed headed paper it is not possible to include any logos or watermarks. If you want to include such features, then you have to print each page as a graphics object, or invest in the appropriate pre-printed headed paper.
It is always valuable when acting as a reviewer to know that you have the complete document in your hands, and when doing a forensic study, to be able to reconstruct any developments in analysis and how things changed. Files that contain information such as the date, the total number of pages printed and so on, are easiest to check.
If there are many options as to what to print and how to print it, then rather than having a set of sub sub-menus it is sometimes better to launch a dialog, containing all the options, and perhaps including a tick-box labelled as ‘Use default printer’, with the box initially ticked. I use such a dialog in one of my programs, which I call the Print Station. This is what it looks like:
Using it, summaries can be printed out in graphics mode so that they can be posted on a noticeboard for all students on that course to have access to, but individual groups can generate reports of their own individual contributions to the overall picture either as a momento of their work or as an adjunct to their report on the activity.
Because a user may wish to print more than one thing, this dialog has a tick box to keep it open until all types of printing are done with. Your program’s (users’?) needs may be different, and you may keep the dialog open or close it after each item as you wish. Notice that an entire category of options is greyed out depending on the selection in the first box. When you link items in this way the user should be helped to work from left to right, even though they can go backwards or forwards in selecting options.
An issue that often escapes attention is that while ClearWin+ allows the programmer to select portrait or landscape format using SET_PRINTER_ORIENTATION@, the user has the final say, and can change this in the printer driver dialog that is part of Windows rather than ClearWin+. At the point of determining the number of pixels in x and y on the printer page it is possible to see if the user changed the program’s settings to their own preference. Should such a situation arise, and the user-selected orientation not be appropriate for the aspect ratio of what is to be printed, there are several options:
The first option may well lead to only part of an image appearing, especially if the print job has a fixed scale (e.g. a site plan at 1:500 scale), but careful programming can overcome that by printing the image on multiple sheets with some sort of overlap. Rotating the print image in the case of a simple graphic is just a matter of using a different transformation, for example, instead of the usual two scaling STATEMENT FUNCTIONs to map x and y real-world coordinates to x and y pixel coordinates respectively, it is a matter or mapping x (real world) to y (pixels) and y (real world) to x (pixels), remembering the relative orientation of the pixel axes.
Asking the user leads to one of the other 2 options, although a third possibility is that the user simply cancels the print job and starts again.
Very early laser printers printed at 75 or 150 dpi, meaning that lines of 1 pixel width printed as almost 1 or 0.5 points. The norm then changed to 300, 600 or even 1200 dpi, and with the highest resolutions, the 1 pixel line becomes at first a hairline and then barely visible. Inkjet printers may offer equivalent resolutions, although some (for example Epson printers) operate with 360, 720, 1440 or 2880 dpi. The issue of the visibility of lines becomes important. The setting is usually chosen by the user at the print driver dialog stage, and is done on the basis of prompts such as ‘high quality’ or ‘superfine’. The solution is to examine the printer properties and thicken the lines as necessary.
Early in my career I was an adept draughtsman, using tubular nib pens (e.g. Rotring or Standardgraph brands) and stencils. At first, I used 0.1, 0.3 and 0.5mm line thicknesses, but later adopted the DIN standard sequence of 0.1, 0.14, 0.2, 0.28, 0.35, 0.5, 0.7 (which increase by √2 each time just as the A series of paper sizes does). Since 1 inch = 25.4mm, the inch
equivalents are readily converted and rendered into pixels at the relevant printer dpi resolution.
Preferred line thicknesses are described in books on technical drawing, but I find the following rules of thumb useful.
|0.2 – 0.3mm||Typical outlines|
|0.28 – 0.35mm||Used to emphasise|
|0.5mm – 0.7mm||Super-emphasis, drawing borders, etc|
Structural engineers drawing (say) reinforcing bars may need to use even thicker lines. I do not normally find that anything thicker is required for normal line drawing work, but in drawing parallel lines it is a lot easier to draw a thick line in black and then over the top, using the same coordinates, draw a thinner line in white, than to attempt to draw a pair of thinner lines separated by a constant distance.
At various printer DPI capabilities, the line thicknesses have an integer number of pixels as shown in the table below.
Character heights are almost infinitely scalable when using fonts (although limited in practice by the pixels). At really high printer resolutions, 6pt text becomes readable, but at normal office printer resolutions 8pt is a minimum. For large bodies of text and tables, 10 to 12pt text is usually fine (corresponding to old typewriter standards of pica and elite, but the choice of font is also a factor. Headings need to be 12-14pt or larger.
This book, for example, has been produced with body text at 12 pt Cambria with Section headings in 14pt Optima and Chapter headings in 16pt Optima. Footnotes are in Cambria 10pt, and Figure captions also in 10pt.
Annotations on printed graphics done with tubular pens and stencils tended to use characters that were 10x the corresponding line thickness, but Windows fonts are more flexible and detailed. For many uses, the default graphics font and font size are good enough in print as onscreen, but if one does need to set font sizes for annotation then smaller fonts are appropriate for higher resolutions. It is always worth checking that text fits on the paper!
My first experiences with pen plotters were with devices connected to mainframes with an unknown plotter control language but using a library of routines customised for that particular mainframe and plotter. Sometimes it was not necessary to know whether the plotter was a drum type or a flatbed, but certainly the selection of pens tended to be limited and that also limited the choice of line thicknesses and colours. Later on, in the PC era, both drum and flatbed types were available, usually connected to the PC using an RS 232 serial connection or a parallel (Centronics) connection, neither of which is found on a modern PC. PC connected plotters came in a variety of paper sizes with A4 sheet or A3 sheet sizes being particularly common for the desktop. A photograph of such an installation manned by my former PhD student, who is now a (retired) professor in his own right, is shown in my book ‘The Stability of Slopes’ (1985).
In the personal computer era, pen plotters were supplied with a useful manual that described the entire plotter control language. Many plotters not only supported their own language but also had compatibility with the language used to control Hewlett-Packard’s pen plotters, a language described as Hewlett-Packard graphics language or more simply HPGL. This graphics language was basically a combination of commands that enabled one to select a particular pen, move it to specific coordinates in an up or down state (only the latter drawing a line), or to draw characters.
Even the monochrome (single pen) plotters without any variation in line thickness were very useful for many types of drawing including but not limited to engineering drawings. For example, circuit diagrams very rarely require colour, even though it is perhaps a useful adjunct.
HPGL was updated to HPGL / 2 with the addition of the ability to set line thicknesses and to fill areas, attributes related to raster-based rather than pen-based devices.
While a Windows program will more often produce its graphics via a dedicated software driver to a device that may be not even physically present where the computer is located, some interchange of graphics created in a plotter language may still be found useful. Doing so in a dedicated, manufacturer specific, plotter language would normally be an extremely eclectic choice, but interchanging graphics using HPGL or HPGL/2 has some benefits, notably that some graphics packages will accept input in this format (for example, CorelDRAW!) and if the two applications have the same authorship, then the formatting of the output by one of them can be recognised by the other without any difficulties of parsing the data in the transmitted file.
The details of HPGL can be found in old plotter manuals of the appropriate sort, on the Internet where HPGL has a good Wikipedia entry, or perhaps preferably in a book which like so many is likely to be out of print. Hewlett-Packard was the corporate author of a book entitled The HP GL/2 reference guide, later published in a third edition as The HPGL /2 and HP RTL reference guide, which makes me suspect that the first edition may well of been HPGL only! I have lost a number of books loaned to students (and colleagues) and not returned as well as books that were loaned out and returned, but my copy of this book is the only one that a student not only returned but in the interim had obtained his own copy which he swore blind he would never use at any later point in his career and therefore gave me to take up that small extra space in my bookshelves!
As the programming of HPGL (any version) is a simple matter of writing files and reading them, and not in any way connected to ClearWin+, then I do not propose to go much further in describing how to do it, but just to make a couple of points.
Firstly, that it is a good idea not to draw right to the paper edge, but instead to consider that the plotter drawing surface is limited in some way, and I find that 270x180 mm is good for A4, 360x270 mm is good for A3, and so on (landscape dimensions). Plotter steps are typically 0.025mm or 0.000 98 inch or 1/40 mm or 1/1016 inch (not 1/1000 exactly).
I have found it most convenient when using HPGL to write a set of routines that mimic the ClearWin+ routines and then to copy my program’s graphics drawing routine but simply to change their names. This does not use anything like the facilities in HPGL or HPGL/2 but does simplify the task. I tend to write the plotter commands using very simple formats as that simplifies rereading the graphic file. CorelDRAW seems to import HPGL files without much demur no matter how big or complicated they are.
An alternative language for the interchange of vector graphics information is a file type called scalable vector graphics which is usually stored in files with the SVG extension. ClearWin+ has the ability to generate SVG files and in certain cases to import them so I describe this facility below.
The SVG graphics language is described in publicly obtainable documents on the Internet. Prior to the implementation of SVG graphics in ClearWin+ I had written my own routines using the method of mimicking ClearWin+’s names for graphics primitives and replacing the terminal @ with something else.
However, in a comparatively recent update to ClearWin+, it is possible to specify that the output should be in the form of SVG graphics language. SVG files are intrinsically readable by Adobe Illustrator as well as CorelDRAW!, but with the latter I have found that complex graphics do not import well, or in some cases at all, because of limitations in the recipient application, which I find strange if not downright unacceptable. It may well be a problem resolved in a later version of the application than the one I use.
The mechanism to switching to SVG format output is covered very clearly in the online help files. ClearWin+ generates superb SVG files, but the format is densely packed and it is not easy, therefore, to use ClearWin+ generated SVG files as a medium of interchange between two of your own programs.
11. I am told that the routine is not accurate when the font is bold or italic, and may underestimate the length somewhat.
FORTRAN and the ART of Windows Programming, Copyright © Eddie Bromhead, 2023.