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

Alexandr Scherbatiy alexandr.scherbatiy at oracle.com
Wed Jul 6 15:40:39 UTC 2016


Could you review the fix:
   http://cr.openjdk.java.net/~alexsch/8156217/webrev.03

   This is the same fix, just applied to the latest repository sources 
where the fix 8132119 "Provide public API for text related methods in 
SwingUtilities2" has been pushed.

   - public isUseFloatingPointAPI()/setUseFloatingPointAPI() methods are 
added to the PlainView and WrappedPlainView classes
   - some @implSpec descriptions are removed from the new text drawing 
methods with floating point arguments
   - Built-in L&Fs are updated to use floating point API in standard 
Java text components

   Thanks,
   Alexandr.

On 6/30/2016 6:50 PM, Alexandr Scherbatiy wrote:
> On 6/28/2016 8:14 PM, Alan Snyder wrote:
>> 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?
>
>   Here is a slightly updated version which adds public 
> isUseFloatingPointAPI()/setUseFloatingPointAPI() methods to the 
> PlainView and WrappedPlainView classes:
> http://cr.openjdk.java.net/~alexsch/8156217/webrev.02
>
>   Using the floating point API is disabled by default and enabled for 
> standard Swing text component classes. This has advantage that 
> selection will work for text component in users applications on HiDPI 
> display.
>
>   But it still has the same problem. Applications which use custom 
> View classes needs to updated them to implement corresponding text 
> drawing methods with floating point arguments and enable the floating 
> point API usage.
>
>   Thanks,
>   Alexandr.
>
>>
>>   Alan
>>
>>
>>> On Jun 28, 2016, at 9:59 AM, Alexandr Scherbatiy 
>>> <alexandr.scherbatiy at oracle.com 
>>> <mailto: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
>>>
>>> - 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
>>>>>>
>>>>>>   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/20160706/bd9dd172/attachment.html>


More information about the swing-dev mailing list