Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Font size conversion issue using Style in JTextPane with HTML #165

Open
samuelhallstrom opened this issue Aug 28, 2020 · 5 comments
Open

Comments

@samuelhallstrom
Copy link

samuelhallstrom commented Aug 28, 2020

Hi,

I have found an issue related to font sizes when I use Styles within HTML documents. Below you find a small program that reproduces this. Basically, what happens is that if I set the font size for a Style, and then retrieve it, I do not always get the same value back, and this can cause very tiny fonts in the text pane, given a font size. The main reason is probably a bug in OpenJDK that I link to below (in short, different conversion tables are used to convert to and from points to CSS size in the StyleSheet class), but perhaps something can be done in Flatlaf.

A side note: Even if I use really ugly hacks to use the same conversion tables, a given font size seems smaller in the text pane than the rest of the application.

Link to bug: https://bugs.openjdk.java.net/browse/JDK-7022164?focusedCommentId=12231004&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel

Small program that reproduces the issue below (couldn't get the code formatting good, sorry). The font size 12 is set on a Style, but when retrieving it, it is 10. The same font size is set on the text pane in another panel and that shows how size 12 should look I think. Comment out the setLookAndFeel call and this problem disappears (on my Win 10 at leats).

Cheers,

Sam

Oh by the way, I really, really like this LAF. Good job!

public class FlatLafTest {

   public static void main(String[] args) throws ClassNotFoundException, UnsupportedLookAndFeelException, InstantiationException, IllegalAccessException, BadLocationException, NoSuchFieldException {
      UIManager.setLookAndFeel("com.formdev.flatlaf.FlatLightLaf");
      int fontSize = 12;

      JTextPane textPane = new JTextPane();
      textPane.setContentType("text/html");
      Style basicStyle = textPane.addStyle("basic", null);
      
      // Set font size 12
      StyleConstants.setFontSize(basicStyle, fontSize);
      
      // Immediately retrieve it. It is 10 with Flatlaf
      final int retrievedFontSize = StyleConstants.getFontSize(basicStyle);

      JFrame frame = new JFrame("Style bug");
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setVisible(true);
      JPanel panel = new JPanel();
      frame.add(panel);

      textPane.getDocument().insertString(0, "Font size " + fontSize + " set but retrieved: " + retrievedFontSize, basicStyle);
      panel.add(textPane);

      JTextPane textPane2 = new JTextPane();
      textPane2.setContentType("text/html");
      HTMLDocument doc2 = new HTMLDocument();
      textPane2.setDocument(doc2);
      final Font font = textPane2.getFont();
      final Font font1 = new Font("Monospace", Font.PLAIN, fontSize);
      textPane2.setFont(font1);
      doc2.insertString(0, "Font size for text added without styles, using textPane.setFont(font): " + font1.getSize(), null);
      panel.add(textPane2);
      frame.pack();
   }

}
@stanio
Copy link

stanio commented Aug 28, 2020

As far as I've found out it is related to JEditorPane.HONOR_DISPLAY_PROPERTIES:

Key for a client property used to indicate whether the default font and foreground color from the component are used if a font or foreground color is not specified in the styled text.

The default varies based on the look and feel; to enable it set the client property with this name to Boolean.TRUE.

If I add to your example:

        textPane.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.FALSE);

I get "Font size 12 set but retrieved: 12" using both of Metal and FlatLaf. So it appears Metal and FlatLaf use different defaults for that property, but I'm still not sure why:

        textPane.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);

would affect:

        // Set font size 12
        StyleConstants.setFontSize(basicStyle, fontSize);

        // Immediately retrieve it. It is 10 with Flatlaf
        final int retrievedFontSize = StyleConstants.getFontSize(basicStyle);

given the font size is set explicitly to that style. Happens with both Metal and FlatLaf so I suspect it's not a FlatLaf problem.

@stanio
Copy link

stanio commented Aug 28, 2020

I'm still not sure why:

        textPane.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);

would affect:

        // Set font size 12
        StyleConstants.setFontSize(basicStyle, fontSize);

        // Immediately retrieve it. It is 10 with Flatlaf
        final int retrievedFontSize = StyleConstants.getFontSize(basicStyle);

given the font size is set explicitly to that style.

There's some styleConstantsValueToCSSValue transformations happening in the javax.swing.text.html.CSS class, so:

        StyleConstants.setFontSize(basicStyle, fontSize);

sets a size which is closest to a set of predefined sizes like [8, 10, 12, 14, 18, 24, 36] (matching HTML <font size="2">) and might not set the exact given size. For some reason, with HONOR_DISPLAY_PROPERTIES=true this predefined set ends up different just for StyleConstants.getFontSize(basicStyle) (vs. StyleConstants.setFontSize(...)), f.e. [6, 8, 10, 12, 15, 20, 30], hence the discrepancy observed.

You may also use:

        System.out.println(((HTMLDocument) textPane.getStyledDocument()).getStyleSheet());

to compare the "default" styles with HONOR_DISPLAY_PROPERTIES=true and HONOR_DISPLAY_PROPERTIES=false.

@stanio
Copy link

stanio commented Aug 28, 2020

So, the behavior appears the same as with other L&Fs when setting HONOR_DISPLAY_PROPERTIES explicitly, but the problem observed when HONOR_DISPLAY_PROPERTIES=true (which happens to be FlatLaf default) doesn't seem like a FlatLaf bug.

@samuelhallstrom
Copy link
Author

samuelhallstrom commented Aug 28, 2020

Thanks a lot for your replies.

I think the main problem is that bug in OpenJDK that you also found now, but I guess I was hoping that there may be a way to work around this from FlatLaf.

Setting HONOR_DISPLAY_PROPERTIES=true seems to be what make that transformation table change (I guess by resulting in a call to doc.getStyleSheet().addRule( "BASE_SIZE ", newBaseSize). Then that OpenJDK bug uses the old transformation table for one of the conversions: Look in StyleSheets.java , the method Object fromStyleConstants(StyleConstants key, Object value) directly uses StyleSheet.sizeMapDefault and not the getter method (that's why you see different transformation tables, or rather array).

I agree with your conclusion that this is not a FlatLaf bug.

Thanks for looking at it.

@KlemenDEV
Copy link
Contributor

I can notice this also happening with e.g. JLabel using HTML inside. Sometimes the size also changes randomly when the component is re-rendered

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants