MacArthur, Ian (SELEX GALILEO, UK) wrote: > 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?
fltk2.0 made width, ascent, descent all return floating point, and removed the width(char) call so you can only pass a string. These are probably acceptable changes for 1.3. getwidth() returns the *advance* of the string, which is different than the horizontal extents. This is the position to put the next letter. If you used the extents to do this, all the letter would be squished together without kerning. Fltk spaces the lines apart by using the size used to select the font. The ascent/descent and any info from the font are *not* used, as I found that too many fonts had strange information in them. And it was really useful for the line spacing to not depend on the font. Fltk only uses the ascent/descent calls to select an origin to center text vertically. This requires these to be constant for a font, as otherwise the "centering" would move up/down depending on the letters being drawn. This is a common bug in code that uses "advanced" font layout and you should make sure you are not doing the same mistake in your requests to get true extents. In fltk2 the measure() call has pretty much been defined as "return the w&h of a box that when passed to drawtext will be filled with the text and the text will look centered in it". The primary use is to center this box in a widget so that the resulting label looks centered. Because of this use it must also not return extents, but advance values and line spacing. Otherwise the labels would move annoyingly depending on which characters are in the labels. Vertically is the main problem, but users expect the same number of letters in a fixed-pitch font to not move horizontally either. I think a new api could be added to return the extents of a string. This would return an entire rectangle, which is the tightly-fitted box around the drawn glyphs. It may make sense to have two of these, one matches width() and the other matches measure(). The width() one would also return the advance value, the measure() one would return both rectangles: the "centering" one, and the "extents" one. > (I think this is a bug...) > > 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. I agree this is a bug. The fltk2 code has already been fixed to do a single GetTextExtentPoint32W() call. _______________________________________________ fltk-dev mailing list [email protected] http://lists.easysw.com/mailman/listinfo/fltk-dev
