<Swing Dev> [9] Review request for 8132119 Provide public API for text related methods in SwingUtilities2
Alexander Scherbatiy
alexandr.scherbatiy at oracle.com
Wed May 11 13:58:24 UTC 2016
Hello,
Could you review the updated fix:
http://cr.openjdk.java.net/~alexsch/8132119/webrev.12
Public methods to handle fractional text position are added to Swing.
- methods which use integer position now has a pair with the same
name and fractional position
- methods which use Rectangle and Point objects have corresponding
methods with 2D suffix.
The DefaultCaret extends directly Rectangle so there is no way to
change it to use Rectangle2D without breaking a backward compatibility.
The new DefaultCaret2D is a subject of a separate fix.
- methods which only returns integer value have corresponding methods
with 'fractional' prefix
The new methods are added only as stubs now. The real implementation
will be provided in the corresponding fixes like:
http://mail.openjdk.java.net/pipermail/swing-dev/2016-May/005828.html
The discussed problem that text width can differ for different
graphics transforms is filled as:
JDK-8156758 Text width depends on the graphics transform
https://bugs.openjdk.java.net/browse/JDK-8156758
Thanks,
Alexandr.
On 4/28/2016 2:31 PM, Sergey Bylokhov wrote:
> On 28.04.16 12:20, Sergey Bylokhov wrote:
>> The problem below and a suggestion of using float has the similar
>> symptoms to the situation when fm-on, when actual rendering and metrics
>> in "int" are different. The suggestion of using float is correct, but
>> why it should be used when fm-off? according to the spec all metrics in
>> this case should be calculated as "int". I still think that all these
>> problems are occurs because we incorrectly calculate "int" metrics when
>> fm-off(actually from the users point of view fm-off mode is useless,
>> because even if fm-off the application get fractional data instead of
>> expected ints).
>
> I suggest to implement it like on OSX, then tweak the algorithm of
> rounding, and if after that someone will complains then add a new
> render hint to round the text according the user space.
>
>>
>>>
>>> When Swing detects complex text it turns over editing and highlighting
>>> to TextLayout, does it not ?
>>> Perhaps doing the same for hi-dpi would work as well.
>>>
>>> -phil.
>>>
>>> On 04/27/2016 01:41 PM, Alexandr Scherbatiy wrote:
>>>>
>>>>
>>>> I just want to highlight one more problem which happen even font
>>>> metrics with right transform are used.
>>>> It refers to the text selection.
>>>>
>>>> Suppose there is a graphics with scale 2. The char 'a' advance can
>>>> be 13 in device space and 13 / 2 = 6.5 in user space.
>>>> The task is to highlight a selected text in the middle of a string
>>>>
>>>> Let's the selected index will be 11. The x coordinate to draw the
>>>> selected text is FontMetrics.charsWidth(chars, 0, index) = 72.
>>>> The selected text drawn from this position will be shifted to the
>>>> right because real x coordinate in user space is 6.5 * 11 = 71.5.
>>>> This leads that text is jumping when it is selected and deselected.
>>>>
>>>> To properly draw a selected text in this case there should be API
>>>> which allows both return float chars width and draw a text from float
>>>> position.
>>>> But we have only API which gets a chars width and draws a text from
>>>> int position in the user space.
>>>>
>>>> Below is a code which illustrate the text selection issue.
>>>> The image shows two strings which are selected from index 10 and 11.
>>>> The second selection is shifted to the right:
>>>> http://cr.openjdk.java.net/~alexsch/8142966/images/text-selection.png
>>>>
>>>> ----------------------------
>>>> int imgWidth = 400;
>>>> int imgHeight = 150;
>>>>
>>>> BufferedImage buffImage = new BufferedImage(imgWidth,
>>>> imgHeight,
>>>> BufferedImage.TYPE_INT_RGB);
>>>>
>>>> Graphics2D g = buffImage.createGraphics();
>>>> g.setColor(Color.WHITE);
>>>> g.fillRect(0, 0, imgWidth, imgHeight);
>>>>
>>>> int x = 10;
>>>> int y1 = 20;
>>>> int y2 = 40;
>>>>
>>>> g.scale(2, 2);
>>>> String text = "aaaaaaaaaaaaaaaaaaaaaaaa";
>>>> g.setColor(Color.BLUE);
>>>> char[] chars = text.toCharArray();
>>>> g.drawChars(chars, 0, chars.length, x, y1);
>>>> g.drawChars(chars, 0, chars.length, x, y2);
>>>>
>>>> int selIndex = 10;
>>>> int selNum = 6;
>>>>
>>>> FontMetrics fm = g.getFontMetrics(g.getFont());
>>>> g.setColor(Color.RED);
>>>> g.drawChars(chars, selIndex, selNum, x + fm.charsWidth(chars,
>>>> 0, selIndex), y1);
>>>> selIndex++;
>>>> g.drawChars(chars, selIndex, selNum, x + fm.charsWidth(chars,
>>>> 0, selIndex), y2);
>>>>
>>>> g.dispose();
>>>> ----------------------------
>>>>
>>>>
>>>> On 4/27/2016 6:17 AM, Philip Race wrote:
>>>>> Applications cannot change the device transform and expect the same
>>>>> user space
>>>>> metrics unless they specify fractional metrics to be ON.
>>>>>
>>>>> In your example below you may already have a scaled graphics context
>>>>> if you were printing (for example).
>>>>>
>>>>> If you want no change to the user space positions or [as also
>>>>> implied] shapes of the glyphs
>>>>> as the transform changes then you are asking for text that will not
>>>>> look
>>>>> right at other resolutions. Printed text will look poorly spaced.
>>>>>
>>>>> Changing what happens in the font system is not an option since it
>>>>> will break many applications - even if it were the right thing to do
>>>>> - which it is not.
>>>>>
>>>>> -phil.
>>>>>
>>>>>
>>>>> On 4/26/16, 4:49 PM, Sergey Bylokhov wrote:
>>>>>> On 27.04.16 1:50, Phil Race wrote:
>>>>>>> Glyphs are always rasterised in device space so it does mean device
>>>>>>> space.
>>>>>>
>>>>>> I don't argue with it, the question is how to round.
>>>>>>
>>>>>>> The identity transform therefore happens to always return a user
>>>>>>> space
>>>>>>> advance is that is an integer, but it is not bound to be so
>>>>>>> under any
>>>>>>> other transform.
>>>>>>
>>>>>> I am not sure that this is correct. The simple example:
>>>>>>
>>>>>> BufferedImage bi = new BufferedImage(width, height,TYPE_INT_ARGB);
>>>>>> int length = g2d.getFontMetrics().stringWidth(TEXT);
>>>>>> Graphics2D g2d = bi.createGraphics();
>>>>>> g2d.scale(2, 2);
>>>>>> length = g2d.getFontMetrics().stringWidth(TEXT);
>>>>>>
>>>>>> In what space will be the length? I assume that this is the user
>>>>>> space. Note that if in the second time we get 13 pixels we will
>>>>>> round it to 7 (but rendering will be done to 6.5 * 2 = 13). My
>>>>>> suggestion in the fix is to make this round on the lower level and
>>>>>> use the same values as stringWidth() and during rendering.
>>>>>>
>>>>>>>
>>>>>>> -phil.
>>>>>>>
>>>>>>> On 04/26/2016 03:28 PM, Sergey Bylokhov wrote:
>>>>>>>> On 27.04.16 0:34, Phil Race wrote:
>>>>>>>>> Fractional metrics being "off" does not mean that *user space*
>>>>>>>>> advances
>>>>>>>>> need to be integers,
>>>>>>>>> it refers to *device* space advances. Of course if your API does
>>>>>>>>> not
>>>>>>>>> support floats you have a
>>>>>>>>> problem - particularly if - you are character advance adding in
>>>>>>>>> which
>>>>>>>>> case it is better to ask the
>>>>>>>>> font system for the overall advance of the text.
>>>>>>>>> https://docs.oracle.com/javase/8/docs/api/java/awt/RenderingHints.html#KEY_FRACTIONALMETRICS
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>> The documentation says that in case of "fm-off" the "simplified
>>>>>>>> system
>>>>>>>> based on integer device positions is typically used" + "rounding
>>>>>>>> advance widths for rasterized glyphs to integer distances", it
>>>>>>>> does
>>>>>>>> not say that the "integer distance" should be rounded to the
>>>>>>>> nearest
>>>>>>>> device/pixel. It says that "rounding operations as the high
>>>>>>>> quality
>>>>>>>> and very precise definition of the shape and metrics of the
>>>>>>>> character
>>>>>>>> glyphs must be matched to discrete device pixels" I guess we
>>>>>>>> should
>>>>>>>> confirm the specification because results of the fix will be
>>>>>>>> "discrete
>>>>>>>> number of device pixels", isn't it?
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>
>>
>>
>
>
More information about the swing-dev
mailing list