Fontmaps

Don’t say his name, let’s refer to him as “the guy who believes he gets to play god on his own planet after he dies”. A little long, though.

Now, to the fonts. I have managed to get Pango up and rolling, so now it’s just a question of programming some textbox class and test how well the metrics hold up under a real stress. I have also noticed that there are a lot of strange symbols in the UTF-8 ranges. Some symbols are kind of “associative” in that they stick to other symbols. I am yet unsure if my fontmap will be able to represent those symbols, for I haven’t made much research on that.

Well for the record what I was trying to say is even immature and impractical people are allowed to be mean on the internet. Inclusion and participation is usually a good thing; except when it’s participation in generally intolerant and psychopathic behavior. I don’t think Romney believes in participation since he participated in a debate the other night that excluded candidates that are on the ballot in most of the states he would like to represent in the executive office. Funny that’s the same reason I can’t in good conscience participate in voting for our presidents. So I guess that makes me unqualified to be a citizen. Still I participate. Who in their right mind thinks about such things much less drags them into online discussion forums I wonder…

The nice thing about online forums is no matter how ugly the baring of teeth no one has yet to die at the hands of a crazed gunman mid post. Most of the meanness you find online is probably just a reflection of the pure frustrated impotency you are faced with when you try to lash out violently at a computer monitor :slight_smile:

Some symbols are kind of “associative” in that they stick to other symbols. I am yet unsure if my fontmap will be able to represent those symbols, for I haven’t made much research on that.

Those would have to be composited. But by god if you are loading up Pango surely it is able to do all of the necessary drawing?!

OT: This forum isn’t about tolerance or acceptance. It’s about helping people with questions regarding OpenGL or topics connected to OpenGL. If in the course of answering a question, or participation in a discussion spawned by said question, you come up with incorrect statements, you should correct that sentence yourself or at least have the decency to accept corrections from others. That’s the only reason why I cam up with the new network comparison. Since I polluted this thread enough with my perceived rants I’m simply gonna stop here with the suggestion, that in the future you either research stuff that you want to comment on, say that you don’t know about something if you can’t answer a question, or simply don’t say anything at all. Thanks.

Where is the fun in doing things like every other bloke? I want to see if my fontmap is possible, for it should theoretically perform much better. I will obviously use Pango itself to render text if I find the fontmap to be impractical or broken.

Success, brothers!

The color is (0.15, 0.15, 0.15) so the contrast isn’t that painful on the eyes. What do you guys think, could you read text like this without problems?

I have had no luck finding the function with which to set the filtering, so I assume it’s some antialias_gridfit one - I’d like the subpixel one (I think it would make the text less painful to read). Does anyone know where I might look?

Here’s how it looks after a complete rewrite (word-wrapping words but not spaces, some optimizations) if anyone still cares.

This is how the quads are positioned: http://imageshack.us/a/img855/5263/screen2ds.png

Who was it that brought it up? I am just trying to fit in. You will survive either way :slight_smile:

[QUOTE=Inagawa;1243230]Here’s how it looks after a complete rewrite (word-wrapping words but not spaces, some optimizations) if anyone still cares.

This is how the quads are positioned: http://imageshack.us/a/img855/5263/screen2ds.png[/QUOTE]

Yeah I care of course. But I can only make a point to read this forum off and on. So this is using your customized technique? Or Pango? Does Pango let you only load the pieces (library modules) you need?

So it looks like you are aiming for either a text editor or a very wordy game or reader or something?

It’s the result of this code:

_renderer = new Renderer(this, 6500);
_renderer.MapBuffer();

var fontMap = new FontMap(_renderer, new Size(512, 512));
fontMap.AddGlyphSet(FontMap.BasicLatin, “Times New Roman”, 10, Style.Normal, Weight.Normal, Underline.None);
fontMap.AddGlyphSet(FontMap.BasicLatin, “Times New Roman”, 16, Style.Normal, Weight.Normal, Underline.None);
fontMap.GenerateFontMap();

