views:

59

answers:

1

Hi,

I'm developing a .net 3.5 Win Forms program and I've run into an "interesting" problem with text drawing.

I'm implementing a text editing control and it draws text with DrawString() and StringFormat.GenericTypographic (henceforth, GT). As the user types, whole words (or groups of words) earlier in the line are moving subtly left and right at random.

It seems likely to be rounding errors - an affected block looks to shift one pixel in the horizontal plane as letters are added to the line's end. If I use StringFormat.GenericDefault (GD) this doesn't happen, but characters are rendered less accurately and this isn't acceptable.

I reasoned that I could slowly change GD into GT (the settings for each are discussed in MSDN and can obviously be examined in the debugger) and see which FormatFlags or other setting was causing this and go from there. However, if I take a copy of GD, change all the properties so it is identical to GT, the character placement is quite different - the behaviour of these two supposedly identical objects is obviously not the same.

Like too many things IMHO, .net Reflector shows that StringFormat is just a wrapper for a non-managed object and I can only assume that not all the properties of this are exposed to .net software.

Can anybody suggest anything that might help me? I'm aware that TextRenderer might provide an alternative method for rendering but I discounted that earlier in my design process (although I can't actually remember what the problem was now...).

Edit

The code I'm using for rendering is as follows:

sForm = new StringFormat(StringFormat.GenericTypographic);
sForm.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;

using (SolidBrush brush = new SolidBrush(frmt.ForegroundColour))
  context.DrawString(line.Text, frmt.DisplayFont, brush, new PointF(horizontal, height), sForm);
A: 

Well, I've solved the problem. It's not the way I wanted to do it, but for reference, I've done it like this:

I already have code that calculates a bounding box for each word (for working out the caret position when clicking in the control and for displaying justified text), so rather than drawing the entire line in one go, I'm now drawing each word separately.

It seems wasteful to continually call DrawString() for each word (when it can cope with whole multi-line blocks in one go), but the program remains pretty fast.

Now if only I could work out why it seems to want to change the kerning for individual letters within a word as the word grows...

Bob Sammers