Package com.badlogic.gdx.tools.hiero

Source Code of com.badlogic.gdx.tools.hiero.Hiero4

/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/

package com.badlogic.gdx.tools.hiero;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FileDialog;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.HashSet;
import java.util.prefs.Preferences;

import javax.swing.BorderFactory;
import javax.swing.ButtonGroup;
import javax.swing.DefaultComboBoxModel;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.JWindow;
import javax.swing.KeyStroke;
import javax.swing.ScrollPaneConstants;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import org.lwjgl.opengl.GL11;

import com.badlogic.gdx.ApplicationListener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.backends.lwjgl.LwjglCanvas;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.TextureData;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.tools.hiero.unicodefont.UnicodeFont;
import com.badlogic.gdx.tools.hiero.unicodefont.effects.EffectUtil;

import de.matthiasmann.twlthemeeditor.fontgen.CharSet;
import de.matthiasmann.twlthemeeditor.fontgen.Effect;
import de.matthiasmann.twlthemeeditor.fontgen.FontData;
import de.matthiasmann.twlthemeeditor.fontgen.FontGenerator;
import de.matthiasmann.twlthemeeditor.fontgen.FontGenerator.ExportFormat;
import de.matthiasmann.twlthemeeditor.fontgen.FontGenerator.GeneratorMethod;
import de.matthiasmann.twlthemeeditor.fontgen.Padding;
import static org.lwjgl.opengl.GL11.*;

/** WIP, based on Matthias' TWL font renderer. Currently missing effects and saving hiero settings.<br>
* <br>
* A tool to visualize settings for {@link UnicodeFont} and to export BMFont files for use with {@link BitmapFont}.
* @author Nathan Sweet */
public class Hiero4 extends JFrame {
  static final String NEHE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n" //
    + "abcdefghijklmnopqrstuvwxyz\n1234567890\n" //
    + "\"!`?'.,;:()[]{}<>|/@\\^$-%+=#_&~*\u007F";

  Color renderingBackgroundColor = Color.BLACK;
  Preferences prefs;
  Renderer renderer;
  FontData fontData;
  FontGenerator fontGenerator;
  HashSet<Character> sampleChars = new HashSet(256);
  HashSet<Character> remainingSampleChars = new HashSet(256);

  JScrollPane appliedEffectsScroll;
  JPanel appliedEffectsPanel;
  JButton addEffectButton;
  JTextPane sampleTextPane;
  JSpinner padAdvanceXSpinner;
  JList effectsList;
  JPanel gamePanel;
  JTextField fontFileText;
  JRadioButton fontFileRadio;
  JRadioButton systemFontRadio;
  JSpinner padBottomSpinner;
  JSpinner padLeftSpinner;
  JSpinner padRightSpinner;
  JSpinner padTopSpinner;
  JList fontList;
  JSpinner fontSizeSpinner;
  DefaultComboBoxModel fontListModel;
  JLabel backgroundColorLabel;
  JButton browseButton;
  JSpinner padAdvanceYSpinner;
  JCheckBox italicCheckBox;
  JCheckBox boldCheckBox;
  JRadioButton vectorRadio;
  JRadioButton drawStringRadio;
  JRadioButton freetypeRadio;
  JComboBox glyphPageHeightCombo;
  JComboBox glyphPageWidthCombo;
  JPanel glyphCachePanel;
  JRadioButton glyphCacheRadio;
  JRadioButton sampleTextRadio;
  JButton sampleAsciiButton;
  JButton sampleNeheButton;
  DefaultComboBoxModel effectsListModel;
  JMenuItem openMenuItem;
  JMenuItem saveMenuItem;
  JMenuItem exitMenuItem;
  JMenuItem saveBMFontMenuItem;

  public Hiero4 () {
    super("Hiero v4.0 - Bitmap Font Tool");
    Splash splash = new Splash(this, "/splash.jpg", 2000);
    initialize();
    splash.close();

    gamePanel.add(new LwjglCanvas(renderer = new Renderer()).getCanvas());

    prefs = Preferences.userNodeForPackage(Hiero4.class);
    java.awt.Color backgroundColor = EffectUtil.fromString(prefs.get("background", "000000"));
    backgroundColorLabel.setIcon(getColorIcon(backgroundColor));
    renderingBackgroundColor = new Color(backgroundColor.getRed() / 255f, backgroundColor.getGreen() / 255f,
      backgroundColor.getBlue() / 255f, 1);

    boolean useFontList = getFontFile(Font.decode("Arial")) != null;
    fontList.setEnabled(useFontList);
    systemFontRadio.setEnabled(useFontList);
    fontFileRadio.setSelected(!useFontList);
    fontFileText.setText(prefs.get("font.file", ""));

    setVisible(true);
  }

