Java by API — различия между версиями

Материал из Java эксперт
Перейти к: навигация, поиск
м (1 версия)
 
(нет различий)

Версия 17:43, 31 мая 2010

AttributedString: addAttribute(Attribute attribute, Object value)

import java.awt.Container;
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.JComponent;
import javax.swing.JFrame;
public class MainClass{
  public static void main(String[] args) {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    MyCanvas tl = new MyCanvas();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class MyCanvas extends JComponent {
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D)g;
    String s = "\"www.jexp.ru,\" www.jexp.ru";
    
    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);
    
    g2.drawString(as.getIterator(), 24, 70);
  }
}





GlyphVector: getGlyphOutline(int glyphIndex)

import java.awt.Container;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class MainClass {
  public static void main(String[] args) {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    MyCanvas tl = new MyCanvas();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class MyCanvas extends JComponent {
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    String s = "www.jexp.ru www.jexp.ru";
    Font font = new Font("Serif", Font.PLAIN, 24);
    FontRenderContext frc = g2.getFontRenderContext();
    g2.translate(40, 80);
    GlyphVector gv = font.createGlyphVector(frc, s);
    int length = gv.getNumGlyphs();
    for (int i = 0; i < length; i++) {
      Point2D p = gv.getGlyphPosition(i);
      double theta = (double) i / (double) (length - 1) * Math.PI / 4;
      AffineTransform at = AffineTransform.getTranslateInstance(p.getX(), p.getY());
      at.rotate(theta);
      Shape glyph = gv.getGlyphOutline(i);
      Shape transformedGlyph = at.createTransformedShape(glyph);
      g2.fill(transformedGlyph);
    }
  }
}





LineBreakMeasurer: getPosition()

import java.awt.Container;
import java.awt.Dimension;
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 java.util.Hashtable;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainClass {
  public static void main(String[] args) {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container c = f.getContentPane();
    c.add(new Justify());
    f.pack();
    f.setVisible(true);
  }
}
class Justify extends JPanel {
  final static int LEFT = 0;
  final static int RIGHT = 1;
  final static int CENTER = 2;
  final static int EQUALITY = 3;
  int justify = EQUALITY;
  public void paint(Graphics g) {
    Dimension size = getSize();
    String s = "To jexp.ru or not to jexp.ru, that is a question";
    Hashtable map = new Hashtable();
    map.put(TextAttribute.SIZE, new Float(32.0f));
    AttributedString as = new AttributedString(s, map);
    map = new Hashtable();
    map.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
    as.addAttributes(map, 33, 52);
    AttributedCharacterIterator aci = as.getIterator();
    int startIndex = aci.getBeginIndex();
    int endIndex = aci.getEndIndex();
    LineBreakMeasurer measurer;
    measurer = new LineBreakMeasurer(aci, new FontRenderContext(null, false, false));
    measurer.setPosition(startIndex);
    float wrappingWidth = (float) size.width;
    float Y = 0.0f;
    while (measurer.getPosition() < endIndex) {
      TextLayout layout = measurer.nextLayout(wrappingWidth);
      Y += layout.getAscent();
      float X = 0.0f;
      switch (justify) {
      case LEFT:
        if (layout.isLeftToRight())
          X = 0.0f;
        else
          X = wrappingWidth - layout.getAdvance();
        break;
      case RIGHT:
        if (layout.isLeftToRight())
          X = wrappingWidth - layout.getVisibleAdvance();
        else
          X = wrappingWidth;
        break;
      case CENTER:
        if (layout.isLeftToRight())
          X = (wrappingWidth - layout.getVisibleAdvance()) / 2;
        else
          X = (wrappingWidth + layout.getAdvance()) / 2 - layout.getAdvance();
        break;
      case EQUALITY:
        layout = layout.getJustifiedLayout(wrappingWidth);
      }
      layout.draw((Graphics2D) g, X, Y);
      Y += layout.getDescent() + layout.getLeading();
    }
  }
}





LineBreakMeasurer: nextLayout(float wrappingWidth)

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.JComponent;
import javax.swing.JFrame;

public class MainClass {
  public static void main(String[] a) throws Exception {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    TextFormat tl = new TextFormat();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class TextFormat extends JComponent {
   List layouts;
   Font font = new Font("SansSerif", Font.BOLD, 42);
   String text = "The quick brown fox jumped over the lazy cow";
  public void paint(Graphics g) {
    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();
    }
  }
  private void getLayouts(Graphics g) {
    layouts = new ArrayList();
    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);
    }
  }
  
}





LineBreakMeasurer: setPosition(int newPosition)

