How to get the natural fontsize of bitmapfont? - libgdx

If I have a bitmapfont such as;
fonttexture = new Texture(Gdx.files.internal("data/fonttest.png"), true);
font= new BitmapFont(Gdx.files.internal("data/fonttest.fnt"),
new TextureRegion(fonttexture ), true);
Is it possible to retrieve or deduce the natural fontsize used on the associated png texture file?
The *.fnt file itself specifies this on the first line;
info face="Calibri Light" size=32 bold=0 italic=0 charset=""
Its that 32 I am after in code.
I couldn't see a method on BitmapFonts class to directly get it, but there was various other height related attributes possible to get.
I tried recreating the size from those but didn't have much luck.
float baseToAssent = font.getCapHeight()+font.getAscent();
float baseToDecent = -font.getDescent();Decent);
float fontHeight = baseToAssent+baseToDecent; //too small, like 11 not 32
Not being a fonttographer? fontophile?...umm...graphic designer, I am probably putting the pieces together wrong, or maybe just lacking one.
In either case, any way to work out the font size used in the fonttest.png would be helpful.
Thanks
Usecase;
I am manually using that texture with a distance field shader. Knowing the textures natural font size is useful in order to accurately scale the text and lineheight to any requested font size without ever resizing a image and thus losing quality.

