My never ending battle with the code editor I’m writing continues.
It seems that Graphics.TextWidth (and Graphics.StringWidth although deprecated) return the wrong value if the passed String (or Text) contain a horizontal tab character (&u0009).
// We'll try to get the length of `a b`
// Get a graphics context.
Var p As TrueWindow.BitmapForCaching(800, 600)
Var g As Graphics = p.Graphics
Var a As String = "a"
Var tab As String = &u0009
Var b As String = "b"
Var aTabb As String = a + tab + b // a b
Var aWidth As Double = g.TextWidth(a) // 6.62
Var tabWidth As Double = g.TextWidth(tab) // 28
Var bWidth As Double = g.TextWidth(b) // 7.37
Var aTabWidth As Double = g.TextWidth(aTabb) // 35.37
As you can see, the correct length should be 6.62 + 28 + 7.37 (41.99) but it’s reported as 35.37.
This happens with longer phrases:
Var hello As String = "hello"
Var world As String = "world"
Var helloTabWorld As String = "hello" + &u0009 + "world" // hello world
Var helloWidth As Double = g.TextWidth(hello) // 27.076
Var worldWidth As Double = g.TextWidth(world) // 31.125
Var helloTabWorldWidth As Double = g.TextWidth(helloTabWorld) // 59.125
In this case, the length should be 27.076 + 28 + 31.125 (86.201) but it’s reported as 59.125. This is the width of the tab (28) plus the characters after the tab (31.125).
It seems that Graphics.TextWidth and Graphics.StringWidth are ignoring the characters before the tab character and only reporting the length of the tab and the characters afterwards.
Can someone confirm that this is a bug (I only have macOS available at present to test).
I should mention that I actually need to use Text not String (see this thread) but the bug affects both data types.
Is the width of the tab wrong? The b is 7, the tab is has a width of 28 which is 4 times the width of the b but it’s barely wider than the b. Other than that I don’t see a problem with the calculation.
If "hello" is 27.076 pixels wide, the tab character is 28 pixels wide and "world" is 31.125 pixels wide, why is "hello world" (with a tab inbetween) only 59.125? That’s the tab width plus the "world" width added together.
Var aTABb As String = a + tab + b
Var aTABTABb As String = a + tab + tab + b
Var aTABbWidth As Double = g.TextWidth(aTABb) // 35.9091796875
Var aTABTABbWidth As Double = g.TextWidth(aTABTABb) // 63.9091796875
If you add another tab you get an increase of 28 which is the exact width of a tab. It’s definitely truncating characters before the first tab,
Tab is also to build a column where the data start exact at the same place.
its more a variable width so you can not just add single values together as one width.
A quick test on my Mac seems to indicate that the tabs up to a certain width are aligned to a set of tab stops. After that the width seems to increase consistently.
This is the test code I used (edited):
NOTE. If you change s2 to be a single character then you should see this more clearly.
Dim p As New Picture(1, 1)
Dim s As String
Dim s2 As String
Dim s3 As String
Dim i As Int32
p.Graphics.TextFont = "SmallSystem"
p.Graphics.TextSize = 0
s = "Hello"
System.DebugLog s + " = " + Str(p.Graphics.StringWidth(s))
s2 = "Me"
System.DebugLog s2 + " = " + Str(p.Graphics.StringWidth(s2))
s3 = Chr(9) + s
For i = 1 To 100
System.DebugLog Str(i) + " = " + Str(p.Graphics.StringWidth(s3))
s3 = s2 + s3
Next
OK guys. It looks like @MarkusR is correct. The tab width is variable. I guess code editors handle things differently than I had engineered in this regards.
No worries. I shall endeavour to work around it. The easiest fix is to replace tabs with spaces but some languages (such as Python) don’t always play nice with that.
Thanks to everyone who has chimed in. I’ve learned something new!
python only gets mad if you mix tabs and spaces, so using all spaces will be fine. I set all my text editors to tab=4 spaces and have never had an issue.