import java.awt.Container;
import java.awt.Dimension;
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 java.util.Hashtable;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainClass {
  public static void main(String[] args) {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container c = f.getContentPane();
    c.add(new Justify());
    f.pack();
    f.setVisible(true);
  }
}
class Justify extends JPanel {
  final static int LEFT = 0;
  final static int RIGHT = 1;
  final static int CENTER = 2;
  final static int EQUALITY = 3;
  int justify = EQUALITY;
  public void paint(Graphics g) {
    Dimension size = getSize();
    String s = "To jexp.ru or not to jexp.ru, that is a question";
    Hashtable map = new Hashtable();
    map.put(TextAttribute.SIZE, new Float(32.0f));
    AttributedString as = new AttributedString(s, map);
    map = new Hashtable();
    map.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
    as.addAttributes(map, 33, 52);
    AttributedCharacterIterator aci = as.getIterator();
    int startIndex = aci.getBeginIndex();
    int endIndex = aci.getEndIndex();
    LineBreakMeasurer measurer;
    measurer = new LineBreakMeasurer(aci, new FontRenderContext(null, false, false));
    measurer.setPosition(startIndex);
    float wrappingWidth = (float) size.width;
    float Y = 0.0f;
    while (measurer.getPosition() < endIndex) {
      TextLayout layout = measurer.nextLayout(wrappingWidth);
      Y += layout.getAscent();
      float X = 0.0f;
      switch (justify) {
      case LEFT:
        if (layout.isLeftToRight())
          X = 0.0f;
        else
          X = wrappingWidth - layout.getAdvance();
        break;
      case RIGHT:
        if (layout.isLeftToRight())
          X = wrappingWidth - layout.getVisibleAdvance();
        else
          X = wrappingWidth;
        break;
      case CENTER:
        if (layout.isLeftToRight())
          X = (wrappingWidth - layout.getVisibleAdvance()) / 2;
        else
          X = (wrappingWidth + layout.getAdvance()) / 2 - layout.getAdvance();
        break;
      case EQUALITY:
        layout = layout.getJustifiedLayout(wrappingWidth);
      }
      layout.draw((Graphics2D) g, X, Y);
      Y += layout.getDescent() + layout.getLeading();
    }
  }
}





LineMetrics: getAscent()

  
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 Main 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 = "this is a test";
    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 Main());
    f.setSize(850, 250);
    f.setVisible(true);
    
  }
}





LineMetrics: getDescent()

  
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 Main 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 = "this is a test";
    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 Main());
    f.setSize(850, 250);
    f.setVisible(true);
    
  }
}





LineMetrics: getLeading()

  
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 Main 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 = "this is a test";
    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 Main());
    f.setSize(850, 250);
    f.setVisible(true);
    
  }
}





new FontRenderContext(AffineTransform tx, boolean isAntiAliased, boolean usesFractionalMetrics)

  
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class Main extends JFrame {
  public Main() {
    getContentPane().add(new DrawingCanvas());
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    setSize(500, 500);
    setVisible(true);
  }
  public static void main(String arg[]) {
    new Main();
  }
}
class DrawingCanvas extends JPanel {
  Font font = new Font("Dialog", Font.BOLD, 40);
  FontMetrics fontMetrics;
  DrawingCanvas() {
    setSize(300, 300);
    setBackground(Color.white);
    fontMetrics = getFontMetrics(font);
  }
  public void paint(Graphics g) {
    Graphics2D g2D = (Graphics2D) g;
    int w = getSize().width;
    int h = getSize().height;
    RenderingHints qualityHints = new RenderingHints(
        RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    qualityHints.put(RenderingHints.KEY_RENDERING,
        RenderingHints.VALUE_RENDER_QUALITY);
    g2D.setRenderingHints(qualityHints);
    AffineTransform at = new AffineTransform();
    at.setToTranslation(-300, -400);
    at.shear(-0.5, 0.0);
    FontRenderContext frc = new FontRenderContext(at, false, false);
    TextLayout tl = new TextLayout("World!", font, frc);
    Shape outline = tl.getOutline(null);
    g2D.setColor(Color.blue);
    BasicStroke wideStroke = new BasicStroke(2.0f);
    g2D.setStroke(wideStroke);
    g2D.draw(outline);
  }
}





new ImageGraphicAttribute(Image image, int alignment)

import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.font.GraphicAttribute;
import java.awt.font.ImageGraphicAttribute;
import java.awt.font.TextAttribute;
import java.awt.image.BufferedImage;
import java.text.AttributedString;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class MainClass {
  public static void main(String[] args) {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    MyCanvas tl = new MyCanvas();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class MyCanvas extends JComponent {
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    Font serifFont = new Font("Serif", Font.PLAIN, 32);
    AttributedString as = new AttributedString("www.jexp.ru");
    as.addAttribute(TextAttribute.FONT, serifFont);
    Image image =  createImage();
    ImageGraphicAttribute imageAttribute = new ImageGraphicAttribute(image,
        GraphicAttribute.TOP_ALIGNMENT);
    as.addAttribute(TextAttribute.CHAR_REPLACEMENT, imageAttribute, 5, 6);
    g2.drawString(as.getIterator(), 20, 120);
  }
  private BufferedImage createImage() {
    BufferedImage bim;
    Color[] colors = { Color.red, Color.blue, Color.yellow, };
    int width = 8, height = 8;
    bim = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    Graphics2D g2 = bim.createGraphics();
    for (int i = 0; i < width; i++) {
      g2.setPaint(colors[(i / 2) % colors.length]);
      g2.drawLine(0, i, i, 0);
      g2.drawLine(width - i, height, width, height - i);
    }
    return bim;
  }
}





new LineBreakMeasurer(AttributedCharacterIterator text, FontRenderContext frc)

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.JComponent;
import javax.swing.JFrame;

public class MainClass {
  public static void main(String[] a) throws Exception {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    TextFormat tl = new TextFormat();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class TextFormat extends JComponent {
   List layouts;
   Font font = new Font("SansSerif", Font.BOLD, 42);
   String text = "The quick brown fox jumped over the lazy cow";
  public void paint(Graphics g) {
    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();
    }
  }
  private void getLayouts(Graphics g) {
    layouts = new ArrayList();
    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);
    }
  }
  
}





new TextLayout(String string, Font font, FontRenderContext frc)

import java.awt.Container;
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.JComponent;
import javax.swing.JFrame;
public class MainClass {
  public static void main(String[] args) {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    MyCanvas tl = new MyCanvas();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class MyCanvas extends JComponent {
  private TextLayout mTextLayout;
  private int mX = 40, mY = 80;
  public MyCanvas() {
    addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent me) {
        TextHitInfo hit = mTextLayout.hitTestChar(me.getX() - mX, me.getY() - mY);
        System.out.println(hit.getCharIndex());
        System.out.println(hit.getInsertionIndex());
        System.out.println(hit.isLeadingEdge());
      }
    });
  }
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    String s = "www.jexp.ru";
    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);
  }
}





