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 :
- in ntfy it’s possible to handle the whole rendering with a control.
- it’s possible to draw a text with a font offscreen, on a bufferedimage.
- it’s possible to convert a bufferedimage to something useable in nifty.
- 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.