sharpdx / SharpDX

SharpDX GitHub Repository
http://sharpdx.org
MIT License
1.69k stars 641 forks source link

SpriteFont.MeasureText inconsistent results #184

Closed Roderik11 closed 10 years ago

Roderik11 commented 10 years ago

Measuring pieces of the same string don't sum up as you would expect:

Using size 8 Segoe UI, regular, no kerning

MeasureString("one word").X = 51 MeasureString("one").X = 22 MeasureString(" word").X = 31

Oddly enough this works correctly in MonoGame, XNA and SlimDX

ArtiomCiumac commented 10 years ago

Using Segoe UI, 8 in a Sprite Font definition I got different results:

MeasureString("one word").X = 49
MeasureString("one").X = 20
MeasureString(" word").X = 26

The sum is actually smaller (46 instead of 49), because during measurements the SpriteFont ignores leading or trailing whitespace chars - this can be interpreted as a bug and fixed, however I can't reproduce your situation when the sum is bigger (54 instead of 51) - what version of SharpDX are you using? do you have a sample project that can reproduce this?

Roderik11 commented 10 years ago

Latest 2.5 Toolkit (2.5.0.0) Only trailing spaces are ignored (not leading). - tested this a lot. Compared the behaviour to XNA, MonoGame, SlimDX. Only SlimDX also ignores trailing spaces, but does not have this measurement problem. It's strange that you get different results, i just tested it again and get the same as i posted earlier.

Segoe UI Size 8 Spacing 0 LineSpacing 0 UseKerning false Format Auto DefaultCharacter 32 Style Regular NoPremultiply true

"do you have a sample project that can reproduce this?" Yes, but it's not easily shared. That would take me a while to extract.

Roderik11 commented 10 years ago

Interestingly, the DirectX Tool Kit also ignores trailing whitespaces: https://directxtk.codeplex.com/workitem/674 Note the examples and ShawnHargreaves response:

"For DirectXTK, I simplified this way down and chose a much more consistent implementation which is just to measure the area between the origin and the rightmost pixel rendered by any character glyph. That's often actually more useful than the XNA implementation, because when you are doing wordwrapping, you don't want to count trailing spaces when computing line fit."

I would strongly argue that this is not useful at all. Doing all text wrapping myself i really need MeasureString to calculate trailing whitespaces. If i needed to trim the strings for line fit, i could do so myself. MeasureString(" ") returns 0,0 - that's not very helpful at all.

In other words: There is no way to directly measure a whitespace char in SharpDX. The only way i could think of is: Measure(" x") - Measure("x").

However, the sum of a strings parts is still not equal to the size of the full string. So here's my vote to use the XNA implementation (same as MonoGame).

ArtiomCiumac commented 10 years ago

The SharpDX SpriteFont class is a direct port from DirectXTk - this is why it has the same behavior. To make it work as in XNA/MonoGame requires a total rewrite of the SpriteFont compilation and rendering which we can't afford right now. Any quick-and-easy fixes lead to incorrect results in which the error is proportional to font size. At this time this is low priority, so I suggest to implement a workaround which suit best your usage scenarios.

Roderik11 commented 10 years ago

"At this time this is low priority, so I suggest to implement a workaround which suit best your usage scenarios."

Sure it's possible to work around the trailing whitespaces, but there is no workaround for the actual bug (sum of parts of a string are not equal to its full size).

No need to implement the XNA version, but a fix to for the sum issue would be greatly appreciated :)

xoofx commented 10 years ago

Commit f198809e141af0b1d8656c40a38833e7c91dffd4 should hopefully fix this issue.