BlueMonkMN's picture

TextPrinter Update

I'm in the process of enhancing TextPrinter to support alignment and word wrap etc. (using MeasureCharacterRanges). I noticed the following code in PerformLayout:

            while (8 * charPositions.Length > vertices.Length)
               vertices = new Vector2[vertices.Length << 1];
 
            while (6 * charPositions.Length > indices.Length)
               indices = new ushort[indices.Length << 1];

Wouldn't it be much more efficient to do this?

            int newLength = vertices.Length;
            while (8 * charPositions.Length > newLength)
               newLength = newLength << 1;
            if (newLength > vertices.Length)
               vertices = new Vector2[newLength];
 
            newLength = indices.Length;
            while (6 * charPositions.Length > newLength)
               newLength = newLength << 1;
            if (newLength > indices.Length)
               indices = new ushort[newLength];

(Ignore the fact that I'm using charPositions.Length instead of text.length for the time being.)

Edit: Attached updated source code.

AttachmentSize
Fonts.zip8.54 KB

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
BlueMonkMN's picture

OK, responses (in no particular order):

1) MeasureString seems to properly measure the entire width of a string while MeasureCharacterRanges will never seem to always get the entire width. I don't think I ever managed to get the two to agree in all cases even when using the same StringFormat objects. MeasureCharacterRanges seems designed for highlighting characters and doesn't care if bits of the characters hang out of the range, regardless of the StringFormat provided, if I recall my results. I guess MeasureCharacterRanges doesn't allow character regions to overlap, so if a character overlaps another character significantly, that overlap (or part of it) may be excluded from this character's boundaries, even though it can draw beyond those boundaries. And MeasureString is the only reliable way I've found to entirely measure a large italic lowercase "f" in Times New Roman. (And even that method cots off a column or two of pixels if you try to measure a 20-point italic lowercase "f" in MS Sans Serif, but that's not TrueType, so that might be an error by design).

2) I removed MeasureString because I thought GetCharacterRanges' functionality of returning the bounding rectangle in the layout parameter would suffice. After seeing how limited GetCharacterRanges is, I see that may not be the case. It's unfortunate that there doesn't seem to be a reliable way to actually measure the visible part of a glyph. I considered just taking the whole glyph rectangles and getting a union of them, but many glyphs have extra pixels around them, and depending on how much space the final measurement method leaves, using the glyph rectangles to measure a string might be less accurate then MeasureString.

3) GenericDefault leaves extra space around the characters, so that's why I thought I should use GenericTypographic. For a while it looked like I might have to use GenericDefault when measuring them and GenericTypographic when drawing them. But I don't remember how that worked out in the end. That might have eliminated the need to track offsets, but caused problems measuring the output size, probably. I was surprised when I found yesterday that there are apparently more differences between GenericDefault and GenericTypographic than any amount of property switching can "fix". I can't seem to find any way to change the properties of a clone of GenericTypographic to behave like GenericDefault, even if I change all the properties to match. Not that I need to convert one into the other. I just thought that a StringFormat object was entirely defined by its visible properties, and I guess it's not.

4) Depending on how drastically the new code needs to change to work correctly, it might make sense to postpone adding the Doc-Strings until they're settled down a bit.

5) I noticed the first character of each line appeared on the screen to be shifted by some fraction of a pixel because they appeared blurry (for a 20 point font). I wonder if this is related to AntiAlias setting. I wonder if MeasureCharacterRanges is offsetting characters by a fraction of a pixel due to a certain (visible or invisible) setting. This could be a problem if we get some glyphs being anti-aliased twice in the process of caching then drawing.

objarni's picture

All these things trouble OpenTK. Fonts are complicated!

Maybe consider moving general text functionality into TK.Util?

And have a robust builtin text font in the OpenTK.dll? Might even be a good-looking font, so as to improve the "OpenTK brand". The current situation with artefacts here and there does not do OpenTK any good..

