Converting LogFont height to Font size in points - delphi

I have a LOGFONT structure. Now all i'd like to do is get the associated font size in points from the LOGFONT height.

When the mapping mode is mm_Text (which it usually is), and when the lfHeight field is positive, it already gives the height in points. When it's negative, the units are pixels. MSDN for LogFont gives you the formula to convert between them:
lfHeight = -MulDiv(PointSize, GetDeviceCaps(hDC, LOGPIXELSY), 72);
There are 72 points per inch. GetDeviceCaps tells you the number of pixels per inch on a given device. Invert the formula to get pixels from points:
PointSize := MulDiv(-lfHeight, 72, GetDeviceCaps(hDC, LogPixelsY);
The important thing to realize here is that you need a device context. Font sizes don't exist independently of the media they appear on. The pixel height of a font on the screen will be different from the pixel height of a font on a printer. Use the Handle property of whatever canvas you're planning on drawing to.

I find this a bit confusing, as well.
Here are a few things that I háve learned. ;)
Examine the two low-order bits of lfPitchAndFamily to determine the font type.
For fixed-pitch fonts, use GetTextMetrics and the TEXTMETRIC structure.
For variable-pitch fonts (true-type, etc), use GetOutlineTextMetrics and the OUTLINETEXTMETRIC structure. Be sure you have the structure aligned properly. Also, the structure is variable-sized. Call the function once to get the size, allocate space, then call the function again to fill the structure.
From there, you can find proper ascent, descent, and other size-related information.
Keep in mind that they are recommended values and not all display routines will use them properly. For example, I am in the process of figuring out a correct method of determining the required height of a dialog box static control for a given string of text.
It does not appear that Microsoft has followed their own documentation. ;)
Not that the documentation is all that clear or complete, to begin with.

Related

Set numeric UILabel for Auto Layout to correctly compute the intrinsic content size

I have a UILabel with a font of size 50 and text 1. At runtime, its text is changed to other numbers.
If I, say, center it in its superview, the automatically detected (intrinsic content size) height is a lot bigger than the actual text, and this is because it tries not to crop other lower characters like g.
The thing is that I know I won't use other characters than digits. I also don't want to set a fixed height constraint for it.
UIFont metrics include ascender, descender, cap height, x height, etc... all of which determines how the characters fit into a container. There is a good explanation and diagram here: http://cocoanetics.com/2010/02/understanding-uifont
If you really want to get the height (and/or width) of the individual character "glyphs" you'll need to use Core Text. This will include calling CTFontGetGlyphsForCharacters() and CTFontCreatePathForGlyph() to get the "glyph path" (a CGPath object), at which point you can get the "bounding box" to determine the exact size.
Lots of discussions and example code out there... A good starting point is simply searching for CTFontCreatePathForGlyph

How can I get a the default width of a specified font in Delphi?

I'm writing a DXF exporter/importer. The DXF MTEXT entity format supports width factor for a text block (how times it is wider than the default font width). The Windows LogFont record contains the lfWidth field (how many pixel will be the average font width if you select the logfont to create a hFont). How can I get the default width of the used font to calculate the scaling factor back and forth? Is there any WinAPI call?
OK. I have found It. The getTextMetrics fills up a TEXTMETRIC record. It has a tmAveCharWidth. The searched value.

How to get font size in delphi

I am looking for a function which should take parameters as Font name, sample character, width, height of the sample character and should return Font Size.
It must look like this:
GetFontSize(<Font Name>, <Sample Character>, <Sample Character Width>,
<Sample Character Height>)
which must return the font size,
Is this possible in delphi?
You may want to take a look at this page that discusses font size and points.
It uses the following to convert between the points and pixel size:
Arial 12pt at 96 dpi:
font size in points 12
font size in pixels = ------------------- × 96 dpi = ---- × 96 = 16 pixels
72 points per inch 72
You could use that for your conversion. You just need to be aware of possible differences in your screen dpi as Blorgbeard stated. Points are usually used to describe the size on paper. You need to decide how you want to map that to the screen. For example many programs will allow you to set a zoom level. That does not change the printed size on paper but does affect the pixel height on the screen.
Depending on what you are trying to accomplish you may need to get the actual sizes of the font. If you are trying to find out exactly how the font is put together take a look at Obtaining Font Metrics The code on that page uses the .Net libraries but it has a good explanation. If you want to get the Text Metrics in Delphi you would use the GetTextMetrics function.
As Rob stated in his comment you can draw text at a specific height by setting the Font.Size property to the negative height in pixels. Windows will then draw the text out at that height. In that case you don't need a specific letter or the width as you have in your prototype function. For a given font size each letter will have a different height and width. I.E. capital letters will be taller than lower case letters and letters like "W" will be wider than letters like "i".
I'm only aware of methods to do the opposite - that is, to get pixel sizes from point sizes.
The only way I can think of is to set up a TCanvas, and repeatedly call GetTextExtent on it, changing the font size each time, until you get a size that's acceptably close to what you want.
Depending on how accurate you need this, you could just convert your desired height in pixels to points - a point is 1/72 of an inch, and your screen is probably 96 pixels per inch (but check GetDeviceCaps to get the real figure). See this question.
That would get you a font size pretty close to the pixel size you want.

BCB: how to get the (approximate) width of a character in a given TFont?

