Page 1 of 1

Differences in Font Size

Posted: Wed Feb 29, 2012 10:53 am
by TI-994A
Hi guys! I've always used this formula to calculate the size of a font when using the CreateFontIndirect API function:

Code: Select all

newFont\lfHeight = -(pointSize * (deviceDPI / 72))
However, I notice that there's a big difference between my output and that of PureBasic's DrawText Function. I have to increase my logical font size to 16 points to match the output drawn by DrawText at 12 points:

Image

Here's the test code:

Code: Select all

Enumeration
  #MainWindow
  #dtFont
EndEnumeration

wFlags = #PB_Window_ScreenCentered | #PB_Window_SystemMenu
OpenWindow(#MainWindow, #PB_Any, #PB_Any, 500, 200, "Font Sizes", wFlags)
LoadFont(#dtFont, "Arial", 12)
If StartDrawing(WindowOutput(#MainWindow))
  Box(0, 0, 500, 200, RGB(255, 255, 255))
  DrawingMode(#PB_2DDrawing_Transparent)
  DrawingFont(FontID(#dtFont))
  DrawText(10, 10, "Hello World! drawn by PureBasic's DrawText function at 12 points", #Red)
  StopDrawing()
EndIf
  
Define cf.LOGFONT
  fontName.s = "Arial"
  For lenLoop = 0 To Len(fontName) - 1
   cf\lfFaceName [lenLoop] = Asc(Mid(fontName, lenloop + 1, 1))
  Next lenLoop
  winDPI = GetDeviceCaps_(GetDC_(WindowID(#MainWindow)), #LOGPIXELSY) 
  cf\lfFaceName [Len(fontName)] = 0
  cf\lfHeight = -(16 * (winDPI / 72))
  
  winDC = GetDC_(WindowID(#MainWindow))
  
  newFont = CreateFontIndirect_(cf)
  oldFont = SelectObject_(winDC, newFont)
  SetTextColor_(winDC, #Blue)
  outStr.s = "Hello World! drawn by Windows' TextOut function at 16 points"
  TextOut_(winDC, 10, 35, outStr, Len(outStr))    
  
  cf\lfHeight = -(12 * (winDPI / 72))
  newFont = CreateFontIndirect_(cf)
  ignore = SelectObject_(winDC, newFont)
  SetTextColor_(winDC, #Black)
  outStr.s = "Hello World! drawn by Windows' TextOut function at 12 points"
  TextOut_(winDC, 10, 60, outStr, Len(outStr))    
  
  dispose = SelectObject_(winDC, oldFont)
  DeleteObject_(newFont)

While WaitWindowEvent() ! #PB_Event_CloseWindow : CloseWindow : Wend
Am I missing something, or is the font height calculation incorrect?

Thanks.

Re: Differences in Font Size

Posted: Wed Feb 29, 2012 11:29 am
by Danilo
TI-994A wrote:

Code: Select all

  winDPI = GetDeviceCaps_(GetDC_(WindowID(#MainWindow)), #LOGPIXELSY)
Change winDPI to winDPI.f

Code: Select all

  winDPI.f = GetDeviceCaps_(GetDC_(WindowID(#MainWindow)), #LOGPIXELSY)
Alternatively use:

Code: Select all

cf\lfHeight = -MulDiv_(12,winDPI,72)

Re: Differences in Font Size

Posted: Wed Feb 29, 2012 11:36 am
by TI-994A
Danilo wrote:Change winDPI to winDPI.f

Code: Select all

  winDPI.f = GetDeviceCaps_(GetDC_(WindowID(#MainWindow)), #LOGPIXELSY)
Genius! I wouldn't have thought of that, since GetDeviceCaps returns a whole number for LOGPIXELSY. It works perfectly now.

Thank you, Danilo!

Re: Differences in Font Size

Posted: Wed Feb 29, 2012 11:44 am
by Danilo
TI-994A wrote:
Danilo wrote:I wouldn't have thought of that, since GetDeviceCaps returns a whole number for LOGPIXELSY.
It is the division "winDPI / 72" -> f.e. 96 / 72 = 1 with Integer/Long numbers.

Code: Select all

Debug 96   / 72
Debug 96.0 / 72
MulDiv_() works also with Integer:

Code: Select all

cf\lfHeight = -MulDiv_(12,winDPI,72)

Re: Differences in Font Size

Posted: Wed Feb 29, 2012 11:49 am
by TI-994A
Danilo wrote:
TI-994A wrote:
Danilo wrote:I wouldn't have thought of that, since GetDeviceCaps returns a whole number for LOGPIXELSY.
It is the division "winDPI / 72" -> f.e. 96 / 72 = 1 with Integer/Long numbers.

Code: Select all

Debug 96   / 72
Debug 96.0 / 72
MulDiv_() works also with Integer:

Code: Select all

cf\lfHeight = -MulDiv_(12,winDPI,72)
Understood. I'm assuming MulDiv does the same thing with integers?

Re: Differences in Font Size

Posted: Wed Feb 29, 2012 11:57 am
by Danilo
TI-994A wrote:Understood. I'm assuming MulDiv does the same thing with integers?
Yes.
MulDiv wrote:MulDiv Function

Multiplies two 32-bit values and then divides the 64-bit result by a third 32-bit value. The return value is rounded up or down to the nearest integer.

Syntax

Code: Select all

int MulDiv(
  __in  int nNumber,
  __in  int nNumerator,
  __in  int nDenominator
);
Parameters
nNumber [in]
The multiplicand.

nNumerator [in]
The multiplier.

nDenominator [in]
The number by which the result of the multiplication operation is to be divided.

Return Value
If the function succeeds, the return value is the result of the multiplication and division. If either an overflow occurred or nDenominator was 0, the return value is -1.

Minimum supported client: Windows 2000 Professional
Minimum supported server: Windows 2000 Server

Re: Differences in Font Size

Posted: Wed Feb 29, 2012 12:33 pm
by TI-994A
Got it! Thank you very much Danilo. Truly appreciate your invaluable help.

Re: Differences in Font Size

Posted: Wed Feb 29, 2012 12:56 pm
by luis
Another way it's to force a promotion to floating point this way:

cf\lfHeight = -(16 * (1.0 * winDPI / 72))


this is somewhat equivalent to the cast to float available in other languages, that's what I use when I don't want to alter a data type (winDPI.i in this case) for some reason.

or a little less explicit visually but it's the same

cf\lfHeight = -(16 * (winDPI / 72.0))

Re: Differences in Font Size

Posted: Wed Feb 29, 2012 2:55 pm
by TI-994A
luis wrote:Another way it's to force a promotion to floating point this way:

cf\lfHeight = -(16 * (1.0 * winDPI / 72))

this is somewhat equivalent to the cast to float available in other languages, that's what I use when I don't want to alter a data type (winDPI.i in this case) for some reason.

or a little less explicit visually but it's the same

cf\lfHeight = -(16 * (winDPI / 72.0))
Didn't know you could do that. This is a very useful casting trick, especially in lieu of CDbl(). Thank you for pointing that out.

Re: Differences in Font Size

Posted: Fri Mar 02, 2012 10:27 am
by Michael Vogel
I would prefer something like a Float(WinDpi)/72 :|

The other way round is easier: a.f=3 : Debug Int(a)<<1

Re: Differences in Font Size

Posted: Fri Mar 02, 2012 10:49 am
by Danilo
Michael Vogel wrote:I would prefer something like a Float(WinDpi)/72 :|

Code: Select all

Procedure.f Float(value.q)
    ProcedureReturn value
EndProcedure

Procedure.d Double(value.q)
    ProcedureReturn value
EndProcedure

Debug        96 / 72
Debug Float (96)/ 72
Debug Double(96)/ 72

Code: Select all

Macro Float(value)
    (1.0 * (value))
EndMacro

WinDPI = 96

Debug       WinDPI / 72
Debug Float(WinDPI)/ 72
Debug Float(WinDPI / 72)


Debug       12 / 5
Debug Float(12)/ 5
Debug Float(12 / 5)
The Macro could be compiled as Resident.


For the problem in this topic you may just want to change the parenthesis:

Code: Select all

WinDPI = 96

Debug (12 * (winDPI / 72)) ; original  , wrong

Debug ((12 * winDPI) / 72) ; MulDiv way, correct

Re: Differences in Font Size

Posted: Fri Mar 02, 2012 6:57 pm
by TerryHough
The original post's question and the answers will help me solve a font size issue I've been having. So, thanks everyone.

I've also been struggling with font sizes when printing to a printer using TextOut_. Seems like those never make sense to me. Might be the same issue.

Re: Differences in Font Size

Posted: Sat Mar 03, 2012 4:51 am
by TI-994A
TerryHough wrote:The original post's question and the answers will help me solve a font size issue I've been having. So, thanks everyone.

I've also been struggling with font sizes when printing to a printer using TextOut_. Seems like those never make sense to me. Might be the same issue.
Not that I'm an expert or anything, but do you actually draw to a device context (DC) that is compatible with the printer you're printing to?