<Swing Dev> [9] Review request for 8132119 Provide public API for text related methods in SwingUtilities2
Sergey Bylokhov
Sergey.Bylokhov at oracle.com
Thu Apr 28 09:20:52 UTC 2016
On 28.04.16 2:03, Phil Race wrote:
> I referred to this issue on this thread many emails ago as one reason
> why float might be better.
>
> Swing should be able to use these - or one of the other related ones -
> where it needs floating point.
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).
>
> 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?
>>>>>>
>>>>>
>>>>
>>>>
>>
>
--
Best regards, Sergey.
More information about the swing-dev
mailing list