Page 1 of 1

Get windows font details

Posted: Wed May 01, 2024 7:37 pm
by Michael Vogel
I'd like to see all variations (and their names for LoadFont) of one (or all) installed font(s). Some font fmilies do have different types like bold, black, semibold, light, italics, etc.

The font family 'Courier New' has 4 types (regular, italics, bold, bold+italics) which is displayed in the windows font settings.
When enumerating this font family I do get a list of around 20 entries missing also more detailed information (see code)

Code: Select all

Procedure EnumFontInfo(*elfx.ENUMLOGFONTEX,*ntmx.NEWTEXTMETRICEX,FontType.i,lParam.i)

	Debug Str(*ntmx\ntmTm\tmPitchAndFamily)+", "+Str(*ntmx\ntmTm\tmAveCharWidth)+"*"+Str(*ntmx\ntmTm\tmHeight)+", "+Str(*ntmx\ntmTm\tmWeight)+" : "+PeekS(@*elfx\elfLogFont\lfFaceName[0])
	
	ProcedureReturn #True

EndProcedure
Procedure EnumFontList(font.s)

	Protected FontLog.LOGFONT
	Protected FontHDC
	Protected Fontname.s
	
	FontHDC=GetDC_(WinID)
	FillMemory(@FontLog,SizeOf(LOGFONT))
	FontLog\lfCharSet=#DEFAULT_CHARSET
	PokeS(@FontLog\lfFaceName,font)

	If EnumFontFamiliesEx_(FontHDC,@FontLog,@EnumFontInfo(),0,0)
		ProcedureReturn #True
	Else
		ProcedureReturn #False
	EndIf

EndProcedure

;Debug EnumFontList("")
Debug EnumFontList("Courier New")

Re: Get windows font details

Posted: Thu May 02, 2024 7:48 am
by pjay
If I've understood your question properly, it'd be because each font can contain a number of character sets as well as the styles you mentioned:

Code: Select all

Global NewMap tm_Charset.s()
tm_Charset("0") = "ANSI_CHARSET" : tm_Charset("1") = "DEFAULT_CHARSET" : tm_Charset("2") = "SYMBOL_CHARSET"
tm_Charset("77") = "MAC_CHARSET" : tm_Charset("128") = "SHIFTJIS_CHARSET" : tm_Charset("129") = "HANGEUL_CHARSET"
tm_Charset("130") = "JOHAB_CHARSET" : tm_Charset("134") = "GB2312_CHARSET" : tm_Charset("136") = "CHINESEBIG5_CHARSET"
tm_Charset("161") = "GREEK_CHARSET" : tm_Charset("162") = "TURKISH_CHARSET"  : tm_Charset("163") = "VIETNAMESE_CHARSET" : tm_Charset("177") = "HEBREW_CHARSET" 
tm_Charset("178") = "ARABIC_CHARSET" : tm_Charset("186") = "BALTIC_CHARSET" : tm_Charset("204") = "RUSSIAN_CHARSET"
tm_Charset("222") = "THAI_CHARSET" : tm_Charset("238") = "EASTEUROPE_CHARSET" : tm_Charset("255") = "OEM_CHARSET"
Global NewMap tm_flag.s()
tm_flag("01") = "Italic " : tm_flag("11") = "Underscore " : tm_flag("21") = "Negative "
tm_flag("31") = "Outline " : tm_flag("41") = "Strikeout " : tm_flag("51") = "Bold "

Macro GetBit(num,bit) : (num >> bit) & 1 : EndMacro

Procedure EnumFontInfo(*elfx.ENUMLOGFONTEX,*ntmx.NEWTEXTMETRICEX,FontType.i,lParam.i)
  Protected myLoop, txt.s, *tmCharSet_asc.ascii = @*ntmx\ntmTm\tmCharSet : Static entries : entries + 1
  txt = Str(entries) + ": "+PeekS(@*elfx\elfLogFont\lfFaceName[0])+": " + tm_Charset(Str(*tmCharSet_asc\a)) + " "
  For myloop = 0 To 5 : txt + tm_flag(Str(myLoop)+Str(GetBit(*ntmx\ntmTm\ntmFlags,myloop))) : Next
  Debug txt
  ProcedureReturn #True
EndProcedure
Procedure EnumFontList(font.s)
  Protected FontLog.LOGFONT
	Protected FontHDC
	Protected Fontname.s
	
	FontHDC=GetDC_(WinID)
	FillMemory(@FontLog,SizeOf(LOGFONT))
	FontLog\lfCharSet=#DEFAULT_CHARSET
	PokeS(@FontLog\lfFaceName,font)

	If EnumFontFamiliesEx_(FontHDC,@FontLog,@EnumFontInfo(),0,0)
		ProcedureReturn #True
	Else
		ProcedureReturn #False
	EndIf
EndProcedure

Debug EnumFontList("Courier New")
;Debug EnumFontList("")

Re: Get windows font details

