private int buildFontCache(RenderingHints hints) {
		Rectangle2D maxbounds = font.getMaxCharBounds(new FontRenderContext(new AffineTransform(), false, false));
		int width = (int) Math.ceil(maxbounds.getWidth() + 2);
		int height = (int) Math.ceil(maxbounds.getHeight() + 2);

		BufferedImage texture = new BufferedImage(width * 10, height * 10, BufferedImage.TYPE_INT_ARGB);

		int x = 0;
		int y = 0;

		for(int i = 32; i < 127; ++i) {
			/* clear the buffer */
			BufferedImage buffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
			Graphics2D gx = buffer.createGraphics();
			gx.setBackground(TRANSPARENT);
			gx.clearRect(0, 0, buffer.getWidth(), buffer.getHeight());
			gx.setColor(Color.WHITE);
			gx.setRenderingHints(hints);
			gx.setFont(font);

			char[] chr = new char[] { (char) i };

			FontMetrics fm = gx.getFontMetrics();
			Rectangle2D rect = fm.getStringBounds(chr, 0, 1, gx);

			gx.drawChars(chr, 0, 1, 0, -(int) rect.getY());
			gx.dispose();

			BufferedImage sub = buffer.getSubimage((int) rect.getX(), 0, (int) rect.getWidth(), (int) rect.getHeight());

			if(x + sub.getWidth() > texture.getWidth()) {
				x = 0;
				y += height;
			}

			Rectangle irect = new Rectangle(x, y, sub.getWidth(), sub.getHeight());
			bounds[i] = irect;

			gx.dispose();
			gx = texture.createGraphics();
			gx.drawImage(sub, x, y, null);

			// get ready for the next
			x += irect.width + 1;
		}

		width = texture.getWidth();
		height = texture.getHeight();
		int bufferSize = width * height;

		xscale = 1.0 / width;
		yscale = 1.0 / height;

		IntBuffer buf = BufferUtils.createIntBuffer(bufferSize);
		{
			int[] abuf = texture.getRGB(0, 0, width, height, null, 0, width);
			for(int i = 0; i < abuf.length; ++i) {
				buf.put(abuf[i]);
			}
		}
		buf.flip();

		int textureID = glGenTextures();
		glBindTexture(GL_TEXTURE_2D, textureID);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);

		return textureID;

	}