MeasureString gets it wrong for italics

H

Hilton

Hi,

Graphics.MeasureString ignores the FontStyle.Italic attribute. How do you
center an italic string?

Normally:

int strWidth = (int) grfx.MeasureString (str, font).Width;

x = (this.ClientSize.Width - strWidth) / 2;

But that doesn't work with italics text.

Hilton
 
S

Simon Hart [MVP]

Have you tried measuring each character as opposed to the whole string?
 
H

Hilton

Simon said:
Have you tried measuring each character as opposed to the whole string?

Yes, they're equal. Visually, an italic "X" is much wider than the
non-italic "X", but .NET reports them as the same width.

Hilton
 
P

Paul G. Tobey [eMVP]

I've checked this with DrawText in native code and it returns the same
rectangle for italic and non-italic versions of the same font. This seems
to be the case for all screen fonts on the device I tested, so I'd call that
"intentional". Whether it's 'right' or not, I'm not sure. Courier New has
no problems with fitting the actual text in the right box in italic mode,
but Tahoma might have some of the string outside the rectangle when drawn
with italics.

Paul T.
 
H

Hilton

Paul said:
I've checked this with DrawText in native code and it returns the same
rectangle for italic and non-italic versions of the same font. This seems
to be the case for all screen fonts on the device I tested, so I'd call
that
"intentional". Whether it's 'right' or not, I'm not sure.

I cannot believe it is 'right' because the width reported is not the width,
but most importantly, how do you center italics text??? Even Microsoft Word
can center italics words! (see below)

Normally: x = (widthOfRect - widthOfString) / 2 <--- clearly this gives
the wrong x with italics.

OK, how about this test: Open Word, write XI, make it a big font, change the
"X" to italics. Using Times New Roman, the X overlaps the I. Now make the
X Comic San MS and it is really bad... and clearly the bounding box doesn't
even match the text when highlighting the X. Speaking of which, I have
noticed that when you combine non-italic text and italic text in Word, it
looks terrible in terms of spacing, now I know why. Here is another, write
"XExcellent" - make the X italics - prety bad overlapping especially when
using Comic San Serif.

So I guess that the C# libraries are (correctly) blinging calling the C code
which is giving the wrong results. Perhaps Microsoft discovered this years
ago, but figured that by fixing it, they would break existing apps. I'm
purely guessing here.

Hilton
 
C

Christopher Fairbairn

Hi,

Hilton said:
So I guess that the C# libraries are (correctly) blinging calling the C
code which is giving the wrong results. Perhaps Microsoft discovered this
years ago, but figured that by fixing it, they would break existing apps.
I'm purely guessing here.

I'm no expert on this kind of thing, but I bieleve the API is working
correctly. The measured width is the bounding box for the characters, it
doesn't include any left-bearing or right-bearing content (i.e. content
which overlaps into the "box" for the previous/next characters).

James Brown has a good discussion of this on his Win32 Text Editor tutorial.
See part 10 - Transparent Text and Selection Highlighting available at
http://www.catch22.net/tuts/editor10.asp. See the section right at the top
discussing italicised 'f' characters.

Hope this helps,
Christopher Fairbairn
 
P

Paul G. Tobey [eMVP]

It's centered fine, at least for the three fonts I've tried. The problem is
that some dots in the drawn letters extend outside the reported bounding
box, which can be a problem for layout with respect to adjacent character
runs with different attributes.

Similar effects occur on the desktop, yes.

Paul T.
 
H

Hilton

Paul said:
It's centered fine, at least for the three fonts I've tried. The problem
is that some dots in the drawn letters extend outside the reported
bounding box, which can be a problem for layout with respect to adjacent
character runs with different attributes.

Similar effects occur on the desktop, yes.

Paul, take a look at this screen shot (Word):
http://www.hiltonswebsite.com/WrongItalics.PNG

