printing

Use this page to accumulate pointers to various issues tcl has with printing:


Various Printing Question:

  • Can we have some cross-platform printing commands that hide all the complexity?
  • How do I print (output a representation of the contents onto a physical sheet of paper) the contents of a text widget that contains various unicode, mixed fonts, colors, etc. ?
  • How do I print a text widget with embedded images?
  • How do I print a spreadsheet or HTML rendered web page?

LV writes:

Printing means different things to different people - different interpretations include:

  • generating a report, like perl's format type command
  • the equivalent of a screen shot of a particular window
  • produce on paper the equivalent of what is on the screen, only scaled to the size of the paper
  • write, directly to a printer, the reports
  • [add your interpretation here]

Different printers can expect data to be in ASCII, PostScript, as well as a variety of custom (and sometimes proprietary) languages. Modern operating systems use printer drivers to generate data in the correct format for the specific printer, but must be fed with data in the correct format for the operating system. In UNIX systems, the printing systems available typically convert files of various formats into PostScript, while in Windows it is GDI.

LV One needs to pick what it is that you are trying to print , then create a solution for that. Once you feel you have something useful, then work with the TCT to create a TIP proposing the way to integrate the solution in Tcl.


To solve the "printing means generating a hard copy type report problem" requires a set of functions that provide assistance in setting the following potentially required features:

   a. a report front page
   b.  a page's header (with possible multiple lines, with possible alternating left and right segments, and possible page numbering)
   c.  footer (see b.)
   d.  generated page breaks at user-definable locations

and then is triggered by being called with the next line of output for the report.

Ideally, one would be able to generate the report to a file, so that one could generate multiple reports in parallel.

Some people might have a requirement that the functions generate the report in PostScript format.

[Add more requirements here]


To solve the "printing an exact duplicate of any specific application window" problem, one needs to be able to generate graphics, colored and styled text in various colors, and fonts, etc.

There are two parts to this. The first is coming up with code on any one specific platform to perform this. For instance, see printing under Windows or printing under macosx. Solutions have to be devised for each environment - and solutions for X may very well be tougher than others. Some people generate HTML and then issue remote commands to web browsers to trigger the print process.

Another part of this problem is figuring out a general API. If printing is going to be a part of Tk on various platforms, it would be best to have a cross platform package, reducing a developer's work in getting the output desired.

[add more requirements here]


LV It seems like a way to begin would be to brainstorm on the requirements and come to some agreement on the interfaces needed, then take on some portion of functionality that is desired, implementing it, then moving on to the next piece.

As mentioned above, printing means many different things to different people. What if we started with a list of what functionality is needed, along with what techniques exist now for providing that functionality?

Types of printing that a Tcl or Tk developer has identified as a need.

  1. output to a printer simple ASCII text
  2. output to a printer simple ASCII text formatted into one of various report formats
  3. output to a printer text in various fonts and colors as displayed in a tk widget
  4. output to a printer a scaled representation of one or more toplevel windows

There are currently several techniques for accomplishing printing supported by Tcl/Tk.

  1. tcl has the ability to open a device and write plain ASCII characters to it. This provides the crude ability for a text editor to get a file's contents printed. KPV under Windows see Printing text files under Windows
  2. TclVSrpt provides some report creation support
  3. I don't know of anything that provides cross-platform support for printing text in appropriate fonts and colors as displayed in a tk widget.
  4. tk's canvas has the ability to generate a PostScript file that reflects an image of some portion of the canvas's contents. [What are the limitations of the canvas postscript generation?]

In addition, tkprint has the ability on windows to perform some degree of printing.

Now, as people read over this, perhaps they will add the names of other extensions which provide some degree of print support.


[Discuss use of Xbit to help with printing. Example: the following script will create a Tk photo from a GUI window:

    # create ram image from a GUI window
    rimage window ramimg [rimage window $guiPath frame]

    # create a gimg image from a ram image
    set img [image create gimg -file ramimg]

    # create a Tk Photo named gui.photo
    $img dump gui.photo TKPHOTO 8 1

    # create a canvas image item with the gui.photo and print it

.....]


