TTF in nifty

Hello everybody.

I was looking for a way to use some ttf font on nifty and it appears that nifty only support the angelfont format.

I am not a pro in font format. However, i know that i can use a lot of fonts with awt and the awt is often included with the java distribution.

Ok, i made a little thing, i know it’s not perfect at all, but it’s something.

First, some “raw code”. The explanation come just after.

In the XML File:

<registerEffect name=“TTFRenderer” class=“mygame.test.NTTFyDisplayer” />

<panel id=“testTTF” align=“center” valign=“top” childLayout=“center” text=“hello” font-family=“arial-bold-16”>
<effect>
<onActive name=“TTFRenderer” post=“true” />
</effect>
</panel>

NTTFyDisplayer
[java]
package mygame.test;

import com.jme3.niftygui.RenderImageJme;
import com.jme3.texture.Image;
import com.jme3.texture.Texture2D;
import com.jme3.texture.plugins.AWTLoader;
import de.lessvoid.nifty.Nifty;
import de.lessvoid.nifty.effects.EffectImpl;
import de.lessvoid.nifty.effects.EffectProperties;
import de.lessvoid.nifty.effects.Falloff;
import de.lessvoid.nifty.elements.Element;
import de.lessvoid.nifty.render.NiftyImage;
import de.lessvoid.nifty.render.NiftyRenderEngine;
import de.lessvoid.nifty.spi.render.RenderImage;
import de.lessvoid.xml.xpp3.Attributes;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.image.BufferedImage;

/**
*

  • @author Bubuche
    */
    public class NTTFyDisplayer implements EffectImpl
    {
    private NiftyImage nimage;
    private String precedentTexte;
    private Dimension preferredSize;

public NTTFyDisplayer()
{
nimage = null;
precedentTexte = “”;
preferredSize = new Dimension();
}

public void activate(Nifty nifty, Element element, EffectProperties parameter)
{
}

public void execute(Element element, float effectTime, Falloff falloff, NiftyRenderEngine r)
{
Attributes attributes = element.getElementType().getAttributes();
String text = attributes.get(“text”);
String fontFamily = attributes.get(“font-family”);
if ( nimage == null || ! text.equals(precedentTexte) )
{
BufferedImage bi;
bi = TTFToImage.instance.toImage(text, Font.decode(fontFamily), Color.white);
preferredSize.setSize(bi.getWidth(), bi.getHeight());

  Image jmeI = new AWTLoader().load(bi, true);
  Texture2D t2d = new Texture2D(jmeI);
  RenderImage ri = new RenderImageJme(t2d);
  nimage = new NiftyImage(r, ri);
  precedentTexte = text;
}

element.setWidth(preferredSize.width);
element.setHeight(preferredSize.height);
r.renderImage(nimage, element.getX(), element.getY(), element.getWidth(), element.getHeight());

}

public void deactivate()
{
}
}
[/java]

TTFToImage.java
[java]
package mygame.test;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;

/**
*

  • @author Bubuche
    */
    public class TTFToImage
    {
    public static final TTFToImage instance = new TTFToImage();

public BufferedImage toImage(String text, Font font, Color color)
{

FontRenderContext f = new FontRenderContext(null, false, false);
TextLayout tl = new TextLayout(text, font, f);

Rectangle2D r2d = tl.getBounds();

int width = (int)Math.ceil(r2d.getWidth());
int height = (int)Math.ceil(r2d.getHeight());

BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

Graphics g = image.getGraphics();
g.setFont(font);
g.setColor(color);
g.drawString(text, 0, height);

return image;

}
}
[/java]

I think it’s all.

The basic idea is :

  1. in ntfy it’s possible to handle the whole rendering with a control.
  2. it’s possible to draw a text with a font offscreen, on a bufferedimage.
  3. it’s possible to convert a bufferedimage to something useable in nifty.
  4. java.awt.Font has a method (“decode”) that take a “fontfamily-style-pointsize” in paramter and return the font (usabl with the graphics class of awt etc.). For more information about it : http://docs.oracle.com/javase/1.5.0/docs/api/java/awt/Font.html#decode(java.lang.String)

So, what i do is :
in the xml, i create a panel that has a “onActivate” that call the controller.
the controller read the text and the font and draw the image on the screen.

This is not perfect.

As you can see, even if i said “align=“center”” i have a left alignement. This is because i change the width of the panel, and so the panel is no longer as large as the screen.
Also, i tried to put a “\n” in the text but it didn’t work.
I have to work on this more, but i would be happy to have some feedback about it.

Thanks for reading.

2 Likes

Uhm, you can convert any font you have installed on the computer via “New File → Font” :slight_smile: This is cool nonetheless, though it will only work on desktop because of the awt dependency. Good job :slight_smile:

One advantage of this approach though is that it will cope with all characters the font copes with rather than being limited to those in the bitmap font…