Well, I think I've got it done. There's one detail bugging me and I don't know what the source of this problem is. When I measure the size of the text and try to draw a rectangle behind it, the rectangle seems offset by about one pixel to left and top and/or one pixel too small vertically and horizontally. I don't know if it's a problem with the measurement or the aligning of the text on the rectangle. Anyway, it seems to be working well for the most part. I haven't optimized it too much because 1) I don't know that I could optimize it with all the considerations in mind that you know about, and 2) This function shouldn't be getting called too frequently.

OK, I attached it to the post. Adding 0.5f to the text's vertex coordinates just seemed to make it blurry (as I suspected would happen). And I know the rectangle is being drawn at the right size and almost in the right place because when I draw a rectangle size 3x3 at 0,0 it draws a 3x3-pixel rectangle at the top left corner of the screen. The problem is it draws it 1 pixel too high, so I only see the bottom 6 pixels of it. That might explain a bit of the vertical problem, but not the horizontal problem, which is 2 or 3 pixels at least. The text extends outside the right side of the rectangle by 2 or 3 pixels. Maybe if you try a similar test with the updated code you'll have an idea.

I checked again, and in most cases the text extends outside the bottom and right sides of the rectangle by exactly 2 pixels. The top of the rectangle has 4 pixels above the top pixel of text and the left side of the rectangle has 2 pixels left of the leftmost pixel of text. In one case, however, the text only extends 1 pixel out the bottom and right sides of the rectangle.

I suspect that this offset has something to do with the way the glyphs acquired. I didn't look at or change any of that code. I guess the glyphs maybe have some buffer around them? I don't entirely understand how the process of acquiring a glyph works at first glance.

I found time to look into this a bit more and indeed it is the process of generating and measuring the glyphs that caused the discrepancy. Those StringFormatFlags really make a big difference. I just had to make sure the flags matched among 1) The measuring of the glyphs, 2) the drawing of the glyphs into the texture and 3) the measuring during the layout of the total string. I'll work on this a bit more and post an update soon.

OK, everything is working perfectly now. With the right StringFormat flags the glyphs are now being cached into the texture properly so they are drawn with the correct position and size when drawing a string. And after I took your advice about offsetting my rectangle by half a pixel, everything aligns perfectly. I've attached the updated code to the original post. Can this code be included in the OpenTK release?

This will replace the current implementation, but there are a couple of minor issues that should be fixed first:

Specifying StringFormat.GenericTypographic in TextureFont will cause glyph overhangs to become clipped. You can check this by printing any italic font of a sufficient size (e.g. Arial italic 24em).

Is there a specific reason why you removed MeasureString? We still need a function of that kind, to help find the bounding box of a string.

Please add doc-string to new public functions! (e.g. GetCharPositions)

Ok, the first one isn't actually minor. I'll try to reproduce the off-by 1 pixel issue - the packing was loosened by 1 pixel on 0.9.1 to fix some filtering artifacts, which might be the root cause of this.

Edit: There's definitely something fishy going on with text centering and measuring. Working on it...

After investigating these questions, I find, I think, there's a problem in MeasureString versus MeasureCharacterRanges that will require storing the offsets of the glyphs within their stored image buffers in order to properly position and measure the size of text. I'm in a rush at the moment, but will respond to the other questions when I can. (MeasureString does something MeasureCharacterRanges can't seem to do, and vice versa.)

I'm still investigating, but it seems you are right - we may have to store the origin for each glyph.

What difference did you find in MeasureString vs MeasureCharacterRanges?

Edit: I just found a problem in the current code: Glyph.Width (Glyph.cs) is calculated using default Graphics settings, while the actual positioning is performed with AntiAlias or AntiAliasGridFit (TextureFont.cs).

This code smells bad, I'll probably have to rewrite it to make it more sane.