In the past, people have suggested generating output in PostScript, PDF, HTML, XML, and other formats. The aim is often to solve the problem of platform-dependence, and/or to offload the printing itself to another application - e.g. Adobe Reader for PDF, and a web browser for HTML.

escargo 16 May 2005 - It may be that we need to use pdf4tcl or Trampoline! to generate PDF files rather than driving a printer directly. I know I have been wondering about simple data base input (using some kind of forms) and data base publishing. I just had a disk upgrade that made me lose my Microsoft Windows applications, which meant that I could not access my MS Access data base any more. That made me feel really vunerable. In looking at how to be independent of Microsoft, the issue of how to print my reports comes to the forefront. This is an issue I would love to solve within Tcl.

PDF is an electronic representation of a printed document, that is independent of the printer and the operating system. If it is used as the intermediate state of a printing solution, the code that writes the PDF file has full control over layout. HTML is less useful as a format for this intermediate state, because it is not a page layout language, and so the browser or other tool that reads the file will have control over page layout.

RS (ab)uses IE as printer driver for multilingual documents by generating a temporary HTML file (see taiku goes multilingual).

Sarnold is writing pdfcanvas ( [L1 ] , [L2 ] ). The goal is to provide a canvas with PDF creation support. Then the step PDF -> portable printing should be easy, at least on most UNIX-like systems (via lpr), and probably on Windows and MacOSX too.


http://www.cpsc.ucalgary.ca/~roseman/tclprint/ used to be a web page where a tcl extension for printing was discussed, but that URL appears to no longer be available.


LV's c.l.t posting "What's the most important thing lacking in your Tcl toolbox?" dated 2007-08-13 [L3 ] inevitably brought forth much discussion of printing. Since LV encouraged "everyone for whom printing is an issue to contribute thoughts, problem areas, suggestions, etc" to this page, some of the points from that thread are summarised below.

  • slebetman pointed out that since the Mac, Linux and the majority of Unices use CUPS, we really only need to support 2 platforms: Windows GDI and CUPS - and suggested a platform-independent interface, like the file related commands and Tk. He can already reliably print on Windows in a native-ish way via the Printer and GDI extensions. He can also print on Unix in a native-ish manner, provided he has a postscript printer (or Ghostscript), by simply dumping the canvas (though, scaling the page is not as nice as the GDI+Printer solution).
  • MJ asked whether any (scripting) language supports printing for multiple platforms as a library or out of the box; Joe English wondered whether any languages, toolkits, or frameworks out there have good printing support. Joe said that the main obstacle to good printer support in Tcl is that nobody knows how to do it. If somebody, anybody, has figured this out, then we can solve the bulk of the problem just by using their design. (KJN adds: since the libraries mentioned below are incompatible with the Tcl License, their design cannot be used unless we take appropriate measures not to copy any of their code.)
  • Kevin Walzer recommended wxWidgets [L4 ]. It's a C++ library, but has scripting interfaces (wxPython is the most well-known). And it seems to provide excellent printing support across platforms, wrapping the native API on each platform. (The "wxWindows Library License" is based on the LGPL.)
  • Stephan Kuhagen recommended Qt [L5 ]. (Qt is GPL-licensed.)
  • DKF added that the problems with printing are actually quite nasty. The problem is that there are two totally different approaches to doing printing, and Tk only supports one of them (and only partially at that!) While on standard Unix systems printing is done by sending postscript into the 'lpr' program, on Windows printing is done by drawing using a special context. And to cap it all, only the canvas supports postscript generation anyway. Fixing it all requires *real* work. Also, different platforms have different interaction styles (blocking vs. non-blocking) for their standard dialogs. Messy!
  • Arjen Markus added that the standard dialogue that pops up on Windows when you print something depends on the printer too. Try printing to a file for instance (as is often needed when printing a picture so that you can import it in a document): Sometimes you can specify a file name (typing it), sometimes a file selection dialogue pops up, sometimes you have no control whatsoever and you have to guess where the thing ends up! Lots of variations and it is very hard to control.
  • Bryan Oakley said that for him, the biggest missing piece is the ability to take the contents of a text widget and print it out while retaining most of the formatting. Every commercial product that he has worked on that was implemented in Tk has struggled with the lack of a decent printing solution.

