Need advice: Textfield, incorrect cursor position with different font

I used the Angel plugin to create a new font. This font I have loaded to the lemur textfield.

With the new font the cursor position is not shown correctly.

In picture: above new font style, down: standard style.

I tried to track the problem down and it might come from

com/simsilica/lemur/component/TextEntryComponent.java

    protected float getVisibleWidth( String text ) {
    float x = font.getLineWidth(text + " ");
    x -= font.getLineWidth(" ");
    //x += 1;
    float scale = bitmapText.getSize() / font.getPreferredSize();
    x *= scale;
    return x;
}

The font.getPreferedSize returns an size that make a scale here. I have followed the font.getPreferredSize() and in the end the PreferredSize is loaded directly from the font in one of the fontloader/bitmap classes.

I am lost here and not sure where the error might be.
Right now it is just the X position of the cursor, so it might be possible that there is a difference between X and Y “getSize()” and "getPreferredSize()?

Any suggestions or hints how to set the cursor position right.

Probably the plugin has generated the font incorrectly. Maybe try the original AngelCode font generator or Heiro. (Hiero?)

That being said, BitmapText is kind of broken in some ways so there may be little that Lemur can do about it.

I have used Hiero and recreated the font (after testing a bit more in lemur).
I thought I found the solution when I created the font file with a huge size (see picture).

But unfortunately the more text you write the more it can be seen, that the text and cursor position dont match.
I have tried with another font (Verdana) and got the same result.

It seems that except the JME standard font all the others are scaled with an deviation, that is smaller the bigger the initial font size was choosen.

I think there is no solution here at that point. At least when a cursor is in place or there is a need to get the textsize it seems to be better to rely on JME standard font.

The SDK has a font creator, have you tired it to see if you get the same result?

I have used the SDK plugin first. The result is the same.

I use lots of different fonts and don’t seem to have this issue. There must be something else at play with how you’ve setup the GUI elements or font or something.

(see bottom of image for the chat bar) I used the AngelCode font generator for that one. But I’d expect similar results with HIero.

 @Override
    public void simpleInitApp() {
        GuiGlobals.initialize(this);
        GuiGlobals globals = GuiGlobals.getInstance();
        BaseStyles.loadGlassStyle();
        globals.getStyles().setDefaultStyle("glass");

         BitmapFont myFont = assetManager.loadFont("Interface/Antique.fnt");
    //    BitmapFont myFont = assetManager.loadFont("Interface/Verdana.fnt");
    C1 = new Container();
        getGuiNode().attachChild(C1);


        C1.setLocalTranslation(300,800,0);
        TextField test = new TextField("LMAA-sehr langer TextNEU", new ElementId("textField"));    
  	test.setSingleLine(false);
        C1.addChild(test);
	test.setFont(myFont);

       TextField test2 = new TextField("LMAA-sehr langer Text ALT", new ElementId("textField"));
       test2.setPreferredLineCount(5);
       test2.setSingleLine(false);
       C1.addChild(test2);

    }

The example is simple like that.

I register the path with
assetManager.registerLocator(url, FileLocator.class);

load that font and then its like that. If it is working for everyone else it must be the font. But I expected that at least the standard Verdana taken with the SDK plugin or Hiero (I did both) is working.

Is the font you are using available? Or let me ask differently. Can you provide me a working non standard JME font so I can test it?

I put that font here:

BitmapText, for whatever reason, uses a completely different loop to calculate the width of a piece of text than it does to actually lay out the text (one of the things that I’m fixing in my eventual refactoring). I’ve worked to make these loops as similar as possible but there may be things about a font that mess with one or the other.

Is there some reason you can’t try the AngelCode font generator?
http://www.angelcode.com/products/bmfont/

Is there some reason you can’t try the AngelCode font generator?

No. But when I used Google (Angelcode font etc.) I did not get that link… Thats Tunisia and tunisian google :-), even the advertisement is in Arabic.

I will check everything and post my findings.

