/*
   A Simple class to demonstrate kludged kerning of an AttributedString
*/
import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.text.*;
import java.io.*;
import java.util.*;
import com.sun.glf.*;
import com.sun.glf.util.*;
import javax.swing.*;
public class Kerning extends JComponent {

   LayerComposition comp = null;

   public static void main(String argv[]) {

      Kerning kern = new Kerning();
      final Composition comp = kern.generateComposition();
      JFrame frame = new JFrame() {
                  public void paint(Graphics g) {
                          super.paint(g);
                          Graphics2D g2 = (Graphics2D)g;
                          g2.translate(50,50);
                          g2.scale(2.0,2.0);
                          g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
                          comp.paint(g2);
                      }
             };
      frame.setBounds(100,100,250,250);
      frame.setVisible(true);
      }

   public Kerning() {
      }

   private Composition generateComposition() {
      comp = new LayerComposition(new Dimension(200,200));
      comp.setLayers(new Layer[]{generateTextLayer(comp)});
      add(new CompositionComponent(comp),BorderLayout.CENTER);
      return comp;
      }
   private Layer generateTextLayer(LayerComposition parent) {
      String text = "Java2D";
      Integer spacing = new Integer(5);
      text = doStringSpacing(text,spacing.intValue());
          Shape shape = null;
          if( text.length() > 0 ) {
             AttributedString ats = new AttributedString(text);
             int j = 0;
                 if(spacing.intValue() > 0 )
                while(j<text.length() && (j = text.indexOf('\uFFFC',j))!=-1 ) {
                       ats.addAttribute(TextAttribute.CHAR_REPLACEMENT,spacer,j,(j+1));
                           j++;
                           }
         shape = TextLayer.makeTextBlock(new AttributedString[]{ats},Float.MAX_VALUE,TextAlignment.LEFT);
         }


      com.sun.glf.Renderer render = new FillRenderer(Color.black);
      Layer layer = new ShapeLayer(parent,shape,render,null);
      return layer;
      }
        /*
           Parse string adding a \uFFFC after each character
           for replacement with a GraphicAttribute later on..
        */
        private static String doStringSpacing(String s, int space) {
                StringBuffer sb = new StringBuffer();
                String _s = "";
                for(int i=0; i<space; i++) {
                   _s+="\uFFFC";
                   }
                for(int i=0; i<(s.length()); i++) {
                   sb.append(s.charAt(i));
                   if( s.length() != i ) sb.append(_s);
                   }
                return sb.toString();
           }

   Spacer spacer = new Spacer();
   /*
      A Simple spacer, takes up a single metric unit width...
   */
   class Spacer extends GraphicAttribute {
      float space = 1.0f;
      Rectangle2D bounds = null;
      public Spacer() {
         this(1.0f);
         }
      public Spacer(float f) {
         super(GraphicAttribute.CENTER_BASELINE);
         this.space=f;
         bounds = new Rectangle2D.Float(0f,0f,f,f);
         }
      public void draw(Graphics2D g, float x, float y) {
          // This class draws nothing, simply
          // acts as a 'spacer' to space between glyphs
         }
      public void draw(Graphics2D g) {
         }
      public float getAscent() {
             return (float) Math.max(0, -bounds.getMinY());
         }
      public float getDescent() {
             return (float) Math.max(0, bounds.getMaxY());
         }
      public float getAdvance() {
             return (float) Math.max(0, bounds.getMaxX());
         }
      public Rectangle2D getBounds() {
             return bounds;
         }
      }
   }