The c.l.t thread "Obstacles for Tcl/Tk commercial application development ?" [L6 ] has a very long discussion, mostly about the problem of printing.


Windows-specific

See also Printing text files under Windows - short answer, for plain text on default printer,

 exec notepad /p $filename

Windows printer information with no particular connection to Tcl;

    package require registry
    registry keys HKEY_CURRENT_USER\\Printers\\Connections

or

    package require printer
    printer list

"printer" here is Michael I. Schwartz's extention, talked about over on the tkprint page.


Use this to access a Windows way to have a printer properties dialog come up:

 RUNDLL32 PRINTUI.DLL,PrintUIEntry /p /n\\machine\printer

ZB - the above works, when one gives particular "\\machine\printer" as parameter. But how can be printer dialog opened "at the very start", allowing to choose the printer first? For printing ordinary text file - not for HTML, like the "hack" below.

RS Surprisingly (positively) you can call

 rundll32 printui.dll,PrintUIEntry /?

to get a lengthy "man page". I can't see a way to use it without printer name, though. But PrintUIEntry is just one symbol in printui.dll...

ZB - as for WinXP, it's surprisingly indeed. But the problem remains: how can I use this sequence for printing a text file (it seems, that I cannot)? Just "accessing properties" - and then nothing more - isn't especially useful. BTW: how in Windows can the host and printer be accessed by some default names? Using "\\localhost\default" (as for "default printer connected to LPT/USB port") doesn't work.


Yet Another Hack To Print Under Windows:

 RUNDLL32.EXE MSHTML.DLL,PrintHTML "C:\Path\To\Somefile.html"

The above will open the Printer selection dialog allowing you to choose where to print. More information available here: [L7 ]


During summer 2002, KBK says on comp.lang.tcl:

I'd love to have native printing on Windows, and would even devote a fair amount of time to it. The difficulty, though, is in coming up with a specification of just what "native printing" is - one that meets the requirements of a fair number of applications.

Generally speaking, page layout is vastly different from screen layout, so what's desired is NOT simply a "print screen" function. Printing a canvas to PostScript comes close for drawing applications, but is totally wrong for a text editor, and a "print" function for the text widget is out of reach unless we can define the pagination mechanism.

It's a hard problem to get started on. The mechanics aren't horribly difficult -- in fact, the hard part from the mechanical standpoint would be a backport of the functionality to Unix. Instead, the really thorny issue is defining what's wanted.


UNIX-specific

On Unix, one can invoke

 exec lpr filename

or

 exec lp filename

to request a file be printed on the local printer. If the system is configured properly, then the file can be of various formats, and the proper conversions will take place.


KBK's quick-and-dirty Unix-side Tcl-ignorant xwd-enabled screen-dump-to-printer:

    exec xwd -id [winfo id .] | xwdtopnm | ppmtops | lpr

MAC-specific

Note that the BI distribution for Mac OS X includes the MacCarbonPrint package.


Kroc - I think Michael Schwartz's gdi+printer solution could be a good starting point, where printing will be splitted in two parts: a cross-platform drawing context and platform specififcs hooks to native printing dialogs (at least for Windows, Mac and linux). The drawing context could be a special canvas using paper instead of screen (like gdi does) while printer and MacCarbonPrint already provide good hooks for Windows and OS X. If gdi+printer and MacCarbonPrint could be merged and use same command names and args, a big step would be done.

SRIV Printing to Postscript is a good common denominator. Linux & Mac use Ghostscript through CUPS, and Ghostscript is available for Windows. Seems sensible to leverage that. I recall using Ghostscript in DOS ~1992 with great success. I print business checks generated on a canvas with precise alignment on Linux. I'll have to try it on Windows some day to see for sure how capable it is.

ZB - Perhaps I'm taking it too simple - but couldn't be possible just to add ability to send a frame/widget/window contents to *.ps (or *.pdf) file? If the contents of the window can be shown on the screen - perhaps its contents could be "described" directly in PostScript? Really no idea about difficulty of such processing. It could be additional "command", common for every widget - and for beginning there could be made a try with simple "label", just to allow something like: ".window.label print" - where "print" means: "save image of the .window.label into a window.label.ps".


