package jmini3d;

import java.util.ArrayList;
import java.util.HashMap;

import jmini3d.geometry.SpriteGeometry;
import jmini3d.material.SpriteMaterial;

/**
 * http://www.angelcode.com/products/bmfont/doc/file_format.html
 */
public class Font {

	public class CharSprite {
		int x;
		int y;
		int width;
		int height;
		int xoffset;
		int yoffset;
		int xadvance;
		int page;
		int chnl;
	}

	public class Kerning {
		char first;
		char second;
		int amount;
	}

	int lineHeight, base, scaleW, scaleH, pages, packed, alphaChnl, redChnl, greenChnl, blueChnl;
	ArrayList<Texture> textures = new ArrayList<Texture>();

	HashMap<Character, CharSprite> chars = new HashMap<Character, CharSprite>();
	ArrayList<Kerning> kernings = new ArrayList<Kerning>();

	public Font() {

	}

	public void setCommon(int lineHeight, int base, int scaleW, int scaleH, int pages, int packed, int alphaChnl, int redChnl, int greenChnl, int blueChnl) {
		this.lineHeight = lineHeight;
		this.base = base;
		this.scaleW = scaleW;
		this.scaleH = scaleH;
		this.pages = pages;
		this.packed = packed;
		this.alphaChnl = alphaChnl;
		this.redChnl = redChnl;
		this.greenChnl = greenChnl;
		this.blueChnl = blueChnl;
	}

	public void addPage(int id, String file) {
		Texture texture = new Texture(file);
		textures.add(texture);
	}

	public void addChar(int id, int x, int y, int width, int height, int xoffset, int yoffset, int xadvance, int page, int chnl) {
		CharSprite cs = new CharSprite();
		char theChar = Character.toChars(id)[0];
		cs.x = x;
		cs.y = y;
		cs.width = width;
		cs.height = height;
		cs.xoffset = xoffset;
		cs.yoffset = yoffset;
		cs.xadvance = xadvance;
		cs.page = page;
		cs.chnl = chnl;
		chars.put(theChar, cs);
	}

	public void addKerning(int first, int second, int amount) {
		Kerning kerning = new Kerning();
		kerning.first = Character.toChars(Integer.valueOf(first))[0];
		kerning.second = Character.toChars(Integer.valueOf(second))[0];
		kerning.amount = Integer.valueOf(amount);
		kernings.add(kerning);
	}

	public Object3d getTextLine(String text) {
		return getTextLine(text, null);
	}

	public Object3d getTextLine(String text, Rect fontMetrics) {
		int length = text.length();
		SpriteGeometry geometry = new SpriteGeometry(text.length());

		int x = 0;
		int y = 0;
		char oldChar = (char) -1;
		for (int i = 0; i < length; i++) {
			char c = text.charAt(i);
			CharSprite cs = chars.get(c);
			if (cs == null) {
				System.out.print("Character " + c + " not found in bitmap texture");
				continue;
			}
			// Check kernings


			geometry.addSprite(x + cs.xoffset, y + cs.yoffset, x + cs.xoffset + cs.width + 1, y + cs.yoffset + cs.height + 1, //
					Utils.p(cs.x, scaleW), Utils.p(cs.y, scaleH), Utils.p(cs.x + cs.width + 1, scaleW), Utils.p(cs.y + cs.height + 1, scaleH));
			x += cs.xadvance;
			oldChar = c;
		}
		if (fontMetrics != null) {
			fontMetrics.right = x;
			fontMetrics.bottom = lineHeight;
		}
		return new Object3d(geometry, new SpriteMaterial(textures.get(0)));
	}

	public void clear() {
		textures.clear();
		chars.clear();
		kernings.clear();
	}
}

@@ -2522,26 +2522,114 @@
 %0A%09%09%09
-// Check kernings%0A
+for (Kerning k : kernings) %7B%0A%09%09%09%09if (k.first == oldChar && k.second == c) %7B%0A%09%09%09%09%09x += k.amount;%0A%09%09%09%09%7D%0A%09%09%09%7D
 %0A%0A%09%09
@@ -2705,20 +2705,16 @@
 cs.width
- + 1
 , y + cs
@@ -2733,20 +2733,16 @@
 s.height
- + 1
 , //%0A%09%09%09
@@ -2755,16 +2755,20 @@
 s.p(cs.x
+ + 1
 , scaleW
@@ -2782,16 +2782,20 @@
 s.p(cs.y
+ + 1
 , scaleH

Check kernings and fix position in texture (starting in 1)