Java/2D Graphics GUI/Text Layout

Материал из Java эксперт
Версия от 21:01, 31 мая 2010; (обсуждение)
(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск

A display of text, formatted by us instead of by AWT/Swing

<source lang="java"> /*

* Copyright (c) Ian F. Darwin, http://www.darwinsys.ru/, 1996-2002.
* All rights reserved. Software written by Ian F. Darwin and others.
* $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS""
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* 
* Java, the Duke mascot, and all variants of Sun"s Java "steaming coffee
* cup" logo are trademarks of Sun Microsystems. Sun"s, and James Gosling"s,
* pioneering role in inventing and promulgating (and standardizing) the Java 
* language and environment is gratefully acknowledged.
* 
* The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
* inventing predecessor languages C and C++ is also gratefully acknowledged.
*/

import java.awt.ruponent; import java.awt.Container; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.font.FontRenderContext; import java.awt.font.LineBreakMeasurer; import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.text.AttributedString; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.swing.JFrame; /**

* A display of text, formatted by us instead of by AWT/Swing.
*

* This program is distributed under the terms of the accompanying COPYRIGHT.txt * file (which is NOT the GNU General Public License). Please read it. Your use * of the software constitutes acceptance of the terms in the COPYRIGHT.txt * file. * * @author Ian F. Darwin * @version $Id: TextFormat.java,v 1.3 2004/03/26 03:34:30 ian Exp $ */ public class TextFormat extends Component { /** The text of this line */ protected String text; /** The Font */ protected Font font; /** The TextLayouts corresponding to "text" */ List layouts; public Font getFont() { return font; } public void setFont(Font f) { font = f; } public String getText() { return text; } public void setText(String t) { text = t; } public void paint(Graphics g) { if (text == null || text.length() == 0) return; if (layouts == null) getLayouts(g); Point pen = new Point(0, 0); Graphics2D g2d = (Graphics2D) g; g2d.setColor(java.awt.Color.black); // or a property g2d.setFont(font); Iterator it = layouts.iterator(); while (it.hasNext()) { TextLayout layout = (TextLayout) it.next(); pen.y += (layout.getAscent()); g2d.setFont(font); layout.draw(g2d, pen.x, pen.y); pen.y += layout.getDescent(); //pen.y += leading; } } /** * Lazy evaluation of the List of TextLayout objects corresponding to this * MText. Some things are approximations! */ private void getLayouts(Graphics g) { layouts = new ArrayList(); Point pen = new Point(10, 20); Graphics2D g2d = (Graphics2D) g; FontRenderContext frc = g2d.getFontRenderContext(); AttributedString attrStr = new AttributedString(text); attrStr.addAttribute(TextAttribute.FONT, font, 0, text.length()); LineBreakMeasurer measurer = new LineBreakMeasurer(attrStr .getIterator(), frc); float wrappingWidth; wrappingWidth = getSize().width - 15; while (measurer.getPosition() < text.length()) { TextLayout layout = measurer.nextLayout(wrappingWidth); layouts.add(layout); } } public static void main(String[] args) { JFrame jf = new JFrame("Demo"); Container cp = jf.getContentPane(); TextFormat tl = new TextFormat(); tl.setFont(new Font("SansSerif", Font.BOLD, 42)); tl.setText("The quick brown fox jumped over the lazy cow"); cp.add(tl); jf.setSize(300, 200); jf.setVisible(true); } } </source>

Another Line Break Demo

<source lang="java"> import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.font.FontRenderContext; import java.awt.font.LineBreakMeasurer; import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.text.AttributedCharacterIterator; import java.text.AttributedString; import javax.swing.JFrame; import javax.swing.JPanel; public class Main extends JPanel {

 String text = "this is a test. This is a test. This is a test. This is a test";
 AttributedString attribString = new AttributedString(text);
 AttributedCharacterIterator attribCharIterator;
 public Main() {
   setSize(350, 400);    
   attribString.addAttribute(TextAttribute.FOREGROUND, Color.blue, 0, text
       .length());
   attribString.addAttribute(TextAttribute.FONT, new Font("sanserif", Font.ITALIC, 20), 
       0, text.length());
 }
 public void paintComponent(Graphics g) {
   super.paintComponent(g);
   Graphics2D g2 = (Graphics2D) g;
   attribCharIterator = attribString.getIterator();
   FontRenderContext frc = new FontRenderContext(null, false, false);
   LineBreakMeasurer lbm = new LineBreakMeasurer(attribCharIterator, frc);
   int x = 10, y = 20; 
   int w = getWidth(); 
   float wrappingWidth = w - 15;
   while (lbm.getPosition() < text.length()) {
     TextLayout layout = lbm.nextLayout(wrappingWidth);
     y += layout.getAscent();
     layout.draw(g2, x, y);
     y += layout.getDescent() + layout.getLeading();
   }
 }
 public static void main(String arg[]) {
   JFrame frame = new JFrame();
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   frame.add("Center", new Main());
   frame.pack();
   frame.setSize(new Dimension(350, 400));
   frame.setVisible(true);
 }

}


 </source>   



Caret action

<source lang="java"> import java.awt.BasicStroke; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.Stroke; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.awt.font.FontRenderContext; import java.awt.font.TextAttribute; import java.awt.font.TextHitInfo; import java.awt.font.TextLayout; import java.awt.geom.AffineTransform; import java.text.AttributedCharacterIterator; import java.text.AttributedString; import javax.swing.JFrame; import javax.swing.JLabel; public class TextLayoutWithCarets extends JLabel {

 private TextHitInfo mHit;
 private TextLayout mLayout;
 private boolean mInitialized = false;
 public TextLayoutWithCarets() {
   addKeyListener(new KeyListener() {
     public void keyPressed(KeyEvent ke) {
       if (ke.getKeyCode() == KeyEvent.VK_RIGHT) {
         mHit = mLayout.getNextRightHit(mHit.getInsertionIndex());
         if (mHit == null)
           mHit = mLayout.getNextLeftHit(1);
         repaint();
       } else if (ke.getKeyCode() == KeyEvent.VK_LEFT) {
         mHit = mLayout.getNextLeftHit(mHit.getInsertionIndex());
         if (mHit == null)
           mHit = mLayout.getNextRightHit(mLayout
               .getCharacterCount() - 1);
         repaint();
       }
     }
     public void keyTyped(KeyEvent arg0) {
       // TODO Auto-generated method stub
       
     }
     public void keyReleased(KeyEvent arg0) {
       // TODO Auto-generated method stub
       
     }
   });
 }
 private void initialize(Graphics2D g2) {
   String s = "Java Source and Support.";
   // Create a plain and italic font.
   int fontSize = 32;
   Font font = new Font("Lucida Sans Regular", Font.PLAIN, fontSize);
   Font italicFont = new Font("Lucida Sans Oblique", Font.ITALIC, fontSize);
   // Create an Attributed String
   AttributedString as = new AttributedString(s);
   as.addAttribute(TextAttribute.FONT, font);
   as.addAttribute(TextAttribute.FONT, italicFont, 2, 5);
   // Get the iterator.
   AttributedCharacterIterator iterator = as.getIterator();
   // Create a TextLayout.
   FontRenderContext frc = g2.getFontRenderContext();
   mLayout = new TextLayout(iterator, frc);
   mHit = mLayout.getNextLeftHit(1);
   
   // Respond to left and right arrow keys.
   mInitialized = true;
 }
 public void paint(Graphics g) {
   Graphics2D g2 = (Graphics2D) g;
   g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
       RenderingHints.VALUE_ANTIALIAS_ON);
   g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
       RenderingHints.VALUE_FRACTIONALMETRICS_ON);
   if (mInitialized == false)
     initialize(g2);
   float x = 20, y = 80;
   mLayout.draw(g2, x, y);
   // Create a plain stroke and a dashed stroke.
   Stroke[] caretStrokes = new Stroke[2];
   caretStrokes[0] = new BasicStroke();
   caretStrokes[1] = new BasicStroke(1, BasicStroke.CAP_BUTT,
       BasicStroke.JOIN_ROUND, 0, new float[] { 4, 4 }, 0);
   // Now draw the carets
   Shape[] carets = mLayout.getCaretShapes(mHit.getInsertionIndex());
   for (int i = 0; i < carets.length; i++) {
     if (carets[i] != null) {
       AffineTransform at = AffineTransform.getTranslateInstance(x, y);
       Shape shape = at.createTransformedShape(carets[i]);
       g2.setStroke(caretStrokes[i]);
       g2.draw(shape);
     }
   }
 }
 public static void main(String[] args) {
   JFrame f = new JFrame();
   f.getContentPane().add(new TextLayoutWithCarets());
   f.setSize(350, 250);
   f.setVisible(true);
 }

}




 </source>   



Caret and TextLayout

<source lang="java"> import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.font.FontRenderContext; import java.awt.font.TextHitInfo; import java.awt.font.TextLayout; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import javax.swing.JFrame; import javax.swing.JPanel; public class TextLayoutPanel extends JPanel {

 TextLayout layout;
 FontRenderContext frc;
 Font font;
 Rectangle2D rect;
 float rx, ry, rw, rh;
 TextHitInfo hitInfo;
 Color caretColor;
 int hit1, hit2;
 int w, h;
 public TextLayoutPanel() {
   setBackground(Color.white);
   setForeground(Color.black);
   setSize(400, 200);
   addMouseListener(new MouseHandler());
   addMouseMotionListener(new MouseMotionHandler());
   w = getWidth();
   h = getHeight();
   String text = "Java Source and Support";
   font = new Font("Arial", Font.PLAIN, 36);
   frc = new FontRenderContext(null, false, false);
   layout = new TextLayout(text, font, frc);
   rx = (float) (w / 2 - layout.getBounds().getWidth() / 2);
   ry = (float) 3 * h / 4;
   rw = (float) (layout.getBounds().getWidth());
   rh = (float) (layout.getBounds().getHeight());
   rect = new Rectangle2D.Float(rx, ry, rw, rh);
   caretColor = getForeground();
 }
 public void update(Graphics g) {
   g.clearRect(0, 0, getWidth(), getHeight());
   paintComponent(g);
 }
 public void paintComponent(Graphics g) {
   super.paintComponent(g);
   Graphics2D g2 = (Graphics2D) g;
   AffineTransform at = AffineTransform.getTranslateInstance(rx, ry);
   Shape hilight = layout.getLogicalHighlightShape(hit1, hit2);
   hilight = at.createTransformedShape(hilight);
   g2.setColor(Color.lightGray);
   g2.fill(hilight);
   g2.setColor(Color.black);
   layout.draw(g2, rx, ry);
   // Draw caret
   Shape[] caretShapes = layout.getCaretShapes(hit1);
   Shape caret = at.createTransformedShape(caretShapes[0]);
   g2.setColor(caretColor);
   g2.draw(caret);
 }
 public int getHitLocation(int mouseX, int mouseY) {
   hitInfo = layout.hitTestChar(mouseX, mouseY, rect);
   return hitInfo.getInsertionIndex();
 }
 class MouseHandler extends MouseAdapter {
   public void mouseClicked(MouseEvent e) {
     caretColor = getForeground();
     hit1 = getHitLocation(e.getX(), e.getY());
     hit2 = hit1;
     repaint();
   }
   public void mousePressed(MouseEvent e) {
     caretColor = getForeground();
     hit1 = getHitLocation(e.getX(), e.getY());
     hit2 = hit1;
     repaint();
   }
   public void mouseReleased(MouseEvent e) {
     hit2 = getHitLocation(e.getX(), e.getY());
     repaint();
   }
 }
 class MouseMotionHandler extends MouseMotionAdapter {
   public void mouseDragged(MouseEvent e) {
     caretColor = getBackground();
     hit2 = getHitLocation(e.getX(), e.getY());
     repaint();
   }
 }
 public static void main(String arg[]) {
   JFrame frame = new JFrame();
   frame.setBackground(Color.white);
   frame.addWindowListener(new WindowAdapter() {
     public void windowClosing(WindowEvent e) {
       System.exit(0);
     }
   });
   frame.getContentPane().add("Center", new TextLayoutPanel());
   frame.pack();
   frame.setSize(new Dimension(400, 300));
   frame.setVisible(true);
 }

}




 </source>   



Drawing a Paragraph of Text

<source lang="java"> import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.font.LineBreakMeasurer; import java.awt.font.TextLayout; import java.text.AttributedString; import javax.swing.JFrame; import javax.swing.JPanel; public class Main extends JPanel {

 public void paint(Graphics g) {
   Graphics2D g2d = (Graphics2D) g;
   drawParagraph(g2d, "adfasdfaf", 20);
 }
 void drawParagraph(Graphics2D g, String paragraph, float width) {
   LineBreakMeasurer linebreaker = new LineBreakMeasurer(new AttributedString(paragraph)
       .getIterator(), g.getFontRenderContext());
   int y = 0;
   while (linebreaker.getPosition() < paragraph.length()) {
     TextLayout textLayout = linebreaker.nextLayout(width);
     y += textLayout.getAscent();
     textLayout.draw(g, 0, y);
     y += textLayout.getDescent() + textLayout.getLeading();
   }
 }
 public static void main(String[] args) {
   JFrame frame = new JFrame("Basic Shapes");
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   frame.add(new Main());
   frame.setSize(350, 250);
   frame.setLocationRelativeTo(null);
   frame.setVisible(true);
 }

}



 </source>   



Drawing multi-line text with AttributedString and LineBreakMeasurer

<source lang="java"> import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.font.FontRenderContext; import java.awt.font.LineBreakMeasurer; import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.text.AttributedCharacterIterator; import java.text.AttributedString; import javax.swing.JFrame; import javax.swing.UIManager; public class Main extends JFrame {

 public void paint(Graphics g) {
   String input = "this is a test.this is a test.this is a test.this is a test.";
   AttributedString attributedString = new AttributedString(input);
   attributedString.addAttribute(TextAttribute.FONT, (Font) UIManager
       .get("Label.font"));
   Color color = (Color) UIManager.get("Label.foreground");
   attributedString.addAttribute(TextAttribute.FOREGROUND, color);
   super.paint(g);
   Graphics2D g2d = (Graphics2D) g;
   int width = getSize().width;
   int x = 10;
   int y = 30;
   AttributedCharacterIterator characterIterator = attributedString
       .getIterator();
   FontRenderContext fontRenderContext = g2d.getFontRenderContext();
   LineBreakMeasurer measurer = new LineBreakMeasurer(characterIterator,
       fontRenderContext);
   while (measurer.getPosition() < characterIterator.getEndIndex()) {
     TextLayout textLayout = measurer.nextLayout(width);
     y += textLayout.getAscent();
     textLayout.draw(g2d, x, y);
     y += textLayout.getDescent() + textLayout.getLeading();
   }
 }
 public static void main(String args[]) {
   JFrame frame = new Main();
   frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
   frame.setSize(20, 200);
   frame.setVisible(true);
 }

}



 </source>   



Drawing Text with Mixed Styles

<source lang="java"> import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.text.AttributedString; import javax.swing.JFrame; import javax.swing.JPanel; public class Main extends JPanel {

 public void paint(Graphics g) {
   Graphics2D g2d = (Graphics2D) g;
   AttributedString astr = new AttributedString("aString");
   astr.addAttribute(TextAttribute.FONT, new Font("", 1, 30), 1, 2);
   astr.addAttribute(TextAttribute.BACKGROUND, Color.red, 2, 3);
   TextLayout tl = new TextLayout(astr.getIterator(), g2d.getFontRenderContext());
   tl.draw(g2d, 10, 20);
 }
 public static void main(String[] args) {
   JFrame frame = new JFrame("Basic Shapes");
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   frame.add(new Main());
   frame.setSize(350, 250);
   frame.setLocationRelativeTo(null);
   frame.setVisible(true);
 }

}



 </source>   



Draws the string at the specified location underlining the specified character

<source lang="java"> /*

* Copyright (c) 2001-2009 JGoodies Karsten Lentzsch. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
*  o Redistributions of source code must retain the above copyright notice,
*    this list of conditions and the following disclaimer.
*
*  o Redistributions in binary form must reproduce the above copyright notice,
*    this list of conditions and the following disclaimer in the documentation
*    and/or other materials provided with the distribution.
*
*  o Neither the name of JGoodies Karsten Lentzsch nor the names of
*    its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

import java.awt.*; import java.awt.print.PrinterGraphics; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.swing.JComponent; import javax.swing.plaf.basic.BasicGraphicsUtils;

/**

* Provides convenience behavior used by the JGoodies Looks.<p>
*
* Note: This class is not part of the public Looks API.
* It should be treated as library internal and should not be used by
* API users. It may be removed or changed with the Looks version
* without further notice.
*
* @author  Karsten Lentzsch
* @author  Andrej Golovnin
* @version $Revision: 1.12 $
*
* @since 2.0
*/

public final class RenderingUtils {

   private static final String PROP_DESKTOPHINTS = "awt.font.desktophints";
   private static final String SWING_UTILITIES2_NAME ="sun.swing.SwingUtilities2";
   /**
    * In Java 5 or later, this field holds the public static method
    * SwingUtilities2#drawStringUnderlinedAt that has been added
    * for Java 5.
    */
   private static Method drawStringUnderlineCharAtMethod = null;
   static {
  
           drawStringUnderlineCharAtMethod = getMethodDrawStringUnderlineCharAt();
      
   }
   private RenderingUtils() {
       // Overrides default constructor; prevents instantiation.
   }
   /**
    * Draws the string at the specified location underlining the specified
    * character.
    *
    * @param c JComponent that will display the string, may be null
    * @param g Graphics to draw the text to
    * @param text String to display
    * @param underlinedIndex Index of a character in the string to underline
    * @param x X coordinate to draw the text at
    * @param y Y coordinate to draw the text at
    */
   public static void drawStringUnderlineCharAt(JComponent c,Graphics g,
                          String text, int underlinedIndex, int x,int y) {
     
           if (drawStringUnderlineCharAtMethod != null) {
               try {
                   drawStringUnderlineCharAtMethod.invoke(null,
                           new Object[] {c, g, text, new Integer(underlinedIndex),
                                         new Integer(x), new Integer(y)});
                   return;
               } catch (IllegalArgumentException e) {
                   // Use the BasicGraphicsUtils as fallback
               } catch (IllegalAccessException e) {
                   // Use the BasicGraphicsUtils as fallback
               } catch (InvocationTargetException e) {
                   // Use the BasicGraphicsUtils as fallback
               }
           }
           Graphics2D g2 = (Graphics2D) g;
           Map oldRenderingHints = installDesktopHints(g2);
           BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, underlinedIndex, x, y);
           if (oldRenderingHints != null) {
               g2.addRenderingHints(oldRenderingHints);
           }
           return;
     
       BasicGraphicsUtils.drawStringUnderlineCharAt(g, text, underlinedIndex, x, y);
   }
   // Private Helper Code ****************************************************
   private static Method getMethodDrawStringUnderlineCharAt() {
       try {
           Class clazz = Class.forName(SWING_UTILITIES2_NAME);
           return clazz.getMethod(
                   "drawStringUnderlineCharAt",
                   new Class[] {JComponent.class, Graphics.class, String.class, Integer.TYPE, Integer.TYPE, Integer.TYPE}
                   );
       } catch (ClassNotFoundException e) {
           // returns null
       } catch (SecurityException e) {
           // returns null
       } catch (NoSuchMethodException e) {
           // returns null
       }
       return null;
   }
   private static Map installDesktopHints(Graphics2D g2) {
       Map oldRenderingHints = null;

           Map desktopHints = desktopHints(g2);
           if (desktopHints != null && !desktopHints.isEmpty()) {
               oldRenderingHints = new HashMap(desktopHints.size());
               RenderingHints.Key key;
               for (Iterator i = desktopHints.keySet().iterator(); i.hasNext();) {
                   key = (RenderingHints.Key) i.next();
                   oldRenderingHints.put(key, g2.getRenderingHint(key));
               }
               g2.addRenderingHints(desktopHints);
           }
   
       return oldRenderingHints;
   }
   private static Map desktopHints(Graphics2D g2) {
       if (isPrinting(g2)) {
           return null;
       }
       Toolkit toolkit = Toolkit.getDefaultToolkit();
       GraphicsDevice device = g2.getDeviceConfiguration().getDevice();
       Map desktopHints = (Map) toolkit.getDesktopProperty(
               PROP_DESKTOPHINTS + "." + device.getIDstring());
       if (desktopHints == null) {
           desktopHints = (Map) toolkit.getDesktopProperty(PROP_DESKTOPHINTS);
       }
       // It is possible to get a non-empty map but with disabled AA.
       if (desktopHints != null) {
           Object aaHint = desktopHints.get(RenderingHints.KEY_TEXT_ANTIALIASING);
           if ((aaHint == RenderingHints.VALUE_TEXT_ANTIALIAS_OFF) ||
               (aaHint == RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT)) {
               desktopHints = null;
           }
       }
       return desktopHints;
   }
   private static boolean isPrinting(Graphics g) {
       return g instanceof PrintGraphics || g instanceof PrinterGraphics;
   }

}



 </source>   



