Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
330 views
in Technique[技术] by (71.8m points)

java - Character display/search for Unicode characters

While answering another question about these parts, I became curious about the glyphs that might be obtained from the Unicode characters as displayed by the available fonts on the system.

Of course there are 65,536 Unicode chars, and over 250 fonts on a typical machine! Leaves one wondering where to start. What would be wonderful is an app. that allows us to browse tables of the code points of Unicode as displayed in ..any font selected in a list. It would be nice to also have:

  • A spinner that allows us to jump to any code point of interest.
  • The names of the less obscure Unicodes in a list, with a text search editable combo.
  • Details on a particular selected Unicode point, including:
    • A big display of the character or glyph, so we can eyeball it.
    • a list of fonts that can display it.
    • The attributes of the code point.

Does such an app. exist?

It might look, well ..something like this!

Unicode Glyph Browser

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Sure. Give this a run.

import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.*;
import javax.swing.table.*;
import javax.swing.plaf.basic.BasicComboBoxEditor;
import javax.swing.text.Document;
import java.util.*;
import java.util.logging.*;

public class UnicodeExplorer {

    public static final int codePointColumnWidth = 16;
    public static final int numberUnicodes = 256 * 256;
    private final ArrayList<Font> fontList = new ArrayList<Font>();
    private final SpinnerNumberModel startPage = new SpinnerNumberModel(
            0, 0, numberUnicodes, 1);
    private Font[] fontArray;
    private JList<Font> fonts = new JList<Font>(fontArray);
    private final FontTableCellRenderer fontTableCellRenderer =
            new FontTableCellRenderer();
    private final JTable codePointTable = new JTable(new CodePointTableModel(
            numberUnicodes / codePointColumnWidth, codePointColumnWidth));

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                // the GUI as seen by the user (without frame)
                JPanel gui = new JPanel(new BorderLayout());
                gui.setBorder(new EmptyBorder(2, 3, 2, 3));

                UnicodeExplorer ue = new UnicodeExplorer();
                ue.initGui(gui);

                JFrame f = new JFrame("UGlys - Unicode Glyphs");
                f.add(gui);
                // Ensures JVM closes after frame(s) closed and
                // all non-daemon threads are finished
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                // See http://stackoverflow.com/a/7143398/418556 for demo.
                f.setLocationByPlatform(true);

                ue.setCharacterSpinner(new Integer(65));
                f.pack();
                f.setMinimumSize(f.getSize());

