import java.awt.*; import java.awt.event.*; import java.awt.font.*; import java.awt.print.*; import java.text.*; import java.util.*; import javax.swing.*; public class Print extends JFrame implements Printable { public Print() { super("Print"); setSize(400, 200); setJMenuBar(createMenuBar()); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); setVisible(true); } protected JMenuBar createMenuBar() { JMenuBar menuBar = new JMenuBar(); JMenu mFile = new JMenu("File"); mFile.setMnemonic('f'); JMenuItem mPrint = new JMenuItem("Print..."); mPrint.setMnemonic('p'); ActionListener lstPrint = new ActionListener() { public void actionPerformed(ActionEvent e) { Thread runner = new Thread() { public void run() { printData(); } }; runner.start(); } }; mPrint.addActionListener(lstPrint); mFile.add(mPrint); JMenuItem mExit = new JMenuItem("Exit"); mExit.setMnemonic('x'); ActionListener lstExit = new ActionListener() { public void actionPerformed(ActionEvent e) { System.exit(0); } }; mExit.addActionListener(lstExit); mFile.add(mExit); menuBar.add(mFile); return menuBar; } public void printData() { try { PrinterJob prnJob = PrinterJob.getPrinterJob(); prnJob.setPrintable(this); if (!prnJob.printDialog()) { return; } prnJob.print(); } catch (PrinterException e) { e.printStackTrace(); System.err.println("Printing error: "+e.toString()); } } private AttributedCharacterIterator getIterator(String value, Font font) { AttributedCharacters characters = new AttributedCharacters(); for (int i=0; i < value.length(); i++) { characters.append(value.charAt(i), font, Color.black); } return characters.iterator(); } private static final FontRenderContext FONT_RENDER_CONTEXT = new FontRenderContext(null, true, true); private Graphics2D getGraphics(Graphics g) { Graphics2D graphics = (Graphics2D) g; graphics.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); graphics.setRenderingHint( RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); return graphics; } public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException { if (pageIndex != 0) { return NO_SUCH_PAGE; } Graphics2D g = getGraphics(graphics); TextLayout textLayout1 = new TextLayout(getIterator("print monospaced test print monospaced test print monospaced test", new Font("Monospaced", Font.PLAIN, 20)), FONT_RENDER_CONTEXT); textLayout1.draw(g, 30, 100); TextLayout textLayout2 = new TextLayout(getIterator("print times roman test print times roman test print times roman test", new Font("TimesRoman", Font.PLAIN, 20)), FONT_RENDER_CONTEXT); textLayout2.draw(g, 30, 150); TextLayout textLayout3 = new TextLayout(getIterator("print serif test print serif test print serif test", new Font("Serif", Font.PLAIN, 20)), FONT_RENDER_CONTEXT); textLayout3.draw(g, 30, 200); return PAGE_EXISTS; } public static void main(String argv[]) { new Print(); } // ---------------------------------------- private static class AttributedCharacters { protected char[] chars; protected Font[] fonts; protected Color[] colors; protected int[] runStart; protected int[] runLimit; protected int current; public AttributedCharacters() { chars = new char[10]; fonts = new Font[10]; colors = new Color[10]; runStart = new int[10]; runLimit = new int[10]; current = -1; } public void append(char c, Font f, Color color) { if (f == null) { return; } if (++current == chars.length) { char[] ctmp = new char[2 * chars.length]; Font[] ftmp = new Font[2 * chars.length]; Color[] cotmp = new Color[2 * chars.length]; int[] rstmp = new int[2 * chars.length]; int[] rltmp = new int[2 * chars.length]; System.arraycopy(chars, 0, ctmp, 0, chars.length); System.arraycopy(fonts, 0, ftmp, 0, chars.length); System.arraycopy(colors, 0, cotmp, 0, chars.length); System.arraycopy(runStart, 0, rstmp, 0, chars.length); System.arraycopy(runLimit, 0, rltmp, 0, chars.length); chars = ctmp; fonts = ftmp; colors = cotmp; runStart = rstmp; runLimit = rltmp; } chars[current] = c; fonts[current] = f; colors[current] = color; if (current != 0) { int prev = current - 1; if (fonts[prev].equals(f) && colors[prev].equals(color)) { runLimit[runStart[current] = runStart[prev]] = current; } else { runLimit[current] = current; runStart[current] = current; } } } public void append(char[] a, Font f, Color color) { if ((a == null) || (a.length == 0) || (f == null) || (color == null)) { return; } if ((++current + a.length) >= chars.length) { int size = Math.max(current + a.length, 2 * chars.length); char[] ctmp = new char[size]; Font[] ftmp = new Font[size]; Color[] cotmp = new Color[size]; int[] rstmp = new int[size]; int[] rltmp = new int[size]; System.arraycopy(chars, 0, ctmp, 0, chars.length); System.arraycopy(fonts, 0, ftmp, 0, fonts.length); System.arraycopy(colors, 0, cotmp, 0, chars.length); System.arraycopy(runStart, 0, rstmp, 0, chars.length); System.arraycopy(runLimit, 0, rltmp, 0, chars.length); chars = ctmp; fonts = ftmp; colors = cotmp; runStart = rstmp; runLimit = rltmp; } System.arraycopy(a, 0, chars, current, a.length); for (int i = 0; i < a.length; i++) { fonts[i + current] = f; colors[i + current] = color; } int prev = current - 1; int pseudo = (current + a.length) - 1; if (prev < 0) { runLimit[0] = pseudo; } else { int replace; if (fonts[prev].equals(f) && colors[prev].equals(color)) { runLimit[runStart[prev]] = pseudo; replace = runStart[prev]; } else { runLimit[current] = pseudo; replace = current; } for (int i = current; i <= pseudo; i++) { runStart[i] = replace; } } current = pseudo; } public AttributedCharacterIterator iterator() { int size = current + 1; char[] cs = new char[size]; Font[] fs = new Font[size]; Color[] colos = new Color[size]; int[] rstmp = new int[size]; int[] rltmp = new int[size]; System.arraycopy(runStart, 0, rstmp, 0, size); System.arraycopy(runLimit, 0, rltmp, 0, size); System.arraycopy(chars, 0, cs, 0, size); System.arraycopy(fonts, 0, fs, 0, size); System.arraycopy(colors, 0, colos, 0, size); AttributedCharacterIterator ret = new AttributedCharacterIteratorImpl(cs, fs, colos, rstmp, rltmp); return ret; } private class AttributedCharacterIteratorImpl implements AttributedCharacterIterator { protected int current; protected char[] chars; protected Font[] fonts; protected Color[] colors; protected int[] runStart; protected int[] runLimit; protected Set singleton; public AttributedCharacterIteratorImpl(char[] chars, Font[] fonts, Color[] colors, int[] rs, int[] rl) { this.chars = chars; this.fonts = fonts; this.colors = colors; runStart = rs; runLimit = rl; } public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { return null; } } public char current() { if (current >= chars.length) { return DONE; } return chars[current]; } public char first() { current = 0; if (current >= chars.length) { return DONE; } return chars[current]; } public int getBeginIndex() { return 0; } public int getEndIndex() { return chars.length; } public int getIndex() { return current; } public char last() { int end = getEndIndex(); if (end == 0) { return DONE; } return chars[current = end - 1]; } public char next() { if (current >= (getEndIndex() - 1)) { return DONE; } return chars[++current]; } public char previous() { if (current == 0) { return DONE; } return chars[--current]; } public char setIndex(int i) { if (i < 0) { throw new IllegalArgumentException(); } if (i == getEndIndex()) { current = getEndIndex(); return DONE; } return chars[current = i]; } public Set getAllAttributeKeys() { if (singleton == null) { Set l = new HashSet(4); l.add(TextAttribute.FONT); l.add(TextAttribute.FOREGROUND); singleton = Collections.unmodifiableSet(l); } return singleton; } public Object getAttribute(AttributedCharacterIterator.Attribute att) { if (att == TextAttribute.FONT) { return fonts[getIndex()]; } else if (att == TextAttribute.FOREGROUND) { return colors[getIndex()]; } else { return null; } } public Map getAttributes() { Map m = new HashMap(1); m.put(TextAttribute.FONT, fonts[getIndex()]); m.put(TextAttribute.FOREGROUND, colors[getIndex()]); return m; } public int getRunLimit() { return runLimit[runStart[getIndex()]] + 1; } public int getRunLimit(AttributedCharacterIterator.Attribute att) { if ((att != TextAttribute.FONT) && (att != TextAttribute.FOREGROUND)) { return getEndIndex(); } return getRunLimit(); } public int getRunLimit(Set attributes) { if (attributes.contains(TextAttribute.FONT) || attributes.contains(TextAttribute.FOREGROUND)) { return getRunLimit(); } else { return getEndIndex(); } } public int getRunStart() { return runStart[getIndex()]; } public int getRunStart(AttributedCharacterIterator.Attribute att) { if ((att != TextAttribute.FONT) && (att != TextAttribute.FOREGROUND)) { return 0; } return getRunStart(); } public int getRunStart(Set attributes) { if ((attributes.contains(TextAttribute.FONT)) || attributes.contains(TextAttribute.FOREGROUND)) { return getRunStart(); } else { return 0; } } } } }