rougier / freetype-py

Python binding for the freetype library
Other
298 stars 88 forks source link

Wrong horizontal character positioning in hello world examples #161

Closed badicsalex closed 1 year ago

badicsalex commented 1 year ago

The left bearing is not used in these examples (pyright does complain about this):

https://github.com/rougier/freetype-py/blob/51ee6e15e6d7b3a9ca0f5e96b11bfa8c07575c36/examples/hello-world.py#L42 https://github.com/rougier/freetype-py/blob/51ee6e15e6d7b3a9ca0f5e96b11bfa8c07575c36/examples/hello-world-cairo.py#L47

And probably some other places. This should probably fixed, because it is common practice to start out from examples and build from there.

Example with the Good Times font; notice that the distance between MP and TI are way off: image

The correct rendering looks like this: image

rougier commented 1 year ago

Thansk for the report. For the correct rendering, did you do it with freetype-py (i.e. do you have a fix ?)

HinTak commented 1 year ago

The full fix is probably something close to what I did here: https://github.com/HinTak/harfbuzz-python-demos/blob/38f4c107f37c518a2f028bf7031ae3c306ae1311/hb-view.py#L198

hb-view.py was written to explicitly support Arabic and Hebrew fonts, where non-zero left-side bearing (and top/bottom-side bearings too) are common.

That said, I think the original example works as it is, for a font that mostly have zero left-side bearing. For those who think they need non-zero leftside/topside bearings, like Arabic users, they know they need to add it anyway.

I am more inclined to say add a new example using a different font - or even refer to my repo, instead of bloating the existing one.

badicsalex commented 1 year ago

Thansk for the report. For the correct rendering, did you do it with freetype-py (i.e. do you have a fix ?)

I basically changed this line: https://github.com/rougier/freetype-py/blob/51ee6e15e6d7b3a9ca0f5e96b11bfa8c07575c36/examples/hello-world.py#L47

to

 Z[y:y+h,x+left:x+w+left] += numpy.array(bitmap.buffer, dtype='ubyte').reshape(h,w)

It worked for my case, but for negative left values, it would probably be incorrect.

For those who think they need non-zero leftside/topside bearings, like Arabic users, they know they need to add it anyway.

Well, my font and text was western, so I didn't know I had to add it.

HinTak commented 1 year ago

Arabic fonts have top/bottom bearings too. While I agree the example is limited, I think it is best to create a new example using a font with obviously non-zero left bearings. Perhaps one cursive font.

rougier commented 1 year ago

A new example might help to show the problem. But as shown by @badicsalex, the simple hello-world rendering is wrong. I would add the left bearing with a comment warning this is not the correct way to do tue and redirect reader to your hb-view.py example.

HinTak commented 1 year ago

I wonder if any of the glyphs in "Hello World" has a non-zero leftside bearing, in the example font. That's basically my question. A future contributor might decide to "simplify" the code if it is all zeros.

While working on the hb-view example (I thought of contributing that to freetype-py but it has extra dependencies on harfbuzz, which is another thing) , I remember there is a rather big omission to the hello world example - none of "Hello World" has a descender part below the baseline, so it does not allocate drawing space below the baseline. This is quite unusual - longer normal run of texts have a "g" or a "y". This (the example does not allocate drawing space below baseline, so "y", and "g" are cut off, if you put one in) probably could go in as a comment as well.

badicsalex commented 1 year ago

In any case, the original lines I linked are dead code since the left variable is not used afterwards, so these should be deleted.

I think the above mentioned comments or something like a generic warning should be added at least, even if the code isn't touched for simplicity.

rougier commented 1 year ago

@HinTak You're right. This hello-world.py example is really bad (my fault). As mentioned by @badicsalex, people will probably use it as a start and extend from it but, if is wrong from the start, it is a problem. We can modify the text to include some g/j/y and add the left bearing. It won't be perfect but at least not totally wrong.

HinTak commented 1 year ago

I only found one other problem like this, in hello-vf.py . Most of the other examples seem to use the left side bearing value - or at least, not obviously not using it.

Actually the left side bearings of the example are mostly non-zero - and illustrates the problem better than the Good Times font (most of them 1 or two pixels off) - the "!" at the end of "Hello World !" was off by 7 pixels.

I did compare the result with hb-view.py (that gets the leftside bearings from harfbuzz instead of freetype).

I re-check the descender comment - I think it probably concerns another example instead of hello-world.