Page 1 of 1

Default font

Posted: Sat Jul 27, 2013 10:37 pm
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.

Re: Default font

Posted: Sat Jul 27, 2013 11:11 pm
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.

Re: Default font

Posted: Sun Jul 28, 2013 12:55 am
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

Re: Default font

Posted: Sun Jul 28, 2013 2:20 am
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. :)

Re: Default font

Posted: Sun Jul 28, 2013 11:07 am
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...

Re: Default font

Posted: Mon Jul 29, 2013 5:17 am
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()

Re: Default font

Posted: Mon Jul 29, 2013 8:07 am
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.

Re: Default font

Posted: Mon Jul 29, 2013 8:44 am
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!

Re: Default font

Posted: Tue Jul 30, 2013 2:30 pm
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 :-)

Re: Default font

Posted: Tue Jul 30, 2013 2:44 pm
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!

Re: Default font

Posted: Tue Jul 30, 2013 10:55 pm
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