bobbylight / RSyntaxTextArea

A syntax highlighting, code folding text editor for Java Swing applications.
BSD 3-Clause "New" or "Revised" License
1.12k stars 259 forks source link

Cannot enable ligatures (JetBrains Mono font) #503

Closed tferr closed 4 months ago

tferr commented 1 year ago

JetBrains mono is a much-improved font for coding, featuring many readability features such as coding-specific ligatures. I am not able to use this font properly in RSyntaxTextArea.

Take this snippet that requires FlatLaf and the FlatLaf JetBrains Mono distribution (direct downloadable jars for both dependencies: flatlaf, flatlaf-fonts-jetbrains-mono):

import java.awt.Font;
import java.awt.font.TextAttribute;
import java.util.*;
import javax.swing.*;

import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;

import com.formdev.flatlaf.fonts.jetbrains_mono.FlatJetBrainsMonoFont;
import com.formdev.flatlaf.util.FontUtils;

public class Test {

    public Test() {
        FlatJetBrainsMonoFont.install();
        run(new JTextArea());
        run(new RSyntaxTextArea());
    }

    void run(final JTextArea ta) {
        final Font f = FontUtils.getCompositeFont(FlatJetBrainsMonoFont.FAMILY, Font.PLAIN, 40);
        final Map<TextAttribute, Object> textAttributes = new HashMap<>();
        textAttributes.put(TextAttribute.KERNING, TextAttribute.KERNING_ON);
        textAttributes.put(TextAttribute.LIGATURES, TextAttribute.LIGATURES_ON);
        ta.setFont(f.deriveFont(textAttributes));
        ta.setText("Current font: " + ta.getFont().getFontName() + "\nligatures: ## <> => ++ ~~ <= >= <=> ->>");
        JFrame frame = new JFrame(ta.getClass().getSimpleName());
        frame.getContentPane().add(ta);
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(final String[] args) {
        new Test();
    }

The ligatures do render in JTextArea: image

..but not in a RSyntaxTextArea:

image

Why is that? I could not find any obvious signs that TextAttributes are being overridden in the code base.

tferr commented 1 year ago

pinging @DevCharly in case they have experienced this elsewhere

DevCharly commented 1 year ago

I'm actually surprised that ligatures work in Swing 😮 Didn't know TextAttribute.LIGATURES...

So I tried to enable ligatures in FlatLaf Theme Editor, which uses RSyntaxTextArea, and it works 😮

image

I think the reason is that FlatLaf Theme Editor uses a subclass of org.fife.ui.rsyntaxtextarea.SyntaxScheme, which always uses the same font that has the ligatures attribute.

There are several places in SyntaxScheme where a new font is created using family, style and size, but without attributes. I think the ligature attribute is lost there. E.g.

https://github.com/bobbylight/RSyntaxTextArea/blob/9097e51fc5e289d761dca139a3a08459bf12614a/RSyntaxTextArea/src/main/java/org/fife/ui/rsyntaxtextarea/SyntaxScheme.java#L445-L449

or

https://github.com/bobbylight/RSyntaxTextArea/blob/9097e51fc5e289d761dca139a3a08459bf12614a/RSyntaxTextArea/src/main/java/org/fife/ui/rsyntaxtextarea/SyntaxScheme.java#L109-L110

To fix this, and keep the usage of StyleContext.getFont(), it is probably necessary to additionally invoke font.deriveFont(Map attributes) to reapply some font attributes of the base font.

tferr commented 1 year ago

Thanks a lot for this. I'm closing it, as this is a reasonable workaround.

bobbylight commented 1 year ago

I'll reopen this to make the necessary changes in SyntaxScheme pointed out above. Thanks folks for this!

bobbylight commented 4 months ago

Fixed in #554 and #559.