Font Metrics (was TextField Document model)
swpalmer at gmail.com
Sat Oct 27 22:00:38 PDT 2012
My only complaint is that I had to subclass the default TextFieldSkin and set the TextField to use my skin just to get at the FontMetrics that were in use on the TextField control. I had no intention of actually implementing a skin or changing the behaviour of the default skin. I just wanted to position a popup where the caret was. So yes FontMetrics has what I need, but it should be more accessible.
On 2012-10-28, at 12:25 AM, Felipe Heidrich <felipe.heidrich at oracle.com> wrote:
> On Oct 26, 2012, at 8:18 AM, Richard Bair wrote:
>> I think these are two distinct issues -- font metrics and locating glyph bounds within a string of text. FontMetrics I think is fairly straightforward -- Felipe what do you think?
> Here the basics
> Text text = new Text();
> text.setFont(Font.font("Helvetica", 24));
> System.out.println("Baseline:" + text.getBaselineOffset());
> Bounds bounds = text.getLayoutBounds();
> //text origin by default is relative to baseline
> System.out.println("Ascent " + -bounds.getMinY());
> System.out.println("Descent " + bounds.getMaxY());//including leading
> System.out.println("LineHeight " + bounds.getHeight());
> If you dig in the internals a bit you will see a FontLoader class that returns a FontMetrics object for a given Font, it has x-height and other properties in it.
> Other metrics like average char width I don't think the user can ever get. I think we could provide better API in this area.
>> For the other use case, actually knowing the glyph bounds is not enough (probably). The problem is, suppose that text you were looking for wrapped from one line to the next (letter wrapping instead of word wrapping, or maybe you were searching for a phrase rather than just a word). In this case you need to know the shape that would encompassing text from both lines (think: blue selection box). Even more challenging is BIDI and ligatures -- what if the text you searched for was only using part of a glyph due to ligatures? Or you have disjoint shape due to BIDI (selection is a good example of this again).
>> Now, internally we use an impl on Text to get the shape based on a range of indexes into the Text, and this shape is then used to draw selection. In our quest to get rid of impl methods, I have wanted to see this get proper API treatment. Maybe we would have a TextMeasurement class, and Text node (and TextFlow) would return an instance of it and we could have a method on it that vends a shape. Once you have a shape you can set the fill, stroke, etc as you like.
> As Richard said, internally we have all the information, we just need to design a proper API.
> In the meantime, have you looked at TextFieldSkin caretPosition() and getCharacterBounds(), it is based on Text's private API but it is a bit cleaner and sounds like what you are looking for. Anyhow, TextFieldSkin is not part of the public API so not sure if it is a better approach for you.
More information about the openjfx-dev