J2TextPrinter known problems

The Java 2 printing model was new in JDK 1.2 and there were a large number of problems there were not fixed until the JDK 1.3 release.  More problems were fixed in JDK 1.4, which also added some important new features.  For these reason, the use of JDK 1.4 or later, and preferably the current JDK, is strongly recommended.  This section documents problems present in Java that can impact your use of J2PrinterWorks.

Known Java problems affecting J2TextPrinter

Uneven character spacing when printing JTextPane, JEditorPane, or JTextArea - Bug Parade 6488219
Fixed in JDK 1.6.0_10.
Printing text using JTextPane, JEditorPane, or JTextArea can result in uneven spacing between characters depending on the font, as though the wrong kerning information is being used. Some letters have too much space after them, resulting in noticable (several pixel) gaps with the following letters. Other letters have too little space after them, resulting in their touching the letters that follow them. The problem only occurs in printed output, the screen display looks fine. The problem occurs for JTextComponent subclasses but not when printing the same strings using drawString. This was not a problem under JDK 1.4 but appeared starting with JDK 1.5 and continues in JDK 1.6. In JDK 1.5 some much more serious character spacing problems were fixed (see Bug Parade 4724061 and 4352983), which apparently introduced this new problem.  

Incomplete printing of HTML document containing PNG image to certain networked printers
Fixed in JDK 1.5.
We have had customer reports that an HTML document containing a PNG image will cause the document to terminate at the point of the PNG image when printing across the network to a Windows shared printer.  The problem occured for a Windows XP client printing to certain HP inkjet printers (HP InkJet 22/30 and HP OfficeJet G55) on a Windows NT server.  The same HTML document prints correctly across the network to the same printer and NT system under Internet Explorer. The same document prints correctly to other HP printers (e.g. HP LaserJet 6L, HP PSC 2410), to non-HP printers on the NT server, and when the server was Windows 2000 or XP.   The problem occurs for JDK 1.3.1 and JDK 1.4.2, but is fixed in JDK 1.5.  A workaround for earlier JDK's is to use a GIF or JPG image instead of  PNG.

Text and borders in HTML table run over right edge - Bug Parade 4764897
Fixed in JDK 1.5.
Significant drawing errors can occur for the rightmost column of HTML tables in JTextPane. For certain text and widths, text in the right column will fail to wrap properly within the HTML table cell and can overshoot the right table border by several characters. Iappears to be triggered when an earlier cell of the HTML table has a non-breaking word of size greater than its cell width.

HTML table only supports border=0 or border=2 - Bug Parade 4174871
Fixed in JDK 1.5.
Java displays and prints HTML tables either with no border (same as border=0, which is the default), or with border=2 if you specify border=n for any n>0.  A workaround to get 1 pixel wide lines is to convert the HTML table to a JTable, break the JTextPane into two parts, and use a J2FlowPrinter with a J2TextPrinter followed by a J2TablePrinter followed by another J2TextPritner.

HTML table border displays but won't print - Bug Parade 4691546
Fixed in JDK 1.5.
When using a JTextPane to display HTML, if the HTML uses the <table border> tag, it displays the table with a border, but if you serialize the StyledDocument of the JTextPane (such as printing with setCloningUsed(true), the default), the border disappears. Other HTML tags and subtags serialize OK and the table itself comes out OK, just the border is lost.  A workaround is to setCloningUsed(false), but there is no workaround if you need cloning turned on and are also using table borders.

 The <center> tag doesn't work if using HTMLEditorKit - Bug Parade 4671625
When using HTMLEditorKit to read HTML into a JTextPane, the <center> tag does not work, the text stays left justified.  The <center> tag is widely used by HTML editors (e.g. Netscape), so it's a pain not to have this work.  Workarounds:  the tags <div align=center> and <p align=center> work OK.  The <center> tag works OK you have the JTextPane read the same HTML from a file using:
URL url = new File(fileName).toURL();

HTML body doesn't display if <META content="text/html"> in <head> section  - Bug Parade 4695909
Fixed in JDK 1.5.
When the tag <meta http-equiv=Content-Type content=text/html> is included in the HEAD section of an HTML document read in using setText(String), JTextPane fails to render the body section entirely.  Workaround: parse the HTML String and remove everything in the HEAD section before calling setText(String).

