We are about to switch to a new forum software. Until then we have removed the registration on this forum.
I am using the following text() signature:
text(str, x1, y1, x2, y2);
where: x1 and y2 are cordinates of the text box and x2 and y2 are width and height of text box
I would like the font to have the highest possible size for which it still fits entirely into the text box specified by x2 and y2. I cannot use trial and error to determine the right font size - the String length varies, so the font size must be adapted each time the String length is altered.
The width and height of the box are constant - so the font size depends on them, not the other way around.
I was wondering if there was a simple method to achieve this?
I tried finding a formula for the font size but didn't succeed since the text size in this context depends on many factors:
Do you know the solution to this problem? Maybe there is a built in Processing method that does that?
Answers
Hey,
you can use textWidth() wo get the width of a string with the current text-size. Adding textAscent() textDescent() will give you its height.
The default text-size is 12, so you can calculate the rest from there.
Example:
Thanks for your answer.
However, your code seems to put the entire string into one line. What I wanted to achieve, is that the entre string (which is a sentence, so it has several words) populates the entire box. That is, the text size could be bigger because it could be distributed among several lines if the the text height allows for it.
Do you know a solution to that?
I need to think about it but
1) the number of lines of text depend on the font size
2) changing the font size alters the text width
3) changing the text width can change the number lines ....back to (1)
@benja that was a nice solution I will be very impressed if you come up with a multi-line solution that uses word boundary line breaks.
Uh... multiline... hmm, that is more complicated, but not impossible. Starting to think about it.
Thanks for your replies.
My very rough estimate was the following:
Assumtion: - each char is a square box with side equal to textSize (in pixels). [This assumption is wrong, but, given a long enough String the average value of side of such a box is probably around textSize.]
The area of the entire text box is widthheight. [A = wh;] The number of chars in the String is str.length(); [wlength = str.length();]
The average area per char is the entire area divided by number of chars [a = A/wlength]
The average area per char is equal to textSize^2.
Therefore:
textSize = sqrt((w * h)/wlength);
Now, this "analysis" did not take into account a number of other factors, such as the ones I enumerated originally. Therefore, I introduce a constant c1 that will more or less make up for this. This constant is determined by experiment for each font and should be good enough so that when the string length changes, the string still fits into the box while having the greatest possible font size.
The result is:
If you change the string length, the width or height, you will see that the text size adapts and should fit into the square. You might have to alter the value of the constant originally.
Sadly, this seems inaccurate and would give different results depending on the word-lengths and line-breaks.
I think the only way to do this is to split the text into words and recreate the lines word by word and test when the text will exceed the boundaries of the box. Here is a draft, open for discussion, imporovements and ideas:
This works great, thanks!
Plus the search takes only about 0.0001s for short Strings to about 0.005s for long sentences to execute, so it can be used without slowing down the program.
I will try and see if there is any potential for improvement but the code works great for now.
I think such a method should be added to the Processing library as it is extremely useful.
I have tried that also, but apparently I made things over complicated :)
The code is posted in this related trhead:
http://forum.processing.org/two/discussion/11654/how-to-count-line-feeds#Comment_47074