JDK-5062649 : REG: JEditorPane/JTextPane(J2SE1.5) No support for dynamic Fonts
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 5.0
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2004-06-14
  • Updated: 2005-09-20
  • Resolved: 2005-09-20
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other JDK 6
5.0u7Fixed 6 b53Fixed
Related Reports
Relates :  
Relates :  
Relates :  
Description
Name: js151677			Date: 06/14/2004


FULL PRODUCT VERSION :
J2SE 1.5 -beta1-beta2

ADDITIONAL OS VERSION INFORMATION :
Linux/WindowsXP

A DESCRIPTION OF THE PROBLEM :
In J2SE 1.5 beta release, the swing JEditorPane and JTextPane does not support font created on the fly(that is, a font that is not insatalled on the underlying OS but created using the java.awt.Font.createFont() method). However,  all other swing components support this. This feature was supported by all swing components, including JEditorPane and JTextPane, in earlier release of JDK,.


REPRODUCIBILITY :
This bug can be reproduced always.

Release Regression From : 1.4.2
The above release value was the last known release where this 
bug was known to work. Since then there has been a regression.

(Incident Review ID: 277251) 
======================================================================

The test case is:
/*
 * TextPaneDemo.java
 *
 * Created on September 7, 2004, 10:19 AM
 */

/**
 *
 * @author  mshahriar
 */
import java.io.*;
import java.awt.*;
import javax.swing.text.html.*;

public class TextPaneDemo extends javax.swing.JFrame {
    
    /** Creates new form TextPaneDemo */
    public TextPaneDemo() throws Exception {
        
        initComponents();
        
        //we want to use font named amoraboti-unicode.
the font file name
        //is amoraboti_unicode.ttf. this file contains
Bangla (unicode name
        //is Bengali) character set. suppose this font
is not installed in
        //the system, so we want to create it
manually.
        
        //NOTE:
        File fontFile = new
File("amoraboti_unicode.ttf");
        FileInputStream inStream = new
FileInputStream(fontFile);
        
        Font banglaFont =
Font.createFont(Font.TRUETYPE_FONT,inStream);
        banglaFont =
banglaFont.deriveFont(Font.PLAIN,12);
        
        //set the font of the text field
        textField.setFont(banglaFont);
        //insert some text in the textfield, the text
is in Bangla. this works
        //fine in all JDKs greater than or equal to
1.4 and also in the 1.5 beta.
        String text =
"\u09AC\u09BE\u0982\u09B2\u09BE";
        textField.setText(text);
        
        //set font and text in first text pane. this
works fine in JDK greater
        //than or equal to 1.4 but not in JDK 1.5
beta.
        textPane1.setFont(banglaFont);
        textPane1.setText(text);
        
        
        //set some html text in first text pane. this
works fine in JDK greater
        //than or equal to 1.4 but not in JDK 1.5
beta.
        String html = "<html><body><font
face=\"amoraboti-unicode\" size=\"4\">" +
        				text + "</font></body></html>";
              
        textPane2.setEditorKit(new HTMLEditorKit());
        textPane2.setText(html);
    }
    
    /** This method is called from within the
constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content
of this method is
     * always regenerated by the Form Editor.
     */
    private void initComponents()
{//GEN-BEGIN:initComponents
        textField = new javax.swing.JTextField();
        midPanel = new javax.swing.JPanel();
        scrollPane1 = new javax.swing.JScrollPane();
        textPane1 = new javax.swing.JTextPane();
        scrollPane2 = new javax.swing.JScrollPane();
        textPane2 = new javax.swing.JTextPane();

        getContentPane().setLayout(new
java.awt.BorderLayout(5, 5));

       
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        textField.setPreferredSize(new
java.awt.Dimension(11, 25));
        getContentPane().add(textField,
java.awt.BorderLayout.NORTH);

        midPanel.setLayout(new java.awt.GridLayout(1,
2, 5, 5));

        scrollPane1.setViewportView(textPane1);

        midPanel.add(scrollPane1);

        scrollPane2.setViewportView(textPane2);

        midPanel.add(scrollPane2);

        getContentPane().add(midPanel,
java.awt.BorderLayout.CENTER);

        java.awt.Dimension screenSize =
java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((screenSize.width-428)/2,
(screenSize.height-329)/2, 428, 329);
    }//GEN-END:initComponents
    
    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) throws
Exception  {
        new TextPaneDemo().setVisible(true);
    }
    
