-1

1
I need the absolute position of the charater. With:
editorPane.getFontMetrics(f).getAscent()
I only get a relative distance to the baseline. Maybe there is a way to get the absolute position of the baseline?

EDIT: This is the result of rect.y + rect.height - metrics.getDescent() - metrics.getAscent()

Cœur
  • 37,241
  • 25
  • 195
  • 267
Andreas
  • 23
  • 8
  • Call the JEditorPane’s [modelToView](http://docs.oracle.com/javase/8/docs/api/javax/swing/text/JTextComponent.html#modelToView-int-) method. – VGR Jan 12 '17 at 16:18
  • ModelToView does not work. It returns 0 for the y value. The height is like the word "World". I need y-coordinate of the beginning of the word "Hello". – Andreas Jan 12 '17 at 16:24
  • 1
    You will need to compute it from the bottom of the view rectangle: `rect.y + rect.height - metrics.getDescent() - metrics.getAscent()` (where `rect` is the value returned by modelToView) – VGR Jan 12 '17 at 16:35
  • Sorry, it does not work. Ascent + descent + leading = height. It is the height of the Highlighter. So I missed the space under the Highlighter. – Andreas Jan 12 '17 at 20:30
  • How are you obtaining the Font which you use to obtain a FontMetrics? – VGR Jan 12 '17 at 20:46
  • Font font = new Font((String) set.getAttribute(StyleConstants.FontFamily), Font.BOLD, (Integer) set.getAttribute(StyleConstants.FontSize)); – Andreas Jan 12 '17 at 21:08
  • And the set: AttributeSet set = ((AttributeSet)((StyledDocument)editorPane.getDocument()).getCharacterElement(pos)); – Andreas Jan 12 '17 at 21:09
  • Have you verified that the font is what you expect it to be? – VGR Jan 12 '17 at 21:28
  • Yeah, It is the current font. – Andreas Jan 13 '17 at 08:34
  • Is it the smaller font, or the larger font? – VGR Jan 13 '17 at 15:10
  • The problem is the smaller font – Andreas Jan 13 '17 at 15:11

2 Answers2

1

Since all fonts in a line share a baseline*, you can compute a character’s visual position by calling modelToView and subtracting the descent and ascent from the bottom of the rectangle.

Since multiple fonts are involved, obviously the getFont method of JEditorPane is not sufficient. The document’s raw element attributes are also insufficient, as an HTMLDocument’s attributes merely model the HTML elements themselves. However, the actual font for any document position can be obtained from the corresponding View:

static Point getLocation(int pos,
                         JEditorPane editorPane)
throws BadLocationException {

    HTMLDocument doc = (HTMLDocument) editorPane.getDocument();

    View view = editorPane.getUI().getRootView(editorPane);
    int index;
    while ((index = view.getViewIndex(pos, Position.Bias.Backward)) >= 0) {
        view = view.getView(index);
    }

    AttributeSet attr = doc.getStyleSheet().getViewAttributes(view);
    Font f = doc.getStyleSheet().getFont(attr);

    FontMetrics metrics = editorPane.getFontMetrics(f);
    Rectangle rect = editorPane.modelToView(pos);

    return new Point(rect.x,
        rect.y + rect.height - metrics.getDescent() - metrics.getAscent());
}

* For simplicity, I’m ignoring characters with hanging baselines and vertical baselines.

Edit: Since the RTFEditorKit is rarely used, I incorrectly assumed you were using an HTMLEditorKit. This will work with RTF documents:

static Point getLocation(int pos,
                     JEditorPane editorPane)
throws BadLocationException {
    StyledDocument doc = (StyledDocument) editorPane.getDocument();
    View view = editorPane.getUI().getRootView(editorPane);
    int index;
    while ((index = view.getViewIndex(pos, Position.Bias.Backward)) >= 0) {
        view = view.getView(index);
    }

    AttributeSet attr = view.getAttributes();
    Font f = doc.getFont(attr);

    FontMetrics metrics = editorPane.getFontMetrics(f);
    Rectangle rect = editorPane.modelToView(pos);

    return new Point(rect.x,
        rect.y + rect.height - metrics.getDescent() - metrics.getAscent());
}
VGR
  • 40,506
  • 4
  • 48
  • 63
0

I'm using the RTFEditorKit. So I changed the code:

static Point getLocation(int pos,
            JEditorPane editorPane)
            throws BadLocationException {

        View view = editorPane.getUI().getRootView(editorPane);
        int index;
        while ((index = view.getViewIndex(pos, Position.Bias.Backward)) >= 0) {
            view = view.getView(index);
        }

        AttributeSet set = view.getAttributes();
        if (set != null && set.getAttribute(StyleConstants.FontFamily) != null) {
            Font f = new Font((String) set.getAttribute(StyleConstants.FontFamily), Font.PLAIN, (Integer) set.getAttribute(StyleConstants.FontSize));
            FontMetrics metrics = editorPane.getFontMetrics(f);

            Rectangle rect = editorPane.modelToView(pos);
            return new Point(rect.x,
                    rect.y + rect.height - metrics.getDescent() - metrics.getAscent());
        }
        else {
            return new Point(0, 0);
        }
    }

But I always get the ascent of the current Font and not the ascent of the largest Font.

Andreas
  • 23
  • 8
  • Isn’t that what you want? Are you saying you always wanted the ascent of the largest font on the line, rather than the ascent of the font at the desired position? – VGR Jan 16 '17 at 13:13
  • Yeah, I need the ascent of the largest font. But I always get the ascent of the current position. – Andreas Jan 16 '17 at 13:15
  • This seems to conflict with the image in your question, which has a red arrow pointing to the top of the smaller font. Also, you commented: “ModelToView does not work. It returns 0 for the y value. The height is like the word "World". I need y-coordinate of the beginning of the word "Hello".” So, do you want the y-coordinate for text in the larger font, or the y-coordinate of text in the smaller font? – VGR Jan 16 '17 at 13:21
  • I want to set the caret to the right position (the arrow). The y-coordinate is r.y + (ascent of largest font - ascent of current font). – Andreas Jan 16 '17 at 13:26
  • If I understand you correctly, you want a text cursor which is as tall as the tallest font on the line, regardless of the font size at the cursor’s position. Correct? – VGR Jan 16 '17 at 18:21
  • No, I want a text cursor that has the size of the font size at the cursor’s position. – Andreas Jan 17 '17 at 15:49
  • Then why do you want the ascent of the largest font? – VGR Jan 17 '17 at 16:01
  • y = (r.y +(ascent of largest font - ascent of current font)) or not? – Andreas Jan 18 '17 at 11:30
  • That might work. But it seems to me calculating the result using just the font at the desired position would be more reliable. – VGR Jan 18 '17 at 14:34
  • I have updated my answer to work with RTF documents. – VGR Jan 19 '17 at 15:09