Open frankheckenbach opened 4 years ago
Thanks for all the info in this post.
If it were 10 years ago, I would volunteer for maintainer. I use FTGL a lot in Vovoid projects, and I've added a few things to our internal fork of FTGL which are too "hackish" to contribute back. Color per character for instance, implemented as some bit mask thing.
I agree that FTGL is a bit clumsy compared to what you can do these days with C++ and a new architecture would also be better - in the case of polygon fonts - leveraging VRAM by generating a character string as a VBO and only updating it when the contents of the text changes is one pretty low hanging fruit.
Anti aliasing is not perfect but at least servicable in GPUs these days so if one can agree to rely on that, the VBO route is a very efficient way to render fonts.
Using VBO instead of gl Lists as FTGL does (for historic reasons) gives much better control over other things - uv coords, color, feeding data to a shader etc.
By building up a mesh one character at a time, one can also pick characters from multiple loaded fonts - one big drawback of FTGL was how hard it would be to mix regular/bold/italic characters in the same line of text.
By decoupling font and character this can be done in a nice way. Another benefit would then be that one can have a garbage collected glyph cache that can hold glyphs that are often used and retire those who aren't. This instead of the 128 glyphs which make more sense considering multiple languages.
So while I've enjoyed using FTGL for many years I agree it's time for a rewrite. If you want to banter about my architecture, feel free to join me at discord: http://vovoid.info
Thanks for your comments. I don't have too much to add.
I also faced the issue of mixing different fonts, sizes or colors, but I'd always implemented that outside of FTGL, i.e. calling FTGL for each piece of text with uniform attributes. At least for TextureFont, I don't think this was really less efficient since FTGL basically draws each character as one textured rectangle anyway.
But it's a reminder that maybe many developers have implemented their own extensions which would also make a port or rewrite more difficult to them. Perhaps a potential new maintainer should start with a large round of requirement gathering ...
By the way, FTGL is used in CERN's ROOT framework. https://github.com/root-project/root or https://root.cern - I believe they may maintain a vendored copy there.
I hacked together this in a weekend and some more:
https://twitter.com/jawrxu/status/1275540670833471488
It's a bunch of classes though.
I want to take care of it. What's the process ?
Thanks for your interest. I don't think there's any formal process. Just make a fork on Github and apply your changes (and possibly other changes that have been posted in my fork or the previous forks like ulrichard).
You're welcome to post a note here to point people to your fork.
You might want to contact package maintainers for some distributions. In case of Debian and Ubuntu, that's Manuel A. Fernandez Montecelo (https://people.debian.org/~mafm/). I corresponded with him when I made my fork, so he may like to hear about your changes, and he might know maintainers for other systems.
Okay then thank you very much.
not sure how this evolved (it seems like @HamzaM3 did not create a fork yet).
maybe we should just create an ftgl
group and move the repository there, so it no longer lives in some "personal namespace" and take-over can happen more easily?
@HamzaM3 has created a fork: https://github.com/HamzaM3/ftgl
thanks. no idea how i missed this.
unfortunately the fork is one of those "contributor forks" with no issues, PRs and whatnot.
i would still prefer to move the maintenance of ftgl in a separate "FTGL" organization (hmm. https://github.com/ftgl/ gives me 404, but when i try to create a new organization, github says the name is already taken).
what does @HamzaM3 think?
Might be a private name taken by someone. Probably nothing we can do about it. Of course, I have no objection to making such an organization, though you might want to fork (or move) @HamzaM3's code. But it'll be hard to unify all development -- I forked from @ulrichard and he also still gets issues and pull request, e.g. see https://github.com/ulrichard/ftgl/pull/17
If it helps, I can transfer the ownership of my fork to a new maintainer. Sometimes that gives a nicer fork graph.
TL/DR: I've dumped FTGL in my own code and won't do any more maintenance in my GitHub fork. Reasons follow, including some general criticism of FTGL.
I forked this repo from ulrichard who also told me then he wasn't interested in maintaining it further. The original authors have been unresponsive for a long time. Anyone who cares about the library might want to take over maintenance, which may be a simple as forking this repo and declaring it the new official version. :) And hopefully fixing some of the open issues ...
The immediate cause was that I needed to adapt my code so it can run with and without an OpenGL connection and do text layout in either case. Since FTGL loads the fonts into textures in its constructors already, I could not use it in the "no OpenGL" case, so I needed to use FreeType directly.
Now, doing the same layout with FT in one case and FTGL in the other would lead to quite some code duplication (and possible bugs since the conversion from FT's metrics is a bit tricky in some places). So I now do it with FT fonts in either case.
However, it's not possible to "upgrade" an FT font to an FTGL font, i.e. constructing the latter from the former. So in the OpenGL case I'd have to load the same font again for FTGL which is inefficient (and opens the door for other bugs).
So I looked into FTGL as for what it would take to make this possible. But at the same time, I also looked how much of FTGL's code actually remained that I'd be using, and especially for the texture font (the most common and "normal" one, and the one I currently care about), this was petty little.
Apart from interfacing FT and converting the metrics (which I'd already implemented myself before, for another non-FTGL project), all that remained was basically mapping the characters into textures (see FTTextureFontImpl::MakeGlyphImpl and FTTextureGlyphImpl::FTTextureGlyphImpl).
Side note, the FTGL code gets a little more complex due to preloading 128 glyphs. I don't seem to need that feature, and I wonder if it's actually more harmful than beneficial: Besides doing more work (in most cases, not all of those 128 glyphs are in fact used, and no work is actually saved or optimized by doing it at start), it creates (IMHO unnecessary) distinction between those 128 glyphs and the rest (i.e., typically ~ ASCII and non-ASCII), and bugs that would affect only the glyphs loaded later might be easily overlooked by developers using only ASCII, in particular English-speaking developers.
So after removing this in my test code, and reusing my general texture-setup code I had written elsewhere, what actually remained was just a few dozen lines of codes to map the glyph pixmaps FT gives me onto a texture. That was all that FTGL was doing for me at this point, and I had to conclude that's not worth it. The mere boilerplate that comes with using a library, dependency management, plus FTGL-specific setup including setting LegacyOpenGLState (that was necessitated by some historic mismanagement) took slightly more lines than reimplementing the texture mapping. So by that metric, FTGL's value had become negative to me. So I've now completely dumped FTGL and use FT directly.
(Short note about the other font types: Bitmap and pixmap are basically obsolete if they haven't always been (seeing as they don't respect the transformation matrix etc.), polygon font doesn't seem to offer anything texture font doesn't since multitexturing exists. Outline and extrude do provide for some extra features, but if I'll ever need them, I now think it would be easier to reimplement them myself too.)
Also I was reminded again of some code quality issues in FTGL I'd seen before but almost managed to forget about. I'll list some of them here. Anyone who plans to do major work on FTGL's code might want to consider these points in advance, to know what you're getting into:
The class structure seems much too complex for its job, partly due to heavy overuse (IMHO) of the pimpl pattern. Almost any simple operation goes through so many classes (e.g. FTextureFont, FTTextureFontImpl, FTFont, FTFontImpl, FTTextureGlyph, FTTextureGlyphImpl, FTGlyph, FTGlyphImpl) and many of their methods just forward to the next one, so it's often unnecessarily hard to find out what's actually going on). Plus a number of helper classes such as FTPoint which look like a great example of OO overengineering -- there's no point declaring data private and at the same time providing fully-general public getter and setter methods. It does not provide any encapsulation (not that any is needed), and burdens the caller with method calls instead of field accesses.
Of course, being written in the early 2000's, the code doesn't use any newer C++ features such as "auto", range-based "for" loops, unique_ptr, inline initialization etc. Honestly, reading this kind of code today feels closer to C than to modern C++.
The Unicode support uses wchar_t which is generally a rather useless type since it's unspecified whether it's 16 or 32 bits wide (or in theory, even 8 bits). Of course, char32_t wasn't available back then. Actually, I now realize, FTGL seems to treat wchar_t as UTF-16 always, even when it's 32 bits. This might explain a bug I'd had for a long time that it didn't seem to work with non-BMP characters -- it probably expected UTF-16 surrogates even in UTF-32 (wrongly). I'd never investigated that further because non-BMP wasn't that important to me. I just know that after switching to FT, non-BMP works just fine.
All of these things, and some miscellaneous issues, give me the impression the code is ripe for a complete rewrite already.
Finally, OpenGL is evolving. We now have OpenGLES and Vulkan, both of which I might need to port my code to in the foreseeable future. Of course, FTGL doesn't support those, and given that state of the code, I'd fear having to make such a port. Whereas now I have a clear separation of FT (which doesn't need porting), my own texture handling etc. (which I'd need to port anyway) and just a few lines of font to texture mapping which are easy to port.