Draw text with TextLayout

<source lang="java"> import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.font.FontRenderContext; import java.awt.font.TextLayout; import javax.swing.JFrame; import javax.swing.JPanel; public class Main extends JPanel {

 public Main() {
   setBackground(Color.white);
 }
 public void paint(Graphics g) {
   Graphics2D g2D;
   g2D = (Graphics2D) g;
   g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
   g2D.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
   FontRenderContext frc = g2D.getFontRenderContext();
   Font font1 = new Font("Courier", Font.BOLD, 24);
   String str1 = new String("Java");
   TextLayout tl = new TextLayout(str1, font1, frc);
   g2D.setColor(Color.gray);
   tl.draw(g2D, 50, 150);
 }
 public static void main(String s[]) {
   JFrame frame1 = new JFrame("2D Text");
   frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   frame1.getContentPane().add("Center", new Main());
   frame1.pack();
   frame1.setSize(new Dimension(500, 300));
   frame1.setVisible(true);
 }

}



 </source>   



Getting the Shape from the Outline of Text

<source lang="java"> import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.font.FontRenderContext; import java.awt.font.TextLayout; import javax.swing.JFrame; import javax.swing.JPanel; public class Main extends JPanel {

 public void paint(Graphics g) {
   Graphics2D g2d = (Graphics2D) g;
   g2d.draw(getTextShape(g2d, "asdf", new Font("", 1, 30)));
 }
 public Shape getTextShape(Graphics2D g2d, String str, Font font) {
   FontRenderContext frc = g2d.getFontRenderContext();
   TextLayout tl = new TextLayout(str, font, frc);
   return tl.getOutline(null);
 }
 public static void main(String[] args) {
   JFrame frame = new JFrame("Basic Shapes");
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   frame.add(new Main());
   frame.setSize(350, 250);
   frame.setLocationRelativeTo(null);
   frame.setVisible(true);
 }

}



 </source>   



