Default font

Just starting out? Need help? Post your questions and find answers here.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Default font

Post by blueznl »

I'm sure I must have seen it somewhere, but I cannot find it back... how to find the default Font (name, size, type) that PB is using before actually loading another font?

I found this one: http://www.purebasic.fr/english/viewtop ... fautl+font (notice the misspelling, that's how I found it :-)) but isn't there an 'onboard' cross platform solution in PureBasic?

<edit>

Okay, figured out most of the stuff. Scroll to the bottom for updated code.
Last edited by blueznl on Tue Jul 30, 2013 10:55 pm, edited 1 time in total.
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
User avatar
Andre
PureBasic Team
PureBasic Team
Posts: 2137
Joined: Fri Apr 25, 2003 6:14 pm
Location: Germany (Saxony, Deutscheinsiedel)
Contact:

Re: Default font

Post by Andre »

That's why I made this feature request: http://www.purebasic.fr/english/viewtop ... =3&t=53875

I think, knowing about the original OS system font settings is an important part for building GUI's in the user's OS standard look.
Bye,
...André
(PureBasicTeam::Docs & Support - PureArea.net | Order:: PureBasic | PureVisionXP)
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Default font

Post by blueznl »

At first glance it looks like Fred's using the default gui font.

I think I've also figured out how to convert to / from points sizewize. Not sure though if my DC code near the end is correct... (Experts feel free to have a look :-))

Code: Select all

