Has anyone used a library that calculate the pixel width of a text base on font and font-size?
The only library that could give you an accurate answer is the same library you used to draw the text in the first place. Different text rendering libraries will render it at slightly different sizes so you cannot trust anything other than the text rendering library itself.
I guess I just have to approximate then, and use fonts that are as close to monospace that still looks good.
You should mention which platform/graphics library you are using.
For Windows, there are a number of different API calls that you can use. One of them is GetTextEntentPoint; there are several others.
For FreeType you can compute the dimensions of a string from the font's and glyph's metrics or with functions like FT_Outline_Get_BBox.
I imagine QT, GTK, Cocoa, or whatever graphics API/platform you're using will also have such methods.
I assume that you are doing this for SVG. I had to figure this out as well in a personal project I'm working on. These are the steps I followed (for a OpenType font):
- Get the UnitsPerEm measurement of the font.
- Get the AdvanceWidth for the specified glyph.
- Convert the
AdvanceWidth
to EM with theUnitsPerEm
. - Multiply this result by the font-size in
px
to get the advance inpx
.
Be sure to disable kernining while doing this, since this calculation doesn't take kerning into account. You can get the UnitesPerEm
and AdvanceWidth
from the OpenType create (though the documentation is not quite there, and there are some limitations if you are looking at exotic fonts). These measurements look something like this:
http://void.breeden.cc/Spectacle.X13013.png
Do note that the boxes displayed are not bounding boxes. Bounding boxes would hug the glyphs tighter, these are the boxes constructed from the AdvanceWidth
. Also note, that this will not be perfect, some browsers are weird like that.
The application that I'm writing is for svg in the browser, which requires a lot of work getting the dimensions right for each browser. Doing it in javascript seems like the most correct solution, but I thought it would be cool to just generate a static svg from the server. With that said, I'm not doing the measuring of text anymore. Aligning the elements approximate will do just fine.