JDK-8013569 : [macosx] JLabel preferred size incorrect on retina displays with non-default font size
  • Type: Bug
  • Component: client-libs
  • Sub-Component: 2d
  • Affected Version: 7,8
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: os_x
  • Submitted: 2013-04-30
  • Updated: 2014-11-17
  • Resolved: 2013-07-26
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.
JDK 7 JDK 8
7u55Fixed 8 b102Fixed
Related Reports
Duplicate :  
Relates :  
Description
FULL PRODUCT VERSION :
openjdk version  " 1.8.0-internal " 
OpenJDK Runtime Environment (build 1.8.0-internal-strunk_2013_04_24_12_17-b00)
OpenJDK 64-Bit Server VM (build 25.0-b28, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Mac OSX 10.8.2

A DESCRIPTION OF THE PROBLEM :
The preferred size of JLabels is incorrect when displayed on a Retina display, when using a non-default font size.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
  To reproduce, execute the code given below on a retina and a non-retina display. On a retina display the label text is cut off.



EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
JLabel should not be cut off on retina displays.
ACTUAL -
On a retina display the label text is cut off.

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Font;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;

public class JLabelDemo {

    public static void main(String[] args) {

        JFrame frame = new JFrame( " JLabel Demo " );
        Container contentPane = frame.getContentPane();
        contentPane.setLayout(new FlowLayout());
        final JLabel label = new JLabel(
                 " This is a monstrous mmmmmega label text which will not fit " );
        label.setBorder(BorderFactory.createEtchedBorder());
        label.setFont(new Font(label.getFont().getName(), label.getFont().getStyle(), 11));
        contentPane.add(label);
          frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);

    }

}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Increase the preferred width by a few pixels so JLabels are rendered large enough.
Comments
SQE OK to take the fix into CPU14_02
15-01-2014

removed 7u60-critical-request because back port is not ready yet
09-01-2014

How risky is the fix? Did the customer verify it? Can the fix be considered for April CPU inclusion?
19-12-2013

proof of concept: http://cr.openjdk.java.net/~serb/7190349/webrev.01/ Fixes: https://jbs.oracle.com/bugs/browse/JDK-7190349 https://jbs.oracle.com/bugs/browse/JDK-8014069 https://jbs.oracle.com/bugs/browse/JDK-8013569
17-06-2013

Actually when I enable FRACTIONALMETRICS and align implementation of advances calculation, pure image rendering became good. But swing still does not work, because it uses its own FontRenderContext and swing disable FRACTIONALMETRICS without setup options. I do not see how to propagate correct FRACTIONALMETRICS value to the swing since it is depends from the render target, looks like we should always enable FRACTIONALMETRICS(via Toolkit.getDesktopProperty()?) on mac w/o possibility to disable it.
04-06-2013

The problem here is probably because advances get rounded to to an integer in the real device space So (eg) at 2x scale 5.6 would become 11.2 and the roundings would be 6 and 11 respectively. Fractional metrics looks like a solution because advances would be accumulated in floating point. However I am not sure if it'll fix everything. The different fns each using a different approach to the transform does seem to be a problem The case where the transform is available to the code calculating the advance sounds like it should be able to do the right thing. But applying the transform *afterwards* as it sounds like for CTFontGetAdvancesForGlyphs is likely to cause problems. I suppose this is better than it might have been since on OS X advances are unhinted. If this were Windows we might be seeing the effects of hinting resulting in non-linear scaling. This has been a major issue when printing Swing UIs and that's really nothing more than a special kind of hi-dpi. ie stringWidth() needs to know the real FontRenderContext to measure properly. The root of the problem is that Swing does not always measure using the graphics scale/font rendering context that is in effect when we draw and has some assumptions that everything can scale linearly.
03-06-2013

There are 2 issue: - Inaccurate FontMetrics.stringWidth() in HiDPI mode..Looks like INTVAL_FRACTIONALMETRICS should be ON by default in HiDPI. - Two different methods used for advaces calculation with a different accuracy AWTStrike.m.Java_sun_font_CStrike_getNativeGlyphAdvance.CTFontGetAdvancesForGlyphs() CGGlyphImages.m.CGGI_CreateGlyphInfosJRSFontGetAdvancesForGlyphsAndStyle() Note that CreateGlyphInfosJRSFontGetAdvancesForGlyphsAndStyle use a transform, and for CTFontGetAdvancesForGlyphs we apply a transform ourself.
03-06-2013