TextAttribute.FONT

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.RenderingHints;
import java.awt.font.TextAttribute;
import java.text.AttributedString;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class MainClass{
  public static void main(String[] args) {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    MyCanvas tl = new MyCanvas();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class MyCanvas extends JComponent {
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D)g;
    String s = "www.jexp.ru";
    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, 2, 5);
    
    g2.drawString(as.getIterator(), 40, 80);
  }
}





TextAttribute.FOREGROUND

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.RenderingHints;
import java.awt.font.TextAttribute;
import java.text.AttributedString;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class MainClass{
  public static void main(String[] args) {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    MyCanvas tl = new MyCanvas();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class MyCanvas extends JComponent {
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D)g;
    String s = "www.jexp.ru";
    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, 2, 5);
    
    g2.drawString(as.getIterator(), 40, 80);
  }
}





TextAttribute.STRIKETHROUGH

import java.awt.Container;
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.JComponent;
import javax.swing.JFrame;
public class MainClass{
  public static void main(String[] args) {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    MyCanvas tl = new MyCanvas();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class MyCanvas extends JComponent {
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D)g;
    String s = "\"www.jexp.ru,\" www.jexp.ru";
    
    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.STRIKETHROUGH,
        TextAttribute.STRIKETHROUGH_ON, 18, 22);
    g2.drawString(as.getIterator(), 24, 70);
  }
}





TextAttribute.STRIKETHROUGH_ON

import java.awt.Container;
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.JComponent;
import javax.swing.JFrame;
public class MainClass{
  public static void main(String[] args) {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    MyCanvas tl = new MyCanvas();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class MyCanvas extends JComponent {
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D)g;
    String s = "\"www.jexp.ru,\" www.jexp.ru";
    
    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.STRIKETHROUGH,
        TextAttribute.STRIKETHROUGH_ON, 18, 22);
    g2.drawString(as.getIterator(), 24, 70);
  }
}





TextAttribute.UNDERLINE

import java.awt.Container;
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.JComponent;
import javax.swing.JFrame;
public class MainClass{
  public static void main(String[] args) {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    MyCanvas tl = new MyCanvas();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class MyCanvas extends JComponent {
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D)g;
    String s = "\"www.jexp.ru,\" www.jexp.ru";
    
    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, 11);
    g2.drawString(as.getIterator(), 24, 70);
  }
}





TextAttribute.UNDERLINE_ON

import java.awt.Container;
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.JComponent;
import javax.swing.JFrame;
public class MainClass{
  public static void main(String[] args) {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    MyCanvas tl = new MyCanvas();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class MyCanvas extends JComponent {
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D)g;
    String s = "\"www.jexp.ru,\" www.jexp.ru";
    
    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, 11);
    g2.drawString(as.getIterator(), 24, 70);
  }
}





TextHitInfo: getCharIndex()

 
import java.awt.Container;
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.JComponent;
import javax.swing.JFrame;
public class MainClass {
  public static void main(String[] args) {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    MyCanvas tl = new MyCanvas();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class MyCanvas extends JComponent {
  private TextLayout mTextLayout;
  private int mX = 40, mY = 80;
  public MyCanvas() {
    addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent me) {
        TextHitInfo hit = mTextLayout.hitTestChar(me.getX() - mX, me.getY() - mY);
        System.out.println(hit.getCharIndex());
        System.out.println(hit.getInsertionIndex());
        System.out.println(hit.isLeadingEdge());
      }
    });
  }
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    String s = "www.jexp.ru";
    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);
  }
}





TextHitInfo: getInsertionIndex()

 
import java.awt.Container;
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.JComponent;
import javax.swing.JFrame;
public class MainClass {
  public static void main(String[] args) {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    MyCanvas tl = new MyCanvas();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class MyCanvas extends JComponent {
  private TextLayout mTextLayout;
  private int mX = 40, mY = 80;
  public MyCanvas() {
    addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent me) {
        TextHitInfo hit = mTextLayout.hitTestChar(me.getX() - mX, me.getY() - mY);
        System.out.println(hit.getCharIndex());
        System.out.println(hit.getInsertionIndex());
        System.out.println(hit.isLeadingEdge());
      }
    });
  }
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    String s = "www.jexp.ru";
    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);
  }
}





TextHitInfo: isLeadingEdge()

 
import java.awt.Container;
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.JComponent;
import javax.swing.JFrame;
public class MainClass {
  public static void main(String[] args) {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    MyCanvas tl = new MyCanvas();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class MyCanvas extends JComponent {
  private TextLayout mTextLayout;
  private int mX = 40, mY = 80;
  public MyCanvas() {
    addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent me) {
        TextHitInfo hit = mTextLayout.hitTestChar(me.getX() - mX, me.getY() - mY);
        System.out.println(hit.getCharIndex());
        System.out.println(hit.getInsertionIndex());
        System.out.println(hit.isLeadingEdge());
      }
    });
  }
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    String s = "www.jexp.ru";
    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);
  }
}





TextHitInfo: leading(int charIndex)

 
/*
 * @(#)CodePointInputMethod.java  1.6 05/11/17
 * 
 * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 * 
 * -Redistribution of source code must retain the above copyright notice, this
 *  list of conditions and the following disclaimer.
 * 
 * -Redistribution 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.
 * 
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may 
 * be used to endorse or promote products derived from this software without 
 * specific prior written permission.
 * 
 * This software is provided "AS IS," without a warranty of any kind. ALL 
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST 
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, 
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY 
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, 
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 * 
 * You acknowledge that this software is not designed, licensed or intended
 * for use in the design, construction, operation or maintenance of any
 * nuclear facility.
 */
/*
 * @(#)CodePointInputMethod.java  1.6 05/11/17
 */
//package com.sun.inputmethods.internal.codepointim;
import java.awt.AWTEvent;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.InputMethodEvent;
import java.awt.event.KeyEvent;
import java.awt.font.TextAttribute;
import java.awt.font.TextHitInfo;
import java.awt.im.InputMethodHighlight;
import java.awt.im.spi.InputMethod;
import java.awt.im.spi.InputMethodContext;
import java.io.IOException;
import java.text.AttributedString;
import java.util.Locale;
/**
 * The Code Point Input Method is a simple input method that allows Unicode
 * characters to be entered using their code point or code unit values. See the
 * accompanying file README.txt for more information.
 *
 * @author Brian Beck
 */
public class CodePointInputMethod implements InputMethod {
    private static final int UNSET           = 0;
    private static final int ESCAPE          = 1; // \u0000       - \uFFFF
    private static final int SPECIAL_ESCAPE  = 2; // \U000000     - \U10FFFF
    private static final int SURROGATE_PAIR  = 3; // \uD800\uDC00 - \uDBFF\uDFFF
    private InputMethodContext context;
    private Locale locale;
    private StringBuffer buffer;
    private int insertionPoint;
    private int format = UNSET;