Posted: Fri May 03, 2024 10:29 pm
by charvista
- And how to get (with Windows' API if no native code exists) the font name that can be used in LoadFont() from the filename "MyFont.ttf"?
- And how to get the total number of characters the font file contains?
- And how to get the list of characters available (not empty) available in a font?
:wink:

Re: Get windows font details

Posted: Sat May 04, 2024 7:35 am
by Michael Vogel
I don't get any information about a font being italic or bold nor the file name needed to load this font.

Using pjays code (see below) to show details for all fonts starting with "Century751" does produce the following output here:
1: Century751 BT: ANSI_CHARSET
2: Century751 BT: TURKISH_CHARSET
3: Century751 No2 BT: ANSI_CHARSET
4: Century751 No2 BT: TURKISH_CHARSET
5: Century751 SeBd BT: ANSI_CHARSET
6: Century751 SeBd BT: TURKISH_CHARSET

The windows font settings do show 2 types for the 'BT' and 'SeBD' families (Roman and Italic) and 4 types for the 'No2 BT' font (Roman, Italic, Bold, Bold Italic).

So what will happen when using LoadFont(1,"...",24) with font names like...
... "Century751 BT"
... "Century751 BT Regular"
... "Century751 BT Roman"
... "Century751 BT Normal"
... "Century751 BT Bold"
... "Century751 BT Italic"
... "Century751 No2 BT Italic Bold"
... "Century751 No2 BT Bold Italic"

Which one will load an existing font? How do I know that "Century751 SeBd" is just a semibold variant of "Century751 BT"?
Seems more complicated than I thought :lol:

I would like to create a font requester showing only the font families and all existing types for them to choose from. Next step would be a filter to show italic or mono spaced fonts only, etc. This would keep the list smaller, otherwise you have to scroll around a while to find the font you are searching for.

Code: Select all

Global NewMap tm_Charset.s()
tm_Charset("0") = "ANSI_CHARSET" : tm_Charset("1") = "DEFAULT_CHARSET" : tm_Charset("2") = "SYMBOL_CHARSET"
tm_Charset("77") = "MAC_CHARSET" : tm_Charset("128") = "SHIFTJIS_CHARSET" : tm_Charset("129") = "HANGEUL_CHARSET"
tm_Charset("130") = "JOHAB_CHARSET" : tm_Charset("134") = "GB2312_CHARSET" : tm_Charset("136") = "CHINESEBIG5_CHARSET"
tm_Charset("161") = "GREEK_CHARSET" : tm_Charset("162") = "TURKISH_CHARSET"  : tm_Charset("163") = "VIETNAMESE_CHARSET" : tm_Charset("177") = "HEBREW_CHARSET"
tm_Charset("178") = "ARABIC_CHARSET" : tm_Charset("186") = "BALTIC_CHARSET" : tm_Charset("204") = "RUSSIAN_CHARSET"
tm_Charset("222") = "THAI_CHARSET" : tm_Charset("238") = "EASTEUROPE_CHARSET" : tm_Charset("255") = "OEM_CHARSET"
Global NewMap tm_flag.s()
tm_flag("01") = "Italic " : tm_flag("11") = "Underscore " : tm_flag("21") = "Negative "
tm_flag("31") = "Outline " : tm_flag("41") = "Strikeout " : tm_flag("51") = "Bold "

Macro GetBit(num,bit) : (num >> bit) & 1 : EndMacro

Procedure EnumFontInfo(*elfx.ENUMLOGFONTEX,*ntmx.NEWTEXTMETRICEX,FontType.i,lParam.i)

	Protected name.s
	name=PeekS(@*elfx\elfLogFont\lfFaceName[0])
	If Left(name,10)="Century751"
		Protected myLoop, txt.s, *tmCharSet_asc.ascii = @*ntmx\ntmTm\tmCharSet : Static entries : entries + 1
		txt = Str(entries) + ": "+PeekS(@*elfx\elfLogFont\lfFaceName[0])+": " + tm_Charset(Str(*tmCharSet_asc\a)) + " "
		For myloop = 0 To 5 : txt + tm_flag(Str(myLoop)+Str(GetBit(*ntmx\ntmTm\ntmFlags,myloop))) : Next
		Debug txt
	EndIf
	ProcedureReturn #True

EndProcedure
Procedure EnumFontList(font.s)
	Protected FontLog.LOGFONT
	Protected FontHDC
	Protected Fontname.s

	FontHDC=GetDC_(WinID)
	FillMemory(@FontLog,SizeOf(LOGFONT))
	FontLog\lfCharSet=#DEFAULT_CHARSET
	PokeS(@FontLog\lfFaceName,font)

	If EnumFontFamiliesEx_(FontHDC,@FontLog,@EnumFontInfo(),0,0)
		ProcedureReturn #True
	Else
		ProcedureReturn #False
	EndIf
EndProcedure

;Debug EnumFontList("Courier New")
EnumFontList("")

Re: Get windows font details

Posted: Sun May 05, 2024 12:47 pm
by boddhi
I'm not at all an expert on fonts but I have worked a little on the subject (see this topic and this topic) and I will try to provide you with some details which may perhaps help you.

Independently of charsets, Windows uses 3 types of data to manage fonts: Family, subfamily and style.
The family and the style to discriminate them and the subfamily to gender the font.
In theory, the first two data are used to precisely identify the font in the event of a call and the third to allow one font to be substituted by another when it has not been found.
I say in theory because in reality this data is declared at the discretion of the foundry or the creator.

And here is the drama, everyone does a little bit of everything and anything!!!

Some use only the family to discriminate between name and style, others, more rigorously, use both types of data.
Another interesting detail that you should know is that the same font may have been taken over by another founder or creator, slightly modified in its graphic appearance and given another family name (often to add their foundry name: e.g. BT, LT, SSF, etc.) and/or another style class even though it is basically the same family...

So that sometimes for the same font, we can have a good method:
Family font name: "FamilyFontName" - Style: Normal
Family font name: "FamilyFontName" - Style: Italic
Family font name: "FamilyFontName" - Style: Bold
Family font name: "FamilyFontName" - Style: Bold Italic
        Here, Windows will group under the same name (FamilyFontName) with 4 different styles

and a shitty method:
Family font name: "FamilyFontName Normal" - Style: Normal
Family font name: "FamilyFontName Italic" - Style: Normal
Family font name: "FamilyFontName Bold" - Style: Normal
Family font name: "FamilyFontName BoldItalic" - Style: Normal
        Here, Windows will treat each font as a different font with no particular connection between them.