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());
}