-
Notifications
You must be signed in to change notification settings - Fork 315
Description
Error details
get_string_width returns a (slightly) too small a value, leading to multi_cell splitting the string.
In the snippet below, I calculate the width of a string with get_string_width and then create a multi_cell with exactly that width (127.512)
However multi_cell deems that too small and inserts a line break. It is not due to c_margin, which I set to 0/include in the calculation.
This bug is very finicky and hard to hit. Small changes in the text, increasing the value by a tiny amount (length += 1e-12), changing the font or the page unit all make it disappear.
From what I can tell, this is a classic floating point error: MultiLineBreak calculates the width as 127.51200000000001 - which is above the limit of 127.512 - and inserts a line break.
Is this fixable?
My current workaround is to round up the values of get_string_width, is there a better way you'd recommend?
Minimal code
You will need the font Inter, which you can get for free at https://rsms.me/inter/download/
I tried to reproduce the issue with a default font, but couldn't.
from fpdf import FPDF
from fpdf.enums import MethodReturnValue
doc = FPDF(unit="pt")
doc.add_font("Inter", fname="./Inter.ttc")
doc.set_font("Inter")
doc.add_page()
# the bug occurs even if not setting c_margin to 0, since it is included in the length below
doc.c_margin = 0
text = "2025-03-11 17:42 UTC"
length = doc.get_string_width(text) + doc.c_margin * 2
# length = 127.512
print(f"length = {length}")
lines = doc.multi_cell(
text=text,
dry_run=True,
output=MethodReturnValue.LINES,
w=length,
)
# this fails
assert len(lines) == 1, linesEnvironment
- Operating System: Windows 11
- Python version: 3.9.21
fpdf2version used: 2.8.2