United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
JDK-8013569 : [macosx] JLabel preferred size incorrect on retina displays with non-default font size

Details
Type:
Bug
Submit Date:
2013-04-30
Status:
Resolved
Updated Date:
2014-04-18
Project Name:
JDK
Resolved Date:
2013-07-26
Component:
client-libs
OS:
os_x
Sub-Component:
2d
CPU:
Priority:
P3
Resolution:
Fixed
Affected Versions:
7,8
Fixed Versions:

Related Reports
Backport:
Backport:
Backport:
Duplicate:
Relates:

Sub Tasks

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
                                     
2014-01-15
removed 7u60-critical-request because back port is not ready yet
                                     
2014-01-09
How risky is the fix? Did the customer verify it? Can the fix be considered for April CPU inclusion? 
                                     
2013-12-19
URL:   http://hg.openjdk.java.net/jdk8/jdk8/jdk/rev/a8b9df782017
User:  lana
Date:  2013-08-06 17:34:56 +0000

                                     
2013-08-06
URL:   http://hg.openjdk.java.net/jdk8/2d/jdk/rev/a8b9df782017
User:  serb
Date:  2013-07-26 17:21:29 +0000

                                     
2013-07-26
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
                                     
2013-06-17
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.
                                     
2013-06-04
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.
                                     
2013-06-03
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.
                                     
2013-06-03



Hardware and Software, Engineered to Work Together