    public CodePointInputMethod() throws IOException {
    }
    /**
     * This is the input method"s main routine.  The composed text is stored
     * in buffer.
     */
    public void dispatchEvent(AWTEvent event) {
        // This input method handles KeyEvent only.
        if (!(event instanceof KeyEvent)) {
            return;
        }
        KeyEvent e = (KeyEvent) event;
        int eventID = event.getID();
        boolean notInCompositionMode = buffer.length() == 0;
        if (eventID == KeyEvent.KEY_PRESSED) {
            // If we are not in composition mode, pass through
            if (notInCompositionMode)  {
                return;
            }
            switch (e.getKeyCode()) {
                case KeyEvent.VK_LEFT:
                    moveCaretLeft();
                    break;
                case KeyEvent.VK_RIGHT:
                    moveCaretRight();
                    break;
            }
        } else if (eventID == KeyEvent.KEY_TYPED) {
            char c = e.getKeyChar();
            // If we are not in composition mode, wait a back slash
            if (notInCompositionMode)  {
                // If the type character is not a back slash, pass through
                if (c != "\\") {
                    return;
                }
                startComposition(); // Enter to composition mode
            } else {
                switch (c) { 
                case " ": // Exit from composition mode
                    finishComposition();
                    break;
                case "\u007f":  // Delete
                    deleteCharacter();
                    break;
                case "\b":  // BackSpace
                    deletePreviousCharacter();
                    break;
                case "\u001b":  // Escape
                    cancelComposition();
                    break;
                case "\n":  // Return
                case "\t":  // Tab
                    sendCommittedText();
                    break;
                default:
                    composeUnicodeEscape(c);
                    break;
                }
            }
        } else {  // KeyEvent.KEY_RELEASED
            // If we are not in composition mode, pass through
            if (notInCompositionMode)  {
                return;
            }
        }
        e.consume();
    }
    private void composeUnicodeEscape(char c) {
        switch (buffer.length()) {
            case  1:  // \\
                waitEscapeCharacter(c);
                break;
            case 2:  // \\u or \\U
            case 3:  // \\ux or \\Ux
            case 4:  // \\uxx or \\Uxx
                waitDigit(c);
                break;
            case 5:  // \\uxxx or \\Uxxx
                if (format == SPECIAL_ESCAPE) {
                    waitDigit(c);
                } else {
                    waitDigit2(c);
                }
                break;
            case 6:  // \\uxxxx or \\Uxxxx
                if (format == SPECIAL_ESCAPE) {
                    waitDigit(c);
                } else if (format == SURROGATE_PAIR) {
                    waitBackSlashOrLowSurrogate(c);
                } else {
                    beep();
                }
                break;
            case 7:  // \\Uxxxxx
                // Only SPECIAL_ESCAPE format uses this state.
                // Since the second "\\u" of SURROGATE_PAIR format is inserted
                // automatically, users don"t have to type these keys.
                waitDigit(c);
                break;
            case 8:  // \\uxxxx\\u
            case 9:  // \\uxxxx\\ux
            case 10: // \\uxxxx\\uxx
            case 11: // \\uxxxx\\uxxx
                if (format == SURROGATE_PAIR) {
                    waitDigit(c);
                } else {
                    beep();
                }
                break;
            default:
                beep();
                break;
        }
    }
    private void waitEscapeCharacter(char c) {
        if (c == "u" || c == "U") {
            buffer.append(c);
            insertionPoint++;
            sendComposedText();
            format = (c == "u") ? ESCAPE : SPECIAL_ESCAPE;
        } else {
            if (c != "\\") {
                buffer.append(c);
                insertionPoint++;
            }
            sendCommittedText();
        }
    }
    private void waitDigit(char c) {
        if (Character.digit(c, 16) != -1) {
            buffer.insert(insertionPoint++, c);
            sendComposedText();
        } else {
            beep();
        }
    }
    private void waitDigit2(char c) {
        if (Character.digit(c, 16) != -1) {
            buffer.insert(insertionPoint++, c);
            char codePoint = (char)getCodePoint(buffer, 2, 5);
            if (Character.isHighSurrogate(codePoint)) {
                format = SURROGATE_PAIR;
                buffer.append("\\u");
                insertionPoint = 8;
            } else {
                format = ESCAPE;
            }
            sendComposedText();
        } else {
            beep();
        }
    }
    private void waitBackSlashOrLowSurrogate(char c) {
        if (insertionPoint == 6) {
            if (c == "\\") {
                buffer.append(c);
                buffer.append("u");
                insertionPoint = 8;
                sendComposedText();
            } else if (Character.digit(c, 16) != -1) {
                buffer.append("\\u");
                buffer.append(c);
                insertionPoint = 9;
                sendComposedText();
            } else {
                beep();
            }
        } else {
            beep();
        }
    }
    /**
     * Send the composed text to the client.
     */
    private void sendComposedText() {
        AttributedString as = new AttributedString(buffer.toString());
        as.addAttribute(TextAttribute.INPUT_METHOD_HIGHLIGHT,
                        InputMethodHighlight.SELECTED_RAW_TEXT_HIGHLIGHT);
        context.dispatchInputMethodEvent(
                                  InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
                                  as.getIterator(), 0,
                                  TextHitInfo.leading(insertionPoint), null);
    }
    /**
     * Send the committed text to the client.
     */
    private void sendCommittedText() {
        AttributedString as = new AttributedString(buffer.toString());
        context.dispatchInputMethodEvent(
                                  InputMethodEvent.INPUT_METHOD_TEXT_CHANGED,
                                  as.getIterator(), buffer.length(),
                                  TextHitInfo.leading(insertionPoint), null);
        buffer.setLength(0);
        insertionPoint = 0;
        format = UNSET;
    }
    /**
     * Move the insertion point one position to the left in the composed text.
     * Do not let the caret move to the left of the "\\u" or "\\U".
     */
    private void moveCaretLeft() {
        int len = buffer.length();
        if (--insertionPoint < 2) {
            insertionPoint++;
            beep();
        } else if (format == SURROGATE_PAIR && insertionPoint == 7) {
            insertionPoint = 8;
            beep();
        }
        context.dispatchInputMethodEvent(
                                  InputMethodEvent.CARET_POSITION_CHANGED,
                                  null, 0,
                                  TextHitInfo.leading(insertionPoint), null);
    }
    /**
     * Move the insertion point one position to the right in the composed text.
     */
    private void moveCaretRight() {
        int len = buffer.length();
        if (++insertionPoint > len) {
            insertionPoint = len;
            beep();
        }
        context.dispatchInputMethodEvent(
                                  InputMethodEvent.CARET_POSITION_CHANGED,
                                  null, 0,
                                  TextHitInfo.leading(insertionPoint), null);
    }
    /**
     * Delete the character preceding the insertion point in the composed text.
     * If the insertion point is not at the end of the composed text and the
     * preceding text is "\\u" or "\\U", ring the bell.
     */
    private void deletePreviousCharacter() {
        if (insertionPoint == 2) {
            if (buffer.length() == 2) {
                cancelComposition();
            } else {
                // Do not allow deletion of the leading "\\u" or "\\U" if there
                // are other digits in the composed text.
                beep();
            }
        } else if (insertionPoint == 8) {
            if (buffer.length() == 8) {
                if (format == SURROGATE_PAIR) {
                    buffer.deleteCharAt(--insertionPoint);
                }
                buffer.deleteCharAt(--insertionPoint);
                sendComposedText();
            } else {
                // Do not allow deletion of the second "\\u" if there are other
                // digits in the composed text.
                beep();
            }
        } else {
            buffer.deleteCharAt(--insertionPoint);
            if (buffer.length() == 0) {
                sendCommittedText();
            } else {
                sendComposedText();
            }
        }
    }
    /**
     * Delete the character following the insertion point in the composed text.
     * If the insertion point is at the end of the composed text, ring the bell.
     */
    private void deleteCharacter() {
        if (insertionPoint < buffer.length()) {
            buffer.deleteCharAt(insertionPoint);
            sendComposedText();
        } else {
            beep();
        }
    }
    private void startComposition() {
        buffer.append("\\");
        insertionPoint = 1;
        sendComposedText();
    }
    private void cancelComposition() {
        buffer.setLength(0);
        insertionPoint = 0;
        sendCommittedText();
    }
    private void finishComposition() {
        int len = buffer.length();
        if (len == 6 && format != SPECIAL_ESCAPE) {
            char codePoint = (char)getCodePoint(buffer, 2, 5);
            if (Character.isValidCodePoint(codePoint) && codePoint != 0xFFFF) {
                buffer.setLength(0);
                buffer.append(codePoint);
          sendCommittedText();
                return;
            }
        } else if (len == 8 && format == SPECIAL_ESCAPE) {
            int codePoint = getCodePoint(buffer, 2, 7);
            if (Character.isValidCodePoint(codePoint) && codePoint != 0xFFFF) {
                buffer.setLength(0);
                buffer.appendCodePoint(codePoint);
          sendCommittedText();
                return;
            }
        } else if (len == 12 && format == SURROGATE_PAIR) {
      char[] codePoint = {
                (char)getCodePoint(buffer, 2, 5),
          (char)getCodePoint(buffer, 8, 11)
            };
            if (Character.isHighSurrogate(codePoint[0]) &&
                Character.isLowSurrogate(codePoint[1])) {
          buffer.setLength(0);
          buffer.append(codePoint);
          sendCommittedText();
                return;
            }
        }
        beep();
    }
    private int getCodePoint(StringBuffer sb, int from, int to) {
        int value = 0;
        for (int i = from; i <= to; i++) {
            value = (value<<4) + Character.digit(sb.charAt(i), 16);
        }
        return value;
    }
    private static void beep() {
        Toolkit.getDefaultToolkit().beep();
    }

