Just posting this here, so I can link to this thread and the attachment in the message which I'll write to the developer mailing-list in a moment.
Briefly, this is about a request to include an embedded font within the "allegro_font" addon, so that it would be possible for example to display some quick debugging info without having to load an external font file.
I already wrote the function and adapted the font data from Allegro4 for that (see attached zip, which includes the code to create the font at runtime and a modified ex_bitmap.c to demonstrate usage).
edit
attached a new version with minor changes (fixed potentially problematic call to allegros font grabbing function (I wasn't sure whether it was safe to pass NULL for any pointer parameter and if these parameters are sanity checked (!=NULL) inside the function but now that should never happen.) and fixed a comment)
Would it be better to have a function called al_load_default_font that just loads the systems default font? Or just something like a Courier or Terminal font should be fine on any system that has it.
I still like the idea of having a built-in font though...
I think it would be good to have this as a standard add-on in 5.2. The function name is terrible though... Something like al_get_generic_font() is easier to remember. Perhaps it could take a scaling parameter.
Also, it might be beneficial to have this in the same add-on:
al_load_system_font( int family, int size, int flags ); // these could be hard-coded to known OS fonts ALLEGRO_FONT_MONOSPACE (e.g., Courier) ALLEGRO_FONT_SANS_SERIF (e.g., Arial) ALLEGRO_FONT_SERIF (e.g., Times New Roman) // user fonts ... some intersection of commonly defined fonts ALLEGRO_FONT_DESKTOP ALLEGRO_FONT_WINDOW_TITLE
Alternatively:
al_load_system_font( const char *name, int size, int flags ); "Verdana, Arial, sans-serif"
Yes, system fonts would be awesome. Could use fontconfig on linux. That'd be very nice.
I renamed the function to "al_create_default_font" and attached the new version (plus minor fixes) to the first post. I would keep the "create" in the function name as a hint that the user is responsible for cleaning it up in the end via "al_destroy_font".
Loading system fonts would be sweet indeed. For the font family parameter there could maybe even be a parameter like ALLEGRO_FONT_SYSTEM_DEFAULT which would try to load whichever font is usually 100% certainly available on the executing platform (and maybe fall back to a built-in font if that fails).
I kinda like the char* version better. This allows for CSS style font loading, like Matthew has shown.
We can use the same font families as CSS to allow specification of preferred font, backup font, and family. I think things would go smoother from an application programmer's point of view.
I've figured out how to do the thing on OS X: get Library locations (usually ~/Library with fall back to /Library, but there are cocoa functions for getting this that one should use instead of hardcoding) and then look for Fonts. The non-trivial part is figuring out the filename you want, which is typically "Fontname Bold Italic.ttf" or "FontnameBold.ttf", but could be anything really. I guess it's possible to try those first, then look at the font descriptions in each font file until the desired font is found.
Anyway, this is mainly a note to myself for how to implement this once an API is decided on and there is nothing left to do on 5.0.
I've figured out how to do the thing on OS X: get Library locations (usually ~/Library with fall back to /Library, but there are cocoa functions for getting this that one should use instead of hardcoding) and then look for Fonts.
Um, OSX should have a proper API for this. Doing it by searching for some font path is a little error prone.
Um, OSX should have a proper API for this. Doing it by searching for some font path is a little error prone.
The alternative would be to not use Freetype at all and use OS functions to render glyphs instead (without ever knowing the font path). This would be more work to implement though.
I suppose they could have left out a way to find fonts by attributes. That would suck though. I wonder if fontconfig works on OSX too?
Um, OSX should have a proper API for this.
Sure. If I want an NSFont. But I don't, I want an ALLEGRO_FONT, which means I want to know a path to a filename.
It has a proper API for drawing text too, and we're also duplicating that.
The alternative would be to not use Freetype at all and use OS functions to render glyphs instead (without ever knowing the font path). This would be more work to implement though.
Wouldn't work with bitmap fonts and means a substantial redisign of the font addon.
Not something we should be doing right now.
Is an 8x8 font really useful for 90% of the games that will be made? I understand it's good for old retro games, and maybe as a debugging aid, but even as a debugging aid, it's too small!
Sure. If I want an NSFont. But I don't, I want an ALLEGRO_FONT, which means I want to know a path to a filename.
Yeah I misworded that. But it doesn't really matter, OSs like OSX and Windows really couldn't care less about apps that don't use the native toolkits.
OSs like OSX and Windows really couldn't care less about apps that don't use the native toolkits.
No, but we do.
According to Apple's documentation for how the Library directory is laid out, Fonts is a standard location, so the method I outlined above should work fine there.
According to Apple's documentation for how the Library directory is laid out, Fonts is a standard location, so the method I outlined above should work fine there.
Sure, but actually trying to search for a specific font family or other things just won't work. At best you'll be able to do is look at the file name, and thats probably not enough, unless we want to hard code font filenames. But thats not guaranteed to work at all.
Might be an idea to see if fontconfig works on osx and windows. It could be very useful.
Is an 8x8 font really useful for 90% of the games that will be made? I understand it's good for old retro games, and maybe as a debugging aid, but even as a debugging aid, it's too small!
A scale parameter could be used when creating the default font. 16x16 or 32x32 should be plenty big enough.
Might be an idea to see if fontconfig works on osx and windows. It could be very useful.
It's available in DarwinPorts, which gives its description as "An XML-based font configuration API for X Windows", so I'm guessing no native version.
This (from the port file)
platform macosx {
lappend add_fonts /Library/Fonts /Network/Library/Fonts /System/Library/Fonts ${prefix}/share/fonts
}
suggests it's almost (but not quite) looking in the same locations I posted earlier (the function we use for the native file location API on OS X will actually return an array of locations, so if you asked for Library locations it would return all of Library, Networl/Library, System/Library, $HOME/Library; it's important to look in all those locations, I guess).
But there has to be a way (using FreeType?) to get things like font family and the like from the font file? That way, we could do a good "first guess" for common types, then fall back to doing a brute-force search if it fails.
Font loading should not be time-critical code anyway.
I did some time ago my function to enumerate font families and so on. Of course FreeType was used. Loading all fonts to collect font family info during application startup is time consuming task. Therefore I decided to use cache in which I store all necessary information about font face (family, style, physical file path, etc.). Such cache can be loaded and used next time. In the result I could type "Times New Roman" instead of "times.ttf". I think also meta families could be used, like monospace, sherif, etc.
At the moment I have more than 500 font files under windows. This is fresh install with fonts from Office 2010. Collecting information about all fonts during application startup will cause ~2 second penalty in release mode.
I think it is good idea to introduce some functions to enumerate fonts installed in the system. To keep this consistent FreeType should be used to collect necessary data. That's because Windows, Mac and other OS's use different methods to handle combinations of style/face. For there are fonts: Arial, Arial Narrow and Arial Black. Font family is 'Arial', styles are 'Narrow', 'Black', 'Italic', etc. Some come from font attributes some directly from names. Windows will treat those fonts like different fonts. Adobe products will treat all three as 'Arial' family and list 'Narrow' and 'Black' as styles. I'm not sure how this will work on Mac OS X or Linux. But it is clear that same set of font files will lead to different list of fonts on different OS's. With FreeType Allegro can provide unified way of enumerating fonts.
I did some time ago my function to enumerate font families and so on. Of course FreeType was used. Loading all fonts to collect font family info during application startup is time consuming task.
Could do, I suppose. On the other hand, I don't think we need to do it if the user asks for a specific font type and we can do an educated guess first.
I'm not sure how this will work on Mac OS X or Linux.
OS X lists "Arial.ttf", "Arial Bold.ttf", "Arial Italic.ttf" and "Arial Bold Italic.ttf" as "Family Arial" with "Typeface Regular, Bold, Italic, Bold Italic", but it lists "Arial Narrow.ttf", "Arial Narrow Bold.ttf" etc. as "Family Arial Narrow" with "Typeface Regular, Bold, Italic, Bold Italic".
Actually, I think the only recognised typefaces are "regular", "bold" and "italic" (and the combination "bold italic"). Anything else is lumped into the font family.
But it is clear that same set of font files will lead to different list of fonts on different OS's. With FreeType Allegro can provide unified way of enumerating fonts.
Since this would sit on top of the TTF addon, which uses FreeType on all platforms, that shouldn't be a problem. Probably a good thing actually.
Yes, if user ask for specific font file, family name shouldn't be used. But still, enumerating all fonts is time consuming process. Results should be cached for example in file (memory file could be also used).
I think functions for font enumeration should be placed in font add-on. In that way debug font will also be included in result list. TTF add-on should provide sub-enumeration routine.
So as the function searches for a font:
it searches its memory cache first
when that fails it searches the paths, but not bothering to open any files that already have an entry in the cache
every file that it finds that is not what was wanted still has its information remembered in case it is useful for later
It will keep searching for the font until it has run out of locations (meaning an exhaustive search was performed and still failed, by this time all system fonts would be enumerated).
It flock()s & writes any new font cache entries into font cache file in temporary files (%temp% /temp or w/e) on allegro_exit (probably skip if flock fails after 3 seconds in a row or something).
Should programmers should probably be able to specify additional search paths? Ones that would will also override system fonts if clash (i.e ./fonts relative to program executable's assumed path). Might be useful in highly user-customizable, redistributed programs.
Loading /temp/allegro-fonts.cache or w/e, should have a timestamp for each entry, should validate that each entry still exists and has not been modified since, should do this at add-on initialization.
My 2 cents
The cache should probably be enabled explicitly. Something like:
path = al_get_standard_path(ALLEGRO_USER_SETTINGS_PATH) al_set_fontinfo_cache(path + "fontinfo.txt")
That way the cached info would be in ~/.config/mygame/fontinfo.txt for example (under Linux).
It would better belong in temp, or data rather than settings.
Probably. But this should does not matter.
I think ALLEGRO_FILE should be supported in the first place. Second, const char* may be provided not otherwise.
User may want to collect information about system fonts, game fonts or mixed. Let say something like:
In my font renderer I have interfaces IFontFamily, IFont, IFontManager and IFontRenderer. Font can be created using IFontFamily, other IFont but with different style/size, literal family name. Results of my attempt to translate all those to Allegro style functions for sure is not perfect.
My intention is to introduce functions which provide all necessary (and common) information about font face.
I will think about proper interface. Any hints/requirements/wishes will be most welcome.
Would this read in all system fonts?
cache = al_font_info_cache(ALLEGRO_SYSTEM_FONTS);
And what would be the code to get an ALLEGRO_FONT once I have the ALLEGRO_FONT_INFO of the font I want?
Would this read in all system fonts?
Yes. Operation will take a few seconds.
And what would be the code to get an ALLEGRO_FONT once I have the ALLEGRO_FONT_INFO of the font I want?
Hm... I think this will be something like:
Lack of function overloading make those above a bit ugly, but descriptive.
Functions such:
ALLEGRO_FONT_INFO* al_font_get_info(ALLEGRO_FONT* font);
Also should be available.
How does the old allegro-dev saying go? The person who writes the code dictates the API? I think it looks fine and I would use it. I think it's a good base to work with anyway. You'll not usually hammer out an entire API and then write the code without any changes. So if you want, you could start writing this in preparation for 5.1. If anybody doesn't like it, well, they've had a chance to say so. And if something turns out not to work well, code is always modifiable. You'd still keep the underlying code in tact so no loss.
I agree. And the simple builtin 8x8 font the thread originally was about is completely separate - it may still be useful to some even when we have a way to use system fonts.
I just noticed that rendering fonts with that font created by my function is ridiculously slow. Turned out to be a lot faster when I changed it to make it create a video bitmap instead of a memory bitmap but with a video bitmap the process of creating the font takes several seconds, so maybe there should be a parameter to the font creation function to choose the bitmap type to use.
I just noticed that rendering fonts with that font created by my function is ridiculously slow. Turned out to be a lot faster when I changed it to make it create a video bitmap instead of a memory bitmap but with a video bitmap the process of creating the font takes several seconds, so maybe there should be a parameter to the font creation function to choose the bitmap type to use.
Try creating the initial bitmap as a memory bitmap, then set the new bitmap flags to video, and al_clone_bitmap the bitmap, and use that bitmap for the font. Should load fairly fast, and render decently as well.
I think I once replaced the ALLEGRO_FONT vtable so that you could actually render the standard Allegro 4 font. The difficulty then becomes rendering the characters efficiently (didn't solve that one, I was more concerned with getting it to work, so I just used al_draw_pixel). Maybe locking and unlocking the bitmap will help there.
Try creating the initial bitmap as a memory bitmap, then set the new bitmap flags to video, and al_clone_bitmap the bitmap, and use that bitmap for the font. Should load fairly fast, and render decently as well.
Yes, that did the trick. Thank you Tomasu.