Closed egnor closed 1 month ago
Thanks for your proposal. I never received much feedback to the font rendering functions, so thanks for this :-) I like your ideas and they indeed make sense, however, my resources on this project are very limited at the moment, so let's see when I can spent some time on this.
Of course! Any obvious gotchas if someone else were to take a stab at it?
I started to look into this. So far most fonts seem to start exactly at the origin like helvB08 in the picture below.
The only difference seems to be ncenB08, which starts one pixel earlier. Is there any example font, which starts one pixel to the right?
I think there was a similar topic here: https://github.com/olikraus/u8g2/issues/1561
So the uppercase C from helvR08 has a one pixel right offset.
for positive x offset the string width calculation will compensate this a little bit
As a first step, I could implement "getGlyphLeftMargin ()" ...
So at the moment I am more think to keep the name as getXOffset instead of get..LeftMargin, because it is somehow strange to have a negative margin.
I have introduced and tested
int8_t u8g2_GetXOffsetGlyph(u8g2_t *u8g2, uint16_t encoding);
int8_t u8g2_GetXOffsetUTF8(u8g2_t *u8g2, const char *utf8);
So the expected value "1" is returned:
printf("helvR08 C xoffset=%d\n", (int8_t)u8g2_GetXOffsetGlyph(&u8g2, 'C'));
printf("helvR08 Ĉ xoffset=%d\n", (int8_t)u8g2_GetXOffsetUTF8(&u8g2, "Ĉ"));
As expected during my review, the GetStrX doesn't work for UTF8 strings. It will return the wrong value 0:
printf("helvR08 Ĉ xoffset=%d\n", (int8_t)u8g2_GetStrX(&u8g2, "Ĉ"));
I think there is no need for a special mode. If the offset is not required, then just compenstate the offset: u8g2.drawUTF8(x-u8g2.getXOffsetUTF8(string), y, string)
I will close this for now...
References:
It is a surprising misfeature that
drawStr(x, y, text)
doesn't always start drawing atx
-- often the actual text starts a pixel or so to the right of the specified coordinate, depending on the character. This leads to little annoying misalignments that can be seen in many screenshots and examples.My understanding of the issue
In the BDF font format which u8g2 is based on, glyphs are given as a set of pixels within a bounding box, and also an offset from logical "origin 0" of the glyph to the lower-left corner of the bounding box. This "origin 0" describes the start of the glyph's baseline. (There's also an "origin 1" used for writing systems like CJK with multiple writing directions, I'll ignore that here.)
In a theoretical sense, origin 0 is the "left hand edge" of the character, and it would make sense for
drawStr
to place the first character's origin 0 at the provided x/y coordinates. In a more accurate real sense, many fonts, especially Latin fonts, tend to use it as a rough kerning hint. For example, inhelvR08
, uppercase letters with a strong vertical left-hand-side riser have origin 0 one pixel to the left of that riser to give a bit more visual space from the preceding character. (I'm speculating as to the intent of the font's creator. Since X11 uses these fonts, I bet there's been discussion of this!)Currently the only way for a user of u8g2 to deal with this is with the undocumented C-api-only
u8g2_getStrX
function.Preferred behavior
For the purpose of u8g2, it should follow these values for placing one glyph after the next, I believe users care far more about the actual physical leftmost pixel (and rightmost pixel):
draw{Str/Glyph/UTF8}
should place the leftmost drawn pixel at X-coordinatex
get{Str/Glyph/UTF8}Width
should give the X-distance from the leftmost to rightmost drawn pixelsget{Str/Glyph/UTF8}LeftMargin
should give X-distance from leftmost pixel to origin 0get{Str/Glyph/UTF8}RightMargin
should give X-distance from rightmost pixel to (origin 0 + logical width 0)u8g2_getStrX(text)
should be deprecatedI believe this would be minimally surprising for users who care about pixels and don't care about the subtleties of BDF baseline origin semantics, and I believe the concepts of "left margin" and "right margin" are a lot easier to grasp than "offset vector from origin to corner of bounding box".
Behavior of
drawStr
/drawGlyph
/drawUTF8
could be controlled by modes the same way Y-coordinate behavior is controlled by thesetFontPos*(...)
functions. I could imagine offering origin-point, leftmost-pixel, center-pixel, rightmost-pixel, and origin-point-plus-logical-width as X-positioning options consistent with previous Y-positioning options. The default could be compatible with prior behavior.There's a number of interactions here with font-direction and so on to be worked through...