Bundling TTF fonts with an FLTK application

522 views
Skip to first unread message

aditya siram

unread,
Jan 22, 2018, 1:55:32 PM1/22/18
to fltk.general
Hi all,
I'd like to bundle some font assets with an FLTK application but is there a way to load them at runtime? FLTK docs only talk about loading fonts already installed on the system.
Thanks!
-deech

Ian MacArthur

unread,
Jan 22, 2018, 5:26:09 PM1/22/18
to fltkg...@googlegroups.com
Hi deech,

There’s no fltk API for that, but it’s fairly easy to do with only a little platform specific code on the 3 main platforms I usually target (X11+XFT, Win32, OSX).

The OSX case is either the easiest, or the hardest, depending on how you want to go...

If you create an app bundle and put your font resource inside it (which is what OSX expects you to do) then it’s pretty straightforward. Alternately, you can load the font programmatically at runtime; this is harder under OSX, but is what I usually do since it’s is more congruent with what I do on X11+XFT or Win32 cases...

I’ll post the code for that below, I know I have a worked example here somewhere.

What platforms(s) are you targeting?

Also, if you decide you want to see the code for loading the OSX font from the bundle, I can probably post a sample of that too...

//////////////////////////////////////////////////////////////
/* Test the loading of application specific fonts.
* Uses platform-specific coding and API's. */

#ifdef _WIN32
# define _WIN32_WINNT 0x0501 /* need at least WinXP for this API, I think */
# include <windows.h>
#elif __APPLE__
# include <ApplicationServices/ApplicationServices.h>
#else /* Assume X11 with XFT/fontconfig - this will break on systems using legacy Xlib fonts */
# include <fontconfig/fontconfig.h>
# define USE_XFT 1
#endif

/* Fltk headers */
#include <FL/Fl.H>
#include <FL/x.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Box.H>
#include <FL/fl_draw.H>

/*************************************************************/
static int loaded_font = 0;
static Fl_Font test_font = (FL_FREE_FONT + 1);

/*************************************************************/
// Create some portability wrappers
#ifdef _WIN32

# define i_load_private_font(PATH) AddFontResourceEx((PATH),FR_PRIVATE,0)
# define v_unload_private_font(PATH) RemoveFontResourceEx((PATH),FR_PRIVATE,0)

#elif __APPLE__
# include <stdio.h> // I use printf for error reporting in the Apple specific code!
/* For the Apple case, we need to do a bit more work, since we need to convert
* the PATH into a CFURLRef before we can call CTFontManagerRegisterFontsForURL()
* with it.
* Otherwise, all three systems would have basically the same structure here! */
static int i_load_private_font (const char *pf)
{
int result = 0;
CFErrorRef err;
// Make a URL from the font name given
CFURLRef fontURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
(const UInt8*)pf,
strlen(pf),
false);
// Try to load the font file
if (CTFontManagerRegisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &err))
{
result = 1; // OK, we loaded the font, set this non-zero
}
else
{
printf ("Failed loading font: %s\n", pf);
}
// discard the fontURL
if (fontURL) CFRelease (fontURL);
return result;
} // i_load_private_font

static void v_unload_private_font (const char *pf)
{
CFErrorRef err;
// Make a URL from the font name given
CFURLRef fontURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,
(const UInt8*)pf,
strlen(pf),
false);
// Try to unregister the font
CTFontManagerUnregisterFontsForURL(fontURL, kCTFontManagerScopeProcess, &err);
if (fontURL) CFRelease (fontURL);
} // v_unload_private_font

#else /* Assume X11 with XFT/fontconfig - will break on systems using legacy Xlib fonts */

# define i_load_private_font(PATH) (int)FcConfigAppFontAddFile(NULL,(const FcChar8 *)(PATH))
# define v_unload_private_font(PATH) FcConfigAppFontClear(NULL)

#endif