And neither does it do games built on OpenTK any good (right now I'm thinking of going the bitmapped text way in Dogfight2008 because of these artefacts..).

BlueMonkMN's picture

General text functionality is already in the utilities library. It no longer exists in the OpenTK DLL itself, as I understand it. Also, the existing functionality (with MeasureCharacterRanges) is "robust" for simple fonts. It only starts behaving oddly when you start using more complicated fonts (large fonts with kerning and italics). So it might be better to have a single font solution rather than multiple solutions. I think these problems will get worked out and then we'll have the best of both worlds: good font support for both simple and complicated/fancy text. The idea of providing a framework for a bitmapped font is interesting, though, because a good free font design tool is hard to find and use, and a lot of folks might prefer to just draw their font as a bunch of images. But I wouldn't see that as a core OpenTK component either. I think it's more important to get the commonly accepted font formats / text output to work well first, assuming it's do-able.

the Fiddler's picture

Well, drawing text from a bitmap is trivial to implement. There's really nothing wrong with that, and for many games it could be the right approach. On the other hand, OpenTK is not meant just for games and the simple approach just doesn't cut it in the general case.

Once the kinks are worked out, I think that the current GDI+/OpenGL approach will be a good tradeoff between quality (truetype fonts, hinting), speed and implementation difficulty. For the vast majority of uses it should be enough - and the rest don't really need to be covered by the core library.

@BlueMonkMN: I'm still comparing and contrasting differences between MeasureCharacterRanges and MeasureString, trying to figure out exactly how StringFormat affects each. It's getting a bit annoying, but I think the result will be worth it in the end.

Inertia's picture

And have a robust builtin text font in the OpenTK.dll?
How would that look like though? With Serifs or without? We would probably end up with c&p 'Times New Roman' in a dozen possible sizes, and it won't be exactly the sizes people do want.
If Dogfight is locked to a single screen resolution, a simple bitmap solution might be your best choice since you can tweak it until it's just right. I'd recommend using TextPrinter tho and having some patience, there's still several construction sites at the core library and that obviously has higher priority than Fonts.
Please note that OpenTK is also open-source for the simple reason that people may contribute code, rather than making requests, wait and pray that it makes it into the next release.

Might even be a good-looking font, so as to improve the "OpenTK brand".
Don't take my (C), patent, or space-for-rent remarks too seriously, I'm just making fun of desperate capitalists and 'company warfare'. The .com in OpenTK.com should be understood as .community rather than commercial. I actually do prefer OpenTK.Net as it's more descriptive about the general idea.

objarni's picture

Look here, I'm all for open source and community collaboration. I'm also against software patents even though I work in the software industry. Still, that does not mean I'm against the idea of a brand. Do you think Linux is brandless?

OpenTK IS a brand, whether you like it or not. How much score do you want it to have?

Inertia's picture

Well if you look at it from that angle, OpenTK is made out of "OpenGL", "OpenAL", ".Net", "Mono" plus some convenience. I don't think it can exceed your personal perception of those brands, what OpenTK basically does is building a bridge between them to simplify cross-platform development using them.
I believe the projects built with OpenTK are more verbose what it is capable of (and thereby define the 'brand'), than any 'marketing deceptions' we could come up with.

objarni's picture

I'm just gonna be a little evil, pardon me.


Well if you look at it from that angle, Ubuntu is made out of "debian archiver", "Firefox browser", "Compiz", "grub bootloader" plus some convenience. I don't think it can exceed your personal perception of those brands, what Ubuntu basically does is building a bridge between them to simplify the use of the Linux operating system.

I hope you get my point.

Inertia's picture

I'm afraid I don't. Ubuntu, Suse, Red Hat & whatever are just Linux distributions to me, no preference for any of those. However if I had to chose one I'd pick Ubuntu since many people are talking positively about it, not because they have a pretty built-in font, shiny logo or whatever.

OpenTK moves away from branding as far as possible. It does not care if the box runs on "AMD" or "Intel" CPUs, "x86" or "x64", does not care what brand the graphics or sound card are - if it supports the necessary extensions - and doesn't care about the underlying operating system either.

I don't think it will help OpenTK in any way if we put 'a free Power-Ranger-Action figure in every box' ... err ... 'a free won't-suit-your-needs built-in font'. Our clientel are not 10 year old "will buy it when it's shiny" stereotypes, and like I said before the projects built ontop of OpenTK will speak a much stronger language about it.

The only "brand" that could be considered a direct competitor to OpenTK is the Tao Framework, but I actually do encourage people to look into it for functionality that is missing in OpenTK, because Tao has a wider scope of included libraries.

objarni's picture

I'm afraid I don't. Ubuntu, Suse, Red Hat & whatever are just Linux distributions to me, no preference for any of those. However if I had to chose one I'd pick Ubuntu since many people are talking positively about it, not because they have a pretty built-in font, shiny logo or whatever.

"Have you tried OpenTK?"
"Yeah, it's a great OpenGL API for C#. They say they have font rendering support, but actually it's quite buggy (artefacts etc.). You'll have to do your own anyway."

Compared to:

"Have you tried OpenTK?"
"Yeah, it's a great OpenGL API for C#. They've got a simple builtin font so you can get started coding games day one. They've also got general font rendering, but it's a bit buggy right now, hopefully it'll come around."