Advanced font/text rendering options

Started by
21 comments, last by SyncViews 8 years, 8 months ago

I have some existing code using FreeType I did some years ago and have used since, just laying out the glpyhs using the FreeType provided metrics and kerning routine then rendering as mono or 8bit anti-aliased greyscale (some fonts, e.g. Calibri I found will give mono at certain font sizes for most glyphs) then uploading the final result as a D3D or OpenGL texture (so one texture containing the entire block/string of rendered text that I can draw as an alpha blended quad either screen aligned in the UI, or in 3D space).

However I now want to improve this to give correct and higher quality results in more cases. Namely correct handling of composed/decomposed codepoints/glpyhs, non-latin scripts and support for subpixel rendering.

Most of these however appear to not be part of FreeType. e.g. the correct placement of the combining mark for á and Á does not appear to have a FreeType API, and kerning seems to be superseded by GPOS which FreeType does not implement. Things like correct subpixel rendering, while a FreeType feature seem to be highly complex and poorly documented (e.g. how to then deal with coloured text and backgrounds). So at least before I start down that highly complex road am looking at what options I have...

  • FreeType itself seems to recommend a library called Pango. However this looks like a pretty big and heavy weight library, pulling in a lot of other difficult dependencies (e.g. parts of GTK and Cario) which while may be fine on Linux, does not look promising for MSVC/Windows/Direct3D. I also found very little information on using Pango with Window's and OpenGL/Direct3D or just games in general...
    Is this worth pursuing? It looks like I might be able to do without a lot of GTK and work with in memory bitmaps I can upload to the GPU as textures, but I am not sure if it is really suitable and worth learning about?
  • On Window's there is DirectWrite. Which I understand I can use via Direct2D and Direct3D. Don't really know much about this, and again if it is generally suitable for games using D3D11 on Windows 7 to 10. Also I would need something different for anything I do on Linux which would seem a lot of extra work.
  • Anything else? I had a poke around CEGUI and SDL_ttf, but they seemed to use FreeType in much the same way I did. I am planning to look at CEGUI some more and write a demo to see if it has solutions for my problems, but am not entirely sure it solves everything having read through their FreeType logic and not seen much sign if them implementing the things I did not. Also since I do not plan to port the rest of my UI stuff, mostly just looking for inspiration/examples on fixing up my own FreeType logic.
  • Obviously simple bitmap/sprite fonts don't really solve any of my problems here.
Advertisement

Pango is a higher level library that draws together a collection of lower level libraries, including FreeType. You can do much the same thing yourself by just pulling in what you need. For the advanced OpenType shaping and layout stuff (GPOS and friends) you want the HarfBuzz library. DirectWrite is basically a combination of HarfBuzz and FreeType for Windows (with other stuff thrown in, like higher level font selection based on family names). It's not a great idea if you need to be cross platform though, as you've mentioned.

Most games don't even bother with scalable glyph rendering like you get with FreeType, let alone go into even more advanced layout and shaping, which is why you're going to have a hard time finding resources on it. Even with those libraries, applications like web browsers consistently have a hard time getting things perfect for all of the languages they support.

Mike Popoloski | Journal | SlimDX

HarfBuzz looks interesting, and actually found an SDL example, so will take a closer look at that and if I can get something simple going to tell me where to put the glyphs.

Yeah, I guess most games don't bother, but my current project has some what more text than I had previously so I need to make some improvements (namely in the layout of mixed style text and small font size quality areas), and would be nice to get a solution that can support localisation later since I have known for ages that my code does not handle layout of even latin script combining glpyhs correctly (and also since several friends have Chinese as a first language, making that work would be of interest as well).

Gave HarfBuzz a go this evening. Managed to get it to build on MSVC 2013 with only FreeType as a dependency. The basic example code for sdl i found only supporyed a line in a single font. Hopefully ill find api's for wrapping, multiple fonts, etc. in the docs.

So assuming that goes well only leaves subpixel rendering which is mostly a nice to have. But would be nice to figure out how its meant to work with colours.

Have you considered signed distance field fonts?

