<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