Как установить «резервный» шрифт - PullRequest
0 голосов
/ 28 сентября 2018

Я использую Java 10 и качаю.Я использую шрифт DejaVu Sans Mono, потому что я думаю, что он выглядит красиво.Однако он плохо поддерживает символы CJK, поэтому для максимальной поддержки я подумал об использовании Noto Sans CJK в качестве резервной копии.Хотя я мог бы использовать Noto Sans и для латинских символов, мне не очень нравятся их латинские символы.

Хотя это кажется тривиальным вопросом, я не могу понять, как это сделать.Даже если вы не можете ответить, я ценю указатели.

TL; DR:

Моя проблема

Я не могу отображать китайские, японские или корейские символы с помощью DejaVu SansMono

Мое решение

Использование Noto Sans CJK

Проблема с моим решением

Noto Sans уродлива с латыни и не поддерживает арабский

Мой вопрос

Как мне сообщить JComponent, что если он не может найти символ в Font One (DejaVu), он должен вместо этого использовать Font Two (Noto)?

1 Ответ

0 голосов
/ 28 сентября 2018

Один из способов - проверить шрифт на возможность отображения соответствующих символов при создании компонентов (и настройке текста).

Это может быть достигнуто с помощью таких методов, как Font.canDisplayUpTo(String).

EG

enter image description here

import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.util.*;

public class FallbackFont {

    private JComponent ui = null;
    private final String[] fontFamilies = GraphicsEnvironment.
            getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
    String[] examplesTexts = {
        "The quick brown fox jumps over the lazy dog.", // English
        "\u6253\u5370\u8FC7\u671F\u8BC1\u4E66\u8BB0\u5F55", // Chinese
        "\u0627\u0644\u0633\u0644\u0627\u0645 "
        + "\u0639\u0644\u064A\u0643\u0645", // Arabic
        new String(Character.toChars(128176))
    };
    String[] preferredFonts = {
        "DejaVu Sans Mono",
        "Microsoft JhengHei",
        "Noto Sans CJK TC Black", // has strange display problem here .. 
    };

    FallbackFont() {
        initUI();
    }

    private HashMap getCompatibleFonts(String text) {
        HashMap cF = new HashMap<>();
        for (String font : fontFamilies) {
            Font f = new Font(font, Font.PLAIN, 1);
            if (f.canDisplayUpTo(text) < 0) {
                cF.put(font, f);
            }
        }
        return cF;
    }

    private Font getPreferredFontForText(String text) {
        HashMap compatibleFonts = getCompatibleFonts(text);
        for (String preferredFont : preferredFonts) {
            Font font = (Font) compatibleFonts.get(preferredFont);
            if (font != null) {
                return font;
            }
        }
        Set keySet = compatibleFonts.keySet();
        String firstCompatibleFont = (String) keySet.iterator().next();
        return (Font) compatibleFonts.get(firstCompatibleFont);
    }

    public final void initUI() {
        if (ui != null) {
            return;
        }

        ui = new JPanel(new GridLayout(0, 2, 4, 4));
        ui.setBorder(new EmptyBorder(4, 4, 4, 4));
        for (String text : examplesTexts) {
            Font font = getPreferredFontForText(text);
            JButton b = new JButton(text);
            b.setFont(font.deriveFont(b.getFont().getSize2D()));
            ui.add(b);
            ui.add(new JLabel(font.getName()));
        }
    }

    public JComponent getUI() {
        return ui;
    }

    public static void main(String[] args) {
        Runnable r = () -> {
            FallbackFont o = new FallbackFont();

            JFrame f = new JFrame(o.getClass().getSimpleName());
            f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            f.setLocationByPlatform(true);

            f.setContentPane(o.getUI());
            f.pack();
            f.setMinimumSize(f.getSize());

            f.setVisible(true);
        };
        SwingUtilities.invokeLater(r);
    }
}
...