Way to know text width and height before displaying it

Hello, I stopped at this little problem when coding today:

    Is there a way to know exactly the width and height that the TextObject will have BEFORE I call

    display.newText()?

I know this may not be the right place to ask this question, as the Corona may not mount the rendered text with it’s own API, but instead, using the Opengl API… (still, i have no idea how it does this magic spell)

But still, is there a way without using the Corona API? Like, knowing where the bitmap fonts are and loading them to see their properties, or having some kind of formula for the texture size, etc… Is there some way to do this?

For 1 single font it would be easy to solve it, but as there are many fonts inside an application, and in some devices, there may not have some fonts available, I wanted to know if there is a ready algorithm or an easy way to solve this.

Thanks!

Well, you can just create the text, get the width and height and immediately destroy it. Then I guess from there recalculate the font size and create the real text.

I tend to just scale the text down if I need it to fit in a certain space and it doesn’t at a scale of 1.

Thanks for the reply!

Yes… I know it can be done that way, but for doing that lots of times, wouldn’t it cause some kind of lag in the application?

What I want to do is use this to format my text in a easy way. I’m creating a function that agrupates lots of displayText objects and mounts them at the screen. But as I would be doing that, I would call display.newText() and display.remove() many times… Wouldn’t it sound a problem?

After some time thinking, yes, I would display every single text, so I could just render them and keep positioning until they are all OK. But, the reason I’m doing this is to fix a limitation inside the API, which is     you can’t create a single TextObject with diferent colors     .

So, I would like to break the string for a better concat in the screen if possible, and for that I would like to check if the textObject created has a greater width than the area I want right now (I want to create my own text wrapping).

I know it sounds complicated, but it’s like this:

I have some kind of list of strings:

list = {

    “asd”, “gfh”, “zxc”,

}

and I want to display them as if it was a single textObject.

in the screen: “asdgfhzxc”

But, as i call my function to render it, I would have the option to color these small strings inside the list with different colors:

list = {

     {“asd”, {1, 0, 0}},

     {“gfh”,  {0, 1, 0}},

     {“zxc”, {0, 0, 1}},

}

So as i display it, it would be like this: “asdgfhzxc”

But there are larger textObjects, that are way to big. And if you set a width to text parameters, the resultant textObject will automatically wrap, and I wanted some kind of way to know where exactly is should be wrapping, so I can separate the strings and don’t lose any position when mounting the formatted textObject.

Giant_String = “asdasdadadasdasdasdadaadsads”

display.newText({

    text = Giant_String,

    width = 100,

})

In the screen:

                 100 px

|--------------------------------------|

asdasdadadasdasdasdadaad  <- here it wraps.   I wanted to know where in the string it happens before calling display.newText()

sads

So, that’s why I think your answer doesn’t solve so much of my problem, as I would call this too many times, the game or application would have too much unnecessary lag…

But, if there is a way to do this, pls tell me, that’s the reason i’m asking this question!

You can’t get the exact width and height before you create it. But you can easily guess an approximate value.

The widest characters, W and M are basically squares, so using that information, you can use the font point size as a starting basis. Of course letters like I (uppercase Eye) and l (lower case el) are really narrow, so the average character width will naturally be less than the point size, but there is spacing between the letters which makes the actual width wider. 

So if I have a string of 20 characters at 15 points, would be approximately 300 px wide for most normal fonts. If you’re using a condensed font or a title font that’s naturally wider than the M’s and W’s being square, you would potentially want to factor that in.

As for height, you will have characters with descenders and you have some vertical spacing too, so you could use a guestimate of 1.25x point size and get close. But we actually have API’s to get the font metrics which will give you the height information for the font.

See: http://docs.coronalabs.com/api/library/graphics/getFontMetrics.html

Rob

Hello Rob, thanks for the reply!

  1. I really didn’t see that graphics function at all… I will research more about it.
  2. As I was trying to make a text wrapper, well, I’m trying another way I found out, which is descripted below.

The way I found, which is not so much difficult, is to begin with an empty textObject string, and keep concatenating it until it reaches the maximum width. The real problem is that it will generate multiple textObject (for each line), that, according to this blog’s post (https://coronalabs.com/blog/2013/06/26/wednesday-faqs-display-text-objects/), creating many display text objects can consume lots of memory and slows down the app…

The only reason I wanted that was to pass a string and see where the string with many letters would wrap given a width property. Then I could know how many times the given string would wrap, and how much was each Y coordinate of each line inside the textObject.

With this information, I could simply render the entire string instead of chunks of lines to simulate the wrapping (which is what i’m doing right now). And finally with that, I could render multi-colored textObjects. But yeah, didn’t work that way it seems.

I actually could do what I described above without knowing the font’s dimensions, but I would call display.newText() and display.remove() many times, what would be very costy in the performance of the application.

(Edit)

After some time thinking, your answer does solve my secondary question about the wrapper. That’s just so silly… It’s like, only after I write all of that, and make my wrap function to work, I understand how to do it with some simple calls.

Unfortunately, there is not a way to change the width property of the textObject after creation, but simply removing it and displaying another one does the trick.

What I should do, is call display.newText() to the text without the width set. Then call it again in another variable, but now, with the width property on.

Then, with the ‘leading’ and ‘center object’ values, I can calculate the Y coordinate of each line, with no need to create a wrapper…

Thanks!

Well, you can just create the text, get the width and height and immediately destroy it. Then I guess from there recalculate the font size and create the real text.

I tend to just scale the text down if I need it to fit in a certain space and it doesn’t at a scale of 1.

Thanks for the reply!

Yes… I know it can be done that way, but for doing that lots of times, wouldn’t it cause some kind of lag in the application?

What I want to do is use this to format my text in a easy way. I’m creating a function that agrupates lots of displayText objects and mounts them at the screen. But as I would be doing that, I would call display.newText() and display.remove() many times… Wouldn’t it sound a problem?

After some time thinking, yes, I would display every single text, so I could just render them and keep positioning until they are all OK. But, the reason I’m doing this is to fix a limitation inside the API, which is     you can’t create a single TextObject with diferent colors     .

So, I would like to break the string for a better concat in the screen if possible, and for that I would like to check if the textObject created has a greater width than the area I want right now (I want to create my own text wrapping).

I know it sounds complicated, but it’s like this:

I have some kind of list of strings:

list = {

    “asd”, “gfh”, “zxc”,

}

and I want to display them as if it was a single textObject.

in the screen: “asdgfhzxc”

But, as i call my function to render it, I would have the option to color these small strings inside the list with different colors:

list = {

     {“asd”, {1, 0, 0}},

     {“gfh”,  {0, 1, 0}},

     {“zxc”, {0, 0, 1}},

}

So as i display it, it would be like this: “asdgfhzxc”

But there are larger textObjects, that are way to big. And if you set a width to text parameters, the resultant textObject will automatically wrap, and I wanted some kind of way to know where exactly is should be wrapping, so I can separate the strings and don’t lose any position when mounting the formatted textObject.

Giant_String = “asdasdadadasdasdasdadaadsads”

display.newText({

    text = Giant_String,

    width = 100,

})

In the screen:

                 100 px

|--------------------------------------|

asdasdadadasdasdasdadaad  <- here it wraps.   I wanted to know where in the string it happens before calling display.newText()

sads

So, that’s why I think your answer doesn’t solve so much of my problem, as I would call this too many times, the game or application would have too much unnecessary lag…

But, if there is a way to do this, pls tell me, that’s the reason i’m asking this question!

You can’t get the exact width and height before you create it. But you can easily guess an approximate value.

The widest characters, W and M are basically squares, so using that information, you can use the font point size as a starting basis. Of course letters like I (uppercase Eye) and l (lower case el) are really narrow, so the average character width will naturally be less than the point size, but there is spacing between the letters which makes the actual width wider. 

So if I have a string of 20 characters at 15 points, would be approximately 300 px wide for most normal fonts. If you’re using a condensed font or a title font that’s naturally wider than the M’s and W’s being square, you would potentially want to factor that in.

As for height, you will have characters with descenders and you have some vertical spacing too, so you could use a guestimate of 1.25x point size and get close. But we actually have API’s to get the font metrics which will give you the height information for the font.

See: http://docs.coronalabs.com/api/library/graphics/getFontMetrics.html

Rob

Hello Rob, thanks for the reply!

  1. I really didn’t see that graphics function at all… I will research more about it.
  2. As I was trying to make a text wrapper, well, I’m trying another way I found out, which is descripted below.

The way I found, which is not so much difficult, is to begin with an empty textObject string, and keep concatenating it until it reaches the maximum width. The real problem is that it will generate multiple textObject (for each line), that, according to this blog’s post (https://coronalabs.com/blog/2013/06/26/wednesday-faqs-display-text-objects/), creating many display text objects can consume lots of memory and slows down the app…

The only reason I wanted that was to pass a string and see where the string with many letters would wrap given a width property. Then I could know how many times the given string would wrap, and how much was each Y coordinate of each line inside the textObject.

With this information, I could simply render the entire string instead of chunks of lines to simulate the wrapping (which is what i’m doing right now). And finally with that, I could render multi-colored textObjects. But yeah, didn’t work that way it seems.

I actually could do what I described above without knowing the font’s dimensions, but I would call display.newText() and display.remove() many times, what would be very costy in the performance of the application.

(Edit)

After some time thinking, your answer does solve my secondary question about the wrapper. That’s just so silly… It’s like, only after I write all of that, and make my wrap function to work, I understand how to do it with some simple calls.

Unfortunately, there is not a way to change the width property of the textObject after creation, but simply removing it and displaying another one does the trick.

What I should do, is call display.newText() to the text without the width set. Then call it again in another variable, but now, with the width property on.

Then, with the ‘leading’ and ‘center object’ values, I can calculate the Y coordinate of each line, with no need to create a wrapper…

Thanks!