// Renderer, FontMap, MaxWidth, MaxHeight, FontName, FontSize, FontStyle, FontWeight, FontUnderline, PosX|Y|Z
_block = new Block(_renderer, fontMap, 790, 600, “Times New Roman”, 16, Style.Normal, Weight.Normal, Underline.None, 0, 0, 0);
_block.SetText(Text, Block.Alignment.Center);

So, basically the fontmap uses Pango to paint all the glyphs that you need (e.g., FontMap.BasicLatin) into a dynamically managed buffer.
The rendered glyphs are sorted with an offshoot of the Cygon Bin Packer and then an opengl texture is generated with “GenerateFontMap()” call.

Well, after generating the texture you can access any glyph information by calling

glyphInfo = _fontMap.GetGlyph(Character, FontName, Size, Style, Weight, Underline);

The glyphInfo contains everything you need to successfully render a single glyph (e.g., position on the texture, index of the texture, bearingX|Y, advanceX|Y, etc).

It’s quite neat, but the dependency on Mono makes it all quite … distasteful. On the other hand, I doubt you’ll find faster dynamic text. Sure it may suffer against static text, but for my uses this was what I needed.

^Can comment on which constructs in the code above belong to what libraries?

PS: I’ve subscribed to this thread (should have already) just now and will make a point to report back here after I am able to figure the best solution for my needs. I recommend anyone who wants to hear what I come up with subscribe too because it may well come a year from now :slight_smile:

My hope is to come up with something that apes DrawText in ease of use but is portable and serves as many non-proprietary (or de facto so) fonts as possible be they compatible with DrawText or not. It’s a nut I will have to crack sooner or later if a proper solution doesn’t boil up in the meantime. My theory is rendering text for things like games should be brain dead simple regardless of your platform.

The Renderer uses only OpenTK, FontMap uses OpenTK, Pango and Cairo. The block closely uses FontMap. I can PM you the source to the classes you want to see, or I can post them here if anyone else is interested. But as you know, it’s all in C# (and I guess all of you are using C++).

Also, this is by no means completed. As far as fontmap generating goes, the GDI-based fontmap supports all installed fonts and fonts from file and memory. It’s also able (thanks to GDI+) to render glyphs from other fonts if they don’t exist in the specified font. The downside are the simulated glyph metrics. Since I had to fake them, the text isn’t aligned very well (the reason I abandoned it, after all). The Pango-based fontmap only supports installed fonts and cannot substitute glyphs, but has better quality of text and pixel-perfect glyph alignment. It is also much more memory efficient and 10x faster.

The Block is programmed to work with the newer, Pango-based fontmap, but it’s easy to use it with the older fontmap.

^So is it safe to assume that all of the code above is your own (wrapped around the public libraries we are negotiating) ?

FYI: It should not be necessary to use “simulated glyph metrics” with the GDI based fonts. I remember DrawText will ignore leading and trailing spaces in lines of text so I had to manually calculate the metrics to get correct results. With Unicode there are more than a few kinds of spacing characters, and I did have trouble making sense of the metrics, but eventually I figured them out. They are confusing maybe, but surely they are the same metrics Windows uses under the hood. You just have to spend more time with them I suspect.

Also it’s disappointing if Pango requires fonts to be installed. I find it’s very helpful to go around the installed fonts with games. The software I have been working with for a while now originated in Japan, and to make it work as intended it’s easiest to just deliver the core fonts with it since many people do not have Windows’ Japanese fonts installed (Unicode fonts don’t really count) plus game authors and translators like to use custom fonts and asking the end user to install fonts for a game on demand is really bothersome, plus the font will remain installed after the game is no more.

PS: I suspect the best approach here would be to use GDI as much as possible on Windows. And do whatever is necessary on Linux with X… possibly going low-level if need be. If Pango will only do installed fonts on Windows it’s not going to give you anything (critical) that GDI can’t do, so it’s probably not worth the dependency in my book. Probably implementing something like ID3DXFont that works with OpenGL (basically what you were originally doing) is a good way to go if the fonts must be displayed with OpenGL.

Usage of installed fonts is not Pango’s limitation, but merely my own. I don’t care for portable fonts enough to bother with converting the .NET Font object to the Pango Font object. And yes, all the code is mine.