                // should be done last, to avoid flickering, moving,
                // resizing artifacts.
                f.setVisible(true);
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency
        SwingUtilities.invokeLater(r);
    }

    public void handleCodePointTableSelection(ListSelectionEvent e) {
        if (!e.getValueIsAdjusting()) {
            int row = codePointTable.getSelectedRow();
            int col = codePointTable.getSelectedColumn();
            int codePoint = (row * codePointColumnWidth) + col;
            setCodePointDetailView(codePoint);
        }
    }
    JPanel characterPanel = null;
    JList<Font> supportedFonts = new JList<Font>();
    JLabel bigCharacter = new JLabel();
    JLabel characterDetails = new JLabel();

    public void setFontsForThisCodePoint(int codePoint) {
        DefaultListModel<Font> dlm = new DefaultListModel<Font>();
        for (Font font : fontArray) {
            if (font.canDisplay(codePoint)) {
                dlm.addElement(font);
            }
        }
        supportedFonts.setModel(dlm);
        supportedFonts.setVisibleRowCount(5);
    }

    public void setCodePointDetailView(int codePoint) {
        String s = UnicodeUtil.getCodePointString(codePoint);
        bigCharacter.setText(s);

        StringBuilder sb = new StringBuilder("<html><body><table>");
        sb.append(getTableRow("Character", s));
        sb.append(getTableRow("Name", "" + Character.getName(codePoint)));
        sb.append(getTableRow("Code Point", "" + codePoint));
        sb.append(getTableRow(
                "Is Defined", "" + Character.isDefined(codePoint)));
        sb.append(getTableRow(
                "Is BMP", "" + Character.isBmpCodePoint(codePoint)));
        sb.append(getTableRow(
                "Is ISO Control", "" + Character.isISOControl(codePoint)));
        sb.append(getTableRow(
                "Is Mirrored", "" + Character.isMirrored(codePoint)));

        sb.append(getTableRow(
                "Is Digit", "" + Character.isDigit(codePoint)));
        sb.append(getTableRow(
                "Is Letter", "" + Character.isLetter(codePoint)));
        sb.append(getTableRow(
                "Is Alphabetic", "" + Character.isAlphabetic(codePoint)));
        sb.append(getTableRow(
                "Is Ideographic", "" + Character.isIdeographic(codePoint)));

        sb.append(getTableRow(
                "Is Space Character", "" + Character.isSpaceChar(codePoint)));
        sb.append(getTableRow(
                "Is White Space", "" + Character.isWhitespace(codePoint)));

        sb.append(getTableRow(
                "Is Lower Case", "" + Character.isLowerCase(codePoint)));
        sb.append(getTableRow(
                "Is Title Case", "" + Character.isTitleCase(codePoint)));
        sb.append(getTableRow(
                "Is Upper Case", "" + Character.isUpperCase(codePoint)));


        sb.append("</table></body></html>");
        characterDetails.setText(sb.toString());

        setFontsForThisCodePoint(codePoint);
    }

    public String getTableRow(String key, String value) {
        return "<tr><th>" + key + "</th><td>" + value + "</td></tr>";
    }

    public Component getCharacterPanel() {
        if (characterPanel == null) {
            characterPanel = new JPanel(new BorderLayout(5, 5));

            JPanel characterAndFonts = new JPanel(new BorderLayout(3, 3));
            characterAndFonts.add(bigCharacter, BorderLayout.PAGE_START);
            characterAndFonts.add(
                    new JScrollPane(supportedFonts), BorderLayout.CENTER);

            JSplitPane sp = new JSplitPane(
                    JSplitPane.HORIZONTAL_SPLIT,
                    characterAndFonts,
                    new JScrollPane(characterDetails));

            characterPanel.add(sp, BorderLayout.CENTER);
            supportedFonts.setCellRenderer(new FontCellRenderer());
            ListSelectionListener lsl = new ListSelectionListener() {

                @Override
                public void valueChanged(ListSelectionEvent e) {
                    selectFont(supportedFonts.getSelectedValue());
                }
            };
            supportedFonts.addListSelectionListener(lsl);
        }

        return characterPanel;
    }

    @SuppressWarnings("unchecked")
    public void initGui(Container c) {
        if (fontList.size() != 0) {
            return;
        }

        GraphicsEnvironment ge =
                GraphicsEnvironment.getLocalGraphicsEnvironment();
        String[] fontNameArray = ge.getAvailableFontFamilyNames();

        codePointTable.setDefaultRenderer(Object.class, fontTableCellRenderer);
        codePointTable.setRowSelectionAllowed(false);
        codePointTable.setCellSelectionEnabled(true);
        ListSelectionModel lsm = codePointTable.getSelectionModel();
        lsm.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        ListSelectionListener codePointListSelectionListener =
                new ListSelectionListener() {

                    @Override
                    public void valueChanged(ListSelectionEvent e) {
                        handleCodePointTableSelection(e);
                    }
                };
        codePointTable.getSelectionModel().
                addListSelectionListener(codePointListSelectionListener);

        TableColumnModelListener tcml = new TableColumnModelListener() {

            @Override
            public void columnAdded(TableColumnModelEvent e) {
            }

            @Override
            public void columnRemoved(TableColumnModelEvent e) {
            }

            @Override
            public void columnMoved(TableColumnModelEvent e) {
            }

            @Override
            public void columnMarginChanged(ChangeEvent e) {
            }

            @Override
            public void columnSelectionChanged(ListSelectionEvent e) {
                handleCodePointTableSelection(e);
            }
        };
        codePointTable.getColumnModel().addColumnModelListener(tcml);

        Logger.getLogger(
                UnicodeExplorer.class.getCanonicalName()).log(
                Level.INFO, "fontNameArray: " + fontNameArray.length);
        fontArray = new Font[fontNameArray.length];
        String[] logicalFonts = {
            Font.DIALOG, Font.DIALOG_INPUT,
            Font.MONOSPACED,
            Font.SANS_SERIF, Font.SERIF
        };
        for (int ii = 0; ii < logicalFonts.length; ii++) {
            Font f = new Font(logicalFonts[ii], Font.PLAIN, 1);
            fontArray[ii] = f;
            fontList.add(f);
        }
        int count = 0;
        for (int ii = 0; ii < fontNameArray.length; ii++) {
            Font f = new Font(fontNameArray[ii], Font.PLAIN, 1);
            if (!fontList.contains(f)) {
                fontArray[logicalFonts.length + count++] = f;
                fontList.add(f);
            }
        }

        Logger.getLogger(
                UnicodeExplorer.class.getCanonicalName()).log(
                Level.INFO, "fontArray: " + fontArray.length);

        fonts = new JList<Font>(fontArray);
        fonts.setCellRenderer(new FontCellRenderer());
        fonts.setVisibleRowCount(8);
        Dimension d = fonts.getPreferredSize();
        Dimension d1 = new Dimension(
                (int) (d.getWidth() / 3), (int) d.getHeight());
        fonts.setPreferredSize(d1);
        ListSelectionListener lsl = new ListSelectionListener() {

            @Override
            public void valueChanged(ListSelectionEvent e) {
                int index = fonts.getSelectedIndex();
                if (index < 0) {
                    index = 0;
                }
                Font f = fontArray[index].deriveFont(32f);
                fontTableCellRenderer.setDisplayFont(f);
                codePointTable.setRowHeight(f.getSize());
                bigCharacter.setFont(f.deriveFont(128f));
            }
        };
        fonts.addListSelectionListener(lsl);
        JScrollPane fontScroll = new JScrollPane(fonts);

        JPanel tools = new JPanel(new FlowLayout(FlowLayout.CENTER));

        JSpinner page = new JSpinner(startPage);
        tools.add(page);
        ChangeListener cl = new ChangeListener() {

            @Override
            public void stateChanged(ChangeEvent e) {
                int index = startPage.getNumber().intValue();
                selectCodePoint(index);
            }
        };
        page.addChangeListener(cl);

        JPanel codePointTableComponent = new JPanel(new BorderLayout(3, 3));
        codePointTableComponent.add(tools, BorderLayout.PAGE_START);

        JScrollPane codePointTableScroll = new JScrollPane(codePointTable);

        ArrayList<Integer> namedCodePoints = new ArrayList<Integer>();
        final FilteredCodePointListModel namedCodePointListModel =
                new FilteredCodePointListModel();
        ListCellRenderer namedCodePointListeCellRenderer =
                new CodePointListCellRenderer();

        String s;
        for (int ii = 0; ii < numberUnicodes; ii++) {
            s = Character.getName(ii);
            if (s != null) {
                s = s.trim().toLowerCase();
                if (!s.startsWith("null")
                        && !s.contains("private")
                        && !s.contains("cjk")
                        && !s.contains("surrogate")) {
                    namedCodePoints.add(ii);
                    namedCodePointListModel.addElement(new Integer(ii));
     

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...