    public void activate() {
        if (buffer == null) {
            buffer = new StringBuffer(12);
            insertionPoint = 0;
        }
    }
    public void deactivate(boolean isTemporary) {
        if (!isTemporary) {
            buffer = null;
        }
    }
    public void dispose() {
    }
    public Object getControlObject() {
        return null;
    }
    public void endComposition() {
        sendCommittedText();
    }
    public Locale getLocale() {
        return locale;
    }
    public void hideWindows() {
    }
    public boolean isCompositionEnabled() {
        // always enabled
        return true;
    }
    public void notifyClientWindowChange(Rectangle location) {
    }
    public void reconvert() {
        // not supported yet
        throw new UnsupportedOperationException();
    }
    public void removeNotify() {
    }
    public void setCharacterSubsets(Character.Subset[] subsets) {
    }
    public void setCompositionEnabled(boolean enable) {
        // not supported yet
        throw new UnsupportedOperationException();
    }
    public void setInputMethodContext(InputMethodContext context) {
        this.context = context;
    }
    /*
     * The Code Point Input Method supports all locales.
     */
    public boolean setLocale(Locale locale) {
        this.locale = locale;
        return true;
    }
}





TextLayout: draw(Graphics2D g2, float x, float y)

import java.awt.Container;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.font.TextLayout;
import javax.swing.JComponent;
import javax.swing.JFrame;
public class MainClass{
  public static void main(String[] args) {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    MyCanvas tl = new MyCanvas();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class MyCanvas extends JComponent {
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D)g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        RenderingHints.VALUE_ANTIALIAS_ON);
    
    String s = "www.jexp.ru";
    Font font = new Font("Serif", Font.PLAIN, 32);
    
    TextLayout textLayout = new TextLayout(s, font,
        g2.getFontRenderContext());
    textLayout.draw(g2, 40, 80);
  }
}





TextLayout: getAdvance()

import java.awt.Container;
import java.awt.Dimension;
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 java.util.Hashtable;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainClass {
  public static void main(String[] args) {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container c = f.getContentPane();
    c.add(new Justify());
    f.pack();
    f.setVisible(true);
  }
}
class Justify extends JPanel {
  final static int LEFT = 0;
  final static int RIGHT = 1;
  final static int CENTER = 2;
  final static int EQUALITY = 3;
  int justify = EQUALITY;
  public void paint(Graphics g) {
    Dimension size = getSize();
    String s = "To jexp.ru or not to jexp.ru, that is a question";
    Hashtable map = new Hashtable();
    map.put(TextAttribute.SIZE, new Float(32.0f));
    AttributedString as = new AttributedString(s, map);
    map = new Hashtable();
    map.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
    as.addAttributes(map, 33, 52);
    AttributedCharacterIterator aci = as.getIterator();
    int startIndex = aci.getBeginIndex();
    int endIndex = aci.getEndIndex();
    LineBreakMeasurer measurer;
    measurer = new LineBreakMeasurer(aci, new FontRenderContext(null, false, false));
    measurer.setPosition(startIndex);
    float wrappingWidth = (float) size.width;
    float Y = 0.0f;
    while (measurer.getPosition() < endIndex) {
      TextLayout layout = measurer.nextLayout(wrappingWidth);
      Y += layout.getAscent();
      float X = 0.0f;
      switch (justify) {
      case LEFT:
        if (layout.isLeftToRight())
          X = 0.0f;
        else
          X = wrappingWidth - layout.getAdvance();
        break;
      case RIGHT:
        if (layout.isLeftToRight())
          X = wrappingWidth - layout.getVisibleAdvance();
        else
          X = wrappingWidth;
        break;
      case CENTER:
        if (layout.isLeftToRight())
          X = (wrappingWidth - layout.getVisibleAdvance()) / 2;
        else
          X = (wrappingWidth + layout.getAdvance()) / 2 - layout.getAdvance();
        break;
      case EQUALITY:
        layout = layout.getJustifiedLayout(wrappingWidth);
      }
      layout.draw((Graphics2D) g, X, Y);
      Y += layout.getDescent() + layout.getLeading();
    }
  }
}





TextLayout: getAscent()

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.JComponent;
import javax.swing.JFrame;

