/* Demo.java -- Shows examples of AWT components Copyright (C) 1998, 1999, 2002, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath examples. GNU Classpath is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Classpath is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Classpath; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package gnu.classpath.examples.awt; import gnu.java.awt.font.FontDelegate; import gnu.java.awt.font.GNUGlyphVector; import gnu.java.awt.font.opentype.OpenTypeFontFactory; import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GridLayout; import java.awt.Insets; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.font.FontRenderContext; import java.io.File; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.text.StringCharacterIterator; import javax.swing.BoxLayout; import javax.swing.JCheckBox; import javax.swing.JFileChooser; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.JTextField; import javax.swing.border.TitledBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; public class HintingDemo extends JFrame { FontDelegate font; GNUGlyphVector glyph; GlyphPreview glyphPreview; HintPanel hintPanel; StringViewer stringViewer; Chooser chooser; char character; Options options; boolean antiAlias; boolean showGrid; boolean showOriginal; boolean showHinted; int flags; class StringViewer extends JPanel implements ActionListener { JTextField input; GNUGlyphVector gv; Viewer viewer; StringViewer() { setLayout(new GridLayout(0, 1)); setBorder(new TitledBorder("Use this field to render complete strings")); input = new JTextField(); input.addActionListener(this); add(input); viewer = new Viewer(); add(viewer); } public void actionPerformed(ActionEvent event) { refresh(); } void refresh() { gv = (GNUGlyphVector) font.createGlyphVector(new Font("Dialog", 0, 12), new FontRenderContext(null, false, false), new StringCharacterIterator(input.getText())); viewer.repaint(); } class Viewer extends JPanel { protected void paintComponent(Graphics g) { if (gv != null && g instanceof Graphics2D) { Graphics2D g2d = (Graphics2D) g; if (antiAlias) { g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } else { g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); } g2d.clearRect(0, 0, getWidth(), getHeight()); g2d.setColor(Color.BLACK); Shape outline = gv.getOutline(0, 0, flags | FontDelegate.FLAG_FITTED); g2d.translate(20, Math.floor(outline.getBounds2D().getHeight()) + 2); g2d.fill(outline); } } } } class HintPanel extends JPanel { HintPanel() { setBorder(new TitledBorder("Detailed glyph view")); } protected void paintComponent(Graphics g) { if (glyph != null && g instanceof Graphics2D) { Graphics2D g2d = (Graphics2D) g.create(); Insets i = getInsets(); g2d.clearRect(i.left, i.top, getWidth() - i.left - i.right, getHeight() - i.top - i.bottom); if (showGrid) { g2d.setColor(Color.GRAY); for (int x = 20; x < getWidth(); x += 20) { g2d.drawLine(x, i.top, x, getHeight() - i.top - i.bottom); } for (int y = 20; y < getHeight(); y += 20) { g2d.drawLine(i.left, y, getWidth() - i.left - i.right, y); } } // g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, // RenderingHints.VALUE_ANTIALIAS_ON); g2d.translate(40, 300); g2d.scale(20., 20.); g2d.setStroke(new BasicStroke((float) (1/10.))); if (showOriginal) { g2d.setColor(Color.RED); g2d.draw(glyph.getOutline(0, 0, flags & ~FontDelegate.FLAG_FITTED)); } if (showHinted) { g2d.setColor(Color.RED); g2d.draw(glyph.getOutline(0, 0, flags | FontDelegate.FLAG_FITTED)); } } } } class GlyphPreview extends JPanel { protected void paintComponent(Graphics g) { if (glyph != null && g instanceof Graphics2D) { Graphics2D g2d = (Graphics2D) g; if (antiAlias) { g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } else { g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); } g2d.clearRect(0, 0, getWidth(), getHeight()); g2d.setColor(Color.BLACK); Shape outline = glyph.getOutline(0, 0, flags | FontDelegate.FLAG_FITTED); g2d.translate(20, outline.getBounds2D().getHeight() + 2); g2d.fill(outline); } } } HintingDemo() { File file = new File("/usr/share/fonts/truetype/freefont/FreeSans.ttf"); loadFont(file); setLayout(new BorderLayout()); chooser = new Chooser(); add(chooser, BorderLayout.NORTH); hintPanel = new HintPanel(); character = 'A'; add(hintPanel); options = new Options(); add(options, BorderLayout.EAST); stringViewer = new StringViewer(); add(stringViewer, BorderLayout.SOUTH); refresh(); JMenuBar mb = new JMenuBar(); setJMenuBar(mb); JMenu fileMenu = new JMenu("File"); mb.add(fileMenu); JMenuItem loadFont = new JMenuItem("Load font"); loadFont.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent ev) { JFileChooser fc = new JFileChooser() { public boolean accept(File f) { return f.isDirectory() || f.getName().endsWith(".ttf"); } }; int status = fc.showOpenDialog(HintingDemo.this); if (status == JFileChooser.APPROVE_OPTION) { File file = fc.getSelectedFile(); loadFont(file); } } }); fileMenu.add(loadFont); } void refresh() { if (chooser != null) chooser.refresh(); if (glyphPreview != null) glyphPreview.repaint(); if (hintPanel != null) hintPanel.repaint(); if (stringViewer != null) stringViewer.refresh(); } class Options extends JPanel implements ActionListener { JCheckBox antiAliasOpt; JCheckBox showGridOpt; JCheckBox showOriginalOpt; JCheckBox showHintedOpt; JCheckBox hintHorizontalOpt; JCheckBox hintVerticalOpt; JCheckBox hintEdgeOpt; JCheckBox hintStrongOpt; JCheckBox hintWeakOpt; Options() { setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); setBorder(new TitledBorder("Hinting options")); antiAliasOpt = new JCheckBox("Antialias"); antiAliasOpt.setSelected(true); antiAliasOpt.addActionListener(this); add(antiAliasOpt); showGridOpt = new JCheckBox("Show grid"); showGridOpt.setSelected(true); showGridOpt.addActionListener(this); add(showGridOpt); showOriginalOpt = new JCheckBox("Show original"); showOriginalOpt.setSelected(true); showOriginalOpt.addActionListener(this); add(showOriginalOpt); showHintedOpt = new JCheckBox("Show hinted"); showHintedOpt.setSelected(true); showHintedOpt.addActionListener(this); add(showHintedOpt); hintHorizontalOpt = new JCheckBox("Hint horizontal"); hintHorizontalOpt.setSelected(true); hintHorizontalOpt.addActionListener(this); add(hintHorizontalOpt); hintVerticalOpt = new JCheckBox("Hint vertical"); hintVerticalOpt.setSelected(true); hintVerticalOpt.addActionListener(this); add(hintVerticalOpt); hintEdgeOpt = new JCheckBox("Hint edge points"); hintEdgeOpt.setSelected(true); hintEdgeOpt.addActionListener(this); add(hintEdgeOpt); hintStrongOpt = new JCheckBox("Hint strong points"); hintStrongOpt.setSelected(true); hintStrongOpt.addActionListener(this); add(hintStrongOpt); hintWeakOpt = new JCheckBox("Hint weak points"); hintWeakOpt.setSelected(true); hintWeakOpt.addActionListener(this); add(hintWeakOpt); sync(); } void sync() { antiAlias = antiAliasOpt.isSelected(); showGrid = showGridOpt.isSelected(); showOriginal = showOriginalOpt.isSelected(); showHinted = showHintedOpt.isSelected(); if (hintHorizontalOpt.isSelected()) flags &= ~FontDelegate.FLAG_NO_HINT_HORIZONTAL; else flags |= FontDelegate.FLAG_NO_HINT_HORIZONTAL; if (hintVerticalOpt.isSelected()) flags &= ~FontDelegate.FLAG_NO_HINT_VERTICAL; else flags |= FontDelegate.FLAG_NO_HINT_VERTICAL; if (hintEdgeOpt.isSelected()) flags &= ~FontDelegate.FLAG_NO_HINT_EDGE_POINTS; else flags |= FontDelegate.FLAG_NO_HINT_EDGE_POINTS; if (hintStrongOpt.isSelected()) flags &= ~FontDelegate.FLAG_NO_HINT_STRONG_POINTS; else flags |= FontDelegate.FLAG_NO_HINT_STRONG_POINTS; if (hintWeakOpt.isSelected()) flags &= ~FontDelegate.FLAG_NO_HINT_WEAK_POINTS; else flags |= FontDelegate.FLAG_NO_HINT_WEAK_POINTS; refresh(); } public void actionPerformed(ActionEvent event) { sync(); } } class Chooser extends JPanel { JSpinner spin; Chooser() { setLayout(new GridLayout(1, 0)); setBorder(new TitledBorder("Choose and preview the character to render")); spin = new JSpinner(); spin.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent event) { int val = ((Integer) spin.getValue()).intValue(); setGlyph((char) val); } }); add(spin); glyphPreview = new GlyphPreview(); add(glyphPreview); } void refresh() { spin.setValue(new Integer(character)); repaint(); } } private void loadFont(File file) { try { RandomAccessFile raf = new RandomAccessFile(file, "r"); FileChannel chan = raf.getChannel(); ByteBuffer buf = chan.map(FileChannel.MapMode.READ_ONLY, 0, raf.length()); FontDelegate[] fonts = OpenTypeFontFactory.createFonts(buf); font = fonts[0]; setGlyph(character); refresh(); } catch (Exception ex) { ex.printStackTrace(); } } void setGlyph(char ch) { character = ch; glyph = (GNUGlyphVector) font.createGlyphVector(new Font("Dialog", 0, 12), new FontRenderContext(null, false, false), new StringCharacterIterator(new String(new char[]{ch}))); refresh(); } public static void main(String[] args) { HintingDemo f = new HintingDemo(); f.setSize(500, 500); f.setVisible(true); } }