I have tried the Angelcode with different standard fonts (Times, Arial, Verdana). I have not changed the options and settings. Still the cursor is not positioned correct.

Edit 2:

I have tried the font you have provided…
Even there the cursor is not positioned correct. The (last of 3) pictures showing the anita font with the line home key hit. If you enter a character it wont be placed there etc.

I have no explaination for that? I am using an old used business win7 laptop here. I am using the unchanged lemur library.

Just in case I have the exact same issue. It looks very odd, but I thought that did something wrong somewhere, but seems not. I did the font with the jme SDK.

Can you post a single class complete test case that illustrates the issue using the anita font?

package demo;

import com.jme3.app.SimpleApplication;
import com.jme3.asset.plugins.FileLocator;
import com.jme3.font.BitmapFont;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.GuiGlobals;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.TextField;
import com.simsilica.lemur.event.CursorEventControl;
import com.simsilica.lemur.event.DragHandler;
import com.simsilica.lemur.style.BaseStyles;
import com.simsilica.lemur.style.ElementId;



public class Neues_Text extends SimpleApplication {


    protected Container C1;

    public Neues_Text(){
    }
    public static void main(String... args) {
        Neues_Text main = new Neues_Text();
        main.start();
    }

    @Override
    public void simpleInitApp() {
        GuiGlobals.initialize(this);
        GuiGlobals globals = GuiGlobals.getInstance();
        BaseStyles.loadGlassStyle();
        globals.getStyles().setDefaultStyle("glass");

        String s = System.getProperty("user.dir");
        assetManager.registerLocator(s, FileLocator.class);
        BitmapFont myFont = assetManager.loadFont("Interface/anita30.fnt");
   //    BitmapFont myFont = assetManager.loadFont("Interface/Times.fnt");


        C1 = new Container();
        getGuiNode().attachChild(C1);
        C1.setLocalTranslation(300,500,0);
        TextField test = new TextField("This is the anita30 font, that I just downloaded", new ElementId("textField"));
        test.setPreferredLineCount(5);
        test.setSingleLine(false);
        C1.addChild(test);

        // C1.addChild(new Label("Just to move"));
        // CursorEventControl.addListenersToSpatial(C1, new DragHandler());
        test.setFont(myFont);

        TextField test2 = new TextField("This is the unchanged JME Font", new ElementId("textField"));
        test2.setPreferredLineCount(5);
        C1.addChild(test2);
    }
    @Override
    public void simpleUpdate(float tpf) {
    }
}

During the course of that topic I have put that class directly in the original lemur → right here

It is the 100% github version

Note for the future:

I am warming up this topic, as I might have found the error causing the problem. I will also provide a solution and a workaround.

The problem is indeed in the getVisibleWidth() method in the TextEntryComponent

As you see in my case I have created a textfield and then changed the Font of the textfield

 TextField test = new TextField("This is the anita30 font, that I just downloaded", new ElementId("textField"));
...
 test.setFont(myFont);

This call finally leads to:

Unfortunately the font is not reset (while the bitmapText is).
Therefore after changing a font of a textField with that method, the calculatinon of the size of text (and cursorposition etc.) is still using the parameters of the initial font with that the textField was created.

I am sure @pspeed you did not have this issue as you was using a style on your textFields and already created them with the new font and never changed it after creation. Anyhow this is how I figured it out.

A solution is to add a line

this.font = font;

in the setFont() method of the TextEntryComponent.java.

If someone dont like to change the lemur sources, he might change the style of a textfield before creating it insteadt of using the setFont() of the textField.

 Styles style = GuiGlobals.getInstance().getStyles();
 Attributes attrs = style.getSelector("textField", "glass");
 attrs.set("font",myFont);

Unfortunately this way you are stil not able to change a font of a textfield after creation.

3 Likes

Good find!

If you submit a PR with this one line change then I will apply it right away. Else I will add this to my list of things to fix when I get a block of “Lemur time”.

Edit: bonus points if you add a line to the release notes file in your PR. :slight_smile:

2 Likes