public class MainClass {
  public static void main(String[] a) throws Exception {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    TextFormat tl = new TextFormat();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class TextFormat extends JComponent {
   List layouts;
   Font font = new Font("SansSerif", Font.BOLD, 42);
   String text = "The quick brown fox jumped over the lazy cow";
  public void paint(Graphics g) {
    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();
    }
  }
  private void getLayouts(Graphics g) {
    layouts = new ArrayList();
    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);
    }
  }
  
}





TextLayout: getDescent()

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.JComponent;
import javax.swing.JFrame;

public class MainClass {
  public static void main(String[] a) throws Exception {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    TextFormat tl = new TextFormat();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class TextFormat extends JComponent {
   List layouts;
   Font font = new Font("SansSerif", Font.BOLD, 42);
   String text = "The quick brown fox jumped over the lazy cow";
  public void paint(Graphics g) {
    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();
    }
  }
  private void getLayouts(Graphics g) {
    layouts = new ArrayList();
    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);
    }
  }
  
}





TextLayout: getJustifiedLayout(float justificationWidth)

import java.awt.Container;
import java.awt.Dimension;
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 java.util.Hashtable;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainClass {
  public static void main(String[] args) {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container c = f.getContentPane();
    c.add(new Justify());
    f.pack();
    f.setVisible(true);
  }
}
class Justify extends JPanel {
  final static int LEFT = 0;
  final static int RIGHT = 1;
  final static int CENTER = 2;
  final static int EQUALITY = 3;
  int justify = EQUALITY;
  public void paint(Graphics g) {
    Dimension size = getSize();
    String s = "To jexp.ru or not to jexp.ru, that is a question";
    Hashtable map = new Hashtable();
    map.put(TextAttribute.SIZE, new Float(32.0f));
    AttributedString as = new AttributedString(s, map);
    map = new Hashtable();
    map.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
    as.addAttributes(map, 33, 52);
    AttributedCharacterIterator aci = as.getIterator();
    int startIndex = aci.getBeginIndex();
    int endIndex = aci.getEndIndex();
    LineBreakMeasurer measurer;
    measurer = new LineBreakMeasurer(aci, new FontRenderContext(null, false, false));
    measurer.setPosition(startIndex);
    float wrappingWidth = (float) size.width;
    float Y = 0.0f;
    while (measurer.getPosition() < endIndex) {
      TextLayout layout = measurer.nextLayout(wrappingWidth);
      Y += layout.getAscent();
      float X = 0.0f;
      switch (justify) {
      case LEFT:
        if (layout.isLeftToRight())
          X = 0.0f;
        else
          X = wrappingWidth - layout.getAdvance();
        break;
      case RIGHT:
        if (layout.isLeftToRight())
          X = wrappingWidth - layout.getVisibleAdvance();
        else
          X = wrappingWidth;
        break;
      case CENTER:
        if (layout.isLeftToRight())
          X = (wrappingWidth - layout.getVisibleAdvance()) / 2;
        else
          X = (wrappingWidth + layout.getAdvance()) / 2 - layout.getAdvance();
        break;
      case EQUALITY:
        layout = layout.getJustifiedLayout(wrappingWidth);
      }
      layout.draw((Graphics2D) g, X, Y);
      Y += layout.getDescent() + layout.getLeading();
    }
  }
}





TextLayout: getLeading()

import java.awt.Container;
import java.awt.Dimension;
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 java.util.Hashtable;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainClass {
  public static void main(String[] args) {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container c = f.getContentPane();
    c.add(new Justify());
    f.pack();
    f.setVisible(true);
  }
}
class Justify extends JPanel {
  final static int LEFT = 0;
  final static int RIGHT = 1;
  final static int CENTER = 2;
  final static int EQUALITY = 3;
  int justify = EQUALITY;
  public void paint(Graphics g) {
    Dimension size = getSize();
    String s = "To jexp.ru or not to jexp.ru, that is a question";
    Hashtable map = new Hashtable();
    map.put(TextAttribute.SIZE, new Float(32.0f));
    AttributedString as = new AttributedString(s, map);
    map = new Hashtable();
    map.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
    as.addAttributes(map, 33, 52);
    AttributedCharacterIterator aci = as.getIterator();
    int startIndex = aci.getBeginIndex();
    int endIndex = aci.getEndIndex();
    LineBreakMeasurer measurer;
    measurer = new LineBreakMeasurer(aci, new FontRenderContext(null, false, false));
    measurer.setPosition(startIndex);
    float wrappingWidth = (float) size.width;
    float Y = 0.0f;
    while (measurer.getPosition() < endIndex) {
      TextLayout layout = measurer.nextLayout(wrappingWidth);
      Y += layout.getAscent();
      float X = 0.0f;
      switch (justify) {
      case LEFT:
        if (layout.isLeftToRight())
          X = 0.0f;
        else
          X = wrappingWidth - layout.getAdvance();
        break;
      case RIGHT:
        if (layout.isLeftToRight())
          X = wrappingWidth - layout.getVisibleAdvance();
        else
          X = wrappingWidth;
        break;
      case CENTER:
        if (layout.isLeftToRight())
          X = (wrappingWidth - layout.getVisibleAdvance()) / 2;
        else
          X = (wrappingWidth + layout.getAdvance()) / 2 - layout.getAdvance();
        break;
      case EQUALITY:
        layout = layout.getJustifiedLayout(wrappingWidth);
      }
      layout.draw((Graphics2D) g, X, Y);
      Y += layout.getDescent() + layout.getLeading();
    }
  }
}





TextLayout: getVisibleAdvance()

