Kozea / WeasyPrint

The awesome document factory
https://weasyprint.org
BSD 3-Clause "New" or "Revised" License
7.21k stars 683 forks source link

Handle y offset of glyphs #1958

Closed gauravsamudra closed 1 year ago

gauravsamudra commented 1 year ago

Hello! I am creating a pdf with weasyprint's html to pdf feature. I've gotten everything to work fine except for one specific set of combination of devanagari characters - in this case a glyph made up of conjunct consonant with vowel diacritics - e.g. ङ्गु - which is made up of ङ, ग and ु. It looks like image in ITF Devanagari font (in vscode or chrome or firefox browsers). The glyph is ङ, underneath that a partial ग and underneath that ु

I am a loss of what should I be investigating. I’ve tried playing with css’ font feature settings but that doesn’t seem to have any effect. I'll appreciate any help to point me in the right direction or forum!

liZe commented 1 year ago

Hi!

That’s probably a bug in Harfbuzz. I don’t have the ITF Devanagari font, but I also have the bug in my browser, based on the same shaping libraries as WeasyPrint, on this page (but not in Chrome and Firefox).

Could you please share the font by mail (for testing purpose, of course)?

gauravsamudra commented 1 year ago

Thanks @liZe !

I am using ITF Devanagari font that is available by default on mac. I'm not sure if I can/should export and share it. Here is a simplified version of my css and html using which I can reproduce the issue -

html {
  font-family: 'ITF Devanagari';
  font-size: 22pt;
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Test</title>
  </head>

  <body>
    <p>ङ्गु</p>
  </body>
</html>

and the python code I use

    html_01 = HTML(filename='./app/template/01-template.html')
    css_01 = CSS(filename='./app/template/01-style.css')
    pdf_01 = html_01.write_pdf(stylesheets=[css_01])
    with open('../dist/01.pdf', 'wb') as f:
        f.write(pdf_01)
liZe commented 1 year ago

Thanks for sharing your HTML/CSS, but I can already reproduce without 😄.

I am using ITF Devanagari font that is available by default on mac. I'm not sure if I can/should export and share it.

Even if I can swear that I won’t use the font for anything but testing, even if it’s technically possible (the font is just a regular file that you can copy and share), even if it’s included in macOS by default, it’s probably illegal to share the font with me. The problem is that I can’t help you without this font 😒.

If you don’t want to share the font, you can do the technical stuff I’d like to do, but it may be difficult, and obviously I don’t have a Mac to guide you! Here are the steps you can follow:

If you see the problem on the glyph, then it’s (probably) a bug in HarfBuzz and we should open a new issue on their bug tracker. If it’s correctly displayed, then we’ll have to dig further!

gauravsamudra commented 1 year ago

thanks! the glyph looks correct. I executed hb-view /System/Library/Fonts/Supplemental/ITFDevanagari.ttc ङ्गु -O png > output.png and got this - output

gauravsamudra commented 1 year ago

I also tried pango-view --font "ITF Devanagari" --text "ङ्गु" --output test.png --dpi 300 - and the glyph looks correct here too test

liZe commented 1 year ago

Strange.

I’m not sure that it’s the same font used for your two examples, but both work, so…

Could you please share a PDF where the problem appears?

gauravsamudra commented 1 year ago

sure! here you go - 01.pdf

liZe commented 1 year ago

I’ve tried to find the reason why we have this bug, but without the font I can’t do much. If someone wants to share the font…

gauravsamudra commented 1 year ago

thanks @liZe! would you be ok to share your email? I can share the font files I received for trial purposes.

liZe commented 1 year ago

You’ll find it on my profile. Thanks!

gauravsamudra commented 1 year ago

Thanks! I've sent you an email.

liZe commented 1 year ago

Thanks! I've sent you an email.

Thanks a lot, it really helped!

The bug is in WeasyPrint, in draw.py. We should take care of y_offset as we do for x_offset. I’ve managed to draw the glyph correctly using the Ts operator described in chapter 9.3.7 of the PDF 1.7 specification, but we should find a way to do this using pydyf cleanly.

Anyone intersted? It would be a nice first contribution for anyone with some Python knowledge who isn’t scared of reading specifications. 😄 I’ll help of course!

gauravsamudra commented 1 year ago

Thanks @liZe! I would love to contribute! I have made some changes locally and it seems to be working, although I'll need to test more. While doing those change, I had to add a method to Stream class in pydyf to set the rise. it looks like this -

    def set_rise(self, height):
        """Set rise."""
        self.stream.append(_to_bytes(height) + b' Ts')

Should I raise a PR in that repo first to include this change and then upgrade it in here (WeasyPrint) to use it?

liZe commented 1 year ago

Thanks @liZe! I would love to contribute!

💜

Should I raise a PR in that repo first to include this change and then upgrade it in here (WeasyPrint) to use it?

Yes! You can call the function set_text_rise to be more explicit, otherwise it’s perfect.

gauravsamudra commented 1 year ago

thanks @liZe, I've raised a PR in pydyf.