The non-italic version fits perfectly in the |---|. Then when I change the
WingX to italics, the 'base' of the letters stay in the same place, but the
top just moves over. Clearly everything above the base has moved to the
right and has become wider. All the text here was centered and clearly, the
second WingX is no longer centered. This is even more obvious with the
lowercase "i". The character gets wider (clearly) and slants to the right.
Therefore to center this, the character must move left - it doesn't. When
highlightng the itlics "i", Word does its best and highlights complete the
wrong rectangle whose width is based on the non-italic "i".

Again, the reason I brought this up was because I spent ages figuring out
why "WingX" in italics was not being centered correctly - then I found this
Microsoft bug.

Hilton
 
G

Guest

I think the link in Christopher's post indicates (at least to me) that this
isn't a bug - it's how the APIs work. You're getting the "B" width, not the
ABC width. I don't know offhand how to get the ABC width, but the API
behavior is consistent with the desktop. If it's the same on both and is
documented, I have a hard time calling it a bug. Non-intuitive, however, it
most certainly is. I do wonder what the recommended ".NET" way of
determining actual width is.
 
C

Christopher Fairbairn

Hi,

I think the link in Christopher's post indicates (at least to me) that this
isn't a bug - it's how the APIs work. You're getting the "B" width, not
the ABC width. I don't know offhand how to get the ABC width, but the API
behavior is consistent with the desktop.

As I said in my earlier response, this aspect of GDI certainly isn't my
strong point either, but here's my thoughts on the topic...

The ABC widths for a given character can apparently be determined by calling
the GetCharABCWidths API
(http://msdn2.microsoft.com/en-us/library/ms901130.aspx), if it is present
on your platform.

As discussed in a desktop specific article "Drawing Text from Different
Fonts on the Same Line" (available on MSDN at
http://msdn2.microsoft.com/en-us/library/ms534212(VS.85).aspx) drawing
styled text is inheriently more difficult, especially when different font
styles and sizes are involved.

For example regular text drawn immediatly after italic text probably needs
to be moved over slightly to avoid any sloping content hanging over from the
previously drawn italic string.

However if you were calling DrawText for a second time in a row with the
same (italic) font you obviously wouldn't need to avoid the sloping content
and would want to start off where the previous string ended.

The DrawText API (DT_CALCRECT) etc had to pick one way or the other. If it
returned a rectangle that bounded all pixels drawn to the screen then italic
text drawn via DrawText one character at a time would have large gaps
between letters. As you have found out the API designers choose the other
option, and this has gotchas for fonts with overhang etc.

Text rendering is a complex business, as the tutorial I referenced
highlights.

Like Chris Tacke, I'm not aware of what the nice "managed way" for getting
text metrics is (if there is in fact one on the Compact Framework).

Hope this helps,
Christopher Fairbairn
 
C

Christopher Fairbairn

Hi,

Christopher Fairbairn said:
As I said in my earlier response, this aspect of GDI certainly isn't my
strong point either, but here's my thoughts on the topic...

I have not tried it, but the following knowledge base article on MSDN may be
of help. Perhaps you could PInvoke these APIs and see if it helps.

INFO: Calculating Text Extends of Bold and Italic Text
http://support.microsoft.com/kb/74298

Although the article is helpful most of it doesn't apply since Windows CE
uses true type fonts. However the article explains the different measurement
approachs and then states:

NOTE: This article applies only to Raster and Vectory Fonts. The
GetTextExtent() family of functions always return advance widths of strings
for TrueType fonts as described by ABC widths structure. For more
information on ABC advance widths, see the GetCharABCWidths() function
documentation.

So perhaps try measuring the string via the GetTextExtentPoint API
(http://msdn2.microsoft.com/en-us/library/aa911432.aspx) and see if that
takes into account italics etc. A worthy experiment...

Hope this helps,
Christopher Fairbairn
 
P

Paul G. Tobey [eMVP]

On CE5, at least, this appears to give approximately the same result as
DrawText().

Paul T.
 
H

Hilton

This is getting wierder by the minute... When I draw each character
seperately (bold, not italic), and add its width to "x", it looks perfect on
the device, but extremely spaced out of my desktop.

Hilton
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top