/*************************************************************/
class page_view : public Fl_Box
{
public:
// constructor
page_view(int x, int y, int w, int h) : Fl_Box(x,y,w,h) {}
private:
void draw(void); // draw method
};
/*************************************************************/
void page_view::draw(void)
{
/* This is the "raw" UTF8 encoding for some symbols from the Supplementary Plane. Musical Notation in this case */
static const char notes[] = ":\xf0\x9d\x85\xa0-\xf0\x9d\x85\xa1-\xf0\x9d\x85\xa2-\xf0\x9d\x85\xa1-\xf0\x9d\x85\xa0:";
const char solo[] = "\xf0\x9d\x85\xa0";
char clefG[8]; // 1D11E

/* Convert a Unicode value, 0x1D11E in this case (a G clef), into a UTF8 string using the fltk helper function */
int ll = fl_utf8encode(0x1d11e, clefG);
clefG[ll] = 0; // make sure UTF8 string is NULL terminated

int x0 = x(); // origin is w.r.t. the Fl_Box
int y0 = y();
int w0 = w();
int h0 = h();
fl_push_clip (x0, y0, w0, h0); // clip to the current page view

// set the background colour
fl_color(FL_WHITE);
fl_rectf(x0, y0, w0, h0);

// Basic string in default font test
fl_font(FL_HELVETICA, 30);
fl_color(FL_BLACK);
fl_draw("This is the default font (FL_HELVETICA)", x0+25, y0+100);

// Test the "private" font the application has loaded for its own use
fl_font(test_font, 40);
fl_color(FL_BLACK);
fl_draw("This is the private font we loaded", x0+25, y0+200);
fl_font(test_font, 25);
fl_color(FL_DARK_RED);
fl_draw("Here are some glyphs from the SMP using the test font", x0+25, y0+250);

fl_font(test_font, 40);
fl_color(FL_BLACK);
// Special notes test
fl_draw(notes, x0+25, y0+300);
// SINGLE note test
fl_draw(solo, x0+225, y0+300);
// CLEF test
fl_draw(clefG, x0+300, y0+300); // clefG

fl_pop_clip(); // restore the default clip region
} // draw method

/*****************************************************************************/
static void load_extra_font(void)
{
/* Load the font using the appropriate platform API */
loaded_font = i_load_private_font("./font/fltk-test-regular.otf");

/* set the extra font */
if (loaded_font)
{
Fl::set_font(test_font, "fltk");
}
} // load_extra_font

/*****************************************************************************/
static void free_extra_font(void)
{
if (loaded_font)
{
v_unload_private_font("./font/fltk-test-regular.otf");
}
loaded_font = 0;
} // free_extra_font

/*****************************************************************************/
int main(int argc, char **argv)
{
Fl_Window *main_win = new Fl_Window(650, 400, "Load Special Font");

/* Load our additional font for musical symbols from the Supplementary Plane */
load_extra_font();

page_view *test_page = new page_view(5, 5, (main_win->w() - 10), (main_win->h() - 10));
test_page->type(FL_FLAT_BOX);

main_win->end();
main_win->resizable(test_page);

// Show the test window
main_win->show(argc, argv);

/* Run the fltk event loop */
int result = Fl::run();

/* Unload the private font we loaded earlier */
free_extra_font();

return result;
}
/* end of file */



Ian MacArthur

unread,
Jan 22, 2018, 5:36:46 PM1/22/18
to fltkg...@googlegroups.com


> On 22 Jan 2018, at 22:26, Ian MacArthur wrote:
>
>
> I’ll post the code for that below, I know I have a worked example here somewhere.
>


Also, and this may be obvious, I should caution that this code only works if invoked from the console, since I used a fixed path to the font file to load; a more robust version would need to set the font path more intelligently.

Double clicking this app on OSX or *most* X11 WM will likely not work, since the CWD will be wrong for loading the font from. That said, since Win32 exe’s have the CWD set to the exe dir, that probably will work as is!



aditya siram

unread,
Jan 22, 2018, 7:07:59 PM1/22/18
to fltk.general
This is really great. Thank you very much!

Albrecht Schlosser

unread,
Jan 23, 2018, 2:28:35 PM1/23/18
to fltkg...@googlegroups.com
On 22.01.2018 23:26 Ian MacArthur wrote:

> There’s no fltk API for that, but it’s fairly easy to do with only a little platform specific code on the 3 main platforms I usually target (X11+XFT, Win32, OSX).

Thank you very much for the example code. I tested it with some example
fonts (.ttf and .otf) and it basically worked. But it seems somewhat
fragile when it comes to loading the font because you need the
real/exact font name when loading the font (AFAICT). How do we get (or
guess) the font name? Here is what I mean (other parts of your code elided):