Also, I tried quite a bit of GDI+ measuring functions, but it always returned padding and other stuff that makes it (to me) impossible to get the exact size of the glyph. In the end, I have simply settled for a loop that maps the area the glyph is occupying. Although that was also one of the slowdowns I got with the GDI+ version. No such thing is necessary with Pango.


        /// <summary>
        /// Measures the symbol in the buffer with pixel-precision.
        /// </summary>
        /// <returns>The exact region that the symbol occupies, in pixels</returns>
        internal unsafe Rectangle MeasureSymbolInBuffer()
        {
            // Create variables to hold the coordinates
            var lowestX = _bufferBitmap.Width;
            var lowestY = _bufferBitmap.Height;
            var highestX = 0;
            var highestY = 0;

            // Lock the bits into memory
            var bitmapData = _bufferBitmap.LockBits(new Rectangle(0, 0, _bufferBitmap.Width, _bufferBitmap.Height),
                                                    ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

            // Get the buffer pointer
            var buffer = (Byte*) bitmapData.Scan0.ToPointer();

            // Find the exact span of pixels this symbol occupies
            for (int j = 0; j < _bufferBitmap.Width*4; j += 4)
            {
                for (int i = 0; i < _bufferBitmap.Height*4; i += 4)
                {
                    // Only stop at the pixels that are not transparent
                    if (buffer[(i*_bufferBitmap.Width) + j + 3] != 0)
                    {
                        var x = j/4;
                        var y = i/4;

                        if (x < lowestX)
                        {
                            lowestX = x;
                        }

                        if (y < lowestY)
                        {
                            lowestY = y;
                        }

                        if (x > highestX)
                        {
                            highestX = x;
                        }

                        if (y > highestY)
                        {
                            highestY = y;
                        }
                    }
                }
            }

            // Unlock the bits
            _bufferBitmap.UnlockBits(bitmapData);

            // In case this is the first time this is run, acquire data for the default
            if (_defaultSize.Y == 0 && _defaultSize.Height == 0)
            {
                _defaultSize.Y = lowestY;
                _defaultSize.Height = highestY;
            }

            // If these two coordinates are less than the default, they have to be
            // set to the default, otherwise symbols like underscores would be drawn
            // at the very top because of their minimal height, same for small letters
            if (lowestY > _defaultSize.Y)
            {
                lowestY = _defaultSize.Y;
            }
            if (highestY < _defaultSize.Height)
            {
                highestY = _defaultSize.Height;
            }

            // Shift the higher coordinates so that they point behind the visible pixels
            highestX++;
            highestY++;

            // Create a rectangle from the coordinates
            var region = new Rectangle(lowestX, lowestY, highestX - lowestX, highestY - lowestY);

            // Clean up used resources
            _bufferBitmap.Dispose();
            _bufferGraphics.Dispose();

            return region;
        }

^So is the above code is reading back the pixels as a way of determining the bounds of the glyphs? Sorry I am just scanning the code.

The metrics provided by GDI are first and foremost for the letter spacing, so that includes padding naturally. Plus there is kerning too if you want things to look really nice. I don’t have great memory, but if you wanted like the width between the leftmost and rightmost (or vice versa) non-empty pixel then yeah, that’s a little bit unusual. I’d not be surprised if those metrics are available but I would not be surprised if they are not either.

If you include the padding in your textures it would probably remain sufficiently packed together. Sometimes things that seem like savings are really not even worth the time to worry about.

PS: Does Pango not honor all fonts installed by Windows?

Yes, the code scans the buffer bitmap (the size of which is determined by a rough metrics returned by GDI+) pixel by pixel and determines its bounds. It’s primitive and it certainly could be improved, but for GDI+ it worked good enough.

And I guess there is a way to get some meaningful numbers, but GDI+ is not worth the time - Pango is much nicer to work with and it’s not Microsoft-exclusive.

I don’t understand what you mean by “honoring” all fonts. Pango sees all the fonts that are installed and uses them without any problem.

Not sure if it’s been mentioned on this thread already - NV_path_rendering https://developer.nvidia.com/nv-path-rendering

It’s vendor-specific, at this point in time.

  • Nigel