Not sure how to get the font size specific, however you can easily get the String width and height of a font using a GlyphLayout, like this:
BitmapFont font = new BitmapFont(Gdx.files.internal("data/fonttest.fnt", false);
GlyphLayout glyph = new GlyphLayout(font, "TextMessage");
float width = glyph.width;
float height = glyph.height;
Read this topic if you want to learn more about GlyphLayout and BitmapFont.
Experimented quite a bit with a 32px font, like yours. The String "W" seemed to be 29px wide, which was the widest I could find, so it's definately not precise if what you want to archive is the size exactly.
You could do a little hacky method, reading the .fnt file as a text file and looking for the Integer after "size=", pretty much like a properties file work, it will be less efficient but will return exact value.

Related

Is it possible to change the size of Heiro generated font in the code?-LibGdx

I am using a font generated by Heiro tool.
game.scoreFont = new BitmapFont(Gdx.files.internal("fonts/score.fnt"), false);
I applied it for a label;
private void drawScore() {
Label.LabelStyle scoreStyle = new Label.LabelStyle();// style
scoreStyle.font = game.scoreFont;
scoreLabel2 = new Label(scoreController.getScoreString(), scoreStyle);// label
scoreLabel2.setPosition(scoreBox.getX()+scoreBox.getWidth()/2.7f,scoreBox.getY()+scoreBox.getHeight()/2);
scoreLabel2.setAlignment( Align.center);
}
While generating font,I gave a size of 32.
But same font I want to use for a label somewhere else in the game ,with a little bit bigger size.
Is it possible to increase the size then?or Should I generate a new font of required size with Heiro tool again?
You can scale your BitmapFont by
bitmapFont.getData().setScale(2);
and then use this font in LabelStyle, however you can also scale in this way
labelStyle.font.getData().setScale(2);
It works on reference of BitmapFontso it scaled everywhere, where you're using that BitmapFont in your game.
So you can create two object of BitmapFont with same file and scale one font and use where you want bigger font.
I'll recommend you to create two font with different size using your tools. Scaling is never a good solution.

Can I change LibGDX Label lineHeight temporarily?

I have a bitmap font built with Hiero, which I'm using in scene2d Labels.
In a single Label instance I need to reduce the font's lineHeight value, but I'd like to leave the other Labels (which are using the same font) intact, so they should keep the default lineHeight of the font.
I've tried to simply adjust the value like this:
label.getStyle().font.getData().setLineHeight(localReducedValue);
However, this has modified all the Labels everywhere -- which, in retrospect, seems logical, since I'm modifying the LabelStyle itself.
Unfortunately something like label.setLineHeight(localReducedValue) doesn't exist, so at this point I see two possible solutions:
Create a copy of the font, set its lineHeight to the value I need, and create a separate LabelStyle with that font; or
Write a custom Label for myself which implements setLineHeight.
The first idea seems wasteful, the second is likely a bit complicated, so I'm hoping there's an easier way of achieving a temporary lineHeight in Labels.
Nathan Sweet, one of LibGDX's core developers has kindly suggested a solution, which is working perfectly:
Override Label#layout, set line height, call super.layout, set line height back. You need to use layout and not draw because layout computes and caches the glyph positions, draw just draws them.
You can change the LabelStyle of a single Label by doing something like this:
//skin is the skin that you use
Label myLabel = new Label(text, new LabelStyle(skin.get(LabelStyle.class)));
And then you can modify the style without affecting all the labels.

Text scaling and positioning in libgdx

I am working with libgdx. I need to scale and position text. Let's say I want to draw X that is 30 pixels hight and I want it to be in the middle of the screen. I want to draw more of those in diffrent locations and with different scales.
Is there any way how could I achieve that? I can't find the solution anywhere. I dont want to create more BitmapFonts if possible.
If you want to handle all platforms (android, html, ios, desktop) you need to use several BitmapFonts in order to avoid ugly scaling. Otherwise, if you don't need to deploy to HTML, you can use the gdx-freetype extension (see here https://github.com/libgdx/libgdx/wiki/Gdx-freetype).
Assuming you go with BitmapFont, you can simply use code similar to this to center your text:
String text = "Your text here!";
TextBounds bounds = font.getBounds(text);
font.draw(batch, text, (width - bounds.width) / 2.0f, (height - bounds.height) / 2.0f);
For scaling, you can set the scale in font.draw, but you probably want several BitmapFont of various sizes to avoid ugly artifacts.

How get a string width in Libgdx?

I wonder know how to get the width of my string in pixels
BitmapFont API < 1.5.6
To mesure the width of a String you use your Font and get the bounds of the String, you are going to draw.
BitmapFont.getBounds(String str).width
BitmapFont API
You can get the height to for the right offset for drawing too. Just replace width with height.
In addition for multiline texts use getMultiLineBounds(someString).width to get the bounds.
BitmapFont API >= 1.5.6
The BitmapFont API changed in 1.5.7 so there is a different way to get the bounds now:
BitmapFont.TextBounds and getBounds are done. Instead, give the string to GlyphLayout and get the bounds using its width and height fields. You can then draw the text by passing the same GlyphLayout to BitmapFont, which means the glyphs don’t have to be laid out twice like they used to.
Source (Web archive)
Example:
GlyphLayout layout = new GlyphLayout(); //dont do this every frame! Store it as member
layout.setText("meow");
float width = layout.width;// contains the width of the current set text
float height = layout.height; // contains the height of the current set text
According to #Nates answer: https://stackoverflow.com/a/20759876/619673 calling method
BitmapFont.getBounds(String str).width
not always returns proper width! Especially when you are reusing font.
If you want draw text for example in the center of part of view port, you can avoid this problem by using another method
BitmapFont.drawWrapped(...)
Example code:
font.drawWrapped(spriteBatch, "text", x_pos, y_pos, your_area_for_text, BitmapFont.HAlignment.CENTER);
If you use skins in UI it is a hassle to find out the correct font to feed into the GlyphLayout.
In this case I use a throw away instance of Label to figure everything out for me then ask the Label for the width.
Skin skin = getMySkin();
Label cellExample = new Label("888.88888", skin);
cellExample.layout();
float cellWidth = cellExample.getWidth();
Table table = new Table(skin);
table.defaults().width(cellWidth);
// fill table width cells ...
This is not the answer if you want to position the text yourself, but it is useful to make a UI layout stable and less dependent on the actual content of the cells.

Comparing two bitmaps against each other for match as3

I'm trying to position an image on top of another image based upon the make-up of the smaller image. The smaller image is a cut-out of a larger image and I need it to be positioned exactly on the larger image to make it look like a single image, but allow for separate filters and alphas to be applied. As the images are not simple rectangles or circles, but complex satellite images, I cannot simply redraw them in code. I have quite a few images and therefore do not feel like manually finding the position of each image every and hard setting them manually in actionscript. Is there any way for me to sample a small 5-10 sq. pixel area against the larger image and set the x and y values of the smaller image if a perfect match is found? All the images are in an array and iterating through them has already been set, I just need a way to sample and match pixels. My first guess was to loop the images pixel by pixel right and down, covering the whole bitmap and moving to the next child in the array once a match was found, leaving the matched child where it was when the perfect match was found.
I hope I understood your question correctly.
There may be an option that uses copypixels to achieve what you want. You can use the bitmapdata.rect value to determine the size of the sample you want, and loop through the bigger bitmap using thet rectangle and a moving point. Let's see if I can code this out...
function findBitmapInBitmap(tinyimg:BitmapData, largeimg:BitmapData):Point {
var rect:Rectangle = tinyimg.rect;
var xbound:uint = largeimg.rect.width;
var ybound:uint = largeimg.rect.height;
var imgtest:BitmapData = new BitmapData(tinyimg.rect.width, tinyimg.rect.height);
for (var ypos:uint = 0, y <= ybound, y++) {
for (var xpos:uint = 0, x <= xbound, x++) {
imgtest.copyPixels(largeimg, rect, new Point(xpos, ypos);
if (imgtest.compare(tinyimg) == 0) return new Point(xpos, ypos);
}
}
return new Point(-1,-1); // Dummy value, indicating no match.
}
Something along those lines should work - I'm sure there's room for code elegance and possible optimization. However, it seems like something like this method would be very slow, since you'd have to check each pixel for a match.
There is a better way. Split your big image into layers, and use the blitting technique to composite them at runtime. In your case, you could create a ground texture without satellites, and then create the satellites separately, and use the copyPixels method to place them whereever you want. Google "blitting in as3" to find some good tutorials. I'm currently working on a game project that uses this technique and it's a very good method.
Good luck!
Edit: Forgot to code in a default return statement. Using this method, you'd have to return an invalid point (like (-1,-1)) and check for it outside the function. Alternatively, you could just copy your small bitmap to the big one within the function, which would be much more logical, but I don't know your requirements.
You need to find pixel sequence in the big image. BitmapData.getPixel gives you pixel value. So get first pixel from small image, find it in big image, then continue comparing until you find full match. If you have trouble to code that, feel free to ask.
For the actual comparison, there's BitmapData.compare which returns the number 0 if the BitmapData objects are equivalent.