Text styles shifted left or right - Bug Parade 4724061 and Bug Parade 4352983
Fixed in JDK 1.5.
If you print a JTextPane containing long lines of plain text with the occasional bold, italic, or underlined text, the styled text can wind up shifted left or right relative to where it should be. The result is either extra spaces or overlapping of characters and can be as much as several characters wide.  The problem does not show up on the screen. The effect is dependent on the text that appears before the style change on the line. Style changes early in the line show the problem less. Style changes later in the line can shift left or right depending on the earlier characters.  The effect is font-dependent, some fonts and sizes do better than others.

The problem is a result of a font metrics mismatch between the screen and the printer due to their differing resolutions.  Depending on the characters involved, a given number of display pixels don't convert to an exact number of printer pixels, and the cummulative round-off error can build up to a large number of pixels, either too many or too few.  When the style changes, Java sets the absolute printer position for the next run of text based on this calculation, and all the cumulative error shows up at once, resulting in either a gap or overlapping characters.

A workaround is to cause this repositioning to occur after every word or even after every character so that the error never gets too large.  If the JTextPane is defined using HTML, then every new HTML tag causes this repositioning to take place.  A sequence such as <b></b> does nothing and so it can be inserted as often as desired to bring about this effect.  The smallest sequence that appears to work and have no effect on the display is <a>.  This is the hyperlink ("anchor") tag with no HREF or other subtags, so a closing </a> is not required.  If you employ this technique after every character, you may discover that for certain fonts it is counter-productive after some characters (for example: l, m, n, i, ...), which would do better left alone.  A further refinement in this case is to build a "kerning" table indicating which characters are OK to follow with <a> and which are not.  The general idea is to place the repositionings where they are least noticeable, e.g., after whole words and after those characters whose width favors it.

Text clipped at right edge of JTextPane (or JLabel) - Bug Parade 4352983
Fixed in JDK 1.5.
Some JTextPanes with long lines will print with the rightmost character(s) partially clipped off.  The problem does not occur on the screen.  The problem can also occur in JLabel instances, including in the J2PrinterWorks headers and/or footers.  A workaround for the JLabel case is to pad your JLabel String with one or two extra spaces.  The <a> tag technique described under "Text styles shifted left or right" also works.

Problems importing RTF documents
J2TextPrinter is built on Java's JTextPane print (and related) methods.  The native Java StyledDocument format (DefaultStyledDocument) is well supported for both display and printing by JTextPane and thus J2TextPrinter.  Unfortunately, JTextPane has some problems supporting the RTF format, and these in turn affect J2TextPrinter.

JTextPane only imports a limited subset of the RTF format (see Bug Parade 4261277 and Bug Parade 4723383).  It will preserve most styles and sizes correctly but substitutes SansSerif font for anything that isn't exactly the same name as the fonts used by Java (on Windows these are: Time New Roman, Arial, Courier, Symbol, and WingDings). Many other key RTF features, including embedded graphics and tables, are also not supported.  However, whatever JTextPane imports and displays in the application window, J2TextPrinter is able to print reliably.

There are many postings on Sun's Bug Parade requesting that Sun address the problem of missing or broken RTF features.  Unfortunately, Sun's responses are generally negative and include statements like these:
    "The demand for RTF support seems to be low, so implementing this is a very low priority."
    "Unfortunately the rtf support in Swing is rather limited, and we don't plan on fixing this at this time."
There was even talk that Sun would drop RTF support altogether, though this hasn't happened. Based on this, Java's support for RTF is very unlikely to improve over its current state, and we therefore strongly advise you to either switch to the StyledDocument or HTML formats or restrict your use of RTF to just that narrow subset of features that presently work.

There is also a commercially-available RTF converter from Novosoft which is callable from Java and can convert RTF (including embedded graphics and tables) to the XML XSL FO format.  This package references converters which can transform XSL FO to HTML, PDF, Postscript, and other formats.  

