pdf.write_html() doesn't support custom fonts
Describe the bug
I am trying to write some markdown text containing characters that are not supported by the core font. I have followed the instructions from the docs (which are great by the way, thank you for this!). When writing to html, an error is raised which seems to be a relatively soluble case-issue in the self.fonts of the HTML2FPDF class.
Error details
Minimal code Please include some minimal Python code reproducing your issue:
from fpdf import FPDF
html = markdown.markdown(md_text)
# Create a PDF object
pdf = FPDF()
try:
# Add the HTML to the PDF
pdf.add_page()
pdf.add_font("dejavusans", fname=r"...\media\fonts\dejavu-sans\DejaVuSans.ttf")
pdf.add_font("dejavusansB",
fname=r"...\media\fonts\dejavu-sans\DejaVuSans-Bold.ttf")
pdf.add_font("dejavusansBO",
fname=r"...\media\fonts\dejavu-sans\DejaVuSans-BoldOblique.ttf")
pdf.set_font("dejavusans", style='', size=font_size)
pdf.set_text_color(0,0,0)
pdf.write_html(html,font_family=font_family) # <--- Error is raised here. It tries to get dejavusansB, but can't find it because the key for the font is "dejavusansb" (lowercase b)
except FPDFUnicodeEncodingException as e:
raise e
# Save the PDF to a bytes buffer
pdf_buffer = pdf.output(dest='S')
pdf.output(f'output_path.pdf')...
Environment Please provide the following information:
- Operating System: Windows 11
- Python version: 3.10.11
fpdf2version used: fpdf2==2.8.2
Found a potential fix for this issue, please see pull request here: https://github.com/py-pdf/fpdf2/pull/1408
Hi @tur-ium
You need to add the bold version of the font with the same name, and the correct style. Like this:
pdf.add_font("dejavusans", style="", fname=r"...\media\fonts\dejavu-sans\DejaVuSans.ttf")
pdf.add_font("dejavusans", style="B", fname=r"...\media\fonts\dejavu-sans\DejaVuSans-Bold.ttf")
pdf.add_font("dejavusans", style="BI", fname=r"...\media\fonts\dejavu-sans\DejaVuSans-BoldOblique.ttf")
Hi @andersonhc , that worked, but it would be good to document or have a better error message. How about asking in the error if the user has correctly added the font, something like below?
[referring to lines 2116-2119]
if fontkey not in self.fonts:
if fontkey not in CORE_FONTS:
raise FPDFException(
f"Undefined font: {fontkey} - "
f"Use built-in fonts or FPDF.add_font() beforehand. Ensure that if you have also added bold or italic fonts where necessary, using the style parameter e.g. pdf.add_font('MyFont', style='B', '\path\to\MyFont-Bold.ttf')"
)
Hi @tur-ium
Thank you for reaching out, and even submitting a PR! 👍 It's great to have helpful contributors like you.
You did not provide an autonomous minimal reproducible example, as suggested in our bug report issue template: https://github.com/py-pdf/fpdf2/blob/master/.github/ISSUE_TEMPLATE/bug_report.md
md_text / font_size / font_family were not provided.
There is a shorter autonomous code snippet that I think reproduce your issue:
from fpdf import FPDF
pdf = FPDF()
pdf.add_page()
pdf.add_font(fname="test/fonts/DejaVuSans.ttf") # add font DejaVuSans
pdf.add_font("DejaVuSansB", fname="test/fonts/DejaVuSans-Bold.ttf") # reproduce the issue you reported
# pdf.add_font("DejaVuSans", style="B", fname="test/fonts/DejaVuSans-Bold.ttf") # fix
pdf.set_font("DejaVuSans", size=10)
pdf.write_html("<b>BOLD</b>", font_family="DejaVuSans")
pdf.output("issue_1407.pdf")
This exception is then raised: fpdf.errors.FPDFException: Undefined font: dejavusansB - Use built-in fonts or FPDF.add_font() beforehand
Is it the error you got @tur-ium?
it would be good to document or have a better error message.
I agree that we should try to improve our error messages, especially if you did not understand what was required there.
First, could you please explain to use why you try to pass "dejavusansB" to pdf.add_font()?
Second, the error message currently already suggests to call FPDF.add_font() beforehand.
Could you tell us why/how this was a clear enough indication?
Given the lack of answer, I'm closing this for now.