Page 1 of 1
VectorTextWidth returns wrong values
Posted: Fri Oct 26, 2018 6:59 pm
by Michael Vogel
When using larger font sizes you may get wrong values like seen below. The drawing functions seem to work correct, but the TextWidth is calcuated wrong.
Code: Select all
For i=990 To 1010
z0=z1
VectorFont(FontID(#FontID),i)
z1=VectorTextWidth(Text)
Debug Str(i)+": "+Str(z1)+", "+Str(z1-z0)
Next i
990: 6021, 6021
991: 6027, 6
992: 6033, 6
993: 6039, 6
994: 6046, 7
995: 6052, 6
996: 6058, 6
997: 6064, 6
998: 6070, 6
999: 6076, 6
1000: 6082, 6
1001: 6149, 67
1002: 6155, 6
1003: 6161, 6
1004: 6167, 6
1005: 6173, 6
1006: 6179, 6
1007: 6186, 7
1008: 6192, 6
1009: 6198, 6
1010: 6204, 6
Re: VectorTextWidth returns wrong values
Posted: Fri Oct 26, 2018 7:46 pm
by STARGĂ…TE
No problem here (PB 5.60 x64 Windows 7)
I tried it with multiple fonts and sizes.
Code: Select all
Enumeration
#Window
#Gadget
#Font1
#Font2
#Font3
EndEnumeration
Procedure UpdateCanvasGadget(Gadget.i)
Protected i, Z0, Z1
Protected Text.s = "Hello World"
If StartVectorDrawing(CanvasVectorOutput(Gadget))
Debug "---"
For i=500 To 1500
z0=z1
VectorFont(FontID(#Font1), i)
z1=VectorTextWidth(Text)
Debug Str(i)+": "+Str(z1)+", "+Str(z1-z0)
Next i
Debug "---"
For i=500 To 1500
z0=z1
VectorFont(FontID(#Font2), i)
z1=VectorTextWidth(Text)
Debug Str(i)+": "+Str(z1)+", "+Str(z1-z0)
Next i
Debug "---"
For i=500 To 1500
z0=z1
VectorFont(FontID(#Font3), i)
z1=VectorTextWidth(Text)
Debug Str(i)+": "+Str(z1)+", "+Str(z1-z0)
Next i
StopVectorDrawing()
EndIf
EndProcedure
Procedure Callback_SizeWindow()
ResizeGadget(#Gadget, 0, 0, WindowWidth(#Window), WindowHeight(#Window))
UpdateCanvasGadget(#Gadget)
EndProcedure
OpenWindow(#Window, 0, 0, 800, 450, "Vector Canvas Gadget", #PB_Window_MaximizeGadget|#PB_Window_MaximizeGadget|#PB_Window_SizeGadget|#PB_Window_ScreenCentered)
CanvasGadget(#Gadget, 0, 0, WindowWidth(#Window), WindowHeight(#Window), #PB_Canvas_Keyboard)
LoadFont(#Font1, "Arial", 128)
LoadFont(#Font2, "Times New Roman", 128)
LoadFont(#Font3, "Courier New", 128)
UpdateCanvasGadget(#Gadget)
BindEvent(#PB_Event_SizeWindow, @Callback_SizeWindow(), #Window)
Repeat
Select WaitWindowEvent()
Case #PB_Event_CloseWindow
Break
EndSelect
ForEver
End
Re: VectorTextWidth returns wrong values
Posted: Fri Oct 26, 2018 10:30 pm
by infratec
With this
working example all went Ok with PB 5.70B2 32bit Win10
Code: Select all
#FontID = 0
LoadFont(#FontID, "Arial", 100)
Text$ = "12345678901234567890"
CreateImage(0, 100, 100)
If StartVectorDrawing(ImageVectorOutput(0))
For i=990 To 1010
z0=z1
VectorFont(FontID(#FontID), i)
z1=VectorTextWidth(Text$)
Debug Str(i)+": "+Str(z1)+", "+Str(z1-z0)
Next i
StopVectorDrawing()
EndIf
990: 11012, 11012
991: 11023, 11
992: 11034, 11
993: 11045, 11
994: 11056, 11
995: 11067, 11
996: 11079, 12
997: 11090, 11
998: 11101, 11
999: 11112, 11
1000: 11123, 11
1001: 11134, 11
1002: 11145, 11
1003: 11156, 11
1004: 11168, 12
1005: 11179, 11
1006: 11190, 11
1007: 11201, 11
1008: 11212, 11
1009: 11223, 11
1010: 11234, 11
Bernd
Re: VectorTextWidth returns wrong values
Posted: Sat Oct 27, 2018 1:09 pm
by Michael Vogel
The whole thing seems to depend from the (true type) font and the chosen text, with the following code I get multiple hits here:
Code: Select all
Global NewMap FontMap.s()
Global NewList Fonts.s()
Procedure EnumFontInfo(*elfx.ENUMLOGFONTEX,*ntmx.NEWTEXTMETRICEX,FontType.i,lParam.i)
AddMapElement(FontMap(),PeekS(@*elfx\elfLogFont\lfFaceName[0]))
ProcedureReturn #True
EndProcedure
Procedure EnumFontList(WinID,List FontList.s())
Protected FontLog.LOGFONT
Protected FontHDC
FontHDC=GetDC_(WinID)
FillMemory(@FontLog,SizeOf(LOGFONT))
FontLog\lfCharSet= #DEFAULT_CHARSET
FontLog\lfFaceName[0]= 0
If EnumFontFamiliesEx_(FontHDC,@FontLog,@EnumFontInfo(),0,0)
ForEach FontMap()
AddElement(FontList())
FontList()=MapKey(FontMap())
Next
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
OpenWindow(0,0,0,0,0,"*")
If EnumFontList(WindowID(0),Fonts())
ForEach Fonts()
#FontID = 0
LoadFont(#FontID,Fonts(),15)
;Text$ = "12345678901234567890"
Text$ = "CAPTT"
CreateImage(0, 100, 100)
StartVectorDrawing(ImageVectorOutput(0))
#limit=20
z1=0
error=0
For i=990 To 1010
z0=z1
VectorFont(FontID(#FontID), i)
z1=VectorTextWidth(Text$)
If i>991 And z1-z0>#limit
Debug Fonts()+" / "+Str(i)+": "+Str(z1)+", "+Str(z1-z0)
error=1
EndIf
Next i
If error
Debug z1-z0
EndIf
StopVectorDrawing()
Next
EndIf
The most extreme outlier is the following:
Benguiat / 1001: 2822,
93
3
Re: VectorTextWidth returns wrong values
Posted: Sat Oct 27, 2018 1:47 pm
by infratec
Hi,
now you know why always a working example is needed
My results:
Source Sans Pro ExtraLight / 1001: 2634, -30
Noto Sans / 1001: 3011, 23
Miriam Libre / 1001: 2826, 25
Noto Sans Cond / 1001: 2386, 17
Noto Sans Light / 1001: 2902, 22
Source Sans Pro Light / 1001: 2659, -28
Source Sans Pro / 1001: 2732, -21
Source Sans Pro Semibold / 1001: 2792, -16
(I added ABS() to get also the negative results)
One thing is very interesting:
It happens always at 1001. Also your mentioned font throw this error with 1001.
Maybe it's a magic number

Re: VectorTextWidth returns wrong values
Posted: Sat Oct 27, 2018 2:01 pm
by infratec
Or it has something todo with the floatingpoint arithmetic, since the size parameter is .d
Re: VectorTextWidth returns wrong values
Posted: Sat Oct 27, 2018 2:08 pm
by Michael Vogel
Not sure what the reason for the difference between the calculation and the drawing output, I only found and UPM parameter within the ttf files which has the value 1000.
Another interesting thing, I don't see these issues when using standard drawing commands (but the calculated widths are 33% higher compared to the vector texts):
Code: Select all
text$ = "CAPTT"
CreateImage(0, 100, 100)
For i=997 To 1005
LoadFont(0,"Benguiat",i)
StartDrawing(ImageOutput(0))
z0=z1
DrawingFont(FontID(0))
z1=TextWidth(Text$)
Debug Str(i)+": "+Str(z1)+", "+Str(z1-z0)
StopDrawing()
Next i
Re: VectorTextWidth returns wrong values
Posted: Sat Oct 27, 2018 2:28 pm
by Michael Vogel
infratec wrote:Or it has something todo with the floatingpoint arithmetic, since the size parameter is .d
I was hoping the floats are leading to smoother results - and this seems to be correct for normal (see below), using non vector functions would lead to a more wobbling effect...
Code: Select all
#X=960
#Y=640
;LoadFont(1,"Benguiat",15)
LoadFont(1,"Segoe UI",15)
Procedure Draw(time)
Protected s.s
Protected frames,now
Protected alpha,glass,color
Protected fx.f,fy.f,fw.f,fs.f
Protected delta.f
StartVectorDrawing(CanvasVectorOutput(0))
VectorSourceColor($FF000000)
FillVectorOutput()
#Width=0.012
If time>=0 And time<500
now=time
frames=200
delta=now/frames
fs=3000+delta*-400-time*4
alpha=$FF000000
glass=$60000000
VectorFont(FontID(1),fs)
fx=300+delta*20-VectorTextWidth("N")/2
fy=450+delta*80-VectorTextHeight("N")/2
fw=1+#Width*fs
MovePathCursor(fx,fy)
AddPathText("N")
VectorSourceColor(alpha|$0000D0)
StrokePath(fw)
MovePathCursor(fx,fy)
AddPathText("N")
VectorSourceColor(glass|$1010FF)
StrokePath(fw*1.4)
MovePathCursor(fx,fy)
AddPathText("N")
VectorSourceColor(glass|$1010FF)
fs/10
DashPath(fw*0.9,fs,#PB_Path_DiagonalCorner,fs)
EndIf
StopVectorDrawing()
EndProcedure
OpenWindow(0,0,0,#X,#Y,"*",#PB_Window_ScreenCentered|#PB_Window_BorderLess)
StickyWindow(0,1)
CanvasGadget(0,0,0,#X,#Y)
AddWindowTimer(0,0,10)
Repeat
Select WaitWindowEvent()
Case #PB_Event_Timer
time+1
Draw(time)
Case #PB_Event_CloseWindow,#WM_CHAR
End
EndSelect
ForEver
Re: VectorTextWidth returns wrong values
Posted: Sun Oct 28, 2018 9:05 am
by Michael Vogel
Here's a workaround for the wrong VectorTextWidth calculation - remember to recalculate the correction value for every different text you are using!
If you are using more than one font type you can easily adapt the procedure to manage this as well...
Code: Select all
Procedure.d TextWidthCorrection(text.s)
#TmpImage=999
#TmpFont=999
Protected i
Protected Dim value.d(2)
LoadFont(#TmpFont,"Benguiat",666)
If CreateImage(#TmpImage,1,1)
If StartVectorDrawing(ImageVectorOutput(#TmpImage))
For i=0 To 2
VectorFont(FontID(#TmpFont),1000+i)
value(i)=VectorTextWidth(text)
Next i
StopVectorDrawing()
EndIf
FreeImage(#TmpImage)
EndIf
ProcedureReturn value(0)-value(1)*2+value(2)
EndProcedure
text.s
text = "TJ"
;text = "LJ"
;text = "TT"
correction.d=TextWidthCorrection(text)
LoadFont(0,"Benguiat",666)
CreateImage(0,1,1)
StartVectorDrawing(ImageVectorOutput(0))
For n=990 To 1010
VectorFont(FontID(0),n)
Debug Str(n)+": "+StrD(VectorTextWidth(text)+correction*Bool(n>1000),2)
Next n
StopVectorDrawing()