> /*****************************************************************************/
> static void load_extra_font(void)
> {
> /* Load the font using the appropriate platform API */
> loaded_font = i_load_private_font("./font/fltk-test-regular.otf");
>
> /* set the extra font */
> if (loaded_font)
> {

In your example the font file is "fltk-test-regular.otf" and you assign
the font to the chosen FLTK font number with:

> Fl::set_font(test_font, "fltk");
> }
> } // load_extra_font

In my experiments I was likely always successful if I used the fonts
under Linux, but it was harder under Windows. I believe there is a
difference if the font is installed under Windows so I tried to use some
(open source, free license) Linux or other downloaded fonts. I defined a
simple struct that associates the FLTK font name with the given font
file name and used this similarly to your example above. Here is what I
came up finally with three example fonts that can all be loaded as
regular, bold, italic, and bold italic. Note that the Windows font
"Palatino Linotype" has German names on my German Windows machine.

I used the Windows built-in font viewer to see/guess font names for
Windows because the short Linux font name didn't work. Here is what I
got so far:

typedef struct fontdef_ {
const char *name; // FLTK font name (1st char = { ' ' | 'B' | 'I' | 'P' }
const char *file; // system font (file) name to load
} fontdef_t;

static fontdef_t font[] = {
#ifdef _WIN32

{ " GFSArtemisia-Regular", "/path/to/fonts/GFSArtemisia.otf" },
{ "BGFSArtemisia-Bold", "/path/to/fonts/GFSArtemisiaBold.otf" },
{ "IGFSArtemisia-Italic", "/path/to/fonts/GFSArtemisiaIt.otf" },
{ "PGFSArtemisia-BoldItalic", "/path/to/fonts/GFSArtemisiaBoldIt.otf" },

{ " Palatino Linotype", "/path/to/fonts/pala.ttf" },
{ "BPalatino Linotype Fett", "/path/to/fonts/palab.ttf" },
{ "IPalatino Linotype Kursiv", "/path/to/fonts/palai.ttf" },
{ "PPalatino Linotype Fett Kursiv", "/path/to/fonts/palabi.ttf" },

{ " Gentium Plus", "/path/to/fonts/GentiumPlus-R.ttf" },
{ "BGentium Plus", "/path/to/fonts/GentiumPlus-R.ttf" },
{ "IGentium Plus Italic", "/path/to/fonts/GentiumPlus-I.ttf" },
{ "PGentium Plus Italic", "/path/to/fonts/GentiumPlus-I.ttf" },

#else // Linux: the "simple" way (no need to adjust font names)

{ " GFSArtemisia", "/path/to/fonts/GFSArtemisia.otf" },
{ "BGFSArtemisia", "/path/to/fonts/GFSArtemisiaBold.otf" },
{ "IGFSArtemisia", "/path/to/fonts/GFSArtemisiaIt.otf" },
{ "PGFSArtemisia", "/path/to/fonts/GFSArtemisiaBoldIt.otf" },

{ " Palatino Linotype", "/path/to/fonts/pala.ttf" },
{ "BPalatino Linotype", "/path/to/fonts/palab.ttf" },
{ "IPalatino Linotype", "/path/to/fonts/palai.ttf" },
{ "PPalatino Linotype", "/path/to/fonts/palabi.ttf" },

{ " Gentium Plus", "/path/to/fonts/GentiumPlus-R.ttf" },
{ "BGentium Plus", "/path/to/fonts/GentiumPlus-R.ttf" },
{ "IGentium Plus", "/path/to/fonts/GentiumPlus-I.ttf" },
{ "PGentium Plus", "/path/to/fonts/GentiumPlus-I.ttf" },

#endif

{ NULL, NULL }
};

Loading the font is then cross platform like this:

fontdef_t *ft = &font[fn]; // internal font definition

/* Load the font using the appropriate platform API */
loaded_font = i_load_private_font(ft->file);

