Articles Projects Tips Downloads Contacts About

Scaling with custom GlyphPainter in the JEditorPane/JTextPane.
By Stanislav Lapitsky

I was often asked about alternative solution for the fractional measuring support. To fix incorrect caret positioning all the measuring and drawing related methods must use float values based calculation. So to provide this I used replacement of standard java class GlyphPainter1 (unfortunately it’s not public) and changed all calculation to provide not int but float values. The main difference is using

    public Rectangle2D getStringBounds( char [] chars,
                                        int beginIndex, int limit,
                                        Graphics context) 

method rather than

    public int charsWidth(char data[], int off, int len) 

method used in GlyphPainter1 (not direct call but calling from Utilities.getTabbedTextWidth()). The second method returns int but from the first one we get float width of rectangle not the rounded int.

The alternative way works with properly set rendering hint of Graphics. I set the rendering hint in paint() method of root view.

        g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);

Also I replaced standard SUNís LabelView class with alternative one which sets the custom GlyphPainter.

class ScaledLabelView extends LabelView {
    static GlyphPainter defaultPainter;
    public ScaledLabelView(Element elem) {
        super(elem);
    }

    protected void checkPainter() {
        if (getGlyphPainter() == null) {
            if (defaultPainter == null) {
                defaultPainter = new ScaledGlyphPainter();
            }
            setGlyphPainter(defaultPainter.getPainter(this, getStartOffset(), getEndOffset()));
        }
    }

After the replacement caret is correctly positioned during navigation by arrow keys or by mouse click.

Appendix

You can download the example here. Source code is included in the .jar (see src directory).

Back to Table of Content