472,958 Members | 2,305 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,958 software developers and data experts.

How to calculate font size for a string to make it fit into a rectangle of a fixed size.

This is how I do it now.

1. Determine the dimensions of the rectangle.

2. Set a my font size to a fixed maximum size.

3. Apply the font my string and measure the string using the graphics
object.

4. If string size is less than the size of the rectangle, we are done.

5. Loop, subtracting one from the size of the font until the sting size
measures less than the size of the rectangle.

6. Draw the string in the rectangle.

The result is that the font scales the string to fit inside of the
rectangle. The trouble with this method is that it is rather slow due
to the loop. I would rather determine the size of the font needed for
the string based on the area of the rectangle and simply apply that
font size to the string. This has proven to be more difficult than I
expected. The trial and error used in the method above, however crude,
works. It's just slow.

Dec 8 '06 #1
7 43621
<ca*******@gmail.comwrote in message
news:11**********************@f1g2000cwa.googlegro ups.com...
[...]
The result is that the font scales the string to fit inside of the
rectangle. The trouble with this method is that it is rather slow due
to the loop. I would rather determine the size of the font needed for
the string based on the area of the rectangle and simply apply that
font size to the string.
Unfortunately, other than trial-and-error, I don't think there's a way to do
what you want. You can make some reasonably good guesses about the size of
a rendered string based on the size of that string at a given font size, but
it won't scale perfectly.

That said, you can certainly improve upon the method you're using now. One
way would be to use a binary search technique. Pick a size (perhaps your
"fixed maximum size", for example), and then do a binary search on the font
size until it just barely fits. In pseudocode:

sizeMac = sizeMax;
sizeMin = 1; // or whatever suitable minimum size applies in your case
sizeCur = (sizeMin + sizeMac) / 2;
while (sizeMin != sizeMac)
{
if (FTextFits(sizeCur))
{
sizeMin = sizeCur;
}
else
{
sizeMac = sizeCur - 1;
}
sizeCur = (sizeMin + sizeMac) / 2;
}

I might have an off-by-one error in there somewhere, but hopefully you get
the idea.

Another method would be to calculate a scale based on the difference between
the desired text size and the actual text size. For example, if you have a
rectangle 100 pixels wide, and the text at the maximum size is 150 pixels
wide, you might scale the maximum font size by the 2/3rds that is the ratio
of those two sizes (100/150). From there, you should be within a few points
of the correct size, which should be quicker to test.

Finally, you could combine the two methods. While there is no exact way to
predict the size of text drawn at one size based on how large it is at
another size, it will always be close. You could use the scaling method to
determine a good guess, then start your binary search with the minimum and
maximum some fixed percentage away from that guess. Not that the binary
search will ever take that many iterations anyway, but doing this will
reduce that number even further.

Of course, it should go without saying that you should perform this
calculation as infrequently as possible. Only when the destination drawing
rectangle actually does change in size should you do it. As long as the
destination remains the same size, you should cache the correct font size
and use that instead of recalculating each time.

Pete
Dec 8 '06 #2
"Peter Duniho" <Np*********@NnOwSlPiAnMk.comwrote:
>Another method would be to calculate a scale based on the difference between
the desired text size and the actual text size.
This is what I've done. If I remember correctly, it pretty much works
first time so I never even bothered with subsequent refinement.

--
Lucian
Dec 8 '06 #3
"Lucian Wischik" <lu***@wischik.comwrote in message
news:il********************************@4ax.com...
"Peter Duniho" <Np*********@NnOwSlPiAnMk.comwrote:
>>Another method would be to calculate a scale based on the difference
between
the desired text size and the actual text size.

