<Swing Dev> [9] Review request for 8156217 Selected text is shifted on HiDPI display

Alan Snyder javalists at cbfiddle.com
Tue Jun 28 17:14:45 UTC 2016


Suppose an application is only partially fixed to use/override the floating point methods. Perhaps it uses a library that has not been fixed.

Is there a more fine grained way to detect programmer awareness or lack of awareness of the new methods?

  Alan


> On Jun 28, 2016, at 9:59 AM, Alexandr Scherbatiy <alexandr.scherbatiy at oracle.com> wrote:
> 
> 
>   Hello,
> 
>   I tried to merge this fix with the 8132119 Provide public API for text related methods in SwingUtilities2
>   and found a flow in the used algorithm.
> 
>  For each method that uses integer coordinates the fix adds a pair with floating point arguments.
>  The fix 8156217 uses only methods with floating point values to correctly handle a selected text.
>  This leads that overridden method with integer arguments in user code is not called anymore.
> 
>  I think that this can be handled in the following way:
>  - Add a property that enables to use methods with floating point arguments in Swing.
>    By default it is false and all work as before. The issue with selected text is reproduced.
>    An application with enabled property does not have issue with the selected text but a user should override
>    all methods with floating point values if he uses corresponding methods with integer values.
>  
>   Here is a proposed solution where new public system property "javax.swing.floatingPoints.enabled" is added:
>     http://cr.openjdk.java.net/~alexsch/8156217/webrev.01 <http://cr.openjdk.java.net/~alexsch/8156217/webrev.01> 
>  
> - Fix the enhancement JDK-8157461 Glyph image rendering for HiDPI displays
>   
>   Thanks,
>   Alexandr. 
> 
> On 6/16/2016 6:07 PM, Alexandr Scherbatiy wrote:
>> On 6/16/2016 4:47 PM, Alexandr Scherbatiy wrote:
>>> 
>>> I tried to look deeper in the code and it seems there is a rounding issue when float values are summed up.
>>> 
>>> Suppose a transform with scale 1.5 is used and the 'a' char advance is 10 in a dev space.
>>> The 'a' char has advance 10 / 1.5 = 6.666666666666667 as double value and 6.6666665 when it is cast to float in user space.
>>> The width of a string which consists of 15 'a' chars is 15 * 6.6666665 =  100.000000.
>>> But the same width calculated as sum of each glyph advance in StandardGlyphVector.initPositions() method is 99.999992. 
>>> --------------
>>>        double scale = 1.5;
>>>         float advance = (float) (10 / scale);
>>>         int N = 15;
>>>         System.out.printf("%d * %f = %f\n", N, advance, N * advance);
>>>         float sum = 0;
>>>         for (int i = 0; i < N; i++) {
>>>             sum += advance;
>>>         }
>>>         System.out.printf("sum: %f\n", sum);
>>> --------------
>>> 
>>> Because of this a string drawn from float position 99.999998 is shifted one pixel left which affects the text selection code in Swing:
>>> ------------------------ 
>>>         g.scale(1.5, 1.5); 
>>>         String TEXT = "aaaaaaaaaaaaaaaa";
>>>         Rectangle2D rect = font.getStringBounds(TEXT, 0, index, g.getFontMetrics().getFontRenderContext()); 
>>>         float selectedTextPosition = (float) rect.getWidth();  //   99.999992
>>>         g.drawString(TEXT.substring(0, index), x, y); // non-selected text
>>>         g.drawString(TEXT.substring(index, TEXT.length()), x + selectedTextPosition, y); // selected text is shifted to one pixel left 
>>> ------------------------ 
>>    The last step is how coordinates are scaled in Graphics2D.drawString() method.
>>    If the graphics has scale 1.5 and zero translate the transformed coordinates are:    
>>     (99.999992 + 0) * 1.5 = 149.999985
>>     (100.000000 + 0) * 1.5 = 150.000000
>> 
>>   Both of them are rounded to the same value.
>> 
>>   If the translate is set to integer 1 value:
>>     (99.999992 + 1) * 1.5 = 151.499989  // shifted to one pixel left
>>     (100.000000 + 1) * 1.5 = 151.500000 
>> 
>>  A position 99.999992 in user space is rounded to 151 in dev space.
>>  A position 100.000000 in user space is rounded to 152 in dev space.
>> 
>>  And this difference can depend on the translate even it has integer value in user space because it is multiplied on the graphics scale.
>> 
>> Thanks,
>> Alexandr.
>> 
>>> 
>>> Thanks,
>>> Alexandr.
>>> 
>>> On 6/2/2016 11:41 PM, Alexandr Scherbatiy wrote:
>>>> On 5/31/2016 10:40 PM, Phil Race wrote:
>>>>> 
>>>>> I applied this and it is *much* better but there still seem to be some tiny quirks. 
>>>>> When I drag the mouse to select text down and then up again, as I pass the 
>>>>> original mouse click point vertically, repaint seem to jiggle vertically by a pixel. 
>>>>> Perhaps a rounding issue in the repaint code's calculation of the location of 
>>>>> the target y. I think I may see the same in left/right dragging along a line too. 
>>>>> So I think this is repaint and not text related. Can you take a look. 
>>>> 
>>>>     I am able to reproduce this only using a floating point scale.
>>>>     It looks like 2d issue. I used a test which draws a text in two pieces. The second piece of the text is shifted from the first piece by the floating point size of the the first piece of the text.
>>>>   -----------
>>>>     Rectangle2D rect = font.getStringBounds(TEXT, 0, index, g.getFontMetrics().getFontRenderContext()); 
>>>>     float selectedTextPosition = (float) rect.getWidth();
>>>>     g.drawString(TEXT.substring(0, index), x, y); 
>>>>     g.drawString(TEXT.substring(index, TEXT.length()), x + selectedTextPosition, y); 
>>>>   -----------
>>>>   
>>>>   The second piece of the text can be shifted in the 2 cases:
>>>>   a) graphics scale is 1.5 and translation is 1. 
>>>>   b) graphics scale is 2.25 without applied translation 
>>>> 
>>>>   I have filed an issue on it: 
>>>>     JDK-8158370 Text drawn from float pointing position and with float pointing scale is shifted
>>>>       https://bugs.openjdk.java.net/browse/JDK-8158370 <https://bugs.openjdk.java.net/browse/JDK-8158370>
>>>> 
>>>>   Thanks,
>>>>   Alexandr.
>>>> 
>>>>> 
>>>>> -phil.
>>>>> 
>>>>> 
>>>>> On 05/06/2016 12:31 PM, Alexandr Scherbatiy wrote:
>>>>>> Hello, 
>>>>>> 
>>>>>> Could you review the fix: 
>>>>>>   bug: https://bugs.openjdk.java.net/browse/JDK-8156217 <https://bugs.openjdk.java.net/browse/JDK-8156217> 
>>>>>>   webrev: http://cr.openjdk.java.net/~alexsch/8156217/webrev.00 <http://cr.openjdk.java.net/%7Ealexsch/8156217/webrev.00> 
>>>>>> 
>>>>>>   This is the second part of the fix related to the fact that char width can be fractional in user space. 
>>>>>> http://mail.openjdk.java.net/pipermail/swing-dev/2016-May/005814.html <http://mail.openjdk.java.net/pipermail/swing-dev/2016-May/005814.html> 
>>>>>> 
>>>>>>   The Font.getStringBounds(...) method is used for the fractional string width calculation by Swing in user space. 
>>>>>> 
>>>>>>  Thanks, 
>>>>>>  Alexandr. 
>>>>>> 
>>>>> 
>>>> 
>>> 
>> 
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/swing-dev/attachments/20160628/ff48eeb7/attachment.html>


More information about the swing-dev mailing list