import java.io.*;
import java.util.*;


public class acVectorFont {
  static final float SCALE = 0.5f;

  static final int MOVETO = 0;
  static final int LINETO = 1;

  float x[][] = new float[256][50];
  float y[][] = new float[256][50];
  int kind[][] = new int[256][50];
  int numPoints[] = new int[256];
  float width[] = new float[256];
  float height[] = new float[256];

  float leading;
  float descent;
  float maxHeight;


  public acVectorFont(InputStream is) { //String name) {
    try {
      //InputStream is = getClass().getResourceAsStream(name);
      BufferedReader reader = new BufferedReader(new InputStreamReader(is));

      char currentLetter = 'a';
      float bigWidth = 0;
      float bigHeight = 0;
      int currentPoint = 0;

      String line = null;
      //System.out.println(is);
      //System.out.println(reader);
      while ((line = reader.readLine()) != null) {
        StringTokenizer st = new StringTokenizer(line);
        if (st.countTokens() < 2) continue;

        char what = st.nextToken().charAt(0);
        float nX, nY;

        switch (what) {
        case 'C':
          if (currentLetter != 0) {
            numPoints[currentLetter] = currentPoint;
            height[currentLetter] = bigHeight;
            if (width[currentLetter] == 0) {
              // support the old-school format, not for long
              width[currentLetter] = bigWidth * 1.5f;
            }
            currentPoint = 0;
          }
          currentLetter = st.nextToken().charAt(0);
          width[currentLetter] = 0;
          height[currentLetter] = 0;
          bigWidth = 0;
          bigHeight = 0;
          currentPoint = 0;
          break;

        case 'L':  // lineto
          nX = floater(st.nextToken());
          nY = floater(st.nextToken());
          kind[currentLetter][currentPoint] =
            (currentPoint == 0) ? MOVETO : LINETO; // bug workaround
          x[currentLetter][currentPoint] = nX * SCALE;
          y[currentLetter][currentPoint] = nY * SCALE;
          if (nX > bigWidth) bigWidth = nX;
          if (nY > bigHeight) bigHeight = nY;
          currentPoint++;
          break;

        case 'M':  // moveto
          nX = floater(st.nextToken());
          nY = floater(st.nextToken());
          kind[currentLetter][currentPoint] = MOVETO;
          x[currentLetter][currentPoint] = nX * SCALE;
          y[currentLetter][currentPoint] = nY * SCALE;
          if (nX > bigWidth) bigWidth = nX;
          if (nY > bigHeight) bigHeight = nY;
          currentPoint++;
          break;

        case 'W':  // width
          width[currentLetter] = floater(st.nextToken()) * SCALE;
          break;

        case 'D':  // leading
          leading = floater(st.nextToken()) * SCALE;
          break;

        case '#':  // comment
          break;

        default:  // fukkup
          System.err.println("duh.. error in font file");
        }
      }

      // cleanup for the last char read from the file
      if (currentLetter != 0) {
        numPoints[currentLetter] = currentPoint;
        height[currentLetter] = bigHeight;
        if (width[currentLetter] == 0) {
          // support the old-school format, not for long
          width[currentLetter] = bigWidth * 1.5f;
        }
      }
      descent = 0;
      maxHeight = 0;
      for (int i = 0; i < 256; i++) {
        for (int p = 0; p < numPoints[i]; p++) {
          if (y[i][p] < descent) descent = y[i][p];
          if (y[i][p] > maxHeight) maxHeight = y[i][p];
        }
      }
      if (leading == 0) {
        // default leading, if not defined in font
        leading = getHeight() * 1.2f;
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public float floater(String piss) {
    return new Float(piss).floatValue();
  }

  float getHeight() {
    return maxHeight + descent;
  }

  float charWidth(char c) {
    return (c != ' ') ? width[c] : charWidth('n');
  }


  int bcount;
  float bx1[], by1[], bx2[], by2[];

  public void buildString(String what, float startX, float startY) {
    bcount = 0; // reset
    char letters[] = what.toCharArray();

    bx1 = new float[128];
    by1 = new float[128];
    bx2 = new float[128];
    by2 = new float[128];

    float offsetX = startX;
    float offsetY = startY;

    for (int i = 0; i < letters.length; i++) {
      int index = (int) letters[i];
      for (int j = 0; j < numPoints[index]; j++) {
        buildStringPoint(kind[index][j], x[index][j] + offsetX,
                         y[index][j] + offsetY);
      }
      offsetX += charWidth(letters[i]);
    }
  }

  float curX, curY;
  protected void buildStringPoint(int kind, float x, float y) {
    if (kind == MOVETO) {
      curX = x;
      curY = y;
      return;
    }
    if (bcount == bx1.length) {
      float temp[];
      temp = new float[bcount*2];
      System.arraycopy(bx1, 0, temp, 0, bcount);
      bx1 = temp;
      temp = new float[bcount*2];
      System.arraycopy(bx2, 0, temp, 0, bcount);
      bx2 = temp;
      temp = new float[bcount*2];
      System.arraycopy(by1, 0, temp, 0, bcount);
      by1 = temp;
      temp = new float[bcount*2];
      System.arraycopy(by2, 0, temp, 0, bcount);
      by2 = temp;
    }
    bx1[bcount] = curX;
    by1[bcount] = curY;
    bx2[bcount] = x;
    by2[bcount] = y;
    curX = x;
    curY = y;
    bcount++;
  }
}
