fpdf2 icon indicating copy to clipboard operation
fpdf2 copied to clipboard

write_html() ignores font changes

Open gmischler opened this issue 1 year ago • 5 comments

Error details When write_html() encounters eg. a <font face="helvetica">, then it will process that but the changed font will not necessarily be reflected in the output.

Minimal code The "html_features" test shows the problem, where the "hello helvetica" line is now actually rendered in Times.

It seems that this has happened in #1207. In my comments there I had tried to point out the reasons why the graphics state context switches had previously been done the way they were, but apparently I didn't make their purpose sufficiently clear. I also didn't notice at the time that the font handling got broken.

gmischler avatar Jul 08 '24 07:07 gmischler

Thank you for the bug report @gmischler 👍

Given that I probably caused this regression, I will have a look at this myself during the week.

Lucas-C avatar Jul 08 '24 14:07 Lucas-C

While investigating this issue, I was surprised by the behaviour of the following code snippets:

pdf = FPDF()
pdf.add_page()
pdf.set_font("Helvetica", size=32)
with pdf.text_columns() as cols:
    with cols.paragraph() as par:
        par.write(text="Un.")
    pdf.font_style = "B"
    with cols.paragraph() as par:
        par.write(text="Deux.")
        pdf.font_style = "I"
        par.write(text="Trois.")
        print(cols._paragraphs[0]._text_fragments[0].graphics_state["font_style"])  # ""
        print(cols._paragraphs[1]._text_fragments[0].graphics_state["font_style"])  # "B"
        print(cols._paragraphs[1]._text_fragments[1].graphics_state["font_style"])  # "I"
pdf.output("paragraph_emphasis.pdf")

Why the PDF produced by this code does not contain any emphasis (bold/italics)? This seems to be the underlying problem causing this bug...

Lucas-C avatar Jul 10 '24 19:07 Lucas-C

That's an interesting observation. The reason seems to be that setting pdf.font_style does not change pdf.current_font. And once we know that, it doesn't surprise that the same effect can be observed by using eg. pdf.cell():

pdf.font_style = ""
pdf.cell(text="Eins.")
pdf.font_style = "B"
pdf.cell(text="Zwei.")
pdf.font_style = "I"
pdf.cell(text="Drei.")

Apparently hardly anyone uses FPDF.font_style in this manner, or that bug would have been discovered a long time ago... FPDF.font_family may have the same problem. And it doesn't make any difference whether you use a built-in or a TTF font.

All of that isn't directly related to our HTML font settings issue here, but should of course also be fixed.

gmischler avatar Jul 10 '24 21:07 gmischler

The reason seems to be that setting pdf.font_style does not change pdf.current_font.

You are right. I opened this issue with a proposal to change that: https://github.com/py-pdf/fpdf2/issues/1223

I still think there is something fishy with how the GraphicsStates of TextFragments are handled... I'll be back soon with another code snippet 🙂

Lucas-C avatar Jul 11 '24 11:07 Lucas-C

I opened PR https://github.com/py-pdf/fpdf2/pull/1246 to fix this problem.

Would you like to review it @gmischler?

Lucas-C avatar Aug 19 '24 21:08 Lucas-C