/* set the extra font */
if (loaded_font) {
Fl::set_font(test_font + fn, ft->name);

Note that I load all fonts in all variants and select one (test_font +
fn) for display. The GentiumPlus font doesn't have all four variants
(only a regular and an italic variant). Under Linux the bold variants
seem to be created on the fly (pretty well), whereas Windows seems to
use the fonts as-is (no artificial bolding).

This works so far (Windows and Linux), but I think there should be an
easier way to retrieve the font name that is required to assign the FLTK
font (under Windows) - or did I do anything wrong?

How to get the "font name" from the font file if you have an arbitrary
(maybe user-supplied) font file?


Do you know of a better way for Windows?

Albrecht Schlosser

unread,
Jan 23, 2018, 3:04:17 PM1/23/18
to fltkg...@googlegroups.com
On 23.01.2018 20:28 Albrecht Schlosser wrote:

> Here is what I got so far:
> ...

FWIW: I'm attaching my full modified program and an image of 6 instances
of the demo program running under Windows (left hand and middle column)
and Linux (right hand side). The middle and right columns have the same
setup and should be comparable (they are pretty similar). Note that I
didn't use pango nor do I have the musical notes font installed. The
font is always the same but with different styles.

I hope it's useful for someone...

If you want to use it you'll have to adjust the paths and font names and
you need some suitable font files.
load_font_from_file.cxx
load_font_from_file.png

Ian MacArthur

unread,
Jan 23, 2018, 5:43:38 PM1/23/18
to fltkg...@googlegroups.com
Hi Albrecht,


> On 23 Jan 2018, at 19:28, Albrecht Schlosser wrote:
>
> On 22.01.2018 23:26 Ian MacArthur wrote:
>
>> There’s no fltk API for that, but it’s fairly easy to do with only a little platform specific code on the 3 main platforms I usually target (X11+XFT, Win32, OSX).
>
> Thank you very much for the example code. I tested it with some example fonts (.ttf and .otf) and it basically worked. But it seems somewhat fragile when it comes to loading the font because you need the real/exact font name when loading the font (AFAICT). How do we get (or guess) the font name? Here is what I mean (other parts of your code elided):


Well, I don’t really know the context of deech’s question, but I interpreted it as asking how to load some special application specific font...

The approach I show is a pretty rubbish way of loading fonts in the general case - you are far better putting them somewhere the OS will find them by “normal” means then, and just using the normal fltk font handling methods.

However if you have some special font that your application needs (e.g. in my original case some special musical notation glyphs...) then I’m proceeding on the assumption that you already know the name of your font file, and presumably also know the “given names” of the faces within the file (which is true in my case, at any rate!) and so this issue doesn’t really arise.

I just hard code the actual name of the font face (occasionally with an ifdef to help out, if the OS presents the name differently.)

Latterly, as with the "fltk-test-regular.otf” font used here, I’ve been using a font editor to collate my own collections of glyphs, and so I have control of the names too.
How useful that is for other users though...



>
>> /*****************************************************************************/
>> static void load_extra_font(void)
>> {
>> /* Load the font using the appropriate platform API */
>> loaded_font = i_load_private_font("./font/fltk-test-regular.otf");
>> /* set the extra font */
>> if (loaded_font)
>> {
>
> In your example the font file is "fltk-test-regular.otf" and you assign the font to the chosen FLTK font number with:
>
>> Fl::set_font(test_font, "fltk");
>> }
>> } // load_extra_font
>
> In my experiments I was likely always successful if I used the fonts under Linux, but it was harder under Windows. I believe there is a difference if the font is installed under Windows so I tried to use some (open source, free license) Linux or other downloaded fonts. I defined a simple struct that associates the FLTK font name with the given font file name and used this similarly to your example above. Here is what I came up finally with three example fonts that can all be loaded as regular, bold, italic, and bold italic. Note that the Windows font "Palatino Linotype" has German names on my German Windows machine.
>
> I used the Windows built-in font viewer to see/guess font names for Windows because the short Linux font name didn't work. Here is what I got so far:
>
> typedef struct fontdef_ {
> const char *name; // FLTK font name (1st char = { ' ' | 'B' | 'I' | 'P' }
> const char *file; // system font (file) name to load
> } fontdef_t;


There’s a bit of a trick to the fltk font name 1st character thing, in that the matching of the first glyph is case sensitive, but matching of the font face name generally appears not to be.

So you can’t, for example, ask for “Palatino” and get the right thing, since the leading “P” is interpreted as bold+italic, and so on.

However, if you ask for “palatino” it doesn’t match the “P”, nor does it match “ “, “B”, or “I”, so then falls back to trying the whole name, which usually does then match OK... Well, it does for me at any rate.

If you look at the code, e.g. fl_font_xft.cxx, fl_font_win32.cxx, etc, are littered with variants of this switch:

switch (*name++) {
case 'I': italic = 1; break;
case 'P': italic = 1;
case 'B': weight = FW_BOLD; break;
case ' ': break;
default: name--;
}


Where basically we look for the “ “, I, P, B and if they are not present we step back to using the whole name and present that to the font engine verbatim.

Though I’m not sure if that helps with your question or not?


>
> Note that I load all fonts in all variants and select one (test_font + fn) for display. The GentiumPlus font doesn't have all four variants (only a regular and an italic variant). Under Linux the bold variants seem to be created on the fly (pretty well), whereas Windows seems to use the fonts as-is (no artificial bolding).
>

The X11+XFT setup will fake bolding, in essence by “overstriking” the glyph, just like in the olden days!

TBH, I thought Windows did too (I’m pretty sure it used to...) but haven’t really tried.


> This works so far (Windows and Linux), but I think there should be an easier way to retrieve the font name that is required to assign the FLTK font (under Windows) - or did I do anything wrong?
>
> How to get the "font name" from the font file if you have an arbitrary (maybe user-supplied) font file?
>
>
> Do you know of a better way for Windows?


I’ve never really tried to get the “actual” names under Windows from a raw font file, though I’m sure it must be possible!

FLTK can do it for a font, once it is loaded, if you use Fl::get_font_name(...), it can return the name - I think our Fl_Fontdesc struct holds two names in effect, one in “fontname” and one in “name” where “fontname” is the “pretty” name extracted from the face, and “name” is what we load it as. Or something...

Anyway:

The only time something similar came up, I let the user load their supplied “private” font file using basically the code I showed before, e.g. using AddFontResourceEx() etc under Windows, or FcConfigAppFontAddFile() under XFT, and then loaded *all* the fonts (basically using font_count = Fl::set_fonts("*”); and etc) and then displayed a font chooser widget (based on the same code as the one I hacked up for the utf8 test program) and allowed the user to select a font face from there.

I then stored the selected name in an fl_preferences widget, so that I could use the name again next time. So I never actually extracted the name, I let the user find it...

Anyway, worked well enough I guess.

Is there some specific thing we need to fix here, or...?

Cheers,
--
Ian


Albrecht Schlosser

unread,
Jan 24, 2018, 11:42:42 AM1/24/18
to fltkg...@googlegroups.com
Hi Ian,

On 23.01.2018 23:43 Ian MacArthur wrote:
> Hi Albrecht,
>
> Well, I don’t really know the context of deech’s question, but I interpreted it as asking how to load some special application specific font...

And so did I. My case is similar, hence I tested your code to see if it
fits my purpose. I'm developing a private application with a potential
tiny user group (3 or 4 persons). The first person is me, and I'd like
to develop and use the application under Linux, the other potential
users must be assumed to know absolutely nothing about software
installation and such, and they are all Windows users. My app includes a
small sqlite3 database (i.e. one external file) and needs a special font
for printing and pdf generation. Basically printing can also use pdf
files, so I'm using libharu/hpdf for this. I found out that libharu can
embed a font in the pdf file, so this is all fine and working. The font
is the second external file my application needs.

I thought of embedding a font somehow (I'm still investigating this,
especially for Windows) and I believe I can manage to do this, but I'd
also like a cross platform solution with an external font file.

> The approach I show is a pretty rubbish way of loading fonts in the general case - you are far better putting them somewhere the OS will find them by “normal” means then, and just using the normal fltk font handling methods.

That would be fine if I could assume that my potential users could and
would install a special font under their Windows version. AFAICT the
current font in question (Palatino Linotype, see my example) is
available under Windows 10, but at least one user has Windows 7 and I
currently don't know if it is available under Win7, but I can likely
find this out.

> However if you have some special font that your application needs (e.g. in my original case some special musical notation glyphs...) then I’m proceeding on the assumption that you already know the name of your font file, and presumably also know the “given names” of the faces within the file (which is true in my case, at any rate!) and so this issue doesn’t really arise.

That's true in the special case I need. But I was wondering how it would
be in a more general case.

> I just hard code the actual name of the font face (occasionally with an ifdef to help out, if the OS presents the name differently.)

Yep, that's what I did now.

> Latterly, as with the "fltk-test-regular.otf” font used here, I’ve been using a font editor to collate my own collections of glyphs, and so I have control of the names too.
> How useful that is for other users though...

I wouldn't go so far. It's a very small application and what I need is
really only one ready-to-use font. But thanks for sharing your solution.

>> I used the Windows built-in font viewer to see/guess font names for Windows because the short Linux font name didn't work.

Maybe I should have written "because the short Linux font name didn't
_always_ work". One example is the "GFS Artemisia" font. Under Linux I
get with the utf8 demo (thanks for that and the hint in your other
posting, btw.):

$ bin/examples/utf8
idx 123
User name :GFS Artemisia:
FLTK name : GFS Artemisia:
size 16

idx 124
User name :GFS Artemisia bold:
FLTK name :BGFS Artemisia:
size 16

idx 125
User name :GFS Artemisia italic:
FLTK name :IGFS Artemisia:
size 16

BTW: I don't see "GFS Artemisia bold italic" in the list of fonts in the
utf8 font selector although I have all four font files (Ubuntu 16.04):

/usr/share/fonts/truetype/artemisia/GFSArtemisiaIt.otf
/usr/share/fonts/truetype/artemisia/GFSArtemisiaBold.otf
/usr/share/fonts/truetype/artemisia/GFSArtemisia.otf
/usr/share/fonts/truetype/artemisia/GFSArtemisiaBoldIt.otf

WRT Windows: I think I got the "FLTK font name" wrong with this
particular font. Windows shows something that looks like a font name in
the window title displaying the font when you double-click on the font
file in the explorer. It also shows the "font name" below in the window
which is in this case "GFS Artemisia" (with a space between "GFS" and
"A.."). I missed this space and used the font names from the window
title which seemed to work (see my posted example program) but now I see
that "GFS Artemisia" works well in all 4 font faces (regular, bold,
italics, and bold italics). So this issue is resolved. Thanks for your help.

>> Here is what I got so far:
>>
>> typedef struct fontdef_ {
>> const char *name; // FLTK font name (1st char = { ' ' | 'B' | 'I' | 'P' }
>> const char *file; // system font (file) name to load
>> } fontdef_t;
>
>
> There’s a bit of a trick to the fltk font name 1st character thing, in that the matching of the first glyph is case sensitive, but matching of the font face name generally appears not to be.

Interesting. I didn't know that the font name would match case insensitive.

> So you can’t, for example, ask for “Palatino” and get the right thing, since the leading “P” is interpreted as bold+italic, and so on.

That's why I always used one leading character, with a space for the
regular font. This seems to work always (Windows and Linux). I think
it's also documented this way, hence we should encourage users to do it
like this to avoid ambiguities.

> However, if you ask for “palatino” it doesn’t match the “P”, nor does it match “ “, “B”, or “I”, so then falls back to trying the whole name, which usually does then match OK... Well, it does for me at any rate.

See above. I think always using a space or B, I, P is to be preferred.

> If you look at the code, e.g. fl_font_xft.cxx, fl_font_win32.cxx, etc, are littered with variants of this switch:
>
> switch (*name++) {
> case 'I': italic = 1; break;
> case 'P': italic = 1;
> case 'B': weight = FW_BOLD; break;
> case ' ': break;
> default: name--;
> }
>
>
> Where basically we look for the “ “, I, P, B and if they are not present we step back to using the whole name and present that to the font engine verbatim.

I'd seen this, but I missed the "default: name--;" case so I got the
impression that you'd always need a leading character which is not true
as you pointed out, but I'll use it in my code anyway.

> Though I’m not sure if that helps with your question or not?

I knew that particular bit of your answer(s), but everything else really
helped. Thanks again.

>> Note that I load all fonts in all variants and select one (test_font + fn) for display. The GentiumPlus font doesn't have all four variants (only a regular and an italic variant). Under Linux the bold variants seem to be created on the fly (pretty well), whereas Windows seems to use the fonts as-is (no artificial bolding).
>
> The X11+XFT setup will fake bolding, in essence by “overstriking” the glyph, just like in the olden days!

Yep, that's what I saw in my tests.

> TBH, I thought Windows did too (I’m pretty sure it used to...) but haven’t really tried.

You're correct. I tested again, and (if you use the correct font names
and the regular font file, then) it does. Of course the original font
files have a much better quality, but Windows does it also with the
"regular" font file in all cases. Sorry for the noise...

>> This works so far (Windows and Linux), but I think there should be an easier way to retrieve the font name that is required to assign the FLTK font (under Windows) - or did I do anything wrong?
>>
>> How to get the "font name" from the font file if you have an arbitrary (maybe user-supplied) font file?
>>
>>
>> Do you know of a better way for Windows?
>
>
> I’ve never really tried to get the “actual” names under Windows from a raw font file, though I’m sure it must be possible!
>
> FLTK can do it for a font, once it is loaded, if you use Fl::get_font_name(...), it can return the name - I think our Fl_Fontdesc struct holds two names in effect, one in “fontname” and one in “name” where “fontname” is the “pretty” name extracted from the face, and “name” is what we load it as. Or something...

Thanks for this as well. I'll try that and investigate a little more.

> Anyway:
>
> The only time something similar came up, I let the user load their supplied “private” font file using basically the code I showed before, e.g. using AddFontResourceEx() etc under Windows, or FcConfigAppFontAddFile() under XFT, and then loaded *all* the fonts (basically using font_count = Fl::set_fonts("*”); and etc) and then displayed a font chooser widget (based on the same code as the one I hacked up for the utf8 test program) and allowed the user to select a font face from there.
>
> I then stored the selected name in an fl_preferences widget, so that I could use the name again next time. So I never actually extracted the name, I let the user find it...
>
> Anyway, worked well enough I guess.

Good approach. Would be at least a "Plan B".

> Is there some specific thing we need to fix here, or...?

Not really. But after all my struggling I could imagine to add a feature
(request) to set a FLTK font directly from a font file. Instead of using
platform specific code in the app and then to use the font name with

Fl::set_font(font_number, font_name);

I could imagine a new or overloaded function

Fl::set_font[_from_file](Fl_Font font_number, [int mode,] const char
*file_or_name);

Given your code for all major supported platforms this should be doable.

What do you and other devs (and users) think of such an extension?

Another option would be to embed a font (somehow) and load the font from
this embedded resource, just like we can open jpg and png images from
memory. Something like that, maybe...

Webb Hinton

unread,
Jul 27, 2021, 11:17:32 PM7/27/21
to fltk.general
I also ran into the problem of needing to embed a font. It'd be great if we could load a font from embedded bytes, just like we can load an svg from embedded bytes via Fl_SVG_Image(), without the need for platform specific code. 

Another use case: what if we needed to load a font from some kind of online font service (as Photoshop currently does)? Doing something like this would be very tricky with the current font loading setup. 

Webb Hinton

unread,
Aug 5, 2021, 2:05:12 AM8/5/21
to fltk.general
Another option would be to embed a font (somehow) and load the font from
this embedded resource, just like we can open jpg and png images from
memory. Something like that, maybe...

Are people still interested in this idea?
On Wednesday, January 24, 2018 at 11:42:42 AM UTC-5 Albrecht Schlosser wrote:

Albrecht Schlosser

unread,
Aug 5, 2021, 4:42:32 AM8/5/21
to fltkg...@googlegroups.com
On 8/5/21 8:05 AM Webb Hinton wrote:
Another option would be to embed a font (somehow) and load the font from
this embedded resource, just like we can open jpg and png images from
memory. Something like that, maybe...

I've been working with Ian's platform specific code and I have demo code somewhere which loads a font from a ttf or similar file. This works fine. Embedding a font in binary form in a program would likely be more involved because the platform specific code Ian provided does only load from a file. ISTR that e.g. Windows can load from "font resources" but I don't know how to "build" such a resource.


Are people still interested in this idea?

I'm still interested but for now I have working code for myself.

We could probably add a public method to load a font from a font file to hide the platform specific code with what we have already.

If you need to bundle the font in binary form inside the program you could convert the file to a binary image (e.g. with xxd), compile it into the program, and write it to a temporary file to load it.

Reply all
Reply to author
Forward
0 new messages