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?











Reply via email to