blob: 17c804f78587dc3de3f72b7020218ca5a5f51118 [file] [log] [blame] [raw]
package li.cil.oc.client.gui
import net.minecraft.client.renderer.GLAllocation
import net.minecraft.client.renderer.Tessellator
import net.minecraft.client.renderer.texture.TextureManager
import net.minecraft.util.ResourceLocation
import org.lwjgl.opengl.GL11
object MonospaceFontRenderer {
private val font = new ResourceLocation("opencomputers", "textures/font/ascii.png")
private var instance: Option[Renderer] = None
def init(textureManager: TextureManager) =
instance = instance.orElse(Some(new Renderer(textureManager)))
val (fontWidth, fontHeight) = (5, 9)
def drawString(value: Array[Char], x: Int, y: Int) = instance match {
case None => // Do nothing, not initialized.
case Some(renderer) => renderer.drawString(value, x, y)
}
private class Renderer(private val textureManager: TextureManager) {
/** Display lists, one per char (renders quad with char's uv coords). */
private val charLists = GLAllocation.generateDisplayLists(256)
/** Buffer filled with char display lists to efficiently draw strings. */
private val listBuffer = GLAllocation.createDirectIntBuffer(512)
// Set up the display lists.
{
// The font texture is 16x12, but chars are really only 10x12.
val charsPerRow = 16
val (charWidth, charHeight) = (MonospaceFontRenderer.fontWidth * 2, MonospaceFontRenderer.fontHeight * 2)
val uStep = 1.0 / charsPerRow
val vStep = 1.0 / 12 * 240 / 256 // Correct for padding at bottom.
val uOffset = uStep * 3 / 16
val uSize = uStep * 10 / 16
val vOffset = vStep * 1 / 20
val vSize = vStep * 18 / 20
val t = Tessellator.instance
// Special case for whitespace: just translate, don't render.
GL11.glNewList(charLists + 32, GL11.GL_COMPILE)
GL11.glTranslatef(charWidth, 0, 0)
GL11.glEndList()
// Now create lists for all printable chars.
for (index <- (33 until 0x7F).union(0x9F until 0xFF)) {
// The font texture does not contain the 0-1F range, nor the 0x7F to
// 0x9F range (control chars as per Character.isISOControl).
val textureIndex =
(if (index - 32 >= 0x7F) index - (0x9F - 0x7F) else index) - 32
val x = textureIndex % charsPerRow
val y = textureIndex / charsPerRow
val u = x * uStep + uOffset
val v = y * vStep + vOffset
GL11.glNewList(charLists + index, GL11.GL_COMPILE)
t.startDrawingQuads()
t.addVertexWithUV(0, charHeight, 0, u, v + vSize)
t.addVertexWithUV(charWidth, charHeight, 0, u + uSize, v + vSize)
t.addVertexWithUV(charWidth, 0, 0, u + uSize, v)
t.addVertexWithUV(0, 0, 0, u, v)
t.draw()
GL11.glTranslatef(charWidth, 0, 0)
GL11.glEndList()
}
}
def drawString(value: Array[Char], x: Int, y: Int) = {
setTexture(textureManager, MonospaceFontRenderer.font)
GL11.glPushMatrix()
GL11.glTranslatef(x, y, 0)
GL11.glScalef(0.5f, 0.5f, 1)
GL11.glColor4f(1, 1, 1, 1)
for (c <- value) {
listBuffer.put(charLists + c)
if (listBuffer.remaining == 0)
flush()
}
flush()
GL11.glPopMatrix()
}
private def flush() = {
listBuffer.flip()
GL11.glCallLists(listBuffer)
listBuffer.clear()
}
}
private def setTexture(tm: TextureManager, resource: ResourceLocation) = tm.bindTexture(resource)
}