Hightlight text by drag and selection

<source lang="java"> import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.awt.font.FontRenderContext; import java.awt.font.TextHitInfo; import java.awt.font.TextLayout; import java.awt.geom.AffineTransform; import javax.swing.JFrame; import javax.swing.JPanel; public class Highlights extends JPanel {

 private TextLayout textLayout;
 private TextHitInfo firstHit, secondHit;
 private int x = 40, y = 80;
   public Highlights(){
   addMouseListener(new MouseAdapter() {
     public void mousePressed(MouseEvent me) {
       firstHit = textLayout.hitTestChar(me.getX() - x, me.getY()
           - y);
       secondHit = null;
     }
     public void mouseReleased(MouseEvent me) {
       secondHit = textLayout.hitTestChar(me.getX() - x, me.getY()
           - y);
       repaint();
     }
   });
   addMouseMotionListener(new MouseMotionAdapter() {
     public void mouseDragged(MouseEvent me) {
       secondHit = textLayout.hitTestChar(me.getX() - x, me.getY()
           - y);
       repaint();
     }
   });
       
   }
 public void paint(Graphics g) {
   Graphics2D g2 = (Graphics2D) g;
   g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
       RenderingHints.VALUE_ANTIALIAS_ON);
   g2.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
       RenderingHints.VALUE_FRACTIONALMETRICS_ON);
   String s = "Drag the text to highlight Java Source and Support.";
   Font font = new Font("Serif", Font.PLAIN, 32);
   if (textLayout == null) {
     FontRenderContext frc = g2.getFontRenderContext();
     textLayout = new TextLayout(s, font, frc);
   }
   // Draw the highlight.
   if (firstHit != null && secondHit != null) {
     Shape base = textLayout.getLogicalHighlightShape(firstHit
         .getInsertionIndex(), secondHit.getInsertionIndex());
     AffineTransform at = AffineTransform.getTranslateInstance(x, y);
     Shape highlight = at.createTransformedShape(base);
     g2.setPaint(Color.white);
     g2.fill(highlight);
   }
   g2.setPaint(Color.black);
   textLayout.draw(g2, x, y);
 }
 public static void main(String[] args) {
   JFrame f = new JFrame();
   f.getContentPane().add(new Highlights());
   f.setSize(850, 250);
   f.show();
 }

}




 </source>   



