I haven't tried this (by @mprevel), but it's an interesting idea and work looking into.
import java.awt._
import java.awt.image._
import java.io._
import javax.imageio.ImageIO
object Font2Bitmap {
val fontFile = "some.ttf"
val fontSize = 24
val charaterCodes = 32 to 255
val charactersPerLine = 16
val color = Color.BLACK
val antiAlias = true
def main(args: Array[String]): Unit =
try {
val font =
Font
.createFont(Font.TRUETYPE_FONT, new File(fontFile))
.deriveFont(fontSize.toFloat)
val tmpBuffer = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB)
val tmpG2d = tmpBuffer.createGraphics()
tmpG2d.setFont(font)
val fontMetrics = tmpG2d.getFontMetrics()
val charWidth = fontMetrics.charWidth('A')
val charHeight = fontMetrics.getHeight()
tmpG2d.dispose()
val width = charWidth * charactersPerLine
val height = charHeight * ((charaterCodes.size + charactersPerLine - 1) / charactersPerLine)
val bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB)
val g2d = bufferedImage.createGraphics()
if (antiAlias)
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON)
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY)
g2d.setFont(font)
g2d.setColor(color)
val baselineOffset = fontMetrics.getLeading() + fontMetrics.getAscent()
charaterCodes.foreach { code =>
val n = code - charaterCodes.start
val c = code.toChar.toString
val x = (n % charactersPerLine) * charWidth
val y = (n / charactersPerLine) * charHeight + baselineOffset
g2d.drawString(c, x, y)
}
g2d.dispose()
val file = new File(s"output_${fontSize}.png")
ImageIO.write(bufferedImage, "PNG", file)
} catch {
case e: Exception => e.printStackTrace()
}
}
println(
s"""
| val width = ${width}
| val height = ${height}
| val charWidth = ${charWidth}
| val charHeight = ${charHeight}
| val perLine = ${charactersPerLine}
| val startAt = ${charaterCodes.start}
| val endAt = ${charaterCodes.end}
|
| def fontChar(i: Int) = {
| val n = i - startAt
| FontChar(
| character = i.toChar.toString,
| x = n % perLine * charWidth,
| y = n / perLine * charHeight,
| width = charWidth,
| height = charHeight
| )
| }
|
| FontInfo(fontKey, Size(width, height), fontChar(63), Batch.fromSeq((startAt to endAt).map(fontChar)), caseSensitive = true)
|""".stripMargin
)
Short of doing real GPU text rendering, we could generate font sheets + info in the plugin based on a TTF. Producing them for fixed sizes is perfectly ok.
The road to GPU font's might be:
As above.
Alter to read glyph info output to code, and have indigo do something like the above onload (requires render targets?). Since we only need pixel art, this may not be too bad (if pixel inside glphy then render else dispose)
Instead of rendering immediately, use the glyph info to render SDF data.
I haven't tried this (by @mprevel), but it's an interesting idea and work looking into.
Short of doing real GPU text rendering, we could generate font sheets + info in the plugin based on a TTF. Producing them for fixed sizes is perfectly ok.
The road to GPU font's might be: