libsdl-org / SDL_ttf

Support for TrueType (.ttf) font files with Simple Directmedia Layer.
zlib License
343 stars 116 forks source link

Second Atlas Draft (Implemenattion done, examples/docs can improve) #359

Open LevoDeLellis opened 1 month ago

LevoDeLellis commented 1 month ago

I don't think there's anything else I want to add to the library. I'll want to improve documentation and examples.

I like the C++ version because of the hash table but both are pretty close. The C++ example uses multiple atlas functions while the C version uses the function that loads everything at once. Here's a picture of the C++ version which loads 2 fonts and intentionally didn't load the 'Y' in the larger font

IIRC GL supports a texture with 8bit alpha channel (GL_Alpha8 and GL_R8 for pixel shaders). Is it possible to use an 8bit format for this? At the moment only SDL_PIXELFORMAT_ARGB8888 is supported. I simply use white and set the alpha bits (0x00FFFFFF | ((Uint32)*src << 24);)

Let me know what you think. If it's all good I'll write better documentation and may add more to the example(s) Screenshot_2024-05-11_21-06-49

slouken commented 1 month ago

I haven't done a full review, but here are some thoughts:

LevoDeLellis commented 1 month ago

I just noticed how hard to read this is when looking at the diff. I'll have the next PR be based on the main tree.

  1. Sure, if you were looking at draft1 I removed that function, in draft two I can add a SDL_Surface and remove the width/height/pixel format
  2. Correct no kerning. I never heard of anyone using that when using an atlas. Do you strongly want this? If so I'll look into it
  3. Is there a way to get expected line height? I've been treating y as the top of the line (instead of baseline). In the example I treated baseline as the ascent of E + some padding for line height. I prefer using y as the top but if that's weird I can have y be the baseline
LevoDeLellis commented 1 month ago

I found some time to look at kernings. It appears FreeType will scan the file every time you look up a pair and there's no way to get a table. However stb_truetype.h appears to create a table which I think is an excellent choice

It offers two license, mit and public domain https://github.com/nothings/stb?tab=License-1-ov-file#readme https://github.com/nothings/stb/blob/master/stb_truetype.h#L804

I'm interested in implementing kerning with some stb code. I just want to make sure that you'll accept my code before I go out to do this. I can write a text document of the API (funcs and structs) if you want. A quick summary is

https://github.com/LevoDeLellis/SDL_ttf/blob/main/include/SDL3_ttf/SDL_ttf.h#L2251

  1. Replacing various members in TTF_AtlasInfo with SDL_Surface as you requested
  2. Better documentation and param names (does canvasSquare make more sense than canvasWidthHeight?)
  3. Change TTF_AtlasInitFixed to use a surface
  4. Change the ReserveEntry function. I'm thinking instead of having two functions, have one with an extra param, but instead of bool which is easy to get wrong, use 2 or 3 to state if the array is {width, height} or {width, height, id}
  5. Add a function to get the kerning table
  6. Requested on the discourse is having a function to render instead of having the user copy/paste that code
  7. Possibly an extremely simple hash table to make kerning and character lookups faster (which I would need for the render function)

Thoughts? I'm not in a rush to implement this. Here's the drawing code from the example (which will be changed to use a hashtable), I like having the Y be top instead of baseline but if it makes more sense for Y to be baseline that's completely fine and a minor edit https://github.com/LevoDeLellis/SDL_ttf/blob/main/examples/AtlasLoadAll.c#L142