I have a lot of doubts about this as well as trouble getting my head
around all of it.
Given that apps need to 'buy in' to the floating point I am not sure
what we are gaining
but I need to make sure I understand the problem.
It affects only the methods that the 3rd party code can over-ride
in subclasses and that are called by the JDK internal code.
There are just two protected methods that matter :-
PlainView.drawSelectedText(..)
and
PlainView.drawUnselectedText(..)
The hidpi precison matters since they are drawing a sub-range of the text.
Is there any other method that matters / is used in this way ?
Since 3rd party code is not over-riding these they will get the JDK
super-class version, thus losing any customisation they might have done
in the no-longer-called int version.
Assuming that is correct, what customisation would be lost and how much
does it matter?
My prefernce is to deprecate the int versions and always call the float
versions
rather than the opt-in approach.
Actually my real preference would be to come up with something that does
not involve drawing the text in chunks like this.
ie Swing should use AttributedCharacterIterator .. it looks like the
code to
do this might already be there !
106 private float drawElement(int lineIndex, Element elem, Graphics g,
107 float x, float y, boolean
fractionalCharBounds)
108 throws BadLocationException
109 {
110 int p0 = elem.getStartOffset();
111 int p1 = elem.getEndOffset();
112 p1 = Math.min(getDocument().getLength(), p1);
113
114 if (lineIndex == 0) {
115 x += firstLineOffset;
116 }
117 AttributeSet attr = elem.getAttributes();
118 if (Utilities.isComposedTextAttributeDefined(attr)) {
119 g.setColor(unselected);
120 x = Utilities.drawComposedText(this, attr, g, x, y,
121 p0-elem.getStartOffset(),
122 p1-elem.getStartOffset());
123 } else {
In fact what *that* illustrates is that applications already cannot expect
their over-ridden methods to be called, so this fix is trying to fix
something
that can't be fixed.
So why can't we do that ? Just deprecate those int methods, don't add
the float methods and use ACI ..
BTW getTabSize() is supposed to be a character count isn't it ? Not a pixel
count. So why does it need a float version.
-phil
On 06/30/2016 08:50 AM, 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.scherba...@oracle.com
<mailto:alexandr.scherba...@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.