  void initialize () {
    initializeComponents();
    initializeMenus();
    initializeEvents();

    setSize(800, 600);
    setLocationRelativeTo(null);
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

    sampleNeheButton.doClick();
  }

  void changeFont () {
    if (renderer.batch == null) return;

    String path;
    if (systemFontRadio.isSelected()) {
      path = getFontFile(Font.decode((String)fontList.getSelectedValue()));
    } else {
      path = fontFileText.getText();
    }
    if (path == null) {
      renderer.font = null;
      return;
    }

    int fontSize = ((Integer)fontSizeSpinner.getValue()).intValue();

    try {
      fontData = new FontData(new File(path), fontSize);
    } catch (IOException ex) {
      ex.printStackTrace();
      renderer.font = null;
      return;
    }

    sampleChars.clear();
    updateFont(true);
  }

  void updateFont (boolean force) {
    if (fontData == null || renderer.batch == null) return;

    final String text = sampleTextPane.getText();

    if (!force) {
      // Don't regenerate font unless the text has new characters or has removed characters.
      boolean newCharFound = false;
      remainingSampleChars.clear();
      remainingSampleChars.addAll(sampleChars);
      for (int i = text.length() - 1; i >= 0; i--) {
        Character ch = text.charAt(i);
        if (sampleChars.add(ch)) newCharFound = true;
        remainingSampleChars.remove(ch);
      }
      if (!newCharFound && remainingSampleChars.isEmpty()) return;
    }
    sampleChars.clear();
    for (int i = text.length() - 1; i >= 0; i--)
      sampleChars.add(text.charAt(i));

    int fontSize = ((Integer)fontSizeSpinner.getValue()).intValue();

    int style = Font.PLAIN;
    if (boldCheckBox.isSelected()) {
      style = Font.BOLD;
      if (italicCheckBox.isSelected()) style |= Font.ITALIC;
    } else if (italicCheckBox.isSelected()) //
      style = Font.ITALIC;
    fontData = fontData.deriveFont(fontSize, style);

    int sampleFontSize = sampleTextPane.getFont().getSize();
    if (sampleFontSize < 14) sampleFontSize = 14;
    sampleTextPane.setFont(fontData.getJavaFont().deriveFont((float)sampleFontSize));

    final Padding padding = new Padding((Integer)padTopSpinner.getValue(), (Integer)padLeftSpinner.getValue(),
      (Integer)padBottomSpinner.getValue(), (Integer)padRightSpinner.getValue(), (Integer)padAdvanceXSpinner.getValue());
    final int width = (Integer)glyphPageWidthCombo.getSelectedItem();
    final int height = (Integer)glyphPageHeightCombo.getSelectedItem();

    final GeneratorMethod method;
    if (vectorRadio.isSelected())
      method = GeneratorMethod.AWT_VECTOR;
    else if (drawStringRadio.isSelected())
      method = GeneratorMethod.AWT_DRAWSTRING;
    else
      method = GeneratorMethod.FREETYPE2;

    new Thread() {
      public void run () {
        fontGenerator = new FontGenerator(fontData, method);
        CharSet charset = new CharSet();
        charset.setManualCharacters(text);
        try {
          fontGenerator.generate(width, height, charset, padding, new Effect.Renderer[0], true);
          fontGenerator.write(new File("out"), ExportFormat.TEXT);
        } catch (IOException ex) {
          ex.printStackTrace();
        }
        EventQueue.invokeLater(new Runnable() {
          public void run () {
            final ByteBuffer buffer = ByteBuffer.allocateDirect(1024 * 1024 * 4);
            buffer.order(ByteOrder.LITTLE_ENDIAN);
            fontGenerator.getTextureData(buffer.asIntBuffer());
            TextureRegion glyphRegion = new TextureRegion(new Texture(new TextureData() {
              Pixmap pixmap;

              public int getWidth () {
                return width;
              }

              public int getHeight () {
                return height;
              }

              @Override
              public Pixmap consumePixmap () {
                this.pixmap = new Pixmap(width, height, Format.RGBA8888);
                pixmap.getPixels().put(buffer);
                pixmap.getPixels().rewind();
                return pixmap;
              }

              @Override
              public boolean disposePixmap () {
                return true;
              }

              @Override
              public Format getFormat () {
                return pixmap.getFormat();
              }

              @Override
              public boolean useMipMaps () {
                return false;
              }

              @Override
              public boolean isManaged () {
                return true;
              }

              @Override
              public TextureDataType getType () {
                return TextureDataType.Pixmap;
              }

              @Override
              public void consumeCustomData (int target) {
              }

              @Override
              public boolean isPrepared () {
                return true;
              }

              @Override
              public void prepare () {
              }
            }));
            renderer.font = new BitmapFont(Gdx.files.absolute("out"), glyphRegion, false);
          }
        });
      }
    }.start();
  }

