All, What follows is kind of in 3 parts, but all jumbled in together: partly me proposing an enhancement to fltk's text handling API, partly me asking for suggestions for my current problem, and partly me making some observations on the current method.
Probably this needs broken out as a couple of STR's, but I wanted to see what folk thought about it first. Background: I had done a little app that used Cairo to render text (as an organised map) positioning the various strings in specific locations wrt each other. This worked well, but was surprisingly slow. So I reworked the code in "plain" fltk. This ran much faster, but basically did not work. The reason it did not work was that the extents returned by fl_measure, fl_height and fl_width for a given string are not really all that useful - at least not in this context. So I had a look at the code, here's what I find: - fl_height (and by extension the height part of fl_measure) is simply set when the font is loaded (based on reported ascent and descent for the most part) and does not measure the actual extent of the text at all. - No method even exists such as "fl_height(char *)" that could be used to ascertain the height extent of given string. - fl_width(char *) (and it's siblings) more or less seem to work, although I am concerned about the win32 implementation, which seems suspect to me. (More on that story later...) Tests: I ran a few tests, loading the same font (as far as I can tell) in both fltk and Cairo, then printed the extents of a few strings in each. The reported widths are similar (although win32 is a bit dodgy) but the heights vary significantly. It is clear that some faces have quite odd ascent/descent settings, and the height we generate really doesn't match the rendered glyphs at all well. In general, the width/height returned by Cairo defines a box that fits fairly neatly round the actual glyphs, whereas the fltk extents do not, the bounding box is generally too high. Sometimes very much so. Which messed up my app. Proposal 1: For fltk-1.3 we consider adding a fl_height(char *) function (or set of functions) analogous to the fl_width(...) family, that returns, as best we can, the *actual* extent of the passed string, rather than simply returning the font's default height all the time. The existing fl_height(void) function will continue as at present for backwards compatibility. Proposal 2: For fltk-1.3 we consider, as above, reworking fl_measure(...) to return the actual height extent of the passed string. I am not clear on whether we need a "backwards compatible" fl_measure or not... Anyone? fl_width and win32: (I think this is a bug...) When testing this, I found that the width returned on win32 seemed to be more "out of step" with the Cairo value than I was seeing from the same test on OSX. Looking at the win32 implementation of "double fl_width(const char* c, int n)" I notice it looks a bit odd; certainly it seems to be out of step with the OSX and XFT implementations. (It *might* be more consistent with the implementation of XUtf8TextWidth() in the fl_font_x.cxx version, but I seldom/never use that variant.) Anyway, when passed a string, the win32 version of fl_width essentially computes the width of each individual character, then adds them together, completely ignoring any kerning or similar that the text rendering mechanism will apply, so the computed width is generally going to be a bit bigger than "the truth", possibly by a lot depending on which actual glyphs are in the string... Even more strangely, it does this using the function call GetTextExtentPoint32W(...) which is intended to be passed a string for measuring, so we have special code in fl_width() to chop the input string up into individual characters for measuring independently, then the measured widths are cached in a large (dynamically allocated and resized) array so we can get the individual glyph sizes more quickly next time. Both the XFT and OSX implementations simply measure the passed string directly, (using XftTextExtents* and ATSUGetUnjustifiedBounds respectively) so that the returned width reflects kerning and so forth of the string *as it will be rendered*. No attempt is made to cache glyph widths. The win32 implementation seems wrong to me - we need to know the width of the string *as it will be drawn* and therefore we need to allow for kerning and layout, and to this end we must not measure individual glyphs, and we can not cache the glyph sizes (since the sizes may not be valid, depending on which glyphs are adjacent in any given string with kerning, layout, etc...) And that's about it... Long post, sorry. - What do people think? Should we have an extended fl_height/fl_measure mechanism to determine the actual size of the text glyphs to be drawn? If so, I'll generate some STR's. - Does anyone have existing code to determine actual glyph height under fltk? If not, I'll be writing some anyway, so I'll (later) post it onto any STR's I raise for this. It doesn't look to be all that hard (if we do it inside the fl_font mechanism) but looks to be a real pain to do in "user space" under fltk, as we don't have ready access to the actual platform specific font entities.. - Do folk think the win32 fl_width() mechanism should be brought more into line with the XFT/OSX implementation? Or should we leave it alone? Or...? Cheers, -- Ian SELEX Sensors and Airborne Systems Limited Registered Office: Sigma House, Christopher Martin Road, Basildon, Essex SS14 3EL A company registered in England & Wales. Company no. 02426132 ******************************************************************** This email and any attachments are confidential to the intended recipient and may also be privileged. If you are not the intended recipient please delete it from your system and notify the sender. You should not copy it or use it for any purpose nor disclose or distribute its contents to any other person. ******************************************************************** _______________________________________________ fltk-dev mailing list [email protected] http://lists.easysw.com/mailman/listinfo/fltk-dev