JFreeChart: Draw String Demo

<source lang="java"> /* ========================================================================

* JCommon : a free general purpose class library for the Java(tm) platform
* ========================================================================
*
* (C) Copyright 2000-2004, by Object Refinery Limited and Contributors.
* 
* Project Info:  http://www.jfree.org/jcommon/index.html
*
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
* in the United States and other countries.]
* 
* -------------------
* DrawStringDemo.java
* -------------------
* (C) Copyright 2003, 2004, by Object Refinery Limited.
*
* Original Author:  David Gilbert (for Object Refinery Limited);
* Contributor(s):   -;
*
* $Id: DrawStringDemo.java,v 1.3 2005/06/01 14:12:28 taqua Exp $
*
* Changes
* -------
* 10-Jun-2003 : Version 1;
*
*/

package org.jfree.demo; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTabbedPane; import org.jfree.ui.ApplicationFrame; import org.jfree.ui.FontChooserPanel; import org.jfree.ui.RefineryUtilities; import org.jfree.ui.Spinner; import org.jfree.ui.TextAnchor; /**

* A demo of some of the string drawing methods in the JCommon class library.
*
* @author David Gilbert
*/

public class DrawStringDemo extends ApplicationFrame

                           implements ActionListener, PropertyChangeListener {
   /** The alignment anchor for the first panel. */
   private JComboBox combo1;
   /** The alignment anchor for the second panel. */
   private JComboBox combo2;
   /** The rotation anchor for the second panel. */
   private JComboBox combo3;
   /** A spinner for the second panel. */
   private Spinner spinner;
   /** String panel 1. */
   private DrawStringPanel drawStringPanel1;
   /** String panel 2. */
   private DrawStringPanel drawStringPanel2;
   /**
    * Creates a new demo instance.
    *
    * @param title  the frame title.
    */
   public DrawStringDemo(final String title) {
       super(title);
       setContentPane(createContentPane());
   }
   /**
    * Receives action events.
    *
    * @param event  the event.
    */
   public void actionPerformed(final ActionEvent event) {
       if (event.getActionCommand().equals("fontButton.clicked")) {
           displayFontDialog();
       }
       if (event.getActionCommand().equals("combo1.changed")) {
           handleCombo1Change();
       }
       if (event.getActionCommand().equals("combo2.changed")) {
           handleCombo2Change();
       }
       if (event.getActionCommand().equals("combo3.changed")) {
           handleCombo3Change();
       }
   }
   /**
    * Receives property change events.
    *
    * @param event  the event.
    */
   public void propertyChange(final PropertyChangeEvent event) {
       final int r = this.spinner.getValue();
       final double angle = Math.PI * 2.0 * (r / 360.0);
       this.drawStringPanel2.setAngle(angle);
       this.drawStringPanel2.invalidate();
       this.drawStringPanel2.repaint();
   }
   /**
    * Updates the display when combo 1 is updated.
    */
   private void handleCombo1Change() {
       final String text = this.rubo1.getSelectedItem().toString();
       this.drawStringPanel1.setAnchor(convertStringToAnchor(text));
       this.drawStringPanel1.invalidate();
       this.drawStringPanel1.repaint();
   }
   /**
    * Updates the display when combo 2 is updated.
    */
   private void handleCombo2Change() {
       final String text = this.rubo2.getSelectedItem().toString();
       this.drawStringPanel2.setAnchor(convertStringToAnchor(text));
       this.drawStringPanel2.invalidate();
       this.drawStringPanel2.repaint();
   }
   /**
    * Updates the display when combo 3 is updated.
    */
   private void handleCombo3Change() {
       final String text = this.rubo3.getSelectedItem().toString();
       this.drawStringPanel2.setRotationAnchor(convertStringToAnchor(text));
       this.drawStringPanel2.invalidate();
       this.drawStringPanel2.repaint();
   }
   /**
    * Creates the content pane for the demo frame.
    *
    * @return The content pane.
    */
   private JPanel createContentPane() {
       final JPanel content = new JPanel(new BorderLayout());
       final JTabbedPane tabs = new JTabbedPane();
       tabs.add("Alignment", createTab1Content());
       tabs.add("Rotation", createTab2Content());
       content.add(tabs);
       return content;
   }
   /**
    * Creates the content for tab 1.
    *
    * @return The content panel.
    */
   private JPanel createTab1Content() {
       final JPanel content = new JPanel(new BorderLayout());
       this.rubo1 = new JComboBox();
       this.rubo1.setActionCommand("combo1.changed");
       populateTextAnchorCombo(this.rubo1);
       this.rubo1.addActionListener(this);
       final JPanel controls = new JPanel();
       controls.add(this.rubo1);
       final JButton fontButton = new JButton("Select Font...");
       fontButton.setActionCommand("fontButton.clicked");
       fontButton.addActionListener(this);
       controls.add(fontButton);
       content.add(controls, BorderLayout.NORTH);
       this.drawStringPanel1 = new DrawStringPanel("0123456789", false);
       content.add(this.drawStringPanel1);
       return content;
   }
   /**
    * Creates the content for tab 2.
    *
    * @return The content panel.
    */
   private JPanel createTab2Content() {
       final JPanel content = new JPanel(new BorderLayout());
       final JPanel controls = new JPanel();
       controls.add(new JLabel("Text anchor: "));
       this.rubo2 = new JComboBox();
       populateTextAnchorCombo(this.rubo2);
       this.rubo2.setActionCommand("combo2.changed");
       this.rubo2.addActionListener(this);
       controls.add(this.rubo2);
       controls.add(new JLabel("Rotation anchor: "));
       this.rubo3 = new JComboBox();
       populateTextAnchorCombo(this.rubo3);
       this.rubo3.setActionCommand("combo3.changed");
       this.rubo3.addActionListener(this);
       controls.add(this.rubo3);
       this.spinner = new Spinner(0);
       this.spinner.addPropertyChangeListener(this);
       controls.add(this.spinner);
       content.add(controls, BorderLayout.NORTH);
       this.drawStringPanel2 = new DrawStringPanel("Rotated Text", true);
       content.add(this.drawStringPanel2);
       return content;
   }
   /**
    * Displays a primitive font chooser dialog to allow the user to change the font.
    */
   private void displayFontDialog() {
       final FontChooserPanel panel = new FontChooserPanel(this.drawStringPanel1.getFont());
       final int result = JOptionPane.showConfirmDialog(this, panel, "Font Selection",
                                                  JOptionPane.OK_CANCEL_OPTION,
                                                  JOptionPane.PLAIN_MESSAGE);
       if (result == JOptionPane.OK_OPTION) {
           this.drawStringPanel1.setFont(panel.getSelectedFont());
           this.drawStringPanel2.setFont(panel.getSelectedFont());
       }
   }
   /**
    * Populates a combo box with the available {@link TextAnchor} options.
    *
    * @param combo  the combo box.
    */
   private void populateTextAnchorCombo(final JComboBox combo) {
       combo.addItem("TextAnchor.TOP_LEFT");
       combo.addItem("TextAnchor.TOP_CENTER");
       combo.addItem("TextAnchor.TOP_RIGHT");
       combo.addItem("TextAnchor.HALF_ASCENT_LEFT");
       combo.addItem("TextAnchor.HALF_ASCENT_CENTER");
       combo.addItem("TextAnchor.HALF_ASCENT_RIGHT");
       combo.addItem("TextAnchor.CENTER_LEFT");
       combo.addItem("TextAnchor.CENTER");
       combo.addItem("TextAnchor.CENTER_RIGHT");
       combo.addItem("TextAnchor.BASELINE_LEFT");
       combo.addItem("TextAnchor.BASELINE_CENTER");
       combo.addItem("TextAnchor.BASELINE_RIGHT");
       combo.addItem("TextAnchor.BOTTOM_LEFT");
       combo.addItem("TextAnchor.BOTTOM_CENTER");
       combo.addItem("TextAnchor.BOTTOM_RIGHT");
   }
   /**
    * Converts a string to a corresponding {@link TextAnchor} instance.
    *
    * @param text  the text.
    *
    * @return The anchor.
    */
   private TextAnchor convertStringToAnchor(final String text) {
       if (text.equals("TextAnchor.TOP_LEFT")) {
           return TextAnchor.TOP_LEFT;
       }
       else if (text.equals("TextAnchor.TOP_CENTER")) {
           return TextAnchor.TOP_CENTER;
       }
       else if (text.equals("TextAnchor.TOP_RIGHT")) {
           return TextAnchor.TOP_RIGHT;
       }
       else if (text.equals("TextAnchor.CENTER_LEFT")) {
           return TextAnchor.CENTER_LEFT;
       }
       else if (text.equals("TextAnchor.CENTER")) {
           return TextAnchor.CENTER;
       }
       else if (text.equals("TextAnchor.CENTER_RIGHT")) {
           return TextAnchor.CENTER_RIGHT;
       }
       else if (text.equals("TextAnchor.HALF_ASCENT_LEFT")) {
           return TextAnchor.HALF_ASCENT_LEFT;
       }
       else if (text.equals("TextAnchor.HALF_ASCENT_CENTER")) {
           return TextAnchor.HALF_ASCENT_CENTER;
       }
       else if (text.equals("TextAnchor.HALF_ASCENT_RIGHT")) {
           return TextAnchor.HALF_ASCENT_RIGHT;
       }
       else if (text.equals("TextAnchor.BASELINE_LEFT")) {
           return TextAnchor.BASELINE_LEFT;
       }
       else if (text.equals("TextAnchor.BASELINE_CENTER")) {
           return TextAnchor.BASELINE_CENTER;
       }
       else if (text.equals("TextAnchor.BASELINE_RIGHT")) {
           return TextAnchor.BASELINE_RIGHT;
       }
       else if (text.equals("TextAnchor.BOTTOM_LEFT")) {
           return TextAnchor.BOTTOM_LEFT;
       }
       else if (text.equals("TextAnchor.BOTTOM_CENTER")) {
           return TextAnchor.BOTTOM_CENTER;
       }
       else if (text.equals("TextAnchor.BOTTOM_RIGHT")) {
           return TextAnchor.BOTTOM_RIGHT;
       }
       else {
           return null;
       } 
   }
   /**
    * The starting point for the demo.
    *
    * @param args  ignored.
    */
   public static void main(final String[] args) {
       final DrawStringDemo demo = new DrawStringDemo("DrawString Demo");
       demo.pack();
       RefineryUtilities.centerFrameOnScreen(demo);
       demo.setVisible(true);
   }

}




 </source>   



