Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate Fonts in the plugin #726

Closed
davesmith00000 opened this issue Apr 16, 2024 · 1 comment
Closed

Generate Fonts in the plugin #726

davesmith00000 opened this issue Apr 16, 2024 · 1 comment

Comments

@davesmith00000
Copy link
Member

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:

  1. As above.
  2. 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)
  3. Instead of rendering immediately, use the glyph info to render SDF data.
@davesmith00000
Copy link
Member Author

Will be in the next release.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant