# Improve bisection method or alternate algorithm for efficient determination of text font size to fit in a box

I need to find the font size of a text that fits in a box.

Given my current font size, I can get the bounding rectangle of the text.

If I set some arbitrary min and max font size, I suppose I can increment or decrement my font size until I get to the given box.

I am thinking bisection method:

ChangeFontMethod(float currentFont, float reqWidth)

float minFont = 1, maxFont = 1000
int tolerance = 0.001, maxIter = 1000
int n = 1

float currentWidth = textWithCurrentFont.boundingRect.Width

do
if currentWidth = reqWidth
break
else if currentWidth < reqWidth
minFont = currentFont
else
maxFont = currentFont

if maxFont - minFont < tolerance
break

currentFont = (minFont + maxFont)/2
currentWidth = textWithCurrentFont.boundingRect.Width
n++

while n <= maxIter

return currentFont


From what I read it should have logarithmic speed, but also I read that it is "slow"

Is there a better way ?

I don't know if I can improve my search by assuming a relationship between font size and font width - definitely there is one, but it's non-linear. So I don't know how to even improve the speed by a better "first guess"

• The relationship between font "size" and font width may not actually be linear, but it will be approximately linear. Commented Jul 1, 2015 at 15:22
• @JohnR.Strohm I have tried to just multiply my current font with the reqWidth/curentWidth ratio... the results are way off the scale. The font changes a lot slower. It doesn't help that, based on the text contents, some letters are taking less space than others, so the relationship between font size and text width is affected not only by the amount of text, but also by the actual letters used, as well as font type. That's why I have to approximate.. iterate... guess... Commented Jul 1, 2015 at 15:23
• So if the current box is too large currentWidth > reqWidth then you search in the larger interval with [currentFont, maxFont]? And if it is too small you search in the smaller interval [minFont, currentFont]? Isn't that backwards? Commented Jul 1, 2015 at 15:53
• @dpmcmlxxvi Fixing, thanks - that's what I meant but my subroutine for translating thoughts to pseudocode is buggy Commented Jul 1, 2015 at 17:25
• Bisection requires that you have the final solution bracketed, but otherwise assumes nothing about the form of the solution. If you know something about the form of the solution, you also have a way of estimating where to look for the solution. Use that to guess your new font, rather than just bisecting, and iterate, and you have what numerical analysis people call the "false position method". (Note: Hamming's "modified false position method" is better. Newton's method is far better, but you don't have the derivative available.) Commented Jul 1, 2015 at 18:54

I am not going to code it but I will give you a math approach. Assuming you know the resulting width with two different font sizes:
font size 1 (s1) implies text width 1 (w1) (the small value)
font size 2 (s2) implies text width 2 (w2) (the bigger value)
then your linear estimate of size (s3) that will fit the required width (w) is from using manipulating this formula:
(s3-s1)/(s2-s1)=(w-w1)/(w2-w1)
so estimate correct width is
s3 = s1+(w-w1)*(s2-s1)/(w2-w1)

now you check w3 (the width when using s3). If w < w3 then repeat the method but using s1,w1,s3,w3 if w > w3 then repeat the method but using s3,w3,s2,w2.
This iterative approach only requires that the width for a given text is a monotonic function of the font size, in other words doesn't matter if linear but it will converge faster if the function is closer to linear, so it will accelerate convergence as the range of font sizes reduces.

• Thank you, looks very logical, I will try implementing when I get a chance Commented Jul 1, 2015 at 19:09
• In this answer should font size 2 be using the variables s2, w2? Commented Jul 2, 2015 at 0:45
• Related question: What kind of transform is this? Commented Jul 2, 2015 at 0:46