Line break for textlayout

<source lang="java"> import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.font.FontRenderContext; import java.awt.font.LineBreakMeasurer; import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.text.AttributedCharacterIterator; import java.text.AttributedString; import java.util.Hashtable; import javax.swing.JApplet; import javax.swing.JFrame; import javax.swing.JPanel; public class LineBreakSample extends JPanel {

 private LineBreakMeasurer lineMeasurer;
 // the first character in the paragraph.
 private int paragraphStart;
 // the first character after the end of the paragraph.
 private int paragraphEnd;
 private static final Hashtable map = new Hashtable();
 static {
   map.put(TextAttribute.SIZE, new Float(18.0));
 }
 private static AttributedString vanGogh = new AttributedString(
     "Many people believe that Vincent van Gogh painted his best works "
         + "during the two-year period he spent in Provence. Here is where he "
         + "painted The Starry Night--which some consider to be his greatest "
         + "work of all. However, as his artistic brilliance reached new heights "
         + "in Provence, his physical and mental health plummeted. ",
     map);
 public LineBreakSample() {
   AttributedCharacterIterator paragraph = vanGogh.getIterator();
   paragraphStart = paragraph.getBeginIndex();
   paragraphEnd = paragraph.getEndIndex();
   // Create a new LineBreakMeasurer from the paragraph.
   lineMeasurer = new LineBreakMeasurer(paragraph,
       new FontRenderContext(null, false, false));
 }
 public void paintComponent(Graphics g) {
   super.paintComponent(g);
   setBackground(Color.white);
   Graphics2D graphics2D = (Graphics2D) g;
   // Set formatting width to width of Component.
   Dimension size = getSize();
   float formatWidth = (float) size.width;
   float drawPosY = 0;
   lineMeasurer.setPosition(paragraphStart);
   // Get lines from lineMeasurer until the entire
   // paragraph has been displayed.
   while (lineMeasurer.getPosition() < paragraphEnd) {
     // Retrieve next layout.
     TextLayout layout = lineMeasurer.nextLayout(formatWidth);
     // Move y-coordinate by the ascent of the layout.
     drawPosY += layout.getAscent();
     // Compute pen x position. If the paragraph is
     // right-to-left, we want to align the TextLayouts
     // to the right edge of the panel.
     float drawPosX;
     if (layout.isLeftToRight()) {
       drawPosX = 0;
     } else {
       drawPosX = formatWidth - layout.getAdvance();
     }
     // Draw the TextLayout at (drawPosX, drawPosY).
     layout.draw(graphics2D, drawPosX, drawPosY);
     // Move y-coordinate in preparation for next layout.
     drawPosY += layout.getDescent() + layout.getLeading();
   }
 }
 public static void main(String[] args) {
   JFrame f = new JFrame("");
   f.addWindowListener(new WindowAdapter() {
     public void windowClosing(WindowEvent e) {
       System.exit(0);
     }
   });
   LineBreakSample controller = new LineBreakSample();
   f.getContentPane().add(controller,"Center");
   f.setSize(new Dimension(400, 250));
   f.setVisible(true);
 }

}




 </source>   