import java.awt.Container;
import java.awt.Dimension;
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 java.util.Hashtable;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainClass {
  public static void main(String[] args) {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container c = f.getContentPane();
    c.add(new Justify());
    f.pack();
    f.setVisible(true);
  }
}
class Justify extends JPanel {
  final static int LEFT = 0;
  final static int RIGHT = 1;
  final static int CENTER = 2;
  final static int EQUALITY = 3;
  int justify = EQUALITY;
  public void paint(Graphics g) {
    Dimension size = getSize();
    String s = "To jexp.ru or not to jexp.ru, that is a question";
    Hashtable map = new Hashtable();
    map.put(TextAttribute.SIZE, new Float(32.0f));
    AttributedString as = new AttributedString(s, map);
    map = new Hashtable();
    map.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
    as.addAttributes(map, 33, 52);
    AttributedCharacterIterator aci = as.getIterator();
    int startIndex = aci.getBeginIndex();
    int endIndex = aci.getEndIndex();
    LineBreakMeasurer measurer;
    measurer = new LineBreakMeasurer(aci, new FontRenderContext(null, false, false));
    measurer.setPosition(startIndex);
    float wrappingWidth = (float) size.width;
    float Y = 0.0f;
    while (measurer.getPosition() < endIndex) {
      TextLayout layout = measurer.nextLayout(wrappingWidth);
      Y += layout.getAscent();
      float X = 0.0f;
      switch (justify) {
      case LEFT:
        if (layout.isLeftToRight())
          X = 0.0f;
        else
          X = wrappingWidth - layout.getAdvance();
        break;
      case RIGHT:
        if (layout.isLeftToRight())
          X = wrappingWidth - layout.getVisibleAdvance();
        else
          X = wrappingWidth;
        break;
      case CENTER:
        if (layout.isLeftToRight())
          X = (wrappingWidth - layout.getVisibleAdvance()) / 2;
        else
          X = (wrappingWidth + layout.getAdvance()) / 2 - layout.getAdvance();
        break;
      case EQUALITY:
        layout = layout.getJustifiedLayout(wrappingWidth);
      }
      layout.draw((Graphics2D) g, X, Y);
      Y += layout.getDescent() + layout.getLeading();
    }
  }
}





TextLayout: hitTestChar(float x, float y)

import java.awt.Container;
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.JComponent;
import javax.swing.JFrame;
public class MainClass {
  public static void main(String[] args) {
    JFrame jf = new JFrame("Demo");
    Container cp = jf.getContentPane();
    MyCanvas tl = new MyCanvas();
    cp.add(tl);
    jf.setSize(300, 200);
    jf.setVisible(true);
  }
}
class MyCanvas extends JComponent {
  private TextLayout mTextLayout;
  private int mX = 40, mY = 80;
  public MyCanvas() {
    addMouseListener(new MouseAdapter() {
      public void mouseClicked(MouseEvent me) {
        TextHitInfo hit = mTextLayout.hitTestChar(me.getX() - mX, me.getY() - mY);
        System.out.println(hit.getCharIndex());
        System.out.println(hit.getInsertionIndex());
        System.out.println(hit.isLeadingEdge());
      }
    });
  }
  public void paint(Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
    String s = "www.jexp.ru";
    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);
  }
}





TextLayout: isLeftToRight()

import java.awt.Container;
import java.awt.Dimension;
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 java.util.Hashtable;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MainClass {
  public static void main(String[] args) {
    JFrame f = new JFrame();
    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Container c = f.getContentPane();
    c.add(new Justify());
    f.pack();
    f.setVisible(true);
  }
}
class Justify extends JPanel {
  final static int LEFT = 0;
  final static int RIGHT = 1;
  final static int CENTER = 2;
  final static int EQUALITY = 3;
  int justify = EQUALITY;
  public void paint(Graphics g) {
    Dimension size = getSize();
    String s = "To jexp.ru or not to jexp.ru, that is a question";
    Hashtable map = new Hashtable();
    map.put(TextAttribute.SIZE, new Float(32.0f));
    AttributedString as = new AttributedString(s, map);
    map = new Hashtable();
    map.put(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE);
    as.addAttributes(map, 33, 52);
    AttributedCharacterIterator aci = as.getIterator();
    int startIndex = aci.getBeginIndex();
    int endIndex = aci.getEndIndex();
    LineBreakMeasurer measurer;
    measurer = new LineBreakMeasurer(aci, new FontRenderContext(null, false, false));
    measurer.setPosition(startIndex);
    float wrappingWidth = (float) size.width;
    float Y = 0.0f;
    while (measurer.getPosition() < endIndex) {
      TextLayout layout = measurer.nextLayout(wrappingWidth);
      Y += layout.getAscent();
      float X = 0.0f;
      switch (justify) {
      case LEFT:
        if (layout.isLeftToRight())
          X = 0.0f;
        else
          X = wrappingWidth - layout.getAdvance();
        break;
      case RIGHT:
        if (layout.isLeftToRight())
          X = wrappingWidth - layout.getVisibleAdvance();
        else
          X = wrappingWidth;
        break;
      case CENTER:
        if (layout.isLeftToRight())
          X = (wrappingWidth - layout.getVisibleAdvance()) / 2;
        else
          X = (wrappingWidth + layout.getAdvance()) / 2 - layout.getAdvance();
        break;
      case EQUALITY:
        layout = layout.getJustifiedLayout(wrappingWidth);
      }
      layout.draw((Graphics2D) g, X, Y);
      Y += layout.getDescent() + layout.getLeading();
    }
  }
}