<Swing Dev> [9] Review request for 8163124 Add floating point API support to javax.swing.text.Caret

Philip Race philip.race at oracle.com
Tue Sep 27 21:02:29 UTC 2016

Somewhat contrived but OK.
Is there an up-to-date webrev for this proposal ?


On 9/21/16, 9:21 AM, Alexandr Scherbatiy wrote:
>  When a font size is small and UI scale is large it is possible that a 
> char advance can be smaller than 1. For example, if font is Dialog 
> plain with size 2 and UI scale is 32 the 'j' char width has value 
> 0.47. For this case saved int caret position which is used to move a 
> caret to next line does not have enough precision to be placed between 
> the first and the second 'j' char.
>  I have prepared the test [1]. It should be run with the applied patch 
> [2] for the fix JDK-8156217 because it contains implementation of the 
> TextComponent.modelToView2D(pos) method. The test shows a JTextArea 
> with two lines "jjjjjjjjjjj" and uses a custom caret implementation. 
> Pressing the arrow key to the right and down leads that the caret is 
> moved before the first character on the second line instead of the 
> second character.
>   [1] 
> http://cr.openjdk.java.net/~alexsch/8163124/samples/MagicCaretPositionTest.java
>   [2] http://cr.openjdk.java.net/~alexsch/8156217/webrev.07/all_01
> Thanks,
> Alexandr.
> On 8/25/2016 8:58 AM, Philip Race wrote:
>> On 8/24/16, 9:45 AM, Alexander Scherbatiy wrote:
>>> On 17/08/16 22:49, Phil Race wrote:
>>>> Sorry, but I have had some trouble trying to picture this.
>>>> If the caret is between "b" and "c", being off by a fractional 
>>>> value seems
>>>> unlikely to make it jump to between "a" and "b".
>>>> It might now "round" to somewhere in the trailing pixel of "b" but 
>>>> nowhere
>>>> near the leading edge.
>>>   I suppose yes.
>>>   Another case is when a caret is in the center of the "b". In this 
>>> case it can be moved to another character if fractional values are 
>>> not taken into account. However, may be it does not matter which 
>>> character "a" or "c" would be chosen because they have nearly the 
>>> same distance to the center of the "b".
>> Indeed. And I think that is no different than today that "in the 
>> middle" means
>> it is 50:50 which way it goes with integers too.
>> Also unless this position was set by some code that just picked a 
>> position
>> out thin air, I would expect this to always be "between" the 
>> characters as
>> a result of normal calculation of the caret.
>> -phil.
>>> Thanks,
>>> Alexandr.
>>>> -phil.
>>>> On 08/11/2016 09:55 AM, Alexandr Scherbatiy wrote:
>>>>> I am sorry. The JTextComponent.viewToModel(Point) method returns 
>>>>> the closest location for the provided point. If the caret position 
>>>>> is N.25 the distance to the right character is 0.25 and to the 
>>>>> left one is greater than 0.75. Even in for the worst case the 
>>>>> distance to the right character is less than 1 and to the left is 
>>>>> greater than 1 (suppose a character width is greater than 1). For 
>>>>> the provided cases the caret should always be placed in the proper 
>>>>> closest location.
>>>>> There is just a question could a user just compare the provided 
>>>>> magic caret position (which coordinates are rounded) with the 
>>>>> result of rectangle from the method 
>>>>> JTextComponent.modelToView2(position) which returns the floating 
>>>>> point positions. So for the same position the rounded point can be 
>>>>> (N, y) and the rectangle can have bounds (N.25, y, w, h). 
>>>>> Comparing these results can lead that the magic caret point does 
>>>>> not belong to the provided rectangle but it is definitely that the 
>>>>> x coordinate of this rectangle is the closest one to this point.
>>>>> By the way, I can merge the added JTextComponent.modelToView2D(int 
>>>>> pos)/viewToModel2D(Point2D pt) public methods with the fix for the
>>>>>   8156217 Selected text is shifted on HiDPI display
>>>>>     http://cr.openjdk.java.net/~alexsch/8156217/webrev.04/
>>>>> Thanks,
>>>>> Alexandr.
>>>>> On 8/10/2016 5:22 PM, Alexandr Scherbatiy wrote:
>>>>>> Suppose there is a text area with two lines with the same text:
>>>>>> abcdefghij
>>>>>> abcdefghij
>>>>>> The char 'c' on the fist line has offset 2 and some coordinates 
>>>>>> (x1, y1) where x1 can have a floating point values like 21.25.
>>>>>> The char 'c' on the second line has offset 13 and coordinates 
>>>>>> (x2, y2) where x2 is equal to x1.
>>>>>> Setting the caret to the first 'c' character sets the magic caret 
>>>>>> position to  (round (x1), round (y1)) position.
>>>>>> Pressing the arrow down key calculates the new  y position and 
>>>>>> uses the x position from the magic caret position which is 
>>>>>> round(21.5) = 21.
>>>>>> Now the new offset can be calculated as 
>>>>>> textComponent.viewToModel(new Point(21, newY)) which returns 
>>>>>> offset 12 for char 'b' on the second line instead the offset 13 
>>>>>> for char 'c'.
>>>>>> Thanks,
>>>>>> Alexandr.
>>>>>> On 8/9/2016 11:32 PM, Philip Race wrote:
>>>>>>> But characters are of varying width. Being on the "20th" char on 
>>>>>>> line N
>>>>>>> may mean being on the "25th" on line N+1.
>>>>>>> So I am claiming this is nothing new and we really do not need 
>>>>>>> do anything here.
>>>>>>> -phil.
>>>>>>> On 8/9/16, 1:06 PM, Alexandr Scherbatiy wrote:
>>>>>>>> On 8/9/2016 12:44 AM, Phil Race wrote:
>>>>>>>>> I was not familiar with this "magic caret" but from reading it 
>>>>>>>>> seems like it has just one use/purpose.
>>>>>>>>> In the event that someone has multi-line text that you can 
>>>>>>>>> navigate around with up/down arrow keys
>>>>>>>>> and that text has lines of varying length, you want a 
>>>>>>>>> "preferred" horizontal position for the caret
>>>>>>>>> to be remembered so the caret is placed at that position 
>>>>>>>>> whenever the line of text has a length
>>>>>>>>> greater than the caret position. Is there anything more to it 
>>>>>>>>> than that ?
>>>>>>>>> Obviously the caret needs to be placed correctly in the 
>>>>>>>>> context of the text, so the precise position,
>>>>>>>>> even in an all-integer world, is not going to line up on every 
>>>>>>>>> single line, unless you have monospaced text.
>>>>>>>>> ie the "pixel" position is going to get converted into a 
>>>>>>>>> position on the leading or trailing edge of some glyph
>>>>>>>>> So I wonder, does adding float matter .. is the extra 
>>>>>>>>> precision valuable here ?
>>>>>>>>   It may depend on the rounding of a point position.
>>>>>>>>   Suppose there are two lines with the same text. The caret is 
>>>>>>>> on the first line can have x position N.25. Pressing down the 
>>>>>>>> arrow key can round it to the N and the caret can be set to a 
>>>>>>>> previous char on the second line.
>>>>>>>>   Thanks,
>>>>>>>>   Alexandr.
>>>>>>>>> -phil.
>>>>>>>>> On 08/04/2016 05:44 AM, Alexandr Scherbatiy wrote:
>>>>>>>>>> Hello,
>>>>>>>>>> Could you review the fix:
>>>>>>>>>>   bug: https://bugs.openjdk.java.net/browse/JDK-8163124
>>>>>>>>>>   webrev: http://cr.openjdk.java.net/~alexsch/8163124/webrev.00
>>>>>>>>>>   The text position can have floating point value on HiDPI 
>>>>>>>>>> display. The Caret interface should be updated to allow use 
>>>>>>>>>> floating point positions.
>>>>>>>>>>   The fix adds the following public API with floating point 
>>>>>>>>>> positions:
>>>>>>>>>>   javax.swing.text.Caret.getMagicCaretPosition2D()
>>>>>>>>>> javax.swing.text.Caret.setMagicCaretPosition2D(Point2D p)
>>>>>>>>>> javax.swing.text.JTextComponent.modelToView2D(int pos)
>>>>>>>>>> javax.swing.text.JTextComponent.viewToModel2D(Point2D pt)
>>>>>>>>>> javax.swing.text.ParagraphView.getClosestPositionTo(int pos, 
>>>>>>>>>> Position.Bias b, Shape a, int direction, Position.Bias[], int 
>>>>>>>>>> rowIndex, float x)
>>>>>>>>>>   The fix replaces 
>>>>>>>>>> Caret.getMagicCaretPosition()/setMagicCaretPosition(Point p) 
>>>>>>>>>> to 
>>>>>>>>>> Caret.getMagicCaretPosition2D()/setMagicCaretPosition2D(Point2D 
>>>>>>>>>> p) in all places
>>>>>>>>>>   except DefaultCaret because DefaultCaret extends Rectangle 
>>>>>>>>>> so its coordinates always have int values.
>>>>>>>>>>   I have filled a separated enhancement for this JDK-8163174 
>>>>>>>>>> Add DefaultCaret2D which supports floating point API
>>>>>>>>>>   To make a custom caret use floating point API it is also 
>>>>>>>>>> necessary that PlainView.modelToView() returns a rectangle 
>>>>>>>>>> with floating point values. It can be done after the fix
>>>>>>>>>>     JDK-8156217 Selected text is shifted on HiDPI display
>>>>>>>>>>   which implements Utilities.getTabbedTextWidth(Segment s, 
>>>>>>>>>> FontMetrics metrics, float x, TabExpander e, int startOffset) 
>>>>>>>>>> method.
>>>>>>>>>>   I have filled a separated issue on it:
>>>>>>>>>>     JDK-8163175 PlainView.modelToView() method should return 
>>>>>>>>>> Rectangle2D
>>>>>>>>>>  Thanks,
>>>>>>>>>>  Alexandr.

More information about the swing-dev mailing list