JDK-8154177 : Font spacing is incorrect at 125% or 150% scaling on Windows
  • Type: Bug
  • Component: javafx
  • Sub-Component: graphics
  • Affected Version: 9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2016-04-13
  • Updated: 2016-04-22
  • Resolved: 2016-04-22
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Related Reports
Relates :  
After the fix for JDK-8091832 we will render using non-integer scales on Windows platforms if the UI scale is set to a non-integer value, for example, 125% or 150%. With a non-integer render scale, the font spacing is incorrect in some cases. It looks like an accumulation error possibly caused by rounding or truncating at the wrong point.

It is most noticeable with smaller fonts and when using gray-scale AA. The attached test program can be used to demonstrate this. When run at 100% or 200% scaling it looks fine. When run with 125% or 150% scaling, the problem shows up. It is most noticeable at 125%.

If run on a system with a desktop UI scale of 1, you can use the following command to reproduce it:

$ java -Dglass.win.uiScale=1.25 TextSpacing

That makes a ton of sense. +1 from me...

The fix looks good to me. I also ran all of my tests and everything looks fine. It fixes the text spacing issues I was seeing, including the odd text rendering in the full-screen overlay warning that I reported when testing the fix for JDK-8091832. +1

I used "lllll" in the test to see that we have a theoretical advance of 2.9 and this gets rounded to 3.0. Then when we scale it becomes 3.75. Eventually we end up with values of 18.75 and 21.25 for the final rendering position. The D3D hardware rounds this to 19 and 21. So we end up with an actual advance that is far less than it should be. The problem is in GlyphCache.render(..) pt.setLocation(x + gl.getPosX(gi), y + gl.getPosY(gi)); int subPixel = strike.getQuantizedPosition(pt); GlyphData data = getCachedGlyph(gc, subPixel); .... xform.transform(pt, pt); addDataToQuad(data, vb, tex, pt.x, pt.y, dstw, dsth); That call to getQuantizedPosition() is doing the rounding to 3.0 before we have the final device space - clearly not correct. The fix is to move the transform to before the call to getQuantizedPosition() This makes the test look much better. TextTest was also used to verify that everything behaves well under scales and rotates. Webrev: http://cr.openjdk.java.net/~prr/8154177/

If it looks off at 200%, then it would look off in 8u as well. This would be a good candidate to back-port in that case.

We need to examine how the advance is being calculated, accumulated, rounded and in what co-ordinate space ...

I don't think it is correct at 200% either. I would expect the spacing of the default 12 point font to look roughly the same at 200% as a 24 point font does at 100%. However, I still see spacing problems at 200% that I don't see with a 24-point font at 100%.