Add "no font mapper" switch to LoadFont()

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
User avatar
heartbone
Addict
Addict
Posts: 1058
Joined: Fri Apr 12, 2013 1:55 pm
Location: just outside of Ferguson

Add "no font mapper" switch to LoadFont()

Post by heartbone »

I remain surprised that there is not a FontExists(FontName$) command in PureBasic.
It seems much less efficient to load a font and then test for a load failure to learn if a font is on the computer.
But no, it seems that PureBasic has its own special way of handling fonts by using something called a "font mapper".
This functionality prevents the use of the IsFont(#font) command to test for a font's successful loading.

For Windows® there is a hack to provide a FontExists() equivalent in PureBasic, but I know not a replacement for FontExists() in Linux.
Obviously by using such a command, the undesirable font mapping could be prevented.

When dealing with computers I am used to logical events, and asking for one font and getting another does not seem very logical.
Using PureBasic, when I instruct the computer to load "Random Font", there is no positive way to ascertain that the font was loaded or not loaded... or even what was loaded.
WTF?

Specific fonts can be an important part of many computer programs.
In my opinion this "font mapper" is not even a halfway good implementation of a questionable idea, because the replacement font is not well mapped in Linux. I can expand on the deficiencies if needed.

Without success, I looked at the LoadFont() command return codes to see if I could detect when the font mapper was invoked so I could use that information to adjust the program.

Please allow a switch into LoadFont() command to shut the font mapping off.
This would allow the IsFont() check to be used to detect if there is a need for a fallback font.


And/Or


Add the FontExists(FontName$) command.
This would allow Linux programs to have needed functionality.
Keep it BASIC.
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Re: Add "no font mapper" switch to LoadFont()

Post by Rescator »

heartbone wrote:But no, it seems that PureBasic has its own special way of handling fonts by using something called a "font mapper".
False!

Do not blame PureBasic for the font mapping. It is the OS that does this, and which font is used varies depending on the installed OS language pack, and what font's are installed on the system.

It is Windows that does the font mapping.
This always guarantees that text can be rendered.

In the event a font does not exist the closest match will always be picked so if a Sans-Serif type font is asked for but is not available then another Arial may be returned instead.
After all, if a program asks for a font and it is not available, should no text be show at all to the user? Just a blank message box or window?

I'm pretty sure Linux, Mac, Android whatever has a similar font mapper as part of the OS.
heartbone wrote:Add the FontExists(FontName$) command.
This however has some merit. Sadly the EnumFontFamiliesEx is only partly useful, you must provide a device context.
This means that a window on Monitor 1 may have "Supra Fine" available but for some reason a window on Monitor 2 may not have it available. (why? either due to OS/user preferences, DPI monitor/screen settings or Monitor 2 is not a normal monitor.)
I have no idea if other OS also behaves in a similar way.

In one of my own programs I use the Windows API directly to load a font from the program folder, and in such a way that the font is only available to the current program (and not available to all programs on the system).

For those curious I use this AddFontResourceEx (MSDN)
With the FR_PRIVATE flag.

If the font fail to load then it fails to load and I have to have code myself to deal with that scenario as the OS can not help me here at all.


Another, and in my opinion better way could be to add a FontName() command which gets the name of the font loaded by LoadFont()
That way you can simply do

Code: Select all

If FontName(#Font) = "Times New Roman"
   Debug "Yay! The right font was loaded."
EndIf
And if the font is not a match then you can choose to use either use it/inform the user of it,
or choose to not to use it and inform the user of this.


I'd rather see a LoadFontfile() and a FontName() myself, allowig to load custom fots for this program only, and to show the name of watever font LoadFont() loaded.


PS! The OS fontmapper does a few other interesting things. Certain bitmap fonts may only be available at small sizes and the fontmapper will then use a diffr4ent (but otherwise matching/similar font type) for larger sizes. That way your program won't fail to show text just because the user changed from 12pt to 24pt font in the font dialog on a bitmap font that only has bitmaps for max 12pt fonts.
User avatar
heartbone
Addict
Addict
Posts: 1058
Joined: Fri Apr 12, 2013 1:55 pm
Location: just outside of Ferguson

Re: Add "no font mapper" switch to LoadFont()

Post by heartbone »

Rescator wrote:
heartbone wrote:But no, it seems that PureBasic has its own special way of handling fonts by using something called a "font mapper".
False!

Do not blame PureBasic for the font mapping. It is the OS that does this, and which font is used varies depending on the installed OS language pack, and what font's are installed on the system.

It is Windows that does the font mapping.
This always guarantees that text can be rendered.
I believe that your "False!" declaration is not true.
Automatic use of the font mapper is the PureBasic way. Other BASICs don't use it.
I am confident that the compiler designers made a decision to use the font mapper, and I seriously doubt if it was a mandatory inclusion.
And its use does not guarantee that the font will render correctly, just a guarantee that a font was loaded to render.
Rescator wrote:In the event a font does not exist the closest match will always be picked so if a Sans-Serif type font is asked for but is not available then another Arial may be returned instead.
After all, if a program asks for a font and it is not available, should no text be show at all to the user? Just a blank message box or window?
Only if the programmer is inept.

The rest of your post seems valid, and your alternate suggestion would be another way to skin that cat.
Either way would be better than what I do now.
Right now (for Linux) I have to resort to checking the results from the TextWidth() function to determine if the mystery font loaded by LoadFont() is suitable for the program's use.

And if you ever figure out how to load and use a local font in Linux, kindly share that knowledge, because that is something that is lacking from mine, and is truly needed.
Keep it BASIC.
User avatar
Rescator
Addict
Addict
Posts: 1769
Joined: Sat Feb 19, 2005 5:05 pm
Location: Norway

Re: Add "no font mapper" switch to LoadFont()

Post by Rescator »

heartbone wrote:Automatic use of the font mapper is the PureBasic way. Other BASICs don't use it.
I am confident that the compiler designers made a decision to use the font mapper, and I seriously doubt if it was a mandatory inclusion.
And its use does not guarantee that the font will render correctly, just a guarantee that a font was loaded to render.
Which is all done by the OS.
PureBasic (on Windows) only calls the Win32 OS API, either CreateFont or CreateFontIndirect or CreateFontIndirectEx. The OS does automatic font mapping (for all three). Read more here: http://msdn.microsoft.com/en-us/library/dd183499.aspx

If other languages does not do it then that is because they have extra code that does a name check, or they lookup the font in the registry and directly load the file.
PureBasic (on Windows) does not actually load the fonts at all, the entire workload related to that is offloaded to the OS (the GDI library to be exact).

A lot of software also uses FreeType which is a font loading library, you might want to look into that if you do not like the way the Windows API loads fonts.
On Linux I'm guessing GTK and other GUIs actually uses FreeType.
heartbone wrote:Right now (for Linux) I have to resort to checking the results from the TextWidth() function to determine if the mystery font loaded by LoadFont() is suitable for the program's use.
Designing a UI to work with any font provided the size/metrics are the same is a good practice.
heartbone wrote:And if you ever figure out how to load and use a local font in Linux, kindly share that knowledge, because that is something that is lacking from mine, and is truly needed.
Never had the time to explore PureBasic and Linux, but look into FreeType.


Most people think of font's as these small .otf or .ttf files, but it's not, a font mapper/engine/loader is needed and they can be surprisingly complex.

As far as I know you can not "disable" the font mapper on Windows, but it is possible to give it very tight restrains to ensure the font mapper gives you font characters as close as possible to what you want. By default the settings are very flexible. You can use the minus sing "-" in-front of a font size in PureBasic for example (this triggers a different font mapping on Windows).

You should also be aware that on Windows, if the virtualization (Vista+) stuff kicks in then font mapping "may" be forced to behave a certain way, you may need to add te correct manifest to your exe to avoid this.
User avatar
heartbone
Addict
Addict
Posts: 1058
Joined: Fri Apr 12, 2013 1:55 pm
Location: just outside of Ferguson

Re: Add "no font mapper" switch to LoadFont()

Post by heartbone »

Thanks Rescator, for digging into that convoluted topic.
I stand corrected.

As you've indicated, it looks like the compiler developers developed a font loading solution that works according to the OS constraints, and my request is not practical.

I'll do the best that I can to correct any odd mappings in software, but ultimately I'll need to advise the users to install a particular font to obtain the best looking display if the automatically mapped font is unsuitable.
Keep it BASIC.
Post Reply