    // Variables declaration - do not
modify//GEN-BEGIN:variables
    private javax.swing.JPanel midPanel;
    private javax.swing.JScrollPane scrollPane1;
    private javax.swing.JScrollPane scrollPane2;
    private javax.swing.JTextField textField;
    private javax.swing.JTextPane textPane1;
    private javax.swing.JTextPane textPane2;
    // End of variables declaration//GEN-END:variables
    
}
###@###.### 2004-09-08
###@###.### 10/21/04 18:30 GMT

Comments
EVALUATION the fix introduced a regression: 6361892 Printing of HTML through JEditorPane is broken since Mustang-b53
12-12-2005

EVALUATION Here is how we can address it: HTML only part: CSS does not try to translate font-names by itself. It relies on StyleContext for this. StyledDocument and HTML part: component's font is stored in the default style for the document. StyleContext.getFont(family, style, size) uses the stored font to derive from it when needed. byproduct: Developer can override StyleContext.getFont to customize the font mapping. It was impossible to do because of the CSS font-name translation. note: part of the test from the bug description will not work after the fix. They do not set the font for textPane2. This component does not know about amoraboti-unicode font. you might check for the details here: http://sa.sfbay.sun.com/projects/swing_data/mustang/5062649
07-09-2005

EVALUATION Could you please provide a test case for the bug? I am not sure I understand the description. ###@###.### 2004-06-14 ================= swing-text is using the font from setFont(Font font) to get fontFamily, fontStyle and fontSize. (for JTextPane it happens all the time. See JEditorPane.honorDisplayProperties to enable this for JEditorPane) These values are used to create font in javax.swing.text.StyleContext.getFont For html documents fontFamily is translated using (new Font(fontStyle,Font.PLAIN,12)).getFamily() ( see javax.swing.text.html.CSS.setFontName ) Font.createFont does not make font available for new Font. This is why new Font("amoraboti-unicode") is not amoraboti-unicode font. There are seems to be three ways to address this bug. 1. Use the font from setFont directly. StyledDocument might use multiple fonts. Some of them might be created using Font.createFont Using only one font from setFont does not solve it 2. have fontFamily to font mapping per text component basis. having API like component.registerFontFamily(String fontFamily, Font font) <note> For styledDocuments is is possible to do now. Customize StyleContext.getFont to return fonts created by Font.createFont. styledDocument = new DefaultStyledDocument(new CustomizedStyleContext()); textPane.setDocument(styledDocument) For html documents it will not work because of the font family translation I have mentioned before. </note> 3. Have global fontFamily to font mapping. for example: Font.registerFontFamily(String fontFamily, font) after that call new Font(fontFamily) will pick up a correct font. The first one does not do. The second offers great flexibility. The price for this is maintaining mapping from font families to created fonts. Also it requires developers to register such mapping for every text component which could be both confusing and error prone. The third one is more satisfactory than the previous one in my opinion. While not offering as much flexibility as the second one it solves this problem once and for all. (Using the second solution it is is possible to have different mapping for different components. For one component Dialog could be Helvetica for the other one it could be SunsSerif. I am not sure that it is a common use case) Reassigning to java2d team. ###@###.### 10/22/04 03:28 GMT ============================================= This analysis is not unexpected. It is essentially the same as 4950815. The difference is that in that report the app was using createFont incorrectly, whereas here it is but it still didn't work, so we need to look deeper into how Swing uses the font. What swing is doing is not reliable. It needs to do more to compare the fonts to decide if this is valid. Font is subclassable - Swing even subclasses Font itself - therefore "new Font(..)" based on a few pieces of information is not necessarily correct and cannot be guaranteed to preserve behaviour. In this particular case the issue is that Fonts created from createFont are by specification not available to new Font(..). Anything that may have worked like that is unspecified unreliable behaviour. In this case the app was obeying the rules but Swing was not being careful enough. There are many reasons why the simplistic approach apparently used in Swing cannot be supportable, since it ignores any attributes set on the font. Font.deriveFont would work in this case and all cases except subclasses where its more complex. We need to investigate the alternatives but at the very least it is clear that simply extracting the family and creating a new Font is not strictly correct. It may be more complex for HTML where attributes are set differently and you want to ignore other attributes on the Font. However that presumes a lot about what you know about applicable Font attributes. But deriveFont would seem to have a much better chance of working thna new Font. Reassigning to swing but I think we'll need more discussion. ###@###.### 10/22/04 05:07 GMT
22-10-0004