LineMetrics: the metrics to layout characters along a line

<source lang="java"> import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.font.FontRenderContext; import java.awt.font.LineMetrics; import java.awt.geom.Line2D; import javax.swing.JFrame; import javax.swing.JPanel; public class LineMetricsIllustration extends JPanel{

 public void paint(Graphics g) {
   Graphics2D g2 = (Graphics2D) g;
   g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
       RenderingHints.VALUE_ANTIALIAS_ON);
   Font font = new Font("Serif", Font.PLAIN, 72);
   g2.setFont(font);
   String s = "Java Source and Support";
   float x = 50, y = 150;
   // Draw the baseline.
   FontRenderContext frc = g2.getFontRenderContext();
   float width = (float) font.getStringBounds(s, frc).getWidth();
   Line2D baseline = new Line2D.Float(x, y, x + width, y);
   g2.setPaint(Color.red);
   g2.draw(baseline);
   // Draw the ascent.
   LineMetrics lm = font.getLineMetrics(s, frc);
   Line2D ascent = new Line2D.Float(x, y - lm.getAscent(), x + width, y
       - lm.getAscent());
   g2.draw(ascent);
   // Draw the descent.
   Line2D descent = new Line2D.Float(x, y + lm.getDescent(), x + width, y
       + lm.getDescent());
   g2.draw(descent);
   // Draw the leading.
   Line2D leading = new Line2D.Float(x, y + lm.getDescent()
       + lm.getLeading(), x + width, y + lm.getDescent()
       + lm.getLeading());
   g2.draw(leading);
   // Render the string.
   g2.setPaint(Color.black);
   g2.drawString(s, x, y);
 }
 public static void main(String[] args) {
   JFrame f = new JFrame();
   f.getContentPane().add(new LineMetricsIllustration());
   f.setSize(850, 250);
   f.show();
   
 }

}




 </source>   



Mouse hit and textlayout

<source lang="java"> import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.awt.font.FontRenderContext; import java.awt.font.TextAttribute; import java.awt.font.TextHitInfo; import java.awt.font.TextLayout; import java.awt.geom.Point2D; import java.text.AttributedCharacterIterator; import java.text.AttributedString; import java.util.Hashtable; import javax.swing.JFrame; import javax.swing.JPanel; public class HitTestSample extends JPanel {

 private static final Color STRONG_CARET_COLOR = Color.red;
 private static final Color WEAK_CARET_COLOR = Color.black;
 private TextLayout textLayout;
 private int insertionIndex;
 private static final FontRenderContext DEFAULT_FRC = new FontRenderContext(
     null, false, false);
 private static final Hashtable map = new Hashtable();
 static {
   map.put(TextAttribute.SIZE, new Float(18.0));
 }
 private static AttributedString helloWorld = new AttributedString(
     "Java Source and Support.", map);
 public HitTestSample() {
   AttributedCharacterIterator text = helloWorld.getIterator();
   // Create a new TextLayout from the given text.
   textLayout = new TextLayout(text, DEFAULT_FRC);
   // Initilize insertionIndex.
   insertionIndex = 0;
   addMouseListener(new HitTestMouseListener());
 }
 public Dimension getPreferredSize() {
   return new Dimension(400, 250);
 }
 private Point2D computeLayoutOrigin() {
   Dimension size = getPreferredSize();
   Point2D.Float origin = new Point2D.Float();
   origin.x = (float) (size.width - textLayout.getAdvance()) / 2;
   origin.y = (float) (size.height - textLayout.getDescent() + textLayout
       .getAscent()) / 2;
   return origin;
 }
 public void paintComponent(Graphics g) {
   super.paintComponent(g);
   setBackground(Color.white);
   Graphics2D graphics2D = (Graphics2D) g;
   Point2D origin = computeLayoutOrigin();
   graphics2D.translate(origin.getX(), origin.getY());
   // Draw textLayout.
   textLayout.draw(graphics2D, 0, 0);
   // Retrieve caret Shapes for insertionIndex.
   Shape[] carets = textLayout.getCaretShapes(insertionIndex);
   graphics2D.setColor(STRONG_CARET_COLOR);
   graphics2D.draw(carets[0]);
   if (carets[1] != null) {
     graphics2D.setColor(WEAK_CARET_COLOR);
     graphics2D.draw(carets[1]);
   }
 }
 private class HitTestMouseListener extends MouseAdapter {
   public void mouseClicked(MouseEvent e) {
     Point2D origin = computeLayoutOrigin();
     // Compute the mouse click location relative to
     // textLayout"s origin.
     float clickX = (float) (e.getX() - origin.getX());
     float clickY = (float) (e.getY() - origin.getY());
     // Get the character position of the mouse click.
     TextHitInfo currentHit = textLayout.hitTestChar(clickX, clickY);
     insertionIndex = currentHit.getInsertionIndex();
     // Repaint the Component so the new caret(s) will be displayed.
     repaint();
   }
 }
 public static void main(String[] args) {
   JFrame f = new JFrame("HitTestSample");
   HitTestSample demo = new HitTestSample();
   f.getContentPane().add(demo, "Center");
   f.addWindowListener(new WindowAdapter() {
     public void windowClosing(WindowEvent e) {
       System.exit(0);
     }
   });
   f.setSize(new Dimension(400, 250));
   f.setVisible(true);
 }

}




 </source>   