Fabricio Rocha in brainstorming moment - 06 Apr 2009 - I think that the lack of good printing support is the hardest argument against Tcl/Tk for commercial development and it´s past the time this issue had to be solved. I have a feeling that PDF generation is very good but it is not the way. From what I´ve read in various articles and posts in comp.lang.tcl, it seems that all the issues involved with printing are being largely mixed up and confused -- these include how to show a page in screen and transform that into a PostScript or PDF; or how to communicate with the printers, the printer dialogs, how to get contents of widgets printed, etc.

I don´t know how hard the task would really be, but we need to identify and isolate the different issues. For example, I think that Tk should provide a "print" command, which would be used for sending data to a default printer (in different modes, such as ASCII/PostScript/PCL), retrieve a list of available printers, retrieve information from the selected printer (like paper size, default font for plain-text printing, color mode, etc). Notice that most of the command functionality would be "read-only", except for the data output subcommand. There should be commands to allow the user to choose a printer and configure it, but these commands would simply invoke the underlying OS/printing system and its native dialogs, and after they were closed/OKed the application would read the configurations again -- i.e., the dialogs and printer configuration would not be a duty for Tcl itself. I have a strong impression that this is how most "native" programming environments/languages work, and should be enough if we use the "GDI+CUPS approach" proposed by slebetman. And we must also remember that data would not be sent directly to a printer, but to its driver, and this is an abstraction layer which works very well for each platform, if not among different platforms.

The second step would be WYSIWYG for Tcl/Tk -- in my opinion, nor the canvas nor the text widgets are really appropriate for that, and a really new (and complex) widget should mix their features somehow. I imagine something like a "pageview" widget which would show "page" objects (i´m not neccessarily talking about OO here). These "page" objects could be configured in size (papersheet-like or metrical/imperial units), margins and orientation; and would somewhat act as containers, much like toplevels and frames. On top of them one could create "frames" -- not like the frame widgets, but instead content areas, editable or readonly, which could also include images, with the same functionality of our beloved text widgets (here is where code could be reused). Possibly those frames could be arranged in the page with our old friends pack/grid/place, and could expand automatically until filling the whole page -- when this happens, the content could optionally flow to a new page object created with the same layout of the previous one. And then -- back to the printing issue -- these page objects could be completely transformed into "printer code" and sent to the printer driver by the "platform-specific portion" of the Tcl/Tk interpreter.

'FM' suggest about printing issue, something like that :

set Printer [chan open [tk_choosePrinter]]
chan puts -format pdf -- $Printer [read [open file.pdf]]
chan puts -format ps -- $Printer  [read [open file.ps]]
chan puts -format txt -- $Printer [$Text get 0.0 end]
chan puts -format img -- $Printer [image create photo -format window -data $win]
chan close $Printer

Fabricio Rocha 08-Apr-09 - Hmm, this looks simple as desired, but I think there are difficulties. This approach contains a common confusion about the output issue, and PostScript is the major example -- it is not a file format, nor a formatting filter, but indeed a kind of a special programming language which is understood by some printers. This is not the case of "txt" or "img", which here are used basically like file formats ("pdf" might fall in this category as well). chan could even be able to wrap some binary or ASCII data in a file format, but it would have no ways to effectively create and/or setup this data.

RJM 2013 - Printing canvases work well, e.g. using the Schwarz packages printer and gdi. The packages are released as 8.5.7-packages, but they operate well under Tcl 8.6. However, there is still no capability to print a text widget while pretaining fonts, text sizes and colors. A trick, embedding a text widget in a canvas, yields a black box at the position of the text widget. The Tkprint 1.1 package [L8 ] does this job, but it is pretty old, does not retain fonts etc. Only its PrintWindow works OK in this respect, but that's based on taking a screenshot of the appropriate display part. Since there is some commercial interest here, a certain paid effort could be applied in order to realize text widget printing as required (Windows).