SDL Fnt Library

Hello,

I’m a little tired of SDL_TTF and its idiosyncracies. I was looking at alternative formats and found AngelCode’s fnt bitmap format.

I didn’t find anything which already exists within the SDL community, so I was thinking of starting on a library myself and calling it SDL_Fnt, making it open source, etc.

Theoretical advantages over SDL_TTF:

  1. Real-time rendering instead of caching rendered fonts as a single image. This would allow more efficient scrolling text which doesn’t require re-allocating a surface and copying to a texture every time the text changes.

  2. No allocations other than vertices for UV-mapping the quads in the regular SDL RenderCopy calls

  3. Can potentially apply motion effects/offsets to individual characters in the string, which would be cool in some game character’s dialog (such as a spooky ghost)

  4. More accurate string-width calculations, perhaps.

Potential disadvantages:

  1. A bitmapped font sheet means imperfect scaling - scaling up will result in texture interpolation. As TTF is a vector format, this doesn’t happen with SDL_TTF. This would not really be a problem with pixel-art fonts since they’re meant to scale with nearest-neighnbor anyways. Scaling down would also be a problem without mipmapping

This would still allow people to render text once and cache the image for re-use, but they may have to allocate the texture/surface and set the render target themselves, but perhaps that could be wrapped as well.

Would anyone be interested in this library? Is my use-case for it too specific to warrant supporting it for the community, or should I just throw it in my game engine

Potential disadvantages:

  • You cannot do proper internationalization this way and support Asian languages (tons of symbols).

This is true, as far as I can tell - it would be an ascii or extended ascii (some latin characters with accents to support spanish, perhaps) spritesheet. Though I wonder if there are some shortcuts/hacks to support asian languages. Korean, for example, is made up of building blocks of characters and I wonder if methods exist to combine spritesheets of simple hangeul characters into complex Korean syllables, and similarly with building blocks for Chinese characters. That would be beyond the scope of my own uses, where the fonts I’m looking to turn into bitmaps already don’t support anything outside of ASCII

It’s rather a leap from accented characters to CJK languages! What about the much simpler requirements of Greek, Cyrillic, Hebrew, Arabic (slightly more complicated) etc. alphabets? From a European perspective, if you don’t support those it’s not worth doing.

I did some more research, and this format supports UTF-16 perfectly well! I generated every possible Korean character and it was only 1.8mb of images (and not every Korean character is actually even used in Korean), so it seems like as long as the developer generates the correct sheets ahead of time, there’s no issues with internationalization!

1 Like

Fwiw, if you call it this, everyone will send the bug reports to us, thinking we wrote it.

(But I do think this is a cool idea for a library and you should build it.)

Yeah I thought of that too and went back and changed all my types and headers from SDL_Fnt_* to Fnt_* because I didn’t want to inadvertently associate the project with SDL

Well after some initial work in C, I’ve managed to confirm that one can trivially decode a UTF16 or UTF8 string and UV map the relevant glyphs. Thankfully, MSVC has supported UTF16 literals since the 90s and C11 supports them now too. Here’s a couple examples of rendered text

VsDebugConsole_WzqPF3Hkkj

GGA4aeZNLb

I believe I’ve proven the concept to myself to be feasible enough to continue forward. features I’d like to try to implement would be

  • Per-character offset transformations
  • Per-character size transformations
  • Per-character color transformations
  • Configurable Character spacing
  • Configurable Line spacing
  • Text-wrapping with break-word or break-line
  • Some form of multi-core rendering, though I’m not sure how this would interact with SDL2’s batched queue system

The code to render the Korean characters is simply:

// Load font "Han3.fnt". This allocates textures and malloc's some space for character definitions
Fnt_LoadFromFileW(L"Han3.fnt", &fnt, "", renderer);
SDL_FPoint cursor = { .x = 10.0f, .y = 10.0f };

// No allocations occur in this render call
Fnt_RenderTextUTF16(renderer, L"안녕하세요", &fnt, NULL, &cursor);
SDL_RenderPresent(renderer);

Will you be supporting Arabic contextual forms? Contrast this, which is just the base glyphs strung together (right-to-left):

with this, which is how it should appear with contextual forms:

Here’s the original text to copy and paste if you want to try it:

هنا مثال يمكنك من الكتابة من اليمين
الى اليسار باللغة العربية

I’ll try it out. Do you know the names of any default Arabic fonts, so I can generate the sprite sheets? Glancing at it, and based on a very small understanding of Arabic, it looks like some characters are drawing iver others? This may not currently work, since I’ve yet to code the alpha blending, but I dont see why it couldnt work. I’ll get back to you with what I find soon. My guess is their offsets are defined in the kerning table

So I didn’t get very good results. There is no kerning table in Arabic fonts, it seems, and the format is agnostic of the right-to-left scheme with arabic (it produces positive x offsets rather than negative), so the right-to-left would have to be calculated in the library. I think it’s also missing some characters in the sprite sheet, and I have no idea where to find them

Here’s an example of what I got, with wordpad rendering the text on top, and the library on bottom:

It vaguely looks like some of the characters are in the correct place.

Anyways, I don’t know enough about Arabic to really make any progress on it, so I’ll have to leave that to any open source contributors to implement themselves. I can do left-to-right languages with “distinct” (for lack of a better term) characters, such as English and Korean (the only other writing system I know how to read).

In simple terms, Arabic and related languages use a different form depending on whether the character is isolated, begins a word, ends a word or is within a word. The font I used for the example was DejaVuSans, but I think most Unicode fonts should include Arabic glyphs, since it’s used in so many countries across the world.

The complexity of rendering different languages is why libraries like Uniscribe in Windows and Harfbuzz in Linux exist. One possibility might be for your library to interface with them.

Well I’m going to release the library under lgpl, so hopefully someone can come along and implement arabic (or Hebrew for that matter)

As another suggestion, if you’re looking for them, changing fonts mid-string, like I mentioned in that other thread about SDL_ttf, would be great to accommodate italics, bold, smallcaps, underline, etc.

What do you think would be the best interface for that? Like what would you pass to the render call with the string to say “at X chars, draw this font”

In HTML, they do it with markup. Maybe something like “There is [myfont-bold]one[/myfont-bold] bold word in this string!” But then you have to figure out how to escape the markup and it would mess up any string-length calculations you’re using. Or you could try parsing another string that defines when the fonts change. Maybe something like “myfont:0,myfont-bold:10,myfont:10” but that would be a pain to use, especially if you were generating your strings dynamically.