[Openmcl-devel] baselineDeltaForCharacterAtIndex:

Paul Krueger plkrueger at comcast.net
Thu Aug 15 16:46:17 PDT 2013

A short answer might be to check out #/boundingRectForGlyph: where the y position in the return value will be negative in the amount that it descends below its baseline. As you suggested in your question, if you get that for all the characters in the string you could perhaps compute the baseline offset as the maximum of those although I'm not at all sure that this is the way things are always laid out because in general if there is a single font used I believe the line spacing is uniform regardless of which individual glyphs displayed on each line. I suspect (although I don't know for sure) that the layout manager uses default font baseline offsets within each line-fragment rect (maybe using the max offset of all fonts displayed within the rect), but may change the size of each line-fragment rect independently depending on the fonts, sizes, and baseline adjustments of characters displayed within it. I guess I could also imagine that subscripting within the line-segment would result in a higher baseline for everything else too (i.e. greater than the max of all the font-specific baseline offsets). So if you're looking for an offset relative to a whole text view, I'm guessing it will get more complicated unless you assume there is no sub/super scripting.

The longer answer ...

I can almost imagine a convoluted way to accomplish what you want without making too many assumptions, but I have some questions.

For an arbitrary ns-text-view the text can be in any orientation (or in multiple different orientations in different parts) and in theory could be split across multiple text containers and multiple line-fragment rectangles within each container, but let's assume you're using a standard CCL hemlock text view. You still don't know that any arbitrary string is viewable on a single line and even if it is at the moment, that can change if the user resizes the window, so it isn't a constant. So what baseline do you want if text is split across multiple lines? Keep in mind that the layout manager will create multiple line-fragment rects at its own discretion.

Assuming that you somehow know that all the text of interest is displayed within a single line fragment rect, I can sort of imagine a way to get what you want, but it's very messy. I'm going to hand-wave my way through it because I wouldn't trust anything I'd do in detail without testing it.

Basically you need to work with the layout manager for the ns-text-view to first get the bounding rectangle for the line fragment in which you are interested by using #/lineFragmentRectForGlyphAtIndex:effectiveRange: and then find the position of the first glyph within that rect using #/locationForGlyphAtIndex:.

Then you have to find out how that glyph is normally laid out relative to its font, which you can do by calling #/boundingRectForGlyph: with the glyph's font and the glyph itself. That returns a rect and the y position will tell you how far it descends below the baseline (as a negative number). Of course you'll need to figure out what font is being used for that glyph in order to make that call and you can get that from the attributed string being laid out (using a #/attribute:atIndex:effectiveRange: call using NSFontAttributeName as a call parameter). You can get that attributed string from the ns-text-view's layout manager using a #/attributedString call. Then you need to worry about the possibility that the character had its baseline modified just for this display so you have to get that attribute for the glyph as well using another #/attribute:atIndex:effectiveRange: call but with NSBaselineOffsetAttributeName as the parameter. Note that either or both of those attribute retrievals might return a null pointer and you'll have to use some default return values if that happens.

Once you have all that, I think you have enough information to compute the baseline being used for the line segment in question relative to the bottom of its line-fragment rect. It should be something like the y-position of the glyph within the line-fragment rect + the amount the glyph normally descends from the baseline - any baseline adjustment that was made for this particular glyph display.

Line fragment rects are returned in container coordinates, so you may need to do some conversion to get everything correct for whatever view you want the coordinates to be relative to. 

As I said, that's a lot of hand-waving. I hope you have a really good reason for wanting to do this.

On Aug 15, 2013, at 11:51 AM, Glen Foy <lisp at clairvaux.org> wrote:

> This is a method of the NSTextInputClient protocol.  Implementation is optional, and NSTextView apparently does not provide an implementation.  The symbol is unbound.
> I need to find the screen coordinates of the baseline of a string of Hemlock code. The string will contain a mixture of fonts and font sizes. #/baselineDeltaForCharacterAtIndex: in combination with #/firstRectForCharacterRange:actualRange: will provide this, but the method is not implemented.
> Another approach would be to find the length of the largest descender in the string.  That would also probably provide the position of the baseline.  But the NSFont method #/descender returns the length of the largest descender in the font, not the descender of a particular glyph.
> Does anyone know a workaround?
> Thanks,
> -- Glen
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel

More information about the Openmcl-devel mailing list