I find rendering text using this technique not only visually excellent, but incredibly fast compared to glyph based rendering.

Had a read through this https://www.mapbox.com/blog/text-signed-distance-fields/ . Looks interesting but more as a possible rendering optimization if I find myself rendering lots of 3D text and want the extra quality due to constantly changing transforms. For mostly static text I think uploading a per-text bitmap should be fine, but will keep this in mind to revist.

So looked at HarfBuzz some more. As far as i can tell it cant lay out multiple lines for me, with it only really taking care of getting the glyphs for a single line ("run") of text? I guess the intention is that I give HarfBuzz my paragraph, then post process its results to insert line breaks with the help of some other library. Is that the intention? I could likely manage English and similar languages using the same logic I always have, but is there such another library to do it for me? Im sure even English could be laid out better, and I have no idea about other scripts.

Ideally I just want to be able to give something some text fragments with associated styles/fonts (e.g. effectively like the content of a HTML <p> with some simple <span>'s in it) and just get a bitmap back, or at least all the glyphs with positions. Maybe another look at Pango or other UI libs is in order?

Considering looking at DirectWrite more for Window's, but the interop with D3D appears to be fairly complex, and would then have to consider the Linux/Mac support separately (somewhat in the hope that the libraries for Linux desktop applications include a suitable equivalent).


For mostly static text I think uploading a per-text bitmap should be fine

Won't this make localisation a total nightmare?

I don't mean a bitmap I made offline and shipped with the game, but one I rendered with FreeType or some other lib at runtime then turned into a D3D/OGL texture rather than creating a sheet of all required glpyhs or similar mechanism to render as a text block on the GPU.

Since such UI text is not changing per-frame or anything close to it, I don't think that should be a performance issue as the per frame cost is rendering one textured rectangle per piece of text. 3D text is where the other method looks interesting, because of the performance/quality issues of changing the 3D transform (either re-rendering the text block on the CPU with a different transform, if supported at all, or the quality loss of transforming anti-aliased rendered text even at a highish resolution).

I am in pretty much exactly the same situation as you are.

Unfortunately, I don't have much to say to help, but at the moment, I'm leaning towards just biting the bullet and make a separate integration per platform with whatever text rendering API is available there. For iOS and OSX I'm currently using CoreText for it, and rendering full text blocks to texture as you are suggesting, and it works great.

It should be the least effort with the most language and features support, for just a bit performance hit when generating the texture (which is manageable). And I'm guaranteed it will look as good as the platforms own text rendering. There is a lot to text rendering that you don't think about in the beginning... like when the designer need outlines & shadows, and things like different text alignments (left, right, center or both left and right-aligned, etc...).

For dynamic scaling&transform on the text, It should be possible to use an SDF generated from the full text string, as opposed to per glyph.

SDFs works great for any monochrome bitmap, not just font glyphs.

I'm a bit worried about the time to generate the SDF though, but then I mostly dev for mobile platforms.

Harfbuzz seems competent, but it does not solve text wrapping, it just sets up a line fragment.

Pango should work, but the LGPL license is bit of a turnoff, bc of the closed platforms I need to support. (that includes Android)

But I guess for linux support, that is what you'd have to use. (but also no license problem on that platform)

Console I unfortunately have no idea about, was kind of hoping some console dev would post here too smile.png

Not using at least harfbuzz, for a non-OS specific sollution, seems out of the question because of the complexity of unicode rendering. (I don't really want to have to know _that_ much about every stupid language rule in the whole world, and every weird unicode quirk and font hinting detail).

I'm sure just getting the text wrapping and alignment right is enough to ruin most of the fun.

Edit: Changed paragraphs around a bit to get my point across clearer...

Have you considered OS-specific APIs?

In the past, I have used Windows Uniscribe for positioning while I rendered the glyphs using blinn-loop beziers. It was surprisingly effective.

Honestly, I could not tell if HarfBuzz was a real thing at the time. Everything with an open source background is usually an hell of dependency, the idea of having Pango in my dependency list gives me the shrivels.

Previously "Krohm"

This topic is closed to new replies.

Advertisement