This is what I've done. If I remember correctly, it pretty much works
first time so I never even bothered with subsequent refinement.
As I mentioned, it will always get you close. But you have no guarantee
that the resulting value will be exactly the largest size that would fit,
nor even that it will fit (a few pixels may be truncated, or the text might
wrap if you've selected that formatting option).
Dec 9 '06 #4
"Peter Duniho" <Np*********@NnOwSlPiAnMk.comwrote in message
news:12*************@corp.supernews.com...
>This is what I've done. If I remember correctly, it pretty much works
first time so I never even bothered with subsequent refinement.

As I mentioned, it will always get you close. But you have no guarantee
that the resulting value will be exactly the largest size that would fit,
nor even that it will fit (a few pixels may be truncated, or the text
might wrap if you've selected that formatting option).
One more follow-up...

In the interest of quantifying the statement I made, I wrote a small program
that tests all of the fonts on the computer for all calculated widths and
font sizes from the smallest to largest.

The basic algorithm:

For every font family installed:
Find the width of the font at 128 points
For every possible width between 1/128th of the max width and the
max width:
Calculate a new font size based on the ratio of the target width
to the max width
Find the actual width of the font for that calculated font size

Note: where I write "font size" what I actually mean is the width of a
sample string, arbitrarily chosen, at a given font size.

I divided the results into three categories:

* calculated font size definitely fit
* calculated font size might not fit
* calculated font size definitely does not fit

The "might not" comes about because for fractional widths, I don't know what
the defined Windows behavior is, and there may not in fact be a defined
behavior when the necessary width for a string is some fractional amount
larger than the desired size. For the sake of discussion, I assumed that
half of the "might nots" actually do result in display truncation or
unwanted wrapping, adding that half to the "definitely does not" for the
purpose of calculating error rates.

I tried a variety of methods, each variation involving truncating one or
more parts of the calculation (there were three places that the supporting
calculations could be truncated: the max width of the string, the calculated
font size, and the end result of the width for the string at the calculated
size).

Interestingly, the *best* results occurred when I truncated all of the
results of the calculations, including the target font size. One of the
worst outcomes was when the widths were truncated, but the font size was
not. This isn't entirely unexpected, since truncation of the font size and
the final width makes the string more likely to fit by making it slightly
smaller.

Generally speaking, the string fails to fit into the target width roughly
somewhere between 5% and 35% of the time, depending on how the calculations
are done (yes, I realize that's a huge variance).

For extra credit, I also added a histogram display to show me roughly what
range of scaling causes the most error. Not surprisingly, the results are
heavily weighted toward the larger scales (that is, a target font size
closer to the maximum). I say "not surprisingly", because it stands to
reason that when the absolute sizes are larger, small variations in
percentage are more likely going to result in multi-pixel errors.
Interestingly, the outcome here wasn't perfectly smooth, and in fact had
peaks and valleys for some calculation variations (for example, truncating
everything resulted in the bin for 88-91% scaling having more occurences
than either of the two higher bins).

Note that this weighting towards the sizes closer to the maximum means that
the error rate may be significantly higher than the stated "5% to 35%" when
considering scenarios in which the font size needs to be reduced only a
small amount.

Finally, I also tried calculating the target font size based on the Pixels
unit rather than Point unit. This did result in a significant improvement
in speed, but otherwise the basic results were very similar (slightly
"smoother" as far as the histogram goes, but otherwise basically the same).

Anyway, I hope that this helps illustrate the underlying problem. IMHO, the
main lessons to take away are:

* A straight calculation _can_ result in the incorrect answer
* You are more likely to get the incorrect answer when the string only
has to shrink a little bit and/or when the maximum size is large

I wish that there was a more reliable way to make a string fit in a specific
area, but at some point one really does need to do some trial and error
calculations to ensure that the font size chosen really does result in the
displayed string fitting entirely within the target rectangle. Otherwise,
your code is not assured of working 100% of the time.

Pete
Dec 13 '06 #5
A better way would be to use the MeasureString or equivalent GDI method
to find the width of a string using your current font. Then, use that
width to calculate the ratio by which you need to scale your font.

The fomula is:

CurrentWidth = MeasureString(myString, myFont).Width
newFontSize = CurrentFontSize * (DesiredWidth / CurrentWidth)
The following is an example in VB.NET.

Using g As Graphics = Me.CreateGraphics()
Dim w As Integer = g.MeasureString("HELLO WORLD",
Me.Font).Width
Me.Font = New Font(Me.Font.FontFamily, Me.Font.Size *
CSng(Me.Width / w), Me.Font.Style, Me.Font.Unit)
End Using

Dec 28 '06 #6
JR
And then if the result is too large reduce the points by 1.

JR

<fe*************@gmail.comwrote in message
news:11**********************@n51g2000cwc.googlegr oups.com...
>A better way would be to use the MeasureString or equivalent GDI method
to find the width of a string using your current font. Then, use that
width to calculate the ratio by which you need to scale your font.

The fomula is:

CurrentWidth = MeasureString(myString, myFont).Width
newFontSize = CurrentFontSize * (DesiredWidth / CurrentWidth)
The following is an example in VB.NET.

Using g As Graphics = Me.CreateGraphics()
Dim w As Integer = g.MeasureString("HELLO WORLD",
Me.Font).Width
Me.Font = New Font(Me.Font.FontFamily, Me.Font.Size *
CSng(Me.Width / w), Me.Font.Style, Me.Font.Unit)
End Using

Dec 28 '06 #7
<fe*************@gmail.comwrote in message
news:11**********************@n51g2000cwc.googlegr oups.com...
>A better way would be to use the MeasureString or equivalent GDI method
to find the width of a string using your current font. Then, use that
width to calculate the ratio by which you need to scale your font.

The fomula is:

CurrentWidth = MeasureString(myString, myFont).Width
newFontSize = CurrentFontSize * (DesiredWidth / CurrentWidth)
If you had bothered to read the discussion in this thread, you would
understand that that's not a reliable way to do it. You're not even
guaranteed to be within one pixel (as "JR" implies).
The following is an example in VB.NET. [...]
Why are you posting VB code in a C# newsgroup?

Pete
Dec 28 '06 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

21
by: Arthur Connor | last post by:
I want to embed some source code lines in an article on a web page. As usual I want to use a fixed sized font for this souce code lines (read: the letters should have all the same width). The...
6
by: erdem | last post by:
hi all, i guess this question had been asked many times but i couldnt find a way how can we generate a struct with managed code with fixed size i mean struct easy {
13
by: cvh | last post by:
Hello, In delphi I could do this : Var Str: String (String of size 2char) How would I do this with VB.NET in CF? Thank you,
0
by: Ken Varn | last post by:
I have a managed C++ assembly in which I need to interact with some 'C' APIs that take fixed size 'C' data blocks. I need to wrap these data blocks into a managed object. It seems like a lot of...
2
by: neuneudr | last post by:
Hi everybody, I'm scratching my head with a CSS problem. I want to have the following (the two pics have these size for a good reason, the whole point of the page is basically to show these...
3
by: patl | last post by:
Hi all, I am trying to write a terminal emulator using Javascript + AJAX and I need to create an 80x25 table (each cell contains 1 character) in which I can update the contents of each cell...
1
by: shofu_au | last post by:
Hi Group, I am trying to define a class that has a fixed size array of a structure containing a fixed size array of a structure. I am using System.Runtime.InteropServices and trying to define...
2
by: Jack | last post by:
Hi, I want to read a string a chars from a stream, and put it into a string. At the moment, I'm creating a buffer of a fixed size, and reading the stream of text into it. It works, but I have...
3
by: rami.mawas | last post by:
I have implemented an RPN calculator in python but now I would like to make the stack size fixed. how can I transform the user's RPN expression from a stack overflow to a computable expression. ...
0
by: lllomh | last post by:
Define the method first this.state = { buttonBackgroundColor: 'green', isBlinking: false, // A new status is added to identify whether the button is blinking or not } autoStart=()=>{
2
by: DJRhino | last post by:
Was curious if anyone else was having this same issue or not.... I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
0
by: Aliciasmith | last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
0
tracyyun
by: tracyyun | last post by:
Hello everyone, I have a question and would like some advice on network connectivity. I have one computer connected to my router via WiFi, but I have two other computers that I want to be able to...
4
NeoPa
by: NeoPa | last post by:
Hello everyone. I find myself stuck trying to find the VBA way to get Access to create a PDF of the currently-selected (and open) object (Form or Report). I know it can be done by selecting :...
3
NeoPa
by: NeoPa | last post by:
Introduction For this article I'll be using a very simple database which has Form (clsForm) & Report (clsReport) classes that simply handle making the calling Form invisible until the Form, or all...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM) Please note that the UK and Europe revert to winter time on...
3
by: nia12 | last post by:
Hi there, I am very new to Access so apologies if any of this is obvious/not clear. I am creating a data collection tool for health care employees to complete. It consists of a number of...
2
by: GKJR | last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.