Paragraph Layout

<source lang="java"> import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.RenderingHints; import java.awt.font.FontRenderContext; import java.awt.font.LineBreakMeasurer; import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.text.AttributedCharacterIterator; import java.text.AttributedString; import javax.swing.JFrame; import javax.swing.JPanel; public class ParagraphLayout extends JPanel {

 public void paint(Graphics g) {
   Graphics2D g2 = (Graphics2D) g;
   g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
       RenderingHints.VALUE_ANTIALIAS_ON);
   String s = "Java components and products Directory for Java components " +
       "and applications.Hundreds of Java components and applications " +
       "are organized by topic. You can find what you need easily. " +
       "You may also compare your product with others. If your component " +
       "is not listed, just send your url to jexp@jexp.ru. " +
       "http://www.jexp.ru";
   Font font = new Font("Serif", Font.PLAIN, 24);
   AttributedString as = new AttributedString(s);
   as.addAttribute(TextAttribute.FONT, font);
   AttributedCharacterIterator aci = as.getIterator();
   FontRenderContext frc = g2.getFontRenderContext();
   LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc);
   Insets insets = getInsets();
   float wrappingWidth = getSize().width - insets.left - insets.right;
   float x = insets.left;
   float y = insets.top;
   while (lbm.getPosition() < aci.getEndIndex()) {
     TextLayout textLayout = lbm.nextLayout(wrappingWidth);
     y += textLayout.getAscent();
     textLayout.draw(g2, x, y);
     y += textLayout.getDescent() + textLayout.getLeading();
     x = insets.left;
   }
 }
 public static void main(String[] args) {
   JFrame f = new JFrame();
   f.getContentPane().add(new ParagraphLayout());
   f.setSize(350, 250);
   f.show();
 }

}




 </source>   



Renders a paragraph of text (line breaks ignored) to an image (created and returned).

<source lang="java"> /*

*
* Created on March 16, 2007, 4:34 PM
*
* Copyright 2006-2007 Nigel Hughes
*
* 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.
*/

import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsConfiguration; import java.awt.GraphicsEnvironment; import java.awt.RenderingHints; import java.awt.Transparency; import java.awt.font.FontRenderContext; import java.awt.font.LineBreakMeasurer; import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.awt.image.BufferedImage; import java.text.AttributedCharacterIterator; import java.text.AttributedString; import java.util.Hashtable; /**

* @author nigel
*/

public class Utils {

 /** 
  * Renders a paragraph of text (line breaks ignored) to an image (created and returned). 
  *
  * @param font The font to use
  * @param textColor The color of the text
  * @param text The message
  * @param width The width the text should be limited to
  * @return An image with the text rendered into it
  */
 public static BufferedImage renderTextToImage(Font font, Color textColor, String text, int width){
     Hashtable   map = new Hashtable();
     map.put(TextAttribute.FONT, font);
     AttributedString attributedString = new AttributedString(text,map);
     AttributedCharacterIterator paragraph = attributedString.getIterator();
     
     FontRenderContext frc = new FontRenderContext(null, false, false);
     int paragraphStart = paragraph.getBeginIndex();
     int paragraphEnd = paragraph.getEndIndex();
     LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, frc);      
     
     float   drawPosY=0;
     
     //First time around, just determine the height
     while (lineMeasurer.getPosition() < paragraphEnd) {
         TextLayout layout = lineMeasurer.nextLayout(width);
         
         // Move it down
         drawPosY += layout.getAscent() + layout.getDescent() + layout.getLeading();
     }
     
     BufferedImage image = createCompatibleImage(width,(int) drawPosY);
     Graphics2D graphics = (Graphics2D) image.getGraphics();
     graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
     
     drawPosY=0;
     lineMeasurer.setPosition(paragraphStart);
     while (lineMeasurer.getPosition() < paragraphEnd) {
         TextLayout layout = lineMeasurer.nextLayout(width);
         
         // Move y-coordinate by the ascent of the layout.
         drawPosY += layout.getAscent();
         
        /* Compute pen x position.  If the paragraph is
           right-to-left, we want to align the TextLayouts
           to the right edge of the panel.
         */
         float drawPosX;
         if (layout.isLeftToRight()) {
             drawPosX = 0;
         } else {
             drawPosX = width - layout.getAdvance();
         }
         
         // Draw the TextLayout at (drawPosX, drawPosY).
         layout.draw(graphics, drawPosX, drawPosY);
         
         // Move y-coordinate in preparation for next layout.
         drawPosY += layout.getDescent() + layout.getLeading();
     }
     
     graphics.dispose();
     return image;
 }
 /**
  * Creates an image compatible with the current display
  * 
  * @return A BufferedImage with the appropriate color model
  */
 public static BufferedImage createCompatibleImage(int width, int height) {
   GraphicsConfiguration configuration = GraphicsEnvironment.getLocalGraphicsEnvironment()
       .getDefaultScreenDevice().getDefaultConfiguration();
   return configuration.createCompatibleImage(width, height, Transparency.TRANSLUCENT);
 }

}


 </source>   



TextAttribute: color and font

<source lang="java"> import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.font.TextAttribute; import java.text.AttributedString; import javax.swing.JFrame; import javax.swing.JPanel; public class IteratorTest extends JPanel {

 public void paint(Graphics g) {
   Graphics2D g2 = (Graphics2D) g;
   String s = "Java Source and Support";
   Dimension d = getSize();
   g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
       RenderingHints.VALUE_ANTIALIAS_ON);
   Font serifFont = new Font("Serif", Font.PLAIN, 48);
   Font sansSerifFont = new Font("Monospaced", Font.PLAIN, 48);
   AttributedString as = new AttributedString(s);
   as.addAttribute(TextAttribute.FONT, serifFont);
   as.addAttribute(TextAttribute.FONT, sansSerifFont, 2, 5);
   as.addAttribute(TextAttribute.FOREGROUND, Color.red, 5, 6);
   as.addAttribute(TextAttribute.FOREGROUND, Color.red, 16, 17);
   g2.drawString(as.getIterator(), 40, 80);
 }
 public static void main(String[] args) {
   JFrame f = new JFrame();
   f.getContentPane().add(new IteratorTest());
   f.setSize(850, 250);
   f.show();
 }

}




 </source>   