logfont.LOGFONT
font_h = GetStockObject_(#DEFAULT_GUI_FONT)
If font_h > 0
  GetObject_(font_h, SizeOf(LOGFONT), @logfont)
  x_defaultguifontname.s = PeekS(@logfont\lfFaceName[0])
  x_defaultguifontsize.i = logfont\lfHeight
EndIf
;
logfont.LOGFONT
font_h = GetStockObject_(#SYSTEM_FONT)
If font_h > 0
  GetObject_(font_h, SizeOf(LOGFONT), @logfont)
  x_defaultsystemfontname.s = PeekS(@logfont\lfFaceName[0])
  x_defaultsystemfontsize.i = logfont\lfHeight
EndIf
;
nonclientmetrics.NONCLIENTMETRICS
nonclientmetrics\cbSize = SizeOf(nonclientmetrics)
SystemParametersInfo_(#SPI_GETNONCLIENTMETRICS,SizeOf(nonclientmetrics),@nonclientmetrics,0)
x_defaultmenufontname.s = PeekS(@nonclientmetrics\lfMenuFont\lfFaceName[0])
x_defaultmenufontsize.i = nonclientmetrics\lfMenuFont\lfHeight
x_defaultstatusfontname.s = PeekS(@nonclientmetrics\lfStatusFont\lfFaceName[0])
x_defaultstatusfontsize.i = nonclientmetrics\lfStatusFont\lfHeight
x_defaultmessagefontname.s = PeekS(@nonclientmetrics\lfMessageFont\lfFaceName[0])
x_defaultmessagefontsize.i = nonclientmetrics\lfMessageFont\lfHeight
;
;
OpenWindow(1,100,100,800,500,"Test",#PB_Window_SystemMenu)
TextGadget(1,20,10,700,30,"Test ABCXXX purebasic default")
;
TextGadget(2,20,40,700,30,"Test ABCXXX default gui font "+x_defaultguifontname+" "+Str(x_defaultguifontsize))
LoadFont(2,x_defaultguifontname,x_defaultguifontsize)
SetGadgetFont(2,FontID(2))
;
hdc = GetDC_(0)
height = 0 - ( x_defaultguifontsize * 72 / GetDeviceCaps_( hdc, #LOGPIXELSY ))
ReleaseDC_(0,hdc)
TextGadget(3,20,70,700,30,"Test ABCXXX default gui font "+x_defaultguifontname+" "+Str(height))
LoadFont(3,x_defaultguifontname,height)
SetGadgetFont(3,FontID(3))
;
TextGadget(4,20,100,700,30,"Test ABCXXX default menu font "+x_defaultmenufontname+" "+Str(x_defaultmenufontsize))
LoadFont(4,x_defaultmenufontname,x_defaultmenufontsize)
SetGadgetFont(4,FontID(4))
;
TextGadget(5,20,130,700,30,"Test ABCXXX "+x_defaultmenufontname+" "+Str(9))
LoadFont(5,x_defaultmenufontname,9)
SetGadgetFont(5,FontID(5))
;
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
User avatar
TI-994A
Addict
Addict
Posts: 2705
Joined: Sat Feb 19, 2011 3:47 am
Location: Singapore
Contact:

Re: Default font

Post by TI-994A »

blueznl wrote:...how to find the default Font (name, size, type) that PB is using before actually loading another font?
Hello blueznl. Nice code! However, if you just need the width and height of the default system font, the easiest and cross-platform approach would be to use the GetGadgetFont() function with the #PB_Default parameter:

Code: Select all

OpenWindow(0, 0, 0, 300, 300, "Get System Font")
DefaultFontID = GetGadgetFont(#PB_Default)

StartDrawing(WindowOutput(0))
DrawingFont(DefaultFontID)
  tHeight.s = "(" + Str(TextHeight("ABC")) + " px)"
  Debug "Default system font is:"
  If TextWidth("M") <> TextWidth("I")
    Debug "  Proportionately spaced " + tHeight
  Else
    Debug "  Fixed width " + tHeight
  EndIf
StopDrawing()
Usually, such requirements stem from the need to maintain conformity with the system UI, so the information returned by GetGadgetFont(#PB_Default) should suffice. :)
Texas Instruments TI-99/4A Home Computer: the first home computer with a 16bit processor, crammed into an 8bit architecture. Great hardware - Poor design - Wonderful BASIC engine. And it could talk too! Please visit my YouTube Channel :D
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Default font

Post by blueznl »

Ah okay. That makes sense. Now would it be possible to retrieve text height (which is actually not strictly the same as point size / font size) without opening a window?

Oh.... wait.... I think I know how to figure that one out, at least under windows...
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
ozzie
Enthusiast
Enthusiast
Posts: 443
Joined: Sun Apr 06, 2008 12:54 pm
Location: Brisbane, Qld, Australia
Contact:

Re: Default font

Post by ozzie »

blueznl wrote:Ah okay. That makes sense. Now would it be possible to retrieve text height (which is actually not strictly the same as point size / font size) without opening a window?

Oh.... wait.... I think I know how to figure that one out, at least under windows...
Not sure if you've already answered your own question, but you can modify TI-994A's code to use an image instead of a window so you don't have to open a window. For example:

Code: Select all

CreateImage(0,16,16)
DefaultFontID = GetGadgetFont(#PB_Default)

StartDrawing(ImageOutput(0))
  DrawingFont(DefaultFontID)
  tHeight.s = "(" + Str(TextHeight("ABC")) + " px)"
  Debug "Default system font is:"
  If TextWidth("M") <> TextWidth("I")
    Debug "  Proportionately spaced " + tHeight
  Else
    Debug "  Fixed width " + tHeight
  EndIf
StopDrawing()
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Default font

Post by blueznl »

The information on this page confuses the hell out of me:

http://msdn.microsoft.com/en-us/library ... 85%29.aspx

It would suggest that height > 0 are cell heights, and heights < 0 are character heights.

Now, cell heights are larger than character heights, at least that's what the graph on this page suggests:

http://support.microsoft.com/kb/74299

However, when I fool around a bit by interrogating the system, I get matching sizes (on screen) for +9 and -11, probably indicating I haven't figured things out properly yet...

Very confusing, this font stuff. Anyone has a better explanation page?

<edit>

Looks like negative numbers specify cell height, yet the mapper then uses character height for matches, whilst positive numbers specify character height in which case the mapper uses cell height for matches. Duh.
Last edited by blueznl on Tue Jul 30, 2013 10:59 pm, edited 2 times in total.
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Default font

Post by blueznl »

... also, I think TextHeight does not return the font size, but the space required to draw the font. Note that this is something different!
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Default font

Post by blueznl »

Mmmm. Looks like it works like this:

height < 0 - size is specified in cell height, font mapper however uses character height
height > 0 - size is specified in character height, font mapper however uses cell height

Sounds like MicroSoft logic :-)
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Default font

Post by blueznl »

Mmmm. Looks like it works like this:

height < 0 - size is specified in cell height, font mapper however uses character height
height > 0 - size is specified in character height, font mapper however uses cell height

Sounds like MicroSoft logic :-)

<edit>

Darn! Double post!
Last edited by blueznl on Tue Jul 30, 2013 11:00 pm, edited 1 time in total.
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6166
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Default font

Post by blueznl »

My results thus far, perhaps this can help someone else.

Code: Select all

;
; basically, the character height of a font is expressed in points
; (1 point = 1/72 inch) in older versions of windows displays were 
; assumed to have 96 pixels per inch, thus
;
;     height (in pixels) = height (in points) / 72 * 96
;
; newer versions of windows support different DPI settings:
;
;     height = 0 - (72 * fontsize / GetDeviceCaps_( hdc, #LOGPIXELSY ))
;
; preceeding the font is a little whitespace called internal leading,
; thus:
;
;     cell size = font size + internal leading
;
; the internal leading can be retrieved from the TEXTMETRIC data
; structure, but only after the font has been loaded
;
; there are two two ways to load a specific font of a specific size:
;
;     by character height, a number > 0
;     by cell height, a number < 0
;
; windows tries to find a matching font, if it cannot fint the
; specified one, there's a confusing remark regarding the mechanism used:
;
;     > 0  font mapper uses cell height to find a matching font
;     < 0  font mapper uses character height to find a matching font
;
; see also:
;
;     http://msdn.microsoft.com/en-us/library/windows/desktop/ff684173%28v=vs.85%29.aspx
;     http://msdn.microsoft.com/en-us/library/windows/desktop/dd145037%28v=vs.85%29.aspx
;     http://support.microsoft.com/kb/74299
;     http://forums.purebasic.com/english/viewtopic.php?p=265168
;
; purebasic uses a certain default font (probably retrieved from the default gui font)
; the handle to the default font can be retrieved using getgadgetfont()
; which points to a regular logfont structure
;
logfont.LOGFONT
x_defaultpurebasicfontid = GetGadgetFont(#PB_Default)
GetObject_(x_defaultpurebasicfontid, SizeOf(LOGFONT), @logfont)
x_defaultpurebasicfontname.s = PeekS(@logfont\lfFaceName[0])
x_defaultpurebasicfontsize.i = logfont\lfHeight
;
test.s = "ABCD abcd 1234 ASbd!Qgjq - "
;
OpenWindow(1,100,100,850,500,"Test",#PB_Window_SystemMenu)
;
; text height could be deducted using the textheight() command
; this requires a startdrawing() stopdrawing() section
; textheight() does not return font height, but space required to draw the given text
;
StartDrawing(WindowOutput(1))
  DrawingFont(x_defaultpurebasicfontid)
  height = TextHeight(test)  
StopDrawing()
;
; haven't set or changed anything, this is the default font
;
TextGadget(1,20,10,800,30,test+"default, textheigth - "+Str(height)+" pixels")
;
; a bit earlier we retrieved the point size of the font using the LOGFONT structure
; draw a gadget using fontname and size deducted then
;
TextGadget(2,20,40,800,30,test+"default font, fontsize from logfont structure - "+x_defaultpurebasicfontname+" "+Str(x_defaultpurebasicfontsize))
LoadFont(2,x_defaultpurebasicfontname,x_defaultpurebasicfontsize)
SetGadgetFont(2,FontID(2))
;
; on my system the default font size seems to be 9 pt so lets show that as well
;
TextGadget(3,20,70,800,30,test+"default font, set to 9 pt - "+x_defaultpurebasicfontname+" 9")
LoadFont(3,x_defaultpurebasicfontname,9)
SetGadgetFont(3,FontID(3))
;
; character size can be deduced from cell size minus internal leading
; note: my machine returned -11 as default font size, so 0-(-11)-2=9
;
textmetric.TEXTMETRIC
LoadFont(4,x_defaultpurebasicfontname,x_defaultpurebasicfontsize)
  hdc = StartDrawing(WindowOutput(1))
  DrawingFont(FontID(4))
  GetTextMetrics_(hdc,@textmetric)
  height = 0 - x_defaultpurebasicfontsize - textmetric\tmInternalLeading
StopDrawing()
;
TextGadget(4,20,100,800,30,test+"pb_default, calculated char size "+x_defaultpurebasicfontname+" "+Str(height))
LoadFont(4,x_defaultpurebasicfontname,height)
SetGadgetFont(4,FontID(4))
;
; windows elements use fonts from different locations
; the default gui font and system font can be retrieved as stock objects
; note that microsoft advises (for gui elements) to use the data found through systemparametersinfo_
;
logfont.LOGFONT
font_h = GetStockObject_(#DEFAULT_GUI_FONT)
GetObject_(font_h, SizeOf(LOGFONT), @logfont)
x_defaultguifontname.s = PeekS(@logfont\lfFaceName[0])
x_defaultguifontsize.i = logfont\lfHeight
font_h = GetStockObject_(#SYSTEM_FONT)
GetObject_(font_h, SizeOf(LOGFONT), @logfont)
x_defaultsystemfontname.s = PeekS(@logfont\lfFaceName[0])
x_defaultsystemfontsize.i = logfont\lfHeight
;
TextGadget(6,20,160,800,30,test+"default gui font - "+x_defaultguifontname+" "+Str(x_defaultguifontsize))
LoadFont(6,x_defaultguifontname,x_defaultguifontsize)
SetGadgetFont(6,FontID(6))
;
; font names and sizes of gui elements can be retrieved via the systemparametersinfo_ winapi
;
nonclientmetrics.NONCLIENTMETRICS
nonclientmetrics\cbSize = SizeOf(nonclientmetrics)
SystemParametersInfo_(#SPI_GETNONCLIENTMETRICS,SizeOf(nonclientmetrics),@nonclientmetrics,0)
x_defaultmenufontname.s = PeekS(@nonclientmetrics\lfMenuFont\lfFaceName[0])
x_defaultmenufontsize.i = nonclientmetrics\lfMenuFont\lfHeight
x_defaultstatusfontname.s = PeekS(@nonclientmetrics\lfStatusFont\lfFaceName[0])
x_defaultstatusfontsize.i = nonclientmetrics\lfStatusFont\lfHeight
x_defaultmessagefontname.s = PeekS(@nonclientmetrics\lfMessageFont\lfFaceName[0])
x_defaultmessagefontsize.i = nonclientmetrics\lfMessageFont\lfHeight
;
TextGadget(7,20,190,800,30,test+"default menu font - "+x_defaultmenufontname+" "+Str(x_defaultmenufontsize))
LoadFont(7,x_defaultmenufontname,x_defaultmenufontsize)
SetGadgetFont(7,FontID(7))
;
TextGadget(8,20,220,800,30,test+"default message font - "+x_defaultmessagefontname+" "+Str(x_defaultmessagefontsize))
LoadFont(8,x_defaultmenufontname,x_defaultmenufontsize)
SetGadgetFont(8,FontID(8))
;
TextGadget(9,20,250,800,30,test+"default status font - "+x_defaultstatusfontname+" "+Str(x_defaultstatusfontsize))
LoadFont(9,x_defaultmenufontname,x_defaultmenufontsize)
SetGadgetFont(9,FontID(9))
;
; this 30 pt font below actually requires a 42 pixels high area to be fully displayed
; calculating the pixel size using 30 * 96 / 72 = 40 pixels on my machine
;
LoadFont(10,"Courier New",30)
StartDrawing(WindowOutput(1))
  DrawingFont(FontID(10))
  height = TextHeight(test)
StopDrawing()
TextGadget(10,20,300,800,50,"+30 pt font requiring "+Str(height)+" pixels")
SetGadgetFont(10,FontID(10))
;
LoadFont(11,"Courier New",-32)
StartDrawing(WindowOutput(1))
  DrawingFont(FontID(11))
  height = TextHeight(test)
StopDrawing()
TextGadget(11,20,350,800,50,"-32 pt font requiring "+Str(height)+" pixels")
SetGadgetFont(11,FontID(11))
;
Repeat
Until WaitWindowEvent() = #PB_Event_CloseWindow
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
Post Reply