  private void initializeEvents () {
    class FontChangeListener implements ChangeListener, ActionListener {
      public void stateChanged (ChangeEvent evt) {
        changeFont();
      }

      public void actionPerformed (ActionEvent evt) {
        changeFont();
      }
    }
    FontChangeListener change = new FontChangeListener();
    fontFileRadio.addActionListener(change);
    systemFontRadio.addActionListener(change);
    fontList.addListSelectionListener(new ListSelectionListener() {
      public void valueChanged (ListSelectionEvent evt) {
        if (evt.getValueIsAdjusting()) return;
        prefs.put("system.font", (String)fontList.getSelectedValue());
        changeFont();
      }
    });

    class FontUpdateListener implements ChangeListener, ActionListener, DocumentListener {
      private final boolean force;

      public FontUpdateListener (boolean force) {
        this.force = force;
      }

      public void stateChanged (ChangeEvent evt) {
        updateFont(force);
      }

      public void actionPerformed (ActionEvent evt) {
        updateFont(force);
      }

      public void removeUpdate (DocumentEvent evt) {
        updateFont(force);
      }

      public void insertUpdate (DocumentEvent evt) {
        updateFont(force);
      }

      public void changedUpdate (DocumentEvent evt) {
        updateFont(force);
      }

      public void addSpinners (JSpinner[] spinners) {
        // Swing sucks.
        for (int i = 0; i < spinners.length; i++) {
          final JSpinner spinner = spinners[i];
          spinner.addChangeListener(this);
          ((JSpinner.DefaultEditor)spinner.getEditor()).getTextField().addKeyListener(new KeyAdapter() {
            String lastText;

            public void keyReleased (KeyEvent evt) {
              JFormattedTextField textField = ((JSpinner.DefaultEditor)spinner.getEditor()).getTextField();
              String text = textField.getText();
              if (text.length() == 0) return;
              if (text.equals(lastText)) return;
              lastText = text;
              int caretPosition = textField.getCaretPosition();
              try {
                spinner.setValue(Integer.valueOf(text));
                textField.setCaretPosition(caretPosition);
              } catch (Throwable ignored) {
              }
            }
          });
        }
      }
    }
    FontUpdateListener update = new FontUpdateListener(true);
    FontUpdateListener updateText = new FontUpdateListener(false);
    update.addSpinners(new JSpinner[] {padTopSpinner, padRightSpinner, padBottomSpinner, padLeftSpinner, padAdvanceXSpinner,
      padAdvanceYSpinner});
    fontSizeSpinner.addChangeListener(update);
    glyphPageWidthCombo.addActionListener(update);
    glyphPageHeightCombo.addActionListener(update);
    boldCheckBox.addActionListener(update);
    italicCheckBox.addActionListener(update);
    vectorRadio.addActionListener(update);
    drawStringRadio.addActionListener(update);
    freetypeRadio.addActionListener(update);
    sampleTextPane.getDocument().addDocumentListener(updateText);

    sampleTextRadio.addActionListener(new ActionListener() {
      public void actionPerformed (ActionEvent evt) {
        glyphCachePanel.setVisible(false);
      }
    });
    glyphCacheRadio.addActionListener(new ActionListener() {
      public void actionPerformed (ActionEvent evt) {
        glyphCachePanel.setVisible(true);
      }
    });

    fontFileText.getDocument().addDocumentListener(new DocumentListener() {
      public void removeUpdate (DocumentEvent evt) {
        changed();
      }

      public void insertUpdate (DocumentEvent evt) {
        changed();
      }

      public void changedUpdate (DocumentEvent evt) {
        changed();
      }

      private void changed () {
        File file = new File(fontFileText.getText());
        if (fontList.isEnabled() && (!file.exists() || !file.isFile())) return;
        prefs.put("font.file", fontFileText.getText());
        updateFont(true);
      }
    });

    browseButton.addActionListener(new ActionListener() {
      public void actionPerformed (ActionEvent evt) {
        FileDialog dialog = new FileDialog(Hiero4.this, "Choose TrueType font file", FileDialog.LOAD);
        dialog.setLocationRelativeTo(null);
        dialog.setFile("*.ttf");
        dialog.setVisible(true);
        String fileName = dialog.getFile();
        if (fileName == null) return;
        fontFileText.setText(new File(dialog.getDirectory(), fileName).getAbsolutePath());
      }
    });

    backgroundColorLabel.addMouseListener(new MouseAdapter() {
      public void mouseClicked (MouseEvent evt) {
        java.awt.Color color = JColorChooser.showDialog(null, "Choose a background color",
          EffectUtil.fromString(prefs.get("background", "000000")));
        if (color == null) return;
        renderingBackgroundColor = new Color(color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, 1);
        backgroundColorLabel.setIcon(getColorIcon(color));
        prefs.put("background", EffectUtil.toString(color));
      }
    });

    saveBMFontMenuItem.addActionListener(new ActionListener() {
      public void actionPerformed (ActionEvent evt) {
        if (fontGenerator == null) return;
        FileDialog dialog = new FileDialog(Hiero4.this, "Save BMFont files", FileDialog.SAVE);
        dialog.setLocationRelativeTo(null);
        dialog.setFile("*.fnt");
        dialog.setVisible(true);
        String fileName = dialog.getFile();
        if (fileName == null) return;
        try {
          fontGenerator.write(new File(dialog.getDirectory(), fileName), ExportFormat.TEXT);
        } catch (IOException ex) {
          ex.printStackTrace();
        }
      }
    });

    exitMenuItem.addActionListener(new ActionListener() {
      public void actionPerformed (ActionEvent evt) {
        dispose();
      }
    });

    sampleNeheButton.addActionListener(new ActionListener() {
      public void actionPerformed (ActionEvent evt) {
        sampleTextPane.setText(NEHE);
      }
    });

    sampleAsciiButton.addActionListener(new ActionListener() {
      public void actionPerformed (ActionEvent evt) {
        StringBuilder buffer = new StringBuilder();
        buffer.append(NEHE);
        buffer.append('\n');
        int count = 0;
        for (int i = 33; i <= 255; i++) {
          if (buffer.indexOf(Character.toString((char)i)) != -1) continue;
          buffer.append((char)i);
          if (++count % 30 == 0) buffer.append('\n');
        }
        sampleTextPane.setText(buffer.toString());
      }
    });
  }