Problems importing HTML documents 
Fixed in JDK 1.4
Java has continued to improve its HTML support from JDK 1.2 to 1.3 to 1.4.  While it can display basic HTML 3.2 web pages including images, tables, and frames, the capabilities fall short if you try to print any given web page or a page composed with HTML editing tools such as Netscape or FrontPage.  As with RTF, your document must explicitly use the Java fonts by name, otherwise it will substitute SansSerif.  As a result, the "Variable Width" font setting common in HTML documents winds up as SansSerif instead of Serif as in the standard browsers.  Also, prior to JDK 1.4, Java substituted larger font sizes for the "logical" HTML font sizes compared to the standard browsers (see Bug Parade 4285636 , a workaround is to use "relative" font sizes, see discussion for J2Label ).  Other spacing, alignment, and bullet style properties are approximated at best.  HTML tables can only have either no border or border=2.  HTML tables will only paginate on major row boundaries.  In general, for any given HTML tag, only a subset of subtags are supported.  

Images in HTML documents in wrong folder
The standard web browers assume that the images referenced with IMG tags in an HTML document are in the same folder (directory) as the .HTML file itself.  But in Java, loading your HTML document using the statements:
    java.net.URL url = new java.net.URL("file",null,fileName);
loads the HTML images from the program folder (i.e., the folder you were in when your program is executed), not the document folder (i.e., where the HTML document itself is), see Bug Parade 4294902 (and related bugs 4456393 , 4252701 , and 4472003 ).  A workaround for this problem is to access your HTML document with the statements:
    java.net.URL url = new File(fileName).toURL();
which will cause the images to be located properly relative to the document folder.  This workaround is incorporated in the J2TextPrinterTestApplication sample code.  

Document serialization doesn't work across Java versions
Solution provided in JDK 1.4
Sun serialization of documents is not compatible across JDK releases.  This means, for example, that the documents J2TextPrinterTestApplication or Stylepad save under one JDK version (e.g. 1.2.2) can only be read back by that release and not by any other JDK version (e.g., 1.3, 1.3.1, 1.4, 1.4.1, 1.4.2, etc.), and vice-versa.  In addition, the class HTMLDocument itself is not serializable, see Bug Parade 4630761.  However, JDK 1.4 added new XML classes XMLEncoder and XMLDecoder that provide an effective way to achieve long-term persistence of Java objects across different JDKs starting with 1.4.   To keep J2TextPrinterTestApplication and Stylepad usable under all JDKs, they have not been modified to take advantage of these new XML persistence classes. 

Can't insertIcon(Image) in an HTML document
Fixed in JDK 1.6
Due to a bug in the Java JTextPane implementation (see Bug Parade 4671653 and Bug Parade 4636235), you cannot embed an instance of the Java class Image into an HTML document in a JTextPane using the method JTextPane.insertIcon(Image) .  However, the HTML document itself can contain images using the usual <IMG SRC=image.gif> tag.  Also, the J2FlowPrinter component of J2PrinterWorks also lets you print HTML in a J2TextPrinter instance, followed immediately by a J2PanelPrinter instance containing an Image, followed immediately by more HTML in a second J2TextPrinter instance..

Problems printing a JTextPane with embedded components ("CloneException" or components missing when print from print preview)
Mostly fixed in JDK 1.6.
Using J2TextPrinter to print a JTextPane containing one or more components (embedded using insertComponent()) presents certain difficulties, owing to underlying problems with the embedded component support of JTextPane.  In particular, it is not possible to print a JTextPane with embedded components that is also displayed on the screen, because Java is not able to display (including print) the same component simultaneously in two different views.  For this reason, by default J2TextPrinter prints using a cloned copy of your JTextPane (i.e., the default is setCloningUsed(true)).  

However, Java serialization is not perfect and this cloning operation can sometimes fail depending upon the complexity of your JTextPane, particularly if you have embedded components (also note that HTML document serialization itself is broken in JDK 1.4, see Bug Parade 4630761.).  If your JTextPane cannot be cloned, J2TextPrinter will throw a com.wildcrest.j2printerworks.CloneException, and you will need to call setCloningUsed(false) in order to print.  However, in this case your original JTextPane and not a cloned copy will be added to a different view as part of printing and removed from your view hierarchy, causing it to disappear. To avoid this problem, you should use one of the following approaches:

1) Print using a JTextPane that is not and never was displayed.
2) Print using a second, equivalent, completely independent JTextPane which uses separately constructed copies of all embedded components and which  matches exactly the contents of your on-screen JTextPane but is not itself displayed on the screen.  Typically this second JTextPane will be built in parallel with your displayed JTextPane using duplicate operations.
3) Temporarily remove your JTextPane from your on-screen Frame (or JFrame, etc.) while printing using:
J2TextPrinterTestApplication switches to this approach if it gets a CloneException when trying to clone your JTextPane.  After printing is done, you can add your JTextPane back to your view hierarchy, or you may find it easier to rebuild your entire Frame.
4) Avoid embedded components entirely and instead use a J2FlowPrinter to alternate J2TextPrinter instances with J2PanelPrinter instances containing the desired components.  However, note that this approach does not allow you to embed components within lines of text, rather each component will appear on its own line alternating with your text down the page.

