py-pdf / fpdf2

Simple PDF generation for Python
https://py-pdf.github.io/fpdf2/
GNU Lesser General Public License v3.0
1.12k stars 253 forks source link

A corner case for line-break exception with two CJK fonts loaded #1250

Open socrateslee opened 2 months ago

socrateslee commented 2 months ago

This is a rather a corner case. I have two CJK fonts loaded, and use one for set_font, and the other for fallback fonts. The two fonts have a lot of overlapped characters. When detecting link-break in a table cell, the fragments generated will not be a single-fragment list, but a list of fragmented fragments. For example,

# original text
text ='隆数萨代发据大大顺大水费水菲发,发萨发死理试放了丰中水库灵、发势发服测达文大趋发舒'
# fragments
[['隆'], ['数', '萨'], ['代', '发', '据', '大', '大'], ['顺'], ['大', '水'], ['费'], ['水', '菲', '发', ',', '发'], ['萨'], ['发', '死', '理'], ['试'], ['放', '了', '丰', '中', '水'], ['库'], ['灵', '、', '发'], ['势'], ['发', '服'], ['测'], ['达', '文', '大'], ['趋'], ['发', '舒']]

So the fragments above are very easily triggering the exception in link_break.py:

                if idx_last_forced_break == self.character_index:
                    raise FPDFException(
                        "Not enough horizontal space to render a single character"
                    )

Minimal code Please include some minimal Python code reproducing your issue:

import fpdf
import io

def do():
    cell_content = '隆数萨代发据大大顺大水费水菲发,发萨发死理试放了丰中水库灵、发势发服测达文大趋发舒'
    html_content = f'<table><tr><td width="25%">{cell_content}</td>{'<td width="25%"></td>'*3}</table>'

    pdf = fpdf.FPDF(format='A4')
    pdf.add_font('NotoSansSC-Regular', fname='NotoSansSC-Regular.ttf')
    pdf.add_font('NotoSansHK-Regular', fname='NotoSansHK-Regular.ttf')
    pdf.set_fallback_fonts(["NotoSansSC-Regular"])
    pdf.set_font('NotoSansHK-Regular', size=12)
    pdf.add_page()
    pdf.write_html(html_content)
    pdf.output(io.BytesIO())

do()

Environment Please provide the following information:

socrateslee commented 2 months ago

by the way, the exception can be mitigated by setting wrapmode=WrapMode.CHAR

Lucas-C commented 2 months ago

Thank you for the report @socrateslee 👍