<Swing Dev> [9] Review request for 8156217 Selected text is shifted on HiDPI display
Alexandr Scherbatiy
alexandr.scherbatiy at oracle.com
Thu Jun 16 15:07:37 UTC 2016
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
>>
>> 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
>>>> webrev: http://cr.openjdk.java.net/~alexsch/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
>>>>
>>>> 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/20160616/acf2621f/attachment.html>
More information about the swing-dev
mailing list