It's a TMemo, not that that should make any difference.
Googling suggests that I can use Canvas->TextWidth() but those are Delphi examples and BCB doesn't seem to offer this property.
I really want something analogous to memo->Font->Height for width.
I realize that not all fonts are fixed width, so a good estimate will do.
All that I need is to take the width of a TMemo in pixels and make a reasonable guess at how many characters of the current font it will hold.
Of course, if I really want to be lazy, I can just google for the average height/width ratio, since height is known. Remember, an approximation is good enough for me if it is tricky to get exact.
http://www.plainlanguagenetwork.org/type/utbo211.htm says, " A width to height ratio of 3:5 (0.6) is recommended for most applications"
Actually your google search is not entirely off. You do need access to a canvas object, or at least a handle to a DC object. In general when searching for help concerning VCL classes it often pays to search for delphi examples since these are more common.
Anyway to calculate the size of a string you could have a look at the TextExtent function, it is a function for the TCanvas class. Simply pass the character which width you want to test, and the return value will be a TSize construct. However there is also a TextWidth function, as well as a TextHeight function. You can use these as well. Actually these call the TextExtent internally.
You have to note one thing though, the functions use the current font of the TCanvas object, more specifically the font bound to the DC the canvas uses. So assign the font you wish to test with first, and then pass the character.
I have some old code that calculates the width of a string like this:
// This canvas could be the form canvas: canvas = Form1->Canvas or the
// memo canvas which will probably be what you want.
canvas->Font->Assign(fontToTest);
int textwidth = TextWidth(textToTest);
If you want more control of what to do, you can also do this using the Windows API, this is essentially what the VCL does for you, in that case the following example would look like this:
// This canvas could be the form canvas: canvas = Form1->Canvas
canvas->Font->Assign(fontToTest);
// The initial size, this is really important if we use wordwrapping. This is
// the text area of the memo control.
TRect rect = ClientRect;
// This is the font format we wish to calculate using, in this example our text
// will be left aligned, at the top of the rectangle.
fontformat = DT_LEFT | DT_TOP;
// Here we calculate the size of the text, both width and height are calculated
// and stored in the rect variable. Also note that we add the DT_CALCRECT to the
// fontformat variable, this makes DrawTextEx calculate the size of the text,
// without drawing it.
::DrawTextEx(canvas->handle,
textToTest.c_str(),
textToTest.Length(),
&rect,
fontformat | DT_CALCRECT,
NULL);
// The width is:
int width = rect.Width();
The fontformat is a parameter that specifies different options for how to align and layout the text, if you plan on drawing text it will be a good idea to check out the different possibilities it offers: DrawTextEx Function [1]
EDIT: Reading through your question again, it struck me that the function you might be searching for is: GetTextExtentExPoint Windows API documentation states the following about this function:
The GetTextExtentExPoint function
retrieves the number of characters in
a specified string that will fit
within a specified space and fills an
array with the text extent for each of
those characters. (A text extent is
the distance between the beginning of
the space and a character that will
fit in the space.) This information is
useful for word-wrapping calculations.
You can find more information about the GetTextExtentExPoint function here: GetTextExtentExPoint Function [2]
[1] http://msdn.microsoft.com/en-us/library/dd162499%28VS.85%29.aspx
[2] http://msdn.microsoft.com/en-us/library/dd144935%28VS.85%29.aspx
What you could do, if you have access to Win32 API functions, is create a RichEdit Window the same size as your TMemo window, place the text in the RichEdit window, send the EM_FORMATRANGE message to the window and from the result determine how many characters it will hold. Of course this method will work with multiple lines etc...

Query regarding drawing TikZ figure

In this sample code, the author does the following
\draw ($(closedStart.south) + (-.5em,0)$)
edge[stateEdge] node[edgeLabel, xshift=-3em]{\emph{Passive open}}
($(listen.north) + (-.5em,0)$);
What irritates me most about these markup based drawing tools is that I've to measure a value and specify. In this case, the author specifies .5em
I've yet not understood how to figure that out? How much is .5em? I don't even know the size of the base object, so how can I be sure that if I give a value it will be valid?
Is there any approach to do this? How should I decide the value and also the unit? Is em always the best unit to use?
Google is your friend: http://en.wikipedia.org/wiki/Em_%28typography%29
An em is a unit of measurement in the field of typography, equal to the point size of the current font. This unit is not defined in terms of any specific typeface, and thus is the same for all fonts at a given point size. So, 1 em in a 16 point typeface is 16 points.
You can change the unit of measurement to anything supported by latex, i'm sure: in, mm, cm, pts, picas, etc etc.
Not too sure how TikZ handles it but in LaTeX you can specify measurements as fractions (larger or smaller than 1) of known lengths, so you could set a length to be, say, 0.5\textwidth. My bet is that TikZ has this sort of facility so if you are going to be a long term user you'll want to figure it out.
To expand on what Mica says:
ems are the usual way that intercharacter space is measured, and is historically was the width of a character "M" in a given font ("M" normally being the widest letter in Latin-based fonts): crucially, it is a relative measure, and subscript fonts, say, have a smaller em than normal text. Modern fonts generally have narrower "M" characters than historically, and there are many non-Latin fonts, so the em measure is now derived from the dimensions of the square (or oblong) that the font designer places the character in, and is communicated as a parameter, together with such facts as the height of the baseline that text sits on, that tells us the scale of the font.
The point size of a font is the number of points (usually 1/72 inch) to an em, so a 12 point font is one whose character "M" is 1/6th of an inch wide (i.e., 12/72 in). The subscripts of a 12 point font are usually shown in a 7 point font, for which the em is just under 1/10th inch.
If you want to do positioning on a page, use points. If you want to control spacing in text, use ems because they scale.
Postscript
Fixed the discussion of the character `M', thanks to Mica.

Resources