TextAttribute: Underline and strike through

<source lang="java"> import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.font.TextAttribute; import java.text.AttributedString; import javax.swing.JFrame; import javax.swing.JPanel; public class IteratorUnderStrike extends JPanel{

 public void paint(Graphics g) {
   Graphics2D g2 = (Graphics2D) g;
   String s = "\"www.jexp.ru\" is great.";
   g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
       RenderingHints.VALUE_ANTIALIAS_ON);
   Font plainFont = new Font("Times New Roman", Font.PLAIN, 24);
   AttributedString as = new AttributedString(s);
   as.addAttribute(TextAttribute.FONT, plainFont);
   as.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON, 1,
       15);
   as.addAttribute(TextAttribute.STRIKETHROUGH,
       TextAttribute.STRIKETHROUGH_ON, 18, 25);
   g2.drawString(as.getIterator(), 24, 70);
 }
 public static void main(String[] args) {
   JFrame f = new JFrame();
   f.getContentPane().add(new IteratorUnderStrike());
   f.setSize(850, 250);
   f.show();
 }

}




 </source>   



TextHitInfo Demo: tell you which is the letter you are clicking

<source lang="java"> import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.font.FontRenderContext; import java.awt.font.TextHitInfo; import java.awt.font.TextLayout; import javax.swing.JFrame; import javax.swing.JPanel; public class TextHitInfoDemo extends JPanel {

 private TextLayout mTextLayout;
 private int mX = 40, mY = 80;
 public TextHitInfoDemo() {
   addMouseListener(new MouseAdapter() {
     public void mouseClicked(MouseEvent me) {
       TextHitInfo hit = mTextLayout.hitTestChar(me.getX() - mX, me
           .getY()
           - mY);
       System.out.println(hit);
     }
   });
 }
 public void paint(Graphics g) {
   Graphics2D g2 = (Graphics2D) g;
   g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
       RenderingHints.VALUE_ANTIALIAS_ON);
   String s = "Java Source and Support";
   Font font = new Font("Serif", Font.PLAIN, 32);
   if (mTextLayout == null) {
     FontRenderContext frc = g2.getFontRenderContext();
     mTextLayout = new TextLayout(s, font, frc);
   }
   mTextLayout.draw(g2, mX, mY);
 }
 public static void main(String[] args) {
   JFrame f = new JFrame();
   f.getContentPane().add(new TextHitInfoDemo());
   f.setSize(200, 200);
   f.show();
 }
 

}




 </source>   



TextLayout demo

<source lang="java"> import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.font.TextLayout; import javax.swing.JFrame; import javax.swing.JPanel; public class TextLayoutOne extends JPanel {

 public void paint(Graphics g) {
   Graphics2D g2 = (Graphics2D) g;
   g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
       RenderingHints.VALUE_ANTIALIAS_ON);
   String s = "Java Source and Support.";
   Font font = new Font("Serif", Font.PLAIN, 32);
   TextLayout textLayout = new TextLayout(s, font, g2
       .getFontRenderContext());
   textLayout.draw(g2, 40, 80);
 }
 public static void main(String[] args) {
   JFrame f = new JFrame();
   f.getContentPane().add(new TextLayoutOne());
   f.setSize(300, 200);
   f.setVisible(true);
 }

}




 </source>   



Unicode display

<source lang="java"> import java.awt.Font; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; public class HelloInJapanese extends JPanel {

 static JFrame frame;
 static String helloInJapanese = "Hello in Japanese is konnichi wa, \u4eca\u65e5\u306f.";
 public HelloInJapanese(String characters) {
   Font theFont = new Font("Bitstream Cyberbit", Font.PLAIN, 20);
   JTextArea area = new JTextArea(characters, 2, 30);
   area.setFont(theFont);
   area.setLineWrap(true);
   JScrollPane scrollpane = new JScrollPane(area);
   add(scrollpane);
 }
 public static void main(String argv[]) {
   HelloInJapanese japanesePanel = new HelloInJapanese(helloInJapanese);
   frame = new JFrame("Hello in Japanese");
   frame.addWindowListener(new WindowAdapter() {
     public void windowClosing(WindowEvent e) {
       System.exit(0);
     }
   });
   frame.getContentPane().add("Center", japanesePanel);
   frame.pack();
   frame.setVisible(true);
 }

}




 </source>   



Unicode: test layout

<source lang="java"> /* Java Internationalization By Andy Deitsch, David Czarnecki ISBN: 0-596-00019-7 O"Reilly

  • /

import java.awt.*; import java.awt.event.*; import java.awt.font.*; import java.text.*; import javax.swing.*; public class TextLayoutDemo extends JFrame {

 String davidMessage = "David says, \"\u05E9\u05DC\u05D5\u05DD \u05E2\u05D5\u05DC\u05DD\" ";
 String andyMessage = "Andy also says, \"\u05E9\u05DC\u05D5\u05DD \u05E2\u05D5\u05DC\u05DD\" ";
 String textMessage = davidMessage + andyMessage + davidMessage + andyMessage +
                      davidMessage + andyMessage + davidMessage + andyMessage +
                      davidMessage + andyMessage + davidMessage + andyMessage +
                      davidMessage + andyMessage + davidMessage + andyMessage;
 public TextLayoutDemo() {
   super("TextLayoutDemo");
 }
 public void paint(Graphics g) {
   Graphics2D graphics2D = (Graphics2D)g;
   GraphicsEnvironment.getLocalGraphicsEnvironment();
   Font font = new Font("LucidaSans", Font.PLAIN, 14);
   AttributedString messageAS = new AttributedString(textMessage);
   messageAS.addAttribute(TextAttribute.FONT, font);
   AttributedCharacterIterator messageIterator = messageAS.getIterator();
   FontRenderContext messageFRC = graphics2D.getFontRenderContext();
   LineBreakMeasurer messageLBM = new LineBreakMeasurer(messageIterator, messageFRC);
   Insets insets = getInsets();
   float wrappingWidth = getSize().width - insets.left - insets.right;
   float x = insets.left;
   float y = insets.top;
   while (messageLBM.getPosition() < messageIterator.getEndIndex()) {
     TextLayout textLayout = messageLBM.nextLayout(wrappingWidth);
     y += textLayout.getAscent();
     textLayout.draw(graphics2D, x, y);
     y += textLayout.getDescent() + textLayout.getLeading();
     x = insets.left;
   }
 }
 public static void main(String[] args) {
   JFrame frame = new TextLayoutDemo();
   frame.addWindowListener(new WindowAdapter() {
     public void windowClosing(WindowEvent e) {System.exit(0);}
   });
   frame.pack();
   frame.setVisible(true);
 }

}




</source>