//----------------------------------------------------------------------------// // // // S y m b o l R i p p e r // // // //----------------------------------------------------------------------------// // <editor-fold defaultstate="collapsed" desc="hdr"> // // Copyright © Hervé Bitteur and others 2000-2013. All rights reserved. // // This software is released under the GNU General Public License. // // Goto http://kenai.com/projects/audiveris to report bugs or suggestions. // //----------------------------------------------------------------------------// // </editor-fold> package omr.ui.symbol; import omr.ui.MainGui; import omr.ui.field.IntegerListSpinner; import omr.ui.field.LDoubleField; import omr.ui.field.LHexaSpinner; import omr.ui.field.LIntegerSpinner; import omr.ui.field.LSpinner; import omr.ui.field.SpinnerUtil; import omr.ui.util.Panel; import omr.ui.util.UILookAndFeel; import com.jgoodies.forms.builder.PanelBuilder; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsEnvironment; import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.font.FontRenderContext; import java.awt.font.GlyphVector; import java.awt.font.TextLayout; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSpinner; import javax.swing.SpinnerListModel; import javax.swing.SpinnerNumberModel; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; /** * Class {@code SymbolRipper} is a stand-alone utility to generate the * textual description of a symbol. Symbol appearance is "ripped" from a musical * font. * * @author Hervé Bitteur */ public class SymbolRipper { //~ Static fields/initializers --------------------------------------------- /** Usual logger utility */ private static final Logger logger = LoggerFactory.getLogger( SymbolRipper.class); static { // UI Look and Feel UILookAndFeel.setUI(null); } //~ Instance fields -------------------------------------------------------- /** Related frame */ private final JFrame frame; /** Image being built */ private BufferedImage image; //---------------// // paramListener // //---------------// private ChangeListener paramListener = new ChangeListener() { @Override public void stateChanged (ChangeEvent e) { JSpinner s = (JSpinner) e.getSource(); if (s == fontName.getSpinner()) { // New font name defineFont(); } else { if (s == fontBase) { // New font base changeCode(); } else if (s == fontSize.getSpinner()) { // New font size defineFont(); } else if (s == pointCode.getSpinner()) { // New point code changeCode(); } else if (s == hexaCode.getSpinner()) { // New hexa point code changeHexaCode(); } else if ((s == xOffset.getSpinner()) || (s == yOffset.getSpinner())) { // New drawing offset } else if ((s == width.getSpinner()) || (s == height.getSpinner())) { // New drawing dimension resizeDrawing(); } } // For all image = buildImage(); frame.repaint(); } }; // Panel where the icon is drawn private JPanel drawing; // String used to draw the symbol private String string; // Current music font private Font musicFont; // Font name private LSpinner fontName = new LSpinner( "Font", "Name of the font"); // Font base private IntegerListSpinner fontBase = new IntegerListSpinner(); // Font size private LIntegerSpinner fontSize = new LIntegerSpinner( "Size", "Font size in picas"); // Point code private LIntegerSpinner pointCode = new LIntegerSpinner( "Code", "Point code"); // Hexa representation private LHexaSpinner hexaCode = new LHexaSpinner( "Hexa", "Hexa value of the point code"); // X Offset private LIntegerSpinner xOffset = new LIntegerSpinner( "xOffset", "X offset"); // Width private LIntegerSpinner width = new LIntegerSpinner( "Width", "Drawing Width"); // Y Offset private LIntegerSpinner yOffset = new LIntegerSpinner( "yOffset", "Y offset"); // Height private LIntegerSpinner height = new LIntegerSpinner( "Height", "Drawing Height"); // x symbol private final String f = "%.3f"; private LDoubleField xSym = new LDoubleField(false, "xSym", "x symbol", f); // w symbol private LDoubleField wSym = new LDoubleField(false, "wSym", "w symbol", f); // y symbol private LDoubleField ySym = new LDoubleField(false, "ySym", "y symbol", f); // y symbol private LDoubleField hSym = new LDoubleField(false, "hSym", "h symbol", f); //~ Constructors ----------------------------------------------------------- /** * Creates a new SymbolRipper object. */ public SymbolRipper () { // Related frame frame = new JFrame(); frame.setTitle("Symbol Ripper"); // Actors drawing = new Drawing(); fontBase.setModel( new SpinnerListModel(new Integer[]{0, 0xf000, 0x1d100})); SpinnerUtil.setRightAlignment(fontBase); SpinnerUtil.fixIntegerList(fontBase); fontName.setModel( new SpinnerListModel( GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames())); // Initial values ///fontName.getSpinner().setValue("MusicalSymbols"); fontName.getSpinner() .setValue("Symbola"); fontBase.setValue(0); //0); fontSize.setValue(200); pointCode.setModel(new SpinnerNumberModel(0x1d100, 0, 0x1d1ff, 1)); width.setValue(400); height.setValue(500); xOffset.setValue(200); yOffset.setValue(300); changeCode(); defineFont(); // Listeners fontName.addChangeListener(paramListener); fontBase.addChangeListener(paramListener); fontSize.addChangeListener(paramListener); pointCode.addChangeListener(paramListener); hexaCode.addChangeListener(paramListener); xOffset.addChangeListener(paramListener); yOffset.addChangeListener(paramListener); width.addChangeListener(paramListener); height.addChangeListener(paramListener); // Global layout defineLayout(); // Frame behavior frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); MainGui.getInstance() .show(frame); // Actions image = buildImage(); frame.repaint(); } //~ Methods ---------------------------------------------------------------- //------// // main // //------// /** * Command line entry point, no arguments are used today. */ public static void main (String... args) { new SymbolRipper(); } //----------// // getFrame // //----------// /** * Report the related User Interface frame of this entity * * @return the window frame */ public JFrame getFrame () { return frame; } //------------// // buildImage // //------------// private BufferedImage buildImage () { BufferedImage img = (BufferedImage) drawing.createImage( width.getValue(), height.getValue()); Graphics2D g2 = img.createGraphics(); g2.setBackground(Color.white); g2.setColor(Color.white); g2.fillRect(0, 0, width.getValue(), height.getValue()); g2.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.setColor(Color.black); g2.setFont(musicFont); g2.drawString(string, xOffset.getValue(), yOffset.getValue()); FontRenderContext frc = g2.getFontRenderContext(); TextLayout layout = new TextLayout(string, musicFont, frc); Rectangle2D rect = layout.getBounds(); xSym.setValue(rect.getX()); ySym.setValue(rect.getY()); wSym.setValue(rect.getWidth()); hSym.setValue(rect.getHeight()); return img; } //------------// // changeCode // //------------// private void changeCode () { int base = (Integer) fontBase.getValue(); int code = (Integer) pointCode.getSpinner() .getValue(); string = new String(Character.toChars(base + code)); hexaCode.setValue(base + code); } //----------------// // changeHexaCode // //----------------// private void changeHexaCode () { int base = (Integer) fontBase.getValue(); int hexa = (Integer) hexaCode.getSpinner() .getValue(); string = new String(Character.toChars(hexa)); pointCode.setValue(hexa - base); } //------------// // defineFont // //------------// private void defineFont () { String name = (String) fontName.getSpinner() .getValue(); int val = fontSize.getValue(); musicFont = new Font(name, Font.PLAIN, val); } //--------------// // defineLayout // //--------------// private void defineLayout () { Container pane = frame.getContentPane(); pane.setLayout(new BorderLayout()); pane.add(getParamPanel(), BorderLayout.WEST); resizeDrawing(); JScrollPane scrollPane = new JScrollPane(drawing); pane.add(scrollPane, BorderLayout.CENTER); } //---------------// // getParamPanel // //---------------// private JPanel getParamPanel () { FormLayout layout = Panel.makeFormLayout( 13, 2, "right:", "35dlu", "45dlu"); PanelBuilder builder = new PanelBuilder(layout, new Panel()); builder.setDefaultDialogBorder(); CellConstraints cst = new CellConstraints(); int r = 1; // -------------------------------- builder.addSeparator("Font", cst.xyw(1, r, 7)); r += 2; // -------------------------------- builder.add(fontName.getLabel(), cst.xy(1, r)); builder.add(fontName.getSpinner(), cst.xyw(3, r, 5)); r += 2; // -------------------------------- builder.addLabel("Base", cst.xy(1, r)); builder.add(fontBase, cst.xy(3, r)); builder.add(fontSize.getLabel(), cst.xy(5, r)); builder.add(fontSize.getSpinner(), cst.xy(7, r)); r += 2; // -------------------------------- builder.add(pointCode.getLabel(), cst.xy(1, r)); builder.add(pointCode.getSpinner(), cst.xy(3, r)); builder.add(hexaCode.getLabel(), cst.xy(5, r)); builder.add(hexaCode.getSpinner(), cst.xy(7, r)); r += 2; // -------------------------------- builder.addSeparator("Drawing", cst.xyw(1, r, 7)); r += 2; // -------------------------------- builder.add(xOffset.getLabel(), cst.xy(1, r)); builder.add(xOffset.getSpinner(), cst.xy(3, r)); builder.add(width.getLabel(), cst.xy(5, r)); builder.add(width.getSpinner(), cst.xy(7, r)); r += 2; // -------------------------------- builder.add(yOffset.getLabel(), cst.xy(1, r)); builder.add(yOffset.getSpinner(), cst.xy(3, r)); builder.add(height.getLabel(), cst.xy(5, r)); builder.add(height.getSpinner(), cst.xy(7, r)); r += 2; // -------------------------------- builder.addSeparator("Symbol", cst.xyw(1, r, 7)); r += 2; // -------------------------------- builder.add(xSym.getLabel(), cst.xy(1, r)); builder.add(xSym.getField(), cst.xy(3, r)); builder.add(wSym.getLabel(), cst.xy(5, r)); builder.add(wSym.getField(), cst.xy(7, r)); r += 2; // -------------------------------- builder.add(ySym.getLabel(), cst.xy(1, r)); builder.add(ySym.getField(), cst.xy(3, r)); builder.add(hSym.getLabel(), cst.xy(5, r)); builder.add(hSym.getField(), cst.xy(7, r)); return builder.getPanel(); } //---------------// // resizeDrawing // //---------------// private void resizeDrawing () { drawing.setPreferredSize( new Dimension(width.getValue(), height.getValue())); drawing.revalidate(); } //~ Inner Classes ---------------------------------------------------------- //---------// // Drawing // //---------// private class Drawing extends Panel { //~ Methods ------------------------------------------------------------ @Override public void paintComponent (Graphics g) { // For background super.paintComponent(g); // Meant for visual check if (image != null) { Graphics2D g2 = (Graphics2D) g; g2.drawImage(image, 1, 1, this); g.setColor(Color.BLUE); g.drawLine( 0, yOffset.getValue(), width.getValue(), yOffset.getValue()); g.drawLine( xOffset.getValue(), 0, xOffset.getValue(), height.getValue()); g.setColor(Color.ORANGE); g.drawRect(0, 0, width.getValue(), height.getValue()); FontRenderContext frc = g2.getFontRenderContext(); GlyphVector glyphVector = musicFont.createGlyphVector( frc, string); Rectangle rect = glyphVector.getPixelBounds( frc, xOffset.getValue(), yOffset.getValue()); g.setColor(Color.RED); g2.draw(rect); // Debug TextLayout layout = new TextLayout(string, musicFont, frc); logger.debug( "getAdvance(): {} getVisibleAdvance(): {}", layout.getAdvance(), layout.getVisibleAdvance()); } } } }