  private void initializeComponents () {
    getContentPane().setLayout(new GridBagLayout());
    JPanel leftSidePanel = new JPanel();
    leftSidePanel.setLayout(new GridBagLayout());
    getContentPane().add(
      leftSidePanel,
      new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0),
        0, 0));
    {
      JPanel fontPanel = new JPanel();
      leftSidePanel.add(fontPanel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,
        GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
      fontPanel.setLayout(new GridBagLayout());
      fontPanel.setBorder(BorderFactory.createTitledBorder("Font"));
      {
        fontSizeSpinner = new JSpinner(new SpinnerNumberModel(32, 0, 256, 1));
        fontPanel.add(fontSizeSpinner, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
          GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0));
        ((JSpinner.DefaultEditor)fontSizeSpinner.getEditor()).getTextField().setColumns(2);
      }
      {
        JScrollPane fontScroll = new JScrollPane();
        fontPanel.add(fontScroll, new GridBagConstraints(1, 1, 4, 1, 1.0, 1.0, GridBagConstraints.CENTER,
          GridBagConstraints.BOTH, new Insets(0, 0, 5, 5), 0, 0));
        {
          fontListModel = new DefaultComboBoxModel(GraphicsEnvironment.getLocalGraphicsEnvironment()
            .getAvailableFontFamilyNames());
          fontList = new JList();
          fontScroll.setViewportView(fontList);
          fontList.setModel(fontListModel);
          fontList.setVisibleRowCount(6);
          fontList.setSelectedIndex(0);
          fontScroll.setMinimumSize(new Dimension(220, fontList.getPreferredScrollableViewportSize().height));
        }
      }
      {
        systemFontRadio = new JRadioButton("System:", true);
        fontPanel.add(systemFontRadio, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTHEAST,
          GridBagConstraints.NONE, new Insets(0, 5, 0, 5), 0, 0));
        systemFontRadio.setMargin(new Insets(0, 0, 0, 0));
      }
      {
        fontFileRadio = new JRadioButton("File:");
        fontPanel.add(fontFileRadio, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, GridBagConstraints.EAST,
          GridBagConstraints.NONE, new Insets(0, 5, 5, 5), 0, 0));
        fontFileRadio.setMargin(new Insets(0, 0, 0, 0));
      }
      {
        fontFileText = new JTextField();
        fontPanel.add(fontFileText, new GridBagConstraints(1, 2, 3, 1, 1.0, 0.0, GridBagConstraints.CENTER,
          GridBagConstraints.HORIZONTAL, new Insets(0, 0, 5, 0), 0, 0));
      }
      {
        fontPanel.add(new JLabel("Size:"), new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, GridBagConstraints.EAST,
          GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0));
      }
      {
        boldCheckBox = new JCheckBox("Bold");
        fontPanel.add(boldCheckBox, new GridBagConstraints(2, 3, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,
          GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0));
      }
      {
        italicCheckBox = new JCheckBox("Italic");
        fontPanel.add(italicCheckBox, new GridBagConstraints(3, 3, 1, 1, 1.0, 0.0, GridBagConstraints.WEST,
          GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0));
      }
      {
        browseButton = new JButton("...");
        fontPanel.add(browseButton, new GridBagConstraints(4, 2, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,
          GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0));
        browseButton.setMargin(new Insets(0, 0, 0, 0));
      }
      {
        fontPanel.add(new JLabel("Rendering:"), new GridBagConstraints(0, 4, 1, 1, 0.0, 0.0, GridBagConstraints.EAST,
          GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0));
      }
      {
        vectorRadio = new JRadioButton("Vector");
        fontPanel.add(vectorRadio, new GridBagConstraints(1, 4, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,
          GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0));
        if (!FontGenerator.GeneratorMethod.FREETYPE2.isAvailable) vectorRadio.setSelected(true);
      }
      {
        drawStringRadio = new JRadioButton("DrawString");
        fontPanel.add(drawStringRadio, new GridBagConstraints(2, 4, 1, 1, 1.0, 0.0, GridBagConstraints.WEST,
          GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0));
      }
      {
        freetypeRadio = new JRadioButton("FreeType");
        fontPanel.add(freetypeRadio, new GridBagConstraints(3, 4, 1, 1, 1.0, 0.0, GridBagConstraints.WEST,
          GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0));
        if (FontGenerator.GeneratorMethod.FREETYPE2.isAvailable)
          freetypeRadio.setSelected(true);
        else
          freetypeRadio.setEnabled(false);
      }
      ButtonGroup buttonGroup = new ButtonGroup();
      buttonGroup.add(systemFontRadio);
      buttonGroup.add(fontFileRadio);
      buttonGroup = new ButtonGroup();
      buttonGroup.add(vectorRadio);
      buttonGroup.add(drawStringRadio);
      buttonGroup.add(freetypeRadio);
    }
    {
      JPanel samplePanel = new JPanel();
      leftSidePanel.add(samplePanel, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.CENTER,
        GridBagConstraints.BOTH, new Insets(5, 0, 5, 5), 0, 0));
      samplePanel.setLayout(new GridBagLayout());
      samplePanel.setBorder(BorderFactory.createTitledBorder("Sample Text"));
      {
        JScrollPane textScroll = new JScrollPane();
        samplePanel.add(textScroll, new GridBagConstraints(0, 0, 3, 1, 1.0, 1.0, GridBagConstraints.CENTER,
          GridBagConstraints.BOTH, new Insets(0, 5, 5, 5), 0, 0));
        {
          sampleTextPane = new JTextPane();
          textScroll.setViewportView(sampleTextPane);
        }
      }
      {
        sampleNeheButton = new JButton();
        sampleNeheButton.setText("NEHE");
        samplePanel.add(sampleNeheButton, new GridBagConstraints(2, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,
          GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0));
      }
      {
        sampleAsciiButton = new JButton();
        sampleAsciiButton.setText("ASCII");
        samplePanel.add(sampleAsciiButton, new GridBagConstraints(1, 1, 1, 1, 1.0, 0.0, GridBagConstraints.EAST,
          GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0));
      }
    }
    {
      JPanel renderingPanel = new JPanel();
      leftSidePanel.add(renderingPanel, new GridBagConstraints(0, 1, 2, 1, 1.0, 1.0, GridBagConstraints.CENTER,
        GridBagConstraints.BOTH, new Insets(0, 5, 5, 5), 0, 0));
      renderingPanel.setBorder(BorderFactory.createTitledBorder("Rendering"));
      renderingPanel.setLayout(new GridBagLayout());
      {
        JPanel wrapperPanel = new JPanel();
        renderingPanel.add(wrapperPanel, new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER,
          GridBagConstraints.BOTH, new Insets(0, 5, 5, 5), 0, 0));
        wrapperPanel.setLayout(new BorderLayout());
        wrapperPanel.setBackground(java.awt.Color.white);
        {
          gamePanel = new JPanel();
          wrapperPanel.add(gamePanel);
          gamePanel.setLayout(new BorderLayout());
          gamePanel.setBackground(java.awt.Color.white);
        }
      }
      {
        glyphCachePanel = new JPanel() {
          private int maxWidth;

          public Dimension getPreferredSize () {
            // Keep glyphCachePanel width from ever going down so the CanvasGameContainer doesn't change sizes and flicker.
            Dimension size = super.getPreferredSize();
            maxWidth = Math.max(maxWidth, size.width);
            size.width = maxWidth;
            return size;
          }
        };
        glyphCachePanel.setVisible(false);
        renderingPanel.add(glyphCachePanel, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.NORTH,
          GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
        glyphCachePanel.setLayout(new GridBagLayout());
        {
          glyphCachePanel.add(new JLabel("Page width:"), new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0,
            GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 5, 5, 5), 0, 0));
        }
        {
          glyphCachePanel.add(new JLabel("Page height:"), new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0,
            GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(0, 5, 5, 5), 0, 0));
        }
        {
          glyphPageWidthCombo = new JComboBox(new DefaultComboBoxModel(new Integer[] {new Integer(64), new Integer(128),
            new Integer(256), new Integer(512), new Integer(1024), new Integer(2048)}));
          glyphCachePanel.add(glyphPageWidthCombo, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
            GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0));
          glyphPageWidthCombo.setSelectedIndex(4);
        }
        {
          glyphPageHeightCombo = new JComboBox(new DefaultComboBoxModel(new Integer[] {new Integer(64), new Integer(128),
            new Integer(256), new Integer(512), new Integer(1024), new Integer(2048)}));
          glyphCachePanel.add(glyphPageHeightCombo, new GridBagConstraints(1, 2, 1, 1, 0.0, 0.0, GridBagConstraints.WEST,
            GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0));
          glyphPageHeightCombo.setSelectedIndex(4);
        }
      }
      {
        JPanel radioButtonsPanel = new JPanel();
        renderingPanel.add(radioButtonsPanel, new GridBagConstraints(0, 0, 2, 1, 0.0, 0.0, GridBagConstraints.CENTER,
          GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
        radioButtonsPanel.setLayout(new GridBagLayout());
        {
          sampleTextRadio = new JRadioButton("Sample text");
          radioButtonsPanel.add(sampleTextRadio, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,
            GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0));
          sampleTextRadio.setSelected(true);
        }
        {
          glyphCacheRadio = new JRadioButton("Glyph cache");
          radioButtonsPanel.add(glyphCacheRadio, new GridBagConstraints(3, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,
            GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0));
        }
        {
          radioButtonsPanel.add(new JLabel("Background:"), new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0,
            GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(0, 5, 5, 5), 0, 0));
        }
        {
          backgroundColorLabel = new JLabel();
          radioButtonsPanel.add(backgroundColorLabel, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.WEST,
            GridBagConstraints.NONE, new Insets(0, 0, 5, 5), 0, 0));
        }
        ButtonGroup buttonGroup = new ButtonGroup();
        buttonGroup.add(glyphCacheRadio);
        buttonGroup.add(sampleTextRadio);
      }
    }
    JPanel rightSidePanel = new JPanel();
    rightSidePanel.setLayout(new GridBagLayout());
    getContentPane().add(
      rightSidePanel,
      new GridBagConstraints(1, 0, 1, 2, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0),
        0, 0));
    {
      JPanel paddingPanel = new JPanel();
      paddingPanel.setLayout(new GridBagLayout());
      rightSidePanel.add(paddingPanel, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,
        GridBagConstraints.BOTH, new Insets(0, 0, 5, 5), 0, 0));
      paddingPanel.setBorder(BorderFactory.createTitledBorder("Padding"));
      {
        padTopSpinner = new JSpinner();
        paddingPanel.add(padTopSpinner, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,
          GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
        ((JSpinner.DefaultEditor)padTopSpinner.getEditor()).getTextField().setColumns(2);
      }
      {
        padRightSpinner = new JSpinner();
        paddingPanel.add(padRightSpinner, new GridBagConstraints(2, 2, 1, 1, 1.0, 0.0, GridBagConstraints.WEST,
          GridBagConstraints.NONE, new Insets(0, 0, 0, 5), 0, 0));
        ((JSpinner.DefaultEditor)padRightSpinner.getEditor()).getTextField().setColumns(2);
      }
      {
        padLeftSpinner = new JSpinner();
        paddingPanel.add(padLeftSpinner, new GridBagConstraints(0, 2, 1, 1, 1.0, 0.0, GridBagConstraints.EAST,
          GridBagConstraints.NONE, new Insets(0, 5, 0, 0), 0, 0));
        ((JSpinner.DefaultEditor)padLeftSpinner.getEditor()).getTextField().setColumns(2);
      }
      {
        padBottomSpinner = new JSpinner();
        paddingPanel.add(padBottomSpinner, new GridBagConstraints(1, 3, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER,
          GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
        ((JSpinner.DefaultEditor)padBottomSpinner.getEditor()).getTextField().setColumns(2);
      }
      {
        JPanel advancePanel = new JPanel();
        FlowLayout advancePanelLayout = new FlowLayout();
        advancePanel.setLayout(advancePanelLayout);
        paddingPanel.add(advancePanel, new GridBagConstraints(0, 4, 3, 1, 1.0, 0.0, GridBagConstraints.CENTER,
          GridBagConstraints.NONE, new Insets(0, 0, 0, 0), 0, 0));
        {
          advancePanel.add(new JLabel("X:"));
        }
        {
          padAdvanceXSpinner = new JSpinner();
          advancePanel.add(padAdvanceXSpinner);
          ((JSpinner.DefaultEditor)padAdvanceXSpinner.getEditor()).getTextField().setColumns(2);
        }
        {
          advancePanel.add(new JLabel("Y:"));
        }
        {
          padAdvanceYSpinner = new JSpinner();
          advancePanel.add(padAdvanceYSpinner);
          ((JSpinner.DefaultEditor)padAdvanceYSpinner.getEditor()).getTextField().setColumns(2);
        }
      }
    }
    {
      JPanel effectsPanel = new JPanel();
      effectsPanel.setLayout(new GridBagLayout());
      rightSidePanel.add(effectsPanel, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.CENTER,
        GridBagConstraints.BOTH, new Insets(5, 0, 5, 5), 0, 0));
      effectsPanel.setBorder(BorderFactory.createTitledBorder("Effects"));
      effectsPanel.setMinimumSize(new Dimension(210, 1));
      {
        JScrollPane effectsScroll = new JScrollPane();
        effectsPanel.add(effectsScroll, new GridBagConstraints(1, 0, 1, 1, 1.0, 0.0, GridBagConstraints.NORTH,
          GridBagConstraints.HORIZONTAL, new Insets(0, 5, 5, 5), 0, 0));
        {
          effectsListModel = new DefaultComboBoxModel();
          effectsList = new JList();
          effectsScroll.setViewportView(effectsList);
          effectsList.setModel(effectsListModel);
          effectsList.setVisibleRowCount(6);
          effectsScroll.setMinimumSize(effectsList.getPreferredScrollableViewportSize());
        }
      }
      {
        addEffectButton = new JButton("Add");
        effectsPanel.add(addEffectButton, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.EAST,
          GridBagConstraints.NONE, new Insets(0, 5, 6, 5), 0, 0));
        addEffectButton.setEnabled(false);
      }
      {
        appliedEffectsScroll = new JScrollPane();
        effectsPanel.add(appliedEffectsScroll, new GridBagConstraints(1, 3, 1, 1, 1.0, 1.0, GridBagConstraints.NORTH,
          GridBagConstraints.BOTH, new Insets(0, 0, 5, 0), 0, 0));
        appliedEffectsScroll.setBorder(new EmptyBorder(0, 0, 0, 0));
        appliedEffectsScroll.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
        {
          JPanel panel = new JPanel();
          panel.setLayout(new GridBagLayout());
          appliedEffectsScroll.setViewportView(panel);
          {
            appliedEffectsPanel = new JPanel();
            appliedEffectsPanel.setLayout(new GridBagLayout());
            panel.add(appliedEffectsPanel, new GridBagConstraints(0, 0, 1, 1, 1.0, 1.0, GridBagConstraints.NORTH,
              GridBagConstraints.HORIZONTAL, new Insets(0, 0, 0, 0), 0, 0));
            appliedEffectsPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, java.awt.Color.black));
          }
        }
      }
    }
  }

  private void initializeMenus () {
    {
      JMenuBar menuBar = new JMenuBar();
      setJMenuBar(menuBar);
      {
        JMenu fileMenu = new JMenu();
        menuBar.add(fileMenu);
        fileMenu.setText("File");
        fileMenu.setMnemonic(KeyEvent.VK_F);
        {
          openMenuItem = new JMenuItem("Open Hiero settings file...");
          openMenuItem.setMnemonic(KeyEvent.VK_O);
          openMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, KeyEvent.CTRL_MASK));
          fileMenu.add(openMenuItem);
        }
        {
          saveMenuItem = new JMenuItem("Save Hiero settings file...");
          saveMenuItem.setMnemonic(KeyEvent.VK_S);
          saveMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, KeyEvent.CTRL_MASK));
          fileMenu.add(saveMenuItem);
        }
        fileMenu.addSeparator();
        {
          saveBMFontMenuItem = new JMenuItem("Save BMFont files (text)...");
          saveBMFontMenuItem.setMnemonic(KeyEvent.VK_B);
          saveBMFontMenuItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_B, KeyEvent.CTRL_MASK));
          fileMenu.add(saveBMFontMenuItem);
        }
        fileMenu.addSeparator();
        {
          exitMenuItem = new JMenuItem("Exit");
          exitMenuItem.setMnemonic(KeyEvent.VK_X);
          fileMenu.add(exitMenuItem);
        }
      }
    }
  }

  static Icon getColorIcon (java.awt.Color color) {
    BufferedImage image = new BufferedImage(32, 16, BufferedImage.TYPE_INT_RGB);
    java.awt.Graphics g = image.getGraphics();
    g.setColor(color);
    g.fillRect(1, 1, 30, 14);
    g.setColor(java.awt.Color.black);
    g.drawRect(0, 0, 31, 15);
    return new ImageIcon(image);
  }

  static private class Splash extends JWindow {
    final int minMillis;
    final long startTime;

    public Splash (Frame frame, String imageFile, int minMillis) {
      super(frame);
      this.minMillis = minMillis;
      getContentPane().add(new JLabel(new ImageIcon(Splash.class.getResource(imageFile))), BorderLayout.CENTER);
      pack();
      setLocationRelativeTo(null);
      setVisible(true);
      startTime = System.currentTimeMillis();
    }

    public void close () {
      final long endTime = System.currentTimeMillis();
      new Thread(new Runnable() {
        public void run () {
          if (endTime - startTime < minMillis) {
            addMouseListener(new MouseAdapter() {
              public void mousePressed (MouseEvent evt) {
                dispose();
              }
            });
            try {
              Thread.sleep(minMillis - (endTime - startTime));
            } catch (InterruptedException ignored) {
            }
          }
          EventQueue.invokeLater(new Runnable() {
            public void run () {
              dispose();
            }
          });
        }
      }, "Splash").start();
    }
  }

  class Renderer implements ApplicationListener {
    SpriteBatch batch;
    BitmapFont font;

    @Override
    public void create () {
      batch = new SpriteBatch();
      changeFont();
    }

    @Override
    public void resize (int width, int height) {
      GL11.glViewport(0, 0, width, height);
      batch.getProjectionMatrix().setToOrtho(0, width, 0, height, 0, 1);
    }

    @Override
    public void render () {
      int viewWidth = Gdx.graphics.getWidth();
      int viewHeight = Gdx.graphics.getHeight();

      BitmapFont font = this.font;
      if (font == null) {
        glClearColor(0, 0, 0, 0);
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
        return;
      }

      if (sampleTextRadio.isSelected()) {
        glClearColor(renderingBackgroundColor.r, renderingBackgroundColor.g, renderingBackgroundColor.b,
          renderingBackgroundColor.a);
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);

        batch.begin();
        font.drawWrapped(batch, sampleTextPane.getText(), 0, viewHeight, viewWidth);
        batch.end();
      } else {
        glClearColor(1, 1, 1, 1);
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);

        TextureRegion region = font.getRegion();
        float y = viewHeight - region.getRegionHeight();

        glColor4f(renderingBackgroundColor.r, renderingBackgroundColor.g, renderingBackgroundColor.b, 0);
        glBegin(GL_QUADS);
        glVertex3f(0, y + region.getRegionHeight(), 0);
        glVertex3f(0, y, 0);
        glVertex3f(region.getRegionWidth(), y, 0);
        glVertex3f(region.getRegionWidth(), y + region.getRegionHeight(), 0);
        glEnd();

        batch.begin();
        batch.draw(region, 0, y);
        batch.end();
      }
    }

    @Override
    public void pause () {
    }

    @Override
    public void resume () {
    }

    @Override
    public void dispose () {
    }
  }

  static public String getFontFile (Font font) {
    try {
      font.getFamily(); // Causes font2DHandle to be set.
      Field font2DHandleField = Font.class.getDeclaredField("font2DHandle");
      font2DHandleField.setAccessible(true);
      Object font2DHandle = font2DHandleField.get(font);
      Field font2DField = font2DHandle.getClass().getDeclaredField("font2D");
      Object font2D = font2DField.get(font2DHandle);
      Field platNameField = Class.forName("sun.font.PhysicalFont").getDeclaredField("platName");
      platNameField.setAccessible(true);
      return (String)platNameField.get(font2D);
    } catch (Exception ex) {
      return null;
    }
  }

  static public void main (String[] args) throws Exception {
    LookAndFeelInfo[] lookAndFeels = UIManager.getInstalledLookAndFeels();
    for (int i = 0, n = lookAndFeels.length; i < n; i++) {
      if ("Nimbus".equals(lookAndFeels[i].getName())) {
        try {
          UIManager.setLookAndFeel(lookAndFeels[i].getClassName());
        } catch (Throwable ignored) {
        }
        break;
      }
    }
    SwingUtilities.invokeLater(new Runnable() {
      @Override
      public void run () {
        new Hiero4();
      }
    });
  }
}
TOP

Related Classes of com.badlogic.gdx.tools.hiero.Hiero4

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.