<Swing Dev> [9] Review request for 8132119 Provide public API for text related methods in SwingUtilities2
Phil Race
philip.race at oracle.com
Fri May 13 20:58:18 UTC 2016
On 05/11/2016 06:58 AM, Alexander Scherbatiy wrote:
>
> Hello,
>
> Could you review the updated fix:
> http://cr.openjdk.java.net/~alexsch/8132119/webrev.12
From an API perspective this seems fine with the caveats that you have
follow-on implementation work to do and that I am not familiar with a number
of these Swing APIs ..
-phil.
>
> 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