In addition, if you have an embedded component in your JTextPane and you call setCloningUsed(false), then J2PrinterWorks must call setVisible(true) on the internal imaging JFrame it uses as part of printing (or print preview).  This causes a "printing..." tab to show up in the Windows task bar, which is not removed when printing completes.  Calling the J2TextPrinter dispose() method after printing completes will deallocate this JFrame and thereby cause the "printing..." tab to go away.

Note that due to a regression error, Java can't print embedded components under JDK 1.4 at all, see Bug Parade 4708924, but this was fixed in JDK 1.4.1.

A related problem is that if  you have embedded components in your JTextPane and print using the "Print" button in the print preview dialog, the components can fail to print in the JTextPane (gaps will appear where the components would have gone).  The problem does not occur when you invoke print directly, i.e., not from print preview.  In addition to trying the above techniques, a reliable workaround for this problem is to use setSeparatePrintThread(false).  A refinement is to call setSeparatePrintThread(false) just before calling showPrintPreviewDialog(), then restore setSeparatePrintThread(true) when the print preview dialog returns, so that printing from the print preview dialog will use the same thread but regular printing will still use a background thread.

Null Pointer Exception if print or print preview while editing embedded JTable cell
Components embedded in a JTextPane such as JTable, JTree, JTextField, etc. are "live", in that you can edit them and print the results.  However, Java throws a Null Pointer Exception if you print or print preview while in the middle of editing a JTable cell.  The problem does not occur if you hit <CR> or tab out of the open cell in order to finalize your entry.  A workaround is to include an explicit call to JTable.getCellEditor().stopCellEditing() in order to perform the equivalent of tabbing out of the cell just before calling print() or showPrintPreviewDialog().  

Text insertion caret in embedded text components
J2TextPrinter controls the focus of the JTextPane being printed so that the text insertion caret does not appear in printed output.  However, if you have embedded text components in your JTextPane, J2TextPrinter cannot control whether one of these components will have focus and print with a text insertion caret.  Workarounds include having your embedded components not be focus traversable, calling setEditable(false) on your JTextPane, moving the focus to some other window when printing, or not having a text component as the first embedded component in your document.  Printing from the same thread also appears to fix the problem since it does not permit the UI thread to update the focus during printing.

CloneException when printing documents containing special (e.g. Unicode) characters
Fixed in JDK 1.4.2.
Due to a bug in Java, printing documents containing non-ASCII (e.g Unicode) characters cause Java to throw a NotSerializableException, which J2PrinterWorks rethrows as a CloneException.  This problem can be avoided by calling setCloningUsed(false), but there is no workaround if cloning is required.  This problem was fixed in JDK 1.4.2.

Printing JTextPane with embedded components throws IllegalStateException (JDK 1.4.0, JDK 1.4.2) - Bug Parade 4708924
Regression from JDK 1.3.1, fixed in JDK 1.4.1, broken in 1.4.2, fixed in 1.4.2_02
When Java tries to print (or print preview) embedded components under JDK 1.4, it throws the exception:
    java.lang.IllegalStateException: constrain(xywh) not supported for complex transform
This problem was fixed in JDK 1.4.1, broken again in 1.4.2, and fixed again in 1.4.2_02.  The problem was a regression from JDK 1.3.1 where printing embedded components worked OK.  Embedded components in JTextPane has always been a somewhat flaky feature of Java, and we recommend you instead use a J2FlowPrinter with alternating J2TextPrinter and J2PanelPrinter instances to embedded Java components in a text document.

The LineSpacing ParagraphAttribute for JTextPane doesn't work (JDK 1.3.x and 1.4.0) - Bug Parade 4242645
Fixed in JDK 1.4.1
The LineSpacing attribute doesn't work in JTextPane in JDK 1.3.x or 1.4.  Since it doesn't work in JTextPane, there is nothing J2TextPrinter can do about this since J2TextPrinter can only print what JTextPane will draw.

