<div dir="ltr">Thanks for your response!<br>Sorry about not mentioning it explicitly in the original email, but it was not<br>about functionality gap - we can definitely achieve required behaviour using<br>already existing API. It was about performance and simplicity of the code needed<br>to achieve that.<br><br>> You don't really need a hidpi device, you just need a transform for that logic<br>> to become a problem.<br>Graphics transform doesn't represent a problem for our case, as we deliver an<br>application (where user only chooses font name and size), not a text component<br>to our users, and transform is under our control (we don't use any). On the<br>other hand, we cannot control what screen type our application is being<br>used on.<br><br>Complex text, surely, needs to be handled differently, and we do handle it<br>differently (using Font.layoutGlyphVector). But as our use case is a code<br>editor, most of the actual text is simple, and a separate code path for it,<br>for optimization purposes, seemed like a good idea. This changed somewhat when<br>programming fonts with ligatures became popular, so maybe, in future, always<br>working with glyph vectors will be a simpler option.<br><br>As for the code sample with getStringBounds, you're right, it should use<br>getWidth() instead of 'x'. The code was not real - it's just an illustration.<br>We've not settled down on a solution, supporting hidpi screens yet. We can<br>probably live with the existing API, I just wanted to highlight that making<br>quite simple things with it now requires more complex code. Optimising<br>getStringBounds can be useful, but introducing something like 'charWidth2D'<br>looked conceptually simpler for me (I understand though, that it might be too<br>late for Java 9). And 'charWidth', as well as other integer-returning 'width'<br>methods just become much less useful in Java 9, taking into account spreading<br>of hidpi monitors.<br><br>Best regards,<br>Dmitry Batrak<br><div class="gmail_extra"><br><div class="gmail_quote">On Fri, Dec 23, 2016 at 9:52 PM, Phil Race <span dir="ltr"><<a href="mailto:philip.race@oracle.com" target="_blank">philip.race@oracle.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
  
    
  
  <div bgcolor="#FFFFFF">
    <br>
    <br>
    <div class="gmail-m_-5569145984667353568moz-cite-prefix">On 12/20/2016 02:11 AM, Dmitry Batrak
      wrote:<br>
    </div>
    <blockquote type="cite">
      <div dir="ltr">Missing floating-point-precision method in font
        measuring API<br>
        <br>
        Hello,<br>
        <br>
        It looks like there's currently a gap in text measuring API with
        respect to<br>
        methods working with floating point coordinates. It's not
        something new, but<br>
        with HiDPI support added in Java 9, it seems to become more
        significant.<br>
        <br>
        Consider the following simplified use case of custom text
        component which<br>
        supports highlighting. Suppose we initially draw a couple of
        characters<br>
        (in paintComponent method) like this<br>
        <br>
          char[] text = new char[] {'a', 'b'};<br>
          int x = ..., y = ...;<br>
          g.drawChars(text, 0, 2, x, y);<br>
          <br>
        But then we need draw the second character in a different color,
        and we'd like<br>
        the glyph positions to be the same. We assume the text is simple
        (e.g. Latin, <br>
        without ligatures, etc). The simplest way to do it is<br>
        <br>
          g.drawChars(text, 0, 1, x, y);<br>
          g.setColor(...);<br>
          int advance = g.getFontMetrics().charWidth(<wbr>text[0]);<br>
          g.drawChars(text, 1, 1, x + advance, y);<br>
      </div>
    </blockquote>
    <br>
    Even though Swing has been doing this, we've frowned on this for a
    long time<br>
    because there are many rendering attributes that might affect this
    and it<br>
    pre-supposes an unscaled graphics. You don't really need a hidpi
    device,<br>
    you just need a transform for that logic to become a problem.<br>
    And that also supposes that you *know* the user didn't specify any
    non-obvious<br>
    attributes on the font. There is even a "hasLayoutAttributes()"
    method that<br>
    should be called before you even attempt such logic.<br>
    And you still need to know its not complex text.<br>
    <br>
    <blockquote type="cite">
      <div dir="ltr"><br>
        This will not work though, if advance is not integer. We
        wouldn't be affected<br>
        by this issue, if we didn't use fractional metrics, but in HiDPI
        case <br>
        the advance can fractional even if fractional metrics are not
        used - <br>
        glyph is positioned at integer coordinates in device space, so
        e.g. with <br>
        200% scale, in user space it can contain half-pixels. Current
        solution is<br>
        <br>
         float advance = (float)g.getFontMetrics().<wbr>getStringBounds(text,
        0, 1, g).x;<br>
      </div>
    </blockquote>
    <br>
    Is that actual code, or just trying to give an idea of what you are
    doing.<br>
    "x" is (a) only available if you know you can cast to Rectangle, and
    I don't think you can<br>
    and (b) x would give you the logical position of the char at index 0
    .. which should<br>
    always be 0.0 .. not the advance from there to the char at index 1.<br>
    <br>
    I also don't understand why you aren't using the APIs on Font
    directly<br>
    if efficiency is a concern but as you note here ...<br>
    <br>
    <blockquote type="cite">
      <div dir="ltr"> g.drawString(new String(text, 1, 1), x + advance,
        (float)y);<br>
         <br>
        Alternatively, we can use font.createGlyphVector() instead of
        getStringBounds<br>
        (this is done internally anyway), but in any case an instance of
        GlyphVector<br>
        will be created in the process, which seems unnecessary </div>
    </blockquote>
    <br>
    ... we are creating a GlyphVector which is a lot more heavyweight
    than a Rectangle<br>
    so you won't see a lot of savings.<br>
    <br>
    <blockquote type="cite">
      <div dir="ltr">- all we need is advance<br>
        which is already available, we just cannot get it directly
        without it being<br>
        rounded.</div>
    </blockquote>
    <br>
    You can definitely get it using getStringBounds() as you noted.<br>
    You mean you cannot get it without the extra overhead ?<br>
    <br>
    <br>
    <blockquote type="cite">
      <div dir="ltr"> Creation of new String instance, copying
        underlying text, also doesn't<br>
        seem to be necessary, but there's no other method to draw part
        of existing text<br>
        using floating point coordinates.<br>
        <br>
        Do you think adding corresponding new floating-point-based
        method to FontMetrics<br>
        (and maybe to Graphics2D) makes sense? Maybe it's planned
        already as part of<br>
        HiDPI-related activity? Should I raise an RFE via <a href="http://bugs.java.com" target="_blank">bugs.java.com</a>
        for this?<br>
      </div>
    </blockquote>
    <br>
    <br>
    Java 2D in JDK 1.2 added the floating point APIs to Font<br>
    I am not aware of anything you might need to do at an API level that
    isn't there.<br>
    The question seems to be more about a more lightweight
    implementation.<br>
    <br>
    What I think you are asking for is basically<br>
    public float java.awt.Font.<wbr>getStringAdvance(String s,
    FontRenderContext frc)<br>
    and/or<br>
    public float java.awt.Font.<wbr>getStringAdvance(char[] chs, int begin,
    int limit,  FontRenderContext frc)<br>
    <br>
    Although if we accept that the Rectangle is just a minor problem,
    then<br>
    perhaps updating the implementation of getStringBound to avoid the
    GlyphVector<br>
    in the same cases that we'd be able to do with a proposed
    getStringAdvance.<br>
    <br>
    That would get you 95% of the available performance gain with no
    need to change code.<br>
    And it would avoid needing to create new API after JDK 9 feature
    freeze which<br>
    was reached this week.<br>
    <br>
    I think that is something that would be expected to be done if we
    added a new API anyway.<br>
    <br>
    <br>
    -phil.<br>
    <br>
    <blockquote type="cite">
      <div dir="ltr"><br>
        Thanks,<br>
        Dmitry Batrak<br>
        <br>
        <br>
      </div>
    </blockquote>
    <br>
  </div>

</blockquote></div><br></div></div>