Can't type characters immediately after embedded JTable (JDK 1.3)
Fixed in JDK 1.4
This is not a printing problem, but might arise in your working with JTextPane documents.  If you use the JTextPane method insertComponent() to embed a JTable in your JTextPane and then place the cursor immediately after the JTable and begin typing (or programmatically insert text), an exception will be thrown on each keystroke due to a bug in Java (see Bug Parade 4353673). The problem only occurs if the JTable is contained in a JScrollPane, but unfortunately that is the typical case since this is how you get JTable column headers to appear.  The problem does not occur if the JTable is inserted directly (not contained in a JScrollPane), and the problem does not occur for components other than JTable contained in a JScrollPane. 

Printing is slow, especially pages with embedded images or components (JDK 1.2.x)
Improved in JDK 1.3, fixed in JDK 1.4
Under JDK 1.2.2, printing a full rich text page takes Java about 30 seconds, before the actual OS spooling to the printer.  In addition, due to major performance problems in JDK 1.2.2 (see Bug Parade 4185726), the printing of pages containing any embedded images or components is 3-4 times slower, even if just one small image or component is present. The J2TextPrinter background printing thread feature is a great help in overcoming this problem for interactive (client) applications.  

Problems with JTextPane text layout (JDK 1.2.x)
Some fixed in JDK 1.3, more fixed in JDK 1.4
J2TextPrinter relies on the Java JTextPane component for its printing functionality, including layout of text and graphics.  Any anomalies displayed using JTextPane will carry over to printing the JTextPane component and additionally Java's JTextPane printing can introduce anomalies of its own.  The following problems have been noted:

JTextPane tab support broken (JDK 1.2.x)
Fixed in JDK 1.3
This isn't a J2TextPrinter problem per se, but it is something people often run into when printing.  JTextPane tabs simply don't work under JDK 1.2, even though tabs used to work in Swing.  Check out the Sun Bug Parade report 4191750 on this problem.

Here's how to set up tabs (only works in JDK 1.3 or later).  Look at the J2TextPrinterSimpleTest makeAttribute method.  To set 5 tabs, 1 inch (72 "points") apart, you can add the following lines:
        TabStop[] tabStopArray = new TabStop[5];
        for (int i=0; i<5; i++) tabStopArray[i] = new TabStop((float)((i+1)*72.0));
        StyleConstants.setTabSet(attribute, new TabSet(tabStopArray));
Then you simply insert "\t" (tab) characters wherever you like in the appendStyledText method calls.

If you only need single tabs, for example to add 1" line or paragraph indentation, adding the following line does work under all JDK's 1.2 or later::
        StyleConstants.setFirstLineIndent(attribute, (float)72.0);
Note that the size is given in printing coordinates, for which there are 72 units per inch.

The basic rule for J2TextPrinter is that (with a very few exceptions) it will print whatever you can get JTextPane to display on the screen.  

Black backgrounds when printing transparent GIFs under Windows NT (JDK 1.2.x)
Fixed in JDK 1.3
Under Windows NT, GIF images with transparent backgrounds print incorrectly with black instead of transparent backgrounds due to a known Java bug (see Bug Parade 4175560), despite the fact that they display correctly.  Under Windows 95 and Solaris, transparent GIFs display and print correctly.  There are two workarounds for this: 1) make your GIFs with white non-transparent backgrounds or 2) make your GIFs with white backgrounds, specify white as your transparent color, and change non-transparent white pixels in your icon to near-white so they aren't transparent when displayed. 

Problems printing documents containing Chinese characters (JDK 1.2.x)
Fixed in JDK 1.3
It has come to our attention that Java will print incorrect characters in documents containing Chinese Unicode characters under JDK 1.2.2.  The printed output will be wrong even though the J2TextPrinter print preview is correct. 

HTML printing more-or-less unusable under JDK 1.2.x
Fixed in JDK 1.3
Printing of HTML only works intermittently under JDK 1.2.2, with Java often throwing exceptions and sometimes printing.  Printing under JDK 1.2.2 is very slow when it does work.  Also, JDK 1.2.2 always substitutes SansSerif, even if you use the Java fonts by name.   Another problem is that JDK 1.2.2 displays (and prints) meta tag indicators in the document (see Bug Parade 4245401).  

Copyright 2009, Wildcrest Associates (http://www.wildcrest.com)